Proxmox Infrastruktur - Vollstaendige Konfiguration
Enthaelt: - Docker Compose mit allen Services (Nextcloud, Vaultwarden, n8n, etc.) - nginx Reverse Proxy Konfiguration mit Rate Limiting - WireGuard VPN Template - Backup und Health-Check Scripts - Deployment Script - Ausfuehrliche Dokumentation und Troubleshooting Guide Services: - Isolierte Netzwerke pro Service - Resource Limits (CPU/Memory) - Health Checks - Logging Konfiguration Sicherheit: - .env Template ohne Secrets - Rate Limiting auf nginx - TLS 1.2+ only - Security Headers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
187
README.md
Normal file
187
README.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# Proxmox Infrastruktur
|
||||
|
||||
Self-Hosted Services auf Proxmox VE mit Docker.
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
Internet
|
||||
|
|
||||
v
|
||||
[Windows VPS: 217.154.65.205]
|
||||
- nginx Reverse Proxy
|
||||
- SSL (Let's Encrypt via win-acme)
|
||||
- WireGuard Server
|
||||
|
|
||||
| WireGuard Tunnel (10.0.0.0/24)
|
||||
v
|
||||
[Proxmox: 192.168.178.111 / 10.0.0.2]
|
||||
- Docker Host
|
||||
- Alle Services als Container
|
||||
```
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Port | URL (Extern) | Beschreibung |
|
||||
|---------|------|--------------|--------------|
|
||||
| Nextcloud | 8081 | eckardt-cloud.duckdns.org | Cloud Storage |
|
||||
| Vaultwarden | 8083 | eckardt-vault.duckdns.org/vault/ | Passwort Manager |
|
||||
| n8n | 5678 | eckardt-vault.duckdns.org/n8n/ | Workflow Automation |
|
||||
| Gitea | 3000 | eckardt-git.duckdns.org | Git Repository |
|
||||
| Websites | 8082 | eckardt-vault.duckdns.org | Statische Websites |
|
||||
| API | 8000 | eckardt-vault.duckdns.org/api/ | FastAPI Backend |
|
||||
| Audiobookshelf | 13378 | (intern) | Audiobook Server |
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
- Proxmox VE oder Debian/Ubuntu mit Docker
|
||||
- WireGuard fuer externen Zugriff
|
||||
- Min. 4GB RAM, 50GB Speicher
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Repository klonen
|
||||
git clone https://eckardt-git.duckdns.org/Martin/proxmox-infrastruktur.git
|
||||
cd proxmox-infrastruktur
|
||||
|
||||
# Environment-Variablen konfigurieren
|
||||
cp docker/.env.template docker/.env
|
||||
nano docker/.env # Passwoerter anpassen!
|
||||
|
||||
# Deployment starten
|
||||
sudo ./scripts/deploy.sh
|
||||
```
|
||||
|
||||
## Verzeichnisstruktur
|
||||
|
||||
```
|
||||
proxmox-infrastruktur/
|
||||
├── docker/
|
||||
│ ├── docker-compose.yml # Haupt-Konfiguration
|
||||
│ ├── .env.template # Environment Template
|
||||
│ └── .gitignore # Secrets ausschliessen
|
||||
├── configs/
|
||||
│ ├── nginx/
|
||||
│ │ └── nginx.conf # VPS Reverse Proxy
|
||||
│ └── wireguard/
|
||||
│ └── wg0.conf.template # WireGuard Template
|
||||
├── scripts/
|
||||
│ ├── deploy.sh # Installations-Script
|
||||
│ ├── backup.sh # Backup-Script
|
||||
│ └── health-check.sh # Health-Check Script
|
||||
├── docs/
|
||||
│ ├── INSTALL.md # Detaillierte Installation
|
||||
│ └── TROUBLESHOOTING.md # Problemloesungen
|
||||
└── README.md # Diese Datei
|
||||
```
|
||||
|
||||
## Wartung
|
||||
|
||||
### Health Check
|
||||
|
||||
```bash
|
||||
# Alle Services pruefen
|
||||
/opt/scripts/health-check.sh
|
||||
|
||||
# Einzelnen Container pruefen
|
||||
docker inspect --format='{{.State.Health.Status}}' nextcloud
|
||||
```
|
||||
|
||||
### Backup
|
||||
|
||||
```bash
|
||||
# Vollstaendiges Backup
|
||||
/opt/scripts/backup.sh all
|
||||
|
||||
# Einzelner Service
|
||||
/opt/scripts/backup.sh nextcloud
|
||||
|
||||
# Automatisches Backup (crontab -e)
|
||||
0 3 * * * /opt/scripts/backup.sh all >> /var/log/backup.log 2>&1
|
||||
```
|
||||
|
||||
### Updates
|
||||
|
||||
```bash
|
||||
cd /opt/docker
|
||||
|
||||
# Alle Container aktualisieren
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
# Einzelnen Container aktualisieren
|
||||
docker compose pull nextcloud
|
||||
docker compose up -d nextcloud
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
# Alle Container
|
||||
docker compose logs -f
|
||||
|
||||
# Einzelner Container
|
||||
docker logs -f nextcloud
|
||||
|
||||
# Letzte 100 Zeilen
|
||||
docker logs --tail 100 nextcloud
|
||||
```
|
||||
|
||||
## Sicherheit
|
||||
|
||||
### Implementierte Massnahmen
|
||||
|
||||
- **Isolierte Netzwerke**: Jeder Service hat sein eigenes Docker-Netzwerk
|
||||
- **Resource Limits**: CPU und Memory Limits pro Container
|
||||
- **Health Checks**: Automatische Ueberwachung aller Services
|
||||
- **Rate Limiting**: nginx begrenzt Anfragen pro IP
|
||||
- **TLS 1.2+**: Nur sichere Verschluesselung
|
||||
- **Security Headers**: X-Frame-Options, X-Content-Type-Options, etc.
|
||||
|
||||
### Zu beachten
|
||||
|
||||
- `.env` Datei NIEMALS committen
|
||||
- Admin-Tokens regelmaessig rotieren
|
||||
- Backups extern speichern
|
||||
- Updates zeitnah einspielen
|
||||
|
||||
## Netzwerk
|
||||
|
||||
### WireGuard Tunnel
|
||||
|
||||
```
|
||||
VPS (Server) Proxmox (Client)
|
||||
10.0.0.1 <--> 10.0.0.2
|
||||
217.154.65.205 192.168.178.111
|
||||
```
|
||||
|
||||
### Ports
|
||||
|
||||
| Port | Service | Zugriff |
|
||||
|------|---------|---------|
|
||||
| 51820/UDP | WireGuard | VPS extern |
|
||||
| 80 | nginx HTTP | VPS extern |
|
||||
| 443 | nginx HTTPS | VPS extern |
|
||||
| 3000 | Gitea Web | Proxmox intern |
|
||||
| 2222 | Gitea SSH | Proxmox intern |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Siehe [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) fuer:
|
||||
|
||||
- Container startet nicht
|
||||
- Permission denied Fehler
|
||||
- Netzwerk-Probleme
|
||||
- SSL-Zertifikat Fehler
|
||||
- Backup-Probleme
|
||||
|
||||
## Changelog
|
||||
|
||||
### 2024-12-28
|
||||
- Initial Setup mit allen Services
|
||||
- Gitea auf eigener Subdomain
|
||||
- Security Hardening (Registration disabled, Rate Limiting)
|
||||
- Health Checks und Resource Limits
|
||||
177
configs/nginx/nginx.conf
Normal file
177
configs/nginx/nginx.conf
Normal file
@@ -0,0 +1,177 @@
|
||||
# nginx Reverse Proxy Konfiguration
|
||||
# Pfad auf VPS: C:\nginx\conf\nginx.conf
|
||||
# Server: Windows VPS 217.154.65.205
|
||||
|
||||
worker_processes 1;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
client_max_body_size 10G;
|
||||
server_names_hash_bucket_size 64;
|
||||
|
||||
# Security Headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Rate Limiting
|
||||
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
|
||||
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
|
||||
|
||||
# ============================================
|
||||
# HTTP -> HTTPS Redirects
|
||||
# ============================================
|
||||
server {
|
||||
listen 80;
|
||||
server_name eckardt-vault.duckdns.org;
|
||||
location /.well-known/acme-challenge/ {
|
||||
alias C:/nginx/html/.well-known/acme-challenge/;
|
||||
}
|
||||
location / {
|
||||
return 301 https://eckardt-vault.duckdns.org$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name eckardt-cloud.duckdns.org;
|
||||
location /.well-known/acme-challenge/ {
|
||||
alias C:/nginx/html/.well-known/acme-challenge/;
|
||||
}
|
||||
location / {
|
||||
return 301 https://eckardt-cloud.duckdns.org$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name eckardt-git.duckdns.org;
|
||||
location /.well-known/acme-challenge/ {
|
||||
alias C:/nginx/html/.well-known/acme-challenge/;
|
||||
}
|
||||
location / {
|
||||
return 301 https://eckardt-git.duckdns.org$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# eckardt-vault.duckdns.org - Main Services
|
||||
# ============================================
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name eckardt-vault.duckdns.org;
|
||||
|
||||
ssl_certificate C:/nginx/ssl/eckardt-vault.duckdns.org-chain.pem;
|
||||
ssl_certificate_key C:/nginx/ssl/eckardt-vault.duckdns.org-key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# Vaultwarden - Password Manager
|
||||
location /vault/ {
|
||||
limit_req zone=login burst=5 nodelay;
|
||||
proxy_pass http://10.0.0.2:8083/;
|
||||
proxy_ssl_verify off;
|
||||
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;
|
||||
}
|
||||
|
||||
# n8n - Workflow Automation
|
||||
location /n8n/ {
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
proxy_pass http://10.0.0.2:5678/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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;
|
||||
}
|
||||
|
||||
# API - FastAPI Backend
|
||||
location /api/ {
|
||||
limit_req zone=general burst=50 nodelay;
|
||||
proxy_pass http://10.0.0.2:8000/;
|
||||
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;
|
||||
}
|
||||
|
||||
# Websites - Static Content (Default)
|
||||
location / {
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
proxy_pass http://10.0.0.2:8082/;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# eckardt-cloud.duckdns.org - Nextcloud
|
||||
# ============================================
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name eckardt-cloud.duckdns.org;
|
||||
|
||||
ssl_certificate C:/nginx/ssl/eckardt-cloud.duckdns.org-chain.pem;
|
||||
ssl_certificate_key C:/nginx/ssl/eckardt-cloud.duckdns.org-key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
limit_req zone=general burst=50 nodelay;
|
||||
proxy_pass http://10.0.0.2:8081/;
|
||||
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;
|
||||
|
||||
# Nextcloud specific
|
||||
proxy_max_temp_file_size 10240m;
|
||||
proxy_connect_timeout 300;
|
||||
proxy_send_timeout 300;
|
||||
proxy_read_timeout 300;
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# eckardt-git.duckdns.org - Gitea
|
||||
# ============================================
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name eckardt-git.duckdns.org;
|
||||
|
||||
ssl_certificate C:/nginx/ssl/eckardt-git.duckdns.org-chain.pem;
|
||||
ssl_certificate_key C:/nginx/ssl/eckardt-git.duckdns.org-key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
limit_req zone=general burst=30 nodelay;
|
||||
proxy_pass http://10.0.0.2:3000/;
|
||||
proxy_http_version 1.1;
|
||||
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_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
client_max_body_size 1G;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
configs/wireguard/wg0.conf.template
Normal file
32
configs/wireguard/wg0.conf.template
Normal file
@@ -0,0 +1,32 @@
|
||||
# WireGuard Konfiguration - Proxmox Client
|
||||
# Pfad auf Proxmox: /etc/wireguard/wg0.conf
|
||||
#
|
||||
# WICHTIG: PrivateKey und PublicKey muessen fuer jede Installation
|
||||
# neu generiert werden!
|
||||
#
|
||||
# Keys generieren:
|
||||
# wg genkey | tee privatekey | wg pubkey > publickey
|
||||
#
|
||||
# Aktivieren:
|
||||
# systemctl enable wg-quick@wg0
|
||||
# systemctl start wg-quick@wg0
|
||||
|
||||
[Interface]
|
||||
# Eigener Private Key (GEHEIM!)
|
||||
PrivateKey = <PRIVATE_KEY_HIER>
|
||||
|
||||
# IP im WireGuard Tunnel-Netzwerk
|
||||
Address = 10.0.0.2/24
|
||||
|
||||
[Peer]
|
||||
# Public Key des VPS Servers
|
||||
PublicKey = <VPS_PUBLIC_KEY_HIER>
|
||||
|
||||
# VPS Server IP und Port
|
||||
Endpoint = 217.154.65.205:51820
|
||||
|
||||
# Erlaubte IPs (nur Tunnel-Netzwerk)
|
||||
AllowedIPs = 10.0.0.0/24
|
||||
|
||||
# Keepalive fuer NAT-Traversal
|
||||
PersistentKeepalive = 25
|
||||
21
docker/.env.template
Normal file
21
docker/.env.template
Normal file
@@ -0,0 +1,21 @@
|
||||
# Proxmox Infrastruktur - Environment Variables
|
||||
# WICHTIG: Diese Datei kopieren nach .env und Werte anpassen!
|
||||
# Die .env Datei NIEMALS committen!
|
||||
|
||||
# ============================================
|
||||
# NEXTCLOUD
|
||||
# ============================================
|
||||
NEXTCLOUD_DB_PASSWORD=<sicheres-passwort-hier>
|
||||
NEXTCLOUD_DB_ROOT_PASSWORD=<sicheres-root-passwort-hier>
|
||||
|
||||
# ============================================
|
||||
# VAULTWARDEN
|
||||
# ============================================
|
||||
# Admin Token generieren: openssl rand -base64 48
|
||||
VAULTWARDEN_ADMIN_TOKEN=<admin-token-hier>
|
||||
|
||||
# ============================================
|
||||
# N8N
|
||||
# ============================================
|
||||
N8N_USER=admin
|
||||
N8N_PASSWORD=<sicheres-passwort-hier>
|
||||
11
docker/.gitignore
vendored
Normal file
11
docker/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# Niemals Secrets committen!
|
||||
.env
|
||||
*.env
|
||||
!.env.template
|
||||
|
||||
# Backup-Dateien
|
||||
*.bak
|
||||
*.backup
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
270
docker/docker-compose.yml
Normal file
270
docker/docker-compose.yml
Normal file
@@ -0,0 +1,270 @@
|
||||
services:
|
||||
# ============================================
|
||||
# NEXTCLOUD - Cloud Storage
|
||||
# ============================================
|
||||
nextcloud:
|
||||
image: nextcloud:latest
|
||||
container_name: nextcloud
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
ports:
|
||||
- "8081:80"
|
||||
volumes:
|
||||
- /opt/docker/nextcloud/data:/var/www/html
|
||||
environment:
|
||||
- MYSQL_HOST=nextcloud-db
|
||||
- MYSQL_DATABASE=nextcloud
|
||||
- MYSQL_USER=nextcloud
|
||||
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
|
||||
depends_on:
|
||||
nextcloud-db:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2.0'
|
||||
memory: 2G
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- nextcloud-net
|
||||
|
||||
nextcloud-db:
|
||||
image: mariadb:10
|
||||
container_name: nextcloud-db
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
volumes:
|
||||
- /opt/docker/nextcloud/db:/var/lib/mysql
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD}
|
||||
- MYSQL_DATABASE=nextcloud
|
||||
- MYSQL_USER=nextcloud
|
||||
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
|
||||
healthcheck:
|
||||
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1G
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- nextcloud-net
|
||||
|
||||
# ============================================
|
||||
# VAULTWARDEN - Password Manager
|
||||
# ============================================
|
||||
vaultwarden:
|
||||
image: vaultwarden/server:latest
|
||||
container_name: vaultwarden
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
ports:
|
||||
- "8083:80"
|
||||
volumes:
|
||||
- /opt/docker/vaultwarden:/data
|
||||
environment:
|
||||
- ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
|
||||
- SIGNUPS_ALLOWED=false
|
||||
- INVITATIONS_ALLOWED=true
|
||||
- SHOW_PASSWORD_HINT=false
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/alive"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- vaultwarden-net
|
||||
|
||||
# ============================================
|
||||
# N8N - Workflow Automation
|
||||
# ============================================
|
||||
n8n:
|
||||
image: n8nio/n8n:latest
|
||||
container_name: n8n
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
ports:
|
||||
- "5678:5678"
|
||||
volumes:
|
||||
- /opt/docker/n8n:/home/node/.n8n
|
||||
environment:
|
||||
- N8N_BASIC_AUTH_ACTIVE=true
|
||||
- N8N_BASIC_AUTH_USER=${N8N_USER}
|
||||
- N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
|
||||
- N8N_PATH=/n8n/
|
||||
- N8N_EDITOR_BASE_URL=https://eckardt-vault.duckdns.org/n8n/
|
||||
- WEBHOOK_URL=https://eckardt-vault.duckdns.org/n8n/
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost:5678/healthz"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1G
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- n8n-net
|
||||
|
||||
# ============================================
|
||||
# AUDIOBOOKSHELF - Audiobook Server
|
||||
# ============================================
|
||||
audiobookshelf:
|
||||
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||
container_name: audiobookshelf
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
ports:
|
||||
- "13378:80"
|
||||
volumes:
|
||||
- /opt/docker/audiobookshelf/audiobooks:/audiobooks
|
||||
- /opt/docker/audiobookshelf/podcasts:/podcasts
|
||||
- /opt/docker/audiobookshelf/config:/config
|
||||
- /opt/docker/audiobookshelf/metadata:/metadata
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/healthcheck"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 512M
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- audiobookshelf-net
|
||||
|
||||
# ============================================
|
||||
# WEBSITES - Static Website Hosting
|
||||
# ============================================
|
||||
websites:
|
||||
image: nginx:alpine
|
||||
container_name: websites
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
ports:
|
||||
- "8082:80"
|
||||
volumes:
|
||||
- /opt/docker/websites/html:/usr/share/nginx/html:ro
|
||||
- /opt/docker/websites/conf:/etc/nginx/conf.d:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 128M
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- websites-net
|
||||
|
||||
# ============================================
|
||||
# API - FastAPI Backend
|
||||
# ============================================
|
||||
api:
|
||||
image: python:3.11-slim
|
||||
container_name: api-server
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
working_dir: /app
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- /opt/docker/api:/app
|
||||
command: sh -c "pip install --quiet fastapi uvicorn httpx && python -m uvicorn main:app --host 0.0.0.0 --port 8000"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 512M
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
networks:
|
||||
- api-net
|
||||
|
||||
# ============================================
|
||||
# NETWORKS - Isolierte Netzwerke pro Service
|
||||
# ============================================
|
||||
networks:
|
||||
nextcloud-net:
|
||||
driver: bridge
|
||||
vaultwarden-net:
|
||||
driver: bridge
|
||||
n8n-net:
|
||||
driver: bridge
|
||||
audiobookshelf-net:
|
||||
driver: bridge
|
||||
websites-net:
|
||||
driver: bridge
|
||||
api-net:
|
||||
driver: bridge
|
||||
275
docs/INSTALL.md
Normal file
275
docs/INSTALL.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# Installationsanleitung
|
||||
|
||||
Detaillierte Anleitung zur Erstinstallation der Proxmox Infrastruktur.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
### Hardware
|
||||
|
||||
- **CPU:** Min. 2 Cores (4 empfohlen)
|
||||
- **RAM:** Min. 4GB (8GB empfohlen)
|
||||
- **Speicher:** Min. 50GB SSD
|
||||
|
||||
### Software
|
||||
|
||||
- Proxmox VE 7.x/8.x oder Debian 11/12 / Ubuntu 22.04+
|
||||
- Docker CE (wird automatisch installiert)
|
||||
- WireGuard (fuer externen Zugriff)
|
||||
|
||||
### Netzwerk
|
||||
|
||||
- Statische IP oder DHCP-Reservierung
|
||||
- Zugriff auf Port 51820/UDP (WireGuard)
|
||||
- Domain/Subdomain (z.B. via DuckDNS)
|
||||
|
||||
---
|
||||
|
||||
## Teil 1: Proxmox Server vorbereiten
|
||||
|
||||
### 1.1 Docker installieren
|
||||
|
||||
```bash
|
||||
# System aktualisieren
|
||||
apt update && apt upgrade -y
|
||||
|
||||
# Docker installieren
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
|
||||
# Docker beim Boot starten
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
|
||||
# Pruefen
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### 1.2 WireGuard installieren
|
||||
|
||||
```bash
|
||||
# WireGuard installieren
|
||||
apt install wireguard -y
|
||||
|
||||
# Keys generieren
|
||||
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
|
||||
|
||||
# Berechtigungen setzen
|
||||
chmod 600 /etc/wireguard/privatekey
|
||||
|
||||
# Keys anzeigen
|
||||
cat /etc/wireguard/privatekey
|
||||
cat /etc/wireguard/publickey
|
||||
```
|
||||
|
||||
### 1.3 WireGuard konfigurieren
|
||||
|
||||
```bash
|
||||
cat > /etc/wireguard/wg0.conf << 'EOF'
|
||||
[Interface]
|
||||
PrivateKey = <DEIN_PRIVATE_KEY>
|
||||
Address = 10.0.0.2/24
|
||||
|
||||
[Peer]
|
||||
PublicKey = <VPS_PUBLIC_KEY>
|
||||
Endpoint = <VPS_IP>:51820
|
||||
AllowedIPs = 10.0.0.0/24
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
# Aktivieren
|
||||
systemctl enable wg-quick@wg0
|
||||
systemctl start wg-quick@wg0
|
||||
|
||||
# Testen
|
||||
ping 10.0.0.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teil 2: Repository klonen und konfigurieren
|
||||
|
||||
### 2.1 Repository klonen
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
git clone https://eckardt-git.duckdns.org/Martin/proxmox-infrastruktur.git
|
||||
cd proxmox-infrastruktur
|
||||
```
|
||||
|
||||
### 2.2 Environment-Variablen konfigurieren
|
||||
|
||||
```bash
|
||||
# Template kopieren
|
||||
cp docker/.env.template docker/.env
|
||||
|
||||
# Sichere Passwoerter generieren
|
||||
echo "NEXTCLOUD_DB_PASSWORD=$(openssl rand -hex 16)"
|
||||
echo "NEXTCLOUD_DB_ROOT_PASSWORD=$(openssl rand -hex 16)"
|
||||
echo "VAULTWARDEN_ADMIN_TOKEN=$(openssl rand -base64 48)"
|
||||
echo "N8N_PASSWORD=$(openssl rand -hex 16)"
|
||||
|
||||
# Datei bearbeiten und Passwoerter eintragen
|
||||
nano docker/.env
|
||||
```
|
||||
|
||||
### 2.3 Verzeichnisse erstellen
|
||||
|
||||
```bash
|
||||
# Alle Datenverzeichnisse erstellen
|
||||
mkdir -p /opt/docker/nextcloud/{data,db}
|
||||
mkdir -p /opt/docker/vaultwarden
|
||||
mkdir -p /opt/docker/n8n
|
||||
mkdir -p /opt/docker/audiobookshelf/{audiobooks,podcasts,config,metadata}
|
||||
mkdir -p /opt/docker/websites/{html,conf}
|
||||
mkdir -p /opt/docker/api
|
||||
mkdir -p /opt/docker/gitea
|
||||
mkdir -p /opt/backups
|
||||
mkdir -p /opt/scripts
|
||||
|
||||
# Berechtigungen setzen
|
||||
chown -R 1000:1000 /opt/docker/*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teil 3: Services deployen
|
||||
|
||||
### 3.1 Docker Compose kopieren
|
||||
|
||||
```bash
|
||||
cp docker/docker-compose.yml /opt/docker/
|
||||
cp docker/.env /opt/docker/
|
||||
```
|
||||
|
||||
### 3.2 Container starten
|
||||
|
||||
```bash
|
||||
cd /opt/docker
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 3.3 Status pruefen
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teil 4: Services einrichten
|
||||
|
||||
### 4.1 Nextcloud
|
||||
|
||||
1. Browser oeffnen: `http://<PROXMOX_IP>:8081`
|
||||
2. Admin-Account erstellen
|
||||
3. Datenbank: MySQL/MariaDB
|
||||
- Host: `nextcloud-db`
|
||||
- Datenbank: `nextcloud`
|
||||
- User: `nextcloud`
|
||||
- Passwort: aus .env
|
||||
4. Installation abschliessen
|
||||
|
||||
### 4.2 Vaultwarden
|
||||
|
||||
1. Browser oeffnen: `http://<PROXMOX_IP>:8083`
|
||||
2. Account erstellen
|
||||
3. Admin-Panel: `http://<PROXMOX_IP>:8083/admin`
|
||||
- Token aus .env eingeben
|
||||
4. Einstellungen anpassen:
|
||||
- Registrierung deaktivieren
|
||||
- Invite only aktivieren
|
||||
|
||||
### 4.3 Gitea
|
||||
|
||||
Separates Repository: [proxmox-gitea](https://eckardt-git.duckdns.org/Martin/proxmox-gitea)
|
||||
|
||||
```bash
|
||||
cd /opt/docker/gitea
|
||||
# docker-compose.yml aus proxmox-gitea Repository
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
1. Browser oeffnen: `http://<PROXMOX_IP>:3000`
|
||||
2. Datenbank: SQLite3
|
||||
3. Admin-Account erstellen
|
||||
|
||||
### 4.4 n8n
|
||||
|
||||
1. Browser oeffnen: `http://<PROXMOX_IP>:5678`
|
||||
2. Login mit Credentials aus .env
|
||||
|
||||
---
|
||||
|
||||
## Teil 5: VPS Reverse Proxy (Optional)
|
||||
|
||||
Fuer externen Zugriff ueber das Internet.
|
||||
|
||||
### 5.1 WireGuard auf VPS
|
||||
|
||||
```bash
|
||||
# Auf Windows VPS mit WireGuard installiert
|
||||
# Config in C:\Program Files\WireGuard\wg0.conf
|
||||
|
||||
[Interface]
|
||||
PrivateKey = <VPS_PRIVATE_KEY>
|
||||
Address = 10.0.0.1/24
|
||||
ListenPort = 51820
|
||||
|
||||
[Peer]
|
||||
PublicKey = <PROXMOX_PUBLIC_KEY>
|
||||
AllowedIPs = 10.0.0.2/32
|
||||
```
|
||||
|
||||
### 5.2 nginx auf VPS
|
||||
|
||||
```bash
|
||||
# nginx.conf aus configs/nginx/nginx.conf verwenden
|
||||
# Pfad auf Windows: C:\nginx\conf\nginx.conf
|
||||
```
|
||||
|
||||
### 5.3 SSL-Zertifikate
|
||||
|
||||
```cmd
|
||||
# win-acme fuer Let's Encrypt
|
||||
C:\winacme\wacs.exe --target manual --host eckardt-vault.duckdns.org --validation filesystem --webroot C:\nginx\html --store pemfiles --pemfilespath C:\nginx\ssl
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teil 6: Automatisierung
|
||||
|
||||
### 6.1 Scripts installieren
|
||||
|
||||
```bash
|
||||
cp scripts/*.sh /opt/scripts/
|
||||
chmod +x /opt/scripts/*.sh
|
||||
```
|
||||
|
||||
### 6.2 Backup Cronjob
|
||||
|
||||
```bash
|
||||
# crontab -e
|
||||
0 3 * * * /opt/scripts/backup.sh all >> /var/log/backup.log 2>&1
|
||||
```
|
||||
|
||||
### 6.3 Health-Check Cronjob
|
||||
|
||||
```bash
|
||||
# crontab -e
|
||||
*/5 * * * * /opt/scripts/health-check.sh >> /var/log/health-check.log 2>&1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fertig!
|
||||
|
||||
Nach der Installation sollten alle Services laufen:
|
||||
|
||||
```bash
|
||||
# Pruefen
|
||||
/opt/scripts/health-check.sh
|
||||
```
|
||||
|
||||
Bei Problemen: [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
|
||||
351
docs/TROUBLESHOOTING.md
Normal file
351
docs/TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,351 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
1. [Container Probleme](#1-container-probleme)
|
||||
2. [Netzwerk Probleme](#2-netzwerk-probleme)
|
||||
3. [SSL/Zertifikat Probleme](#3-sslzertifikat-probleme)
|
||||
4. [Service-spezifische Probleme](#4-service-spezifische-probleme)
|
||||
5. [Backup/Restore Probleme](#5-backuprestore-probleme)
|
||||
6. [Performance Probleme](#6-performance-probleme)
|
||||
|
||||
---
|
||||
|
||||
## 1. Container Probleme
|
||||
|
||||
### Container startet nicht
|
||||
|
||||
**Symptom:** `docker compose up -d` laeuft, aber Container ist nicht aktiv
|
||||
|
||||
```bash
|
||||
# Status pruefen
|
||||
docker compose ps
|
||||
|
||||
# Logs anzeigen
|
||||
docker logs <container-name>
|
||||
|
||||
# Detaillierte Infos
|
||||
docker inspect <container-name>
|
||||
```
|
||||
|
||||
**Haeufige Ursachen:**
|
||||
|
||||
1. **Port bereits belegt**
|
||||
```bash
|
||||
# Port pruefen
|
||||
netstat -tulpn | grep <port>
|
||||
|
||||
# Prozess beenden oder Port aendern
|
||||
```
|
||||
|
||||
2. **Volume-Berechtigungen**
|
||||
```bash
|
||||
# Berechtigungen korrigieren
|
||||
chown -R 1000:1000 /opt/docker/<service>
|
||||
chmod -R 755 /opt/docker/<service>
|
||||
```
|
||||
|
||||
3. **Fehlende .env Datei**
|
||||
```bash
|
||||
# Pruefen ob .env existiert
|
||||
ls -la /opt/docker/.env
|
||||
|
||||
# Aus Template erstellen
|
||||
cp docker/.env.template docker/.env
|
||||
```
|
||||
|
||||
### "Permission denied" auf Proxmox
|
||||
|
||||
**Symptom:** `socketpair() failed (13: Permission denied)`
|
||||
|
||||
**Loesung:** security_opt in docker-compose.yml:
|
||||
```yaml
|
||||
security_opt:
|
||||
- apparmor=unconfined
|
||||
- seccomp=unconfined
|
||||
```
|
||||
|
||||
### Container restarts staendig
|
||||
|
||||
**Symptom:** Container Status zeigt "Restarting"
|
||||
|
||||
```bash
|
||||
# Exit-Code pruefen
|
||||
docker inspect --format='{{.State.ExitCode}}' <container>
|
||||
|
||||
# Letzten Fehler anzeigen
|
||||
docker logs --tail 50 <container>
|
||||
|
||||
# Health-Check deaktivieren zum Debuggen
|
||||
docker compose up -d --no-healthcheck <service>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Netzwerk Probleme
|
||||
|
||||
### WireGuard Tunnel nicht verbunden
|
||||
|
||||
**Symptom:** Keine Verbindung zu 10.0.0.x Adressen
|
||||
|
||||
```bash
|
||||
# WireGuard Status
|
||||
wg show wg0
|
||||
|
||||
# Interface pruefen
|
||||
ip addr show wg0
|
||||
|
||||
# Tunnel neu starten
|
||||
systemctl restart wg-quick@wg0
|
||||
|
||||
# Logs pruefen
|
||||
journalctl -u wg-quick@wg0 -n 50
|
||||
```
|
||||
|
||||
**Checkliste:**
|
||||
- [ ] PrivateKey/PublicKey korrekt?
|
||||
- [ ] Endpoint IP:Port erreichbar?
|
||||
- [ ] Firewall-Regeln auf VPS?
|
||||
- [ ] PersistentKeepalive gesetzt?
|
||||
|
||||
### Service nicht extern erreichbar
|
||||
|
||||
```bash
|
||||
# 1. Container laeuft?
|
||||
docker ps | grep <service>
|
||||
|
||||
# 2. Port offen auf Proxmox?
|
||||
curl http://localhost:<port>
|
||||
|
||||
# 3. WireGuard Tunnel aktiv?
|
||||
ping 10.0.0.1 # VPS von Proxmox
|
||||
|
||||
# 4. nginx Config auf VPS testen
|
||||
cd C:\nginx && nginx.exe -t
|
||||
|
||||
# 5. nginx neu laden
|
||||
net stop nginx && net start nginx
|
||||
```
|
||||
|
||||
### DNS-Probleme
|
||||
|
||||
```bash
|
||||
# DuckDNS IP pruefen
|
||||
nslookup eckardt-vault.duckdns.org
|
||||
|
||||
# Eigene externe IP pruefen
|
||||
curl ifconfig.me
|
||||
|
||||
# DuckDNS manuell aktualisieren
|
||||
curl "https://www.duckdns.org/update?domains=eckardt-vault&token=<TOKEN>&ip="
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. SSL/Zertifikat Probleme
|
||||
|
||||
### Zertifikat abgelaufen
|
||||
|
||||
**Auf Windows VPS:**
|
||||
```cmd
|
||||
# Zertifikat erneuern
|
||||
cd C:\winacme
|
||||
wacs.exe --renew --force
|
||||
|
||||
# nginx neu laden
|
||||
net stop nginx && net start nginx
|
||||
```
|
||||
|
||||
### Let's Encrypt Rate Limit
|
||||
|
||||
**Symptom:** "too many certificates already issued"
|
||||
|
||||
**Loesung:**
|
||||
- 5 Zertifikate pro Domain pro Woche
|
||||
- Warten oder Subdomain aendern
|
||||
- Staging-Umgebung zum Testen nutzen
|
||||
|
||||
### Mixed Content Warnung
|
||||
|
||||
**Symptom:** Browser zeigt "unsichere Inhalte"
|
||||
|
||||
**Loesung:** Alle Services muessen HTTPS nutzen
|
||||
```nginx
|
||||
# In nginx.conf
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Service-spezifische Probleme
|
||||
|
||||
### Nextcloud
|
||||
|
||||
**"Maintenance mode is enabled"**
|
||||
```bash
|
||||
docker exec nextcloud php occ maintenance:mode --off
|
||||
```
|
||||
|
||||
**Datei-Upload schlaegt fehl**
|
||||
```bash
|
||||
# PHP Limits anpassen
|
||||
docker exec nextcloud bash -c 'echo "upload_max_filesize=10G" >> /usr/local/etc/php/conf.d/uploads.ini'
|
||||
docker exec nextcloud bash -c 'echo "post_max_size=10G" >> /usr/local/etc/php/conf.d/uploads.ini'
|
||||
docker restart nextcloud
|
||||
```
|
||||
|
||||
**"Trusted Domain" Fehler**
|
||||
```bash
|
||||
docker exec nextcloud php occ config:system:set trusted_domains 1 --value=eckardt-cloud.duckdns.org
|
||||
```
|
||||
|
||||
### Vaultwarden
|
||||
|
||||
**Admin-Seite nicht erreichbar**
|
||||
```bash
|
||||
# Admin-Token pruefen
|
||||
docker logs vaultwarden | grep -i admin
|
||||
|
||||
# URL: /admin mit Token aus .env
|
||||
```
|
||||
|
||||
**Sync-Fehler in Clients**
|
||||
```bash
|
||||
# Verbindung testen
|
||||
curl -v https://eckardt-vault.duckdns.org/vault/api/alive
|
||||
```
|
||||
|
||||
### Gitea
|
||||
|
||||
**SSH Clone funktioniert nicht**
|
||||
```bash
|
||||
# SSH-Verbindung testen
|
||||
ssh -T -p 2222 git@192.168.178.111
|
||||
|
||||
# Authorized Keys pruefen
|
||||
docker exec gitea cat /data/git/.ssh/authorized_keys
|
||||
```
|
||||
|
||||
**"Unable to find user" nach Restart**
|
||||
```bash
|
||||
# Gitea User pruefen
|
||||
docker exec gitea gitea admin user list
|
||||
```
|
||||
|
||||
### n8n
|
||||
|
||||
**Webhooks funktionieren nicht**
|
||||
```bash
|
||||
# Webhook-URL pruefen
|
||||
# Muss WEBHOOK_URL in .env auf externe URL zeigen
|
||||
docker logs n8n | grep -i webhook
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Backup/Restore Probleme
|
||||
|
||||
### Backup schlaegt fehl
|
||||
|
||||
```bash
|
||||
# Berechtigungen pruefen
|
||||
ls -la /opt/backups/
|
||||
|
||||
# Speicherplatz pruefen
|
||||
df -h /opt/backups/
|
||||
|
||||
# Manuell testen
|
||||
/opt/scripts/backup.sh nextcloud
|
||||
```
|
||||
|
||||
### Restore durchfuehren
|
||||
|
||||
```bash
|
||||
# Container stoppen
|
||||
docker compose stop <service>
|
||||
|
||||
# Altes Volume loeschen
|
||||
rm -rf /opt/docker/<service>/*
|
||||
|
||||
# Backup entpacken
|
||||
tar -xzf /opt/backups/<service>_YYYYMMDD.tar.gz -C /opt/docker/<service>/
|
||||
|
||||
# Container starten
|
||||
docker compose up -d <service>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Performance Probleme
|
||||
|
||||
### Hohe CPU-Last
|
||||
|
||||
```bash
|
||||
# Top Prozesse
|
||||
docker stats --no-stream
|
||||
|
||||
# Ressourcen-Limits pruefen
|
||||
docker inspect --format='{{.HostConfig.NanoCpus}}' <container>
|
||||
```
|
||||
|
||||
### Speicher voll
|
||||
|
||||
```bash
|
||||
# Docker Cleanup
|
||||
docker system prune -a --volumes
|
||||
|
||||
# Alte Logs loeschen
|
||||
truncate -s 0 /var/lib/docker/containers/*/*-json.log
|
||||
|
||||
# Alte Backups loeschen
|
||||
find /opt/backups -mtime +30 -delete
|
||||
```
|
||||
|
||||
### Langsame Antwortzeiten
|
||||
|
||||
```bash
|
||||
# Netzwerk-Latenz testen
|
||||
ping -c 10 10.0.0.2
|
||||
|
||||
# Container-Ressourcen
|
||||
docker stats <container>
|
||||
|
||||
# Disk I/O
|
||||
iostat -x 1 5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Diagnose-Befehle Uebersicht
|
||||
|
||||
```bash
|
||||
# Alle Container Status
|
||||
docker compose ps
|
||||
|
||||
# Alle Logs (live)
|
||||
docker compose logs -f
|
||||
|
||||
# Ressourcen-Nutzung
|
||||
docker stats
|
||||
|
||||
# Netzwerke anzeigen
|
||||
docker network ls
|
||||
|
||||
# Volumes anzeigen
|
||||
docker volume ls
|
||||
|
||||
# System-Info
|
||||
docker system df
|
||||
|
||||
# Health-Check ausfuehren
|
||||
/opt/scripts/health-check.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Kontakt / Hilfe
|
||||
|
||||
- **Gitea Issues:** https://eckardt-git.duckdns.org/Martin/proxmox-infrastruktur/issues
|
||||
- **Docker Docs:** https://docs.docker.com/
|
||||
- **Nextcloud Docs:** https://docs.nextcloud.com/
|
||||
- **Vaultwarden Wiki:** https://github.com/dani-garcia/vaultwarden/wiki
|
||||
144
scripts/backup.sh
Normal file
144
scripts/backup.sh
Normal file
@@ -0,0 +1,144 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# Proxmox Infrastruktur Backup Script
|
||||
# ============================================
|
||||
# Ausfuehrung: ./backup.sh [service|all]
|
||||
# Cronjob: 0 3 * * * /opt/scripts/backup.sh all >> /var/log/backup.log 2>&1
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BACKUP_DIR="/opt/backups"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
RETENTION_DAYS=7
|
||||
|
||||
# Farben fuer Output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
|
||||
|
||||
# Backup-Verzeichnis erstellen
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
backup_nextcloud() {
|
||||
log_info "Starte Nextcloud Backup..."
|
||||
local backup_file="$BACKUP_DIR/nextcloud_$DATE.tar.gz"
|
||||
|
||||
# Maintenance Mode aktivieren
|
||||
docker exec nextcloud php occ maintenance:mode --on || true
|
||||
|
||||
# Daten sichern
|
||||
tar -czf "$backup_file" \
|
||||
-C /opt/docker/nextcloud \
|
||||
data db \
|
||||
2>/dev/null
|
||||
|
||||
# Maintenance Mode deaktivieren
|
||||
docker exec nextcloud php occ maintenance:mode --off || true
|
||||
|
||||
log_info "Nextcloud Backup erstellt: $backup_file ($(du -h "$backup_file" | cut -f1))"
|
||||
}
|
||||
|
||||
backup_vaultwarden() {
|
||||
log_info "Starte Vaultwarden Backup..."
|
||||
local backup_file="$BACKUP_DIR/vaultwarden_$DATE.tar.gz"
|
||||
|
||||
tar -czf "$backup_file" \
|
||||
-C /opt/docker \
|
||||
vaultwarden \
|
||||
2>/dev/null
|
||||
|
||||
log_info "Vaultwarden Backup erstellt: $backup_file ($(du -h "$backup_file" | cut -f1))"
|
||||
}
|
||||
|
||||
backup_gitea() {
|
||||
log_info "Starte Gitea Backup..."
|
||||
local backup_file="$BACKUP_DIR/gitea_$DATE.tar.gz"
|
||||
|
||||
# Gitea internen Backup-Befehl nutzen
|
||||
docker exec -u git gitea gitea dump -c /data/gitea/conf/app.ini -f /data/gitea-dump.zip || true
|
||||
|
||||
# Dump und Daten sichern
|
||||
tar -czf "$backup_file" \
|
||||
-C /opt/docker/gitea \
|
||||
. \
|
||||
2>/dev/null
|
||||
|
||||
log_info "Gitea Backup erstellt: $backup_file ($(du -h "$backup_file" | cut -f1))"
|
||||
}
|
||||
|
||||
backup_n8n() {
|
||||
log_info "Starte n8n Backup..."
|
||||
local backup_file="$BACKUP_DIR/n8n_$DATE.tar.gz"
|
||||
|
||||
tar -czf "$backup_file" \
|
||||
-C /opt/docker \
|
||||
n8n \
|
||||
2>/dev/null
|
||||
|
||||
log_info "n8n Backup erstellt: $backup_file ($(du -h "$backup_file" | cut -f1))"
|
||||
}
|
||||
|
||||
backup_audiobookshelf() {
|
||||
log_info "Starte Audiobookshelf Backup..."
|
||||
local backup_file="$BACKUP_DIR/audiobookshelf_$DATE.tar.gz"
|
||||
|
||||
# Nur Config und Metadata, nicht die Audiobooks selbst
|
||||
tar -czf "$backup_file" \
|
||||
-C /opt/docker/audiobookshelf \
|
||||
config metadata \
|
||||
2>/dev/null
|
||||
|
||||
log_info "Audiobookshelf Backup erstellt: $backup_file ($(du -h "$backup_file" | cut -f1))"
|
||||
}
|
||||
|
||||
backup_configs() {
|
||||
log_info "Starte Config Backup..."
|
||||
local backup_file="$BACKUP_DIR/configs_$DATE.tar.gz"
|
||||
|
||||
tar -czf "$backup_file" \
|
||||
/opt/docker/docker-compose.yml \
|
||||
/opt/docker/gitea/docker-compose.yml \
|
||||
/etc/wireguard/wg0.conf \
|
||||
2>/dev/null || true
|
||||
|
||||
log_info "Config Backup erstellt: $backup_file"
|
||||
}
|
||||
|
||||
cleanup_old_backups() {
|
||||
log_info "Loesche Backups aelter als $RETENTION_DAYS Tage..."
|
||||
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
|
||||
log_info "Cleanup abgeschlossen"
|
||||
}
|
||||
|
||||
backup_all() {
|
||||
log_info "========== VOLLSTAENDIGES BACKUP GESTARTET =========="
|
||||
backup_nextcloud
|
||||
backup_vaultwarden
|
||||
backup_gitea
|
||||
backup_n8n
|
||||
backup_audiobookshelf
|
||||
backup_configs
|
||||
cleanup_old_backups
|
||||
log_info "========== BACKUP ABGESCHLOSSEN =========="
|
||||
log_info "Backup-Groesse gesamt: $(du -sh "$BACKUP_DIR" | cut -f1)"
|
||||
}
|
||||
|
||||
# Hauptprogramm
|
||||
case "${1:-all}" in
|
||||
nextcloud) backup_nextcloud ;;
|
||||
vaultwarden) backup_vaultwarden ;;
|
||||
gitea) backup_gitea ;;
|
||||
n8n) backup_n8n ;;
|
||||
audiobookshelf) backup_audiobookshelf ;;
|
||||
configs) backup_configs ;;
|
||||
all) backup_all ;;
|
||||
*)
|
||||
echo "Verwendung: $0 [nextcloud|vaultwarden|gitea|n8n|audiobookshelf|configs|all]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
96
scripts/deploy.sh
Normal file
96
scripts/deploy.sh
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# Proxmox Infrastruktur Deployment Script
|
||||
# ============================================
|
||||
# Erstinstallation oder Update der kompletten Infrastruktur
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# Root-Check
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
log_error "Bitte als root ausfuehren"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "=========================================="
|
||||
log_info " Proxmox Infrastruktur Deployment"
|
||||
log_info "=========================================="
|
||||
|
||||
# Verzeichnisse erstellen
|
||||
log_info "Erstelle Verzeichnisse..."
|
||||
mkdir -p /opt/docker/{nextcloud/{data,db},vaultwarden,n8n,audiobookshelf/{audiobooks,podcasts,config,metadata},websites/{html,conf},api,gitea}
|
||||
mkdir -p /opt/backups
|
||||
mkdir -p /opt/scripts
|
||||
|
||||
# .env pruefen
|
||||
if [ ! -f /opt/docker/.env ]; then
|
||||
log_warn ".env Datei nicht gefunden!"
|
||||
log_info "Erstelle Template..."
|
||||
cat > /opt/docker/.env << 'EOF'
|
||||
# Proxmox Infrastruktur - Environment Variables
|
||||
NEXTCLOUD_DB_PASSWORD=CHANGE_ME_$(openssl rand -hex 8)
|
||||
NEXTCLOUD_DB_ROOT_PASSWORD=CHANGE_ME_$(openssl rand -hex 8)
|
||||
VAULTWARDEN_ADMIN_TOKEN=$(openssl rand -base64 48)
|
||||
N8N_USER=admin
|
||||
N8N_PASSWORD=CHANGE_ME_$(openssl rand -hex 8)
|
||||
EOF
|
||||
log_warn "WICHTIG: Bearbeite /opt/docker/.env und ersetze die Passwoerter!"
|
||||
log_warn "Dann erneut ausfuehren."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Docker installieren (falls nicht vorhanden)
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_info "Installiere Docker..."
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
fi
|
||||
|
||||
# Docker Compose pruefen
|
||||
if ! docker compose version &> /dev/null; then
|
||||
log_error "Docker Compose nicht gefunden!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Scripts kopieren
|
||||
log_info "Kopiere Scripts..."
|
||||
cp -f scripts/*.sh /opt/scripts/ 2>/dev/null || true
|
||||
chmod +x /opt/scripts/*.sh 2>/dev/null || true
|
||||
|
||||
# Docker Compose kopieren
|
||||
log_info "Kopiere Docker Compose..."
|
||||
cp -f docker/docker-compose.yml /opt/docker/
|
||||
|
||||
# Container starten
|
||||
log_info "Starte Container..."
|
||||
cd /opt/docker
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
# Status pruefen
|
||||
log_info "Warte auf Container-Start..."
|
||||
sleep 10
|
||||
|
||||
docker compose ps
|
||||
|
||||
log_info "=========================================="
|
||||
log_info " Deployment abgeschlossen!"
|
||||
log_info "=========================================="
|
||||
log_info ""
|
||||
log_info "Naechste Schritte:"
|
||||
log_info " 1. Nextcloud einrichten: http://$(hostname -I | awk '{print $1}'):8081"
|
||||
log_info " 2. Vaultwarden Admin: http://$(hostname -I | awk '{print $1}'):8083/admin"
|
||||
log_info " 3. Gitea einrichten: http://$(hostname -I | awk '{print $1}'):3000"
|
||||
log_info ""
|
||||
log_info "Health Check: /opt/scripts/health-check.sh"
|
||||
log_info "Backup: /opt/scripts/backup.sh all"
|
||||
122
scripts/health-check.sh
Normal file
122
scripts/health-check.sh
Normal file
@@ -0,0 +1,122 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# Proxmox Infrastruktur Health Check Script
|
||||
# ============================================
|
||||
# Ausfuehrung: ./health-check.sh
|
||||
# Cronjob: */5 * * * * /opt/scripts/health-check.sh >> /var/log/health-check.log 2>&1
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Farben fuer Output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
FAILED=0
|
||||
|
||||
check_service() {
|
||||
local name=$1
|
||||
local url=$2
|
||||
local expected=${3:-200}
|
||||
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$url" 2>/dev/null || echo "000")
|
||||
|
||||
if [ "$response" = "$expected" ]; then
|
||||
echo -e "${GREEN}[OK]${NC} $name - HTTP $response"
|
||||
else
|
||||
echo -e "${RED}[FAIL]${NC} $name - HTTP $response (erwartet: $expected)"
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
check_container() {
|
||||
local name=$1
|
||||
|
||||
if docker ps --format '{{.Names}}' | grep -q "^${name}$"; then
|
||||
status=$(docker inspect --format='{{.State.Health.Status}}' "$name" 2>/dev/null || echo "no-healthcheck")
|
||||
if [ "$status" = "healthy" ] || [ "$status" = "no-healthcheck" ]; then
|
||||
echo -e "${GREEN}[OK]${NC} Container $name - Running ($status)"
|
||||
else
|
||||
echo -e "${YELLOW}[WARN]${NC} Container $name - $status"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}[FAIL]${NC} Container $name - Not running"
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
check_disk() {
|
||||
local path=$1
|
||||
local threshold=${2:-90}
|
||||
|
||||
usage=$(df "$path" | tail -1 | awk '{print $5}' | tr -d '%')
|
||||
|
||||
if [ "$usage" -lt "$threshold" ]; then
|
||||
echo -e "${GREEN}[OK]${NC} Disk $path - ${usage}% verwendet"
|
||||
else
|
||||
echo -e "${RED}[FAIL]${NC} Disk $path - ${usage}% verwendet (Grenze: ${threshold}%)"
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
check_wireguard() {
|
||||
if wg show wg0 &>/dev/null; then
|
||||
latest_handshake=$(wg show wg0 latest-handshakes | awk '{print $2}')
|
||||
current_time=$(date +%s)
|
||||
diff=$((current_time - latest_handshake))
|
||||
|
||||
if [ "$diff" -lt 180 ]; then
|
||||
echo -e "${GREEN}[OK]${NC} WireGuard - Verbunden (Handshake vor ${diff}s)"
|
||||
else
|
||||
echo -e "${YELLOW}[WARN]${NC} WireGuard - Letzter Handshake vor ${diff}s"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}[FAIL]${NC} WireGuard - Nicht aktiv"
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "=========================================="
|
||||
echo " Proxmox Infrastruktur Health Check"
|
||||
echo " $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
echo "--- Container Status ---"
|
||||
check_container "nextcloud"
|
||||
check_container "nextcloud-db"
|
||||
check_container "vaultwarden"
|
||||
check_container "n8n"
|
||||
check_container "audiobookshelf"
|
||||
check_container "websites"
|
||||
check_container "api-server"
|
||||
check_container "gitea"
|
||||
echo ""
|
||||
|
||||
echo "--- Service Endpoints (Intern) ---"
|
||||
check_service "Nextcloud" "http://localhost:8081/status.php"
|
||||
check_service "Vaultwarden" "http://localhost:8083/alive"
|
||||
check_service "n8n" "http://localhost:5678/healthz"
|
||||
check_service "Websites" "http://localhost:8082/"
|
||||
check_service "API" "http://localhost:8000/health"
|
||||
check_service "Gitea" "http://localhost:3000/api/healthz"
|
||||
echo ""
|
||||
|
||||
echo "--- Netzwerk ---"
|
||||
check_wireguard
|
||||
echo ""
|
||||
|
||||
echo "--- Disk Usage ---"
|
||||
check_disk "/" 85
|
||||
check_disk "/opt/docker" 90
|
||||
echo ""
|
||||
|
||||
echo "=========================================="
|
||||
if [ $FAILED -eq 0 ]; then
|
||||
echo -e "${GREEN}Alle Checks bestanden!${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}$FAILED Check(s) fehlgeschlagen!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user