Commit 29f5d17
committed
675b826 docs: add improvements index for hetzner demo tracker deployment (Jose Celano)
11c020e docs: add bugs index for hetzner demo tracker deployment (Jose Celano)
81a31b9 docs: add tracker registry guide for newTrackon submission (Jose Celano)
4c79724 docs(maintenance): add uptime monitoring guide (Jose Celano)
9b11d27 docs: record successful reboot, tick API/SSH checklist, add public REST health check endpoint (Jose Celano)
4b55ad0 docs(maintenance): add step 4g - delete old SSH key from Hetzner console (done) (Jose Celano)
954a6a8 docs(maintenance): mark local file archival done (step 7) and secrets rotation complete (Jose Celano)
fda93d0 docs(maintenance): mark SSH deployer key rotation as done (step 4) (Jose Celano)
d3d1401 docs(maintenance): mark MySQL torrust and root password rotation as done (step 2) (Jose Celano)
c55763c docs(maintenance): mark tracker admin token rotation as done (step 1) (Jose Celano)
c684920 docs(maintenance): fix restart vs recreate for env var changes in step 1 (Jose Celano)
a3775f1 docs(maintenance): add OS updates guide with apply/verify/reboot procedure (Jose Celano)
8a0064d docs(maintenance): mark Grafana admin password as rotated (step 3 done) (Jose Celano)
96d1628 docs(maintenance): mark Hetzner Cloud and DNS API tokens as deleted (Jose Celano)
0894d85 docs(maintenance): add secrets rotation guide for post-AI-agent deployment (Jose Celano)
ea7ea22 docs(post-provision): add Hetzner backups step to ToC and post-provision index (Jose Celano)
36af759 docs(post-provision): add screenshot of Hetzner backups enabled state (Jose Celano)
7001123 docs(deploy): update progress — all 9 services verified, fill in service endpoints table (Jose Celano)
7a4f714 docs(verify): add Torrust tracker client announce tests for HTTP and UDP trackers (Jose Celano)
487c1b5 docs(verify): add backup verification and document credentials oversight (Jose Celano)
6870512 docs(verify): add actual tree output to storage verification (Jose Celano)
31c4869 docs(verify): add storage volume mount verification (Jose Celano)
8f97bf8 docs(verify): add MySQL database connectivity verification (Jose Celano)
c5ab1db docs(verify): add Docker services health and log verification (Jose Celano)
7c3d68b docs(verify): add UDP tracker verification results (Jose Celano)
c0dd03a docs(verify): add Grafana verification results (Jose Celano)
a2d454c docs(verify): fix corrupted results table in api.md (Jose Celano)
96224e0 docs(verify): add API, HTTP tracker, and health check verification results (Jose Celano)
fb288b3 docs: add test command output, verify guides, floating IP improvement (Jose Celano)
45f06bf docs(hetzner-demo): populate run README and add test command docs (Jose Celano)
16167cc docs(hetzner-demo): add Bug 3 (URL encoding) and run improvements doc (Jose Celano)
d3d6c64 docs(hetzner-demo): clarify Bug 2 root password was never implemented (Jose Celano)
b136e5c docs(hetzner-demo): document run command MySQL bugs and failure (Jose Celano)
a5c7913 docs: document successful release command (task 3.3 done) (Jose Celano)
fb7a7ff fix: skip docker-compose local validation when docker is not in PATH (Jose Celano)
e874e96 docs: document release fails when deployer runs inside Docker (docker not in PATH) (Jose Celano)
beaf2f9 docs: add observations file and fill in missing ToC entries (Jose Celano)
31d724c docs: document volume/IP setup sequencing tradeoffs in post-provision (Jose Celano)
650936f docs: document configure command execution (task 3.2 done) (Jose Celano)
1422f83 docs: fix misleading volume snapshot claim; document limitation (Jose Celano)
4fba745 docs: document volume setup via Hetzner Cloud API (Jose Celano)
4a4914b docs: document DNS record creation via Hetzner Cloud API (Jose Celano)
837057d docs: [#405] configure floating IPs permanently on VM via netplan (Jose Celano)
db6a702 docs: [#405] add post-provision guides (DNS + volume setup) and assign floating IPs (Jose Celano)
3872406 docs: [#405] mark provision task as complete in issue tracker (Jose Celano)
fda04f1 docs: [#405] add attempt-4 screenshot and document Hetzner activity log confusion (Jose Celano)
9ba435f docs: [#405] document provision success, passphrase bug, IPv6 omission, and UDP domains bug (Jose Celano)
642d043 docs: [#405] add cleanup-between-attempts guide and update provision README (Jose Celano)
a28016b feat: [#405] increase SSH retry budget to 5 minutes with 5s interval (Jose Celano)
182e33b feat: [#405] log full SSH stderr in wait_for_connectivity retry messages (Jose Celano)
3248a63 fix: [#405] add IdentitiesOnly=yes to Ansible ssh_args (Jose Celano)
019e39c fix: [#405] add IdentitiesOnly=yes to default SSH options (Jose Celano)
f4c5e8f docs: [#405] add provision improvements document with deployer enhancement recommendations (Jose Celano)
010a053 docs: [#405] refine Problem 5 root cause with precise log-based evidence (Jose Celano)
3ffb1d4 docs: [#405] add debug-command-failure skill for investigating deployer errors (Jose Celano)
2034809 docs: [#405] refactor hetzner-demo-tracker docs into per-command subdirectories (Jose Celano)
61e24fe docs: [#405] configure environment and create for Hetzner demo tracker (Phase 2) (Jose Celano)
739f003 docs: [#405] document and complete prerequisites for Hetzner demo tracker (Jose Celano)
e5ad25c docs: [#405] create deployment journal directory structure for Hetzner demo tracker (Jose Celano)
Pull request description:
Closes #405
## Summary
Real-world deployment of a Torrust Tracker demo instance to Hetzner Cloud using the deployer tool, with full documentation of every step, decision, and problem encountered. The documentation will serve as both an internal reference and a source for a blog post on [torrust.com](https://torrust.com).
## Progress
- [x] Phase 1: Prerequisites documented
- [x] Phase 2: Environment created and configured
- [x] Phase 3.1: Infrastructure provisioned (Hetzner `ccx23` at `nbg1`)
- [x] Phase 3.2: Post-provision manual steps (DNS, volume, Hetzner backups)
- [x] Phase 3.3: Configure instance (Docker 28.2.2, Docker Compose v2.29.2)
- [x] Phase 3.4: Release application (all Docker images staged)
- [x] Phase 3.5: Run services (all 5 services healthy)
- [x] Phase 4: Verify and document (HTTP tracker, UDP tracker, API, Grafana, health check, MySQL, storage, backup)
- [x] Phase 5: Post-deployment maintenance
- [x] Secrets rotation (all 7 secrets rotated)
- [x] OS updates (59 packages incl. 37 security, reboot, all services healthy)
- [x] Uptime monitoring documented (Hetzner has no native monitoring — external tools listed)
- [x] Tracker registry — `udp1` submitted to newTrackon (2026-03-04)
- [x] Phase 6: Bug and improvement indexes
- [x] [bugs.md](docs/deployments/hetzner-demo-tracker/bugs.md) — 11 bugs, 1 fixed
- [x] [improvements.md](docs/deployments/hetzner-demo-tracker/improvements.md) — 13 recommendations
## What's in this PR
### Documentation (`docs/deployments/hetzner-demo-tracker/`)
New deployment journal with per-command subdirectories:
- **prerequisites.md** — Hetzner account, API token, SSH key setup, tool versions
- **deployment-spec.md** — Environment config decisions and sanitized config
- **commands/provision/** — Command walkthrough, problems (5), improvements (7), bugs, cleanup procedure
- **commands/configure/** — Docker installation walkthrough
- **commands/release/** — Image pull walkthrough
- **commands/run/** — Service start walkthrough, problems, improvements, bugs (3)
- **post-provision/** — DNS setup, volume setup, Hetzner backups
- **verify/** — Full verification index: HTTP tracker, UDP tracker, API, Grafana, health check, Docker services, MySQL, storage, backup
- **maintenance/**
- `secrets-rotation.md` — Complete procedure for rotating all 7 secrets; records first rotation (2026-03-04)
- `os-updates.md` — `apt` update procedure with log of first run (59 updates, reboot, all services healthy)
- `uptime-monitoring.md` — Documents Hetzner monitoring gap vs DigitalOcean; lists external tools (UptimeRobot, Freshping, etc.)
- **tracker-registry.md** — newTrackon submission; explains why only `udp1` is listed (`udp2` kept quiet for production debugging)
- **bugs.md** — All 11 deployer bugs found, with severity, status, and links to full descriptions
- **improvements.md** — All 13 improvement recommendations, with links to full descriptions
- **observations.md** — Cross-cutting insights and deployer learnings
### Code fixes (`src/`, `templates/`)
- `fix: IdentitiesOnly=yes` added to default SSH options (`src/adapters/ssh/client.rs`)
- `fix: IdentitiesOnly=yes` added to Ansible `ssh_args` (`templates/ansible/ansible.cfg`)
- `feat:` SSH retry budget increased to 300s (60 × 5s)
- `feat:` Full SSH stderr logged in retry messages for easier diagnosis
- `fix:` `release` no longer hard-fails when `docker` is not in PATH inside Docker container
### New skill
- `.github/skills/usage/operations/debug-command-failure/skill.md`
## Service Endpoints
| Service | URL | Status |
| -------------- | ------------------------------------------------- | ---------- |
| HTTP Tracker 1 | `https://http1.torrust-tracker-demo.com/announce` | ✅ Running |
| HTTP Tracker 2 | `https://http2.torrust-tracker-demo.com/announce` | ✅ Running |
| UDP Tracker 1 | `udp://udp1.torrust-tracker-demo.com:6969` | ✅ Running |
| UDP Tracker 2 | `udp://udp2.torrust-tracker-demo.com:6868` | ✅ Running |
| Tracker API | `https://api.torrust-tracker-demo.com/api/v1` | ✅ Running |
| Grafana | `https://grafana.torrust-tracker-demo.com` | ✅ Running |
## Bugs Found (11 total, 1 fixed)
| ID | Command | Description | Severity | Status |
| ---- | ----------- | ----------------------------------------------------- | -------- | -------- |
| B-01 | `create` | Template binds to `0.0.0.0` (IPv4 only) | Major | 🔴 Open |
| B-02 | `create` | Template defaults to SQLite silently | Major | 🔴 Open |
| B-03 | `create` | `instance_name: null` unexplained | Minor | 🔴 Open |
| B-04 | `provision` | SSH probe budget too short for Hetzner (120 s) | Major | 🔴 Open |
| B-05 | `provision` | Passphrase-protected SSH keys fail silently in Docker | Major | 🔴 Open |
| B-06 | `provision` | UDP tracker domains missing from output | Minor | 🔴 Open |
| B-07 | `release` | Fails when `docker` not in PATH | High | 🟢 Fixed |
| B-08 | `run` | MySQL `"root"` username not rejected at creation time | High | 🔴 Open |
| B-09 | `run` | MySQL root password silently diverges | Medium | 🔴 Open |
| B-10 | `run` | MySQL password not URL-encoded in connection string | High | 🔴 Open |
| B-11 | `test` | DNS check false positives with floating IP | Minor | 🔴 Open |
## Key learnings documented
1. **Passphrase-protected SSH keys fail silently in Docker** — no agent, no TTY, signing fails. Root cause of all provision failures. Fix: remove passphrase from deployment keys.
2. **`docker compose restart` does not re-read env vars** — must use `up -d --force-recreate` after rotating secrets in `.env`.
3. **MySQL password URL-encoding in `tracker.toml`** — `/` in password must be encoded as `%2F` in the connection string.
4. **Hetzner has no native uptime monitoring** — requires an external service such as UptimeRobot.
5. **UDP Tracker 2 kept off public tracker lists** — public registration causes constant announce noise that makes production log debugging impractical.
ACKs for top commit:
josecelano:
ACK 675b826
Tree-SHA512: 7698d2888be422336c210c57e60dd06d906d95fff48ae64bdf9b98ccd92fb6c04ee29c7e167cacdff273f1fbdff07c1c9e3ca04949b4876b3552617e582acc21
70 files changed
Lines changed: 6267 additions & 164 deletions
File tree
- .github/skills/usage/operations/debug-command-failure
- docs
- deployments/hetzner-demo-tracker
- commands
- configure
- create
- provision
- release
- run
- test
- maintenance
- media
- configuratrion-ai-agent-questions
- post-provision
- verify
- issues
- src
- adapters/ssh
- infrastructure/templating/docker_compose
- templates/ansible
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 231 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
| 182 | + | |
182 | 183 | | |
183 | 184 | | |
184 | 185 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
0 commit comments