env
All checks were successful
Build & Deploy KLZ Cables / build-and-deploy (push) Successful in 3m46s

This commit is contained in:
2026-01-28 00:34:40 +01:00
parent dab4f3f5b5
commit 8242687b07
8 changed files with 69 additions and 50 deletions

16
.env
View File

@@ -1,11 +1,10 @@
# Application
NODE_ENV=production
NEXT_PUBLIC_BASE_URL=https://klz-cables.com
UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
SENTRY_DSN=https://c10957d0182245b1a2a806ac2d34a197@errors.infra.mintel.me/1
LOG_LEVEL=info
PDF_DEBUG_EXCEL=0
PDF_LOCALE=
PDF_MATCH=
PDF_LIMIT=0
# WooCommerce & WordPress
WOOCOMMERCE_URL=https://klz-cables.com
@@ -13,15 +12,8 @@ WOOCOMMERCE_CONSUMER_KEY=ck_38d97df86880e8fefbd54ab5cdf47a9c5a9e5b39
WOOCOMMERCE_CONSUMER_SECRET=cs_d675ee2ac2ec7c22de84ae5451c07e42b1717759
WORDPRESS_APP_PASSWORD="DlJH 49dp fC3a Itc3 Sl7Z Wz0k"
# Umami Analytics
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
# GlitchTip (Sentry protocol)
SENTRY_DSN=https://c10957d0182245b1a2a806ac2d34a197@errors.infra.mintel.me/1
# Redis Cache
REDIS_URL=
REDIS_URL=redis://redis:6379/2
REDIS_KEY_PREFIX=klz:
# SMTP Configuration

View File

@@ -74,8 +74,8 @@ jobs:
echo ""
echo "📦 Build Arguments:"
echo " • NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID != '' && '***' || 'NOT SET' }}"
echo " • NEXT_PUBLIC_UMAMI_SCRIPT_URL: ${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL != '' && '***' || 'NOT SET' }}"
echo " • SENTRY_DSN: ${{ secrets.SENTRY_DSN != '' && '***' || 'NOT SET' }}"
echo " • NEXT_PUBLIC_SENTRY_DSN: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN != '' && '***' || 'NOT SET' }}"
echo " • NEXT_PUBLIC_BASE_URL: ${{ secrets.NEXT_PUBLIC_BASE_URL != '' && '***' || 'NOT SET' }}"
echo ""
echo "⏱️ Build started at: $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
@@ -87,8 +87,8 @@ jobs:
--pull \
--platform linux/arm64 \
--build-arg NEXT_PUBLIC_UMAMI_WEBSITE_ID="${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}" \
--build-arg NEXT_PUBLIC_UMAMI_SCRIPT_URL="${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL }}" \
--build-arg SENTRY_DSN="${{ secrets.SENTRY_DSN }}" \
--build-arg NEXT_PUBLIC_SENTRY_DSN="${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}" \
--build-arg NEXT_PUBLIC_BASE_URL="${{ secrets.NEXT_PUBLIC_BASE_URL }}" \
-t registry.infra.mintel.me/mintel/klz-cables.com:latest \
--push .
@@ -160,11 +160,13 @@ jobs:
MAIL_RECIPIENTS='${{ secrets.MAIL_RECIPIENTS }}' \
MAIL_USERNAME='${{ secrets.MAIL_USERNAME }}' \
NEXT_PUBLIC_BASE_URL='${{ secrets.NEXT_PUBLIC_BASE_URL }}' \
NEXT_PUBLIC_SENTRY_DSN='${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}' \
NEXT_PUBLIC_UMAMI_WEBSITE_ID='${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}' \
NEXT_PUBLIC_UMAMI_SCRIPT_URL='${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL }}' \
NODE_ENV='${{ secrets.NODE_ENV }}' \
SENTRY_DSN='${{ secrets.SENTRY_DSN }}' \
sudo -u deploy -H -E /home/deploy/deploy.sh"
REDIS_URL='${{ secrets.REDIS_URL }}' \
REDIS_KEY_PREFIX='${{ secrets.REDIS_KEY_PREFIX }}' \
/home/deploy/deploy.sh"
DEPLOY_EXIT_CODE=$?
echo ""

View File

@@ -25,12 +25,11 @@ ENV NEXT_TELEMETRY_DISABLED=1
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
ARG SENTRY_DSN
ARG NEXT_PUBLIC_SENTRY_DSN
ARG NEXT_PUBLIC_BASE_URL
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
ENV SENTRY_DSN=$SENTRY_DSN
ENV NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
RUN npm run build

View File

@@ -0,0 +1,4 @@
services:
app:
env_file:
- .env

View File

@@ -57,24 +57,19 @@ services:
retries: 5
start_period: 30s
environment:
# Umami
- NODE_ENV=${NODE_ENV:-production}
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL:?NEXT_PUBLIC_BASE_URL is required}
- NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID}
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js}
# GlitchTip (Sentry protocol)
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL}
- SENTRY_DSN=${SENTRY_DSN}
- NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN}
# Redis (app-spezifischer DB-Index)
- REDIS_URL=${REDIS_URL:-redis://redis:6379/2}
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX:-klz:}
# Mail
- MAIL_HOST=${MAIL_HOST}
- MAIL_PORT=${MAIL_PORT}
- MAIL_PORT=${MAIL_PORT:-587}
- MAIL_USERNAME=${MAIL_USERNAME}
- MAIL_PASSWORD=${MAIL_PASSWORD}
- MAIL_FROM=${MAIL_FROM}
- MAIL_RECIPIENTS=${MAIL_RECIPIENTS}
# App
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
- REDIS_URL=${REDIS_URL}
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX}
networks:
infra:

View File

@@ -108,18 +108,35 @@ Next.js App (port 3000)
- `staging.klz-cables.com` - Staging
## Environment Variables
### Build-time (in Dockerfile/Workflow)
These variables are baked into the Docker image during the build process.
- `NEXT_PUBLIC_BASE_URL` (Required)
- `NEXT_PUBLIC_UMAMI_WEBSITE_ID`
- `NEXT_PUBLIC_UMAMI_SCRIPT_URL`
- `NEXT_PUBLIC_SENTRY_DSN`
### Runtime (in docker-compose.yml)
- `SENTRY_DSN`
### Runtime (in docker-compose.yml)
These variables are passed to the container at runtime.
- `NODE_ENV` (Defaults to `production`)
- `NEXT_PUBLIC_BASE_URL` (Must be passed again at runtime for server-side use)
- `SENTRY_DSN`
- `MAIL_HOST`
- `MAIL_PORT`
- `MAIL_USERNAME`
- `MAIL_PASSWORD`
- `MAIL_FROM`
- `MAIL_RECIPIENTS`
- `REDIS_URL`
- `REDIS_KEY_PREFIX`
### Local Development
For local development, use a `.env` file. The `docker-compose.override.yml` file automatically loads this file for the `app` service.
## Monitoring

View File

@@ -12,20 +12,40 @@ const getEnv = (key: string, defaultValue?: string): string | undefined => {
return (process.env as any)[key] || defaultValue;
}
if (typeof process === 'undefined') return defaultValue;
if (typeof process === 'undefined') return defaultValue;
// In Docker/Production, variables are in process.env
// In local development, they might be in .env
const value = process.env[key];
if (value !== undefined && value !== '') {
return value;
// Check for quoted values (common when passed via SSH/Docker)
if (typeof value === 'string') {
const trimmed = value.trim();
if ((trimmed.startsWith("'") && trimmed.endsWith("'")) ||
(trimmed.startsWith('"') && trimmed.endsWith('"'))) {
return trimmed.slice(1, -1);
}
if (trimmed !== '') return trimmed;
}
return defaultValue;
};
const isProduction = getEnv('NODE_ENV') === 'production';
// Required variables in production
if (isProduction && typeof window === 'undefined') {
const required = [
'NEXT_PUBLIC_BASE_URL',
];
for (const key of required) {
if (!getEnv(key)) {
throw new Error(`Missing required environment variable: ${key}`);
}
}
}
export const config = {
env: getEnv('NODE_ENV', 'development'),
isProduction: getEnv('NODE_ENV') === 'production',
@@ -37,7 +57,7 @@ export const config = {
analytics: {
umami: {
websiteId: getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID'),
scriptUrl: getEnv('UMAMI_SCRIPT_URL', 'https://analytics.infra.mintel.me/script.js'),
scriptUrl: getEnv('NEXT_PUBLIC_UMAMI_SCRIPT_URL', 'https://analytics.infra.mintel.me/script.js'),
// The proxied path used in the frontend
proxyPath: '/stats/script.js',
enabled: Boolean(getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID')),
@@ -74,16 +94,6 @@ export const config = {
from: getEnv('MAIL_FROM'),
recipients: getEnv('MAIL_RECIPIENTS', '')?.split(',').filter(Boolean) || [],
},
woocommerce: {
url: getEnv('WOOCOMMERCE_URL'),
consumerKey: getEnv('WOOCOMMERCE_CONSUMER_KEY'),
consumerSecret: getEnv('WOOCOMMERCE_CONSUMER_SECRET'),
},
wordpress: {
appPassword: getEnv('WORDPRESS_APP_PASSWORD'),
},
} as const;
/**

View File

@@ -322,7 +322,7 @@ const nextConfig = {
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
},
async rewrites() {
const umamiUrl = (process.env.UMAMI_SCRIPT_URL || 'https://analytics.infra.mintel.me').replace('/script.js', '');
const umamiUrl = (process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL || 'https://analytics.infra.mintel.me').replace('/script.js', '');
const glitchtipUrl = process.env.SENTRY_DSN
? new URL(process.env.SENTRY_DSN).origin
: 'https://errors.infra.mintel.me';