Docker Stacks
GitOps-managed Docker Compose stacks. Push changes to main branch and Gitea Actions will automatically deploy.
Structure
stacks/
├── traefik/ # Reverse proxy + SSL
├── authentik/ # SSO/Identity provider
├── registry/ # Docker registry
├── immich/ # Photo management
├── planka/ # Kanban boards
├── syncthing/ # File sync
├── filebrowser/ # Web file manager
├── memento/ # Custom app
├── obsidian-tools/ # Obsidian vault tools
├── perilous/ # Blog/website
├── ramz/ # Go web app
├── bookclub/ # Form mailer
├── watchtower/ # Auto container updates
├── dockge/ # Container management UI
└── smokeping/ # Network monitoring
How It Works
- Edit compose files in
stacks/<service>/ - Commit and push to
main - Gitea Actions detects changed stacks
- Deploys only the changed stacks to
/var/core/<service>/
Manual Deploy
# Deploy single stack
./scripts/deploy.sh traefik
# Deploy all stacks
./scripts/deploy.sh all
Required Gitea Secrets
Set these in Gitea → Repository → Settings → Actions → Secrets:
Global
| Secret | Description |
|---|---|
DOMAIN |
Base domain (e.g., ghost.tel) |
VOLUMES_ROOT |
Data root path (e.g., /var/core) |
ACME_EMAIL |
Email for Let's Encrypt |
Authentik
| Secret | Description |
|---|---|
AUTHENTIK_SECRET_KEY |
Generate: openssl rand -hex 50 |
AUTHENTIK_PG_PASS |
PostgreSQL password |
Immich
| Secret | Description |
|---|---|
IMMICH_DB_PASSWORD |
PostgreSQL password |
Planka
| Secret | Description |
|---|---|
PLANKA_SECRET_KEY |
Generate: openssl rand -hex 64 |
PLANKA_OIDC_CLIENT_ID |
Authentik client ID |
PLANKA_OIDC_CLIENT_SECRET |
Authentik client secret |
Registry
| Secret | Description |
|---|---|
REGISTRY_HTTP_SECRET |
Generate: openssl rand -hex 32 |
Memento
| Secret | Description |
|---|---|
MEMENTO_AUTH_SECRET |
Auth.js secret |
MEMENTO_AUTHENTIK_CLIENT_ID |
Authentik client ID |
MEMENTO_AUTHENTIK_CLIENT_SECRET |
Authentik client secret |
Bookclub
| Secret | Description |
|---|---|
BOOKCLUB_SMTP_HOST |
SMTP server |
BOOKCLUB_SMTP_USER |
SMTP username |
BOOKCLUB_SMTP_PASS |
SMTP password |
BOOKCLUB_MAIL_FROM |
From email |
BOOKCLUB_MAIL_TO |
Recipient email |
BOOKCLUB_SECRET_PHRASE |
Form submission secret |
Perilous
| Secret | Description |
|---|---|
PERILOUS_CODE_SERVER_PASSWORD |
Code-server password |
Runner Setup
The workflow requires a self-hosted runner on the prod server:
# On ubuntu-prod, register a Gitea runner
# See: https://docs.gitea.com/usage/actions/act-runner
# Install act_runner
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.6/act_runner-0.2.6-linux-amd64
chmod +x act_runner-*
sudo mv act_runner-* /usr/local/bin/act_runner
# Register with Gitea
act_runner register --no-interactive \
--instance https://gitea.ghost.tel \
--token <runner-token> \
--name ubuntu-prod \
--labels ubuntu-prod
# Run as service
act_runner daemon
First-Time Setup
-
Create the
webDocker network:docker network create web -
Create
acme.jsonfor Traefik:touch /var/core/traefik/acme.json chmod 600 /var/core/traefik/acme.json -
Deploy traefik first:
./scripts/deploy.sh traefik -
Then deploy other stacks as needed.
Description
Languages
JavaScript
52.2%
Shell
26.3%
Dockerfile
13.6%
Ruby
7.9%