final-cleanup: Produktionsfertige Konfiguration - Alle Ports auf 443 vereinheitlicht, TLS-Zertifikate vorgeneriert, Zentraler Installer erstellt
This commit is contained in:
@@ -1,153 +0,0 @@
|
||||
# MYP Frontend Produktions-Deployment
|
||||
|
||||
## Übersicht
|
||||
|
||||
Das Frontend läuft jetzt auf **Port 80/443** mit **selbstsigniertem Zertifikat** über **Caddy** als Reverse Proxy. Port 3000 wurde komplett entfernt.
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
Internet/LAN → Caddy (Port 80/443) → Next.js Frontend (Port 80) → Backend API (raspberrypi:443)
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Schnellstart
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
./deploy-production.sh
|
||||
```
|
||||
|
||||
### Manuelles Deployment
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
|
||||
# Container stoppen
|
||||
docker-compose -f docker-compose.production.yml down
|
||||
|
||||
# Neu bauen und starten
|
||||
docker-compose -f docker-compose.production.yml up --build -d
|
||||
|
||||
# Status prüfen
|
||||
docker-compose -f docker-compose.production.yml ps
|
||||
|
||||
# Logs anzeigen
|
||||
docker-compose -f docker-compose.production.yml logs -f
|
||||
```
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### SSL-Zertifikate
|
||||
|
||||
- **Automatisch generiert**: Caddy generiert automatisch selbstsignierte Zertifikate
|
||||
- **Speicherort**: `./certs/` (wird automatisch erstellt)
|
||||
- **Konfiguration**: `tls internal` in der Caddyfile
|
||||
|
||||
### Ports
|
||||
|
||||
- **HTTP**: Port 80
|
||||
- **HTTPS**: Port 443
|
||||
- **Frontend intern**: Port 80 (nicht nach außen exponiert)
|
||||
|
||||
### Backend-Verbindung
|
||||
|
||||
- **Backend URL**: `https://raspberrypi:443`
|
||||
- **API Prefix**: `/api/*` wird an Backend weitergeleitet
|
||||
- **Health Check**: `/health` wird an Backend weitergeleitet
|
||||
|
||||
## Dateien
|
||||
|
||||
### Wichtige Konfigurationsdateien
|
||||
|
||||
- `docker-compose.production.yml` - Produktions-Docker-Konfiguration
|
||||
- `docker/caddy/Caddyfile` - Caddy Reverse Proxy Konfiguration
|
||||
- `Dockerfile` - Frontend Container (Port 80)
|
||||
- `next.config.js` - Next.js Konfiguration (SSL entfernt)
|
||||
|
||||
### Verzeichnisstruktur
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── certs/ # SSL-Zertifikate (automatisch generiert)
|
||||
├── docker/
|
||||
│ └── caddy/
|
||||
│ └── Caddyfile # Caddy Konfiguration
|
||||
├── docker-compose.production.yml # Produktions-Deployment
|
||||
├── deploy-production.sh # Deployment-Script
|
||||
├── Dockerfile # Produktions-Container
|
||||
└── next.config.js # Next.js Konfiguration
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container Status prüfen
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.production.yml ps
|
||||
```
|
||||
|
||||
### Logs anzeigen
|
||||
|
||||
```bash
|
||||
# Alle Logs
|
||||
docker-compose -f docker-compose.production.yml logs -f
|
||||
|
||||
# Nur Frontend
|
||||
docker-compose -f docker-compose.production.yml logs -f frontend
|
||||
|
||||
# Nur Caddy
|
||||
docker-compose -f docker-compose.production.yml logs -f caddy
|
||||
```
|
||||
|
||||
### SSL-Zertifikate neu generieren
|
||||
|
||||
```bash
|
||||
# Container stoppen
|
||||
docker-compose -f docker-compose.production.yml down
|
||||
|
||||
# Caddy Daten löschen
|
||||
docker volume rm frontend_caddy_data frontend_caddy_config
|
||||
|
||||
# Neu starten
|
||||
docker-compose -f docker-compose.production.yml up --build -d
|
||||
```
|
||||
|
||||
### Container neu bauen
|
||||
|
||||
```bash
|
||||
# Alles stoppen und entfernen
|
||||
docker-compose -f docker-compose.production.yml down --volumes --remove-orphans
|
||||
|
||||
# Images entfernen
|
||||
docker rmi frontend_frontend frontend_caddy
|
||||
|
||||
# Neu bauen
|
||||
docker-compose -f docker-compose.production.yml up --build -d
|
||||
```
|
||||
|
||||
## Sicherheit
|
||||
|
||||
### HTTPS-Header
|
||||
|
||||
Caddy setzt automatisch sichere HTTP-Header:
|
||||
|
||||
- `Strict-Transport-Security`
|
||||
- `X-Content-Type-Options`
|
||||
- `X-Frame-Options`
|
||||
- `Referrer-Policy`
|
||||
|
||||
### Netzwerk-Isolation
|
||||
|
||||
- Frontend und Caddy laufen in eigenem Docker-Netzwerk
|
||||
- Nur Ports 80 und 443 sind nach außen exponiert
|
||||
- Backend-Verbindung über gesichertes HTTPS
|
||||
|
||||
## Offline-Betrieb
|
||||
|
||||
Das Frontend ist für Offline-Betrieb konfiguriert:
|
||||
|
||||
- Keine externen Dependencies zur Laufzeit
|
||||
- Alle Assets sind im Container enthalten
|
||||
- Selbstsignierte Zertifikate benötigen keine externe CA
|
@@ -1,32 +0,0 @@
|
||||
# MYP - Manage Your Printer
|
||||
|
||||
MYP (Manage Your Printer) ist eine Webanwendung zur Reservierung von 3D-Druckern.
|
||||
Sie wurde im Rahmen des Abschlussprojektes der Fachinformatiker Ausbildung für Daten- und Prozessanalyse für die Technische Berufsausbildung des Mercedes-Benz Werkes Berlin-Marienfelde entwickelt.
|
||||
|
||||
## Deployment
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
- Netzwerk auf Raspberry Pi ist eingerichtet
|
||||
- Docker ist installiert
|
||||
|
||||
### Schritte
|
||||
|
||||
1. Docker-Container bauen (docker/build.sh)
|
||||
2. Docker-Container speichern (docker/save.sh caddy:2.8 myp-rp:latest)
|
||||
3. Docker-Container auf Raspberry Pi bereitstellen (docker/deploy.sh)
|
||||
|
||||
## Entwicklerinformationen
|
||||
|
||||
### Raspberry Pi Einstellungen
|
||||
|
||||
Auf dem Raspberry Pi wurde Raspbian Lite installiert.
|
||||
Unter /srv/* sind die Projektdateien zu finden.
|
||||
|
||||
### Anmeldedaten
|
||||
|
||||
```
|
||||
Benutzer: myp
|
||||
Passwort: (persönlich bekannt)
|
||||
```
|
||||
|
@@ -1,286 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Dieses Skript konfiguriert das Next.js-Frontend, um das selbstsignierte SSL-Zertifikat zu akzeptieren
|
||||
* und die richtigen SSL-Einstellungen im Frontend zu setzen.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
// Pfade definieren
|
||||
const ENV_LOCAL_PATH = path.join(__dirname, '.env.local');
|
||||
const ENV_FRONTEND_PATH = path.join(__dirname, 'env.frontend');
|
||||
const SSL_DIR = path.join(__dirname, 'ssl');
|
||||
const NEXT_CONFIG_PATH = path.join(__dirname, 'next.config.js');
|
||||
|
||||
console.log('=== Frontend-SSL-Konfiguration ===');
|
||||
|
||||
// Verzeichnis erstellen, falls es nicht existiert
|
||||
if (!fs.existsSync(SSL_DIR)) {
|
||||
console.log(`SSL-Verzeichnis wird erstellt: ${SSL_DIR}`);
|
||||
fs.mkdirSync(SSL_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
// Prüfen, ob SSL-Zertifikate existieren
|
||||
if (!fs.existsSync(path.join(SSL_DIR, 'myp.crt')) || !fs.existsSync(path.join(SSL_DIR, 'myp.key'))) {
|
||||
console.log('SSL-Zertifikate nicht gefunden. Prüfe Backend-Verzeichnis...');
|
||||
|
||||
// Versuche, die Zertifikate aus dem Backend zu kopieren
|
||||
const backendCertPath = path.join('/home/user/Projektarbeit-MYP/backend/certs/myp.crt');
|
||||
const backendKeyPath = path.join('/home/user/Projektarbeit-MYP/backend/certs/myp.key');
|
||||
|
||||
if (fs.existsSync(backendCertPath) && fs.existsSync(backendKeyPath)) {
|
||||
console.log('Zertifikate im Backend-Verzeichnis gefunden. Kopiere...');
|
||||
fs.copyFileSync(backendCertPath, path.join(SSL_DIR, 'myp.crt'));
|
||||
fs.copyFileSync(backendKeyPath, path.join(SSL_DIR, 'myp.key'));
|
||||
console.log('Zertifikate erfolgreich in das Frontend-Verzeichnis kopiert.');
|
||||
} else {
|
||||
console.error('SSL-Zertifikate nicht gefunden. Bitte zuerst das Backend-Skript ausführen.');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('SSL-Zertifikate gefunden. Konfiguriere Frontend...');
|
||||
|
||||
// Umgebungsvariablen konfigurieren
|
||||
function updateEnvFile() {
|
||||
try {
|
||||
let envContent;
|
||||
|
||||
// .env.local erstellen oder aktualisieren
|
||||
if (fs.existsSync(ENV_LOCAL_PATH)) {
|
||||
envContent = fs.readFileSync(ENV_LOCAL_PATH, 'utf8');
|
||||
} else if (fs.existsSync(ENV_FRONTEND_PATH)) {
|
||||
envContent = fs.readFileSync(ENV_FRONTEND_PATH, 'utf8');
|
||||
} else {
|
||||
envContent = `# MYP Frontend Umgebungsvariablen\n`;
|
||||
}
|
||||
|
||||
// SSL-Konfigurationen mit alternativen Testoptionen
|
||||
const sslConfigs = [
|
||||
'NODE_TLS_REJECT_UNAUTHORIZED=0',
|
||||
'HTTPS=true',
|
||||
'SSL_CRT_FILE=./ssl/myp.crt',
|
||||
'SSL_KEY_FILE=./ssl/myp.key',
|
||||
'NEXT_PUBLIC_API_URL=https://raspberrypi:443',
|
||||
'NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443',
|
||||
'NEXT_PUBLIC_BACKEND_PROTOCOL=https',
|
||||
|
||||
// Alternative Konfigurationen für Testversuche (auskommentiert)
|
||||
'# Alternative ohne HTTPS',
|
||||
'# HTTPS=false',
|
||||
'# NEXT_PUBLIC_API_URL=http://raspberrypi:80',
|
||||
'# NEXT_PUBLIC_BACKEND_HOST=raspberrypi:80',
|
||||
'# NEXT_PUBLIC_BACKEND_PROTOCOL=http',
|
||||
|
||||
'# Alternative mit IP statt Hostname',
|
||||
'# NEXT_PUBLIC_API_URL=https://192.168.0.105:443',
|
||||
'# NEXT_PUBLIC_BACKEND_HOST=192.168.0.105:443',
|
||||
|
||||
'# Alternative mit localhost',
|
||||
'# NEXT_PUBLIC_API_URL=https://192.168.0.105:5000',
|
||||
'# NEXT_PUBLIC_BACKEND_HOST=192.168.0.105:5000',
|
||||
|
||||
'# Alternative Ports testen',
|
||||
'# NEXT_PUBLIC_API_URL=https://raspberrypi:8443',
|
||||
'# NEXT_PUBLIC_BACKEND_HOST=raspberrypi:8443',
|
||||
'# NEXT_PUBLIC_API_URL=http://raspberrypi:8080',
|
||||
'# NEXT_PUBLIC_BACKEND_HOST=raspberrypi:8080'
|
||||
];
|
||||
|
||||
// Existierende Konfigurationen aktualisieren
|
||||
sslConfigs.forEach(config => {
|
||||
const [key, value] = config.split('=');
|
||||
const regex = new RegExp(`^${key}=.*$`, 'm');
|
||||
|
||||
if (envContent.match(regex)) {
|
||||
// Update existierende Konfiguration
|
||||
envContent = envContent.replace(regex, config);
|
||||
} else {
|
||||
// Neue Konfiguration hinzufügen
|
||||
envContent += `\n${config}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Speichern der aktualisierten Umgebungsvariablen
|
||||
fs.writeFileSync(ENV_LOCAL_PATH, envContent);
|
||||
console.log('.env.local Datei aktualisiert mit SSL-Konfigurationen');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Fehler bei der Aktualisierung der Umgebungsvariablen: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Next.js-Konfiguration aktualisieren
|
||||
function updateNextConfig() {
|
||||
try {
|
||||
let configContent;
|
||||
|
||||
// next.config.js erstellen oder aktualisieren
|
||||
if (fs.existsSync(NEXT_CONFIG_PATH)) {
|
||||
configContent = fs.readFileSync(NEXT_CONFIG_PATH, 'utf8');
|
||||
} else {
|
||||
configContent = `/** @type {import('next').NextConfig} */\n\nconst nextConfig = {}\n\nmodule.exports = nextConfig\n`;
|
||||
}
|
||||
|
||||
// Prüfen, ob bereits eine HTTPS-Konfiguration vorhanden ist
|
||||
if (configContent.includes('serverOptions:') && configContent.includes('https:')) {
|
||||
console.log('HTTPS-Konfiguration ist bereits in der next.config.js vorhanden.');
|
||||
return true;
|
||||
}
|
||||
|
||||
// HTTPS-Konfiguration hinzufügen
|
||||
const httpsConfig = `
|
||||
/** @type {import('next').NextConfig} */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
webpack: (config) => {
|
||||
return config;
|
||||
},
|
||||
// HTTPS-Konfiguration für die Entwicklung
|
||||
devServer: {
|
||||
https: {
|
||||
key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')),
|
||||
cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')),
|
||||
},
|
||||
},
|
||||
// Konfiguration für selbstsignierte Zertifikate
|
||||
serverOptions: {
|
||||
https: {
|
||||
key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')),
|
||||
cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')),
|
||||
},
|
||||
},
|
||||
// Zusätzliche Konfigurationen
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/api/:path*',
|
||||
destination: 'https://raspberrypi:443/api/:path*',
|
||||
},
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
`;
|
||||
|
||||
// Speichern der aktualisierten Next.js-Konfiguration
|
||||
fs.writeFileSync(NEXT_CONFIG_PATH, httpsConfig);
|
||||
console.log('next.config.js Datei aktualisiert mit HTTPS-Konfiguration');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Fehler bei der Aktualisierung der Next.js-Konfiguration: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Update der Fetch-Konfiguration
|
||||
function updateFetchConfig() {
|
||||
try {
|
||||
const fetchConfigPath = path.join(__dirname, 'src', 'utils', 'api-config.ts');
|
||||
|
||||
if (!fs.existsSync(fetchConfigPath)) {
|
||||
console.warn('Datei api-config.ts nicht gefunden. Überspringe Aktualisierung.');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lesen der aktuellen Konfiguration
|
||||
let configContent = fs.readFileSync(fetchConfigPath, 'utf8');
|
||||
|
||||
// Sicherstellen, dass SSL-Verbindungen akzeptiert werden
|
||||
if (!configContent.includes('NODE_TLS_REJECT_UNAUTHORIZED=0')) {
|
||||
// Hinzufügen eines Kommentars zu Beginn der Datei
|
||||
configContent = `// SSL-Verbindungen akzeptieren (selbstsignierte Zertifikate)
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
|
||||
${configContent}`;
|
||||
}
|
||||
|
||||
// Speichern der aktualisierten Fetch-Konfiguration
|
||||
fs.writeFileSync(fetchConfigPath, configContent);
|
||||
console.log('api-config.ts Datei aktualisiert, um selbstsignierte Zertifikate zu akzeptieren');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Fehler bei der Aktualisierung der Fetch-Konfiguration: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Abhängigkeiten installieren
|
||||
function installDependencies() {
|
||||
try {
|
||||
console.log('Installiere benötigte Abhängigkeiten...');
|
||||
execSync('npm install --save-dev https-localhost', { stdio: 'inherit' });
|
||||
console.log('Abhängigkeiten erfolgreich installiert');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Fehler bei der Installation der Abhängigkeiten: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Frontend neu starten
|
||||
function restartFrontend() {
|
||||
try {
|
||||
console.log('Starte Frontend-Server neu...');
|
||||
|
||||
// Prüfen, ob wir uns in Docker befinden
|
||||
if (process.env.CONTAINER) {
|
||||
console.log('Docker-Umgebung erkannt, verwende Docker-Befehle...');
|
||||
execSync('docker-compose restart frontend', { stdio: 'inherit' });
|
||||
} else {
|
||||
console.log('Lokale Umgebung, starte Next.js-Entwicklungsserver neu...');
|
||||
// Stoppe möglicherweise laufende Prozesse
|
||||
try {
|
||||
execSync('npx kill-port 3000', { stdio: 'ignore' });
|
||||
} catch (e) {
|
||||
// Ignorieren, falls kein Prozess läuft
|
||||
}
|
||||
|
||||
// Starte den Entwicklungsserver mit HTTPS
|
||||
console.log('Frontend wird mit HTTPS gestartet. Verwende https://localhost:3000 zum Zugriff.');
|
||||
console.log('Das Frontend wird im Hintergrund gestartet. Verwenden Sie "npm run dev", um es manuell zu starten.');
|
||||
}
|
||||
|
||||
console.log('Frontend-Server erfolgreich konfiguriert.');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Fehler beim Neustart des Frontend-Servers: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Hauptfunktion
|
||||
async function main() {
|
||||
let success = true;
|
||||
|
||||
success = updateEnvFile() && success;
|
||||
success = updateNextConfig() && success;
|
||||
success = updateFetchConfig() && success;
|
||||
success = installDependencies() && success;
|
||||
success = restartFrontend() && success;
|
||||
|
||||
if (success) {
|
||||
console.log('\n=== Konfiguration erfolgreich abgeschlossen ===');
|
||||
console.log('Das Frontend wurde für die Verwendung von HTTPS mit dem selbstsignierten Zertifikat konfiguriert.');
|
||||
console.log('Sie können nun auf das Frontend über https://localhost:3000 zugreifen.');
|
||||
console.log('Bei Sicherheitswarnungen im Browser können Sie das Zertifikat manuell akzeptieren.');
|
||||
} else {
|
||||
console.error('\n=== Konfiguration nicht vollständig abgeschlossen ===');
|
||||
console.error('Es gab Probleme bei der Konfiguration des Frontends.');
|
||||
console.error('Bitte überprüfen Sie die Fehlermeldungen und versuchen Sie es erneut.');
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführen der Hauptfunktion
|
||||
main().catch(error => {
|
||||
console.error(`Unerwarteter Fehler: ${error.message}`);
|
||||
process.exit(1);
|
||||
});
|
@@ -10,7 +10,7 @@ const PORT = process.env.PORT || 8081;
|
||||
|
||||
// Konfigurationsdatei
|
||||
const CONFIG_FILE = path.join(__dirname, '../../../.env.local');
|
||||
const DEFAULT_BACKEND_URL = 'http://192.168.0.105:5000';
|
||||
const DEFAULT_BACKEND_URL = 'https://raspberrypi';
|
||||
|
||||
// Middleware
|
||||
app.use(express.json());
|
||||
|
@@ -1,62 +0,0 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
# Next.js Frontend
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: myp-frontend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_API_URL=https://raspberrypi:443
|
||||
- NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443
|
||||
- PORT=80
|
||||
volumes:
|
||||
- ./certs:/app/certs
|
||||
ports:
|
||||
- "80"
|
||||
networks:
|
||||
- myp-network
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "http://localhost:80/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# Caddy Proxy für SSL-Terminierung
|
||||
caddy:
|
||||
image: caddy:2.7-alpine
|
||||
container_name: myp-caddy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./certs:/etc/caddy/certs
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
networks:
|
||||
- myp-network
|
||||
depends_on:
|
||||
- frontend
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "raspberrypi:192.168.0.105"
|
||||
- "m040tbaraspi001.de040.corpintra.net:127.0.0.1"
|
||||
environment:
|
||||
- CADDY_HOST=m040tbaraspi001.de040.corpintra.net
|
||||
- CADDY_DOMAIN=m040tbaraspi001.de040.corpintra.net
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
||||
networks:
|
||||
myp-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
@@ -1,5 +1,5 @@
|
||||
# 🎨 MYP Frontend - Entwicklungsumgebung Konfiguration
|
||||
# Frontend-Service für die Entwicklung mit Raspberry Pi Backend
|
||||
# 🎨 MYP Frontend - Produktionsumgebung Konfiguration
|
||||
# Frontend-Service für die Produktion mit Raspberry Pi Backend
|
||||
|
||||
version: '3.8'
|
||||
|
||||
@@ -8,152 +8,64 @@ services:
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- BUILDKIT_INLINE_CACHE=1
|
||||
- NODE_ENV=development
|
||||
image: myp/frontend:dev
|
||||
container_name: myp-frontend-dev
|
||||
dockerfile: Dockerfile
|
||||
container_name: myp-frontend
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
# Backend API Konfiguration (Raspberry Pi)
|
||||
- NEXT_PUBLIC_API_URL=http://192.168.0.105:5000
|
||||
- NEXT_PUBLIC_BACKEND_HOST=192.168.0.105:5000
|
||||
|
||||
# Frontend Server
|
||||
- PORT=3000
|
||||
- HOSTNAME=0.0.0.0
|
||||
|
||||
# Auth Konfiguration (Entwicklung)
|
||||
- NEXTAUTH_URL=http://localhost:3000
|
||||
- NEXTAUTH_SECRET=dev-frontend-auth-secret
|
||||
|
||||
# Debug-Einstellungen
|
||||
- DEBUG=true
|
||||
- NEXT_DEBUG=true
|
||||
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_API_URL=https://raspberrypi
|
||||
- NEXT_PUBLIC_BACKEND_HOST=raspberrypi
|
||||
- NEXT_PUBLIC_FRONTEND_URL=https://m040tbaraspi001.de040.corpintra.net
|
||||
- NEXTAUTH_URL=https://m040tbaraspi001.de040.corpintra.net
|
||||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-myp-secret-key-2024}
|
||||
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
|
||||
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET}
|
||||
- NEXT_PUBLIC_OAUTH_CALLBACK_URL=https://m040tbaraspi001.de040.corpintra.net/auth/login/callback
|
||||
volumes:
|
||||
- .:/app
|
||||
- /app/node_modules
|
||||
- /app/.next
|
||||
- ./public:/app/public:ro
|
||||
|
||||
- ./certs:/app/certs
|
||||
ports:
|
||||
- "3000:3000" # Direkter Port-Zugang für Frontend-Server
|
||||
|
||||
networks:
|
||||
- frontend-network
|
||||
|
||||
extra_hosts:
|
||||
- "raspberrypi:192.168.0.105"
|
||||
|
||||
- myp-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
labels:
|
||||
- "service.type=frontend"
|
||||
- "service.name=myp-frontend-dev"
|
||||
- "service.environment=development"
|
||||
|
||||
# === FRONTEND CACHE (Optional: Redis für Session Management) ===
|
||||
frontend-cache:
|
||||
image: redis:7.2-alpine
|
||||
container_name: myp-frontend-cache
|
||||
# === CADDY PROXY ===
|
||||
caddy:
|
||||
image: caddy:2-alpine
|
||||
container_name: myp-caddy
|
||||
restart: unless-stopped
|
||||
|
||||
command: redis-server --appendonly yes --requirepass ${FRONTEND_REDIS_PASSWORD:-frontend_cache_password}
|
||||
|
||||
volumes:
|
||||
- frontend_redis_data:/data
|
||||
|
||||
ports:
|
||||
- "6380:6379" # Separater Port vom Backend-Cache
|
||||
|
||||
networks:
|
||||
- frontend-network
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
# === FRONTEND CDN/NGINX (Statische Assets) ===
|
||||
frontend-cdn:
|
||||
image: nginx:alpine
|
||||
container_name: myp-frontend-cdn
|
||||
restart: unless-stopped
|
||||
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./public:/usr/share/nginx/html/static:ro
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- frontend_cdn_cache:/var/cache/nginx
|
||||
|
||||
ports:
|
||||
- "8080:80" # Separater Port für statische Assets
|
||||
|
||||
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./certs:/etc/ssl/certs/myp
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
networks:
|
||||
- frontend-network
|
||||
|
||||
- myp-network
|
||||
depends_on:
|
||||
- frontend
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
labels:
|
||||
- "service.type=cdn"
|
||||
- "service.name=myp-frontend-cdn"
|
||||
environment:
|
||||
- CADDY_INGRESS_NETWORKS=myp-network
|
||||
|
||||
# === PERSISTENTE VOLUMES ===
|
||||
volumes:
|
||||
frontend_data:
|
||||
caddy_data:
|
||||
driver: local
|
||||
|
||||
frontend_cache:
|
||||
driver: local
|
||||
|
||||
frontend_redis_data:
|
||||
driver: local
|
||||
|
||||
frontend_cdn_cache:
|
||||
caddy_config:
|
||||
driver: local
|
||||
|
||||
# === FRONTEND-NETZWERK ===
|
||||
# === NETZWERK ===
|
||||
networks:
|
||||
frontend-network:
|
||||
myp-network:
|
||||
driver: bridge
|
||||
driver_opts:
|
||||
com.docker.network.enable_ipv6: "false"
|
||||
com.docker.network.bridge.enable_ip_masquerade: "true"
|
||||
labels:
|
||||
- "description=MYP Frontend Server Netzwerk"
|
||||
- "description=MYP Production Network"
|
||||
- "project=myp-frontend"
|
||||
- "tier=frontend"
|
||||
|
||||
# === KONFIGURATION FÜR FRONTEND ===
|
||||
x-frontend-defaults: &frontend-defaults
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
labels: "service,environment,tier"
|
||||
|
||||
x-healthcheck-frontend: &frontend-healthcheck
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
- "tier=production"
|
@@ -1,62 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Next.js Frontend
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: myp-frontend-prod
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_API_URL=https://raspberrypi:443
|
||||
- NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443
|
||||
- PORT=80
|
||||
volumes:
|
||||
- ./certs:/app/certs
|
||||
- frontend_data:/usr/src/app/db
|
||||
networks:
|
||||
- myp-network
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "http://localhost:80/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# Caddy Proxy für SSL-Terminierung
|
||||
caddy:
|
||||
image: caddy:2.7-alpine
|
||||
container_name: myp-caddy-prod
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./certs:/etc/caddy/certs
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
networks:
|
||||
- myp-network
|
||||
depends_on:
|
||||
- frontend
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "raspberrypi:192.168.0.105"
|
||||
- "m040tbaraspi001.de040.corpintra.net:127.0.0.1"
|
||||
environment:
|
||||
- CADDY_HOST=m040tbaraspi001.de040.corpintra.net
|
||||
- CADDY_DOMAIN=m040tbaraspi001.de040.corpintra.net
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
||||
networks:
|
||||
myp-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
frontend_data:
|
@@ -1,62 +1,49 @@
|
||||
version: '3'
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Next.js Frontend
|
||||
frontend:
|
||||
frontend-app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: myp-frontend
|
||||
restart: unless-stopped
|
||||
container_name: myp-frontend-app
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_API_URL=https://raspberrypi:443
|
||||
- NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443
|
||||
- PORT=80
|
||||
volumes:
|
||||
- ./certs:/app/certs
|
||||
ports:
|
||||
- "80"
|
||||
- NEXT_PUBLIC_API_URL=https://raspberrypi
|
||||
- HOSTNAME=m040tbaraspi001.de040.corpintra.net
|
||||
networks:
|
||||
- myp-network
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "http://localhost:80/health"]
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# Caddy Proxy für SSL-Terminierung
|
||||
caddy:
|
||||
image: caddy:2.7-alpine
|
||||
image: caddy:2-alpine
|
||||
container_name: myp-caddy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./certs:/etc/caddy/certs
|
||||
- ./certs:/etc/ssl/certs/myp
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
networks:
|
||||
- myp-network
|
||||
depends_on:
|
||||
- frontend
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "raspberrypi:192.168.0.105"
|
||||
- "m040tbaraspi001.de040.corpintra.net:127.0.0.1"
|
||||
- frontend-app
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- CADDY_HOST=m040tbaraspi001.de040.corpintra.net
|
||||
- CADDY_DOMAIN=m040tbaraspi001.de040.corpintra.net
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
||||
networks:
|
||||
myp-network:
|
||||
driver: bridge
|
||||
- CADDY_INGRESS_NETWORKS=myp-network
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
caddy_config:
|
||||
|
||||
networks:
|
||||
myp-network:
|
||||
driver: bridge
|
@@ -1,76 +1,36 @@
|
||||
{
|
||||
debug
|
||||
auto_https off
|
||||
local_certs
|
||||
# HTTP to HTTPS redirect
|
||||
:80 {
|
||||
redir https://{host}{uri} permanent
|
||||
}
|
||||
|
||||
# Produktionsumgebung - Frontend auf Port 80/443 mit selbstsigniertem Zertifikat
|
||||
:80, :443 {
|
||||
# TLS mit automatisch generierten selbstsignierten Zertifikaten
|
||||
tls internal {
|
||||
on_demand
|
||||
}
|
||||
|
||||
# API Anfragen zum Backend (Raspberry Pi) weiterleiten
|
||||
@api {
|
||||
path /api/* /health
|
||||
}
|
||||
handle @api {
|
||||
uri strip_prefix /api
|
||||
reverse_proxy raspberrypi:443 {
|
||||
transport http {
|
||||
tls
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
header_up Host {upstream_hostport}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# Alle anderen Anfragen zum Frontend weiterleiten (auf Port 80 intern)
|
||||
handle {
|
||||
reverse_proxy frontend:80 {
|
||||
header_up Host {upstream_hostport}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# OAuth Callbacks
|
||||
@oauth path /auth/login/callback*
|
||||
handle @oauth {
|
||||
header Cache-Control "no-cache"
|
||||
reverse_proxy frontend:80
|
||||
}
|
||||
# HTTPS Frontend
|
||||
m040tbaraspi001.de040.corpintra.net:443 {
|
||||
# TLS configuration with custom certificates
|
||||
tls /etc/ssl/certs/myp/frontend.crt /etc/ssl/certs/myp/frontend.key
|
||||
|
||||
# Produktions-Header
|
||||
# Security headers
|
||||
header {
|
||||
# Enable HSTS
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
# XSS Protection
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
X-Frame-Options "DENY"
|
||||
X-XSS-Protection "1; mode=block"
|
||||
# CSP
|
||||
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://raspberrypi;"
|
||||
# Remove server header
|
||||
-Server
|
||||
}
|
||||
}
|
||||
|
||||
# Spezifische Hostname-Konfiguration für Mercedes-Benz Werk 040 Berlin (falls benötigt)
|
||||
m040tbaraspi001.de040.corpintra.net {
|
||||
# TLS mit automatisch generierten selbstsignierten Zertifikaten
|
||||
tls internal {
|
||||
on_demand
|
||||
|
||||
# Health check endpoint
|
||||
handle /health {
|
||||
respond "OK" 200
|
||||
}
|
||||
|
||||
# API Anfragen zum Backend (Raspberry Pi) weiterleiten
|
||||
@api {
|
||||
path /api/* /health
|
||||
}
|
||||
handle @api {
|
||||
uri strip_prefix /api
|
||||
reverse_proxy raspberrypi:443 {
|
||||
|
||||
# API proxy to backend
|
||||
handle /api/* {
|
||||
reverse_proxy https://raspberrypi {
|
||||
transport http {
|
||||
tls
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
header_up Host {upstream_hostport}
|
||||
@@ -79,85 +39,27 @@ m040tbaraspi001.de040.corpintra.net {
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# Alle anderen Anfragen zum Frontend weiterleiten
|
||||
handle {
|
||||
reverse_proxy frontend:80 {
|
||||
header_up Host {upstream_hostport}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# OAuth Callbacks
|
||||
@oauth path /auth/login/callback*
|
||||
handle @oauth {
|
||||
header Cache-Control "no-cache"
|
||||
reverse_proxy frontend:80
|
||||
|
||||
# Frontend application
|
||||
reverse_proxy frontend-app:3000 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
|
||||
# Produktions-Header
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
# Logging
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
format json
|
||||
}
|
||||
|
||||
# Enable compression
|
||||
encode gzip
|
||||
}
|
||||
|
||||
# Entwicklungsumgebung - Localhost und Raspberry Pi Backend (weiterhin für lokale Entwicklung verfügbar)
|
||||
localhost, 127.0.0.1 {
|
||||
# API Anfragen zum Raspberry Pi Backend weiterleiten
|
||||
@api {
|
||||
path /api/* /health
|
||||
}
|
||||
handle @api {
|
||||
uri strip_prefix /api
|
||||
reverse_proxy raspberrypi:443 {
|
||||
transport http {
|
||||
tls
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
header_up Host {upstream_hostport}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# Alle anderen Anfragen zum Frontend weiterleiten
|
||||
handle {
|
||||
reverse_proxy myp-rp-dev:3000 {
|
||||
header_up Host {upstream_hostport}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# TLS für lokale Entwicklung
|
||||
tls /etc/caddy/ssl/frontend.crt /etc/caddy/ssl/frontend.key
|
||||
|
||||
# OAuth Callbacks für Entwicklung
|
||||
@oauth path /auth/login/callback*
|
||||
handle @oauth {
|
||||
header Cache-Control "no-cache"
|
||||
reverse_proxy myp-rp-dev:3000
|
||||
}
|
||||
|
||||
# Entwicklungsfreundliche Header
|
||||
header {
|
||||
# Weniger restriktive Sicherheitsheader für Entwicklung
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
|
||||
# Keine Caches für Entwicklung
|
||||
Cache-Control "no-store, no-cache, must-revalidate"
|
||||
|
||||
# CORS für Entwicklung
|
||||
Access-Control-Allow-Origin "*"
|
||||
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
||||
Access-Control-Allow-Headers "Content-Type, Authorization"
|
||||
}
|
||||
}
|
||||
# Fallback for direct IP access
|
||||
192.168.0.109:443 {
|
||||
tls /etc/ssl/certs/myp/frontend.crt /etc/ssl/certs/myp/frontend.key
|
||||
redir https://m040tbaraspi001.de040.corpintra.net{uri} permanent
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2.8
|
||||
container_name: caddy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- ./caddy/data:/data
|
||||
- ./caddy/config:/config
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
myp-rp:
|
||||
image: myp-rp:latest
|
||||
container_name: myp-rp
|
||||
environment:
|
||||
- NEXT_PUBLIC_API_URL=http://192.168.0.105:5000
|
||||
- OAUTH_CLIENT_ID=client_id
|
||||
- OAUTH_CLIENT_SECRET=client_secret
|
||||
env_file: "/srv/myp-env/github.env"
|
||||
volumes:
|
||||
- /srv/MYP-DB:/usr/src/app/db
|
||||
restart: unless-stopped
|
||||
# Füge Healthcheck hinzu für besseres Monitoring
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
// Prüfe Backend-Verbindung
|
||||
const backendUrl = process.env.NEXT_PUBLIC_API_URL || 'http://192.168.0.105:5000';
|
||||
const backendUrl = process.env.NEXT_PUBLIC_API_URL || 'https://raspberrypi';
|
||||
let backendStatus = 'unknown';
|
||||
|
||||
try {
|
||||
|
@@ -16,31 +16,16 @@ const getApiBaseUrl = () => {
|
||||
|
||||
// Verbindungsoptionen in Prioritätsreihenfolge
|
||||
return {
|
||||
primary: `https://${hostname}:443`,
|
||||
primary: `https://${hostname}`,
|
||||
fallbacks: [
|
||||
`http://${hostname}:443`,
|
||||
`https://${hostname}:80`,
|
||||
`http://${hostname}:80`,
|
||||
`https://${hostname}:5000`,
|
||||
`http://${hostname}:5000`,
|
||||
`https://raspberrypi:443`,
|
||||
`http://raspberrypi:443`,
|
||||
`https://raspberrypi:80`,
|
||||
`http://raspberrypi:80`,
|
||||
`https://raspberrypi:5000`,
|
||||
`http://raspberrypi:5000`,
|
||||
`https://192.168.0.105:443`,
|
||||
`http://192.168.0.105:443`,
|
||||
`https://192.168.0.105:80`,
|
||||
`http://192.168.0.105:80`,
|
||||
`https://192.168.0.105:5000`,
|
||||
`http://192.168.0.105:5000`,
|
||||
`https://raspberrypi`,
|
||||
`https://192.168.0.105`,
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
// Standardwert für serverseitiges Rendering
|
||||
return `https://raspberrypi:443`;
|
||||
return `https://raspberrypi`;
|
||||
};
|
||||
|
||||
export const API_BASE_URL = getApiBaseUrl();
|
||||
@@ -63,8 +48,8 @@ const getFrontendUrl = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Priorität 3: Default für Localhost
|
||||
return "https://localhost:3000";
|
||||
// Priorität 3: Default für Localhost (development)
|
||||
return "https://m040tbaraspi001.de040.corpintra.net";
|
||||
};
|
||||
|
||||
export const FRONTEND_URL = getFrontendUrl();
|
||||
|
@@ -1,179 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Hilfsskript zur Aktualisierung der OAuth-Konfiguration im MYP-Frontend
|
||||
*
|
||||
* Dieses Skript wird automatisch beim Build ausgeführt, um sicherzustellen,
|
||||
* dass die OAuth-Konfiguration korrekt ist.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Pfad zur OAuth-Konfiguration und Routes
|
||||
const callbackRoutePath = path.join(__dirname, 'src/app/auth/login/callback/route.ts');
|
||||
const loginRoutePath = path.join(__dirname, 'src/app/auth/login/route.ts');
|
||||
const oauthConfigPath = path.join(__dirname, 'src/server/auth/oauth.ts');
|
||||
|
||||
// Aktualisiere die OAuth-Konfiguration
|
||||
try {
|
||||
// 1. Prüfe, ob wir die USED_CALLBACK_URL exportieren müssen
|
||||
let oauthContent = fs.readFileSync(oauthConfigPath, 'utf8');
|
||||
|
||||
if (!oauthContent.includes('export const USED_CALLBACK_URL')) {
|
||||
console.log('✅ Aktualisiere OAuth-Konfiguration...');
|
||||
|
||||
// Füge die USED_CALLBACK_URL-Export hinzu
|
||||
oauthContent = oauthContent.replace(
|
||||
'// Erstelle GitHub OAuth-Client mit expliziter Redirect-URI',
|
||||
'// Berechne die Callback-URL\nexport const USED_CALLBACK_URL = getCallbackUrl();\n\n// Erstelle GitHub OAuth-Client mit expliziter Redirect-URI'
|
||||
);
|
||||
|
||||
// Schreibe die aktualisierte Datei
|
||||
fs.writeFileSync(oauthConfigPath, oauthContent, 'utf8');
|
||||
console.log('✅ OAuth-Konfiguration erfolgreich aktualisiert.');
|
||||
} else {
|
||||
console.log('ℹ️ OAuth-Konfiguration ist bereits aktuell.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Aktualisieren der OAuth-Konfiguration:', error);
|
||||
}
|
||||
|
||||
// Aktualisiere die OAuth-Callback-Route
|
||||
try {
|
||||
let callbackContent = fs.readFileSync(callbackRoutePath, 'utf8');
|
||||
|
||||
// Prüfe, ob Änderungen nötig sind
|
||||
const needsUpdate =
|
||||
callbackContent.includes('await github.validateAuthorizationCode(code, OAUTH_CALLBACK_URL)') ||
|
||||
!callbackContent.includes('USED_CALLBACK_URL');
|
||||
|
||||
if (needsUpdate) {
|
||||
console.log('✅ Aktualisiere OAuth-Callback-Route...');
|
||||
|
||||
// 1. Aktualisiere den Import
|
||||
if (!callbackContent.includes('USED_CALLBACK_URL')) {
|
||||
callbackContent = callbackContent.replace(
|
||||
'import { type GitHubUserResult, github, isValidCallbackHost } from "@/server/auth/oauth";',
|
||||
'import { type GitHubUserResult, github, isValidCallbackHost, USED_CALLBACK_URL } from "@/server/auth/oauth";'
|
||||
);
|
||||
|
||||
// Entferne den OAUTH_CALLBACK_URL-Import, wenn er nicht mehr benötigt wird
|
||||
if (callbackContent.includes('OAUTH_CALLBACK_URL')) {
|
||||
callbackContent = callbackContent.replace(
|
||||
', OAUTH_CALLBACK_URL } from "@/utils/api-config"',
|
||||
' } from "@/utils/api-config"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Korrigiere die validateAuthorizationCode-Funktion
|
||||
if (callbackContent.includes('await github.validateAuthorizationCode(code, OAUTH_CALLBACK_URL)')) {
|
||||
callbackContent = callbackContent.replace(
|
||||
'await github.validateAuthorizationCode(code, OAUTH_CALLBACK_URL)',
|
||||
'await github.validateAuthorizationCode(code)'
|
||||
);
|
||||
}
|
||||
|
||||
// 3. Aktualisiere die Logging-Nachricht
|
||||
if (callbackContent.includes('console.log(`GitHub OAuth Token-Validierung mit Callback-URL: ${OAUTH_CALLBACK_URL}`)')) {
|
||||
callbackContent = callbackContent.replace(
|
||||
'console.log(`GitHub OAuth Token-Validierung mit Callback-URL: ${OAUTH_CALLBACK_URL}`)',
|
||||
'console.log(`GitHub OAuth Token-Validierung erfolgreich, verwendete Callback-URL: ${USED_CALLBACK_URL}`)'
|
||||
);
|
||||
} else if (callbackContent.includes('console.log("GitHub OAuth Token-Validierung erfolgreich")')) {
|
||||
callbackContent = callbackContent.replace(
|
||||
'console.log("GitHub OAuth Token-Validierung erfolgreich")',
|
||||
'console.log(`GitHub OAuth Token-Validierung erfolgreich, verwendete Callback-URL: ${USED_CALLBACK_URL}`)'
|
||||
);
|
||||
}
|
||||
|
||||
// Schreibe die aktualisierte Datei
|
||||
fs.writeFileSync(callbackRoutePath, callbackContent, 'utf8');
|
||||
console.log('✅ OAuth-Callback-Route erfolgreich aktualisiert.');
|
||||
} else {
|
||||
console.log('ℹ️ OAuth-Callback-Route ist bereits aktuell.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Aktualisieren der OAuth-Callback-Route:', error);
|
||||
}
|
||||
|
||||
// Package.json aktualisieren, um das Skript vor dem Build auszuführen
|
||||
try {
|
||||
const packageJsonPath = path.join(__dirname, 'package.json');
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||
|
||||
// Prüfe, ob das Skript bereits in den Build-Prozess integriert ist
|
||||
if (packageJson.scripts.build === 'next build') {
|
||||
console.log('✅ Aktualisiere package.json...');
|
||||
|
||||
// Füge das Skript zum Build-Prozess hinzu
|
||||
packageJson.scripts.build = 'node update-package.js && next build';
|
||||
|
||||
// Schreibe die aktualisierte package.json
|
||||
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
|
||||
console.log('✅ package.json erfolgreich aktualisiert.');
|
||||
} else {
|
||||
console.log('ℹ️ package.json ist bereits aktualisiert.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Aktualisieren der package.json:', error);
|
||||
}
|
||||
|
||||
// Aktualisiere die Login-Route
|
||||
try {
|
||||
let loginContent = fs.readFileSync(loginRoutePath, 'utf8');
|
||||
|
||||
// Prüfe, ob Änderungen nötig sind
|
||||
const loginNeedsUpdate =
|
||||
loginContent.includes('redirectURI: OAUTH_CALLBACK_URL') ||
|
||||
!loginContent.includes('USED_CALLBACK_URL');
|
||||
|
||||
if (loginNeedsUpdate) {
|
||||
console.log('✅ Aktualisiere OAuth-Login-Route...');
|
||||
|
||||
// 1. Aktualisiere den Import
|
||||
if (!loginContent.includes('USED_CALLBACK_URL')) {
|
||||
if (loginContent.includes('import { github } from "@/server/auth/oauth";')) {
|
||||
loginContent = loginContent.replace(
|
||||
'import { github } from "@/server/auth/oauth";',
|
||||
'import { github, USED_CALLBACK_URL } from "@/server/auth/oauth";'
|
||||
);
|
||||
}
|
||||
|
||||
// Entferne den OAUTH_CALLBACK_URL-Import
|
||||
if (loginContent.includes('import { OAUTH_CALLBACK_URL } from "@/utils/api-config";')) {
|
||||
loginContent = loginContent.replace(
|
||||
'import { OAUTH_CALLBACK_URL } from "@/utils/api-config";',
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Korrigiere die createAuthorizationURL-Funktion
|
||||
if (loginContent.includes('redirectURI: OAUTH_CALLBACK_URL')) {
|
||||
loginContent = loginContent.replace(
|
||||
/const url = await github\.createAuthorizationURL\(state, \{\s*scopes: \["user"\],\s*redirectURI: OAUTH_CALLBACK_URL,\s*\}\);/s,
|
||||
'const url = await github.createAuthorizationURL(state, {\n\t\tscopes: ["user"],\n\t});'
|
||||
);
|
||||
}
|
||||
|
||||
// 3. Aktualisiere die Logging-Nachricht
|
||||
if (loginContent.includes('console.log(`Verwendete Callback-URL: ${OAUTH_CALLBACK_URL}`')) {
|
||||
loginContent = loginContent.replace(
|
||||
'console.log(`Verwendete Callback-URL: ${OAUTH_CALLBACK_URL}`',
|
||||
'console.log(`Verwendete Callback-URL: ${USED_CALLBACK_URL}`'
|
||||
);
|
||||
}
|
||||
|
||||
// Schreibe die aktualisierte Datei
|
||||
fs.writeFileSync(loginRoutePath, loginContent, 'utf8');
|
||||
console.log('✅ OAuth-Login-Route erfolgreich aktualisiert.');
|
||||
} else {
|
||||
console.log('ℹ️ OAuth-Login-Route ist bereits aktuell.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Aktualisieren der OAuth-Login-Route:', error);
|
||||
}
|
||||
|
||||
console.log('✅ OAuth-Konfiguration wurde erfolgreich vorbereitet.');
|
Reference in New Issue
Block a user