.env: DATABASE_URL aus DB_*-Komponenten zusammenbauen (kein Doppel-Pflegen)
Bisher: DATABASE_URL und die DB_USER/PASSWORD/etc. mussten parallel
gepflegt werden – Werte konnten auseinanderlaufen.
Fix:
- dotenv-expand installiert (löst ${VAR}-Substitution in .env)
- .env.example: DATABASE_URL=mysql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
- DB_HOST als neue Variable (Default localhost; Container überschreibt zu "db")
- Backend index.ts: dotenvExpand.expand() statt nur dotenv.config()
- Plus Fallback im Code: wenn DATABASE_URL leer aber DB_*-Werte vorhanden,
baut der Backend-Code die URL selbst zusammen (encodeURIComponent für
Sonderzeichen im Passwort).
docker-compose.yml setzt DATABASE_URL weiterhin explizit (Container-
internal Hostname "db") und überschreibt damit die Dev-Variante.
Live-verifiziert:
- Dev-Modus: mysql://root:***@localhost:3306/opencrm (substituiert)
- Container: mysql://root:***@db:3306/opencrm (compose explizit)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+6
-3
@@ -18,14 +18,17 @@ FACTORY_DEFAULTS_DIR=./data/factory-defaults
|
||||
BACKUPS_DIR=./data/backups
|
||||
|
||||
# ============== DATENBANK ==============
|
||||
DB_HOST=localhost # Im Container überschreibt docker-compose das auf "db"
|
||||
DB_NAME=opencrm
|
||||
DB_USER=opencrm
|
||||
DB_PASSWORD=change-this-password
|
||||
DB_ROOT_PASSWORD=change-this-root-password
|
||||
|
||||
# Connection-String fürs Backend (im Container = Service-Name `db`)
|
||||
# Im Dev-Modus (npm run dev) lokal: localhost:DB_PORT
|
||||
DATABASE_URL=mysql://root:change-this-root-password@localhost:3306/opencrm
|
||||
# Connection-String wird aus den DB_*-Komponenten zusammengebaut (dotenv-expand).
|
||||
# Manuell überschreiben nur wenn Sonderfälle (z.B. extra Query-Parameter).
|
||||
# Hinweis: für lokales Dev mit MariaDB im Container nutze DB_HOST=localhost,
|
||||
# weil docker-compose den DB-Port auf 127.0.0.1:DB_PORT mappt.
|
||||
DATABASE_URL=mysql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
|
||||
|
||||
# ============== SECURITY ==============
|
||||
# JWT-Secret: min. 32 Zeichen. Generieren: openssl rand -hex 64
|
||||
|
||||
Generated
+30
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "opencrm-backend",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "opencrm-backend",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"dependencies": {
|
||||
"@prisma/client": "^5.22.0",
|
||||
"adm-zip": "^0.5.16",
|
||||
@@ -14,6 +14,7 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"dotenv-expand": "^13.0.0",
|
||||
"express": "^4.21.1",
|
||||
"express-rate-limit": "^8.4.0",
|
||||
"express-validator": "^7.2.0",
|
||||
@@ -1463,6 +1464,33 @@
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-expand": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-13.0.0.tgz",
|
||||
"integrity": "sha512-aBfBS8eYIeXmpHI9ThIlA7/WLq+SLt18iXUZhb52rW89QLKQFoIpPG1bPeewoPZsTyjSSO3T7234FBVUM1V2rA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dotenv": "^17.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-expand/node_modules/dotenv": {
|
||||
"version": "17.4.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
|
||||
"integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"dotenv-expand": "^13.0.0",
|
||||
"express": "^4.21.1",
|
||||
"express-rate-limit": "^8.4.0",
|
||||
"express-validator": "^7.2.0",
|
||||
|
||||
+18
-3
@@ -3,6 +3,7 @@ import cors from 'cors';
|
||||
import helmet from 'helmet';
|
||||
import path from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
import dotenvExpand from 'dotenv-expand';
|
||||
|
||||
// .env-Dateien laden – Root-.env hat Priorität (zentrale Konfiguration für
|
||||
// Dev + Docker), backend/.env als Legacy-Fallback. Im Container sind
|
||||
@@ -10,9 +11,23 @@ import dotenv from 'dotenv';
|
||||
// existierende process.env-Werte nicht.
|
||||
// __dirname zeigt auf src/ (dev via tsx) oder dist/ (build). In beiden Fällen
|
||||
// liegt Root /.env zwei Ebenen darüber.
|
||||
dotenv.config({ path: path.resolve(__dirname, '../../.env') }); // Root /.env
|
||||
dotenv.config({ path: path.resolve(__dirname, '../.env') }); // backend/.env (Fallback)
|
||||
dotenv.config(); // cwd-relativ (Container etc.)
|
||||
//
|
||||
// dotenvExpand löst ${VAR}-Substitution auf, sodass z.B.
|
||||
// DATABASE_URL=mysql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
|
||||
// dynamisch aus den Komponenten zusammengebaut wird (kein Doppel-Pflegen).
|
||||
dotenvExpand.expand(dotenv.config({ path: path.resolve(__dirname, '../../.env') }));
|
||||
dotenvExpand.expand(dotenv.config({ path: path.resolve(__dirname, '../.env') }));
|
||||
dotenvExpand.expand(dotenv.config());
|
||||
|
||||
// Fallback: wenn DATABASE_URL nicht direkt gesetzt ist (oder Substitution
|
||||
// nicht funktioniert hat), aus den DB_*-Komponenten zusammenbauen.
|
||||
if (!process.env.DATABASE_URL && process.env.DB_USER && process.env.DB_PASSWORD && process.env.DB_NAME) {
|
||||
const u = encodeURIComponent(process.env.DB_USER);
|
||||
const p = encodeURIComponent(process.env.DB_PASSWORD);
|
||||
const h = process.env.DB_HOST || 'localhost';
|
||||
const port = process.env.DB_PORT || '3306';
|
||||
process.env.DATABASE_URL = `mysql://${u}:${p}@${h}:${port}/${process.env.DB_NAME}`;
|
||||
}
|
||||
|
||||
import authRoutes from './routes/auth.routes.js';
|
||||
import customerRoutes from './routes/customer.routes.js';
|
||||
|
||||
Reference in New Issue
Block a user