Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit b84c1e8

Browse files
committed
Merge #27: [#26] Document 12-factor deployment process and two-level environment variable structure
7ede6e4 docs: [#26] fix Docker Compose environment configuration example and improve formatting (Jose Celano) 207c404 docs: [#26] create ADR-007 for two-level environment variable structure (Jose Celano) 3471409 docs: [#26] add 12-factor deployment process overview (Jose Celano) Pull request description: ## Summary This PR addresses issue #26 by documenting our 12-factor deployment process and formalizing the two-level environment variable structure used throughout the project. ## Changes Made ### 📚 12-Factor Deployment Process Documentation - **Enhanced README.md** with comprehensive 4-step deployment process overview - **Updated cloud deployment guide** with detailed workflow explanation aligned with twelve-factor methodology - **Improved copilot instructions** with ADR reference table and environment variable structure details ### 🔐 Two-Level Environment Variable Structure (ADR-007) - **Created ADR-007** documenting the security-focused environment variable separation - **Level 1**: Main environment files (`infrastructure/config/environments/`) containing ALL deployment configuration - **Level 2**: Docker environment files (generated from templates) with filtered container-only variables - **Security benefits**: Reduced attack surface, principle of least privilege for containers ## Key Documentation Updates 1. **README.md**: Added clear 4-step deployment process (Configure → Provision → Deploy → Validate) 2. **Cloud Deployment Guide**: Enhanced with detailed Build/Release/Run stage explanations 3. **Copilot Instructions**: Added ADR reference table and environment variable structure guidance 4. **New ADR-007**: Complete documentation of two-level environment variable approach ## Benefits - **🔒 Security**: Infrastructure secrets isolated from application containers - **📖 Clarity**: Clear separation between infrastructure and application configuration - **🛠️ Maintainability**: Contributors understand where to modify different types of variables - **✅ Compliance**: Aligns with twelve-factor app configuration principles ## Two-Level Environment Structure **Level 1 (Infrastructure)**: - Location: `infrastructure/config/environments/local.env`, `production.env` - Contains: SSL domains, backup settings, VM specifications, all secrets - Usage: Sourced by deployment scripts for complete deployment process **Level 2 (Containers)**: - Template: `infrastructure/config/templates/docker-compose.env.tpl` - Generated: `application/.env` → `/var/lib/torrust/compose/.env` on VM - Contains: Database connections, API tokens, runtime configuration only - Usage: `docker compose --env-file /var/lib/torrust/compose/.env up -d` ## Testing - ✅ All markdown linting passes - ✅ Infrastructure unit tests pass - ✅ Documentation structure validated - ✅ Correct Docker Compose `--env-file` usage documented ## Related Issues Closes #26 ## Checklist - [x] Add 12-factor deployment overview to main documentation - [x] Create ADR for two-level environment variable structure - [x] Update copilot instructions with ADR reference table - [x] Enhance documentation to clarify infrastructure vs container variables - [x] Fix Docker Compose environment configuration example - [x] All linting and tests pass ACKs for top commit: josecelano: ACK 7ede6e4 Tree-SHA512: ba039b5eda7b42e5db0b0398e47939291e535c039d85e9977ec113d256562d7a56e9d5ab68064a7d86547ccdce79935ffee5804b924861816709591c0c274176
2 parents 49aa4f8 + 7ede6e4 commit b84c1e8

File tree

4 files changed

+342
-2
lines changed

4 files changed

+342
-2
lines changed

.github/copilot-instructions.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,20 @@ torrust-tracker-demo/
182182
- **Cross-cutting**: Project-wide documentation and ADRs
183183
- **Architecture Decisions**: Documented design choices and rationale
184184

185+
#### Architecture Decision Records (ADRs)
186+
187+
Key design decisions are documented in `docs/adr/`. Contributors should review relevant ADRs when working on related features:
188+
189+
| ADR | Title | Description |
190+
| ----------------------------------------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------- |
191+
| [ADR-001](../docs/adr/001-makefile-location.md) | Makefile Location | Why the main Makefile is at repository root |
192+
| [ADR-002](../docs/adr/002-docker-for-all-services.md) | Docker for All Services | Why we use Docker for all services including UDP tracker |
193+
| [ADR-003](../docs/adr/003-use-mysql-over-mariadb.md) | Use MySQL Over MariaDB | Database backend selection rationale |
194+
| [ADR-004](../docs/adr/004-configuration-approach-files-vs-environment-variables.md) | Configuration Approach | Files vs environment variables for configuration |
195+
| [ADR-005](../docs/adr/005-sudo-cache-management-for-infrastructure-operations.md) | Sudo Cache Management | Managing sudo credentials during infrastructure operations |
196+
| [ADR-006](../docs/adr/006-ssl-certificate-generation-strategy.md) | SSL Certificate Generation Strategy | Approach for SSL certificate management |
197+
| [ADR-007](../docs/adr/007-two-level-environment-variable-structure.md) | Two-Level Environment Variable Structure | Security-focused separation of infrastructure and container variables |
198+
185199
## 🛠️ Development Workflow
186200

187201
### Quick Start for Contributors
@@ -284,9 +298,11 @@ The twelve-factor **Build, Release, Run** stages apply to the application deploy
284298

285299
- **Release Stage**: Combine built application with environment-specific configuration
286300

287-
- Apply environment variables and configuration files
301+
- Apply environment variables and configuration files using **two-level structure** (see [ADR-007](../docs/adr/007-two-level-environment-variable-structure.md))
302+
- **Level 1**: Main environment files (`infrastructure/config/environments/`) for all deployment processes
303+
- **Level 2**: Docker environment files (generated from templates) for container runtime only
288304
- Combine application artifacts with runtime configuration
289-
- Prepare deployment-ready releases
305+
- Prepare deployment-ready releases with security-focused variable filtering
290306

291307
- **Run Stage**: Execute the application in the runtime environment
292308
- Start application processes (tracker binary, background jobs)

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,51 @@ clear separation between infrastructure provisioning and application deployment:
9090
- **Environment-based Configuration**: Template system with `local.env.tpl` and `production.env.tpl`
9191
- **Build/Release/Run Stages**: Proper separation of configuration processing, deployment, and execution
9292

93+
## 🚀 Deployment Process Overview
94+
95+
This project follows a **four-step deployment process** based on twelve-factor app principles:
96+
97+
### 1. **Configure Environment Variables**
98+
99+
Customize deployment settings using environment-specific templates:
100+
101+
- `infrastructure/config/environments/local.env.tpl``local.env`
102+
- `infrastructure/config/environments/production.env.tpl``production.env`
103+
- Contains ALL deployment configuration (infrastructure, SSL, backups, application secrets)
104+
105+
### 2. **Provision Infrastructure**
106+
107+
Create and configure the target environment:
108+
109+
- **VM Creation**: Deploy virtual machine with specified resources
110+
- **System Setup**: cloud-init installs dependencies, configures firewall, sets up users
111+
- **Platform Preparation**: Ready environment for application deployment
112+
113+
### 3. **Deploy Application** (Build + Release + Run Stages)
114+
115+
Deploy the application stack following twelve-factor principles:
116+
117+
- **Build**: Prepare application artifacts and configuration files
118+
- **Release**: Generate SSL certificates, create Docker environment files, copy configs
119+
- **Run**: Start Docker Compose stack (tracker, MySQL, Nginx, Grafana, Prometheus)
120+
121+
### 4. **Validation**
122+
123+
Verify deployment health and functionality:
124+
125+
- Service health checks (HTTP/UDP endpoints)
126+
- Database connectivity validation
127+
- Monitoring dashboard accessibility
128+
- End-to-end smoke testing
129+
130+
### Quick Commands
131+
132+
```bash
133+
make infra-apply ENVIRONMENT=local # Steps 1-2: Configure + Provision
134+
make app-deploy ENVIRONMENT=local # Step 3: Deploy Application
135+
make app-health-check ENVIRONMENT=local # Step 4: Validation
136+
```
137+
93138
## Demo Tracker
94139

95140
- **HTTP Tracker**: <https://tracker.torrust-demo.com/announce>
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
# ADR-007: Two-Level Environment Variable Structure
2+
3+
## Status
4+
5+
Accepted
6+
7+
## Context
8+
9+
As part of implementing twelve-factor app methodology, we need a clear approach for
10+
managing environment variables throughout the deployment process. The system has
11+
evolved to use a two-level environment variable structure that serves different
12+
purposes and security requirements.
13+
14+
Currently, the project uses environment variables at two distinct levels:
15+
16+
1. **Main Environment Variables**: Used for the entire deployment process
17+
2. **Docker Compose Environment Variables**: Used only for running containers
18+
19+
This separation has emerged organically but lacks clear documentation, leading to
20+
potential confusion about where variables should be defined and how they flow
21+
through the system.
22+
23+
## Decision
24+
25+
We will formalize and document a **two-level environment variable structure**
26+
with clear separation of concerns:
27+
28+
### Level 1: Main Environment Variables
29+
30+
**Purpose**: Complete deployment configuration
31+
**Location**: `infrastructure/config/environments/`
32+
**Examples**: `local.env`, `production.env`
33+
**Scope**: All deployment processes
34+
35+
**Contents**:
36+
37+
- Infrastructure configuration (VM specs, network settings)
38+
- SSL certificate configuration (domains, Let's Encrypt email)
39+
- Database credentials and connection parameters
40+
- Application API tokens and secrets
41+
- Backup and monitoring configuration
42+
- Build and deployment automation settings
43+
44+
**Usage**:
45+
46+
- Sourced by deployment scripts (`provision-infrastructure.sh`, `deploy-app.sh`)
47+
- Used for template rendering (cloud-init, configuration files)
48+
- Contains variables for infrastructure operations (SSL generation, backups)
49+
- Includes variables that containers never need to see
50+
51+
### Level 2: Docker Compose Environment Variables
52+
53+
**Purpose**: Container runtime configuration
54+
**Template**: `infrastructure/config/templates/docker-compose.env.tpl`
55+
**Generated File**: `.env` (in application directory)
56+
**Scope**: Docker Compose and running containers only
57+
58+
**Contents** (filtered subset from Level 1):
59+
60+
- Database connection strings for application containers
61+
- Application API tokens needed by running services
62+
- Docker runtime configuration (USER_ID)
63+
- Service-specific configuration (Grafana admin credentials)
64+
- Container environment overrides
65+
66+
**Filtering Criteria**:
67+
68+
- **Include**: Variables directly used by containerized applications
69+
- **Exclude**: Infrastructure-only variables (SSL domains, backup settings)
70+
- **Exclude**: Build-time variables not needed at runtime
71+
- **Security**: Minimize attack surface by only exposing necessary variables
72+
73+
## Template Transformation Process
74+
75+
```text
76+
Level 1: Main Environment Variables
77+
├── infrastructure/config/environments/local.env.tpl
78+
├── infrastructure/config/environments/production.env.tpl
79+
└── (user creates) local.env or production.env
80+
81+
▼ (template processing)
82+
Level 2: Docker Environment Variables
83+
├── infrastructure/config/templates/docker-compose.env.tpl
84+
└── (generated) application/.env
85+
```
86+
87+
**Processing Flow**:
88+
89+
1. User creates environment file from template (e.g., `local.env`)
90+
2. Deployment script sources the main environment file
91+
3. Template processor generates `docker-compose.env` from template
92+
4. Docker Compose uses the generated `.env` file for container variables
93+
94+
## Rationale
95+
96+
### Security Benefits
97+
98+
- **Principle of Least Privilege**: Containers only receive variables they need
99+
- **Reduced Attack Surface**: Infrastructure secrets not exposed to application containers
100+
- **Separation of Concerns**: Infrastructure and application secrets handled differently
101+
102+
### Operational Benefits
103+
104+
- **Clear Responsibility**: Infrastructure variables vs. application variables
105+
- **Easier Debugging**: Know where to look for specific types of configuration
106+
- **Template Flexibility**: Can generate different container environments from same base config
107+
- **Deployment Isolation**: Infrastructure operations don't leak sensitive data to containers
108+
109+
### Examples
110+
111+
**Level 1 Only (Infrastructure Variables)**:
112+
113+
```bash
114+
# SSL configuration (not needed in containers)
115+
SSL_DOMAIN="tracker.example.com"
116+
SSL_EMAIL="[email protected]"
117+
ENABLE_SSL_AUTOMATION="true"
118+
119+
# Backup configuration (not needed in containers)
120+
ENABLE_DB_BACKUPS="true"
121+
BACKUP_RETENTION_DAYS="30"
122+
123+
# Infrastructure specifications (not needed in containers)
124+
VM_MEMORY="4096"
125+
VM_VCPUS="4"
126+
```
127+
128+
**Level 2 (Container Variables - Filtered from Level 1)**:
129+
130+
```bash
131+
# Database connection (needed by tracker container)
132+
MYSQL_ROOT_PASSWORD="secure_root_password"
133+
MYSQL_PASSWORD="secure_user_password"
134+
TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__PATH="mysql://torrust:${MYSQL_PASSWORD}@mysql:3306/torrust_tracker"
135+
136+
# API tokens (needed by application)
137+
TRACKER_ADMIN_TOKEN="secure_api_token"
138+
139+
# Runtime configuration (needed by containers)
140+
USER_ID="1000"
141+
```
142+
143+
## Implementation Guidelines
144+
145+
### For Infrastructure Scripts
146+
147+
```bash
148+
# Source the main environment file
149+
source "infrastructure/config/environments/${ENVIRONMENT}.env"
150+
151+
# Use all variables for infrastructure operations
152+
generate_ssl_certificates "$SSL_DOMAIN" "$SSL_EMAIL"
153+
configure_backups "$ENABLE_DB_BACKUPS" "$BACKUP_RETENTION_DAYS"
154+
```
155+
156+
### For Template Processing
157+
158+
```bash
159+
# Generate Docker environment file from template
160+
envsubst < "infrastructure/config/templates/docker-compose.env.tpl" > "application/.env"
161+
```
162+
163+
### For Container Configuration
164+
165+
```bash
166+
# Docker Compose command (in deploy-app.sh)
167+
docker compose --env-file /var/lib/torrust/compose/.env up -d
168+
169+
# The .env file contains only container-relevant variables
170+
# and is passed to Docker Compose via the --env-file flag
171+
```
172+
173+
## Benefits
174+
175+
1. **Security**: Reduced container attack surface
176+
2. **Clarity**: Clear separation between infrastructure and application concerns
177+
3. **Maintainability**: Easier to understand what variables are used where
178+
4. **Flexibility**: Can generate different container environments from same base
179+
5. **Compliance**: Aligns with twelve-factor configuration principles
180+
6. **Debugging**: Easier to troubleshoot configuration issues
181+
182+
## Trade-offs
183+
184+
### Accepted Complexity
185+
186+
- **Two Files to Maintain**: Requires keeping template and source in sync
187+
- **Template Processing**: Additional step in deployment process
188+
- **Learning Curve**: Contributors must understand the two-level structure
189+
190+
### Mitigated Risks
191+
192+
- **Template Drift**: Validation scripts check template consistency
193+
- **Missing Variables**: Docker Compose will fail fast if required variables are missing
194+
- **Documentation**: This ADR and inline comments clarify the structure
195+
196+
## Consequences
197+
198+
### For Contributors
199+
200+
- Must understand which level to modify for different types of changes
201+
- Infrastructure changes: Edit main environment templates
202+
- Container configuration: Edit Docker environment template
203+
- New variables: Consider which level(s) need the variable
204+
205+
### For Deployment
206+
207+
- All deployment scripts use Level 1 (main environment)
208+
- Docker Compose only sees Level 2 (filtered environment)
209+
- Template processing is automatic during deployment
210+
- No manual synchronization required
211+
212+
### For Security
213+
214+
- Infrastructure secrets isolated from application containers
215+
- Container compromise doesn't expose infrastructure configuration
216+
- Easier security auditing of container-exposed variables
217+
218+
## Alternative Considered
219+
220+
**Single-Level Environment Variables**: Using one environment file for everything.
221+
222+
**Rejected because**:
223+
224+
- Security: All variables exposed to containers
225+
- Complexity: Difficult to determine which variables containers actually need
226+
- Maintenance: Changes to infrastructure configuration could affect containers unnecessarily
227+
228+
## References
229+
230+
- [Twelve-Factor App: Config](https://12factor.net/config)
231+
- [ADR-004: Configuration Approach](./004-configuration-approach-files-vs-environment-variables.md)
232+
- [Docker Compose Environment Variables](https://docs.docker.com/compose/environment-variables/)

docs/guides/cloud-deployment-guide.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,53 @@ and testing. Hetzner Cloud support is planned as the next implementation target.
1212
The process combines Infrastructure as Code with application deployment automation to
1313
provide a streamlined deployment experience, following twelve-factor app methodology.
1414

15+
## Deployment Process
16+
17+
This project implements a **four-step deployment workflow** aligned with twelve-factor app principles:
18+
19+
### Step 1: Configure Environment Variables
20+
21+
Create environment-specific configuration from templates:
22+
23+
- **Local Development**: `infrastructure/config/environments/local.env.tpl``local.env`
24+
- **Production**: `infrastructure/config/environments/production.env.tpl``production.env`
25+
26+
The environment file contains **all deployment configuration**, including:
27+
28+
- Infrastructure settings (VM specs, network configuration)
29+
- Application secrets (database passwords, API tokens)
30+
- SSL certificate configuration (domains, email for Let's Encrypt)
31+
- Backup and monitoring settings
32+
33+
### Step 2: Provision Infrastructure
34+
35+
Deploy and configure the target environment:
36+
37+
- **VM Creation**: Deploy virtual machine with specified resources
38+
- **System Dependencies**: cloud-init installs Docker, configures firewall, creates users
39+
- **Network Setup**: Configure firewall rules, SSH access, system security
40+
- **Platform Readiness**: Environment prepared for application deployment
41+
42+
### Step 3: Deploy Application (Build + Release + Run)
43+
44+
Deploy the application stack following twelve-factor methodology:
45+
46+
- **Build Stage**: Prepare application artifacts and configuration templates
47+
- **Release Stage**:
48+
- Generate SSL certificates (Let's Encrypt or self-signed)
49+
- Create Docker environment files from templates
50+
- Copy application configurations to target VM
51+
- **Run Stage**: Start Docker Compose stack (Torrust Tracker, MySQL, Nginx, Grafana, Prometheus)
52+
53+
### Step 4: Validation
54+
55+
Verify deployment health and functionality:
56+
57+
- **Service Health**: HTTP/UDP endpoint availability checks
58+
- **Database Connectivity**: MySQL connection and schema validation
59+
- **Monitoring Access**: Grafana dashboard accessibility
60+
- **End-to-end Testing**: Tracker announce/scrape functionality
61+
1562
## Prerequisites
1663

1764
### Local Requirements

0 commit comments

Comments
 (0)