This directory mirrors the live demo server's filesystem. Each file's path here corresponds exactly to its path on the server:
server/<path> → <path> on the server
For example, server/opt/torrust/docker-compose.yml is /opt/torrust/docker-compose.yml on
the server.
- Auditable, reviewable record of the server configuration
- Reference for reproducing or migrating the server
- Track configuration changes over time via git history
All secrets have been replaced with clearly-named placeholders. To restore a working configuration, substitute each placeholder with the real value:
| Placeholder | Secret |
|---|---|
<MYSQL_ROOT_PASSWORD> |
MySQL root password |
<MYSQL_PASSWORD> |
MySQL torrust user password |
<TORRUST_TRACKER_CONFIG_OVERRIDE_HTTP_API__ACCESS_TOKENS__ADMIN> |
Tracker HTTP API admin token |
<GF_SECURITY_ADMIN_PASSWORD> |
Grafana admin password |
<EMAIL_LETS_ENCRYPT_NOTIFICATIONS> |
Let's Encrypt email address |
<REDACTED> |
Any other SSH keys or tokens |
To find all placeholders in one shot:
grep -r '<[A-Z_]*>' server/The following are excluded — they contain runtime data, large binaries, or additional secrets:
| Path on server | Reason excluded |
|---|---|
/opt/torrust/storage/backup/config/ |
Backup archives (.tar.gz) |
/opt/torrust/storage/backup/mysql/ |
MySQL dumps (.sql.gz) |
/opt/torrust/storage/caddy/config/ |
Caddy runtime state |
/opt/torrust/storage/caddy/data/ |
TLS certificates (secrets) |
/opt/torrust/storage/grafana/data/ |
Grafana database, plugins |
/opt/torrust/storage/mysql/data/ |
MySQL data files |
/opt/torrust/storage/tracker/lib/ |
SQLite database |
/opt/torrust/storage/tracker/log/ |
Log files |
ip6tables: true is required to prevent Docker chain rewrites from wiping ufw's live
ip6tables rules after every container restart. Without it, all IPv6 UDP traffic is
silently dropped after each restart.
enable_ipv6: true with subnet fd01:db8:1::/64 on proxy_network gives the tracker
container an IPv6 address, which causes Docker to create ip6tables DNAT rules that bypass
docker-proxy for native IPv6 traffic. Without this, docker-proxy silently drops all native
IPv6 UDP packets because it cannot relay them to an IPv4-only container backend.
A *nat POSTROUTING SNAT rule must be prepended to /etc/ufw/before6.rules on the
server to rewrite reply source addresses from the Docker ULA bridge subnet
(fd01:db8:1::/64) to the floating IPv6 (2a01:4f8:1c0c:828e::1). Without it, Docker's
MASQUERADE rewrites replies to the primary server IPv6 and clients probing the floating IP
time out.
See docs/docker-ipv6.md for the full explanation and all application steps.
Each Hetzner floating IP requires a policy routing table entry so that replies leave via
the same floating IP rather than the primary server IP. Adding a new floating IP requires
updating this file and running sudo netplan apply.