Docker Compose
The self-host bundle lives in
deploy/selfhost/
of the main repository. Copy docker-compose.yml, Caddyfile, and
.env.example into an empty directory (plus
docker-compose.docker-sock.yml only if you plan to run docker://
Actions jobs).
Local evaluation
Section titled “Local evaluation”-
Grab the bundle files and prepare the environment:
Terminal window mkdir oxidean && cd oxidean# copy docker-compose.yml, Caddyfile, .env.example from deploy/selfhostcp .env.example .env -
Set
POSTGRES_PASSWORDandOXIDEAN_ACTIONS_SECRETS_KEYin.env(openssl rand -hex 24/openssl rand -base64 32). For evaluation only, also setOXIDEAN_ENV=development. -
Bring the stack up:
Terminal window docker compose up -d -
Open
http://localhost:8080./setupwalks you through the admin account and auth providers.
Tear down with docker compose down (add -v to drop the data volume).
Production shape
Section titled “Production shape”-
Point a DNS name at the host and keep ports 80/443 reachable.
-
Set the public identity in
.envso generated links and clone URLs point at the forge instead of localhost:Terminal window OXIDEAN_PUBLIC_ORIGIN=https://git.example.comOXIDEAN_SSH_HOST=git.example.comOXIDEAN_SSH_PORTdefaults to2222; publish it fromapior map it through your edge. -
Provision the web-flow signing key. Auto-generation is disabled in production and creating a repository with a UI-seeded initial commit fails closed without it. Set
OXIDEAN_WEB_FLOW_PRIVATE_KEYin.env, or dropweb-flow/web-flow.pubinto/var/sshinside theoxidean_datavolume:Terminal window ssh-keygen -t ed25519 -N '' -f web-flow && base64 -w0 web-flowDetails: required secrets.
-
Set
DOMAIN,POSTGRES_PASSWORD, andOXIDEAN_ACTIONS_SECRETS_KEYin.env— the stack cannot start without them. LeaveOXIDEAN_ENVunset (production default). -
Bring the edge profile up with the stack:
Terminal window docker compose --profile tls up -dCaddy terminates TLS for
$DOMAINwith Let’s Encrypt and proxies toweb:3000. Running your own edge instead? Onereverse_proxy web:3000line is the whole contract. -
Enable CI capacity when you need it. Runners must register before they can claim jobs. Mint a one-time registration token under Admin → Runners in the web UI (or via
admin.actions.createRegistrationToken), hand it to the runner, then start the profile:Terminal window # .env: OXIDEAN_RUNNER_REGISTRATION_TOKEN=<one-time token>docker compose --profile actions up -dThe runner persists its registration (
/data/runner.jsonon its/datavolume) and the token is only needed for that first enroll. The same env token is reusable while set on the api side: fine for local eval (set it on bothapiandrunner), but leave it unset on internet-facing instances and always prefer minted one-time tokens.