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

Commit cc0c4d6

Browse files
committed
docs: [#28] document configuration architecture and override system
- Add comprehensive configuration-architecture.md documentation - Explain two-layer hierarchy: environment configs override provider defaults - Document loading order: environment first, then provider - Clarify why variables appear in both environment and provider configs - Add practical examples of override scenarios - Update provider README.md with hierarchy explanation - Add inline comments to hetzner.env explaining loading order - Resolves confusion about apparent variable duplication
1 parent d8c894d commit cc0c4d6

File tree

3 files changed

+364
-4
lines changed

3 files changed

+364
-4
lines changed

infrastructure/config/providers/README.md

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,60 @@ infrastructure/config/templates/providers/
3333

3434
## Usage Instructions
3535

36+
### Configuration Hierarchy and Override System
37+
38+
The project uses a **hierarchical configuration system** where environment configurations
39+
can override provider defaults:
40+
41+
#### Loading Order
42+
43+
1. **Environment config** loaded first: `infrastructure/config/environments/{environment}-{provider}.env`
44+
2. **Provider config** loaded second: `infrastructure/config/providers/{provider}.env`
45+
3. **Result**: Provider config can override environment values, but environments can override
46+
provider defaults
47+
48+
#### Override Strategy
49+
50+
- **Provider configs**: Set sensible defaults that work for most environments
51+
- **Environment configs**: Override only when necessary (performance, geography, cost)
52+
- **Commented variables**: Environment files contain commented provider variables for easy overriding
53+
54+
#### Example Scenario
55+
56+
```bash
57+
# Provider config (hetzner.env) - defaults for ALL environments
58+
HETZNER_SERVER_TYPE=cpx31 # Default: 4 vCPU, 8GB RAM
59+
HETZNER_LOCATION=fsn1 # Default: Falkenstein datacenter
60+
61+
# Environment config (production-hetzner.env) - environment-specific overrides
62+
# HETZNER_SERVER_TYPE=cx41 # Uncomment: Use higher performance for production
63+
# HETZNER_LOCATION=nbg1 # Uncomment: Use Nuremberg for production
64+
```
65+
66+
### Setup Instructions
67+
3668
1. **Copy the appropriate template:**
3769

3870
```bash
3971
# For local testing
4072
cp infrastructure/config/templates/providers/libvirt.env.tpl infrastructure/config/providers/libvirt.env
41-
73+
4274
# For Hetzner Cloud
4375
cp infrastructure/config/templates/providers/hetzner.env.tpl infrastructure/config/providers/hetzner.env
4476
```
4577

4678
2. **Edit the copied file** with your actual values:
79+
4780
- Replace placeholder tokens with real API keys
4881
- Configure VM sizes and locations
4982
- Set appropriate defaults for your use case
5083

51-
3. **Never commit these files** - they contain secrets and are automatically git-ignored
84+
3. **Override in environment configs when needed**:
85+
86+
- Uncomment variables in environment files only when you need environment-specific settings
87+
- Document why you're overriding the provider default
88+
89+
4. **Never commit these files** - they contain secrets and are automatically git-ignored
5290

5391
## Security Notes
5492

infrastructure/config/providers/hetzner.env

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1-
# Hetzner Cloud Provider Configuration Template
2-
# Copy this file to hetzner.env and replace placeholder values
1+
# Hetzner Cloud Provider Configuration
2+
#
3+
# CONFIGURATION HIERARCHY: This file provides provider-wide defaults that apply
4+
# to all environments using the Hetzner provider. These values can be overridden
5+
# by environment-specific configurations when needed.
6+
#
7+
# Loading order during deployment:
8+
# 1. Environment config is loaded first (e.g., production-hetzner.env)
9+
# 2. Provider config is loaded second (this file)
10+
# 3. Provider values can override environment values, but environments can override provider defaults
11+
#
12+
# BEST PRACTICES:
13+
# - Set sensible defaults here that work for most environments
14+
# - Use environment configs to override only when necessary (performance, geography, etc.)
15+
# - Keep authentication tokens and API keys only in this file
16+
#
317
# Location: infrastructure/config/providers/hetzner.env
418

519
# === HETZNER CLOUD AUTHENTICATION ===
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
# Configuration Architecture Guide
2+
3+
This guide explains the hierarchical configuration system used by the Torrust Tracker Demo
4+
for managing environment and provider configurations.
5+
6+
## Overview
7+
8+
The project uses a **two-level configuration hierarchy** that allows flexible management
9+
of deployment settings across different environments (development, staging, production)
10+
and providers (libvirt, Hetzner Cloud).
11+
12+
## Configuration Layers
13+
14+
### Layer 1: Environment Configuration
15+
16+
**Location**: `infrastructure/config/environments/`
17+
**Purpose**: Environment-specific settings (VM specs, secrets, SSL, backups)
18+
**Examples**: `development-libvirt.env`, `production-hetzner.env`
19+
20+
### Layer 2: Provider Configuration
21+
22+
**Location**: `infrastructure/config/providers/`
23+
**Purpose**: Provider-wide defaults and authentication
24+
**Examples**: `libvirt.env`, `hetzner.env`
25+
26+
## Loading Order and Override System
27+
28+
During deployment, configurations are loaded in this specific order:
29+
30+
```bash
31+
# 1. Environment configuration loaded first
32+
source "infrastructure/config/environments/production-hetzner.env"
33+
34+
# 2. Provider configuration loaded second (can override environment values)
35+
source "infrastructure/config/providers/hetzner.env"
36+
```
37+
38+
### Why This Order?
39+
40+
This loading order provides **environment-specific override capability**:
41+
42+
- **Provider configs** set sensible defaults for all environments using that provider
43+
- **Environment configs** can override provider defaults when specific needs arise
44+
- **Later loaded values win**, so provider configs have final say on their core settings
45+
46+
## Practical Configuration Examples
47+
48+
### Example 1: Default Behavior (No Overrides)
49+
50+
**Provider config** (`hetzner.env`):
51+
52+
```bash
53+
HETZNER_SERVER_TYPE=cpx31 # 4 vCPU, 8GB RAM - good default
54+
HETZNER_LOCATION=fsn1 # Falkenstein datacenter
55+
HETZNER_TOKEN=actual_api_token # Authentication
56+
```
57+
58+
**Environment config** (`production-hetzner.env`):
59+
60+
```bash
61+
VM_MEMORY=8192 # Application-specific setting
62+
DOMAIN_NAME=tracker.example.com # Environment-specific domain
63+
# HETZNER_SERVER_TYPE not set # Uses provider default (cpx31)
64+
```
65+
66+
**Result**: Production uses `cpx31` server in `fsn1` location.
67+
68+
### Example 2: Environment-Specific Override
69+
70+
**Provider config** (`hetzner.env`):
71+
72+
```bash
73+
HETZNER_SERVER_TYPE=cpx31 # Default for most environments
74+
HETZNER_LOCATION=fsn1 # Default datacenter
75+
```
76+
77+
**Environment config** (`production-hetzner.env`):
78+
79+
```bash
80+
VM_MEMORY=16384 # Higher memory requirement
81+
HETZNER_SERVER_TYPE=cx41 # Override: Higher performance for production
82+
# HETZNER_LOCATION not set # Uses provider default (fsn1)
83+
```
84+
85+
**Result**: Production uses `cx41` server (higher performance) in `fsn1` location.
86+
87+
### Example 3: Geographic Distribution
88+
89+
**Provider config** (`hetzner.env`):
90+
91+
```bash
92+
HETZNER_SERVER_TYPE=cpx31 # Standard performance
93+
HETZNER_LOCATION=fsn1 # EU default
94+
```
95+
96+
**Environment configs**:
97+
98+
```bash
99+
# staging-hetzner.env (EU staging)
100+
# HETZNER_LOCATION not set # Uses provider default (fsn1)
101+
102+
# production-us-hetzner.env (US production)
103+
HETZNER_LOCATION=ash # Override: US East Coast
104+
```
105+
106+
**Result**: Staging in EU, production in US, both using same server type.
107+
108+
## Configuration Variable Categories
109+
110+
### Environment-Only Variables
111+
112+
These appear only in environment configurations:
113+
114+
- `VM_MEMORY`, `VM_VCPUS`, `VM_DISK_SIZE` - VM specifications
115+
- `MYSQL_ROOT_PASSWORD`, `MYSQL_PASSWORD` - Application secrets
116+
- `DOMAIN_NAME`, `CERTBOT_EMAIL` - SSL configuration
117+
- `ENABLE_SSL`, `ENABLE_DB_BACKUPS` - Feature flags
118+
119+
### Provider-Only Variables
120+
121+
These appear only in provider configurations:
122+
123+
- `HETZNER_TOKEN`, `PROVIDER_LIBVIRT_URI` - Authentication
124+
- Server type and location defaults
125+
- Provider-specific settings and references
126+
127+
### Shared Variables (Override Candidates)
128+
129+
These can appear in both layers, with environment overriding provider:
130+
131+
- `HETZNER_SERVER_TYPE` - Server performance level
132+
- `HETZNER_LOCATION` - Datacenter location
133+
- `HETZNER_IMAGE` - Operating system image
134+
- Provider-specific performance or regional settings
135+
136+
## Best Practices
137+
138+
### For Provider Configurations
139+
140+
1. **Set sensible defaults** that work for most environments
141+
2. **Include comprehensive documentation** about available options
142+
3. **Keep authentication tokens secure** and never commit to git
143+
4. **Test defaults** across different environment types
144+
145+
### For Environment Configurations
146+
147+
1. **Override sparingly** - only when truly needed for that environment
148+
2. **Document the reason** for any provider overrides
149+
3. **Use comments** to show available override options
150+
4. **Keep secrets separate** from non-sensitive configuration
151+
152+
### When to Override
153+
154+
Override provider defaults in environment configs when:
155+
156+
- **Performance requirements differ** (production needs more power)
157+
- **Geographic requirements** (regulatory or latency concerns)
158+
- **Cost optimization** (development can use smaller instances)
159+
- **Testing specific features** (particular server types or locations)
160+
161+
### When NOT to Override
162+
163+
Don't override unless necessary:
164+
165+
- **API tokens and authentication** should stay in provider configs
166+
- **Standard configurations** work fine with provider defaults
167+
- **Adds unnecessary complexity** without clear benefit
168+
169+
## Configuration Templates
170+
171+
The project includes templates for both layers:
172+
173+
### Template Structure
174+
175+
```text
176+
infrastructure/config/
177+
├── templates/ # Version-controlled templates
178+
│ ├── environments/ # Environment templates
179+
│ │ ├── base.env.tpl
180+
│ │ ├── production.env.tpl
181+
│ │ └── staging.env.tpl
182+
│ └── providers/ # Provider templates
183+
│ ├── hetzner.env.tpl
184+
│ └── libvirt.env.tpl
185+
├── environments/ # User-generated (git-ignored)
186+
│ ├── development-libvirt.env
187+
│ └── production-hetzner.env
188+
└── providers/ # User-generated (git-ignored)
189+
├── hetzner.env
190+
└── libvirt.env
191+
```
192+
193+
### Template Usage
194+
195+
1. **Copy templates** to create user configurations
196+
2. **Customize values** for your specific deployment
197+
3. **Never modify templates directly** - they're shared across all users
198+
4. **User configs are git-ignored** to protect secrets
199+
200+
## Troubleshooting Configuration Issues
201+
202+
### Common Problems
203+
204+
1. **Variable not taking effect**
205+
206+
- Check loading order: provider config loads after environment
207+
- Verify variable name spelling and format
208+
- Check if variable is commented out
209+
210+
2. **Override not working**
211+
212+
- Ensure variable is uncommented in environment config
213+
- Check for typos in variable names
214+
- Verify the variable is loaded by the provisioning script
215+
216+
3. **Missing configuration**
217+
218+
- Check that both environment and provider configs exist
219+
- Verify file naming convention: `{environment}-{provider}.env`
220+
- Ensure files are in correct directories
221+
222+
### Debugging Configuration Loading
223+
224+
Enable debug logging to see configuration loading:
225+
226+
```bash
227+
# Add to provisioning script for debugging
228+
set -x # Enable debug output
229+
echo "Loading environment: ${env_file}"
230+
echo "Loading provider: ${provider_config}"
231+
set +x # Disable debug output
232+
```
233+
234+
## Security Considerations
235+
236+
### Sensitive Data Handling
237+
238+
- **Provider configs**: Contain API tokens and credentials
239+
- **Environment configs**: Contain application secrets and passwords
240+
- **Both layers**: Are git-ignored to prevent accidental commits
241+
- **Templates**: Contain no sensitive data, safe to version control
242+
243+
### Access Control
244+
245+
- Limit access to configuration directories
246+
- Use proper file permissions (600) for config files
247+
- Rotate API tokens and passwords regularly
248+
- Use encrypted storage for backup configurations
249+
250+
This architecture provides flexibility while maintaining security and simplicity for
251+
managing complex multi-environment, multi-provider deployments.### Template Usage
252+
253+
1. **Copy templates** to create user configurations
254+
2. **Customize values** for your specific deployment
255+
3. **Never modify templates directly** - they're shared across all users
256+
4. **User configs are git-ignored** to protect secrets
257+
258+
## Troubleshooting Configuration Issues
259+
260+
### Common Problems
261+
262+
1. **Variable not taking effect**
263+
264+
- Check loading order: provider config loads after environment
265+
- Verify variable name spelling and format
266+
- Check if variable is commented out
267+
268+
2. **Override not working**
269+
270+
- Ensure variable is uncommented in environment config
271+
- Check for typos in variable names
272+
- Verify the variable is loaded by the provisioning script
273+
274+
3. **Missing configuration**
275+
- Check that both environment and provider configs exist
276+
- Verify file naming convention: `{environment}-{provider}.env`
277+
- Ensure files are in correct directories
278+
279+
### Debugging Configuration Loading
280+
281+
Enable debug logging to see configuration loading:
282+
283+
```bash
284+
# Add to provisioning script for debugging
285+
set -x # Enable debug output
286+
echo "Loading environment: ${env_file}"
287+
echo "Loading provider: ${provider_config}"
288+
set +x # Disable debug output
289+
```
290+
291+
## Security Considerations
292+
293+
### Sensitive Data Handling
294+
295+
- **Provider configs**: Contain API tokens and credentials
296+
- **Environment configs**: Contain application secrets and passwords
297+
- **Both layers**: Are git-ignored to prevent accidental commits
298+
- **Templates**: Contain no sensitive data, safe to version control
299+
300+
### Access Control
301+
302+
- Limit access to configuration directories
303+
- Use proper file permissions (600) for config files
304+
- Rotate API tokens and passwords regularly
305+
- Use encrypted storage for backup configurations
306+
307+
This architecture provides flexibility while maintaining security and simplicity for
308+
managing complex multi-environment, multi-provider deployments.

0 commit comments

Comments
 (0)