refactor: Standardize Umami analytics environment variables to non-public names with fallbacks to NEXT_PUBLIC_ prefixed versions.
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

This commit is contained in:
2026-02-06 22:35:49 +01:00
parent 259d712105
commit e179e8162c
15 changed files with 243 additions and 245 deletions

View File

@@ -42,15 +42,15 @@ The application uses a clean, robust, **fully automated** environment variable s
## Environment Variables
### Build-Time Variables (NEXT_PUBLIC_*)
### Build-Time Variables (NEXT*PUBLIC*\*)
These are embedded into the JavaScript bundle during build and are visible to the client:
| Variable | Required | Description |
|----------|----------|-------------|
| `NEXT_PUBLIC_BASE_URL` | ✅ Yes | Base URL of the application (e.g., `https://klz-cables.com`) |
| `NEXT_PUBLIC_UMAMI_WEBSITE_ID` | ❌ No | Umami analytics website ID |
| `NEXT_PUBLIC_UMAMI_SCRIPT_URL` | ❌ No | Umami analytics script URL (default: `https://analytics.infra.mintel.me/script.js`) |
| Variable | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------ |
| `NEXT_PUBLIC_BASE_URL` | ✅ Yes | Base URL of the application (e.g., `https://klz-cables.com`) |
| `UMAMI_WEBSITE_ID` | ❌ No | Umami analytics website ID (passed as prop) |
| `UMAMI_API_ENDPOINT` | ❌ No | Backend-only Umami analytics API target (internal) |
**Important**: These must be provided as `--build-arg` when building the Docker image.
@@ -58,38 +58,40 @@ These are embedded into the JavaScript bundle during build and are visible to th
These are loaded from the `.env` file at runtime and are only available on the server:
| Variable | Required | Description |
|----------|----------|-------------|
| `NODE_ENV` | ✅ Yes | Environment mode (`production`, `development`, `test`) |
| `SENTRY_DSN` | ❌ No | GlitchTip/Sentry error tracking DSN |
| `MAIL_HOST` | ❌ No | SMTP server hostname |
| `MAIL_PORT` | ❌ No | SMTP server port (default: `587`) |
| `MAIL_USERNAME` | ❌ No | SMTP authentication username |
| `MAIL_PASSWORD` | ❌ No | SMTP authentication password |
| `MAIL_FROM` | ❌ No | Email sender address |
| `MAIL_RECIPIENTS` | ❌ No | Comma-separated list of recipient emails |
| `REDIS_URL` | ❌ No | Redis connection URL (e.g., `redis://redis:6379/2`) |
| `REDIS_KEY_PREFIX` | ❌ No | Redis key prefix (default: `klz:`) |
| `STRAPI_DATABASE_NAME` | ✅ Yes | Strapi database name |
| `STRAPI_DATABASE_USERNAME` | ✅ Yes | Strapi database username |
| `STRAPI_DATABASE_PASSWORD` | ✅ Yes | Strapi database password |
| `STRAPI_URL` | ✅ Yes | URL of the Strapi CMS |
| `APP_KEYS` | ✅ Yes | Strapi application keys (comma-separated) |
| `API_TOKEN_SALT` | ✅ Yes | Strapi API token salt |
| `ADMIN_JWT_SECRET` | ✅ Yes | Strapi admin JWT secret |
| `TRANSFER_TOKEN_SALT` | ✅ Yes | Strapi transfer token salt |
| `JWT_SECRET` | ✅ Yes | Strapi JWT secret |
| Variable | Required | Description |
| -------------------------- | -------- | ------------------------------------------------------ |
| `NODE_ENV` | ✅ Yes | Environment mode (`production`, `development`, `test`) |
| `SENTRY_DSN` | ❌ No | GlitchTip/Sentry error tracking DSN |
| `MAIL_HOST` | ❌ No | SMTP server hostname |
| `MAIL_PORT` | ❌ No | SMTP server port (default: `587`) |
| `MAIL_USERNAME` | ❌ No | SMTP authentication username |
| `MAIL_PASSWORD` | ❌ No | SMTP authentication password |
| `MAIL_FROM` | ❌ No | Email sender address |
| `MAIL_RECIPIENTS` | ❌ No | Comma-separated list of recipient emails |
| `REDIS_URL` | ❌ No | Redis connection URL (e.g., `redis://redis:6379/2`) |
| `REDIS_KEY_PREFIX` | ❌ No | Redis key prefix (default: `klz:`) |
| `STRAPI_DATABASE_NAME` | ✅ Yes | Strapi database name |
| `STRAPI_DATABASE_USERNAME` | ✅ Yes | Strapi database username |
| `STRAPI_DATABASE_PASSWORD` | ✅ Yes | Strapi database password |
| `STRAPI_URL` | ✅ Yes | URL of the Strapi CMS |
| `APP_KEYS` | ✅ Yes | Strapi application keys (comma-separated) |
| `API_TOKEN_SALT` | ✅ Yes | Strapi API token salt |
| `ADMIN_JWT_SECRET` | ✅ Yes | Strapi admin JWT secret |
| `TRANSFER_TOKEN_SALT` | ✅ Yes | Strapi transfer token salt |
| `JWT_SECRET` | ✅ Yes | Strapi JWT secret |
## Local Development
### Setup
1. Copy the example environment file:
```bash
cp .env.example .env
```
2. Edit `.env` and fill in your local configuration:
```bash
NODE_ENV=development
NEXT_PUBLIC_BASE_URL=http://localhost:3000
@@ -97,6 +99,7 @@ These are loaded from the `.env` file at runtime and are only available on the s
```
3. Install dependencies:
```bash
npm install
```
@@ -112,8 +115,8 @@ These are loaded from the `.env` file at runtime and are only available on the s
# Build with build-time arguments
docker build \
--build-arg NEXT_PUBLIC_BASE_URL=http://localhost:3000 \
--build-arg NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-id \
--build-arg NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js \
--build-arg UMAMI_WEBSITE_ID=your-id \
--build-arg UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me \
-t klz-cables:local .
# Run with runtime environment file
@@ -138,8 +141,8 @@ docker run --env-file .env -p 3000:3000 klz-cables:local
**Build-Time Variables:**
- `NEXT_PUBLIC_BASE_URL` - Production URL (e.g., `https://klz-cables.com`)
- `NEXT_PUBLIC_UMAMI_WEBSITE_ID` - Umami analytics ID
- `NEXT_PUBLIC_UMAMI_SCRIPT_URL` - Umami script URL
- `UMAMI_WEBSITE_ID` - Umami analytics ID
- `UMAMI_API_ENDPOINT` - Umami API endpoint
**Runtime Variables:**
- `SENTRY_DSN` - Error tracking DSN
@@ -209,11 +212,12 @@ docker-compose logs -f app
**Problem**: Build fails with "Environment validation failed"
**Solution**: Ensure all required `NEXT_PUBLIC_*` variables are provided as build arguments:
```bash
docker build \
--build-arg NEXT_PUBLIC_BASE_URL=https://klz-cables.com \
--build-arg NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-id \
--build-arg NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js \
--build-arg UMAMI_WEBSITE_ID=your-id \
--build-arg UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me \
-t klz-cables .
```
@@ -222,6 +226,7 @@ docker build \
**Problem**: Container starts but application crashes
**Solution**: Check that the `.env` file exists and contains all required runtime variables:
```bash
# On the server
cat /home/deploy/sites/klz-cables.com/.env
@@ -235,9 +240,11 @@ docker-compose logs app
**Problem**: Features not working (email, analytics, etc.)
**Solution**:
1. Check that the secret is configured in Gitea
2. Verify the workflow includes it in the `.env` generation (see `.gitea/workflows/deploy.yml`)
3. Redeploy to regenerate the `.env` file:
```bash
git commit --allow-empty -m "Trigger redeploy"
git push origin main
@@ -255,6 +262,7 @@ docker-compose logs app
**Problem**: `docker-compose up` fails with "env file not found"
**Solution**: The `.env` file should be automatically created by the workflow. If it's missing:
1. Check the workflow logs for errors in the "📝 Preparing environment configuration" step
2. Manually trigger a deployment by pushing to main
3. If still missing, check server permissions and disk space
@@ -264,6 +272,7 @@ docker-compose logs app
**Problem**: Container can't connect to Traefik
**Solution**: Verify the `infra` network exists:
```bash
docker network ls | grep infra
docker network inspect infra

View File

@@ -7,29 +7,31 @@ This guide helps you migrate from the old fragile environment variable setup to
### 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_*)
- 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"
"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
@@ -46,6 +48,7 @@ ssh root@alpha.mintel.me "/home/deploy/deploy.sh"
### Step 1: Update Gitea Secrets
**Remove these secrets** (no longer needed in CI/CD):
-`MAIL_FROM`
-`MAIL_HOST`
-`MAIL_PASSWORD`
@@ -58,9 +61,11 @@ ssh root@alpha.mintel.me "/home/deploy/deploy.sh"
-`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`
-`NEXT_PUBLIC_BASE_URL`
-`UMAMI_WEBSITE_ID`
-`UMAMI_API_ENDPOINT`
-`REGISTRY_USER`
-`REGISTRY_PASS`
-`ALPHA_SSH_KEY`
@@ -81,8 +86,8 @@ 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
UMAMI_WEBSITE_ID=your-actual-id
UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me
# Error Tracking
SENTRY_DSN=your-actual-dsn
@@ -168,6 +173,7 @@ 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
@@ -197,21 +203,22 @@ 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 |
| 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
@@ -229,7 +236,8 @@ A: `NEXT_PUBLIC_*` variables are special in Next.js - they're embedded into the
**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:
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
@@ -240,6 +248,7 @@ For `NEXT_PUBLIC_*` variables, you need to rebuild the Docker image since they'r
**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 \
@@ -250,7 +259,8 @@ scp root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/.env \
**Q: What if I accidentally commit .env to git?**
A:
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)
@@ -267,6 +277,7 @@ If you encounter issues during migration:
## 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