mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 17:13:42 +00:00
feat: add deployment configuration for Hetzner 1
Includes systemd service unit, nginx reverse proxy config, and automated deployment script. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
006ffd5254
commit
fc83db640e
3 changed files with 180 additions and 0 deletions
17
deploy/dak-backend.service
Normal file
17
deploy/dak-backend.service
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
[Unit]
|
||||||
|
Description=DAK Zweitmeinungs-Portal Backend (FastAPI/Uvicorn)
|
||||||
|
After=network.target mariadb.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=dak
|
||||||
|
Group=dak
|
||||||
|
WorkingDirectory=/opt/dak-portal/backend
|
||||||
|
Environment="PATH=/opt/dak-portal/backend/venv/bin:/usr/local/bin:/usr/bin"
|
||||||
|
EnvironmentFile=/opt/dak-portal/backend/.env
|
||||||
|
ExecStart=/opt/dak-portal/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
52
deploy/dak-portal.nginx.conf
Normal file
52
deploy/dak-portal.nginx.conf
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name dak.complexcaresolutions.de;
|
||||||
|
|
||||||
|
# SSL certificates (managed by Plesk/Let's Encrypt)
|
||||||
|
ssl_certificate /etc/letsencrypt/live/dak.complexcaresolutions.de/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/dak.complexcaresolutions.de/privkey.pem;
|
||||||
|
|
||||||
|
# Frontend — serve static files from Vite build
|
||||||
|
root /opt/dak-portal/frontend/dist;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# API proxy to FastAPI backend
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://127.0.0.1:8000/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_read_timeout 120s;
|
||||||
|
client_max_body_size 20M;
|
||||||
|
}
|
||||||
|
|
||||||
|
# FastAPI docs (optional, remove in production)
|
||||||
|
location /docs {
|
||||||
|
proxy_pass http://127.0.0.1:8000/docs;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /openapi.json {
|
||||||
|
proxy_pass http://127.0.0.1:8000/openapi.json;
|
||||||
|
}
|
||||||
|
|
||||||
|
# SPA fallback — all other routes serve index.html
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Content-Type-Options nosniff always;
|
||||||
|
add_header X-Frame-Options DENY always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name dak.complexcaresolutions.de;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
111
deploy/deploy.sh
Executable file
111
deploy/deploy.sh
Executable file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# DAK Zweitmeinungs-Portal — Deployment Script for Hetzner 1
|
||||||
|
# Run as root on the target server
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
APP_DIR="/opt/dak-portal"
|
||||||
|
REPO_URL="https://github.com/complexcaresolutions/dak.c2s.git"
|
||||||
|
BRANCH="main"
|
||||||
|
SERVICE_USER="dak"
|
||||||
|
|
||||||
|
echo "=== DAK Portal Deployment ==="
|
||||||
|
|
||||||
|
# 1. Create service user if needed
|
||||||
|
if ! id "$SERVICE_USER" &>/dev/null; then
|
||||||
|
echo "Creating service user '$SERVICE_USER'..."
|
||||||
|
useradd --system --shell /bin/false --home-dir "$APP_DIR" "$SERVICE_USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Clone or update repository
|
||||||
|
if [ -d "$APP_DIR/.git" ]; then
|
||||||
|
echo "Updating existing installation..."
|
||||||
|
cd "$APP_DIR"
|
||||||
|
git fetch origin
|
||||||
|
git checkout "$BRANCH"
|
||||||
|
git pull origin "$BRANCH"
|
||||||
|
else
|
||||||
|
echo "Fresh install — cloning repository..."
|
||||||
|
git clone --branch "$BRANCH" "$REPO_URL" "$APP_DIR"
|
||||||
|
cd "$APP_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Backend setup
|
||||||
|
echo "Setting up backend..."
|
||||||
|
cd "$APP_DIR/backend"
|
||||||
|
|
||||||
|
if [ ! -d "venv" ]; then
|
||||||
|
python3 -m venv venv
|
||||||
|
fi
|
||||||
|
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install --quiet --upgrade pip
|
||||||
|
pip install --quiet -r requirements.txt
|
||||||
|
|
||||||
|
# 4. Create .env if it doesn't exist
|
||||||
|
if [ ! -f ".env" ]; then
|
||||||
|
echo "Creating .env from template..."
|
||||||
|
cat > .env << 'ENVEOF'
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_NAME=dak_c2s
|
||||||
|
DB_USER=dak_c2s_admin
|
||||||
|
DB_PASSWORD=CHANGE_ME
|
||||||
|
|
||||||
|
JWT_SECRET_KEY=CHANGE_ME_GENERATE_A_SECURE_KEY
|
||||||
|
JWT_ALGORITHM=HS256
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES=15
|
||||||
|
REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||||
|
|
||||||
|
SMTP_HOST=smtp.complexcaresolutions.de
|
||||||
|
SMTP_PORT=465
|
||||||
|
SMTP_USER=noreply@complexcaresolutions.de
|
||||||
|
SMTP_PASSWORD=CHANGE_ME
|
||||||
|
SMTP_FROM=noreply@complexcaresolutions.de
|
||||||
|
|
||||||
|
APP_NAME=DAK Zweitmeinungs-Portal
|
||||||
|
CORS_ORIGINS=https://dak.complexcaresolutions.de
|
||||||
|
ENVEOF
|
||||||
|
echo "!! IMPORTANT: Edit $APP_DIR/backend/.env with real credentials !!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Run database migrations
|
||||||
|
echo "Running Alembic migrations..."
|
||||||
|
alembic upgrade head
|
||||||
|
|
||||||
|
# 6. Frontend build
|
||||||
|
echo "Building frontend..."
|
||||||
|
cd "$APP_DIR/frontend"
|
||||||
|
|
||||||
|
if ! command -v pnpm &>/dev/null; then
|
||||||
|
echo "Installing pnpm..."
|
||||||
|
npm install -g pnpm
|
||||||
|
fi
|
||||||
|
|
||||||
|
pnpm install --frozen-lockfile
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# 7. Set ownership
|
||||||
|
echo "Setting file ownership..."
|
||||||
|
chown -R "$SERVICE_USER":"$SERVICE_USER" "$APP_DIR"
|
||||||
|
|
||||||
|
# 8. Install systemd service
|
||||||
|
echo "Installing systemd service..."
|
||||||
|
cp "$APP_DIR/deploy/dak-backend.service" /etc/systemd/system/
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable dak-backend
|
||||||
|
systemctl restart dak-backend
|
||||||
|
|
||||||
|
# 9. Install nginx config
|
||||||
|
echo "Installing nginx config..."
|
||||||
|
cp "$APP_DIR/deploy/dak-portal.nginx.conf" /etc/nginx/conf.d/dak-portal.conf
|
||||||
|
nginx -t && systemctl reload nginx
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Deployment complete ==="
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Edit /opt/dak-portal/backend/.env with real DB password and JWT secret"
|
||||||
|
echo " 2. Create admin user: cd /opt/dak-portal/backend && source venv/bin/activate && python scripts/create_admin.py"
|
||||||
|
echo " 3. Check service: systemctl status dak-backend"
|
||||||
|
echo " 4. Check logs: journalctl -u dak-backend -f"
|
||||||
|
echo " 5. Test: curl https://dak.complexcaresolutions.de/api/health"
|
||||||
Loading…
Reference in a new issue