Files
klz-cables.com/docs/ENV_MIGRATION.md
Marc Mintel 21b16a5e6c
Some checks failed
Build & Deploy KLZ Cables / build-and-deploy (push) Failing after 1m51s
deploy
2026-01-28 19:05:20 +01:00

277 lines
7.8 KiB
Markdown

# Environment Variables Migration Guide
This guide helps you migrate from the old fragile environment variable setup to the new clean, robust system.
## What Changed?
### Before (Fragile & Overkill)
**Problems:**
- Environment variables passed individually via SSH (12+ vars)
- Duplicate definitions in Dockerfile, docker-compose.yml, and deploy.yml
- Build args included runtime-only variables (SENTRY_DSN, MAIL_*, REDIS_*)
- No single source of truth
- Difficult to maintain and error-prone
```yaml
# Old deploy.yml - FRAGILE!
ssh root@alpha.mintel.me \
"MAIL_FROM='${{ secrets.MAIL_FROM }}' \
MAIL_HOST='${{ secrets.MAIL_HOST }}' \
MAIL_PASSWORD='${{ secrets.MAIL_PASSWORD }}' \
MAIL_PORT='${{ secrets.MAIL_PORT }}' \
MAIL_RECIPIENTS='${{ secrets.MAIL_RECIPIENTS }}' \
MAIL_USERNAME='${{ secrets.MAIL_USERNAME }}' \
NEXT_PUBLIC_BASE_URL='${{ secrets.NEXT_PUBLIC_BASE_URL }}' \
... (12+ variables) \
/home/deploy/deploy.sh"
```
### After (Clean & Robust)
**Benefits:**
- Single `.env` file on server contains all runtime variables
- Only `NEXT_PUBLIC_*` variables passed as build args (3 vars)
- Clear separation: build-time vs runtime
- Easy to maintain and update
- Single source of truth per environment
```yaml
# New deploy.yml - CLEAN!
ssh root@alpha.mintel.me "/home/deploy/deploy.sh"
```
## Migration Steps
### Step 1: Update Gitea Secrets
**Remove these secrets** (no longer needed in CI/CD):
-`MAIL_FROM`
-`MAIL_HOST`
-`MAIL_PASSWORD`
-`MAIL_PORT`
-`MAIL_RECIPIENTS`
-`MAIL_USERNAME`
-`NODE_ENV`
-`REDIS_URL`
-`REDIS_KEY_PREFIX`
-`SENTRY_DSN` (from build args)
**Keep these secrets** (still needed for build):
-`NEXT_PUBLIC_BASE_URL`
-`NEXT_PUBLIC_UMAMI_WEBSITE_ID`
-`NEXT_PUBLIC_UMAMI_SCRIPT_URL`
-`REGISTRY_USER`
-`REGISTRY_PASS`
-`ALPHA_SSH_KEY`
-`GOTIFY_URL`
-`GOTIFY_TOKEN`
### Step 2: Create .env File on Server
SSH to the production server and create the `.env` file:
```bash
ssh root@alpha.mintel.me
# Create .env file
cat > /home/deploy/sites/klz-cables.com/.env << 'EOF'
# Application
NODE_ENV=production
NEXT_PUBLIC_BASE_URL=https://klz-cables.com
# Analytics
NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-actual-id
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
# Error Tracking
SENTRY_DSN=your-actual-dsn
# Email
MAIL_HOST=smtp.eu.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=your-actual-username
MAIL_PASSWORD=your-actual-password
MAIL_FROM=KLZ Cables <noreply@klz-cables.com>
MAIL_RECIPIENTS=info@klz-cables.com
# Redis
REDIS_URL=redis://redis:6379/2
REDIS_KEY_PREFIX=klz:
# Varnish
VARNISH_CACHE_SIZE=256m
EOF
# Secure the file
chmod 600 /home/deploy/sites/klz-cables.com/.env
chown deploy:deploy /home/deploy/sites/klz-cables.com/.env
```
**Important**: Replace all `your-actual-*` placeholders with real values from your old Gitea secrets.
### Step 3: Update Deployment Script
Update `/home/deploy/deploy.sh` to use the new approach:
```bash
cat > /home/deploy/deploy.sh << 'EOF'
#!/bin/bash
set -e
PROJECT_DIR="/home/deploy/sites/klz-cables.com"
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
echo "║ KLZ Cables - Deployment Script ║"
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
echo ""
cd "$PROJECT_DIR"
# Check if .env file exists
if [ ! -f .env ]; then
echo "❌ ERROR: .env file not found at $PROJECT_DIR/.env"
exit 1
fi
echo "🔐 Logging into Docker registry..."
echo "$REGISTRY_PASS" | docker login registry.infra.mintel.me -u "$REGISTRY_USER" --password-stdin
echo "🔄 Pulling latest image..."
docker pull registry.infra.mintel.me/mintel/klz-cables.com:latest
echo "🔄 Stopping existing containers..."
docker-compose down
echo "🚀 Starting new containers..."
docker-compose up -d
echo "⏳ Waiting for services to be healthy..."
sleep 10
echo "🔍 Checking service status..."
docker-compose ps
echo ""
echo "✅ Deployment complete!"
EOF
chmod +x /home/deploy/deploy.sh
```
### Step 4: Deploy Updated Code
The new code is already in the repository. Just push to trigger deployment:
```bash
git push origin main
```
The CI/CD workflow will:
1. Build with only `NEXT_PUBLIC_*` build args
2. Push to registry
3. SSH to server and run deploy.sh
4. Deploy.sh will use the `.env` file for runtime vars
### Step 5: Verify Migration
After deployment, verify everything works:
```bash
# SSH to server
ssh root@alpha.mintel.me
# Check containers are running
cd /home/deploy/sites/klz-cables.com
docker-compose ps
# Verify environment variables are loaded
docker-compose exec app env | grep -E "NODE_ENV|NEXT_PUBLIC|MAIL|REDIS"
# Check application logs
docker-compose logs -f app
# Test the website
curl -I https://klz-cables.com
```
## Comparison Table
| Aspect | Before | After |
|--------|--------|-------|
| **Gitea Secrets** | 15+ secrets | 8 secrets |
| **Build Args** | 4 vars (including runtime-only) | 3 vars (NEXT_PUBLIC_* only) |
| **Runtime Vars** | Passed via SSH command | Loaded from .env file |
| **Maintenance** | Update in 3 places | Update in 1 place |
| **Security** | Secrets in CI logs | Secrets only on server |
| **Clarity** | Confusing duplication | Clear separation |
| **Robustness** | Fragile SSH command | Robust file-based config |
## Rollback Plan
If you need to rollback to the old system:
1. Revert the changes in git:
```bash
git revert HEAD
git push origin main
```
2. Re-add the removed Gitea secrets
3. The old deployment will work again
## FAQ
**Q: Why keep `NEXT_PUBLIC_*` in both build args and .env file?**
A: `NEXT_PUBLIC_*` variables are special in Next.js - they're embedded into the JavaScript bundle at build time. They must be provided as build args. However, they're also needed at runtime for server-side rendering, so they're in the .env file too.
**Q: Can I update environment variables without rebuilding?**
A: Yes, for runtime-only variables (MAIL_*, REDIS_*, SENTRY_DSN, etc.). Just edit the `.env` file on the server and restart containers:
```bash
nano /home/deploy/sites/klz-cables.com/.env
docker-compose down && docker-compose up -d
```
For `NEXT_PUBLIC_*` variables, you need to rebuild the Docker image since they're baked into the client bundle.
**Q: Where should I store the .env file backup?**
A: Keep a secure backup outside the server:
```bash
# Download from server
scp root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/.env \
~/secure-backups/klz-cables.env.backup
# Store in password manager or encrypted storage
```
**Q: What if I accidentally commit .env to git?**
A:
1. Remove it immediately: `git rm .env && git commit -m "Remove .env"`
2. Rotate all credentials in the file
3. Update the `.gitignore` to ensure it doesn't happen again (already done)
## Support
If you encounter issues during migration:
1. Check the logs: `docker-compose logs -f app`
2. Verify .env file exists and has correct permissions
3. Ensure all required variables are set
4. Review [DEPLOYMENT.md](./DEPLOYMENT.md) for detailed troubleshooting
## Summary
The new system is:
-**Simpler**: One .env file instead of scattered variables
-**Cleaner**: Clear separation of build vs runtime
-**Robust**: File-based config instead of fragile SSH commands
-**Secure**: Secrets stay on server, not in CI logs
-**Maintainable**: Single source of truth per environment
You've successfully migrated from a fragile, overkill setup to a clean, production-ready configuration! 🎉