The vault is the project's source of truth, so a link to a page that does not
exist is a promise the repo cannot keep. Three were dangling:
- Dankclaw/Gitea.md pointed twice at dankclaw/compose.yaml — **which this
session retired**. The clean cutover obligation from my own change: the page
now describes the unit that publishes 3000 and the canonical Caddy unit, and
records why the compose file is gone.
- Dankclaw/Hermes-Dashboard.md linked [[LAN DNS]]; the page is [[LAN-DNS]].
- LLM/frank-medium-radiance-mxfp4.md linked [[Observability on Dankclaw]]; the
page is [[Observability]].
scripts/check-vault-links.py + a seam keep it that way. The checker models
Obsidian's rules, which took three corrections to get right — and each was a
false positive that would have sent me editing healthy docs:
1. Wikilinks are case-insensitive. A case-sensitive matcher reported 45
breaks; 39 were `[[qBittorrent]]` vs qbittorrent.md.
2. `[[folder/Note]]` resolves by path suffix, not by stem.
3. `%20` in a markdown link is URL-encoding, not a filename.
Validating the linter against the resolver it models is the prerequisite for
trusting any of its output — the same discipline that caught a bad assertion of
my own earlier tonight.
6.5 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | ||||
|---|---|---|---|---|---|---|---|---|
| configuration | Gitea | Gitea deployment on Dankclaw with its web UI reverse-proxied by the canonical Caddy service. |
|
2026-08-26 |
Gitea
Gitea is a self-hosted Git service with issues, pull requests, and a web UI. On Dankclaw it runs as two Quadlet-managed containers in the rootless Podman session of user dank. The canonical Caddy on the same host reverse-proxies its web UI at gitea.franksdank.cloud.
Host: Dankclaw — LAN access: http://dankclaw:3000 (or http://192.168.0.143:3000) — Proxy domain: gitea.franksdank.cloud — Docs: https://docs.gitea.com
Containers
| Container | Unit | Image | Purpose |
|---|---|---|---|
gitea-postgres |
gitea-postgres.service |
docker.io/library/postgres:16-alpine |
Database |
gitea-server |
gitea-server.service |
docker.io/gitea/gitea:latest |
Web UI, API, git (HTTP :3000, SSH :2222) |
The containers share the private bridge network systemd-gitea. The quadlet network file gitea.network enables DNS, so the containers resolve each other by name. The automatic podman default network has DNS disabled. Do not run the Gitea containers on it.
Hosted repositories
| Repository | Purpose |
|---|---|
dank/serverAppConfigs |
this repo — Podman stacks + LLM fleet |
dank/vllmScripts |
retired 2026-08-22 — merged into dank/serverAppConfigs (history preserved) |
The LLM fleet knowledge base: serverAppConfigs-docs/LLM/index.md
Management
Run all commands as dank on Dankclaw.
| Action | Command |
|---|---|
| Start all | systemctl --user start gitea-postgres gitea-server |
| Stop all | systemctl --user stop gitea-server gitea-postgres |
| Restart Gitea only | systemctl --user restart gitea-server |
| Status | systemctl --user status gitea-postgres gitea-server |
| Container logs | podman logs -f gitea-server |
| Unit logs | journalctl --user -u gitea-server -f |
The units start in dependency order:
graph LR
N[gitea-network.service] --> P[gitea-postgres.service]
P --> S[gitea-server.service]
Boot persistence
User-level linger is enabled for dank (loginctl enable-linger dank). The units start at host boot without a login session. Each unit carries [Install] WantedBy=default.target. The podman generator applies it at boot; no symlink is needed.
The containers use the quadlet fresh-start model. A stop removes the container (podman run --rm --replace). The next start recreates it. The bind-mounted data survives. The canonical Caddy is managed separately by the Dankclaw stack.
Secrets
The database password lives in /home/dank/Containers/gitea/env on the host
(mode 0600); gitea-postgres.container and gitea-server.container load it
via EnvironmentFile= (verified from the live units — the ${GITEA_DB_PASSWORD}
placeholders are expanded by systemd at start). The password never enters this
repository. Placeholders live in
dankclaw/gitea/.env.example.
Do not change the password in place. Change the PostgreSQL role first, then
update the env file and the [database] PASSWD line in the app.ini (see
Gotchas), then restart the stack.
Configuration files
| File | Location | Repo copy |
|---|---|---|
| Quadlet units | ~/.config/containers/systemd/gitea-{postgres,server}.container, gitea.network |
dankclaw/gitea/quadlet/ |
| Caddyfile | /home/dank/Containers/caddy/Caddyfile |
dankclaw/Caddyfile |
| Secrets | /home/dank/Containers/gitea/env (0600; loaded via EnvironmentFile=) |
dankclaw/gitea/.env.example |
After editing a repo copy, deploy through scripts/deploy.sh dankclaw. The Gitea database/server units are installed from this directory; the canonical Caddy and its rendered Caddyfile are deployed as the separate caddy service. Do not manually recreate the retired gitea-caddy unit.
Data volumes
Per the live quadlet units (Volume= lines):
| Container path | Host path | Contents |
|---|---|---|
/data |
/home/dank/Containers/gitea/data |
Git repositories, app.ini, attachments |
/var/lib/postgresql/data |
/home/dank/Containers/gitea/postgres |
PostgreSQL data |
Back up /home/dank/Containers/gitea/ (tar) or pg_dump the database. See the knowledge base page Gitea.
Gotchas
- Data files are owned by
dank(uid 1000), not root. The quadlet units run podman in the user manager with no--user/UserNS override, so container uid 1000 is literally dank's host uid — there is no subuid offset for these containers. Edit files as the owning user withpodman exec --user 1000 gitea-server .... - The host auto-reboots.
unattended-upgradesreboots Dankclaw when a package needs it. The quadlet units make Gitea survive that. See the 2026-08-16 incident below. - Port 3000, and one owner. The live host port is 3000, published by the
giteaQuadlet unit. Thedankclaw/compose.yamlthat mapped 3001 was retired on 2026-09-16 (staged in.AGENTTRASH/) once an ownership audit showed every container on this host reports aPODMAN_SYSTEMD_UNITlabel — a second composition path could only spawn a duplicate fighting a unit for a name. Do not reintroduce a compose service for Gitea or the proxy. - Legacy compose retired.
/opt/gitea/podman-compose.ymlis retired to/opt/gitea/.deprecated/. Do not run it. Its containers collide with the Quadlet units on ports 3000 and 2222. - Canonical proxy.
gitea.franksdank.cloudis served by the canonical Caddy unit (dankclaw/caddy/quadlet/caddy.container, repodankclaw/Caddyfile), which proxies to192.168.0.143:3000. Do not recreate a Gitea-specific Caddy unit or publish another proxy on ports 80/443. If a legacy unit is ever installed again, the deployer stages it under~/.AGENTTRASH/YYYYMMDD-gitea-caddy/before starting canonical Caddy.
Incident: 2026-08-16 — down after unattended reboot
unattended-upgrades rebooted Dankclaw at 15:01 on 2026-08-16. The Gitea containers ran through podman-compose with restart: unless-stopped and no systemd units. Rootless podman does not auto-start containers at boot without units. Gitea stayed down until a manual start at 16:02. The fix: migrate the stack to quadlet units with linger (this page). After the fix, verify on the next reboot.
See Also
- Dankclaw Stack
- Postgres
- Knowledge base: Gitea (tools)