- Why this stack?
- Prerequisites
- Getting started
- Features
- Supply chain trust
- Production checklist
- Backups
- Testing
- Security Notes
- About the maintainer
This repository deploys Confluence (Data Center) behind Traefik with automatic Let's Encrypt TLS, backed by PostgreSQL, with scheduled backups (database + application data) and companion restore scripts. One docker compose up away from a team wiki at https://your-domain.
📙 Full narrative installation guide on the blog: heyvaldemar.com/install-confluence-using-docker-compose/.
⚖️ Licensing note: Confluence Data Center requires an Atlassian license (trials available). This template handles the infrastructure; the license is between you and Atlassian.
| Need | This stack | Manual install | Kubernetes | Other compose examples |
|---|---|---|---|---|
| Ready to deploy in <15 min | ✅ | ❌ | ✅ if K8s is already running | Often |
| TLS via Let's Encrypt, auto-renewed | ✅ Traefik ACME built-in | Manual certbot | Via cert-manager | Rare |
| External PostgreSQL wired with healthchecks | ✅ | Manual | ✅ | Varies |
| Scheduled DB + data backups + pruning | ✅ | Manual cron | External | Rare |
| Restore scripts included | ✅ two scripts | Manual | Manual | Rare |
Upstream images pinned by sha256 digest |
✅ | N/A | Depends | Rare |
| Weekly pin-freshness check in CI | ✅ | N/A | Depends | Rare |
| CI-verified deployment on every push | ✅ /status answers | N/A | Varies | Rare |
| Credentials via env (never committed) | ✅ | N/A | K8s Secrets | Often committed plaintext |
Four moving parts (Traefik + Confluence + Postgres + backups). No Kubernetes prerequisites, no manual certificate management.
- A Linux server with a public IP and RAM for the JVM — defaults are 8 GB min / 12 GB max heap for a production wiki; lower them in
.envfor small instances. - Docker Engine 24+ and Docker Compose 2.20+.
- A domain you control, with two
Arecords pointing at your server's public IP — one for Confluence, one for the Traefik dashboard. DNS must propagate before deploy. - Ports 80 and 443 open on the server's firewall.
- Disk for attachments, indexes, and backups.
# 1. Clone
git clone https://github.com/heyvaldemar/confluence-traefik-letsencrypt-docker-compose
cd confluence-traefik-letsencrypt-docker-compose
# 2. Create the two Docker networks the stack expects
docker network create traefik-network
docker network create confluence-network
# 3. Copy the environment template and fill in required values
cp .env.example .env
$EDITOR .env
# ^ Required: CONFLUENCE_DB_PASSWORD, CONFLUENCE_HOSTNAME, CONFLUENCE_URL,
# TRAEFIK_HOSTNAME, TRAEFIK_ACME_EMAIL, TRAEFIK_BASIC_AUTH.
# 4. Deploy
docker compose -f confluence-traefik-letsencrypt-docker-compose.yml -p confluence up -dFirst boot takes a few minutes. Then https://${CONFLUENCE_HOSTNAME} serves the setup wizard — choose production installation, point it at the bundled database (host postgres, database confluencedb, user confluencedbuser, your CONFLUENCE_DB_PASSWORD), and follow the license step.
# Services healthy:
docker compose -f confluence-traefik-letsencrypt-docker-compose.yml -p confluence ps
# Confluence status endpoint:
curl -fsS "https://${CONFLUENCE_HOSTNAME}/status"
# Expected before setup: {"state":"FIRST_RUN"} — after setup: {"state":"RUNNING"}
# Traefik issued a certificate:
docker compose -p confluence logs traefik | grep -i "adding certificate"
# First backup lands after BACKUP_INIT_SLEEP (default 30m):
docker compose -p confluence logs backups | tail -3- Cert issuance fails. DNS hasn't propagated or port 80 isn't reachable from the internet.
docker compose upfails withset in .env. A required variable is empty; the error names it.network confluence-network not found. Step 2 was skipped.- OOM-killed container. Lower
CONFLUENCE_JVM_MINIMUM_MEMORY/CONFLUENCE_JVM_MAXIMUM_MEMORYin.envto fit your host.
docker compose -f confluence-traefik-letsencrypt-docker-compose.yml -p confluence up -d --force-recreate- Confluence Data Center 10.2 line with an external PostgreSQL 16, healthchecked and backupable.
- Traefik v3 with automatic HTTP→HTTPS redirect and Let's Encrypt TLS-ALPN certificate issuance.
- Basic-auth protected Traefik dashboard on a separate hostname.
- Tunable JVM heap via
CONFLUENCE_JVM_MINIMUM_MEMORY/CONFLUENCE_JVM_MAXIMUM_MEMORY. - Scheduled backups of the database (
pg_dump | gzip) and application data (tar.gz) with retention pruning, plus restore scripts for both. - Credentials required at deploy time — compose fails fast if
.envis incomplete.
This repository is a deployment template, not a custom Docker image. It orchestrates three upstream images:
traefik— reverse proxy, Docker Hub official imageatlassian/confluence— Confluence upstreampostgres— PostgreSQL, Docker Hub official image
All three are pinned to tag@sha256:<digest> as interpolation defaults in the compose file's x-images block — git pull alone delivers the version combination this repository has tested; an *_IMAGE_TAG variable in .env overrides the default deliberately.
The weekly check-pin-freshness CI job re-resolves each pinned tag against its registry, compares the pinned Confluence version against the highest release tag on Docker Hub (Atlassian publishes no GitHub releases), and checks the Traefik minor against the latest upstream release. CI runs on every push, pull request, and every Monday at 06:00 UTC. GitHub Actions are pinned by commit SHA; Dependabot keeps those fresh.
- Strong secrets.
CONFLUENCE_DB_PASSWORDat 24+ random characters; regenerate the Traefik dashboard BCrypt hash per deployment. - Size the JVM to your instance — the defaults suit a real team wiki; shrink for evaluation.
- Host-mount the backup volumes for disaster recovery.
- Verify Let's Encrypt cert issuance in the Traefik logs on first start.
- Back up before upgrades and follow Atlassian's upgrade guidance — there is no downgrade path.
- Know the restore procedure. Run both restore scripts against a test environment before you need them.
The backups container performs a dump → archive → prune → sleep loop: pg_dump | gzip of the Confluence database, tar.gz of the application data (attachments, indexes), pruning by retention windows, then sleeping BACKUP_INTERVAL (default 24h).
Verify backups are running:
docker compose -p confluence logs backups | tail -5Restore with the interactive scripts (chmod +x *.sh once): ./confluence-restore-database.sh, then ./confluence-restore-application-data.sh.
The Deployment Verification workflow runs on every push, pull request, and every Monday at 06:00 UTC:
- Lint — shellcheck on both restore scripts, actionlint on the workflow.
- Trivy scans of all three pinned images (CRITICAL/HIGH, SARIF to the Security tab).
- Pin freshness (weekly/manual) — digest drift, Confluence Docker Hub tag lag, Traefik release lag.
- Deploy-and-test — boots the full stack with ephemeral credentials and requires
/statusto answer through Traefik — the shipped configuration must produce a serving Confluence, not just started containers.
A green run is the authoritative proof that the template deploys end-to-end.
- Credentials are read from
.envat deploy time;.envis gitignored and compose fails fast on missing required variables. - Pre-rotation advisory. Releases before v1.0.0 (2026-08-31) shipped a tracked
.envwith a generated-looking database password. RotateCONFLUENCE_DB_PASSWORDif your deployment reused it. - The database listens only on the internal network.
- Upstream image digests are pinned; the weekly freshness job flags drift loudly.
Maintained by Vladimir Mikhalev — Docker Captain · IBM Champion · AWS Community Builder