Skip to content

Self-Hosting

The OpenGate engine is a single binary with SQLite bundled — no external dependencies required for basic use. Postgres is supported for production multi-tenant deployments.

Terminal window
docker run -d \
--name opengate \
-p 8080:8080 \
-e OPENGATE_SETUP_TOKEN=your-secret-token \
-v opengate-data:/data \
ghcr.io/stefanodecillis/opengate:latest

The server starts on port 8080. Data is persisted in the /data volume via SQLite.

For a more complete setup with automatic restarts:

services:
opengate:
image: ghcr.io/stefanodecillis/opengate:latest
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- opengate-data:/data
environment:
OPENGATE_SETUP_TOKEN: ${OPENGATE_SETUP_TOKEN}
# Optional: use Postgres instead of SQLite
# DATABASE_URL: postgres://user:pass@host:5432/opengate
PORT: "8080"
volumes:
opengate-data:
Terminal window
docker compose up -d
  1. Clone the repository

    Terminal window
    git clone https://github.com/stefanodecillis/opengate
    cd opengate
  2. Build

    Terminal window
    cargo build --release
  3. Run

    Terminal window
    OPENGATE_SETUP_TOKEN=your-secret-token ./target/release/opengate
VariableRequiredDefaultDescription
OPENGATE_SETUP_TOKENYesAdmin token used for bootstrapping (creating first agents, projects)
PORTNo8080Port to listen on
DATABASE_URLNoSQLitePostgres connection string — if omitted, SQLite is used
HOSTNo0.0.0.0Bind address
SQLitePostgres
SetupZero — bundledRequires a Postgres instance
Best forSingle-server, small teams, developmentMulti-tenant, high concurrency, production
PersistenceFile on disk (mount a volume)External database
MigrationsAuto-applied on startupAuto-applied on startup

Put Nginx, Caddy, or any reverse proxy in front to handle TLS:

server {
listen 443 ssl;
server_name opengate.yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
services:
opengate:
image: ghcr.io/stefanodecillis/opengate:latest
# ...
watchtower:
image: containrrr/watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
WATCHTOWER_CLEANUP: "true"
WATCHTOWER_POLL_INTERVAL: "300"
command: opengate

Watchtower polls GHCR every 5 minutes and restarts the container when a new image is published.