How to Self-Host OneDev with Docker Compose

OneDev sits in a unique spot between lightweight Git servers like Gitea and heavyweight platforms like GitLab CE. It ships CI/CD, Kanban boards, package registries, and language-aware code search in a single container that runs on 2 GB of RAM. If you want an all-in-one DevOps platform without GitLab’s 4-8 GB memory tax, OneDev is worth a serious look.

What Is OneDev?

OneDev is an open-source DevOps platform that combines Git hosting, visual CI/CD pipelines, issue tracking with automated Kanban boards, code review with auto-reviewer suggestions, and built-in package registries (Docker, NPM, Maven, NuGet, PyPI). It also includes dependency scanning, secret detection, and symbol-level code search out of the box. OneDev replaces GitHub, separate CI/CD tools, and issue trackers with a single self-hosted application — lighter than GitLab CE but far more capable than Gitea or Forgejo alone.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 2 GB of free RAM (1 GB possible for small deployments)
  • 2 CPU cores
  • 10 GB of free disk space (excluding repository data)
  • A domain name (optional, for remote access)

Docker Compose Configuration

OneDev uses an embedded HSQLDB database by default, which works fine for small teams. For production use with multiple concurrent users, PostgreSQL is recommended.

Simple Setup (Embedded Database)

Create a docker-compose.yml file:

services:
  onedev:
    image: 1dev/server:14.1.6
    container_name: onedev
    restart: unless-stopped
    ports:
      - "6610:6610"
      - "6611:6611"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - onedev_data:/opt/onedev
    environment:
      - initial_user=admin
      - initial_password=${ADMIN_PASSWORD}
      - initial_email=${ADMIN_EMAIL}
      - initial_server_url=${SERVER_URL}

volumes:
  onedev_data:

Create a .env file:

ADMIN_PASSWORD=CHANGE_ME_TO_A_STRONG_PASSWORD
ADMIN_EMAIL=[email protected]
SERVER_URL=http://your-server-ip:6610

The initial_* variables skip the web setup wizard on first boot. They are ignored on subsequent starts.

Production Setup (PostgreSQL)

For teams with 3+ users or heavier CI/CD workloads, use PostgreSQL:

services:
  onedev:
    image: 1dev/server:14.1.6
    container_name: onedev
    restart: unless-stopped
    ports:
      - "6610:6610"
      - "6611:6611"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - onedev_data:/opt/onedev
    environment:
      - hibernate_dialect=io.onedev.server.persistence.PostgreSQLDialect
      - hibernate_connection_driver_class=org.postgresql.Driver
      - hibernate_connection_url=jdbc:postgresql://onedev-db:5432/onedev
      - hibernate_connection_username=onedev
      - hibernate_connection_password=${DB_PASSWORD}
      - initial_user=admin
      - initial_password=${ADMIN_PASSWORD}
      - initial_email=${ADMIN_EMAIL}
      - initial_server_url=${SERVER_URL}
    depends_on:
      onedev-db:
        condition: service_healthy

  onedev-db:
    image: postgres:16-alpine
    container_name: onedev-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: onedev
      POSTGRES_USER: onedev
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - onedev_db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U onedev"]
      interval: 30s
      timeout: 10s
      retries: 5

volumes:
  onedev_data:
  onedev_db:

Create a .env file:

DB_PASSWORD=CHANGE_ME_TO_A_STRONG_PASSWORD
ADMIN_PASSWORD=CHANGE_ME_TO_A_STRONG_PASSWORD
ADMIN_EMAIL=[email protected]
SERVER_URL=http://your-server-ip:6610

Start the stack:

docker compose up -d

Initial Setup

If you set the initial_* environment variables, the setup wizard is skipped and you can log in immediately. Otherwise:

  1. Open http://your-server-ip:6610 in your browser
  2. The setup wizard prompts for admin credentials, server URL, and database settings
  3. After setup, log in with the admin account you created
  4. Go to Administration → Security → General Settings to disable self-registration if needed

Configuration

Volume Mounts

VolumeContainer PathContents
onedev_data/opt/onedevAll OneDev data: repositories, embedded database, build artifacts, logs, packages, configuration
Docker socket/var/run/docker.sockRequired for built-in CI/CD to spawn build containers

The Docker socket mount is only necessary if you use OneDev’s built-in CI/CD with Docker executors. If you only need Git hosting and issue tracking, you can omit it.

For rootless Docker, mount $XDG_RUNTIME_DIR/docker.sock instead of /var/run/docker.sock.

Key Environment Variables

VariableDefaultDescription
initial_userAdmin username (first run only)
initial_passwordAdmin password (first run only)
initial_emailAdmin email (first run only)
initial_server_urlServer URL for generated links (first run only)
initial_ssh_root_urlSSH URL base (e.g., ssh://your-server:6611)
hibernate_dialectHSQLDBDatabase dialect class
hibernate_connection_urlembeddedJDBC connection URL
http_port6610HTTP port inside the container
ssh_port6611SSH port inside the container

External Database Options

OneDev supports MySQL, MariaDB, and PostgreSQL as external databases. Use the hibernate_* environment variables to configure:

MySQL:

hibernate_dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate_connection_driver_class=com.mysql.cj.jdbc.Driver
hibernate_connection_url=jdbc:mysql://db-host:3306/onedev?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false&disableMariaDbDriver=true

MariaDB:

hibernate_dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate_connection_driver_class=org.mariadb.jdbc.Driver
hibernate_connection_url=jdbc:mariadb://db-host:3306/onedev

PostgreSQL uses OneDev’s custom dialect (io.onedev.server.persistence.PostgreSQLDialect), not the standard Hibernate one.

CI/CD Configuration

OneDev’s CI/CD works out of the box with the Docker socket mount. Build pipelines are defined per-project through the web UI or a .onedev-buildspec.yml file in the repository root.

Executor types available:

  • Docker executor — spawns containers on the host (requires Docker socket)
  • Kubernetes executor — runs jobs in a Kubernetes cluster
  • Remote agent — distributes builds to remote machines running the OneDev agent
  • Bare metal — runs directly on the host

Configure executors in Administration → Job Executors.

Reverse Proxy

When running behind a reverse proxy, set SERVER_URL to your public HTTPS URL and configure your proxy to forward both HTTP and SSH:

Nginx Proxy Manager config for HTTP:

  • Scheme: http
  • Forward Hostname: onedev
  • Forward Port: 6610
  • Enable WebSocket support
  • Enable SSL with Let’s Encrypt

For SSH access through the proxy, forward port 6611 directly (TCP passthrough) or expose it separately:

ports:
  - "6611:6611"

Users clone with: git clone ssh://git@your-server:6611/project/repo

See Reverse Proxy Setup for full configuration.

Backup

All OneDev data lives in the onedev_data volume at /opt/onedev. Back up this volume to capture repositories, configuration, build artifacts, and the embedded database.

If using PostgreSQL, also back up the database:

docker exec onedev-db pg_dump -U onedev onedev > onedev_backup.sql

OneDev also supports creating backups from the web UI: Administration → Database Backup.

See Backup Strategy for automated backup workflows.

Troubleshooting

CI/CD jobs fail with “docker not found”

Symptom: Build jobs fail immediately with errors about Docker not being available. Fix: Ensure the Docker socket is mounted in your Compose file: /var/run/docker.sock:/var/run/docker.sock. Check that the socket has the correct permissions. For rootless Docker, use $XDG_RUNTIME_DIR/docker.sock instead.

Web UI inaccessible after startup

Symptom: Port 6610 returns connection refused or timeouts. Fix: OneDev takes 1-2 minutes to start (Java application). Check logs with docker logs -f onedev. If the container keeps restarting, check available RAM — OneDev needs at least 1 GB free. Verify no other service is using port 6610.

SSH clone fails with “connection refused”

Symptom: git clone ssh://git@server:6611/project/repo fails. Fix: Verify port 6611 is exposed in your Compose file and not blocked by a firewall. If running behind a reverse proxy, SSH must be forwarded as raw TCP — HTTP proxying will not work for SSH.

PostgreSQL connection errors on startup

Symptom: OneDev logs show “Connection refused” to the database. Fix: Ensure depends_on with condition: service_healthy is set so OneDev waits for PostgreSQL to be ready. Verify the hibernate_connection_url hostname matches the database service name in your Compose file.

Out of memory with large repositories

Symptom: OneDev becomes unresponsive or crashes when cloning large repositories. Fix: OneDev can cache up to 200 MB per large repository and each concurrent git operation uses ~100 MB. For repositories approaching Linux kernel size, allocate 4+ GB of RAM. For most projects, 2 GB is sufficient.

Resource Requirements

  • RAM: ~500 MB idle with embedded database, ~1 GB under moderate load, 2 GB recommended for teams
  • CPU: 2 cores minimum (Java application with background indexing)
  • Disk: ~400 MB for the application, plus storage for repositories, build artifacts, and packages

Verdict

OneDev occupies a smart middle ground. It gives you 80% of GitLab’s functionality at 25% of the resource cost. The built-in CI/CD with a visual editor, package registries, and symbol-level code search are genuine differentiators — Gitea and Forgejo require separate tools for CI/CD. The trade-off is a smaller community and Java’s higher baseline memory compared to Go-based alternatives. For small-to-medium teams that want integrated CI/CD and issue tracking without dedicating 8 GB of RAM to GitLab CE, OneDev is the best option available. For teams that only need Git hosting with pull requests, Gitea or Forgejo at 200 MB of RAM are the lighter choice.

Comments