--- name: proxmox-lxc description: Proxmox LXC-Container erstellen, konfigurieren und Anwendungen darauf deployen user_invocable: true --- Du bist ein Proxmox-LXC-Agent. Du erstellst und verwaltest LXC-Container auf Proxmox-Servern und deployest Anwendungen darauf. ## KONFIGURATION ``` PVE_HOST=$PVE_HOST # Proxmox-Host (IP oder Hostname) PVE_PORT=$PVE_PORT # API-Port (default: 8006) PVE_USER=$PVE_USER # z.B. root@pam PVE_TOKEN_ID=$PVE_TOKEN_ID # API Token ID PVE_TOKEN_SECRET=$PVE_TOKEN_SECRET # API Token Secret PVE_NODE=$PVE_NODE # Node-Name (default: pve) PVE_STORAGE=$PVE_STORAGE # Storage (default: local-lvm) LXC_TEMPLATE=$LXC_TEMPLATE # Template (default: debian-13-standard) ``` ## LXC-CONTAINER ERSTELLEN ### Via Proxmox API ```bash # Nächste freie VMID ermitteln VMID=$(curl -sk "https://$PVE_HOST:$PVE_PORT/api2/json/cluster/nextid" \ -H "Authorization: PVEAPIToken=$PVE_USER!$PVE_TOKEN_ID=$PVE_TOKEN_SECRET" | jq -r '.data') # Container erstellen curl -sk -X POST "https://$PVE_HOST:$PVE_PORT/api2/json/nodes/$PVE_NODE/lxc" \ -H "Authorization: PVEAPIToken=$PVE_USER!$PVE_TOKEN_ID=$PVE_TOKEN_SECRET" \ -d "vmid=$VMID" \ -d "hostname=app-staging" \ -d "ostemplate=$PVE_STORAGE:vztmpl/$LXC_TEMPLATE.tar.zst" \ -d "storage=$PVE_STORAGE" \ -d "rootfs=$PVE_STORAGE:8" \ -d "memory=2048" \ -d "swap=512" \ -d "cores=2" \ -d "net0=name=eth0,bridge=vmbr0,ip=dhcp" \ -d "start=1" \ -d "unprivileged=1" \ -d "features=nesting=1" \ -d "ssh-public-keys=$(cat ~/.ssh/id_rsa.pub)" ``` ### Via SSH auf Proxmox-Host (Alternative) ```bash ssh root@$PVE_HOST << 'EOF' # Template herunterladen falls nötig pveam update pveam download local debian-13-standard_12.7-1_amd64.tar.zst # Container erstellen pct create $VMID local:vztmpl/debian-13-standard_12.7-1_amd64.tar.zst \ --hostname app-staging \ --storage local-lvm \ --rootfs local-lvm:8 \ --memory 2048 \ --swap 512 \ --cores 2 \ --net0 name=eth0,bridge=vmbr0,ip=dhcp \ --unprivileged 1 \ --features nesting=1 \ --start 1 # SSH-Key hinzufügen pct exec $VMID -- mkdir -p /root/.ssh pct push $VMID /root/.ssh/authorized_keys /root/.ssh/authorized_keys EOF ``` ## LXC-IP ERMITTELN Nach dem Erstellen und Starten des Containers die IP auslesen. Diese IP wird für alle weiteren Schritte und für `/ssh-deploy` verwendet. ### Via Proxmox API ```bash LXC_IP=$(curl -sk "https://$PVE_HOST:$PVE_PORT/api2/json/nodes/$PVE_NODE/lxc/$VMID/interfaces" \ -H "Authorization: PVEAPIToken=$PVE_USER!$PVE_TOKEN_ID=$PVE_TOKEN_SECRET" \ | jq -r '.data[] | select(.name=="eth0") | .["inet-address"]') echo "LXC-IP: $LXC_IP" ``` ### Via SSH auf Proxmox-Host ```bash # Variante 1: lxc-info LXC_IP=$(ssh root@$PVE_HOST "lxc-info -n $VMID -iH 2>/dev/null || pct exec $VMID -- hostname -I | awk '{print \$1}'") echo "LXC-IP: $LXC_IP" # Variante 2: pct exec LXC_IP=$(ssh root@$PVE_HOST "pct exec $VMID -- ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'") echo "LXC-IP: $LXC_IP" ``` ### WICHTIG: Automatische Weitergabe an ssh-deploy Nach der IP-Ermittlung wird SSH_HOST automatisch gesetzt. Kein manueller Eintrag in `project.env` nötig: ```bash # SSH-Verbindung zum neuen LXC testen ssh -i $SSH_KEY_PATH -o StrictHostKeyChecking=accept-new deploy@$LXC_IP "echo 'LXC erreichbar'" ``` Ab hier kann `/ssh-deploy` direkt mit `SSH_HOST=$LXC_IP` arbeiten. ## LXC FÜR WEBPROJEKT EINRICHTEN ### Basis-Setup (Node.js + Docker) ```bash # In den Container verbinden (via Proxmox-Host) ssh root@$PVE_HOST "pct exec $VMID -- bash -c ' apt update && apt upgrade -y apt install -y curl git sudo wget gnupg2 ca-certificates # Node.js 20 LTS curl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt install -y nodejs # Docker (in unprivileged LXC mit nesting) curl -fsSL https://get.docker.com | sh # PM2 für Prozess-Management npm install -g pm2 # Deploy-User anlegen useradd -m -s /bin/bash deploy mkdir -p /home/deploy/.ssh cp /root/.ssh/authorized_keys /home/deploy/.ssh/ chown -R deploy:deploy /home/deploy/.ssh echo \"deploy ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers.d/deploy # App-Verzeichnis mkdir -p /var/www/app chown deploy:deploy /var/www/app # Firewall apt install -y ufw ufw allow 22 ufw allow 80 ufw allow 443 ufw --force enable '" ``` ### Mit Docker-Compose Setup ```bash ssh root@$PVE_HOST "pct exec $VMID -- bash -c ' apt update && apt upgrade -y apt install -y curl git sudo # Docker + Compose curl -fsSL https://get.docker.com | sh apt install -y docker-compose-plugin # Deploy-User mit Docker-Rechten useradd -m -s /bin/bash deploy usermod -aG docker deploy mkdir -p /home/deploy/.ssh /var/www/app cp /root/.ssh/authorized_keys /home/deploy/.ssh/ chown -R deploy:deploy /home/deploy/.ssh /var/www/app '" ``` ### Nginx Reverse-Proxy Setup ```bash ssh deploy@$LXC_IP << 'EOF' sudo apt install -y nginx sudo tee /etc/nginx/sites-available/app << 'NGINX' server { listen 80; server_name _; location / { proxy_pass http://localhost:3000; 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_cache_bypass $http_upgrade; } location /api { proxy_pass http://localhost:4000; 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; } } NGINX sudo ln -sf /etc/nginx/sites-available/app /etc/nginx/sites-enabled/ sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t && sudo systemctl reload nginx EOF ``` ## CONTAINER-VERWALTUNG ### Status & Info ```bash # Via API curl -sk "https://$PVE_HOST:$PVE_PORT/api2/json/nodes/$PVE_NODE/lxc/$VMID/status/current" \ -H "Authorization: PVEAPIToken=$PVE_USER!$PVE_TOKEN_ID=$PVE_TOKEN_SECRET" | jq '.data' # Via SSH ssh root@$PVE_HOST "pct status $VMID" ssh root@$PVE_HOST "pct config $VMID" ssh root@$PVE_HOST "pct list" ``` ### Start / Stop / Restart ```bash ssh root@$PVE_HOST "pct start $VMID" ssh root@$PVE_HOST "pct stop $VMID" ssh root@$PVE_HOST "pct reboot $VMID" ``` ### Snapshot (Backup vor Änderungen) ```bash ssh root@$PVE_HOST "pct snapshot $VMID snap-before-deploy --description 'Vor Deployment'" # Rollback: ssh root@$PVE_HOST "pct rollback $VMID snap-before-deploy" ``` ### Ressourcen anpassen ```bash ssh root@$PVE_HOST "pct set $VMID --memory 4096 --cores 4" ssh root@$PVE_HOST "pct resize $VMID rootfs +10G" ``` ### Container löschen (mit Bestätigung!) ```bash ssh root@$PVE_HOST "pct stop $VMID && pct destroy $VMID --purge" ``` ## DEPLOYMENT-WORKFLOW AUF LXC ### Komplett-Workflow: Neuen LXC + App deployen ``` 1. LXC-Container auf Proxmox erstellen 2. Basis-Setup (Node.js/Docker, Deploy-User, Firewall) 3. Nginx Reverse-Proxy konfigurieren 4. Code deployen (via rsync oder git clone) 5. Dependencies installieren, Build, Service starten 6. Health-Check: curl http://$LXC_IP/health ``` ### In bestehendem LXC deployen Nutze `/ssh-deploy` mit der LXC-IP als SSH_HOST. ## SICHERHEIT - Unprivileged Container bevorzugen - SSH-Keys statt Passwörter - Firewall (ufw) immer aktivieren - Container NICHT als root betreiben - Deploy-User nutzen - Snapshots vor kritischen Änderungen - Nesting nur aktivieren wenn Docker im LXC benötigt wird - NIEMALS Container löschen ohne explizite Bestätigung ## TEMPLATES (häufig genutzt) | Template | Verwendung | |----------|-----------| | `debian-13-standard` | Standard für Webapps (Trixie) | | `ubuntu-24.04-standard` | Alternative mit Ubuntu | | `alpine-3.20-default` | Minimal, für einfache Services |