-
-
Notifications
You must be signed in to change notification settings - Fork 0
Migration Guide
Version: 1.0 Last Updated: November 19, 2025 Applies To: DevStack Core v1.3.0+
- Introduction
- Prerequisites
- Migration Timeline
- Root Token → AppRole Migration
- HTTP → HTTPS (TLS) Migration
- Troubleshooting Guide
- Post-Migration Validation
- Rollback Procedures
- FAQ
This guide provides step-by-step instructions for migrating existing DevStack Core installations to use:
- AppRole Authentication - Replacing root token-based Vault access with role-based authentication
- TLS Encryption - Enabling dual-mode TLS for all data services
Security Enhancements (Phase 1):
- Vault authentication: Root tokens → AppRole (role_id + secret_id)
- Network security: Plaintext → Dual-mode TLS (accepts both HTTP and HTTPS)
- Certificate management: Two-tier PKI (Root CA → Intermediate CA → Service Certs)
- Network segmentation: 4-tier isolation (vault/data/app/observability)
Operational Improvements (Phase 2):
- Startup: Manual → Health-check driven automatic startup
- Backup: Manual → Automated with validation
- Recovery: Undefined → 10-12 minute RTO with documented procedures
- Monitoring: Basic → Comprehensive alerting via Prometheus/Grafana
Performance Optimizations (Phase 3):
- PostgreSQL: +41% throughput improvement
- MySQL: +37% throughput improvement
- MongoDB: +19% throughput improvement
- Redis: 512MB memory limit, <3s failover time
- Testing: 50+ tests → 571+ comprehensive tests
Phase 4 Completion:
- ✅ 100% AppRole adoption (16/16 services)
- ✅ All infrastructure services migrated
- ✅ All reference applications migrated
- ✅ Comprehensive test coverage (32 AppRole tests, 24 TLS tests)
Who: New users installing DevStack Core for the first time Path: Follow standard installation guide - AppRole enabled by default Doc: INSTALLATION.md
Who: Users with DevStack Core installed before November 2025 Path: Migrate from root token to AppRole authentication Complexity: Medium (2-3 hours) Downtime: 10-15 minutes
Who: Users with current setup wanting to enable TLS Path: Generate certificates and enable TLS dual-mode Complexity: Low (30 minutes) Downtime: 5 minutes
Who: Developers adding new services Path: Create AppRole, policy, and init script Complexity: Medium (1-2 hours) Downtime: None (new service)
Before starting:
- ✅ Backup your data:
./devstack backup - ✅ Backup Vault configuration:
cp -r ~/.config/vault ~/vault-backup-$(date +%Y%m%d) - ✅ Note current service versions
- ✅ Have at least 1 hour for migration
- ✅ Test rollback procedure (optional but recommended)
System Requirements:
- DevStack Core v1.2.0 or later
- Vault accessible and unsealed
- All services healthy before migration
cd ~/devstack-core
git fetch origin
git checkout main
git pull origin main
# Review changes
git log --oneline --since="2025-11-01"What changed:
- AppRole authentication for 7 core services
- TLS certificate generation automation
- Service profiles (minimal/standard/full)
- Performance improvements (+41% PostgreSQL, +37% MySQL, +19% MongoDB)
- 571+ test suites
# Graceful shutdown
./devstack stop
# Verify all stopped
docker ps
# Should show only Vault (or empty)3.1: Update docker-compose.yml
# Backup current config
cp docker-compose.yml docker-compose.yml.backup
# New version already includes AppRole entrypoints
# Verify PostgreSQL uses init-approle.sh:
grep "entrypoint.*init-approle" docker-compose.yml | head -1
# Should show: entrypoint: ["/init/init-approle.sh"]3.2: Verify .env file
# Your .env should already have VAULT_TOKEN
cat .env | grep VAULT_TOKEN
# VAULT_TOKEN=hvs.xxxxx (or empty, will read from ~/.config/vault/root-token)# Ensure Vault is running
docker compose up -d vault
sleep 10
# Check Vault health
curl http://localhost:8200/v1/sys/health
# Run vault-bootstrap (THIS IS THE KEY STEP)
export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=$(cat ~/.config/vault/root-token)
./devstack vault-bootstrapExpected output:
============================================
Bootstrapping Vault with Service Credentials
============================================
[*] Enabling AppRole auth method...
[✓] AppRole enabled
[*] Creating policies for services...
[✓] Policy created: postgres-policy
[✓] Policy created: mysql-policy
[✓] Policy created: mongodb-policy
[✓] Policy created: redis-policy
[✓] Policy created: rabbitmq-policy
[✓] Policy created: forgejo-policy
[✓] Policy created: reference-api-policy
[*] Creating AppRole for each service...
[✓] AppRole created: postgres
[✓] AppRole created: mysql
[✓] AppRole created: mongodb
[✓] AppRole created: redis
[✓] AppRole created: rabbitmq
[✓] AppRole created: forgejo
[✓] AppRole created: reference-api
[*] Generating role-id and secret-id for each service...
[✓] Credentials saved: ~/.config/vault/approles/postgres/
[✓] Credentials saved: ~/.config/vault/approles/mysql/
... (etc)
[✓] Vault AppRole bootstrap complete!
# Check all AppRole directories created
ls -la ~/.config/vault/approles/
# Should show: postgres, mysql, mongodb, redis, rabbitmq, forgejo, reference-api, management
# Verify credentials for one service
cat ~/.config/vault/approles/postgres/role-id
# Should show: UUID like abc123-def456-...
# Test AppRole authentication
ROLE_ID=$(cat ~/.config/vault/approles/postgres/role-id)
SECRET_ID=$(cat ~/.config/vault/approles/postgres/secret-id)
curl -X POST http://localhost:8200/v1/auth/approle/login \
-d "{\"role_id\":\"$ROLE_ID\",\"secret_id\":\"$SECRET_ID\"}" | jq
# Should return: {"auth":{"client_token":"hvs.CAESIE..."}}# Start with standard profile (recommended)
./devstack start --profile standard
# Services will now authenticate via AppRole!
# Watch logs to see AppRole authentication:
docker compose logs postgres 2>&1 | grep -i approle
# Should show: "Successfully authenticated to Vault using AppRole"7.1: Check all core services are using AppRole
# These services should have NO "VAULT_TOKEN" in environment
docker inspect dev-postgres | grep -i VAULT_TOKEN
# Should return nothing (empty)
# Instead, they should have VAULT_APPROLE_DIR
docker inspect dev-postgres | grep VAULT_APPROLE_DIR
# Should show: /vault-approles/postgres7.2: Run AppRole security tests
export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=$(cat ~/.config/vault/root-token)
./tests/test-approle-security.shExpected results:
============================================
Testing AppRole Authentication and Security
============================================
PASS: Vault is accessible
PASS: AppRole auth method is enabled
PASS: Invalid role_id rejected
PASS: Invalid secret_id rejected
PASS: Valid credentials rejected without secret_id
PASS: Valid credentials rejected without role_id
PASS: PostgreSQL AppRole authentication successful
... (32 tests total)
============================================
AppRole Security Tests: 32/32 passed (100%)
============================================
7.3: Test database connectivity
# PostgreSQL
docker exec dev-postgres psql -U devuser -d devdb -c "SELECT version();"
# Should show PostgreSQL version
# MySQL
docker exec dev-mysql mysql -u devuser -p$(./devstack vault-show-password mysql) -e "SELECT VERSION();"
# Should show MySQL version# Generate TLS certificates via Vault PKI
export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=$(cat ~/.config/vault/root-token)
./scripts/generate-certificates.sh
# Certificates saved to ~/.config/vault/certs/
ls -la ~/.config/vault/certs/
# Should show: postgres, mysql, mongodb, redis-1, redis-2, redis-3, rabbitmq, forgejo, reference-api
# Certificates are already mounted in docker-compose.yml
# Services will use them automatically
# Restart services to pick up certificates
docker compose restart postgres mysql mongodb redis-1 redis-2 redis-3 rabbitmqVerify TLS enabled:
# PostgreSQL SSL check
export PGPASSWORD=$(./devstack vault-show-password postgres)
docker exec dev-postgres psql -U devuser -d devdb -c "SHOW ssl;"
# Should show: on
# MySQL SSL check
docker exec dev-mysql mysql -u root -p$(./devstack vault-show-password mysql | grep root_password) \
-e "SHOW VARIABLES LIKE 'have_ssl';"
# Should show: YES# New backup system includes AppRole credentials
./devstack backup
# Verify backup includes AppRole
tar -tzf ~/.config/vault/backups/vault-backup-*.tar.gz | grep approles
# Should show: approles/postgres/role-id, approles/postgres/secret-id, etc.# Remove backup if everything works
rm docker-compose.yml.backup
# Optional: Remove old .env variables (if not needed)
# Keep VAULT_TOKEN for management operationsUse case: Adding AppRole authentication to PGBouncer, reference apps, or custom services
- Service currently uses
VAULT_TOKENenvironment variable - Service has init script that fetches credentials from Vault
- Vault is accessible from service container
1. Create Vault Policy
# Create policy file: configs/vault/policies/myservice-policy.hcl
cat > configs/vault/policies/myservice-policy.hcl <<'EOF'
# Policy for myservice
path "secret/data/myservice" {
capabilities = ["read"]
}
EOF
# Write policy to Vault
vault policy write myservice-policy configs/vault/policies/myservice-policy.hcl2. Create AppRole
# Create AppRole with policy
vault write auth/approle/role/myservice \
token_ttl=1h \
token_max_ttl=4h \
policies=myservice-policy
# Generate role-id and secret-id
mkdir -p ~/.config/vault/approles/myservice
vault read -field=role_id auth/approle/role/myservice/role-id > \
~/.config/vault/approles/myservice/role-id
vault write -field=secret_id -f auth/approle/role/myservice/secret-id > \
~/.config/vault/approles/myservice/secret-id
# Set permissions
chmod 600 ~/.config/vault/approles/myservice/secret-id
chmod 644 ~/.config/vault/approles/myservice/role-id3. Create init-approle.sh Script
# Copy template from existing service
cp configs/postgres/scripts/init-approle.sh configs/myservice/scripts/init-approle.sh
# Modify for your service (change SERVICE_NAME, paths, etc.)
nano configs/myservice/scripts/init-approle.sh
# Make executable
chmod +x configs/myservice/scripts/init-approle.sh4. Update docker-compose.yml
myservice:
# Change entrypoint from init.sh to init-approle.sh
entrypoint: ["/init/init-approle.sh"]
environment:
VAULT_ADDR: ${VAULT_ADDR:-http://vault:8200}
VAULT_APPROLE_DIR: /vault-approles/myservice
# Remove VAULT_TOKEN environment variable
volumes:
- ./configs/myservice/scripts/init-approle.sh:/init/init-approle.sh:ro
- ${HOME}/.config/vault/approles/myservice:/vault-approles/myservice:ro
networks:
vault-network: # Ensure service can reach Vault
# ... other networks5. Test AppRole Authentication
# Restart service
docker compose restart myservice
# Check logs for successful AppRole auth
docker compose logs myservice | grep -i approle
# Should show: "Successfully authenticated to Vault using AppRole"
# Verify service started correctly
docker compose ps myservice
# Should show: Up (healthy)# 1. Generate certificates
export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=$(cat ~/.config/vault/root-token)
./scripts/generate-certificates.sh
# 2. Certificates automatically mounted (already in docker-compose.yml)
# 3. Restart services
docker compose restart postgres mysql mongodb redis-1 redis-2 redis-3 rabbitmq
# 4. Verify TLS enabled
docker exec dev-postgres psql -U devuser -d devdb -c "SHOW ssl;"
# Should show: onNote: Dual-mode means services accept BOTH TLS and non-TLS connections.
To enforce TLS and reject non-TLS connections:
PostgreSQL:
# Update postgresql.conf
docker exec dev-postgres bash -c 'echo "ssl_ca_file = \"/var/lib/postgresql/certs/ca.crt\"" >> /var/lib/postgresql/data/postgresql.conf'
docker exec dev-postgres bash -c 'echo "hostssl all all 0.0.0.0/0 scram-sha-256" >> /var/lib/postgresql/data/pg_hba.conf'
docker compose restart postgresMySQL:
# Update my.cnf
docker exec dev-mysql bash -c 'echo "require_secure_transport = ON" >> /etc/mysql/conf.d/tls.cnf'
docker compose restart mysqlIf AppRole causes issues, rollback to root token authentication:
1. Update docker-compose.yml
# Restore from backup
cp docker-compose.yml.backup docker-compose.yml
# Or manually change entrypoint:
# entrypoint: ["/init/init.sh"] # instead of init-approle.sh
# And restore environment:
# VAULT_TOKEN: ${VAULT_TOKEN}2. Restart services
docker compose restart postgres mysql mongodb redis-1 rabbitmq3. Verify services using root token
docker inspect dev-postgres | grep VAULT_TOKEN
# Should show: VAULT_TOKEN=hvs.xxxxx# 1. Remove SSL requirement from configurations
# (depends on service - see service documentation)
# 2. Restart without SSL
docker compose restart postgres mysql mongodb
# 3. Verify SSL disabled (or optional)
docker exec dev-postgres psql -U devuser -d devdb -c "SHOW ssl;"
# May show: on (but connections don't require it)# 1. Stop all services
./devstack stop
# 2. Restore from backup
tar -xzf ~/vault-backup-YYYYMMDD.tar.gz -C ~/.config/
# 3. Restore docker-compose.yml
cp docker-compose.yml.backup docker-compose.yml
# 4. Start services
./devstack start
# 5. Verify services healthy
./devstack healthCheck:
# 1. Verify AppRole credentials exist
ls -la ~/.config/vault/approles/postgres/
# Should show: role-id and secret-id
# 2. Check service logs
docker compose logs postgres | grep -i error
# 3. Test AppRole login manually
ROLE_ID=$(cat ~/.config/vault/approles/postgres/role-id)
SECRET_ID=$(cat ~/.config/vault/approles/postgres/secret-id)
curl -X POST http://localhost:8200/v1/auth/approle/login \
-d "{\"role_id\":\"$ROLE_ID\",\"secret_id\":\"$SECRET_ID\"}"Solution: Re-run ./devstack vault-bootstrap
Check policy:
vault policy read postgres-policy
# Should show: path "secret/data/postgres" { capabilities = ["read"] }Solution: Re-create policy via vault-bootstrap
Check:
ls -la ~/.config/vault/certs/postgres/
# Should show: ca.crt, server.crt, server.key
docker exec dev-postgres ls -la /var/lib/postgresql/certs/
# Should show same filesSolution: Re-run ./scripts/generate-certificates.sh
A: No. All services already use AppRole in DevStack Core v1.3.0+. Migration is only needed if you're upgrading from an older version.
A: No. Migration only changes authentication method, not data storage. However, always backup before migration.
A: 10-15 minutes of downtime, 1-2 hours total including testing.
A: Yes. Core services use AppRole, infrastructure uses root token. Both work together.
A: No. TLS is optional. Services run in dual-mode (accept both TLS and non-TLS).
A: Run ./tests/test-approle-security.sh - all 32 tests should pass.
A: Restart the service to get a new token: docker compose restart postgres
A: Yes. Update AppRole: vault write auth/approle/role/postgres token_ttl=2h token_max_ttl=8h
A: tar -czf approles-backup.tar.gz ~/.config/vault/approles/
A: ~/.config/vault/approles/<service>/role-id and secret-id
Documentation:
- VAULT.md - Vault integration details
- TROUBLESHOOTING.md - AppRole troubleshooting section
- SECURITY_ASSESSMENT.md - Security implementation details
Testing:
- Run
./tests/test-approle-security.shto validate AppRole - Run
./tests/test-tls-connections.shto validate TLS
Getting Help:
- Check logs:
docker compose logs <service> | grep -i error - Run diagnostics:
./devstack health - Review: UltraThink Analysis
Last Updated: November 19, 2025 Phase Status: Phase 4 Complete AppRole Adoption: 100% (16/16 services) ✅ Services: postgres, mysql, mongodb, redis (3 nodes), rabbitmq, forgejo, reference-api, api-first, golang-api, nodejs-api, rust-api, pgbouncer, redis-exporter (3 instances), vector, management