This directory contains architectural decision records for the Torrust Tracker Deployer project. Each ADR documents an important architectural decision, the context that led to it, and the consequences of the decision.
| Status | Date | Decision | Summary |
|---|---|---|---|
| ✅ Accepted | 2026-02-26 | SDK Package Naming | Keep "SDK" name for packages/sdk — the modern API-wrapper meaning is industry-standard |
| ✅ Accepted | 2026-02-24 | SDK Presentation Layer Interface Design | Return () from SDK operations; no domain types or typestate pattern in the SDK public API |
| ✅ Accepted | 2026-02-24 | Docker Compose Local Validation Placement | Validate rendered docker-compose.yml in the infrastructure generator, not the app layer |
| ✅ Accepted | 2026-02-17 | Application-Layer Progress Reporting Trait | Use trait-based progress reporting with Dependency Inversion for testable, reusable design |
| ✅ Accepted | 2026-02-13 | Concurrent Docker Image Builds in Tests | Treat "already exists" tagging error as success when parallel tests build same image |
| ✅ Accepted | 2026-02-06 | Agent Skills Content Strategy | Three-tier content strategy: self-contained workflows, progressive disclosure, linked docs |
| ✅ Accepted | 2026-01-27 | Atomic Ansible Playbooks | Require one-responsibility playbooks with Rust-side gating and registered static templates |
| ✅ Accepted | 2026-01-24 | Bind Mount Standardization | Use bind mounts exclusively for all Docker Compose volumes for observability and backup |
| ✅ Accepted | 2026-01-21 | TryFrom for DTO to Domain Conversion | Use standard TryFrom trait for self-documenting, discoverable DTO→Domain conversions |
| ✅ Accepted | 2026-01-21 | Validated Deserialization for Domain Types | Use custom Deserialize impl with Raw struct to enforce domain invariants during parsing |
| ✅ Accepted | 2026-01-20 | Grafana Default Port 3000 | Use Grafana's default port 3000 instead of 3100 for dedicated VM deployments |
| ✅ Accepted | 2026-01-20 | Caddy for TLS Termination | Use Caddy v2.10 as TLS proxy for automatic HTTPS with WebSocket support |
| ✅ Accepted | 2026-01-20 | Per-Service TLS Configuration | Use domain + use_tls_proxy fields instead of nested tls section for explicit TLS opt-in |
| ✅ Accepted | 2026-01-20 | Uniform HTTP Tracker TLS Requirement | All HTTP trackers must use same TLS setting due to tracker's global on_reverse_proxy |
| ✅ Accepted | 2026-01-10 | Hetzner SSH Key Dual Injection Pattern | Use both OpenTofu SSH key and cloud-init for debugging capability with manual hardening |
| ✅ Accepted | 2026-01-10 | Configuration and Data Directories as Secrets | Treat envs/, data/, build/ as secrets; no env var injection; users secure via permissions |
| ✅ Accepted | 2026-01-07 | Configuration DTO Layer Placement | Keep configuration DTOs in application layer, not domain; defer package extraction |
| ✅ Accepted | 2025-12-23 | Docker Security Scan Exit Code Zero | Use exit-code 0 for security scanning - Trivy detects, GitHub Security decides, CI green |
| ✅ Accepted | 2025-12-20 | Grafana Integration Pattern | Enable Grafana by default with hard Prometheus dependency and environment variable config |
| ✅ Accepted | 2025-12-17 | Secrecy Crate for Sensitive Data Handling | Use secrecy crate for type-safe secret handling with memory zeroing |
| ✅ Accepted | 2025-12-14 | Database Configuration Structure in Templates | Expose structured database fields in templates rather than pre-resolved connection strings |
| ✅ Accepted | 2025-12-13 | Environment Variable Injection in Docker Compose | Use .env file injection instead of hardcoded values for runtime configuration changes |
| ✅ Accepted | 2025-12-11 | Cloud-Init SSH Port Configuration with Reboot | Use cloud-init with reboot pattern to configure custom SSH ports during VM provisioning |
| ✅ Accepted | 2025-12-10 | Single Docker Image for Sequential E2E Command Testing | Use single Docker image with sequential command execution instead of multi-image phases |
| ✅ Accepted | 2025-12-09 | Register Command SSH Port Override | Add optional --ssh-port argument to register command for non-standard SSH ports |
| ✅ Accepted | 2025-11-19 | Disable MD060 Table Formatting Rule | Disable MD060 to allow flexible table formatting and emoji usage |
| ✅ Accepted | 2025-11-19 | Test Command as Smoke Test | Test command validates running services, not infrastructure components |
| ✅ Accepted | 2025-11-13 | Migration to AGENTS.md Standard | Adopt open AGENTS.md standard for multi-agent compatibility while keeping GitHub redirect |
| ✅ Accepted | 2025-11-11 | Use ReentrantMutex Pattern for UserOutput Reentrancy | Use Arc<ReentrantMutex<RefCell>> to fix same-thread deadlock in issue #164 |
| ❌ Superseded | 2025-11-11 | Remove UserOutput Mutex | Remove Arc<Mutex> pattern for simplified, deadlock-free architecture |
| ✅ Accepted | 2025-11-07 | ExecutionContext Wrapper Pattern | Use ExecutionContext wrapper around Container for future-proof command signatures |
| ✅ Accepted | 2025-11-03 | Environment Variable Prefix | Use TORRUST_TD_ prefix for all environment variables |
| ✅ Accepted | 2025-10-15 | External Tool Adapters Organization | Consolidate external tool wrappers in src/adapters/ for better discoverability |
| ✅ Accepted | 2025-10-10 | Repository Rename to Deployer | Rename from "Torrust Tracker Deploy" to "Torrust Tracker Deployer" for production use |
| ✅ Accepted | 2025-10-03 | Error Context Strategy | Use structured error context with trace files for complete error information |
| ✅ Accepted | 2025-10-03 | Command State Return Pattern | Commands return typed states (Environment |
| ✅ Accepted | 2025-10-03 | Actionable Error Messages | Use tiered help system with brief tips + .help() method for detailed troubleshooting |
| ✅ Accepted | 2025-10-01 | Type Erasure for Environment States | Use enum-based type erasure to enable runtime handling and serialization of typed states |
| ✅ Accepted | 2025-09-29 | Test Context vs Deployment Environment Naming | Rename TestEnvironment to TestContext to avoid conflicts with multi-environment feature |
| ✅ Accepted | 2025-09-10 | LXD VMs over Containers | Use LXD virtual machines instead of containers for production alignment |
| ✅ Accepted | 2025-09-09 | Tera Minimal Templating Strategy | Use Tera with minimal variables and templates to avoid complexity and delimiter conflicts |
| ✅ Accepted | 2025-07-08 | MySQL over MariaDB | Use MySQL 8.0 as default database backend over MariaDB for upstream compatibility |
| ✅ Accepted | - | LXD over Multipass | Choose LXD containers over Multipass VMs for deployment testing |
| ✅ Resolved | - | Docker Testing Evolution | Evolution from Docker rejection to hybrid approach for split E2E testing |
| ✅ Accepted | - | Meson Removal | Remove Meson build system from the project |
When creating new ADRs, use the structure defined in TEMPLATE.md.
- One decision per file: Each ADR should focus on a single architectural decision
- Immutable: Once accepted, ADRs should not be modified. Create new ADRs to supersede old ones
- Context-rich: Include enough background for future readers to understand why the decision was made
- Consequence-aware: Document both positive and negative consequences
- Linked: Reference related decisions and external resources
- Proposed: Decision is under discussion
- Accepted: Decision has been approved and is being implemented
- Rejected: Decision was considered but not approved
- Superseded: Decision has been replaced by a newer ADR