Self-host konnos
From bare Linux VPS to working forge in ~30 minutes. This guide is what we ran to bring up code.konnos.org.
What you need before starting
- A Linux VPS with at least 2 GB RAM, 20 GB disk. More disk if you'll host LFS-heavy repos. konnos is happy on a small box.
- A domain you control, e.g.
code.your-domain.com. konnos needs at least one subdomain. A wildcard A record is recommended so future subdomains (matrix, docs, etc.) all work without separate DNS edits. - Docker 24+ and Docker Compose v2 installed on the host.
- Ports 80 and 443 open inbound from the public internet (HTTPS + ACME challenge).
- Port 2222 open inbound if you want git+ssh clones (
ssh://git@code.your-domain.com:2222/...). Optional — HTTPS clones work without it.
Five-minute path — Docker Compose only
This is the fastest path. Everything in this repo, docker compose up, done.
git clone https://code.konnos.org/konnos/konnos.git
cd konnos
cp .env.example .env
# Edit .env and set POSTGRES_PASSWORD to a strong value:
# openssl rand -base64 32
docker compose up -dVisit https://your-domain.com and complete the install wizard (next section).
This works for personal use. For multi-user production, follow the production path below.
Production path — what code.konnos.org runs
The reference instance behind code.konnos.org runs on:
| Layer | Concern |
|---|---|
| Container orchestration | Lightweight: a small VPS running Docker, with a UI on top to manage compose projects. |
| Reverse proxy | Auto-discovers labelled containers, terminates TLS, handles HTTP→HTTPS redirect. |
| TLS | ACME (Let's Encrypt) HTTP-01 challenge. Auto-renews. |
| Forge runtime | The image referenced in docker-compose.yml. Pinned to a major version. |
| Database | Postgres 16, persistent volume, healthcheck-gated startup. |
The docker-compose.yml in this repo is what's deployed. Mount the same compose into your reverse proxy's compose-management UI, or run it directly with docker compose up -d behind any TLS-terminating proxy you already use.
Recommended reverse proxy setup (Traefik)
If you don't already have a reverse proxy, the path we use:
- Spin up a Traefik container with ACME enabled and an external Docker network (e.g.,
dokploy-network). - Add
dokploy-networkto yourdocker-compose.yml'sforgejoservice so Traefik can route to it. - Add Traefik labels to the
forgejoservice for: domain, port (3000), HTTPS entrypoint, cert resolver.
The docker-compose.yml in this repo joins dokploy-network as external: true — drop it into a Dokploy project and Dokploy injects the Traefik labels for you from the domain panel.
If you'd rather not use Dokploy, here's the minimal labels you'd add manually:
labels:
- "traefik.enable=true"
- "traefik.http.routers.konnos.rule=Host(`code.your-domain.com`)"
- "traefik.http.routers.konnos.entrypoints=websecure"
- "traefik.http.routers.konnos.tls.certresolver=letsencrypt"
- "traefik.http.services.konnos.loadbalancer.server.port=3000"DNS prerequisite
Before running ACME / Let's Encrypt, your domain must resolve to the VPS:
# from any machine
dig +short A code.your-domain.com
# should return your VPS public IPIf you used a wildcard *.your-domain.com A record, this works automatically. Without DNS pointing at the VPS, ACME's HTTP-01 challenge fails and you stay on a self-signed cert.
First-run install wizard
Open https://code.your-domain.com in a browser. konnos's install page renders. Fill in:
| Section | Field | Value |
|---|---|---|
| Database | Type | PostgreSQL |
| Host | postgres:5432 | |
| Username | konnos (matches POSTGRES_USER in your .env) | |
| Password | the value of POSTGRES_PASSWORD from your .env | |
| Database name | konnos | |
| SSL | Disable (postgres + forgejo on same Docker network) | |
| General | Site title | konnos (lowercase) |
| Server domain | code.your-domain.com | |
| SSH server domain | code.your-domain.com | |
| SSH server port | 2222 (matches the host port published in the compose) | |
| HTTP listen port | 3000 | |
| Application URL | https://code.your-domain.com/ | |
| Optional → Server settings | Disable Gravatar | ✓ |
| Disable Open Registration | ✓ | |
| Require Sign-In to View Pages | leave unchecked (Dokploy + auto-deploy needs unauthenticated git clone) | |
| Optional → Administrator | Username | your handle |
| a real address (used for ACME notifications, password reset) | ||
| Password | strong, save in password manager |
Click Install. The forge restarts and lands you on the dashboard signed in as the admin you just created.
Email setup (later)
konnos can email password resets, notification emails, etc. Set up SMTP via your preferred provider — for the konnos.org reference instance we use Resend, but anything that speaks SMTP works (Postmark, SendGrid, even Gmail relay).
Add to your .env:
SMTP_HOST=smtp.your-provider.com
SMTP_PORT=587
SMTP_USER=…
SMTP_PASSWORD=…
SMTP_FROM=admin@your-domain.comThen set the corresponding FORGEJO__mailer__* env vars in the compose's forgejo service environment block.
Backups
The two volumes that matter:
forgejo_data → /data — repos, LFS, attachments, config
postgres_data → /var/lib/postgresql/data — issues, PRs, users, settings
Minimum viable backup: nightly pg_dump of the postgres database + a tar snapshot of forgejo_data. Push both to off-site storage (S3-compatible bucket, rsync to another server, etc.). See hardening.md for a worked example.
Don't skip backups. If the VPS dies, the only thing standing between you and total data loss is your most recent backup.
What now?
Once konnos is up:
- Read
hardening.mdbefore exposing the instance to anyone but yourself. - Read
migrate-from-github.mdif you're moving an existing GitHub presence over. - Subscribe to upstream release notifications (see
upstream-tracking.md). - Drop into the Matrix room
#konnos:matrix.organd say hi.