537 lines
19 KiB
Bash
537 lines
19 KiB
Bash
#!/bin/bash
|
|
|
|
# SSL-Konfiguration für MYP-Plattform (Linux/Raspberry Pi)
|
|
|
|
# Farbdefinitionen
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Titel anzeigen
|
|
echo -e "${CYAN}===================================================="
|
|
echo -e " SSL-Konfiguration für MYP-Plattform"
|
|
echo -e "====================================================${NC}"
|
|
echo ""
|
|
|
|
# Prüfen, ob das Skript mit Root-Rechten ausgeführt wird
|
|
if [ "$EUID" -ne 0 ]; then
|
|
echo -e "${YELLOW}WARNUNG: Dieses Skript sollte mit Root-Rechten ausgeführt werden, um Zertifikate im System zu installieren.${NC}"
|
|
echo -e "${YELLOW}Einige Funktionen sind möglicherweise eingeschränkt.${NC}"
|
|
echo ""
|
|
|
|
read -p "Möchten Sie trotzdem fortfahren? (j/n): " continue_anyway
|
|
if [ "$continue_anyway" != "j" ]; then
|
|
echo -e "${RED}Installation abgebrochen.${NC}"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Funktion zum Ausführen von Befehlen mit Ausgabe
|
|
exec_command() {
|
|
command="$1"
|
|
description="$2"
|
|
|
|
echo -e "${YELLOW}> $description...${NC}"
|
|
eval $command
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo -e "${GREEN}✓ Erfolgreich abgeschlossen!${NC}"
|
|
return 0
|
|
else
|
|
echo -e "${RED}✗ Fehler beim Ausführen des Befehls. Exit-Code: $?${NC}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Prüfen, ob Python und pip installiert sind
|
|
if ! command -v python3 &> /dev/null; then
|
|
echo -e "${RED}✗ Python 3 ist nicht installiert. Bitte installieren Sie Python 3.6 oder höher.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v pip3 &> /dev/null; then
|
|
echo -e "${RED}✗ pip3 ist nicht installiert. Bitte installieren Sie pip3.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# 1. Prüfen, ob die notwendigen Abhängigkeiten installiert sind
|
|
echo -e "${CYAN}1. Prüfe Abhängigkeiten...${NC}"
|
|
|
|
# Python-Abhängigkeiten prüfen
|
|
cryptography_installed=$(python3 -c "try: import cryptography; print('True'); except ImportError: print('False')" 2>/dev/null)
|
|
if [ "$cryptography_installed" != "True" ]; then
|
|
echo "Installiere Python-Abhängigkeit 'cryptography'..."
|
|
exec_command "pip3 install cryptography" "Installiere cryptography-Paket"
|
|
fi
|
|
|
|
# 2. SSL-Zertifikat generieren
|
|
echo ""
|
|
echo -e "${CYAN}2. Generiere SSL-Zertifikat...${NC}"
|
|
|
|
# SSL-Verzeichnisse erstellen
|
|
mkdir -p backend/app/instance/ssl
|
|
mkdir -p frontend/ssl
|
|
|
|
# Python-Skript erstellen, falls nicht vorhanden
|
|
if [ ! -f backend/generate_ssl_cert.py ]; then
|
|
echo "SSL-Zertifikatsgenerator nicht gefunden. Erstelle..."
|
|
|
|
cat > backend/generate_ssl_cert.py << 'EOF'
|
|
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import datetime
|
|
from cryptography import x509
|
|
from cryptography.x509.oid import NameOID
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
|
|
|
|
def generate_ssl_certificate():
|
|
"""
|
|
Generiert ein verbessertes SSL-Zertifikat für die MYP-Anwendung
|
|
mit korrekten Metadaten und alternativen Namen.
|
|
"""
|
|
print("Generiere verbessertes SSL-Zertifikat für die MYP-Anwendung...")
|
|
|
|
# Verzeichnispfade definieren
|
|
ssl_dir = "app/instance/ssl"
|
|
ssl_cert_path = os.path.join(ssl_dir, "myp.crt")
|
|
ssl_key_path = os.path.join(ssl_dir, "myp.key")
|
|
|
|
# Verzeichnis erstellen, falls es nicht existiert
|
|
os.makedirs(ssl_dir, exist_ok=True)
|
|
|
|
try:
|
|
# Privaten Schlüssel mit 4096 Bit generieren (sicherer)
|
|
private_key = rsa.generate_private_key(
|
|
public_exponent=65537,
|
|
key_size=4096,
|
|
)
|
|
|
|
# Aktuelles Datum und Ablaufdatum (1 Jahr gültig)
|
|
now = datetime.datetime.now()
|
|
valid_until = now + datetime.timedelta(days=365)
|
|
|
|
# Liste aller möglichen Hostnamen/IPs
|
|
hostnames = [
|
|
"localhost",
|
|
"raspberrypi",
|
|
"m040tbaraspi001",
|
|
"m040tbaraspi001.de040.corpintra.net"
|
|
]
|
|
|
|
# IP-Adressen (als String, werden später konvertiert)
|
|
ip_addresses = [
|
|
"127.0.0.1",
|
|
"192.168.0.105"
|
|
]
|
|
|
|
# Erweiterte Zertifikatsattribute
|
|
subject = issuer = x509.Name([
|
|
x509.NameAttribute(NameOID.COMMON_NAME, "raspberrypi"),
|
|
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Mercedes-Benz AG"),
|
|
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Werk 040 Berlin"),
|
|
x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"),
|
|
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"),
|
|
x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin")
|
|
])
|
|
|
|
# Subject Alternative Names (SAN) erstellen
|
|
san_list = []
|
|
for hostname in hostnames:
|
|
san_list.append(x509.DNSName(hostname))
|
|
|
|
# IP-Adressen hinzufügen
|
|
import socket
|
|
for ip in ip_addresses:
|
|
san_list.append(x509.IPAddress(socket.inet_aton(ip)))
|
|
|
|
# Zertifikat erstellen
|
|
cert = x509.CertificateBuilder().subject_name(
|
|
subject
|
|
).issuer_name(
|
|
issuer
|
|
).public_key(
|
|
private_key.public_key()
|
|
).serial_number(
|
|
x509.random_serial_number()
|
|
).not_valid_before(
|
|
now
|
|
).not_valid_after(
|
|
valid_until
|
|
).add_extension(
|
|
x509.SubjectAlternativeName(san_list),
|
|
critical=False,
|
|
).add_extension(
|
|
x509.BasicConstraints(ca=True, path_length=None), critical=True
|
|
).add_extension(
|
|
x509.KeyUsage(
|
|
digital_signature=True,
|
|
content_commitment=False,
|
|
key_encipherment=True,
|
|
data_encipherment=False,
|
|
key_agreement=False,
|
|
key_cert_sign=True,
|
|
crl_sign=True,
|
|
encipher_only=False,
|
|
decipher_only=False
|
|
), critical=True
|
|
).add_extension(
|
|
x509.ExtendedKeyUsage([
|
|
x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
|
|
x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH
|
|
]), critical=False
|
|
).sign(private_key, hashes.SHA256())
|
|
|
|
# Zertifikat und Schlüssel speichern
|
|
with open(ssl_key_path, "wb") as f:
|
|
f.write(private_key.private_bytes(
|
|
encoding=Encoding.PEM,
|
|
format=PrivateFormat.TraditionalOpenSSL,
|
|
encryption_algorithm=NoEncryption()
|
|
))
|
|
|
|
with open(ssl_cert_path, "wb") as f:
|
|
f.write(cert.public_bytes(Encoding.PEM))
|
|
|
|
# Kopieren des Zertifikats in das Frontend-Verzeichnis
|
|
frontend_ssl_dir = "../frontend/ssl"
|
|
os.makedirs(frontend_ssl_dir, exist_ok=True)
|
|
|
|
import shutil
|
|
shutil.copy2(ssl_cert_path, os.path.join(frontend_ssl_dir, "myp.crt"))
|
|
shutil.copy2(ssl_key_path, os.path.join(frontend_ssl_dir, "myp.key"))
|
|
|
|
print(f"SSL-Zertifikat wurde erstellt:")
|
|
print(f"- Zertifikat: {ssl_cert_path}")
|
|
print(f"- Schlüssel: {ssl_key_path}")
|
|
print(f"- Kopiert nach: {frontend_ssl_dir}")
|
|
print(f"- Gültig bis: {valid_until.strftime('%d.%m.%Y')}")
|
|
print(f"- Hostnamen: {', '.join(hostnames)}")
|
|
print(f"- IP-Adressen: {', '.join(ip_addresses)}")
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Fehler beim Erstellen des SSL-Zertifikats: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
generate_ssl_certificate()
|
|
EOF
|
|
|
|
# Ausführbar machen
|
|
chmod +x backend/generate_ssl_cert.py
|
|
fi
|
|
|
|
# Zertifikat generieren
|
|
cert_gen_success=$(exec_command "cd backend && python3 generate_ssl_cert.py" "Generiere SSL-Zertifikat")
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo -e "${RED}✗ Fehler bei der Zertifikatsgenerierung. Abbruch.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# 3. Zertifikat im System installieren
|
|
echo ""
|
|
echo -e "${CYAN}3. Installiere Zertifikat im System...${NC}"
|
|
|
|
if [ "$EUID" -eq 0 ]; then
|
|
# Als Root ausgeführt
|
|
cert_path=$(readlink -f backend/app/instance/ssl/myp.crt)
|
|
|
|
# Zielverzeichnis für System-Zertifikate
|
|
if [ -d "/usr/local/share/ca-certificates" ]; then
|
|
# Debian/Ubuntu/Raspberry Pi OS
|
|
cert_dir="/usr/local/share/ca-certificates"
|
|
exec_command "cp $cert_path $cert_dir/myp.crt" "Kopiere Zertifikat in System-Verzeichnis"
|
|
exec_command "update-ca-certificates" "Aktualisiere System-Zertifikate"
|
|
elif [ -d "/etc/pki/ca-trust/source/anchors" ]; then
|
|
# RHEL/CentOS/Fedora
|
|
cert_dir="/etc/pki/ca-trust/source/anchors"
|
|
exec_command "cp $cert_path $cert_dir/myp.crt" "Kopiere Zertifikat in System-Verzeichnis"
|
|
exec_command "update-ca-trust extract" "Aktualisiere System-Zertifikate"
|
|
else
|
|
echo -e "${YELLOW}Unbekanntes System. Versuche direkte Installation...${NC}"
|
|
if command -v certutil &> /dev/null; then
|
|
exec_command "certutil -A -n 'MYP SSL Certificate' -t 'C,,' -i $cert_path -d sql:$HOME/.pki/nssdb" "Installiere mit certutil"
|
|
fi
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}Überspringen der System-Installation, da das Skript nicht als Root ausgeführt wird.${NC}"
|
|
echo -e "${YELLOW}Sie können das Zertifikat später manuell installieren durch:${NC}"
|
|
echo -e "${NC}sudo cp backend/app/instance/ssl/myp.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates${NC}"
|
|
fi
|
|
|
|
# 4. Frontend konfigurieren
|
|
echo ""
|
|
echo -e "${CYAN}4. Konfiguriere Frontend...${NC}"
|
|
|
|
# Erstelle Frontend-Konfigurationsskript
|
|
cat > frontend/configure_ssl.js << 'EOF'
|
|
#!/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');
|
|
|
|
// 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 ===');
|
|
|
|
// Prüfen, ob SSL-Verzeichnis und Zertifikate existieren
|
|
if (!fs.existsSync(SSL_DIR) ||
|
|
!fs.existsSync(path.join(SSL_DIR, 'myp.crt')) ||
|
|
!fs.existsSync(path.join(SSL_DIR, 'myp.key'))) {
|
|
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
|
|
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'
|
|
];
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
// Hauptfunktion
|
|
function main() {
|
|
let success = true;
|
|
|
|
success = updateEnvFile() && success;
|
|
success = updateNextConfig() && success;
|
|
success = updateFetchConfig() && 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.');
|
|
} else {
|
|
console.error('\n=== Konfiguration nicht vollständig abgeschlossen ===');
|
|
console.error('Es gab Probleme bei der Konfiguration des Frontends.');
|
|
}
|
|
}
|
|
|
|
// Ausführen der Hauptfunktion
|
|
main();
|
|
EOF
|
|
|
|
# Ausführbar machen
|
|
chmod +x frontend/configure_ssl.js
|
|
|
|
# Frontend konfigurieren
|
|
if command -v node &> /dev/null; then
|
|
frontend_config_success=$(exec_command "cd frontend && node configure_ssl.js" "Konfiguriere Frontend")
|
|
else
|
|
echo -e "${YELLOW}Node.js ist nicht installiert. Überspringe Frontend-Konfiguration.${NC}"
|
|
echo -e "${YELLOW}Sie können die Frontend-Konfiguration später manuell durchführen durch:${NC}"
|
|
echo -e "${NC}cd frontend && node configure_ssl.js${NC}"
|
|
fi
|
|
|
|
# 5. Docker-Compose Datei aktualisieren
|
|
echo ""
|
|
echo -e "${CYAN}5. Aktualisiere Docker-Compose-Konfiguration...${NC}"
|
|
|
|
docker_compose_file="docker-compose.yml"
|
|
if [ -f "$docker_compose_file" ]; then
|
|
if ! grep -q -- "--dual-protocol" "$docker_compose_file"; then
|
|
# Backup erstellen
|
|
cp "$docker_compose_file" "${docker_compose_file}.bak"
|
|
|
|
# Konfiguration aktualisieren
|
|
sed -i 's/command: python -m app\.app/command: python -m app.app --dual-protocol/g' "$docker_compose_file"
|
|
|
|
echo -e "${GREEN}✓ Docker-Compose-Datei wurde aktualisiert, um den dual-protocol-Modus zu aktivieren.${NC}"
|
|
else
|
|
echo -e "${GREEN}✓ Docker-Compose-Datei ist bereits korrekt konfiguriert.${NC}"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}✗ Docker-Compose-Datei nicht gefunden. Überspringe diese Konfiguration.${NC}"
|
|
fi
|
|
|
|
# 6. Docker-Container aktualisieren
|
|
echo ""
|
|
echo -e "${CYAN}6. Möchten Sie die Docker-Container neu starten?${NC}"
|
|
read -p "Neu starten (j/n): " restart_docker
|
|
|
|
if [ "$restart_docker" = "j" ]; then
|
|
if command -v docker-compose &> /dev/null || command -v docker &> /dev/null; then
|
|
echo "Starte Docker-Container neu..."
|
|
|
|
if command -v docker-compose &> /dev/null; then
|
|
exec_command "docker-compose down && docker-compose up -d" "Starte Docker-Container neu mit docker-compose"
|
|
else
|
|
exec_command "docker compose down && docker compose up -d" "Starte Docker-Container neu mit docker compose"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}Docker ist nicht installiert oder nicht im PATH. Überspringe Neustart der Container.${NC}"
|
|
fi
|
|
fi
|
|
|
|
# Abschluss
|
|
echo ""
|
|
echo -e "${CYAN}===================================================="
|
|
echo -e " SSL-Konfiguration abgeschlossen"
|
|
echo -e "====================================================${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}Das SSL-Zertifikat wurde erfolgreich generiert und konfiguriert.${NC}"
|
|
echo -e "${GREEN}Sie können nun auf folgende Weise auf die Anwendung zugreifen:${NC}"
|
|
echo -e "${GREEN}- Backend: https://raspberrypi:443${NC}"
|
|
echo -e "${GREEN}- Frontend: https://localhost:3000${NC}"
|
|
echo ""
|
|
echo -e "${YELLOW}Hinweis: Bei der ersten Verbindung müssen Sie möglicherweise${NC}"
|
|
echo -e "${YELLOW}das selbstsignierte Zertifikat in Ihrem Browser akzeptieren.${NC}"
|
|
echo "" |