Skip to content

Commit 11c020e

Browse files
committed
docs: add bugs index for hetzner demo tracker deployment
Collect all deployer bugs found during this deployment in one file with links to full descriptions in the relevant command docs. 11 bugs total across create/provision/release/run/test: - B-01: create template binds to 0.0.0.0 (IPv4 only) - B-02: create template defaults to SQLite silently - B-03: instance_name: null unexplained in template - B-04: provision SSH probe budget too short for Hetzner (120s) - B-05: passphrase-protected SSH keys fail silently in Docker - B-06: UDP tracker domains missing from provision output - B-07: release fails when docker not in PATH [FIXED] - B-08: MySQL 'root' username not rejected at creation time - B-09: MySQL root password silently diverges (_root suffix) - B-10: MySQL password not URL-encoded in tracker.toml - B-11: test DNS check false positives with floating IP
1 parent 81a31b9 commit 11c020e

2 files changed

Lines changed: 178 additions & 0 deletions

File tree

docs/deployments/hetzner-demo-tracker/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Deploy a public Torrust Tracker demo instance to Hetzner Cloud and document ever
4343
9. [Maintenance](maintenance/README.md) — post-deployment operational tasks:
4444
- [Secrets rotation](maintenance/secrets-rotation.md) — rotate all secrets after AI-assisted deployment
4545
10. [Tracker Registry](tracker-registry.md) — submit the tracker to public registries (newTrackon)
46+
11. [Bugs](bugs.md) — all deployer bugs discovered during this deployment (11 bugs, 1 fixed)
4647

4748
## Deployment
4849

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Bugs Found During Hetzner Demo Tracker Deployment
2+
3+
All deployer bugs discovered during this deployment, collected in one place.
4+
Each entry links to the full description in the relevant command document.
5+
6+
> **Legend**: 🔴 Open  |  🟢 Fixed (in this branch, pending merge)
7+
8+
---
9+
10+
## `create` command
11+
12+
### B-01 — Template defaults bind addresses to `0.0.0.0` (IPv4 only)
13+
14+
🔴 Open  |  **Severity**: Major
15+
16+
The `create template` command hard-codes `0.0.0.0` as the default bind address for
17+
all UDP and HTTP tracker sockets. IPv6 clients cannot connect. Public trackers
18+
should bind to `[::]` by default.
19+
20+
Full description: [commands/create/problems.md — Template defaults bind addresses to `0.0.0.0`](commands/create/problems.md#problem-template-defaults-bind-addresses-to-0000-ipv4-only)
21+
22+
---
23+
24+
### B-02 — Template silently defaults to SQLite with no database choice
25+
26+
🔴 Open  |  **Severity**: Major
27+
28+
The `create template` command uses SQLite without prompting the user or noting that
29+
MySQL is the recommended choice for production. Users may not notice until
30+
deep into the deployment.
31+
32+
Full description: [commands/create/problems.md — Template silently defaults to SQLite](commands/create/problems.md#problem-template-silently-defaults-to-sqlite--no-database-choice-presented)
33+
34+
---
35+
36+
### B-03 — `instance_name: null` generated with no explanation
37+
38+
🔴 Open  |  **Severity**: Minor
39+
40+
The `create template` command outputs `"instance_name": null` with no
41+
documentation of what the deployer will do with a null value (it auto-generates
42+
`torrust-tracker-vm-{env_name}`). The template should explain this.
43+
44+
Full description: [commands/create/problems.md — Template generates `instance_name: null`](commands/create/problems.md#problem-template-generates-instance_name-null-with-no-explanation)
45+
46+
---
47+
48+
## `provision` command
49+
50+
### B-04 — SSH probe budget too short for Hetzner (120 s hardcoded)
51+
52+
🔴 Open  |  **Severity**: Major
53+
54+
The deployer polls SSH with a fixed budget of 60 × 2 s = 120 s.
55+
On Hetzner `ccx23`, cloud-init user provisioning can take over 3 minutes,
56+
causing `provision` to fail even when the server eventually comes up healthy.
57+
58+
Full description: [commands/provision/problems.md — SSH connectivity times out](commands/provision/problems.md#problem-provisioning-fails--ssh-connectivity-to-newly-created-server-times-out)
59+
60+
---
61+
62+
### B-05 — Passphrase-protected SSH keys fail silently inside Docker
63+
64+
🔴 Open  |  **Severity**: Major
65+
66+
When the deployer runs inside Docker (the standard production workflow), there is
67+
no SSH agent. If the configured deployment key has a passphrase, every probe
68+
attempt silently returns `Permission denied`. Neither `create environment` nor
69+
`validate` warns about this. The user sees repeated SSH failures with no
70+
diagnostic pointing at the passphrase as the cause.
71+
72+
Full description: [commands/provision/problems.md — SSH probe always fails — passphrase-protected key](commands/provision/problems.md#problem-ssh-probe-always-fails-from-docker-container--passphrase-protected-private-key)
73+
74+
---
75+
76+
### B-06 — UDP tracker domains missing from `provision` output
77+
78+
🔴 Open  |  **Severity**: Minor
79+
80+
The `domains` array in the `provision` JSON output only contains HTTP-based
81+
domains. The two UDP tracker domains configured in the environment are silently
82+
omitted.
83+
84+
Full description: [commands/provision/bugs.md — UDP tracker domains missing](commands/provision/bugs.md#bug-udp-tracker-domains-missing-from-provision-output)
85+
86+
---
87+
88+
## `release` command
89+
90+
### B-07 — `release` fails when `docker` is not in PATH (Docker-based usage)
91+
92+
🟢 Fixed (this branch)  |  **Severity**: High
93+
94+
The `release` command validates the rendered `docker-compose.yml` locally by
95+
running `docker compose config`. When the deployer runs inside its own Docker
96+
container (where `docker` is not installed), this validation fails with
97+
`ENOENT`. The `release` command is completely broken for Docker-based usage.
98+
99+
**Fix**: the validator now skips with a warning when `docker` is not in PATH
100+
instead of hard-failing.
101+
102+
Full description: [commands/release/bugs.md — `release` fails when docker not in PATH](commands/release/bugs.md#bug-release-fails-when-deployer-runs-inside-docker-docker-not-in-path)
103+
104+
---
105+
106+
## `run` command
107+
108+
### B-08 — MySQL `"root"` username not rejected at creation time
109+
110+
🔴 Open  |  **Severity**: High
111+
112+
The deployer accepts `"root"` as the MySQL application username. MySQL 8.4
113+
explicitly rejects `MYSQL_USER=root`. The error only surfaces at `run` time
114+
when MySQL fails to start, not at `create environment` when the bad value is first
115+
accepted.
116+
117+
Full description: [commands/run/bugs.md — MySQL `"root"` not rejected at creation time](commands/run/bugs.md#bug-1-mysql-app-username-root-is-not-rejected-at-environment-creation-time)
118+
119+
---
120+
121+
### B-09 — MySQL root password silently diverges from operator-configured password
122+
123+
🔴 Open  |  **Severity**: Medium
124+
125+
The deployer auto-derives the MySQL root password by appending `"_root"` to the
126+
configured application password (`format!("{password}_root")`). The effective
127+
root password is never surfaced to the operator, making it impossible to connect
128+
to MySQL as `root` using the value from the env config.
129+
130+
Full description: [commands/run/bugs.md — MySQL root password silently diverges](commands/run/bugs.md#bug-2-mysql-root-password-silently-diverges-from-the-configured-password)
131+
132+
---
133+
134+
### B-10 — MySQL password not URL-encoded in `tracker.toml` connection string
135+
136+
🔴 Open  |  **Severity**: High
137+
138+
The tracker `tracker.toml` template renders the MySQL password raw into the
139+
database connection URL. If the password contains URL-special characters (e.g.
140+
`/`, `@`, `#`), the URL is malformed and the tracker crashes at startup with a
141+
misleading `InvalidPort` error. Worked around in this deployment by manually
142+
URL-encoding the password.
143+
144+
Full description: [commands/run/bugs.md — MySQL password not URL-encoded](commands/run/bugs.md#bug-3-mysql-password-is-not-url-encoded-in-the-tracker-connection-string)
145+
146+
---
147+
148+
## `test` command
149+
150+
### B-11 — DNS check produces false positives when a floating IP is in use
151+
152+
🔴 Open  |  **Severity**: Minor
153+
154+
The `test` command resolves each domain and compares the result against the
155+
**instance IP**. When a floating IP is assigned and DNS points to it instead,
156+
every domain triggers a false-positive warning (`expected 46.225.234.201, got
157+
116.202.176.169`). The deployer has no concept of floating IPs.
158+
159+
Full description: [commands/improvements.md — Deployer is not aware of floating IPs](commands/improvements.md#improvement-deployer-is-not-aware-of-floating-ips)
160+
161+
---
162+
163+
## Summary
164+
165+
| ID | Command | Description | Severity | Status |
166+
| ---- | ----------- | ----------------------------------------------------- | -------- | -------- |
167+
| B-01 | `create` | Template binds to `0.0.0.0` (IPv4 only) | Major | 🔴 Open |
168+
| B-02 | `create` | Template defaults to SQLite silently | Major | 🔴 Open |
169+
| B-03 | `create` | `instance_name: null` unexplained | Minor | 🔴 Open |
170+
| B-04 | `provision` | SSH probe budget too short for Hetzner (120 s) | Major | 🔴 Open |
171+
| B-05 | `provision` | Passphrase-protected SSH keys fail silently in Docker | Major | 🔴 Open |
172+
| B-06 | `provision` | UDP tracker domains missing from output | Minor | 🔴 Open |
173+
| B-07 | `release` | Fails when `docker` not in PATH (Docker-based usage) | High | 🟢 Fixed |
174+
| B-08 | `run` | MySQL `"root"` username not rejected at creation time | High | 🔴 Open |
175+
| B-09 | `run` | MySQL root password silently diverges | Medium | 🔴 Open |
176+
| B-10 | `run` | MySQL password not URL-encoded in connection string | High | 🔴 Open |
177+
| B-11 | `test` | DNS check false positives with floating IP | Minor | 🔴 Open |

0 commit comments

Comments
 (0)