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.
119 lines
6.5 KiB
Markdown
119 lines
6.5 KiB
Markdown
---
|
|
type: configuration
|
|
title: Gitea
|
|
description: Gitea deployment on Dankclaw with its web UI reverse-proxied by the canonical Caddy service.
|
|
tags:
|
|
- gitea
|
|
- dankclaw
|
|
- quadlet
|
|
- caddy
|
|
timestamp: 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](../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:
|
|
|
|
```mermaid
|
|
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`](../../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/`](../../dankclaw/gitea/quadlet/) |
|
|
| Caddyfile | `/home/dank/Containers/caddy/Caddyfile` | [`dankclaw/Caddyfile`](../../dankclaw/Caddyfile) |
|
|
| Secrets | `/home/dank/Containers/gitea/env` (0600; loaded via `EnvironmentFile=`) | [`dankclaw/gitea/.env.example`](../../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 with
|
|
`podman exec --user 1000 gitea-server ...`.
|
|
- **The host auto-reboots.** `unattended-upgrades` reboots 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 `gitea` Quadlet unit. The `dankclaw/compose.yaml` that mapped 3001 was **retired on 2026-09-16** (staged in `.AGENTTRASH/`) once an ownership audit showed every container on this host reports a `PODMAN_SYSTEMD_UNIT` label — 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.yml` is 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.cloud` is served by the canonical Caddy **unit** (`dankclaw/caddy/quadlet/caddy.container`, repo `dankclaw/Caddyfile`), which proxies to `192.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)
|