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

Commit 2a4ddf3

Browse files
committed
Merge #15: feat: [#14] Phase 1 - 12-Factor App configuration management system
77c3fa3 docs: [#14] add comprehensive integration testing guide execution instructions (Jose Celano) 613b5df docs: [#14] add application storage cleanup step to integration testing guide (Jose Celano) cc87760 fix: nginx template variable escaping and add documentation (Jose Celano) f09efaf refactor: [#14] move configuration files to infrastructure layer (Jose Celano) a8b11c5 refactor: move nginx.conf to infrastructure templates and improve configuration management (Jose Celano) 10592d0 feat: [#14] Complete integration test refactoring and verification (Jose Celano) a0456e8 refactor: [#14] align integration tests with 12-factor configuration approach (Jose Celano) 00e13bf docs: update integration testing guide with comprehensive smoke tests and fixes (Jose Celano) 9bbd7bf docs: [#14] update integration testing guide with network architecture and proper testing procedures (Jose Celano) 458546a fix: [#14] resolve tracker database driver configuration issue (Jose Celano) 0c9d081 docs: [#integration-tests] add OpenTofu state refresh step to prevent IP detection issues (Jose Celano) 59bdd15 docs: improve integration testing guide with directory indicators and new config workflow (Jose Celano) 83d62f0 docs: add security documentation for plain text secrets (Jose Celano) 770fe25 fix: correct environment variable names and database config (Jose Celano) 2d19b12 refactor: simplify environment variables to secrets-only approach (Jose Celano) 6b46ddd fix: [#14] resolve yamllint validation warnings in config scripts (Jose Celano) 94d278b feat: [#14] implement Phase 1 of 12-Factor App refactor - configuration management (Jose Celano) Pull request description: ## Phase 1: Configuration Management System This PR implements the first phase of the 12-Factor App refactoring for the Torrust Tracker Demo, focusing on configuration management and environment-based deployment. ### 🎯 **Objectives Completed** - ✅ **Environment-based configuration** using `.env` files and templates - ✅ **Configuration templates** with `envsubst` for dynamic generation - ✅ **Automated configuration scripts** with validation and colored output - ✅ **Docker Compose integration** with generated environment files - ✅ **Makefile automation** for configuration and deployment workflows - ✅ **MySQL database migration** from SQLite for production readiness ### 🏗️ **Architecture Changes** #### Configuration Structure ``` infrastructure/config/ ├── environments/ │ ├── local.env # Local development configuration │ └── production.env # Production deployment configuration └── templates/ ├── tracker.toml.tpl # Torrust Tracker configuration template ├── prometheus.yml.tpl # Prometheus monitoring template └── docker-compose.env.tpl # Docker Compose environment template ``` #### New Automation Scripts - **`configure-env.sh`** - Processes templates and generates configuration files - **`validate-config.sh`** - Validates generated configurations for syntax and completeness #### Enhanced Makefile Targets - `configure-local` / `configure-production` - Generate environment-specific configs - `validate-config` / `validate-config-production` - Validate configurations - `deploy-local` / `deploy-production` - Full deployment workflows ### 🔧 **Key Features** #### 1. **Template-Based Configuration** All configuration files are now generated from templates using environment variables: - No more hardcoded values in configuration files - Environment-specific settings (logging levels, database URLs, etc.) - Secrets management through environment variables #### 2. **Environment Separation** - **Local**: Debug logging, direct access, SQLite/MySQL support - **Production**: Info logging, reverse proxy mode, MySQL database, SSL ready #### 3. **Validation & Quality Assurance** - TOML and YAML syntax validation - Environment-specific configuration checks - Template variable substitution verification - Linting integration with project standards #### 4. **Docker Compose Integration** - Generated `.env` files for Docker Compose - Consistent variable naming across all services - Environment-specific service configurations ### 🚀 **Usage** #### Quick Start - Local Development ```bash make configure-local # Generate local configurations make validate-config # Validate configurations make deploy-local # Deploy with local settings ``` #### Production Deployment ```bash # Set required secrets as environment variables export TORRUST_PROD_DATABASE_URL="mysql://user:pass@host:3306/db" export TORRUST_PROD_API_TOKEN="your-api-token" # ... other production secrets make configure-production # Generate production configurations make validate-config-production # Validate configurations make deploy-production # Deploy to production ``` ### 🛡️ **Security Improvements** - **No hardcoded secrets** - All sensitive values use environment variables - **Environment isolation** - Clear separation between local and production configs - **Validation safeguards** - Prevent deployment with misconfigured settings ### 📋 **Breaking Changes** - Configuration files are now generated and should not be edited directly - `.env` files must be generated using the new scripts - Database configuration now defaults to MySQL for both environments ### 🧪 **Testing** All changes have been validated with: - ✅ **Linting** - yamllint, shellcheck, markdownlint - ✅ **Configuration validation** - Both local and production environments - ✅ **Template processing** - All templates generate correctly - ✅ **Docker Compose integration** - Services start with generated configs ### 📚 **Documentation** Updated documentation includes: - Phase 1 implementation guide with detailed migration steps - Configuration management workflow documentation - Makefile target reference and usage examples ### 🔄 **Next Steps (Future PRs)** - **Phase 2**: Infrastructure as Code enhancements - **Phase 3**: Service isolation and containerization improvements - **Phase 4**: Monitoring and observability integrations --- **Ready for Review**: This PR represents a complete Phase 1 implementation of the 12-Factor App methodology. All existing functionality is preserved while adding robust configuration management capabilities. ACKs for top commit: josecelano: ACK 77c3fa3 Tree-SHA512: 359047b1b8d34aa9586e26011c6ab33fd9d28a5a3f931ff9eef3d1d67c7ee2680f8feaf9231ea761a6d33987f0e6695fd3611130144ae5cf7b4a2618bbf5104d
2 parents b0327d6 + 77c3fa3 commit 2a4ddf3

24 files changed

+2684
-289
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
mode: agent
3+
---
4+
5+
# Integration Testing Guide Execution Instructions
6+
7+
As an expert system administrator, you will execute the **complete integration testing process** following the [Integration Testing Guide](../../docs/guides/integration-testing-guide.md).
8+
9+
## 📋 Overview
10+
11+
This guide performs a **full end-to-end integration test** that includes:
12+
13+
1. **Clean existing state** (VM, application data, certificates)
14+
2. **Deploy fresh infrastructure** (VM with Ubuntu 24.04)
15+
3. **Wait for cloud-init completion** (system provisioning)
16+
4. **Run comprehensive integration tests** (services, connectivity, functionality)
17+
5. **Perform smoke testing** (external validation with official client tools)
18+
6. **Clean up resources** (return to clean state)
19+
20+
**Expected Duration**: ~8-12 minutes total
21+
**Prerequisites**: Must have completed initial setup (`make test-prereq`)
22+
23+
## 🎯 Execution Requirements
24+
25+
### CRITICAL Rules to Follow:
26+
27+
1. **Sequential Execution**: Follow steps in exact order - do NOT skip or reorder
28+
2. **No Command Modifications**: Execute commands exactly as written in the guide
29+
3. **Working Directory**: Always run from project root directory
30+
4. **Error Handling**: Document any failures or deviations immediately
31+
5. **Complete Process**: Execute the entire guide from start to finish
32+
33+
### What Gets Cleaned (Destructive Operations):
34+
35+
- **Virtual Machine**: Complete VM destruction and recreation
36+
- **Application Storage**: Database, SSL certificates, configuration files
37+
- **OpenTofu State**: Infrastructure state reset
38+
- **libvirt Resources**: VM disks, cloud-init ISOs, network configurations
39+
40+
## 📝 Step-by-Step Instructions
41+
42+
### Phase 1: Preparation and Cleanup
43+
44+
- **Step 1.1-1.8**: Clean existing infrastructure and application state
45+
- **Critical**: Step 1.8 (Clean Application Storage) is destructive but recommended
46+
- **Outcome**: Clean slate for fresh deployment
47+
48+
### Phase 2: Infrastructure Deployment
49+
50+
- **Step 2.1-2.4**: Deploy VM with OpenTofu/Terraform
51+
- **Critical**: Wait for cloud-init completion (Step 3)
52+
- **Outcome**: Provisioned VM with Torrust Tracker ready
53+
54+
### Phase 3: Integration Testing
55+
56+
- **Step 4**: Run comprehensive integration tests
57+
- **Step 5**: Optional manual verification
58+
- **Step 6**: Optional performance testing
59+
- **Outcome**: Validated working system
60+
61+
### Phase 4: External Validation
62+
63+
- **Step 7**: External smoke testing with official client tools
64+
- **Reference**: Use [Smoke Testing Guide](../../docs/guides/smoke-testing-guide.md) for details
65+
- **Outcome**: Black-box validation of tracker functionality
66+
67+
### Phase 5: Cleanup
68+
69+
- **Step 8**: Clean up all resources
70+
- **Step 9**: Review insights and best practices
71+
- **Outcome**: Return to clean state
72+
73+
## 🚨 Important Notes
74+
75+
### SSH Key Configuration
76+
77+
- **Required**: Must configure SSH keys before deployment
78+
- **Location**: `infrastructure/terraform/local.tfvars`
79+
- **Template**: Available in `infrastructure/terraform/terraform.tfvars.example`
80+
81+
### Cloud-Init Wait Time
82+
83+
- **Critical**: DO NOT skip Step 3 (cloud-init completion)
84+
- **Duration**: 2-3 minutes typically
85+
- **Failure Mode**: SSH connection failures if rushed
86+
87+
### Error Documentation
88+
89+
- **Immediate**: Document any command failures or unexpected outputs
90+
- **Location**: Add issues directly to the integration testing guide
91+
- **Format**: Include error messages, context, and resolution steps
92+
93+
### Non-Standard Commands
94+
95+
- **Approval Required**: Only execute commands not in the guide if absolutely necessary
96+
- **Documentation**: Clearly indicate when deviating from guide
97+
- **Justification**: Explain why the deviation was needed
98+
99+
## 🔧 Troubleshooting Guidance
100+
101+
### Common Issues and Solutions:
102+
103+
1. **"Command not found"**: Verify you're in project root directory
104+
2. **SSH connection failures**: Ensure cloud-init has completed
105+
3. **libvirt permission errors**: Check user is in libvirt group
106+
4. **VM deployment timeouts**: Normal during cloud-init, wait longer
107+
5. **Storage volume conflicts**: Run manual cleanup steps from guide
108+
109+
### When to Deviate from Guide:
110+
111+
- **System-specific issues**: Different Linux distributions may need adjustments
112+
- **Network configuration**: Firewall or DNS issues requiring resolution
113+
- **Permission problems**: User/group configuration fixes
114+
- **Always document**: Any deviations with full explanation
115+
116+
## 📊 Success Criteria
117+
118+
### Integration Test Success Indicators:
119+
120+
- ✅ All services start successfully (Docker Compose)
121+
- ✅ Tracker responds to UDP/HTTP requests
122+
- ✅ API endpoints return expected data
123+
- ✅ Grafana dashboards display metrics
124+
- ✅ MySQL database is accessible and functional
125+
126+
### Smoke Test Success Indicators:
127+
128+
- ✅ UDP tracker clients receive responses
129+
- ✅ HTTP tracker clients receive responses
130+
- ✅ API health checks return "Ok"
131+
- ✅ Statistics endpoints return valid data
132+
- ✅ Metrics endpoints return Prometheus data
133+
134+
## 🎯 Final Deliverables
135+
136+
Upon completion, you should have:
137+
138+
1. **Executed Complete Guide**: All steps from 1.1 through 9
139+
2. **Documented Issues**: Any problems encountered and how they were resolved
140+
3. **Validated Functionality**: Both integration and smoke tests passed
141+
4. **Clean State**: All resources cleaned up and ready for next test
142+
5. **Updated Documentation**: Any guide improvements or corrections needed
143+
144+
## 📖 Additional Resources
145+
146+
- **Integration Testing Guide**: [docs/guides/integration-testing-guide.md](../../docs/guides/integration-testing-guide.md)
147+
- **Smoke Testing Guide**: [docs/guides/smoke-testing-guide.md](../../docs/guides/smoke-testing-guide.md)
148+
- **Quick Start Guide**: [docs/infrastructure/quick-start.md](../../docs/infrastructure/quick-start.md)
149+
- **Troubleshooting**: See infrastructure documentation for libvirt and OpenTofu issues
150+
151+
---
152+
153+
**Remember**: This is a comprehensive test that validates the entire deployment pipeline. Take your time, follow each step carefully, and document everything for future improvements.

.yamllint-ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
extends: default
22

3+
ignore: |
4+
application/storage/
5+
36
rules:
47
line-length:
58
max: 120 # More reasonable for infrastructure code

Makefile

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Makefile for Torrust Tracker Local Testing Infrastructure
2-
.PHONY: help init plan apply destroy test clean status refresh-state ssh install-deps console vm-console lint lint-yaml lint-shell lint-markdown
2+
.PHONY: help init plan apply destroy test clean status refresh-state ssh install-deps console vm-console lint lint-yaml lint-shell lint-markdown configure-local configure-production validate-config validate-config-production deploy-local deploy-production start-services stop-services
33

44
# Default variables
55
VM_NAME ?= torrust-tracker-demo
@@ -189,7 +189,23 @@ clean-and-fix: ## Clean up all VMs and fix libvirt permissions
189189
@cd $(TERRAFORM_DIR) && rm -f terraform.tfstate terraform.tfstate.backup .terraform.lock.hcl 2>/dev/null || true
190190
@echo "3. Cleaning libvirt images:"
191191
@sudo rm -f /var/lib/libvirt/images/torrust-tracker-demo* /var/lib/libvirt/images/ubuntu-24.04-base.qcow2 2>/dev/null || true
192-
@echo "4. Fixing libvirt setup:"
192+
@echo "4. Cleaning application storage (generated configuration files):"
193+
@if [ -d "application/storage" ]; then \
194+
echo " WARNING: This will delete all generated configuration files in application/storage/"; \
195+
echo " This includes nginx configs, tracker configs, and any cached data."; \
196+
echo " These files will be regenerated when you run 'make configure-local'."; \
197+
read -p " Do you want to delete application/storage? (y/N): " confirm; \
198+
if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \
199+
echo " Removing application/storage..."; \
200+
rm -rf application/storage; \
201+
echo " ✓ Application storage cleaned"; \
202+
else \
203+
echo " Skipping application/storage cleanup"; \
204+
fi; \
205+
else \
206+
echo " No application/storage directory found"; \
207+
fi
208+
@echo "5. Fixing libvirt setup:"
193209
@$(MAKE) fix-libvirt
194210
@echo "✓ Clean up complete. You can now run 'make apply' safely."
195211

@@ -342,3 +358,61 @@ vm-console: ## Access VM graphical console (GUI)
342358
echo "virt-viewer not found. Please install it:"; \
343359
echo " sudo apt install virt-viewer"; \
344360
fi
361+
362+
# Configuration Management Targets
363+
configure-local: ## Generate local environment configuration
364+
@echo "Generating local environment configuration..."
365+
@infrastructure/scripts/configure-env.sh local
366+
367+
configure-production: ## Generate production environment configuration (requires secrets)
368+
@echo "Generating production environment configuration..."
369+
@infrastructure/scripts/configure-env.sh production
370+
371+
validate-config: ## Validate generated configuration files
372+
@echo "Validating configuration files..."
373+
@infrastructure/scripts/validate-config.sh local
374+
375+
validate-config-production: ## Validate production configuration files
376+
@echo "Validating production configuration files..."
377+
@infrastructure/scripts/validate-config.sh production
378+
379+
# Deployment workflow targets
380+
deploy-local: configure-local ## Deploy VM and configure for local environment
381+
@echo "Deploying local environment..."
382+
@$(MAKE) apply
383+
@echo "Waiting for VM to be ready..."
384+
@sleep 30
385+
@echo "Starting application services..."
386+
@$(MAKE) start-services
387+
388+
deploy-production: configure-production ## Deploy and configure for production environment (requires secrets)
389+
@echo "Deploying production environment..."
390+
@$(MAKE) apply
391+
@echo "Waiting for VM to be ready..."
392+
@sleep 30
393+
@echo "Starting application services..."
394+
@$(MAKE) start-services
395+
396+
start-services: ## Start Docker Compose services in the VM
397+
@echo "Starting Docker Compose services..."
398+
@VM_IP=$$(cd $(TERRAFORM_DIR) && tofu output -raw vm_ip 2>/dev/null) || \
399+
VM_IP=$$(virsh domifaddr $(VM_NAME) | grep ipv4 | awk '{print $$4}' | cut -d'/' -f1); \
400+
if [ -n "$$VM_IP" ]; then \
401+
echo "Starting services on $$VM_IP..."; \
402+
ssh -o StrictHostKeyChecking=no torrust@$$VM_IP 'cd /home/torrust/github/torrust/torrust-tracker-demo/application && docker compose up -d'; \
403+
else \
404+
echo "Could not get VM IP. Is the VM deployed?"; \
405+
exit 1; \
406+
fi
407+
408+
stop-services: ## Stop Docker Compose services in the VM
409+
@echo "Stopping Docker Compose services..."
410+
@VM_IP=$$(cd $(TERRAFORM_DIR) && tofu output -raw vm_ip 2>/dev/null) || \
411+
VM_IP=$$(virsh domifaddr $(VM_NAME) | grep ipv4 | awk '{print $$4}' | cut -d'/' -f1); \
412+
if [ -n "$$VM_IP" ]; then \
413+
echo "Stopping services on $$VM_IP..."; \
414+
ssh -o StrictHostKeyChecking=no torrust@$$VM_IP 'cd /home/torrust/github/torrust/torrust-tracker-demo/application && docker compose down'; \
415+
else \
416+
echo "Could not get VM IP. Is the VM deployed?"; \
417+
exit 1; \
418+
fi

application/.env.production

Lines changed: 0 additions & 24 deletions
This file was deleted.

application/compose.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,12 @@ services:
108108
tty: true
109109
restart: unless-stopped
110110
environment:
111-
- USER_ID=${USER_ID}
112-
- TORRUST_TRACKER_DATABASE=${TORRUST_TRACKER_DATABASE:-mysql}
113-
- TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER=${TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER:-mysql}
114-
- TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__PATH=${TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__PATH:-mysql://torrust:password@mysql:3306/torrust_tracker}
115-
- TORRUST_TRACKER_CONFIG_OVERRIDE_HTTP_API__ACCESS_TOKENS__ADMIN=${TORRUST_TRACKER_CONFIG_OVERRIDE_HTTP_API__ACCESS_TOKENS__ADMIN:-MyAccessToken}
111+
- USER_ID=${USER_ID:-1000}
112+
# Database connection for tracker (using Figment override pattern)
113+
- TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER=mysql
114+
- TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__PATH=mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mysql:3306/${MYSQL_DATABASE}
115+
# Admin API token for tracker (using Figment override pattern)
116+
- TORRUST_TRACKER_CONFIG_OVERRIDE_HTTP_API__ACCESS_TOKENS__ADMIN=${TRACKER_ADMIN_TOKEN}
116117
networks:
117118
- backend_network
118119
ports:

application/share/bin/install.sh

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,42 @@
11
#!/bin/bash
22

3+
# Torrust Tracker Demo Installation Script
4+
# This script creates the required directory structure for the application.
5+
# Following 12-factor principles, it expects .env to be provided by the infrastructure layer.
6+
37
if ! [ -f "./.env" ]; then
4-
echo "Creating compose .env './.env'"
5-
cp .env.production .env
8+
echo "ERROR: Environment file './.env' not found!"
9+
echo "The .env file must be provided by the infrastructure configuration system."
10+
echo "Expected location: $(pwd)/.env"
11+
echo ""
12+
echo "To generate the .env file, run:"
13+
echo " make configure-local # For local development"
14+
echo " make configure-production # For production deployment"
15+
exit 1
616
fi
717

18+
echo "Found environment file: ./.env"
19+
820
## Proxy
921

1022
mkdir -p ./storage/proxy/etc/nginx-conf
1123
mkdir -p ./storage/proxy/webroot
1224
mkdir -p ./storage/dhparam
1325

26+
# Verify nginx configuration exists (should be provided by infrastructure)
1427
if ! [ -f "./storage/proxy/etc/nginx-conf/nginx.conf" ]; then
15-
echo "Creating proxy config file: './storage/proxy/etc/nginx-conf/nginx.conf'"
16-
cp ./share/container/default/config/nginx.conf ./storage/proxy/etc/nginx-conf/nginx.conf
28+
echo "ERROR: Nginx configuration file './storage/proxy/etc/nginx-conf/nginx.conf' not found!"
29+
echo "This file should be generated by the infrastructure configuration system."
30+
echo "Expected location: $(pwd)/storage/proxy/etc/nginx-conf/nginx.conf"
31+
echo ""
32+
echo "To generate the configuration file, run:"
33+
echo " make configure-local # For local development"
34+
echo " make configure-production # For production deployment"
35+
exit 1
1736
fi
1837

38+
echo "Found nginx configuration: ./storage/proxy/etc/nginx-conf/nginx.conf"
39+
1940
## Certbot
2041

2142
mkdir -p ./storage/certbot/etc
@@ -33,16 +54,37 @@ fi
3354

3455
mkdir -p ./storage/tracker/etc
3556

36-
if ! [ -f "./storage/tracker/etc/tracker.prod.container.sqlite3.toml" ]; then
37-
echo "Creating tracker configuration: './storage/tracker/etc/tracker.toml'"
38-
cp ./share/container/default/config/tracker.prod.container.sqlite3.toml ./storage/tracker/etc/tracker.toml
57+
# Verify tracker configuration exists (should be provided by infrastructure)
58+
if ! [ -f "./storage/tracker/etc/tracker.toml" ]; then
59+
echo "ERROR: Tracker configuration file './storage/tracker/etc/tracker.toml' not found!"
60+
echo "This file should be generated by the infrastructure configuration system."
61+
echo "Expected location: $(pwd)/storage/tracker/etc/tracker.toml"
62+
echo ""
63+
echo "To generate the configuration file, run:"
64+
echo " make configure-local # For local development"
65+
echo " make configure-production # For production deployment"
66+
exit 1
3967
fi
4068

69+
echo "Found tracker configuration: ./storage/tracker/etc/tracker.toml"
70+
4171
## Prometheus
4272

4373
mkdir -p ./storage/prometheus/etc
4474

75+
# Verify prometheus configuration exists (should be provided by infrastructure)
4576
if ! [ -f "./storage/prometheus/etc/prometheus.yml" ]; then
46-
echo "Creating prometheus config file: './storage/prometheus/etc/prometheus.yml'"
47-
cp ./share/container/default/config/prometheus.yml ./storage/prometheus/etc/prometheus.yml
77+
echo "ERROR: Prometheus configuration file './storage/prometheus/etc/prometheus.yml' not found!"
78+
echo "This file should be generated by the infrastructure configuration system."
79+
echo "Expected location: $(pwd)/storage/prometheus/etc/prometheus.yml"
80+
echo ""
81+
echo "To generate the configuration file, run:"
82+
echo " make configure-local # For local development"
83+
echo " make configure-production # For production deployment"
84+
exit 1
4885
fi
86+
87+
echo "Found prometheus configuration: ./storage/prometheus/etc/prometheus.yml"
88+
89+
echo "Installation completed successfully!"
90+
echo "All required directories created and configuration files verified."

0 commit comments

Comments
 (0)