Some checks failed
Build & Deploy KLZ Cables / 🔍 Prepare Environment (push) Successful in 7s
Build & Deploy KLZ Cables / 🧪 Quality Assurance (push) Failing after 1m31s
Build & Deploy KLZ Cables / 🏗️ Build App (push) Successful in 3m51s
Build & Deploy KLZ Cables / 🚀 Deploy (push) Has been skipped
Build & Deploy KLZ Cables / ⚡ PageSpeed (push) Has been skipped
Build & Deploy KLZ Cables / 🔔 Notifications (push) Successful in 2s
288 lines
8.0 KiB
Markdown
288 lines
8.0 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_BASE_URL`
|
|
- ✅ `UMAMI_WEBSITE_ID`
|
|
- ✅ `UMAMI_API_ENDPOINT`
|
|
- ✅ `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
|
|
UMAMI_WEBSITE_ID=your-actual-id
|
|
UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me
|
|
|
|
# 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! 🎉
|