Multi-Environment Deployment Implementation Guide¶
Quick Start¶
Your infrastructure is now organized into three environment tiers with automatic progression:
Development (rpi-dev-*) → Staging (rpi-staging-*) → Production (rpi-*)
Test Here Validate Here Deploy Here
Environment Overview¶
Development¶
- Purpose: Test configuration changes and new features
- Naming:
rpi-dev-XXX(e.g.,rpi-dev-1883c4049f6c) - Strategy: Immediate deployment
- Backups: Disabled
- Health Checks: Every 5 minutes
- Use Case: Active development, breaking changes acceptable
Staging¶
- Purpose: Pre-production validation
- Naming:
rpi-staging-XXX(e.g.,rpi-staging-1883c404a130) - Strategy: Validated deployment
- Backups: Enabled
- Health Checks: Every 5 minutes (same as dev)
- Use Case: Production-like testing, stable changes
Production¶
- Purpose: Customer-facing infrastructure
- Naming:
rpi-prod-<serial>(e.g.,rpi-prod-1883c404a12f,rpi-100) - Strategy: Approval required
- Backups: Enabled (30-day retention)
- Health Checks: Every 10 minutes (conservative)
- Use Case: Stable, tested, approved changes only
Getting Started with Environments¶
1. Add Your First Development Device¶
Edit ansible/inventory/production/hosts.yml:
development:
hosts:
rpi-dev-1883c4049f6c: # Development device for testing
local_host: 192.168.1.50
tunnel_host: rpi-dev-1883c4049f6c-ssh.tagai.uk
device_region: development
Then deploy:
task ansible:deploy-dev DEVICE=rpi-dev-1883c4049f6c
2. Deploy to All Development Devices¶
task ansible:deploy-dev
3. Add Staging Device¶
Edit ansible/inventory/production/hosts.yml:
staging:
hosts:
rpi-staging-1883c404a130:
local_host: 192.168.1.26
tunnel_host: rpi-staging-1883c404a130-ssh.tagai.uk
device_region: staging
rpi-staging-002:
local_host: 192.168.1.27
tunnel_host: rpi-staging-002-ssh.tagai.uk
device_region: staging
vars:
environment: staging
children:
staging_node_red:
hosts:
rpi-staging-1883c404a130:
rpi-staging-002:
staging_cloudflared:
hosts:
rpi-staging-1883c404a130:
rpi-staging-002:
staging_mqtt:
hosts:
rpi-staging-1883c404a130:
rpi-staging-002:
Deploy to staging:
task ansible:deploy-staging
4. Add Production Devices¶
Edit ansible/inventory/production/hosts.yml:
production:
hosts:
rpi-prod-1883c404a12f:
local_host: 192.168.1.100
tunnel_host: rpi-prod-1883c404a12f-ssh.tagai.uk
device_region: production
rpi-staging-1883c404a130:
local_host: 192.168.1.101
tunnel_host: rpi-staging-1883c404a130-ssh.tagai.uk
device_region: production
rpi-dev-1883c4049f6c:
local_host: 192.168.1.102
tunnel_host: rpi-dev-1883c4049f6c-ssh.tagai.uk
device_region: production
# ... add devices 004-100 following the pattern
Production requires approval:
task ansible:deploy-prod DEVICE=rpi-prod-1883c404a12f
# You will be prompted to confirm
Deployment Workflow¶
Typical Change Flow¶
1. Edit configuration (e.g., Node-RED settings, MQTT config)
└─ Update docs/configuration.md
2. Deploy to Development
└─ task ansible:deploy-dev
└─ Test thoroughly, verify no breaking changes
3. Deploy to Staging
└─ task ansible:deploy-staging
└─ Run production-like validation
└─ Check healthchecks, monitor logs
4. Deploy to Production
└─ task ansible:deploy-prod
└─ Confirm with approval prompt
└─ Monitor health checks post-deployment
Useful Commands by Scenario¶
Testing a Configuration Change¶
# 1. Deploy to dev for testing
task ansible:deploy-dev DEVICE=rpi-dev-1883c4049f6c
# 2. Verify health
task ansible:health-dev
# 3. Check specific service
task ansible:shell DEVICE=rpi-dev-1883c4049f6c CMD="systemctl status nodered"
# 4. If good, promote to staging
task ansible:deploy-staging DEVICE=rpi-staging-1883c404a130
# 5. Final health check before production
task ansible:health-staging
Emergency Service Restart¶
# Restart in dev (test immediately)
task ansible:restart-dev
# Restart in staging (affects pre-prod)
task ansible:restart-staging
# Restart in production (requires confirmation)
task ansible:restart-prod
Monitor Fleet Health¶
# Dev environment status
task ansible:health-dev
# Staging environment status
task ansible:health-staging
# Production environment status
task ansible:health-prod
# All environments at once
task ansible:health
Certificate Renewal¶
# Automatically renews certificates when < 30 days to expiry
task ansible:renew-certs
# Checks all environments (dev, staging, prod)
Environment-Specific Variables¶
Each environment has unique settings in group_vars/:
Development (group_vars/development.yml)¶
environment: development
environment_tier: 1
deploy_strategy: immediate
backup_enabled: false
healthcheck_interval: 300 # 5 minutes
log_level: debug
monitoring_enabled: false
Staging (group_vars/staging.yml)¶
environment: staging
environment_tier: 2
deploy_strategy: validated
backup_enabled: true
healthcheck_interval: 300 # 5 minutes
log_level: info
monitoring_enabled: true
alert_thresholds:
cpu: 80
memory: 85
disk: 90
Production (group_vars/production.yml)¶
environment: production
environment_tier: 3
deploy_strategy: approval_required
backup_enabled: true
backup_retention: 30 # days
healthcheck_interval: 600 # 10 minutes
log_level: info
monitoring_enabled: true
alert_thresholds:
cpu: 75
memory: 80
disk: 85
critical_alerts: true
alert_channels:
- email
- slack
Role Application by Environment¶
The same roles apply to all environments, but behave differently based on environment settings:
node_red: Always version 3.1.3, but dev has debug logs, prod has strict monitoringcloudflared: Uses same tunnel config, but staging validates connectivity, prod has failovermqtt_client: Manages certificates across all environments, renewal threshold consistenthealthcheck: Runs with different intervals (5min dev/staging, 10min prod)
Testing the Three-Tier System¶
Quick Test (10 minutes)¶
# 1. Verify development is empty
ansible-inventory -i ansible/inventory/production/hosts.yml --graph | grep development
# 2. List staging (has rpi-staging-1883c404a130)
ansible-inventory -i ansible/inventory/production/hosts.yml --graph | grep staging
# 3. Verify production is empty (ready for your devices)
ansible-inventory -i ansible/inventory/production/hosts.yml --graph | grep production
# 4. Test health check output format (should show no hosts)
task ansible:health-dev
# 5. Test staging health (will run on rpi-staging-1883c404a130 if online)
task ansible:health-staging
Full Test (30 minutes)¶
- Add a development device to inventory
- Run:
task ansible:deploy-dev DEVICE=rpi-dev-1883c4049f6c - Run:
task ansible:health-dev(verify services started) - Add the same device to staging under a different name
- Run:
task ansible:deploy-staging DEVICE=rpi-staging-1883c404a130 - Run:
task ansible:health-staging(verify staging device works) - Test production deployment with approval prompt:
task ansible:deploy-prod DEVICE=rpi-prod-1883c404a12f # Type 'yes' when prompted
Troubleshooting¶
Devices Not Showing in Environment¶
Check inventory syntax:
ansible-inventory -i ansible/inventory/production/hosts.yml --host rpi-dev-1883c4049f6c
Deployment Hangs Waiting for Confirmation¶
This is normal for production deployments - read the prompt carefully and type exactly yes to proceed.
Health Check Shows No Hosts¶
Make sure devices are added to inventory. Empty environments are normal during initial setup.
Environment Variables Not Applied¶
Verify the device's environment group matches its name prefix:
- rpi-dev-1883c4049f6c must be under development group
- rpi-staging-1883c404a130 must be under staging group
- rpi-prod-1883c404a12f must be under production group
Next Steps¶
- Add your development devices to
developmentgroup in hosts.yml - Test deployment with
task ansible:deploy-dev - Add staging device for pre-production validation
- Configure production devices when changes are validated
- Set up monitoring to watch health checks across environments
For detailed operations, see ansible-environment-workflow.md.