diff --git a/.gitignore b/.gitignore index 763dd2e..c620964 100644 --- a/.gitignore +++ b/.gitignore @@ -7,11 +7,13 @@ vault-password *.key *.pem *.pfx +id_rsa +id_rsa.pub # Ansible temporäre Dateien *.retry .ansible/ - +backup/ # Editor .vscode/ *.swp diff --git a/.kiro/settings/lsp.json b/.kiro/settings/lsp.json new file mode 100644 index 0000000..c25d1d2 --- /dev/null +++ b/.kiro/settings/lsp.json @@ -0,0 +1,198 @@ +{ + "languages": { + "typescript": { + "name": "typescript-language-server", + "command": "typescript-language-server", + "args": [ + "--stdio" + ], + "file_extensions": [ + "ts", + "js", + "tsx", + "jsx" + ], + "project_patterns": [ + "package.json", + "tsconfig.json" + ], + "exclude_patterns": [ + "**/node_modules/**", + "**/dist/**" + ], + "multi_workspace": false, + "initialization_options": { + "preferences": { + "disableSuggestions": false + } + }, + "request_timeout_secs": 60 + }, + "java": { + "name": "jdtls", + "command": "jdtls", + "args": [], + "file_extensions": [ + "java" + ], + "project_patterns": [ + "pom.xml", + "build.gradle", + "build.gradle.kts", + ".project" + ], + "exclude_patterns": [ + "**/target/**", + "**/build/**", + "**/.gradle/**" + ], + "multi_workspace": false, + "initialization_options": { + "settings": { + "java": { + "compile": { + "nullAnalysis": { + "mode": "automatic" + } + }, + "configuration": { + "annotationProcessing": { + "enabled": true + } + } + } + } + }, + "request_timeout_secs": 60 + }, + "python": { + "name": "pyright", + "command": "pyright-langserver", + "args": [ + "--stdio" + ], + "file_extensions": [ + "py" + ], + "project_patterns": [ + "pyproject.toml", + "setup.py", + "requirements.txt", + "pyrightconfig.json" + ], + "exclude_patterns": [ + "**/__pycache__/**", + "**/venv/**", + "**/.venv/**", + "**/.pytest_cache/**" + ], + "multi_workspace": false, + "initialization_options": {}, + "request_timeout_secs": 60 + }, + "go": { + "name": "gopls", + "command": "gopls", + "args": [], + "file_extensions": [ + "go" + ], + "project_patterns": [ + "go.mod", + "go.sum" + ], + "exclude_patterns": [ + "**/vendor/**" + ], + "multi_workspace": false, + "initialization_options": { + "usePlaceholders": true, + "completeUnimported": true + }, + "request_timeout_secs": 60 + }, + "ruby": { + "name": "solargraph", + "command": "solargraph", + "args": [ + "stdio" + ], + "file_extensions": [ + "rb" + ], + "project_patterns": [ + "Gemfile", + "Rakefile" + ], + "exclude_patterns": [ + "**/vendor/**", + "**/tmp/**" + ], + "multi_workspace": false, + "initialization_options": {}, + "request_timeout_secs": 60 + }, + "rust": { + "name": "rust-analyzer", + "command": "rust-analyzer", + "args": [], + "file_extensions": [ + "rs" + ], + "project_patterns": [ + "Cargo.toml" + ], + "exclude_patterns": [ + "**/target/**" + ], + "multi_workspace": false, + "initialization_options": { + "cargo": { + "buildScripts": { + "enable": true + } + }, + "diagnostics": { + "enable": true, + "enableExperimental": true + }, + "workspace": { + "symbol": { + "search": { + "scope": "workspace" + } + } + } + }, + "request_timeout_secs": 60 + }, + "cpp": { + "name": "clangd", + "command": "clangd", + "args": [ + "--background-index" + ], + "file_extensions": [ + "cpp", + "cc", + "cxx", + "c", + "h", + "hpp", + "hxx" + ], + "project_patterns": [ + "CMakeLists.txt", + "compile_commands.json", + "Makefile" + ], + "exclude_patterns": [ + "**/build/**", + "**/cmake-build-**/**" + ], + "multi_workspace": false, + "initialization_options": {}, + "request_timeout_secs": 60 + } + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..54c9987 --- /dev/null +++ b/README.md @@ -0,0 +1,371 @@ +# Ansible Playbooks + +Ansible-Setup für Proxmox-VMs, Hetzner-Server und Borg Backup auf Hetzner Storagebox. + +## Quickstart + +```bash +# Wrapper-Script nutzen +./pfannkuchen.sh setup emby_sascha # VM komplett einrichten +./pfannkuchen.sh backup # Borg auf allen Backup-Hosts +./pfannkuchen.sh update # Alle Hosts updaten +./pfannkuchen.sh gpu tdarr # NVIDIA Setup +./pfannkuchen.sh pve # Proxmox Post-Install +./pfannkuchen.sh passthrough # GPU Passthrough vorbereiten +./pfannkuchen.sh telegraf # Telegraf Monitoring +./pfannkuchen.sh hysteria2 node1 # Hysteria2 + WireGuard +./pfannkuchen.sh ping # Alle Hosts anpingen +./pfannkuchen.sh list # Inventory anzeigen + +# Oder direkt mit Ansible +ansible-playbook site.yml -l emby_sascha +ansible-playbook borg-backup.yml -l proxmox +ansible-playbook update.yml +``` + +## Infrastruktur + +### Proxmox Hosts +| Host | IP | GPU | +|-------|--------------|------| +| node1 | 10.5.85.11 | – | +| node2 | 10.5.85.12 | – | +| node3 | 10.5.85.13 | – | +| node4 | 10.5.85.14 | – | +| node5 | 10.5.85.15 | A400 | +| node6 | 10.5.85.16 | A400 | +| node7 | 10.5.85.17 | A400 | + +### VMs / LXCs +| Name | IP | Gruppe | Zweck | +|-------------|--------------|---------------|------------------------| +| emby-sascha | 10.6.1.103 | media | Emby (Sascha) | +| jellyfin | 10.5.1.112 | media | Jellyfin | +| immich | 10.4.1.107 | media | Immich Fotoverwaltung | +| emby-chris | 10.7.1.106 | media | Emby (Chris) + SMB | +| tdarr | 10.2.1.104 | arr | Tdarr Transcoding | +| arrapps | 10.2.1.100 | arr | Sonarr/Radarr etc. | +| sabnzbd | 10.2.1.119 | arr | SABnzbd | +| dockhand | 10.4.1.116 | docker | Dockhand | +| n8n | 10.4.1.113 | auto | n8n Automation | +| openclaw | 10.4.1.100 | auto | OpenClaw | +| monitoring | 10.1.1.111 | auto | Monitoring Stack | +| automation | 10.1.1.115 | auto | Automation Stack | +| matrix | 10.4.1.110 | communication | Matrix | + +### Hetzner +| Name | IP | Zweck | +|-------------|-----------------|--------------------------| +| pfannkuchen | 159.69.245.190 | Caddy Reverse Proxy + VW | + +### Hetzner Storagebox +- Host: `u457772-sub3.your-storagebox.de` +- User: `u457772-sub3` +- Port: 23 +- SSH Key liegt in `roles/borg/files/` und wird als `/root/.ssh/id_borg` deployed + +## Docker Stacks + +Jeder Stack hat ein eigenes Git-Repo unter `~/pfannkuchen/github/` und ein eigenes Docker-Netzwerk. + +| Stack | VM | Netzwerk | Services | +|------------|--------------|----------------------|-----------------------------------------------------------------| +| pfannkuchen| Hetzner VPS | `proxy_network` | Caddy, Vaultwarden, Homepage | +| monitoring | 10.1.1.111 | `monitoring_network` | Teslamate, Postgres, Grafana, Mosquitto, Prometheus, SNMP-Exporter, InfluxDB, Emby-Exporter, Node-Exporter | +| automation | 10.1.1.115 | `auto_network` | WAHA, Semaphore UI, Patchmon (DB, Redis, Backend, Frontend) | +| n8n | 10.4.1.113 | `n8n_network` | n8n, Postgres | + +### Caddy Reverse Proxy (Hetzner VPS) + +Caddy läuft auf dem Hetzner VPS und proxied alle Services über WireGuard-IPs: + +| Domain | Backend | Bemerkung | +|-------------------------|----------------------------|--------------------| +| tv.sascha-lutz.de | host.docker.internal:18096 | Emby Sascha | +| guck.tv | host.docker.internal:28096 | Emby Chris | +| netzflix.org | host.docker.internal:38096 | Emby Jellyfin | +| vault.sascha-lutz.de | vaultwarden (Container) | Vaultwarden | +| home.sascha-lutz.de | homepage:3000 (Container) | Homepage (Basic Auth) | +| grafana.sascha-lutz.de | grafana:3000 (Container) | Grafana | +| patchmon.sascha-lutz.de | patchmon-frontend:3000 | Patchmon | +| tesla.sascha-lutz.de | teslamate:4000 (Container) | Teslamate (Basic Auth) | +| influx.sascha-lutz.de | influxdb:8086 (Container) | InfluxDB | +| status.guck.tv | 10.200.200.254:3001 | Uptime Kuma | +| n8n.sascha-lutz.de | 10.4.1.113:5678 | n8n | +| docker.sascha-lutz.de | 10.4.1.116:3000 | Dockhand | +| immich.sascha-lutz.de | 10.4.1.107:2283 | Immich | +| dl.guck.tv | 10.2.1.100:5055 | Jellyseerr | +| plappern.com | 10.4.1.110:8008 | Matrix Synapse | +| web.plappern.com | 10.4.1.110:8080 | Matrix Element | +| chat.plappern.com | 10.4.1.110:8090 | Matrix Chat | +| monitor.guck.tv | 10.5.1.102:19999 | Netdata (Basic Auth) | + +### Seerr → WhatsApp + Auto-Approve + +Kombinierter n8n Workflow der zwei Dinge macht: + +**1. Auto-Approve (MEDIA_PENDING):** +``` +Jellyseerr → Webhook → n8n → TMDB Genre+FSK Lookup → Kategorisieren → Pfad+Tags setzen → Approve → 20min warten → FHD Radarr/Sonarr Suche +``` + +Genre-Logik: +| Kategorie | Bedingung | Radarr Pfad | Tag | +|---|---|---|---| +| Horror | Genre "Horror" + FSK ≥ 16 | `/data/UHD/horror` | `horror-4k` | +| Kids | Genre "Animation"/"Family" + FSK ≤ 12 | `/data/UHD/kids-video` | `kids-4k` | +| Normal | Alles andere | `/data/UHD/video` | `video-4k` | + +Serien: +| Kategorie | Bedingung | Sonarr Pfad | Tag | +|---|---|---|---| +| Kids | Genre "Animation" + FSK ≤ 12 | `/data/UHD/kids-serien` | `kids-4k` | +| Streaming | Network ist Netflix/HBO/Amazon/Disney+ etc. | `/data/UHD/serien` | `serien-4k` | +| TV | Alles andere | `/data/UHD/tvshows` | `tvshows-4k` | + +**2. WhatsApp Newsletter (MEDIA_AVAILABLE):** +``` +Jellyseerr → Webhook → n8n → WAHA Session Restart → WAHA sendText → WhatsApp Newsletter +``` + +- Webhook URL: `http://10.4.1.113:5678/webhook/seerr-notify` +- WAHA: `http://10.1.1.115:3500` (Dashboard: admin / WAHA_API_KEY) +- Newsletter Channel: `120363404705299449@newsletter` +- n8n Workflow: `tmp/n8n-seerr-combined.json` +- Status: **Funktioniert** (Text + Bild-URL, keine eingebetteten Bilder möglich) + +### Semaphore UI + +Web-UI für Ansible Playbook Management auf `http://10.1.1.115:3000`. + +- Login: `admin` / `SEMAPHORE_ADMIN_PASSWORD` (aus `.env`) +- Projekt: Pfannkuchen +- Templates: Setup VM, Update All, Borg Backup, Base Setup, NVIDIA GPU +- Git Repo: `https://github.com/feldjaeger/ansible.git` + +### Arr-Stack APIs + +| Service | URL | API Key Datei | +|---|---|---| +| Radarr UHD | `http://10.2.1.100:7878` | `tmp/radarr` | +| Radarr FHD | `http://10.2.1.100:7879` | `tmp/radarr1080p` | +| Sonarr UHD | `http://10.2.1.100:8989` | `tmp/sonarr` | +| Sonarr FHD | `http://10.2.1.100:8990` | `tmp/sonarr1080p` | +| Jellyseerr | `http://10.2.1.100:5055` | `tmp/seer` | +| TMDB API | `https://api.themoviedb.org/3` | `tmp/tmdb` (nicht im Repo) | + +## ISO Builder + +Baut Custom Debian ISOs mit Preseed für unattended Installation. Siehe `iso-builder/README.md`. + +```bash +# ISO bauen + auf Proxmox Node uploaden +./iso-builder/build-iso.sh --node 4 --ip 10.4.1.120 --hostname neue-vm + +# ISO bauen + VM erstellen + starten +./iso-builder/build-iso.sh --node 4 --ip 10.4.1.120 --hostname neue-vm --create-vm +``` + +## Netzwerk + +### WireGuard Tunnel (Hysteria2) + +Alle Proxmox Nodes verbinden sich über Hysteria2 (QUIC) zum VPS. Das umgeht CGNAT-Beschränkungen und versteckt den WireGuard-Traffic vor DPI (Sophos Firewall). + +``` +[Proxmox Node] → Hysteria2-Client → QUIC (UDP:8443) → Hysteria2-Server (VPS) → WireGuard +``` + +- Hysteria2 nutzt UDP:8443, Caddy behält TCP:443 + UDP:443 (HTTP/3) +- TLS: Selbstsigniertes Zertifikat auf dem VPS (10 Jahre gültig), Clients mit `insecure: true` +- Bandwidth-Hints konfiguriert für optimale Performance (400 Mbit/s) + +| Node | WG-IP | VM-Subnetz | Bemerkung | +|-------|----------------|----------------|------------------| +| VPS | 10.200.200.254 | – | WG Server + Hub | +| node1 | 10.200.200.2 | 10.11.1.0/24 | | +| node2 | 10.200.200.3 | 10.2.1.0/24 | Arr-Stack | +| node3 | 10.200.200.113 | 10.3.1.0/24 | | +| node4 | 10.200.200.100 | 10.4.1.0/24 | Docker/Auto | +| node5 | 10.200.200.101 | 10.5.1.0/24 | Media | +| node6 | 10.200.200.116 | 10.6.1.0/24 | A400 | +| node7 | 10.200.200.117 | 10.7.1.0/24 | A400 | + +Direkte Peers (kein Hysteria2): +- embyproxy (10.200.200.1) +- Sascha (10.200.200.5), Chris (10.200.200.6), Sascha Handy (10.200.200.7) +- Fassohneboden (10.200.200.4), Marco Minecraft (10.200.200.8) + +### Netzwerk-Segmente + +| Subnetz | Zweck | Node | +|--------------|----------------|-------| +| 10.5.85.x | Proxmox Hosts | alle | +| 10.1.1.x | Monitoring/Auto| node1 | +| 10.11.1.x | VMs node1 | node1 | +| 10.2.1.x | Arr-Stack | node2 | +| 10.3.1.x | VMs node3 | node3 | +| 10.4.1.x | Docker/Auto | node4 | +| 10.5.1.x | Media VMs | node5 | +| 10.6.1.x | VMs node6 | node6 | +| 10.7.1.x | VMs node7 | node7 | +| 10.200.200.x | WireGuard | VPS | + +## Rollen + +| Rolle | Zweck | +|---------------------|--------------------------------------------------------------| +| base | Repos, Pakete, Locale, SSH Key, Sudo, QEMU Guest Agent | +| docker | Docker CE + Compose Plugin, User sascha → docker Gruppe | +| nvidia | CUDA Repo, cuda-drivers, Container Toolkit, Docker nvidia-RT | +| borg | SSH Key Deploy, Borg Repo Init, Backup-Script, Systemd Timer | +| hawser | Hawser Install + Systemd Service + Token aus Vault | +| sysctl | BBR, TCP Tuning, Buffer Sizes für Streaming-VMs | +| sysctl_proxmox | Overcommit, File Handles, IP Forward, Bridge-Tuning | +| pve_postinstall | Repos (deb822), Enterprise deaktiviert, Nag-Patch, HA aus | +| pve_gpu_passthrough | IOMMU, VFIO, Nouveau/NVIDIA Blacklist für GPU Passthrough | +| telegraf | InfluxData Repo, Telegraf Config, lm-sensors, Synology SNMP | +| hysteria2 | Hysteria2 Client, Bandwidth-Hints, WireGuard Config | +| hysteria2_server | Hysteria2 Server, selbstsigniertes TLS, systemd Service | + +## Playbooks + +| Playbook | Wrapper-Befehl | Zweck | +|--------------------------|------------------------|------------------------------------------| +| `site.yml` | `setup ` | VM komplett einrichten | +| `base-debian.yml` | `base ` | Grundsetup + Docker | +| `nvidia-docker.yml` | `gpu ` | NVIDIA Treiber + Docker GPU Runtime | +| `borg-backup.yml` | `backup [host]` | Borg Backup einrichten | +| `hawser.yml` | `hawser ` | Hawser installieren | +| `update.yml` | `update [host]` | Dist-Upgrade + Autoremove | +| `sysctl.yaml` | `tune ` | Netzwerk-Tuning für Streaming | +| `sysctl-proxmox.yaml` | – | Proxmox-Host-Tuning | +| `pve-postinstall.yml` | `pve [host]` | Proxmox Post-Install (Repos, Nag, HA) | +| `pve-gpu-passthrough.yml`| `passthrough [host]` | GPU PCI Passthrough vorbereiten | +| `telegraf.yml` | `telegraf [host]` | Telegraf Monitoring deployen | +| `hysteria2.yml` | – | Hysteria2 Client + WireGuard deployen | +| `hysteria2-server.yml` | – | Hysteria2 Server auf VPS deployen | + +## Inventory-Gruppen + +| Gruppe | Hosts | Zweck | +|---------------|-------------------------------------------------|------------------------------| +| proxmox | node1–node7 | Alle Proxmox Hosts | +| proxmox_gpu | node2, node4, node6, node7 | Nodes mit A400 GPU | +| nvidia | tdarr, emby-sascha, emby-chris, immich | VMs mit NVIDIA GPU Runtime | +| wireguard | node1–node7 | WireGuard Clients | +| media | emby-sascha, jellyfin, immich, emby-chris | Media VMs | +| arr | tdarr, arrapps, sabnzbd | Arr-Stack | +| docker | dockhand | Docker VMs | +| auto | n8n, openclaw, monitoring, automation | Automation | +| communication | matrix | Kommunikation | +| hetzner | pfannkuchen | Hetzner Server | +| frp | emby-sascha, emby-chris, jellyfin | FRP Clients | +| backup | alle (via children) | Borg Backup | + +## Borg Backup + +Alle Hosts in der Gruppe `backup` bekommen Borg Backup. Die Backup-Quellen sind pro Gruppe konfiguriert: + +| Gruppe | Backup-Quellen | Quelle | +|-----------|-----------------------------------------------------------------------------|-------------------------------| +| VMs | `/app-config` | `roles/borg/defaults/main.yml`| +| Proxmox | `/etc/pve /etc/network /etc/wireguard /etc/crontab /etc/fstab /etc/systemd/system/ /etc/iptables /etc/telegraf` | `group_vars/proxmox/borg.yml` | +| Hetzner | `/etc/wireguard /app-config` | `group_vars/hetzner/borg.yml` | + +Backup-Script: `/usr/local/bin/borg-backup.sh` +Systemd Timer: täglich 03:00 Uhr (±30min Jitter) +Log: `/var/log/borg-backup.log` +Kompression: lz4 +Retention: 7 daily, 4 weekly, 6 monthly + +## Telegraf Monitoring + +Alle Proxmox Hosts bekommen Telegraf mit InfluxDB v2 Output. + +Standard-Inputs: cpu, disk, diskio, kernel, mem, processes, swap, system, nstat, sensors + +Sonderfall node2: Zusätzlich Synology NAS SNMP Monitoring (konfiguriert via `host_vars/node2/telegraf.yml`). + +## Vault + +Vault-Datei: `group_vars/all/vault.yml` + +Enthaltene Variablen: +- `vault_hetzner_storage_host` – Storagebox Hostname +- `vault_hetzner_storage_user` – Storagebox User +- `vault_borg_passphrase` – Borg Verschlüsselungspasswort +- `vault_sascha_password` – SSH/Become-Passwort für User sascha +- `vault_chris_password` – SSH/Become-Passwort für User chris +- `vault_telegraf_influx_token` – InfluxDB v2 Token für Telegraf +- `vault_snmp_sec_name` – SNMP v3 Security Name (Synology) +- `vault_snmp_auth_password` – SNMP v3 Auth Passwort +- `vault_snmp_priv_password` – SNMP v3 Privacy Passwort +- `vault_hysteria2_password` – Hysteria2 Auth Passwort +- `vault_wireguard_vps_pubkey` – WireGuard Public Key des VPS +- `vault_node[1-7]_wg_privkey` – WireGuard Private Keys der Nodes +- `vault_hawser_token` – Hawser Agent Token für Dockhand + +```bash +# Passwörter eintragen und verschlüsseln +ansible-vault edit group_vars/all/vault.yml +ansible-vault encrypt group_vars/all/vault.yml +``` + +Vault-Passwort liegt in `.vault-password` (in `.gitignore`). + +## Verzeichnisstruktur + +``` +ansible/ +├── ansible.cfg +├── pfannkuchen.ini # Inventory +├── pfannkuchen.sh # Wrapper-Script +├── site.yml # Master-Playbook +├── base-debian.yml +├── borg-backup.yml +├── nvidia-docker.yml +├── hawser.yml +├── update.yml +├── sysctl.yaml +├── sysctl-proxmox.yaml +├── pve-postinstall.yml +├── pve-gpu-passthrough.yml +├── telegraf.yml +├── hysteria2.yml +├── hysteria2-server.yml +├── iso-builder/ # Custom Debian ISO Builder +│ ├── build-iso.sh # ISO Build + Upload + VM Create +│ ├── preseed.cfg.tpl # Preseed Template +│ └── output/ # Gebaute ISOs +├── group_vars/ +│ ├── all/vault.yml # Vault (verschlüsselt) +│ ├── proxmox/borg.yml # Proxmox Backup-Pfade +│ └── hetzner/borg.yml # Hetzner Backup-Pfade +├── host_vars/ +│ ├── node1/wireguard.yml +│ ├── node2/ +│ │ ├── telegraf.yml # Synology SNMP +│ │ └── wireguard.yml +│ ├── node3–node7/wireguard.yml +│ └── emby_chris/vars.yml # User chris Credentials +├── tmp/ +│ ├── n8n-seerr-combined.json # n8n Workflow: Auto-Approve + WhatsApp +│ ├── radarr, sonarr, seer # API Keys +│ ├── radarr1080p, sonarr1080p # FHD API Keys +│ └── n8n # n8n API Key +└── roles/ + ├── base/tasks/main.yml + ├── docker/tasks/main.yml + ├── nvidia/{tasks,handlers,defaults}/ + ├── borg/{tasks,defaults,files,templates}/ + ├── hawser/tasks/main.yml + ├── hawser/handlers/main.yml + ├── sysctl/tasks/main.yml + ├── sysctl_proxmox/tasks/main.yml + ├── pve_postinstall/tasks/main.yml + ├── pve_gpu_passthrough/{tasks,handlers}/ + ├── telegraf/{tasks,handlers,defaults,templates}/ + ├── hysteria2/{tasks,handlers,defaults}/ + └── hysteria2_server/{tasks,handlers,defaults}/ +``` diff --git a/ansible.cfg b/ansible.cfg index 46378eb..30fa1cc 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,5 +1,6 @@ [defaults] host_key_checking = false +vault_password_file = .vault-password inventory=pfannkuchen.ini ansible_python_interpreter=/usr/bin/python3 interpreter_python = auto_silent diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..d7ee9a2 --- /dev/null +++ b/backup.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# === Konfiguration === +#REPO="root@10.5.85.202:/cluster-backup/$(hostname)" +REPO="ssh://storagebox/home/$(hostname)" + +# === Zu sichernde Verzeichnisse === +BACKUP_PATHS="/etc/wireguard/ /app-config" + +# === Archivname mit Datum === +ARCHIVE="$(hostname)-$(date +%Y-%m-%d_%H-%M)" + +# === Logging === +LOGFILE="/var/log/proxmox-borg-backup.log" + +#export BORG_RSH='ssh -i /root/.ssh/id_ed25519' +#export BORG_PASSPHRASE='zUGb7Jbc+cMa8RJ' +# === Borg Backup ausführen === +echo "[$(date)] Starte Backup: $ARCHIVE" >> $LOGFILE + +borg create \ + --verbose \ + --filter AME \ + --remote-path=borg-1.4 \ + --stats \ + --show-rc \ + --compression lz4 \ + "$REPO::$ARCHIVE" \ + $BACKUP_PATHS >> $LOGFILE 2>&1 + +BACKUP_RC=$? + +# === Alte Backups aufräumen === +borg prune -v --list "$REPO" \ + --keep-daily=7 \ + --keep-weekly=4 \ + --keep-monthly=6 >> $LOGFILE 2>&1 + +PRUNE_RC=$? + +# === Exit-Code prüfen === +GLOBAL_RC=$(( BACKUP_RC > PRUNE_RC ? BACKUP_RC : PRUNE_RC )) + +echo "[$(date)] Backup beendet mit Code $GLOBAL_RC" >> $LOGFILE +exit $GLOBAL_RC diff --git a/base-debian.yml b/base-debian.yml index 7ffe2a6..5f778e2 100644 --- a/base-debian.yml +++ b/base-debian.yml @@ -2,140 +2,6 @@ - name: Basis-Konfiguration für Debian VMs hosts: all become: yes - vars: - # Pfad auf dem Ansible-LXC (Quelle) - source_folder: "/ansible/komodo/" - # Pfad auf der Ziel-VM (Ziel) - dest_folder: "/app-config/komodo/" - - tasks: - - name: SSH Key für Benutzer sascha hinterlegen - ansible.posix.authorized_key: - user: chris - state: present - key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}" - - name: Standard Debian Trixie Repositories setzen - copy: - dest: /etc/apt/sources.list - content: | - deb http://ftp.gwdg.de/debian/ trixie main non-free-firmware non-free contrib - deb-src http://ftp.gwdg.de/debian/ trixie main non-free-firmware non-free contrib - - deb http://security.debian.org/debian-security trixie-security main non-free-firmware non-free contrib - deb-src http://security.debian.org/debian-security trixie-security main non-free-firmware non-free contrib - - deb http://ftp.gwdg.de/debian/ trixie-updates main non-free-firmware non-free contrib - deb-src http://ftp.gwdg.de/debian/ trixie-updates main non-free-firmware non-free contrib - owner: root - group: root - mode: '0644' - register: repo_status - - - name: Apt Cache aktualisieren (falls Repos geändert wurden) - apt: - update_cache: yes - when: repo_status.changed - - - name: Installiere benötigte Basis-Pakete - apt: - name: - - curl - - gnupg - - ca-certificates - - sudo - - wget - - vim - - mc - state: present - update_cache: yes - - name: Locales-Paket sicherstellen - apt: - name: locales - state: present - - - name: en_US.UTF-8 Locale generieren - locale_gen: - name: en_US.UTF-8 - state: present - - - name: Systemweite Sprache auf en_US.UTF-8 setzen - debconf: - name: locales - question: locales/default_environment_locale - value: en_US.UTF-8 - vtype: select - - - name: Locale-Datei manuell schreiben (Sicherheitsnetz) - copy: - dest: /etc/default/locale - content: | - LANG=en_US.UTF-8 - LC_ALL=en_US.UTF-8 - - - name: Verzeichnis für Keyrings erstellen - file: - path: /etc/apt/keyrings - state: directory - mode: '0755' - - - name: Docker GPG Key herunterladen (Modern) - get_url: - url: https://download.docker.com/linux/debian/gpg - dest: /etc/apt/keyrings/docker.asc - mode: '0644' - - - name: Docker Repository Datei erstellen - copy: - dest: /etc/apt/sources.list.d/docker.list - content: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable" - mode: '0644' - register: docker_repo - - - name: Paketliste aktualisieren - apt: - update_cache: yes - when: docker_repo.changed - - - name: Docker Engine installieren - apt: - name: - - docker-ce - - docker-ce-cli - - containerd.io - - docker-compose-plugin - state: present - - name: Zielverzeichnis auf der VM erstellen - file: - path: "{{ dest_folder }}" - state: directory - mode: '0755' - - # 2. Sudoers anpassen (Ohne Passwort-Abfrage für die Gruppe sudo) - - name: Gruppe sudo passwortloses sudo erlauben - lineinfile: - path: /etc/sudoers - state: present - regexp: '^%sudo' - line: '%sudo ALL=(ALL:ALL) NOPASSWD: ALL' - validate: '/usr/sbin/visudo -cf %s' - - # 3. Sascha in Gruppen stecken - - name: Benutzer sascha zu sudo und docker Gruppen hinzufügen - user: - name: sascha - groups: sudo,docker - append: yes - - - name: Unnötige Pakete entfernen - apt: - autoremove: yes - - - name: QEMU Guest Agent installieren und starten - apt: - name: qemu-guest-agent - state: present - - name: Agent Dienst aktivieren - service: - name: qemu-guest-agent - state: started - enabled: yes + roles: + - base + - docker diff --git a/borg-backup.yml b/borg-backup.yml new file mode 100644 index 0000000..a93da4d --- /dev/null +++ b/borg-backup.yml @@ -0,0 +1,6 @@ +--- +- name: Borg Backup Setup + hosts: backup + become: yes + roles: + - borg diff --git a/caddy b/caddy new file mode 100644 index 0000000..141393c --- /dev/null +++ b/caddy @@ -0,0 +1,69 @@ +{ + metrics + admin :2019 + log { + output file /var/log/caddy/caddy_main.log { + roll_size 100MiB + roll_keep 5 + roll_keep_for 100d + } + format json + level INFO + } +} + +(emby_config) { + log { + output file "/var/log/caddy/{args[0]}.log" { + roll_size 100MiB + roll_keep 5 + roll_keep_for 100d + } + format json + } + @compress { + header Content-Type text/* + header Content-Type application/json* + header Content-Type application/javascript* + header Content-Type image/svg+xml + } + encode @compress zstd gzip + reverse_proxy {args[1]} { + flush_interval 10s + header_up X-Accel-Buffering "no" + } + header { + Access-Control-Allow-Origin * + Cache-Control "no-cache, no-transform" + defer + } +} + + +tunnel.sascha-lutz.de { + @wst { + path /5bb8a961812d2f966e09b2825635a1a1007a283083877ae7873ebda99c514ec7/events + header Upgrade websocket + header Connection *upgrade* + method GET + } + handle @wst { + reverse_proxy tunnel:8080 + } + handle { + respond "Not Found" 404 + } +} + + +tv.sascha-lutz.de { + import emby_config tv.sascha-lutz.de 10.6.1.103:8096 +} + +guck.tv { + import emby_config guck.tv 10.7.1.106:8096 +} + +netzflix.org { + import emby_config netzflix.org 10.6.1.112:8096 +} diff --git a/frp-client.yml b/frp-client.yml new file mode 100644 index 0000000..19ec298 --- /dev/null +++ b/frp-client.yml @@ -0,0 +1,6 @@ +--- +- name: frp Client deployen + hosts: frp + become: yes + roles: + - frp_client diff --git a/frp-server.yml b/frp-server.yml new file mode 100644 index 0000000..09151b2 --- /dev/null +++ b/frp-server.yml @@ -0,0 +1,6 @@ +--- +- name: frp Server deployen + hosts: pfannkuchen + become: yes + roles: + - frp_server diff --git a/glances.yml b/glances.yml new file mode 100644 index 0000000..e315d4f --- /dev/null +++ b/glances.yml @@ -0,0 +1,6 @@ +--- +- name: Glances Web auf allen Proxmox Nodes + hosts: proxmox + become: yes + roles: + - glances diff --git a/group_vars/all/vault.yml b/group_vars/all/vault.yml new file mode 100644 index 0000000..ec6d79b --- /dev/null +++ b/group_vars/all/vault.yml @@ -0,0 +1,154 @@ +$ANSIBLE_VAULT;1.1;AES256 +37383338316537366564323266376164623232323230633861636534373236633035333436336531 +3937336563656166653061636538613331373166326137640a623362646631373264663939613436 +34343939636538383462316532656134396665616438336465366162643230353065343838366638 +3934303464616538640a396337363262333135376264353736623734643836393632373730663864 +37346536623736663063623739323166636438643666366438356565343464306335343738373165 +64393961636664306134313432393864393435616161383437363865663036386164613265383038 +38633839373936366138306631336534666537376239323463653339366334623931356638373733 +63366138303131363139666239616538313236353365356533653763326435313634613538626433 +61623630326434336238646666373834386138623636313636613735616662323661303933623366 +31303466306530646563626437623063356363303963393131646135323731373931326333613535 +61376234643131356163643837663437396632306266623339336166623534646630623234316539 +64373165343137343165366238656130663630343935333966386462373266313430623736333565 +34666265383434646361306436306538383336303539316538656461656266633339663861613663 +34303133613036643066396562613564353432613632366165613163313634643534396263393336 +37373366623133366236613734623238363261363430613537613063613062356136373766653734 +36313136383635343931376638613664373635633963626331366162313033356564333862666264 +64653435393437353961656136363763363730373063313938386538323365303761616232656566 +32313666366334346336383038383531656165333935636139346662633066643936323636306639 +34346661303666656562373538313334303331383365366638326166333665326365363765316136 +30336237613631366463383237366564333738316461653234373232623564326566363064666437 +35663932326638613837306132636166356463353830396131663537313366633938633438383435 +35376132313539333431666362376465336538383561356539313362616632363736343162316435 +39653932623861363965626661393536346536356562343233306235396334353762333765363039 +32303536613137633430333132346263323563363030353664653830646333326231313566363432 +32623336643236356336323332363636323632326537636234623062343365643736373230616336 +33363765363832333532633337373062303431343837346137626336363763636566633363656539 +64653562333834346437383861323731653737356235383533363863646564636437616633363664 +30366564623662383563663731366362353135623135663336343032316232643435373137353639 +32303438363038616662636561393866653032333364623735376637396466373439646137646632 +31313431616263396231383232646237663465333265366636373035633632303033323633323533 +30343737626265353364623839336162643733616631323238663732373830643531646136306133 +37656130393736663437656139643138363933363636643831373230623437653465666637326438 +33393665336330333332323739383539353030323633343237376230333232633231393265373633 +61343666663536613332386562663338333263366235353834393262373161346437633639643063 +64613661636562333564376639646564623331656265323430313034326235323837353035656338 +30336463353766633862663039636133326665326532613231666561653466616364333338656264 +30393731373665333461346232313865376261393561323435626562316630633735396536366636 +36636339353637636335376630343139303064336132373063643665333136383739313833386439 +32353034653430323766303238336130306130353830356230623232356236393336373536346530 +32393461656439643431313461316266313861303435613431313231353663393236663962393262 +31346233356534653261386465323036616138623534313730616435356434386231383533376663 +63303134643232663966613638386566386566333165623938313962313934373039613433643265 +32613465383830343930373037643330613136633735306664613664303833633234636661376364 +63303764386261336162666161393030363064613934373439383133363364306331353962363733 +37366261623532613636353933623662336539363239653266646664353637663139393366663063 +63333564313733313561666531663463386438366638343333363363383963373930323435656264 +39616364626630653163613961366566386132643666663637336136663730346234323063626334 +62313134383966336538393432313035326333666330346464653233306466346232323931356237 +34343365303262616333383932393966303931653561336161663836623231653432633063336333 +65636134653835616437626339393962356563633431396666353933623263316333366131356135 +32323832346266613939373931646535666131303739323162646338363166313163653938376534 +37336438613862643261613636356663333933633331616566653934376435633163353931383736 +66653134626564653862653030393563363736326439653263306432346665356337306239633031 +39306331346164633431343133346361636431356435626564313137666134653035633063383764 +30633964326163326439393333666130366161306465643362336332393130303638353936346232 +39663065663936613234373461613966303036383334653031646638633261386364636539366465 +37326237353736626532303637346537663931626530623333613039313330306263653933636130 +37363032633865623734656238323433353533663734343139663037343236343365333462353738 +39643634316165396437313738373464613731323931656162366564396539643135613731643339 +62373731613432653238613264323238393835663566396230393431363139306437666664303938 +65663839663365303533376439323332323236643366333437326261396433623265653130643263 +33333637303235383836356333623739646366393062316534336637333463643735333038373663 +37333561663065363737363762643736633165636165393663323366343038386332333531653064 +62663934346435386665363766633665643362366363666332613139613938313432376130336361 +61613531376637636439386235646666373761353139613335393232353066306633313262343633 +30323435326632643064373063346439666439643465313264353862636362663237386165646130 +64326562336362386439353434313364343365323238653762313364633538656635346264303864 +65616632376564356162616165616436653037616437666631303066383434346165316532613630 +36363039633633343662303435383730646363373836656635313731376337313130346163333535 +36393135306433633964373961613930653339303563393766303833376165626265323130313561 +65656562663461356631626362323966396133383933393632386365336566373731623131376162 +62313663373430383137306338643032656630613936636462633732336637363762323031343665 +32356166373537343765653437333866323861633136613238663639376332363430623634636462 +33323232663566633736366336396566303762343531343334376464666462653333356336333163 +66623434316630343036383330383531333961313132313566396261326663353661636532313636 +62663537363338386639396630356264303733356538366131643562373730373961333736656464 +31343538383836353262653233383134343063366534343136646162623637393030633133316533 +61643135626666623539613131663537353139376634356266363537326534656339353265636130 +30623233393031323132383233376463316639616132333035643332386232663331326162316332 +32303437653431626633643336613463373036393530663662336537663239656137306565653265 +66613362396331376135336561613633666565363863363930383433393136626332383838356439 +38343136353934386530343538646339323137343431353032386537653330656637343465323839 +63323262303839303261336566386663316334363366346661323131376138626338633435623331 +38643933663134303131373535376636323739333463383834343930336363346435376232363835 +61636165316131623032393234333163643764663539633632393236636232356264623964333732 +32653331313930636366323361346437303465646631623431313332336164303537326535393538 +37623264376530663661613530643731336134626533383134356366393036343133326137396630 +33326536643233346466663931386432653762613639333230663466393662386361663131633563 +62393137643732623566613266323964663431303638663132636633373161333831613134633334 +35383763363366366439396332613534356339326633393830333131333632396233306430343237 +63303264396166393433366464303566316233393335396333393337363933373933343663663332 +66323232626538366433303334633532393465356166333530376230363032323936353666636362 +61363861626562373735633135366333363564663163626434643632323033306561616566396633 +30393766613134316431363364336661323231313361636634326566363139343139623334613366 +35653730626531366634636361393564366564656634303237653565663361343736313263636362 +37316366363965616237306139326338663965373737383066326464383435393039646232303934 +36633836383565643737396234343930323034376664653639393337363330636466626437623636 +30643136323432653733363765363638363065656261383034663837616534346234356462346163 +37316365343762306332313235373565663166316337383938613061666330383030666238343965 +63313534383135306133663336343939386464636530636535666432393433346664656663623338 +30666630633963303663336433303932366339613736636436373464383266636165666335613430 +30343839346262356435393065383434353832623134333535646365353739336638396337356534 +65356366656264373638343863353461383835363135306332636635376131346334613138653665 +31336536656664346465343331643936666636346439353339373433643033363530343430313032 +32343531306537313238623962366666623735613730663463643339323363613434633861343435 +35353737646631376435343932613834363031643939363761633339333633633062383835613131 +34326131373866333832343133616136306462663230386564306439376137373734326134306139 +31326662346134316465616237353530356266356163366237626530343334316566353532653236 +63656261366639323535396165366466306631616665336632396236313437623734643138333764 +31643935643339306462646338343135663730656563373630303731623739663134373438613438 +35666635336465616161653462393537363463366437313135343163386331363830663964373236 +37356661336135343231326634343232643261386263373161303564623762353061306431313730 +36346332346566636565356334653036633639323935386635656331626139316565323935343032 +37666135396631616536643434663935613031643731313631393837313061303963626333343632 +31356164376566656230393637626539666331653063373539333638643236616432343761636663 +39646632333035303263663665623833613763656337616163663164303330323861366135373862 +33346262643636316263383162366430393362626563613737636663366230636162633730383866 +37643161306561613164656638623630333262336632313032313832396436636438663063323862 +35376335346164333932383438376538663162393831323761313031643834303065663831633766 +33386565353565616264386639303463306333396365303764613139326634356438663265373731 +32383435383537353431656536383835396432356366623136353566333631306334643061313232 +38323834633466613739393535633066333861343036633137396435303632636636306661356461 +63646662646233303637326437366633633632623366393630396136633934636435376262323631 +39323237383561313364373331396337356137656233633433646361333063633161666631636364 +34653865383462663165313431373865393938653431396563373832313962616564366439373336 +33303931386363333163666262323832353261386161393462643965333535326636656564383361 +62396662656531626566633239383639363962353463623733616566623639323966613636373364 +35653866656262346238363062353461336136666161386531666134383964626639346132663766 +37333862666366336135373238326335356561366534323139653832353733313364333666383132 +36353436343266346534393563366662623639626132393864653935356437356430356130623130 +63323137663336393633386431643635666661646330356539306161313336376434646434343165 +36653739393861353732613932333430373165633433646133363632303766353263643932626365 +31376261616235343765393737313535616166353961393634386135613636613761623064386334 +32326230373566616639663531336235336234313661323365343432623066613536616131343136 +34643362643932393966393632666264623636313461383534333332623739646433383233383136 +65313965376134323834393539333932643366666535666163363261613866373463653137383931 +65623864326339353162663464643061653931396133393465313133353861333733373237646362 +63663861643539336132306439303963323735643333393563343165626338663233366262386439 +63313335383864663231373066653035343664656430313432376137623031626538663039613737 +66633938353131656566623134323039363764396136303937333536386434663732343533643666 +30306566363138363836663532663932346435353861663466336461333534636464313333663364 +62363436336662386666396565623831366333353765646362373534323334633536663462646432 +39323865613063313034616239666534343435623166313534323136663838316137623862663863 +65393661636430616165656638646335313732656264326638643830663533626135323934303639 +31383535383538343834303533313961353737346665663161613261383538333162376430316438 +36303963346465316434633263616230633137353633393865393431326361393964366565386235 +37366531336138653238653161666232303966326664643663613464306138333935663462313165 +66396533343134616261663465373533333039393630656363663363643632646463626638346138 +31303865333239353533323838363663343961643035343638306339306134396530623631333762 +39333064646134386634643964656636626161366566343934626134666332356636343733623363 +66393332633639383236653433616633316538396436343839396538633637333239346238376262 +65373538656363373333323663623361366261613035393565656663646561313936643633363632 +3565 diff --git a/group_vars/arr/vars.yml b/group_vars/arr/vars.yml new file mode 100644 index 0000000..a6f6c67 --- /dev/null +++ b/group_vars/arr/vars.yml @@ -0,0 +1,4 @@ +ansible_user: sascha +ansible_become_method: su +ansible_password: "{{ vault_sascha_password }}" +ansible_become_password: "{{ vault_sascha_password }}" diff --git a/group_vars/auto/vars.yml b/group_vars/auto/vars.yml new file mode 100644 index 0000000..a6f6c67 --- /dev/null +++ b/group_vars/auto/vars.yml @@ -0,0 +1,4 @@ +ansible_user: sascha +ansible_become_method: su +ansible_password: "{{ vault_sascha_password }}" +ansible_become_password: "{{ vault_sascha_password }}" diff --git a/group_vars/communication/vars.yml b/group_vars/communication/vars.yml new file mode 100644 index 0000000..a6f6c67 --- /dev/null +++ b/group_vars/communication/vars.yml @@ -0,0 +1,4 @@ +ansible_user: sascha +ansible_become_method: su +ansible_password: "{{ vault_sascha_password }}" +ansible_become_password: "{{ vault_sascha_password }}" diff --git a/group_vars/docker/vars.yml b/group_vars/docker/vars.yml new file mode 100644 index 0000000..a6f6c67 --- /dev/null +++ b/group_vars/docker/vars.yml @@ -0,0 +1,4 @@ +ansible_user: sascha +ansible_become_method: su +ansible_password: "{{ vault_sascha_password }}" +ansible_become_password: "{{ vault_sascha_password }}" diff --git a/group_vars/hetzner/borg.yml b/group_vars/hetzner/borg.yml new file mode 100644 index 0000000..326ebb6 --- /dev/null +++ b/group_vars/hetzner/borg.yml @@ -0,0 +1,2 @@ +--- +backup_source: "/etc/wireguard /app-config" diff --git a/group_vars/media/vars.yml b/group_vars/media/vars.yml new file mode 100644 index 0000000..a6f6c67 --- /dev/null +++ b/group_vars/media/vars.yml @@ -0,0 +1,4 @@ +ansible_user: sascha +ansible_become_method: su +ansible_password: "{{ vault_sascha_password }}" +ansible_become_password: "{{ vault_sascha_password }}" diff --git a/group_vars/proxmox/borg.yml b/group_vars/proxmox/borg.yml new file mode 100644 index 0000000..583c531 --- /dev/null +++ b/group_vars/proxmox/borg.yml @@ -0,0 +1,2 @@ +--- +backup_source: "/etc/pve /etc/network /etc/wireguard /etc/crontab /etc/fstab /etc/systemd/system/ /etc/iptables /etc/telegraf" diff --git a/hawser.yml b/hawser.yml index b9b8ea6..155f6d9 100644 --- a/hawser.yml +++ b/hawser.yml @@ -1,14 +1,6 @@ --- -- name: Hawser +- name: Hawser Setup hosts: all become: yes - tasks: - - name: Hawser installieren (offizielles Install-Script) - ansible.builtin.shell: - cmd: curl -fsSL https://raw.githubusercontent.com/Finsys/hawser/main/scripts/install.sh | bash - - name: Hawser aktivieren und starten - ansible.builtin.systemd: - name: hawser - enabled: true - state: started - daemon_reload: true + roles: + - hawser diff --git a/host_vars/arr-chris-live/vars.yml b/host_vars/arr-chris-live/vars.yml new file mode 100644 index 0000000..c2384e1 --- /dev/null +++ b/host_vars/arr-chris-live/vars.yml @@ -0,0 +1,5 @@ +ansible_user: chris +ansible_become_method: sudo +ansible_password: "{{ vault_chris_password }}" +ansible_become_password: "{{ vault_chris_password }}" +base_user: chris diff --git a/host_vars/arr-chris/vars.yml b/host_vars/arr-chris/vars.yml new file mode 100644 index 0000000..c2384e1 --- /dev/null +++ b/host_vars/arr-chris/vars.yml @@ -0,0 +1,5 @@ +ansible_user: chris +ansible_become_method: sudo +ansible_password: "{{ vault_chris_password }}" +ansible_become_password: "{{ vault_chris_password }}" +base_user: chris diff --git a/host_vars/emby-chris/frp.yml b/host_vars/emby-chris/frp.yml new file mode 100644 index 0000000..3935506 --- /dev/null +++ b/host_vars/emby-chris/frp.yml @@ -0,0 +1,6 @@ +--- +frp_proxies: + - name: emby-chris + local_ip: "0.0.0.0" + local_port: 8096 + remote_port: 28096 diff --git a/host_vars/emby-chris/vars.yml b/host_vars/emby-chris/vars.yml new file mode 100644 index 0000000..c2384e1 --- /dev/null +++ b/host_vars/emby-chris/vars.yml @@ -0,0 +1,5 @@ +ansible_user: chris +ansible_become_method: sudo +ansible_password: "{{ vault_chris_password }}" +ansible_become_password: "{{ vault_chris_password }}" +base_user: chris diff --git a/host_vars/emby-sascha/frp.yml b/host_vars/emby-sascha/frp.yml new file mode 100644 index 0000000..cdf2bc3 --- /dev/null +++ b/host_vars/emby-sascha/frp.yml @@ -0,0 +1,6 @@ +--- +frp_proxies: + - name: emby-sascha + local_ip: "0.0.0.0" + local_port: 8096 + remote_port: 18096 diff --git a/host_vars/jellyfin/frp.yml b/host_vars/jellyfin/frp.yml new file mode 100644 index 0000000..c119c41 --- /dev/null +++ b/host_vars/jellyfin/frp.yml @@ -0,0 +1,6 @@ +--- +frp_proxies: + - name: jellyfin + local_ip: "0.0.0.0" + local_port: 8096 + remote_port: 38096 diff --git a/host_vars/node1/wireguard.yml b/host_vars/node1/wireguard.yml new file mode 100644 index 0000000..998d96b --- /dev/null +++ b/host_vars/node1/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.11/24" +wireguard_private_key: "{{ vault_node1_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/host_vars/node2/telegraf.yml b/host_vars/node2/telegraf.yml new file mode 100644 index 0000000..5a2d736 --- /dev/null +++ b/host_vars/node2/telegraf.yml @@ -0,0 +1,3 @@ +--- +telegraf_synology_snmp: true +telegraf_synology_host: "192.168.1.24" diff --git a/host_vars/node2/wireguard.yml b/host_vars/node2/wireguard.yml new file mode 100644 index 0000000..e5b945a --- /dev/null +++ b/host_vars/node2/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.12/24" +wireguard_private_key: "{{ vault_node2_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/host_vars/node3/wireguard.yml b/host_vars/node3/wireguard.yml new file mode 100644 index 0000000..cc2aa6d --- /dev/null +++ b/host_vars/node3/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.13/24" +wireguard_private_key: "{{ vault_node3_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/host_vars/node4/wireguard.yml b/host_vars/node4/wireguard.yml new file mode 100644 index 0000000..dec9b57 --- /dev/null +++ b/host_vars/node4/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.14/24" +wireguard_private_key: "{{ vault_node4_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/host_vars/node5/wireguard.yml b/host_vars/node5/wireguard.yml new file mode 100644 index 0000000..67ea94d --- /dev/null +++ b/host_vars/node5/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.15/24" +wireguard_private_key: "{{ vault_node5_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/host_vars/node6/wireguard.yml b/host_vars/node6/wireguard.yml new file mode 100644 index 0000000..0a22910 --- /dev/null +++ b/host_vars/node6/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.16/24" +wireguard_private_key: "{{ vault_node6_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/host_vars/node7/wireguard.yml b/host_vars/node7/wireguard.yml new file mode 100644 index 0000000..64373e5 --- /dev/null +++ b/host_vars/node7/wireguard.yml @@ -0,0 +1,4 @@ +--- +wireguard_address: "10.200.200.17/24" +wireguard_private_key: "{{ vault_node7_wg_privkey }}" +wireguard_allowed_ips: "10.200.200.0/24" diff --git a/hysteria2-cleanup.yml b/hysteria2-cleanup.yml new file mode 100644 index 0000000..2a1ddcb --- /dev/null +++ b/hysteria2-cleanup.yml @@ -0,0 +1,38 @@ +--- +- name: Hysteria2 von Nodes entfernen + hosts: proxmox + become: yes + tasks: + - name: Hysteria2 Service stoppen und deaktivieren + systemd: + name: hysteria2 + state: stopped + enabled: false + ignore_errors: true + + - name: WireGuard Override entfernen + file: + path: /etc/systemd/system/wg-quick@wg0.service.d + state: absent + notify: reload systemd + + - name: Hysteria2 systemd Unit entfernen + file: + path: /etc/systemd/system/hysteria2.service + state: absent + notify: reload systemd + + - name: Hysteria2 Binary entfernen + file: + path: /usr/local/bin/hysteria + state: absent + + - name: Hysteria2 Config entfernen + file: + path: /etc/hysteria + state: absent + + handlers: + - name: reload systemd + systemd: + daemon_reload: true diff --git a/id_ed25519.pub b/id_ed25519.pub new file mode 100644 index 0000000..3d2b81b --- /dev/null +++ b/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPl/Zptf1zTIgIv01zekT3SqdJfDR10vfTljP1QvHwez sascha@proxy diff --git a/iso-builder/build-iso.sh b/iso-builder/build-iso.sh new file mode 100755 index 0000000..2c6cc14 --- /dev/null +++ b/iso-builder/build-iso.sh @@ -0,0 +1,301 @@ +#!/bin/bash +set -e + +# ============================================================ +# Debian Unattended ISO Builder +# Baut eine Custom Debian ISO mit eingebettetem Preseed +# ============================================================ + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +WORK_DIR="/tmp/iso-builder-$$" +DEBIAN_VERSION="${DEBIAN_VERSION:-13}" +DEBIAN_CODENAME="${DEBIAN_CODENAME:-trixie}" +ARCH="amd64" + +# --- Defaults --- +IP="" +NETMASK="255.255.255.0" +GATEWAY="" +DNS="1.1.1.1" +HOSTNAME="debian" +USER="sascha" +PASSWORD="" +SSH_KEY_FILE="$HOME/.ssh/id_ed25519.pub" +OUTPUT_DIR="$SCRIPT_DIR/output" +NODE="" +VMID="" +CREATE_VM=false +VM_CORES=8 +VM_MEMORY=16384 +VM_DISK=64 + +usage() { + cat </dev/null; then + echo "Installing missing dependency: $cmd" + sudo apt-get install -y xorriso cpio gzip genisoimage 2>/dev/null || true + fi +done + +# --- Password --- +if [[ -z "$PASSWORD" ]]; then + read -sp "Password for user $USER: " PASSWORD + echo +fi +PASSWORD_HASH=$(echo "$PASSWORD" | openssl passwd -6 -stdin) + +# --- SSH Key --- +if [[ -f "$SSH_KEY_FILE" ]]; then + SSH_KEY=$(cat "$SSH_KEY_FILE") +else + echo "Warning: SSH key file not found: $SSH_KEY_FILE" + SSH_KEY="" +fi + +# --- Download Debian ISO --- +ISO_URL="https://cdimage.debian.org/debian-cd/current/${ARCH}/iso-cd/debian-${DEBIAN_VERSION}.*-${ARCH}-netinst.iso" +ISO_FILE="$SCRIPT_DIR/debian-${DEBIAN_VERSION}-${ARCH}-netinst.iso" + +if [[ ! -f "$ISO_FILE" ]]; then + echo "Downloading Debian ${DEBIAN_VERSION} netinstall ISO..." + # Get exact filename from listing + EXACT_URL=$(curl -sL "https://cdimage.debian.org/debian-cd/current/${ARCH}/iso-cd/" | \ + grep -oP "debian-${DEBIAN_VERSION}\.[0-9]+-${ARCH}-netinst\.iso" | head -1) + wget -q --show-progress -O "$ISO_FILE" \ + "https://cdimage.debian.org/debian-cd/current/${ARCH}/iso-cd/${EXACT_URL}" +fi + +echo "Building ISO for: ${HOSTNAME} (${IP})" + +# --- Extract ISO --- +cleanup() { rm -rf "$WORK_DIR"; } +trap cleanup EXIT + +mkdir -p "$WORK_DIR"/{iso,custom} + +xorriso -osirrox on -indev "$ISO_FILE" -extract / "$WORK_DIR/iso" 2>/dev/null +chmod -R u+w "$WORK_DIR/iso" + +# --- Generate Preseed --- +PRESEED="$WORK_DIR/iso/preseed.cfg" +sed \ + -e "s|{{IP}}|${IP}|g" \ + -e "s|{{NETMASK}}|${NETMASK}|g" \ + -e "s|{{GATEWAY}}|${GATEWAY}|g" \ + -e "s|{{DNS}}|${DNS}|g" \ + -e "s|{{HOSTNAME}}|${HOSTNAME}|g" \ + -e "s|{{USER}}|${USER}|g" \ + -e "s|{{PASSWORD_HASH}}|${PASSWORD_HASH}|g" \ + -e "s|{{SSH_KEY}}|${SSH_KEY}|g" \ + "$SCRIPT_DIR/preseed.cfg.tpl" > "$PRESEED" + +# --- Patch GRUB (UEFI) - komplett ersetzen --- +GRUB_CFG="$WORK_DIR/iso/boot/grub/grub.cfg" +if [[ -f "$GRUB_CFG" ]]; then + cat > "$GRUB_CFG" << GRUBEOF +set default=0 +set timeout=0 + +menuentry "Debian Auto Install - ${HOSTNAME}" { + linux /install.amd/vmlinuz auto=true priority=critical preseed/file=/cdrom/preseed.cfg --- + initrd /install.amd/initrd.gz +} +GRUBEOF +fi + +# --- Patch isolinux (BIOS) - komplett ersetzen --- +TXT_CFG="$WORK_DIR/iso/isolinux/txt.cfg" +if [[ -f "$TXT_CFG" ]]; then + cat > "$TXT_CFG" << TXTEOF +default auto +label auto + menu label Auto Install - ${HOSTNAME} + kernel /install.amd/vmlinuz + append auto=true priority=critical preseed/file=/cdrom/preseed.cfg initrd=/install.amd/initrd.gz --- +TXTEOF +fi + +ISOLINUX_CFG="$WORK_DIR/iso/isolinux/isolinux.cfg" +if [[ -f "$ISOLINUX_CFG" ]]; then + sed -i 's/timeout .*/timeout 1/' "$ISOLINUX_CFG" +fi + +# --- Rebuild ISO --- +mkdir -p "$OUTPUT_DIR" +OUTPUT_ISO="$OUTPUT_DIR/debian-${DEBIAN_VERSION}-${HOSTNAME}-${IP}.iso" + +cd "$WORK_DIR/iso" + +# Fix MD5 +find . -type f ! -name 'md5sum.txt' -exec md5sum {} \; > md5sum.txt 2>/dev/null || true + +xorriso -as mkisofs \ + -r -J \ + -b isolinux/isolinux.bin \ + -c isolinux/boot.cat \ + -no-emul-boot \ + -boot-load-size 4 \ + -boot-info-table \ + -eltorito-alt-boot \ + -e boot/grub/efi.img \ + -no-emul-boot \ + -isohybrid-gpt-basdat \ + -o "$OUTPUT_ISO" \ + . 2>/dev/null + +echo "" +echo "============================================" +echo "ISO created: $OUTPUT_ISO" +echo "============================================" +echo "Host: $HOSTNAME" +echo "IP: $IP" +echo "Gateway: $GATEWAY" +echo "User: $USER" +echo "SSH Key: $(echo $SSH_KEY | cut -c1-40)..." +echo "============================================" +echo "" +if [[ -n "$PVE_HOST" ]]; then + echo "Uploading to node${NODE} (${PVE_HOST})..." + scp -o StrictHostKeyChecking=no "$OUTPUT_ISO" "root@${PVE_HOST}:/var/lib/vz/template/iso/" && \ + echo "✅ ISO uploaded to node${NODE}" || \ + { echo "❌ Upload failed"; exit 1; } + + if [[ "$CREATE_VM" == true ]]; then + ISO_NAME="$(basename "$OUTPUT_ISO")" + STORAGE="powerstore-node${NODE}" + PVE_NODE="node${NODE}" + + # Auto-assign next free VMID if not specified + if [[ -z "$VMID" ]]; then + VMID=$(ssh -o StrictHostKeyChecking=no "root@${PVE_HOST}" "pvesh get /cluster/nextid" 2>/dev/null) + echo "Auto-assigned VMID: ${VMID}" + fi + + echo "" + echo "Creating VM ${VMID} on ${PVE_NODE}..." + ssh -o StrictHostKeyChecking=no "root@${PVE_HOST}" " + # Create VM: q35, UEFI, virtio-scsi + pvesh create /nodes/${PVE_NODE}/qemu \ + --vmid ${VMID} \ + --name ${HOSTNAME} \ + --machine q35 \ + --bios ovmf \ + --efidisk0 ${STORAGE}:1,efitype=4m,pre-enrolled-keys=0 \ + --scsihw virtio-scsi-pci \ + --scsi0 ${STORAGE}:${VM_DISK},cache=writeback \ + --ide2 local:iso/${ISO_NAME},media=cdrom \ + --net0 virtio,bridge=vmbr0 \ + --cores ${VM_CORES} \ + --memory ${VM_MEMORY} \ + --cpu cputype=host \ + --agent enabled=1 \ + --boot order='scsi0;ide2' \ + --ostype l26 \ + --onboot 1 \ + --numa 1 \ + --balloon 0 \ + --serial0 socket + " && echo "✅ VM ${VMID} created" || { echo "❌ VM creation failed"; exit 1; } + + echo "Starting VM ${VMID}..." + ssh -o StrictHostKeyChecking=no "root@${PVE_HOST}" \ + "pvesh create /nodes/${PVE_NODE}/qemu/${VMID}/status/start" && \ + echo "✅ VM ${VMID} started - installing Debian..." || echo "❌ VM start failed" + + echo "" + echo "============================================" + echo "Boot order: scsi0 → ide2 (disk first, ISO fallback)" + echo "1st boot: disk empty → boots ISO → installs Debian" + echo "2nd boot: disk has GRUB → boots from disk → done!" + echo "" + echo "After installation (~5 min):" + echo " ssh ${USER}@${IP}" + echo " ansible-playbook site.yml -l ${HOSTNAME}" + echo "============================================" + fi +else + echo "Upload to Proxmox:" + echo " scp $OUTPUT_ISO root@:/var/lib/vz/template/iso/" +fi diff --git a/iso-builder/preseed.cfg.tpl b/iso-builder/preseed.cfg.tpl new file mode 100644 index 0000000..df73252 --- /dev/null +++ b/iso-builder/preseed.cfg.tpl @@ -0,0 +1,74 @@ +# Debian Preseed - Unattended Install + +### Locale & Keyboard +d-i debian-installer/locale string de_DE.UTF-8 +d-i keyboard-configuration/xkb-keymap select de +d-i console-setup/ask_detect boolean false + +### Netzwerk (statisch) +d-i netcfg/choose_interface select auto +d-i netcfg/disable_autoconfig boolean true +d-i netcfg/get_ipaddress string {{IP}} +d-i netcfg/get_netmask string {{NETMASK}} +d-i netcfg/get_gateway string {{GATEWAY}} +d-i netcfg/get_nameservers string {{DNS}} +d-i netcfg/confirm_static boolean true +d-i netcfg/get_hostname string {{HOSTNAME}} +d-i netcfg/get_domain string local + +### Clock +d-i clock-setup/utc boolean true +d-i time/zone string Europe/Berlin +d-i clock-setup/ntp boolean true + +### User + Root +d-i passwd/root-login boolean true +d-i passwd/root-password-crypted string {{PASSWORD_HASH}} +d-i passwd/user-fullname string {{USER}} +d-i passwd/username string {{USER}} +d-i passwd/user-password-crypted string {{PASSWORD_HASH}} + +### Partitioning (auto LVM) +d-i partman-auto/method string lvm +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman-auto/choose_recipe select atomic +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + +### Mirror +d-i mirror/country string manual +d-i mirror/http/hostname string deb.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string + +### Packages +tasksel tasksel/first multiselect standard, ssh-server +d-i pkgsel/include string sudo qemu-guest-agent curl wget ca-certificates gnupg openssh-server +d-i pkgsel/upgrade select full-upgrade +popularity-contest popularity-contest/participate boolean false + +### Grub +d-i grub-installer/only_debian boolean true +d-i grub-installer/bootdev string default + +### Late commands - SSH Key, Sudo, Locale +d-i preseed/late_command string \ + in-target mkdir -p /home/{{USER}}/.ssh; \ + echo '{{SSH_KEY}}' > /target/home/{{USER}}/.ssh/authorized_keys; \ + in-target chmod 700 /home/{{USER}}/.ssh; \ + in-target chmod 600 /home/{{USER}}/.ssh/authorized_keys; \ + in-target chown -R {{USER}}:{{USER}} /home/{{USER}}/.ssh; \ + echo '{{USER}} ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/{{USER}}; \ + in-target chmod 440 /etc/sudoers.d/{{USER}}; \ + in-target systemctl enable ssh; \ + in-target systemctl enable qemu-guest-agent; \ + in-target sed -i 's/# de_DE.UTF-8/de_DE.UTF-8/' /etc/locale.gen; \ + in-target locale-gen; + +### Finish +d-i finish-install/reboot_in_progress note +d-i cdrom-detect/eject boolean true diff --git a/iso-builder/readme.md b/iso-builder/readme.md new file mode 100644 index 0000000..61d4f86 --- /dev/null +++ b/iso-builder/readme.md @@ -0,0 +1,264 @@ +# Debian 13 Fully Unattended ISO – EXTREM DETAILLIERTE ANLEITUNG + +Ziel: Eine **komplett automatisierte Debian 13 ISO** bauen, die: + +- ohne Benutzerinteraktion installiert (unattended) +- automatisch startet (kein GRUB-Menü) +- Sprache, Tastatur, Zeitzone setzt +- statische Netzwerkkonfiguration verwendet (IP / Gateway / DNS) +- Root + User inkl. Passwort erstellt +- automatisch partitioniert (LVM) +- GRUB installiert +- automatisch rebootet + +Diese Anleitung ist bewusst **sehr detailliert und deterministisch**, damit auch eine einfache KI sie korrekt ausführen kann. + +--- + +# 0. WICHTIGE GRUNDLOGIK + +Die Automatisierung basiert auf: + +1. **preseed.cfg** → enthält alle Antworten für den Debian Installer +2. **Bootparameter** → sorgen dafür, dass preseed geladen wird +3. **GRUB + ISOLINUX Anpassung** → damit KEIN Menü erscheint + +--- + +# 1. SYSTEM VORBEREITEN + +## 1.1 Pakete installieren + +```bash +apt update +apt install -y xorriso syslinux isolinux grub-pc-bin grub-efi-amd64-bin mtools dosfstools + +mkdir -p ~/debian-auto-iso/{src,iso,build} +cd ~/debian-auto-iso +~/debian-auto-iso/ + ├── src/ (Original ISO) + ├── iso/ (entpackte ISO – wird bearbeitet) + └── build/ (fertige ISO) + +cd ~/debian-auto-iso/src +wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.0.0-amd64-netinst.iso + +cd ~/debian-auto-iso +xorriso -osirrox on \ + -indev src/debian-13.0.0-amd64-netinst.iso \ + -extract / iso + +chmod -R u+w iso + +nano iso/preseed.cfg + +### -------------------------------- +### LOKALISIERUNG +### -------------------------------- +d-i debian-installer/locale string de_DE.UTF-8 +d-i keyboard-configuration/xkb-keymap select de +d-i console-setup/ask_detect boolean false + +### -------------------------------- +### NETZWERK (STATISCH!) +### -------------------------------- +d-i netcfg/choose_interface select auto +d-i netcfg/disable_autoconfig boolean true + +d-i netcfg/get_ipaddress string 192.168.100.10 +d-i netcfg/get_netmask string 255.255.255.0 +d-i netcfg/get_gateway string 192.168.100.1 +d-i netcfg/get_nameservers string 192.168.100.1 + +d-i netcfg/confirm_static boolean true +d-i netcfg/get_hostname string debian-vm +d-i netcfg/get_domain string local + +### -------------------------------- +### ZEIT +### -------------------------------- +d-i clock-setup/utc boolean true +d-i time/zone string Europe/Berlin +d-i clock-setup/ntp boolean true + +### -------------------------------- +### USER + PASSWÖRTER +### -------------------------------- +d-i passwd/root-login boolean true +d-i passwd/root-password password rootpass +d-i passwd/root-password-again password rootpass + +d-i passwd/user-fullname string Default User +d-i passwd/username string user +d-i passwd/user-password password userpass +d-i passwd/user-password-again password userpass + +### -------------------------------- +### PARTITIONIERUNG (AUTO LVM!) +### -------------------------------- +d-i partman-auto/method string lvm +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-auto/choose_recipe select atomic + +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman/choose_partition select finish + +### -------------------------------- +### MIRROR +### -------------------------------- +d-i mirror/country string manual +d-i mirror/http/hostname string deb.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string + +### -------------------------------- +### PAKETE +### -------------------------------- +tasksel tasksel/first multiselect standard, ssh-server + +d-i pkgsel/include string vim curl htop sudo +d-i pkgsel/upgrade select full-upgrade + +popularity-contest popularity-contest/participate boolean false + +### -------------------------------- +### GRUB INSTALLATION +### -------------------------------- +d-i grub-installer/only_debian boolean true +d-i grub-installer/bootdev string default + +### -------------------------------- +### INSTALLATION ABSCHLIESSEN +### -------------------------------- +d-i finish-install/reboot_in_progress note +d-i cdrom-detect/eject boolean true + +### -------------------------------- +### LATE COMMAND (OPTIONAL) +### -------------------------------- +d-i preseed/late_command string \ + in-target systemctl enable ssh; \ + in-target usermod -aG sudo user + + +nano iso/boot/grub/grub.cfg + +set default=0 +set timeout=0 + +menuentry "Debian Auto Install" { + linux /install.amd/vmlinuz auto=true priority=critical preseed/file=/cdrom/preseed.cfg --- + initrd /install.amd/initrd.gz +} + +nano iso/isolinux/txt.cfg + +default auto +timeout 0 + +label auto + menu label Auto Install Debian + kernel /install.amd/vmlinuz + append auto=true priority=critical preseed/file=/cdrom/preseed.cfg initrd=/install.amd/initrd.gz --- + + +cd ~/debian-auto-iso + +xorriso -as mkisofs \ + -r \ + -V "DEBIAN_AUTO" \ + -o build/debian-13-auto.iso \ + -J -joliet-long -l \ + -b isolinux/isolinux.bin \ + -c isolinux/boot.cat \ + -no-emul-boot \ + -boot-load-size 4 \ + -boot-info-table \ + -eltorito-alt-boot \ + -e boot/grub/efi.img \ + -no-emul-boot \ + -isohybrid-gpt-basdat \ + iso + + +10. ERWARTETES VERHALTEN + +Nach Boot: + +KEIN Menü erscheint +Installer startet automatisch +Keine Eingaben notwendig +Installation läuft komplett durch +System rebootet automatisch +Login möglich mit: +user / userpass +root / rootpass +11. HÄUFIGE FEHLER + DEBUG +Installer fragt trotzdem Dinge ab + +→ Ursache: + +falscher Parameter: preseed/file= fehlt +falscher Pfad: /cdrom/preseed.cfg +Netzwerk funktioniert nicht + +→ Ursache: + +falsches Interface +falsche IP Range +Gateway nicht erreichbar +ISO bootet nicht (UEFI) + +→ Ursache: + +efi.img fehlt +xorriso Flags falsch +GRUB Menü erscheint trotzdem + +→ Ursache: + +timeout != 0 +falsche cfg bearbeitet + + + +METHODE 2 (BESTE LÖSUNG): ISO NACH INSTALLATION "EJECTEN" +Idee: + +Installer wirft CD automatisch aus → VM bootet von HDD + +PRESEED ERWEITERN + +In preseed.cfg hinzufügen: + +d-i cdrom-detect/eject boolean true +ZUSÄTZLICH (WICHTIG!): +d-i finish-install/keep-consoles boolean true +d-i finish-install/reboot_in_progress note + +👉 Ergebnis: + +ISO wird logisch "ausgeworfen" +viele Hypervisor erkennen das +Boot fällt automatisch auf HDD zurück + +👉 Achtung: +Funktioniert zuverlässig bei: + +Proxmox ✅ +KVM/QEMU ✅ +VMware ⚠️ (teilweise) +VirtualBox ⚠️ (oft nicht) +✅ METHODE 3 (PROFI / 100% LÖSUNG): VM-SEITIG BOOT FIXEN +BESTE UND SAUBERSTE LÖSUNG + +Nicht ISO lösen – sondern VM korrekt konfigurieren. + +🔧 PROXMOX +qm set --boot order=scsi0 +qm set --cdrom none + +Oder direkt beim Erstellen: + +qm create 100 --boot order=scsi0 diff --git a/nvidia-docker.yml b/nvidia-docker.yml new file mode 100644 index 0000000..4e12c00 --- /dev/null +++ b/nvidia-docker.yml @@ -0,0 +1,8 @@ +--- +- name: NVIDIA Treiber + Docker GPU Setup + hosts: all + become: yes + environment: + PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + roles: + - nvidia diff --git a/nvidia.yml b/nvidia.yml deleted file mode 100644 index 49849d3..0000000 --- a/nvidia.yml +++ /dev/null @@ -1,88 +0,0 @@ ---- -- name: NVIDIA + Docker Setup fuer Debian Trixie - hosts: all - become: true - - vars: - docker_daemon_config: - default-runtime: nvidia - runtimes: - nvidia: - path: nvidia-container-runtime - runtimeArgs: [] - - tasks: - - # --- Repos ---------------------------------------------------------------- - - - name: NVIDIA Container Toolkit GPG Key hinzufuegen - ansible.builtin.shell: | - curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \ - | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg - args: - creates: /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg - - - name: NVIDIA Container Toolkit Repo hinzufuegen - ansible.builtin.shell: | - curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \ - | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \ - | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list - args: - creates: /etc/apt/sources.list.d/nvidia-container-toolkit.list - - - name: apt update - ansible.builtin.apt: - update_cache: true - - # --- Pakete --------------------------------------------------------------- - - name: Kernel Headers und DKMS installieren - ansible.builtin.apt: - name: - - linux-headers-{{ ansible_kernel }} - - dkms - state: present - - - name: NVIDIA Treiber installieren - ansible.builtin.apt: - name: - - "nvidia-driver" - state: present - - - name: NVIDIA Container Toolkit installieren - ansible.builtin.apt: - name: - - nvidia-container-toolkit - - nvidia-docker2 - state: present - - - name: NFS und CIFS Pakete installieren - ansible.builtin.apt: - name: - - nfs-common - - cifs-utils - state: present - - # --- Docker konfigurieren ------------------------------------------------- - - - name: /etc/docker Verzeichnis sicherstellen - ansible.builtin.file: - path: /etc/docker - state: directory - mode: "0755" - - - name: Docker daemon.json konfigurieren (NVIDIA als default runtime) - ansible.builtin.copy: - content: "{{ docker_daemon_config | to_nice_json }}" - dest: /etc/docker/daemon.json - mode: "0644" - notify: Docker neustarten - - - name: nvidia-ctk runtime fuer Docker konfigurieren - ansible.builtin.command: nvidia-ctk runtime configure --runtime=docker - changed_when: false - - handlers: - - name: Docker neustarten - ansible.builtin.service: - name: docker - state: restarted diff --git a/pfannkuchen.ini b/pfannkuchen.ini index ce670e9..b0d5852 100644 --- a/pfannkuchen.ini +++ b/pfannkuchen.ini @@ -1,45 +1,87 @@ [proxmox] -node1 ansible_host=10.10.1.1 -node2 ansible_host=10.5.85.200 -node4 ansible_host=10.5.85.100 -node5 ansible_host=10.5.85.101 +node1 ansible_host=10.5.85.11 +node2 ansible_host=10.5.85.12 +node3 ansible_host=10.5.85.13 +node4 ansible_host=10.5.85.14 +node5 ansible_host=10.5.85.15 +node6 ansible_host=10.5.85.16 +node7 ansible_host=10.5.85.17 [proxmox:vars] ansible_user=root [media] -emby_sascha ansible_host=10.5.1.103 ansible_user=sascha -emby_chris ansible_host=10.5.1.106 ansible_user=chris -jellyfin ansible_host=10.5.1.112 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 -immich ansible_host=10.4.1.107 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 -emby_chris_new ansible_host=10.5.1.117 ansible_user=chris ansible_become_method=su ansible_become_password=Pimmelparty123 ansible_password=Pimmelparty123 - +emby-sascha ansible_host=10.6.1.103 +jellyfin ansible_host=10.5.1.112 +immich ansible_host=10.4.1.107 +emby-chris ansible_host=10.7.1.106 [arr] -tdarr ansible_host=10.2.1.104 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 -arrapps ansible_host=10.2.1.100 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 -sabnzbd ansible_host=10.2.1.119 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 +tdarr ansible_host=10.2.1.104 +arrapps ansible_host=10.2.1.100 +sabnzbd ansible_host=10.2.1.119 +arr-chris ansible_host=10.7.1.100 +arr-chris-live ansible_host=10.7.1.101 [docker] -dockhand ansible_host=10.4.1.116 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 ansible_password=GT500r8 +dockhand ansible_host=10.4.1.116 [auto] -n8n ansible_host=10.4.1.113 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 ansible_password=GT500r8 -ansible ansible_host=localhost ansible_user=root +n8n ansible_host=10.4.1.113 +openclaw ansible_host=10.4.1.100 +monitoring ansible_host=10.1.1.111 +automation ansible_host=10.1.1.115 +automation1 ansible_host=10.5.85.5 [communication] -matrix ansible_host=10.4.1.110 ansible_user=sascha ansible_become_method=su ansible_become_password=GT500r8 ansible_password=GT500r8 +matrix ansible_host=10.4.1.110 +pihole ansible_host=10.1.1.10 [hetzner] -emby ansible_host=emby ansible_user=root -proxy ansible_host=proxy ansible_user=root +pfannkuchen ansible_host=159.69.245.190 ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_ed25519 +[nvidia] +tdarr +emby-sascha +emby-chris +immich + +[proxmox_gpu] +node2 +node4 +node6 +node7 + +[frp] +emby-sascha +emby-chris +jellyfin + +[wireguard] +node1 +node2 +node3 +node4 +node5 +node6 +node7 [all:children] media arr -media docker auto +communication hetzner -#proxmox +proxmox + +[backup:children] +media +arr +docker +auto +communication +proxmox +hetzner + +# Credentials liegen in group_vars/ (nicht im INI, da kein Jinja2-Support) diff --git a/pfannkuchen.sh b/pfannkuchen.sh new file mode 100755 index 0000000..b492758 --- /dev/null +++ b/pfannkuchen.sh @@ -0,0 +1,148 @@ +#!/bin/bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +# Farben +R='\033[0;31m' G='\033[0;32m' Y='\033[1;33m' C='\033[0;36m' B='\033[1m' N='\033[0m' + +usage() { + echo -e "${B}🥞 Pfannkuchen – Ansible Wrapper${N}\n" + echo -e "${B}Usage:${N} $0 [host/gruppe]\n" + echo -e "${B}Commands:${N}" + echo -e " ${C}setup${N} Neue VM einrichten (base + docker + borg + hawser + sysctl)" + echo -e " ${C}base${N} Nur Basis + Docker" + echo -e " ${C}gpu${N} NVIDIA Treiber + Docker GPU Runtime" + echo -e " ${C}backup${N} [host] Borg Backup einrichten (default: alle backup-Hosts)" + echo -e " ${C}hawser${N} Hawser installieren" + echo -e " ${C}pve${N} [host] Proxmox Post-Install (Repos, Nag, HA)" + echo -e " ${C}passthrough${N} [host] GPU PCI Passthrough vorbereiten" + echo -e " ${C}telegraf${N} [host] Telegraf Monitoring deployen" + echo -e " ${C}wstunnel${N} [host] wstunnel + WireGuard deployen" + echo -e " ${C}tune${N} Sysctl Netzwerk-Tuning" + echo -e " ${C}pvetune${N} [host] Proxmox Host Tuning (sysctl, resolv, hosts)" + echo -e " ${C}update${N} [host] Dist-Upgrade (default: alle Hosts)" + echo -e " ${C}list${N} Inventory anzeigen" + echo -e " ${C}ping${N} [host] Erreichbarkeit testen" + echo -e " ${C}reboot${N} Reboot durchfuehren" + echo -e " ${C}shell${N} Ad-hoc Shell-Befehl ausfuehren" + echo -e "" + echo -e "${B}Beispiele:${N}" + echo -e " $0 setup emby_sascha" + echo -e " $0 backup proxmox" + echo -e " $0 update" + echo -e " $0 gpu tdarr" + echo -e " $0 reboot nvidia" + echo -e " $0 shell media 'uptime'" + exit 1 +} + +run() { + local playbook="$1"; shift + echo -e "${G}▶${N} ansible-playbook ${playbook} $*" + ansible-playbook "$playbook" "$@" +} + +[ $# -lt 1 ] && usage + +CMD="$1" +HOST="${2:-}" + +case "$CMD" in + setup) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host angeben${N}" && exit 1 + run site.yml -l "$HOST" + ;; + base) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host angeben${N}" && exit 1 + run base-debian.yml -l "$HOST" + ;; + gpu) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host angeben${N}" && exit 1 + run nvidia-docker.yml -l "$HOST" + ;; + backup) + if [ -n "$HOST" ]; then + run borg-backup.yml -l "$HOST" + else + run borg-backup.yml + fi + ;; + hawser) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host angeben${N}" && exit 1 + run hawser.yml -l "$HOST" + ;; + tune) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host angeben${N}" && exit 1 + run sysctl.yaml -l "$HOST" + ;; + pvetune) + if [ -n "$HOST" ]; then + run sysctl-proxmox.yaml -l "$HOST" + else + run sysctl-proxmox.yaml + fi + ;; + pve) + if [ -n "$HOST" ]; then + run pve-postinstall.yml -l "$HOST" + else + run pve-postinstall.yml + fi + ;; + passthrough) + if [ -n "$HOST" ]; then + run pve-gpu-passthrough.yml -l "$HOST" + else + run pve-gpu-passthrough.yml + fi + ;; + telegraf) + if [ -n "$HOST" ]; then + run telegraf.yml -l "$HOST" + else + run telegraf.yml + fi + ;; + wstunnel) + if [ -n "$HOST" ]; then + run wstunnel.yml -l "$HOST" + else + run wstunnel.yml + fi + ;; + update) + if [ -n "$HOST" ]; then + run update.yml -l "$HOST" + else + run update.yml + fi + ;; + list) + ansible-inventory --list --yaml 2>/dev/null || ansible-inventory --graph + ;; + ping) + if [ -n "$HOST" ]; then + ansible "$HOST" -m ping + else + ansible all -m ping + fi + ;; + reboot) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host oder Gruppe angeben${N}" && exit 1 + echo -e "${Y}⚠ Reboot von: $HOST${N}" + ansible "$HOST" -m reboot -b -a "msg='Reboot via Pfannkuchen'" + ;; + shell) + [ -z "$HOST" ] && echo -e "${R}Fehler: Host und Befehl angeben${N}" && exit 1 + SHCMD="${*:3}" + [ -z "$SHCMD" ] && echo -e "${R}Fehler: Befehl angeben${N}" && exit 1 + echo -e "${G}▶${N} ansible $HOST -m shell -a '$SHCMD'" + ansible "$HOST" -m shell -b -a "$SHCMD" + ;; + *) + echo -e "${R}Unbekannter Befehl: $CMD${N}" + usage + ;; +esac diff --git a/pihole-dns.yml b/pihole-dns.yml new file mode 100644 index 0000000..668e837 --- /dev/null +++ b/pihole-dns.yml @@ -0,0 +1,6 @@ +--- +- name: Pi-hole DNS Records deployen + hosts: pihole + become: yes + roles: + - pihole_dns diff --git a/pve-gpu-passthrough.yml b/pve-gpu-passthrough.yml new file mode 100644 index 0000000..e15c4b6 --- /dev/null +++ b/pve-gpu-passthrough.yml @@ -0,0 +1,6 @@ +--- +- name: GPU PCI Passthrough vorbereiten + hosts: proxmox_gpu + become: yes + roles: + - pve_gpu_passthrough diff --git a/pve-postinstall.yml b/pve-postinstall.yml new file mode 100644 index 0000000..ebee271 --- /dev/null +++ b/pve-postinstall.yml @@ -0,0 +1,6 @@ +--- +- name: Proxmox Post-Install Setup + hosts: proxmox + become: yes + roles: + - pve_postinstall diff --git a/roles/base/defaults/main.yml b/roles/base/defaults/main.yml new file mode 100644 index 0000000..22926a1 --- /dev/null +++ b/roles/base/defaults/main.yml @@ -0,0 +1,2 @@ +--- +base_user: sascha diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml new file mode 100644 index 0000000..fe4cf28 --- /dev/null +++ b/roles/base/tasks/main.yml @@ -0,0 +1,134 @@ +--- +- name: Hostname setzen + hostname: + name: "{{ inventory_hostname }}" + +- name: /etc/hosts aktualisieren + lineinfile: + path: /etc/hosts + regexp: '^127\.0\.1\.1' + line: "127.0.1.1 {{ inventory_hostname }}.local {{ inventory_hostname }}" + +- name: SSH Public Key für Benutzer {{ base_user }} hinterlegen + ansible.posix.authorized_key: + user: "{{ base_user }}" + state: present + key: "{{ vault_ssh_pubkey }}" + +- name: SSH Private Key für Benutzer {{ base_user }} deployen + copy: + content: "{{ vault_ssh_privkey }}\n" + dest: "/home/{{ base_user }}/.ssh/id_ed25519" + owner: "{{ base_user }}" + group: "{{ base_user }}" + mode: "0600" + +- name: SSH Public Key Datei für Benutzer {{ base_user }} deployen + copy: + content: "{{ vault_ssh_pubkey }}\n" + dest: "/home/{{ base_user }}/.ssh/id_ed25519.pub" + owner: "{{ base_user }}" + group: "{{ base_user }}" + mode: "0644" + +- name: SSH Key auch für root hinterlegen + ansible.posix.authorized_key: + user: root + state: present + key: "{{ vault_ssh_pubkey }}" + +- name: SSH Private Key für root deployen + copy: + content: "{{ vault_ssh_privkey }}\n" + dest: /root/.ssh/id_ed25519 + owner: root + group: root + mode: "0600" + +- name: Standard Debian Trixie Repositories setzen + copy: + dest: /etc/apt/sources.list + content: | + deb http://ftp.gwdg.de/debian/ trixie main non-free-firmware non-free contrib + deb-src http://ftp.gwdg.de/debian/ trixie main non-free-firmware non-free contrib + + deb http://security.debian.org/debian-security trixie-security main non-free-firmware non-free contrib + deb-src http://security.debian.org/debian-security trixie-security main non-free-firmware non-free contrib + + deb http://ftp.gwdg.de/debian/ trixie-updates main non-free-firmware non-free contrib + deb-src http://ftp.gwdg.de/debian/ trixie-updates main non-free-firmware non-free contrib + owner: root + group: root + mode: '0644' + register: repo_status + +- name: Apt Cache aktualisieren (falls Repos geändert wurden) + apt: + update_cache: yes + when: repo_status.changed + +- name: Installiere benötigte Basis-Pakete + apt: + name: + - curl + - gnupg + - ca-certificates + - sudo + - wget + - vim + - mc + state: present + update_cache: yes + +- name: Locales-Paket sicherstellen + apt: + name: locales + state: present + +- name: en_US.UTF-8 Locale generieren + locale_gen: + name: en_US.UTF-8 + state: present + +- name: Systemweite Sprache auf en_US.UTF-8 setzen + debconf: + name: locales + question: locales/default_environment_locale + value: en_US.UTF-8 + vtype: select + +- name: Locale-Datei manuell schreiben (Sicherheitsnetz) + copy: + dest: /etc/default/locale + content: | + LANG=en_US.UTF-8 + LC_ALL=en_US.UTF-8 + +- name: Gruppe sudo passwortloses sudo erlauben + lineinfile: + path: /etc/sudoers + state: present + regexp: '^%sudo' + line: '%sudo ALL=(ALL:ALL) NOPASSWD: ALL' + validate: '/usr/sbin/visudo -cf %s' + +- name: Benutzer {{ base_user }} zu sudo Gruppe hinzufügen + user: + name: "{{ base_user }}" + groups: sudo + append: yes + +- name: Unnötige Pakete entfernen + apt: + autoremove: yes + +- name: QEMU Guest Agent installieren + apt: + name: qemu-guest-agent + state: present + +- name: QEMU Guest Agent aktivieren + service: + name: qemu-guest-agent + state: started + enabled: yes diff --git a/roles/borg/defaults/main.yml b/roles/borg/defaults/main.yml new file mode 100644 index 0000000..be2e969 --- /dev/null +++ b/roles/borg/defaults/main.yml @@ -0,0 +1,14 @@ +--- +backup_source: /app-config +borg_ssh_key: /root/.ssh/id_borg +borg_passphrase: "{{ vault_borg_passphrase }}" +borg_repo: "ssh://storagebox/home/{{ inventory_hostname }}" +borg_retention_daily: 7 +borg_retention_weekly: 4 +borg_retention_monthly: 6 +borg_compression: lz4 +borg_remote_path: borg-1.4 +borg_logfile: /var/log/borg-backup.log +hetzner_storage_host: "{{ vault_hetzner_storage_host }}" +hetzner_storage_user: "{{ vault_hetzner_storage_user }}" +hetzner_storage_port: 23 diff --git a/roles/borg/tasks/main.yml b/roles/borg/tasks/main.yml new file mode 100644 index 0000000..7361cf6 --- /dev/null +++ b/roles/borg/tasks/main.yml @@ -0,0 +1,94 @@ +--- +- name: Borg installieren + apt: + name: borgbackup + state: present + update_cache: yes + +- name: SSH Private Key deployen + copy: + src: id_rsa + dest: "{{ borg_ssh_key }}" + mode: '0600' + +- name: SSH Public Key deployen + copy: + src: id_rsa.pub + dest: "{{ borg_ssh_key }}.pub" + mode: '0644' + +- name: SSH Config für Storage Box + blockinfile: + path: /root/.ssh/config + create: yes + mode: '0600' + marker: "# {mark} BORG STORAGEBOX" + block: | + Host storagebox + Hostname {{ hetzner_storage_host }} + User {{ hetzner_storage_user }} + Port {{ hetzner_storage_port }} + IdentityFile {{ borg_ssh_key }} + IdentitiesOnly yes + StrictHostKeyChecking accept-new + +- name: Backup-Verzeichnis auf Storage Box anlegen + command: ssh storagebox mkdir -p home/{{ inventory_hostname }} + changed_when: false + +- name: Borg Repo initialisieren + environment: + BORG_PASSPHRASE: "{{ borg_passphrase }}" + command: borg init --encryption=repokey {{ borg_repo }} + register: borg_init + failed_when: borg_init.rc != 0 and 'already exists' not in borg_init.stderr + changed_when: borg_init.rc == 0 + +- name: Passphrase-Datei deployen + copy: + dest: /root/.borg-passphrase + content: "{{ borg_passphrase }}" + mode: '0400' + +- name: Backup-Script deployen + template: + src: borg-backup.sh.j2 + dest: /usr/local/bin/borg-backup.sh + mode: '0700' + +- name: Systemd Timer Unit + copy: + dest: /etc/systemd/system/borg-backup.timer + content: | + [Unit] + Description=Borg Backup Timer + + [Timer] + OnCalendar=*-*-* 03:00:00 + RandomizedDelaySec=1800 + Persistent=true + + [Install] + WantedBy=timers.target + +- name: Systemd Service Unit + copy: + dest: /etc/systemd/system/borg-backup.service + content: | + [Unit] + Description=Borg Backup + After=network-online.target + Wants=network-online.target + + [Service] + Type=oneshot + ExecStart=/usr/local/bin/borg-backup.sh + Nice=19 + IOSchedulingClass=idle + +- name: Timer aktivieren und starten + systemd: + name: borg-backup.timer + enabled: true + state: started + daemon_reload: true diff --git a/roles/borg/templates/borg-backup.sh.j2 b/roles/borg/templates/borg-backup.sh.j2 new file mode 100644 index 0000000..6754d91 --- /dev/null +++ b/roles/borg/templates/borg-backup.sh.j2 @@ -0,0 +1,33 @@ +#!/bin/bash +set -euo pipefail + +export BORG_PASSPHRASE=$(cat /root/.borg-passphrase) +REPO="{{ borg_repo }}" +LOGFILE="{{ borg_logfile }}" + +echo "[$(date)] Starte Backup: {{ inventory_hostname }}" >> "$LOGFILE" + +borg create \ + --verbose \ + --filter AME \ + --remote-path={{ borg_remote_path }} \ + --stats \ + --show-rc \ + --compression {{ borg_compression }} \ + "${REPO}::{{ inventory_hostname }}-$(date +%Y-%m-%d_%H-%M)" \ + {{ backup_source }} >> "$LOGFILE" 2>&1 + +BACKUP_RC=$? + +borg prune -v --list "${REPO}" \ + --keep-daily={{ borg_retention_daily }} \ + --keep-weekly={{ borg_retention_weekly }} \ + --keep-monthly={{ borg_retention_monthly }} >> "$LOGFILE" 2>&1 + +PRUNE_RC=$? + +borg compact "${REPO}" >> "$LOGFILE" 2>&1 + +GLOBAL_RC=$(( BACKUP_RC > PRUNE_RC ? BACKUP_RC : PRUNE_RC )) +echo "[$(date)] Backup beendet mit Code $GLOBAL_RC" >> "$LOGFILE" +exit $GLOBAL_RC diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml new file mode 100644 index 0000000..d5e3a04 --- /dev/null +++ b/roles/docker/tasks/main.yml @@ -0,0 +1,39 @@ +--- +- name: Verzeichnis für Keyrings erstellen + file: + path: /etc/apt/keyrings + state: directory + mode: '0755' + +- name: Docker GPG Key herunterladen + get_url: + url: https://download.docker.com/linux/debian/gpg + dest: /etc/apt/keyrings/docker.asc + mode: '0644' + +- name: Docker Repository Datei erstellen + copy: + dest: /etc/apt/sources.list.d/docker.list + content: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian trixie stable" + mode: '0644' + register: docker_repo + +- name: Paketliste aktualisieren + apt: + update_cache: yes + when: docker_repo.changed + +- name: Docker Engine installieren + apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-compose-plugin + state: present + +- name: Benutzer sascha zu docker Gruppe hinzufügen + user: + name: sascha + groups: docker + append: yes diff --git a/roles/frp_client/defaults/main.yml b/roles/frp_client/defaults/main.yml new file mode 100644 index 0000000..670e07d --- /dev/null +++ b/roles/frp_client/defaults/main.yml @@ -0,0 +1,6 @@ +--- +frp_version: "0.68.0" +frp_server_addr: "tunnel.sascha-lutz.de" +frp_server_port: 8443 +frp_token: "{{ vault_frp_token }}" +frp_tc_device: "ens18" diff --git a/roles/frp_client/handlers/main.yml b/roles/frp_client/handlers/main.yml new file mode 100644 index 0000000..4096ddc --- /dev/null +++ b/roles/frp_client/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: reload systemd + systemd: + daemon_reload: true + +- name: restart frpc + systemd: + name: frpc + state: restarted diff --git a/roles/frp_client/tasks/main.yml b/roles/frp_client/tasks/main.yml new file mode 100644 index 0000000..19577ed --- /dev/null +++ b/roles/frp_client/tasks/main.yml @@ -0,0 +1,104 @@ +--- +- name: frpc Binary herunterladen + get_url: + url: "https://github.com/fatedier/frp/releases/download/v{{ frp_version }}/frp_{{ frp_version }}_linux_amd64.tar.gz" + dest: /tmp/frp.tar.gz + +- name: frpc entpacken + unarchive: + src: /tmp/frp.tar.gz + dest: /tmp/ + remote_src: yes + +- name: frpc Binary installieren + copy: + src: "/tmp/frp_{{ frp_version }}_linux_amd64/frpc" + dest: /usr/local/bin/frpc + mode: "0755" + remote_src: yes + +- name: frpc Config Verzeichnis + file: + path: /etc/frp + state: directory + mode: "0755" + +- name: frpc Config deployen + copy: + dest: /etc/frp/frpc.toml + content: | + serverAddr = "{{ frp_server_addr }}" + serverPort = {{ frp_server_port }} + auth.method = "token" + auth.token = "{{ frp_token }}" + transport.protocol = "quic" + transport.poolCount = 5 + transport.tcpMux = true + {% for proxy in frp_proxies %} + + [[proxies]] + name = "{{ proxy.name }}" + type = "tcp" + localIP = "{{ proxy.local_ip | default('127.0.0.1') }}" + localPort = {{ proxy.local_port }} + remotePort = {{ proxy.remote_port }} + transport.useCompression = true + transport.bandwidthLimit = "{{ proxy.bandwidth_limit | default('6MB') }}" + transport.bandwidthLimitMode = "server" + {% endfor %} + mode: "0600" + notify: restart frpc + +- name: frpc systemd Service + copy: + dest: /etc/systemd/system/frpc.service + content: | + [Unit] + Description=frp Client – Reverse Tunnel + After=network-online.target + Wants=network-online.target + + [Service] + Type=simple + Restart=always + RestartSec=5 + ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml + + [Install] + WantedBy=multi-user.target + mode: "0644" + notify: + - reload systemd + - restart frpc + +- name: frpc aktivieren und starten + systemd: + name: frpc + enabled: true + state: started + daemon_reload: true + +- name: iproute2 installieren (fuer tc) + apt: + name: iproute2 + state: present + update_cache: yes + +- name: tc Fair Queueing mit Per-Flow-Limit + shell: /sbin/tc qdisc replace dev {{ frp_tc_device | default('ens18') }} root fq maxrate {{ frp_tc_maxrate | default('50mbit') }} + changed_when: false + +- name: tc Limit persistent via post-up + lineinfile: + path: /etc/network/interfaces + insertafter: "iface {{ frp_tc_device | default('ens18') }}" + line: " post-up /sbin/tc qdisc replace dev {{ frp_tc_device | default('ens18') }} root fq maxrate {{ frp_tc_maxrate | default('50mbit') }}" + regexp: "post-up.*tc qdisc" + +- name: Temp-Dateien aufräumen + file: + path: "{{ item }}" + state: absent + loop: + - /tmp/frp.tar.gz + - "/tmp/frp_{{ frp_version }}_linux_amd64" diff --git a/roles/frp_server/defaults/main.yml b/roles/frp_server/defaults/main.yml new file mode 100644 index 0000000..3abf8a3 --- /dev/null +++ b/roles/frp_server/defaults/main.yml @@ -0,0 +1,5 @@ +--- +frp_version: "0.68.0" +frp_bind_port: 7000 +frp_quic_port: 8443 +frp_token: "{{ vault_frp_token }}" diff --git a/roles/frp_server/handlers/main.yml b/roles/frp_server/handlers/main.yml new file mode 100644 index 0000000..2118446 --- /dev/null +++ b/roles/frp_server/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: reload systemd + systemd: + daemon_reload: true + +- name: restart frps + systemd: + name: frps + state: restarted diff --git a/roles/frp_server/tasks/main.yml b/roles/frp_server/tasks/main.yml new file mode 100644 index 0000000..409b678 --- /dev/null +++ b/roles/frp_server/tasks/main.yml @@ -0,0 +1,74 @@ +--- +- name: frps Binary herunterladen + get_url: + url: "https://github.com/fatedier/frp/releases/download/v{{ frp_version }}/frp_{{ frp_version }}_linux_amd64.tar.gz" + dest: /tmp/frp.tar.gz + +- name: frps entpacken + unarchive: + src: /tmp/frp.tar.gz + dest: /tmp/ + remote_src: yes + +- name: frps Binary installieren + copy: + src: "/tmp/frp_{{ frp_version }}_linux_amd64/frps" + dest: /usr/local/bin/frps + mode: "0755" + remote_src: yes + +- name: frps Config Verzeichnis + file: + path: /etc/frp + state: directory + mode: "0755" + +- name: frps Config deployen + copy: + dest: /etc/frp/frps.toml + content: | + bindPort = {{ frp_bind_port }} + quicBindPort = {{ frp_quic_port }} + auth.method = "token" + auth.token = "{{ frp_token }}" + transport.tcpMux = true + transport.maxPoolCount = 10 + mode: "0600" + notify: restart frps + +- name: frps systemd Service + copy: + dest: /etc/systemd/system/frps.service + content: | + [Unit] + Description=frp Server + After=network-online.target + Wants=network-online.target + + [Service] + Type=simple + Restart=always + RestartSec=5 + ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml + + [Install] + WantedBy=multi-user.target + mode: "0644" + notify: + - reload systemd + - restart frps + +- name: frps aktivieren und starten + systemd: + name: frps + enabled: true + state: started + daemon_reload: true + +- name: Temp-Dateien aufräumen + file: + path: "{{ item }}" + state: absent + loop: + - /tmp/frp.tar.gz + - "/tmp/frp_{{ frp_version }}_linux_amd64" diff --git a/roles/glances/defaults/main.yml b/roles/glances/defaults/main.yml new file mode 100644 index 0000000..44f0022 --- /dev/null +++ b/roles/glances/defaults/main.yml @@ -0,0 +1,2 @@ +--- +glances_port: 61208 diff --git a/roles/glances/handlers/main.yml b/roles/glances/handlers/main.yml new file mode 100644 index 0000000..b6899aa --- /dev/null +++ b/roles/glances/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: reload systemd + systemd: + daemon_reload: true + +- name: restart glances + systemd: + name: glances + state: restarted diff --git a/roles/glances/tasks/main.yml b/roles/glances/tasks/main.yml new file mode 100644 index 0000000..2288f1f --- /dev/null +++ b/roles/glances/tasks/main.yml @@ -0,0 +1,45 @@ +--- +- name: Glances apt-Paket entfernen (fehlende Web-UI) + apt: + name: glances + state: absent + +- name: pip installieren + apt: + name: python3-pip + state: present + update_cache: yes + +- name: Glances mit Web-UI per pip installieren + pip: + name: "glances[web]" + state: present + extra_args: --break-system-packages + +- name: Glances systemd Service (Web-Modus) + copy: + dest: /etc/systemd/system/glances.service + content: | + [Unit] + Description=Glances Web Server + After=network.target + + [Service] + Type=simple + Restart=always + RestartSec=5 + ExecStart=/usr/local/bin/glances -w -B 0.0.0.0 -p {{ glances_port }} --disable-plugin cloud + + [Install] + WantedBy=multi-user.target + mode: "0644" + notify: + - reload systemd + - restart glances + +- name: Glances aktivieren und starten + systemd: + name: glances + enabled: true + state: started + daemon_reload: true diff --git a/roles/hawser/handlers/main.yml b/roles/hawser/handlers/main.yml new file mode 100644 index 0000000..68189e5 --- /dev/null +++ b/roles/hawser/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart hawser + ansible.builtin.systemd: + name: hawser + state: restarted diff --git a/roles/hawser/tasks/main.yml b/roles/hawser/tasks/main.yml new file mode 100644 index 0000000..daaf7d1 --- /dev/null +++ b/roles/hawser/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Hawser installieren (offizielles Install-Script) + ansible.builtin.shell: + cmd: curl -fsSL https://raw.githubusercontent.com/Finsys/hawser/main/scripts/install.sh | bash + creates: /usr/local/bin/hawser + +- name: Hawser Token in Config setzen + ansible.builtin.lineinfile: + path: /etc/hawser/config + regexp: '^TOKEN=' + line: "TOKEN={{ vault_hawser_token }}" + notify: restart hawser + +- name: Hawser aktivieren und starten + ansible.builtin.systemd: + name: hawser + enabled: true + state: started + daemon_reload: true diff --git a/roles/nvidia/defaults/main.yml b/roles/nvidia/defaults/main.yml new file mode 100644 index 0000000..f0d3a86 --- /dev/null +++ b/roles/nvidia/defaults/main.yml @@ -0,0 +1,8 @@ +--- +cuda_keyring_deb_url: "https://developer.download.nvidia.com/compute/cuda/repos/debian13/x86_64/cuda-keyring_1.1-1_all.deb" +docker_daemon_config: + default-runtime: nvidia + runtimes: + nvidia: + path: nvidia-container-runtime + runtimeArgs: [] diff --git a/roles/nvidia/handlers/main.yml b/roles/nvidia/handlers/main.yml new file mode 100644 index 0000000..9bae572 --- /dev/null +++ b/roles/nvidia/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Docker neustarten + ansible.builtin.service: + name: docker + state: restarted diff --git a/roles/nvidia/tasks/main.yml b/roles/nvidia/tasks/main.yml new file mode 100644 index 0000000..c08b1cc --- /dev/null +++ b/roles/nvidia/tasks/main.yml @@ -0,0 +1,77 @@ +--- +- name: Nouveau Treiber blacklisten + ansible.builtin.copy: + dest: /etc/modprobe.d/blacklist-nouveau.conf + content: | + blacklist nouveau + options nouveau modeset=0 + mode: "0644" + register: nouveau_blacklist + +- name: initramfs-tools installieren + apt: + name: initramfs-tools + state: present + +- name: initramfs aktualisieren + ansible.builtin.command: update-initramfs -u + when: nouveau_blacklist.changed + +- name: CUDA Keyring herunterladen und installieren + ansible.builtin.apt: + deb: "{{ cuda_keyring_deb_url }}" + +- name: NVIDIA Container Toolkit GPG Key hinzufuegen + ansible.builtin.shell: | + curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \ + | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg + args: + creates: /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg + +- name: NVIDIA Container Toolkit Repo hinzufuegen + ansible.builtin.shell: | + curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \ + | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \ + | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list + args: + creates: /etc/apt/sources.list.d/nvidia-container-toolkit.list + +- name: apt update + ansible.builtin.apt: + update_cache: true + +- name: Kernel Headers und DKMS installieren + ansible.builtin.apt: + name: + - linux-headers-{{ ansible_kernel }} + - dkms + state: present + +- name: NVIDIA Treiber installieren (CUDA Repo) + ansible.builtin.apt: + name: cuda-drivers + state: present + register: nvidia_driver + +- name: NVIDIA Container Toolkit installieren + ansible.builtin.apt: + name: + - nvidia-container-toolkit + state: present + +- name: Docker daemon.json konfigurieren (NVIDIA als default runtime) + ansible.builtin.copy: + content: "{{ docker_daemon_config | to_nice_json }}" + dest: /etc/docker/daemon.json + mode: "0644" + notify: Docker neustarten + +- name: nvidia-ctk runtime fuer Docker konfigurieren + ansible.builtin.command: nvidia-ctk runtime configure --runtime=docker + changed_when: false + +- name: Reboot nach Treiberinstallation + ansible.builtin.reboot: + msg: "Reboot nach NVIDIA Treiber-Installation" + reboot_timeout: 300 + when: nvidia_driver.changed diff --git a/roles/pihole_dns/defaults/main.yml b/roles/pihole_dns/defaults/main.yml new file mode 100644 index 0000000..e08dab4 --- /dev/null +++ b/roles/pihole_dns/defaults/main.yml @@ -0,0 +1,6 @@ +--- +pihole_dns_domain: local +pihole_custom_list: /etc/pihole/custom.list +pihole_extra_records: [] +# - ip: 10.4.1.120 +# name: authentik diff --git a/roles/pihole_dns/handlers/main.yml b/roles/pihole_dns/handlers/main.yml new file mode 100644 index 0000000..99adfee --- /dev/null +++ b/roles/pihole_dns/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: Reload Pi-hole DNS + ansible.builtin.command: pihole restartdns reload + listen: reload pihole dns diff --git a/roles/pihole_dns/tasks/main.yml b/roles/pihole_dns/tasks/main.yml new file mode 100644 index 0000000..d0374ab --- /dev/null +++ b/roles/pihole_dns/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- name: Deploy Pi-hole custom DNS records + ansible.builtin.template: + src: custom.list.j2 + dest: "{{ pihole_custom_list }}" + owner: root + group: root + mode: "0644" + notify: reload pihole dns diff --git a/roles/pihole_dns/templates/custom.list.j2 b/roles/pihole_dns/templates/custom.list.j2 new file mode 100644 index 0000000..9d4a024 --- /dev/null +++ b/roles/pihole_dns/templates/custom.list.j2 @@ -0,0 +1,11 @@ +# Von Ansible generiert – nicht manuell bearbeiten +{% for host in groups['all'] %} +{% if hostvars[host].ansible_host is defined %} +{{ hostvars[host].ansible_host }} {{ host }}.{{ pihole_dns_domain }} +{{ hostvars[host].ansible_host }} {{ host }} +{% endif %} +{% endfor %} +{% for entry in pihole_extra_records %} +{{ entry.ip }} {{ entry.name }}.{{ pihole_dns_domain }} +{{ entry.ip }} {{ entry.name }} +{% endfor %} diff --git a/roles/pve_gpu_passthrough/handlers/main.yml b/roles/pve_gpu_passthrough/handlers/main.yml new file mode 100644 index 0000000..d72c2c8 --- /dev/null +++ b/roles/pve_gpu_passthrough/handlers/main.yml @@ -0,0 +1,3 @@ +--- +- name: Update GRUB + command: update-grub diff --git a/roles/pve_gpu_passthrough/tasks/main.yml b/roles/pve_gpu_passthrough/tasks/main.yml new file mode 100644 index 0000000..83ea0be --- /dev/null +++ b/roles/pve_gpu_passthrough/tasks/main.yml @@ -0,0 +1,45 @@ +--- +- name: IOMMU Kernel-Parameter setzen (GRUB) + lineinfile: + path: /etc/default/grub + regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=' + line: 'GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"' + register: grub_updated + notify: Update GRUB + +- name: VFIO Module in /etc/modules eintragen + copy: + dest: /etc/modules + content: | + # /etc/modules - VFIO fuer GPU Passthrough + vfio + vfio_iommu_type1 + vfio_pci + mode: "0644" + register: modules_updated + +- name: Alte fehlerhafte modprobe Configs aufraeumen + file: + path: "{{ item }}" + state: absent + loop: + - /etc/modprobe.d/block-nouveau.conf + - /etc/modprobe.d/nvidia-installer-disable-nouveau.conf + +- name: NVIDIA und Nouveau auf Host blacklisten + copy: + dest: /etc/modprobe.d/gpu-passthrough.conf + content: | + blacklist nouveau + blacklist nvidia + blacklist nvidiafb + blacklist rivafb + options nouveau modeset=0 + softdep nvidia pre: vfio-pci + softdep nouveau pre: vfio-pci + mode: "0644" + register: modprobe_updated + +- name: initramfs aktualisieren + command: update-initramfs -u -k all + when: grub_updated.changed or modules_updated.changed or modprobe_updated.changed diff --git a/roles/pve_postinstall/tasks/main.yml b/roles/pve_postinstall/tasks/main.yml new file mode 100644 index 0000000..b673f72 --- /dev/null +++ b/roles/pve_postinstall/tasks/main.yml @@ -0,0 +1,122 @@ +--- +- name: Legacy .list Dateien finden + find: + paths: /etc/apt/sources.list.d + patterns: "*.list" + register: legacy_lists + +- name: Legacy .list Dateien umbenennen + command: mv "{{ item.path }}" "{{ item.path }}.bak" + loop: "{{ legacy_lists.files }}" + when: legacy_lists.files | length > 0 + args: + creates: "{{ item.path }}.bak" + +- name: Legacy sources.list leeren + copy: + dest: /etc/apt/sources.list + content: "" + mode: "0644" + +- name: Debian Trixie Quellen (deb822) + copy: + dest: /etc/apt/sources.list.d/debian.sources + content: | + Types: deb + URIs: http://deb.debian.org/debian/ + Suites: trixie trixie-updates + Components: main contrib non-free non-free-firmware + Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg + + Types: deb + URIs: http://security.debian.org/debian-security/ + Suites: trixie-security + Components: main contrib non-free non-free-firmware + Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg + mode: "0644" + +- name: Enterprise Repo deaktivieren (auskommentiert) + copy: + dest: /etc/apt/sources.list.d/pve-enterprise.sources + content: | + # Types: deb + # URIs: https://enterprise.proxmox.com/debian/pve + # Suites: trixie + # Components: pve-enterprise + # Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg + mode: "0644" + +- name: Ceph Enterprise Repo deaktivieren (auskommentiert) + copy: + dest: /etc/apt/sources.list.d/ceph.sources + content: | + # Types: deb + # URIs: https://enterprise.proxmox.com/debian/ceph-squid + # Suites: trixie + # Components: enterprise + # Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg + mode: "0644" + +- name: PVE No-Subscription Repo (deb822) + copy: + dest: /etc/apt/sources.list.d/proxmox.sources + content: | + Types: deb + URIs: http://download.proxmox.com/debian/pve + Suites: trixie + Components: pve-no-subscription + Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg + mode: "0644" + +- name: PVE Test Repo (disabled) + copy: + dest: /etc/apt/sources.list.d/pve-test.sources + content: | + Types: deb + URIs: http://download.proxmox.com/debian/pve + Suites: trixie + Components: pve-test + Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg + Enabled: false + mode: "0644" + +- name: Subscription Nag Patch Script deployen + copy: + dest: /usr/local/bin/pve-remove-nag.sh + mode: "0755" + content: | + #!/bin/sh + WEB_JS=/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js + if [ -s "$WEB_JS" ] && ! grep -q NoMoreNagging "$WEB_JS"; then + sed -i -e "/data\.status/ s/!//" -e "/data\.status/ s/active/NoMoreNagging/" "$WEB_JS" + fi + +- name: Nag Patch als DPkg Post-Invoke registrieren + copy: + dest: /etc/apt/apt.conf.d/no-nag-script + content: 'DPkg::Post-Invoke { "/usr/local/bin/pve-remove-nag.sh"; };' + mode: "0644" + +- name: Nag Patch einmalig ausfuehren + command: /usr/local/bin/pve-remove-nag.sh + changed_when: false + +- name: HA Services deaktivieren + systemd: + name: "{{ item }}" + enabled: false + state: stopped + loop: + - pve-ha-lrm + - pve-ha-crm + - corosync + failed_when: false + +- name: Apt Cache aktualisieren + apt: + update_cache: yes + +- name: Dist-Upgrade ausfuehren + apt: + upgrade: dist + autoremove: yes diff --git a/roles/sysctl/tasks/main.yml b/roles/sysctl/tasks/main.yml new file mode 100644 index 0000000..c77063e --- /dev/null +++ b/roles/sysctl/tasks/main.yml @@ -0,0 +1,41 @@ +--- +- name: BBR Kernel Modul laden + ansible.builtin.modprobe: + name: tcp_bbr + state: present + +- name: BBR Modul beim Boot laden + ansible.builtin.copy: + content: "tcp_bbr\n" + dest: /etc/modules-load.d/bbr.conf + mode: "0644" + +- name: Sysctl Parameter setzen + ansible.posix.sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" + sysctl_file: /etc/sysctl.d/99-net-tuning.conf + reload: true + state: present + loop: + - { key: net.core.rmem_default, value: "262144" } + - { key: net.core.wmem_default, value: "262144" } + - { key: net.core.rmem_max, value: "67108864" } + - { key: net.core.wmem_max, value: "67108864" } + - { key: net.ipv4.tcp_rmem, value: "4096 87380 67108864" } + - { key: net.ipv4.tcp_wmem, value: "4096 65536 67108864" } + - { key: net.ipv4.tcp_window_scaling, value: "1" } + - { key: net.ipv4.tcp_congestion_control, value: "bbr" } + - { key: net.ipv4.tcp_slow_start_after_idle, value: "0" } + - { key: net.ipv4.tcp_fastopen, value: "3" } + - { key: net.core.netdev_max_backlog, value: "16384" } + - { key: net.core.somaxconn, value: "4096" } + - { key: net.ipv4.tcp_notsent_lowat, value: "16384" } + - { key: net.ipv4.tcp_fin_timeout, value: "15" } + - { key: net.ipv4.tcp_tw_reuse, value: "1" } + - { key: vm.swappiness, value: "1" } + - { key: vm.dirty_ratio, value: "15" } + - { key: vm.dirty_background_ratio, value: "5" } + - { key: net.ipv4.tcp_mtu_probing, value: "1" } + - { key: net.ipv4.ip_forward, value: "1" } + - { key: net.ipv6.conf.all.forwarding, value: "1" } diff --git a/roles/sysctl_proxmox/handlers/main.yml b/roles/sysctl_proxmox/handlers/main.yml new file mode 100644 index 0000000..f138d7b --- /dev/null +++ b/roles/sysctl_proxmox/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: sysctl reload + ansible.builtin.command: sysctl --system + +- name: resolvconf update + ansible.builtin.command: resolvconf -u diff --git a/roles/sysctl_proxmox/tasks/main.yml b/roles/sysctl_proxmox/tasks/main.yml new file mode 100644 index 0000000..70bf05a --- /dev/null +++ b/roles/sysctl_proxmox/tasks/main.yml @@ -0,0 +1,55 @@ +--- +- name: resolvconf installieren + ansible.builtin.apt: + name: resolvconf + state: present + +- name: DNS in resolvconf head setzen + ansible.builtin.copy: + dest: /etc/resolvconf/resolv.conf.d/head + content: | + # Managed by Ansible + nameserver 1.1.1.1 + nameserver 1.0.0.1 + mode: "0644" + notify: resolvconf update + +- name: /etc/hosts deployen + ansible.builtin.template: + src: hosts.j2 + dest: /etc/hosts + mode: "0644" + +- name: sysctl.conf inkludiert sysctl.d + ansible.builtin.lineinfile: + path: /etc/sysctl.conf + create: true + mode: "0644" + line: "# Managed by Ansible – Drop-ins in /etc/sysctl.d/ werden automatisch geladen" + insertbefore: BOF + notify: sysctl reload + +- name: Sysctl Parameter setzen + ansible.posix.sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" + sysctl_file: /etc/sysctl.d/99-proxmox-tuning.conf + reload: true + state: present + loop: + - { key: vm.overcommit_memory, value: "1" } + - { key: vm.swappiness, value: "1" } + - { key: fs.file-max, value: "9999999" } + - { key: fs.inotify.max_user_watches, value: "524288" } + - { key: fs.inotify.max_user_instances, value: "512" } + - { key: net.ipv4.ip_forward, value: "1" } + - { key: net.ipv6.conf.all.forwarding, value: "1" } + - { key: net.bridge.bridge-nf-call-iptables, value: "0" } + - { key: net.bridge.bridge-nf-call-ip6tables, value: "0" } + - { key: vm.dirty_expire_centisecs, value: "3000" } + - { key: vm.dirty_writeback_centisecs, value: "500" } + - { key: net.ipv4.tcp_mtu_probing, value: "1" } + - { key: net.core.rmem_max, value: "67108864" } + - { key: net.core.wmem_max, value: "67108864" } + - { key: net.ipv4.tcp_rmem, value: "4096 87380 67108864" } + - { key: net.ipv4.tcp_wmem, value: "4096 65536 67108864" } diff --git a/roles/sysctl_proxmox/templates/hosts.j2 b/roles/sysctl_proxmox/templates/hosts.j2 new file mode 100644 index 0000000..6e043ab --- /dev/null +++ b/roles/sysctl_proxmox/templates/hosts.j2 @@ -0,0 +1,9 @@ +# Managed by Ansible +127.0.0.1 localhost +127.0.1.1 {{ inventory_hostname }} +::1 localhost ip6-localhost ip6-loopback + +# Proxmox Hosts +{% for host in groups['proxmox'] %} +{{ hostvars[host]['ansible_host'] }} {{ host }} +{% endfor %} diff --git a/roles/telegraf/defaults/main.yml b/roles/telegraf/defaults/main.yml new file mode 100644 index 0000000..4eabab5 --- /dev/null +++ b/roles/telegraf/defaults/main.yml @@ -0,0 +1,11 @@ +--- +telegraf_influx_url: "https://influx.sascha-lutz.de" +telegraf_influx_org: "influx.sascha-lutz.de" +telegraf_influx_token: "{{ vault_telegraf_influx_token }}" +telegraf_influx_bucket: "telegraf" +telegraf_interval: "10s" +telegraf_synology_snmp: false +telegraf_synology_host: "" +telegraf_snmp_sec_name: "{{ vault_snmp_sec_name | default('') }}" +telegraf_snmp_auth_password: "{{ vault_snmp_auth_password | default('') }}" +telegraf_snmp_priv_password: "{{ vault_snmp_priv_password | default('') }}" diff --git a/roles/telegraf/handlers/main.yml b/roles/telegraf/handlers/main.yml new file mode 100644 index 0000000..5008c72 --- /dev/null +++ b/roles/telegraf/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Telegraf neustarten + systemd: + name: telegraf + state: restarted diff --git a/roles/telegraf/tasks/main.yml b/roles/telegraf/tasks/main.yml new file mode 100644 index 0000000..4d7922a --- /dev/null +++ b/roles/telegraf/tasks/main.yml @@ -0,0 +1,51 @@ +--- +- name: InfluxData GPG Key hinzufuegen + get_url: + url: https://repos.influxdata.com/influxdata-archive_compat.key + dest: /etc/apt/keyrings/influxdata-archive-keyring.gpg + mode: "0644" + +- name: InfluxData Repo hinzufuegen + copy: + dest: /etc/apt/sources.list.d/influxdata.list + content: "deb [signed-by=/etc/apt/keyrings/influxdata-archive-keyring.gpg] https://repos.influxdata.com/debian stable main" + mode: "0644" + register: influx_repo + +- name: Apt Cache aktualisieren + apt: + update_cache: yes + when: influx_repo.changed + +- name: Telegraf installieren + apt: + name: telegraf + state: present + +- name: lm-sensors installieren (fuer inputs.sensors) + apt: + name: lm-sensors + state: present + +- name: SNMP Pakete installieren (fuer Synology Monitoring) + apt: + name: + - snmp + - snmp-mibs-downloader + state: present + when: telegraf_synology_snmp + +- name: Telegraf Config deployen + template: + src: telegraf.conf.j2 + dest: /etc/telegraf/telegraf.conf + mode: "0640" + owner: root + group: telegraf + notify: Telegraf neustarten + +- name: Telegraf aktivieren und starten + systemd: + name: telegraf + enabled: true + state: started diff --git a/roles/telegraf/templates/telegraf.conf.j2 b/roles/telegraf/templates/telegraf.conf.j2 new file mode 100644 index 0000000..2cbe998 --- /dev/null +++ b/roles/telegraf/templates/telegraf.conf.j2 @@ -0,0 +1,469 @@ +[global_tags] + +[agent] + interval = "{{ telegraf_interval }}" + round_interval = true + metric_batch_size = 1000 + metric_buffer_limit = 10000 + collection_jitter = "0s" + flush_interval = "10s" + flush_jitter = "0s" + precision = "0s" + hostname = "" + omit_hostname = false + +[[outputs.influxdb_v2]] + urls = ["{{ telegraf_influx_url }}"] + organization = "{{ telegraf_influx_org }}" + token = "{{ telegraf_influx_token }}" + bucket = "{{ telegraf_influx_bucket }}" + +[[inputs.cpu]] + percpu = true + totalcpu = true + fielddrop = ["time_*"] + +[[inputs.disk]] + ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"] + +[[inputs.diskio]] + +[[inputs.kernel]] + +[[inputs.mem]] + +[[inputs.processes]] + +[[inputs.swap]] + +[[inputs.system]] + +[[inputs.nstat]] + +[[inputs.sensors]] + +{% if telegraf_synology_snmp %} +# ============================================ +# Synology NAS SNMP Monitoring +# ============================================ +[[inputs.snmp]] + agents = ["{{ telegraf_synology_host }}"] + interval = "30s" + timeout = "30s" + retries = 3 + max_repetitions = 10 + version = 3 + sec_name = "{{ telegraf_snmp_sec_name }}" + auth_protocol = "MD5" + auth_password = "{{ telegraf_snmp_auth_password }}" + sec_level = "authPriv" + priv_protocol = "DES" + priv_password = "{{ telegraf_snmp_priv_password }}" + name = "snmp.Synology" + + # --- SNMPv2 System Info --- + [[inputs.snmp.field]] + name = "sysName" + oid = "SNMPv2-MIB::sysName.0" + is_tag = true + [[inputs.snmp.field]] + name = "sysDescr" + oid = "SNMPv2-MIB::sysDescr.0" + [[inputs.snmp.field]] + name = "sysContact" + oid = "SNMPv2-MIB::sysContact.0" + [[inputs.snmp.field]] + name = "sysLocation" + oid = "SNMPv2-MIB::sysLocation.0" + [[inputs.snmp.field]] + name = "sysUpTime" + oid = "SNMPv2-MIB::sysUpTime.0" + + # --- UCD-SNMP-MIB: System Stats --- + [[inputs.snmp.field]] + name = "systemStats.ssSwapIn" + oid = "UCD-SNMP-MIB::ssSwapIn.0" + [[inputs.snmp.field]] + name = "systemStats.ssSwapOut" + oid = "UCD-SNMP-MIB::ssSwapOut.0" + [[inputs.snmp.field]] + name = "systemStats.ssIOSent" + oid = "UCD-SNMP-MIB::ssIOSent.0" + [[inputs.snmp.field]] + name = "systemStats.ssIOReceive" + oid = "UCD-SNMP-MIB::ssIOReceive.0" + [[inputs.snmp.field]] + name = "systemStats.ssSysInterrupts" + oid = "UCD-SNMP-MIB::ssSysInterrupts.0" + [[inputs.snmp.field]] + name = "systemStats.ssSysContext" + oid = "UCD-SNMP-MIB::ssSysContext.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuUser" + oid = "UCD-SNMP-MIB::ssCpuUser.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuSystem" + oid = "UCD-SNMP-MIB::ssCpuSystem.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuIdle" + oid = "UCD-SNMP-MIB::ssCpuIdle.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawUser" + oid = "UCD-SNMP-MIB::ssCpuRawUser.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawNice" + oid = "UCD-SNMP-MIB::ssCpuRawNice.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawSystem" + oid = "UCD-SNMP-MIB::ssCpuRawSystem.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawIdle" + oid = "UCD-SNMP-MIB::ssCpuRawIdle.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawWait" + oid = "UCD-SNMP-MIB::ssCpuRawWait.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawKernel" + oid = "UCD-SNMP-MIB::ssCpuRawKernel.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawInterrupt" + oid = "UCD-SNMP-MIB::ssCpuRawInterrupt.0" + [[inputs.snmp.field]] + name = "systemStats.ssIORawSent" + oid = "UCD-SNMP-MIB::ssIORawSent.0" + [[inputs.snmp.field]] + name = "systemStats.ssIORawReceived" + oid = "UCD-SNMP-MIB::ssIORawReceived.0" + [[inputs.snmp.field]] + name = "systemStats.ssRawInterrupts" + oid = "UCD-SNMP-MIB::ssRawInterrupts.0" + [[inputs.snmp.field]] + name = "systemStats.ssRawContexts" + oid = "UCD-SNMP-MIB::ssRawContexts.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawSoftIRQ" + oid = "UCD-SNMP-MIB::ssCpuRawSoftIRQ.0" + [[inputs.snmp.field]] + name = "systemStats.ssRawSwapIn" + oid = "UCD-SNMP-MIB::ssRawSwapIn.0" + [[inputs.snmp.field]] + name = "systemStats.ssRawSwapOut" + oid = "UCD-SNMP-MIB::ssRawSwapOut.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawSteal" + oid = "UCD-SNMP-MIB::ssCpuRawSteal.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawGuest" + oid = "UCD-SNMP-MIB::ssCpuRawGuest.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuRawGuestNice" + oid = "UCD-SNMP-MIB::ssCpuRawGuestNice.0" + [[inputs.snmp.field]] + name = "systemStats.ssCpuNumCpus" + oid = "UCD-SNMP-MIB::ssCpuNumCpus.0" + + # --- UCD-SNMP-MIB: Memory --- + [[inputs.snmp.field]] + name = "memory.memTotalSwap" + oid = "UCD-SNMP-MIB::memTotalSwapX.0" + [[inputs.snmp.field]] + name = "memory.memAvailSwap" + oid = "UCD-SNMP-MIB::memAvailSwapX.0" + [[inputs.snmp.field]] + name = "memory.memTotalReal" + oid = "UCD-SNMP-MIB::memTotalRealX.0" + [[inputs.snmp.field]] + name = "memory.memAvailReal" + oid = "UCD-SNMP-MIB::memAvailRealX.0" + [[inputs.snmp.field]] + name = "memory.memTotalFree" + oid = "UCD-SNMP-MIB::memTotalFreeX.0" + [[inputs.snmp.field]] + name = "memory.memMinimumSwap" + oid = "UCD-SNMP-MIB::memMinimumSwapX.0" + [[inputs.snmp.field]] + name = "memory.memShared" + oid = "UCD-SNMP-MIB::memSharedX.0" + [[inputs.snmp.field]] + name = "memory.memBuffer" + oid = "UCD-SNMP-MIB::memBufferX.0" + [[inputs.snmp.field]] + name = "memory.memCached" + oid = "UCD-SNMP-MIB::memCachedX.0" + + # --- HOST-RESOURCES-MIB: System --- + [[inputs.snmp.field]] + name = "hrSystem.hrSystemUptime" + oid = "HOST-RESOURCES-MIB::hrSystemUptime.0" + [[inputs.snmp.field]] + name = "hrSystem.hrSystemNumUsers" + oid = "HOST-RESOURCES-MIB::hrSystemNumUsers.0" + [[inputs.snmp.field]] + name = "hrSystem.hrSystemProcesses" + oid = "HOST-RESOURCES-MIB::hrSystemProcesses.0" + + # --- SYNOLOGY-SYSTEM-MIB --- + [[inputs.snmp.field]] + name = "synoSystem.systemStatus" + oid = "SYNOLOGY-SYSTEM-MIB::systemStatus.0" + [[inputs.snmp.field]] + name = "synoSystem.temperature" + oid = "SYNOLOGY-SYSTEM-MIB::temperature.0" + [[inputs.snmp.field]] + name = "synoSystem.powerStatus" + oid = "SYNOLOGY-SYSTEM-MIB::powerStatus.0" + [[inputs.snmp.field]] + name = "synoSystem.systemFanStatus" + oid = "SYNOLOGY-SYSTEM-MIB::systemFanStatus.0" + [[inputs.snmp.field]] + name = "synoSystem.cpuFanStatus" + oid = "SYNOLOGY-SYSTEM-MIB::cpuFanStatus.0" + [[inputs.snmp.field]] + name = "synoSystem.modelName" + oid = "SYNOLOGY-SYSTEM-MIB::modelName.0" + [[inputs.snmp.field]] + name = "synoSystem.serialNumber" + oid = "SYNOLOGY-SYSTEM-MIB::serialNumber.0" + [[inputs.snmp.field]] + name = "synoSystem.version" + oid = "SYNOLOGY-SYSTEM-MIB::version.0" + [[inputs.snmp.field]] + name = "synoSystem.upgradeAvailable" + oid = "SYNOLOGY-SYSTEM-MIB::upgradeAvailable.0" + + # --- Tables: Load --- + [[inputs.snmp.table]] + oid = "UCD-SNMP-MIB::laTable" + name = "snmp.Synology.load" + [[inputs.snmp.table.field]] + oid = "UCD-SNMP-MIB::laNames" + is_tag = true + + # --- Tables: Network --- + [[inputs.snmp.table]] + oid = "IF-MIB::ifTable" + name = "snmp.Synology.network" + [[inputs.snmp.table.field]] + oid = "IF-MIB::ifDescr" + is_tag = true + [[inputs.snmp.table]] + oid = "IF-MIB::ifXTable" + name = "snmp.Synology.network" + [[inputs.snmp.table.field]] + oid = "IF-MIB::ifName" + is_tag = true + + # --- Tables: Volume --- + [[inputs.snmp.table]] + oid = "HOST-RESOURCES-MIB::hrStorageTable" + name = "snmp.Synology.volume" + [[inputs.snmp.table.field]] + oid = "HOST-RESOURCES-MIB::hrStorageDescr" + is_tag = true + + # --- Tables: Disk --- + [[inputs.snmp.table]] + oid = "SYNOLOGY-DISK-MIB::diskTable" + name = "snmp.Synology.disk" + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-DISK-MIB::diskID" + is_tag = true + + # --- Tables: RAID --- + [[inputs.snmp.table]] + oid = "SYNOLOGY-RAID-MIB::raidTable" + name = "snmp.Synology.raid" + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-RAID-MIB::raidName" + is_tag = true + + # --- Tables: SSD Cache --- + [[inputs.snmp.table]] + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheTable" + name = "snmp.Synology.cache" + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheSpaceDev" + is_tag = true + + # --- Tables: S.M.A.R.T. --- + [[inputs.snmp.table]] + oid = "SYNOLOGY-SMART-MIB::diskSMARTTable" + name = "snmp.Synology.smart" + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-SMART-MIB::diskSMARTInfoDevName" + is_tag = true + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-SMART-MIB::diskSMARTAttrName" + is_tag = true + + # --- Tables: Space IO --- + [[inputs.snmp.table]] + oid = "SYNOLOGY-SPACEIO-MIB::spaceIOTable" + name = "snmp.Synology.spaceIO" + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-SPACEIO-MIB::spaceIODevice" + is_tag = true + + # --- Tables: Storage IO --- + [[inputs.snmp.table]] + oid = "SYNOLOGY-STORAGEIO-MIB::storageIOTable" + name = "snmp.Synology.storageIO" + [[inputs.snmp.table.field]] + oid = "SYNOLOGY-STORAGEIO-MIB::storageIODevice" + is_tag = true + + # --- Tables: eBox --- + [[inputs.snmp.table]] + name = "snmp.Synology.ebox" + oid = "SYNOLOGY-EBOX-MIB::eboxTable" + [[inputs.snmp.table.field]] + name = "snmp.Synology.ebox.eboxIndex" + oid = "SYNOLOGY-EBOX-MIB::eboxIndex" + [[inputs.snmp.table.field]] + name = "snmp.Synology.ebox.eboxModel" + oid = "SYNOLOGY-EBOX-MIB::eboxModel" + [[inputs.snmp.table.field]] + name = "snmp.Synology.ebox.eboxPower" + oid = "SYNOLOGY-EBOX-MIB::eboxPower" + [[inputs.snmp.table.field]] + name = "snmp.Synology.ebox.eboxRedundantPower" + oid = "SYNOLOGY-EBOX-MIB::eboxRedundantPower" + + # --- Tables: Flash Cache --- + [[inputs.snmp.table]] + name = "snmp.Synology.flashcache" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheTable" + [[inputs.snmp.table.field]] + name = "flashCacheIndex" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheIndex" + [[inputs.snmp.table.field]] + name = "flashCacheSSDDev" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheSSDDev" + [[inputs.snmp.table.field]] + name = "flashCacheSpaceDev" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheSpaceDev" + [[inputs.snmp.table.field]] + name = "flashCacheReadHits" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheReadHits" + [[inputs.snmp.table.field]] + name = "flashCacheWriteHits" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheWriteHits" + [[inputs.snmp.table.field]] + name = "flashCacheTotalRead" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheTotalRead" + [[inputs.snmp.table.field]] + name = "flashCacheTotalWrite" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheTotalWrite" + [[inputs.snmp.table.field]] + name = "flashCacheReadHitRate" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheReadHitRate" + [[inputs.snmp.table.field]] + name = "flashCacheWriteHitRate" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheWriteHitRate" + [[inputs.snmp.table.field]] + name = "flashCacheSsdUuid" + oid = "SYNOLOGY-FLASHCACHE-MIB::flashCacheSsdUuid" + + # --- Tables: GPU --- + [[inputs.snmp.table]] + name = "snmp.Synology.gpu" + [[inputs.snmp.table.field]] + name = "gpuUtilization" + oid = "SYNOLOGY-GPUINFO-MIB::gpuUtilization" + [[inputs.snmp.table.field]] + name = "gpuMemoryUtilization" + oid = "SYNOLOGY-GPUINFO-MIB::gpuMemoryUtilization" + [[inputs.snmp.table.field]] + name = "gpuMemoryFree" + oid = "SYNOLOGY-GPUINFO-MIB::gpuMemoryFree" + [[inputs.snmp.table.field]] + name = "gpuMemoryUsed" + oid = "SYNOLOGY-GPUINFO-MIB::gpuMemoryUsed" + [[inputs.snmp.table.field]] + name = "gpuMemoryTotal" + oid = "SYNOLOGY-GPUINFO-MIB::gpuMemoryTotal" + + # --- Tables: iSCSI LUN --- + [[inputs.snmp.table]] + name = "snmp.Synology.iscsilun" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNTable" + [[inputs.snmp.table.field]] + name = "iSCSILUNInfoIndex" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNInfoIndex" + [[inputs.snmp.table.field]] + name = "iSCSILUNUUID" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNUUID" + [[inputs.snmp.table.field]] + name = "iSCSILUNName" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNName" + [[inputs.snmp.table.field]] + name = "iSCSILUNThroughputReadHigh" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNThroughputReadHigh" + [[inputs.snmp.table.field]] + name = "iSCSILUNThroughputReadLow" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNThroughputReadLow" + [[inputs.snmp.table.field]] + name = "iSCSILUNThroughputWriteHigh" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNThroughputWriteHigh" + [[inputs.snmp.table.field]] + name = "iSCSILUNThroughputWriteLow" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNThroughputWriteLow" + [[inputs.snmp.table.field]] + name = "iSCSILUNIopsRead" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNIopsRead" + [[inputs.snmp.table.field]] + name = "iSCSILUNIopsWrite" + oid = "SYNOLOGY-ISCSILUN-MIB::iSCSILUNIopsWrite" + + # --- Tables: iSCSI Target --- + [[inputs.snmp.table]] + name = "snmp.Synology.iscsitarget" + oid = "SYNOLOGY-ISCSITarget-MIB::iSCSITargetTable" + [[inputs.snmp.table.field]] + name = "iSCSITargetName" + oid = "SYNOLOGY-ISCSITarget-MIB::iSCSITargetName" + [[inputs.snmp.table.field]] + name = "iSCSITargetIQN" + oid = "SYNOLOGY-ISCSITarget-MIB::iSCSITargetIQN" + [[inputs.snmp.table.field]] + name = "iSCSITargetConnectionStatus" + oid = "SYNOLOGY-ISCSITarget-MIB::iSCSITargetConnectionStatus" + + # --- Tables: Services --- + [[inputs.snmp.table]] + name = "snmp.Synology.services" + oid = "SYNOLOGY-SERVICES-MIB::serviceTable" + [[inputs.snmp.table.field]] + name = "serviceName" + oid = "SYNOLOGY-SERVICES-MIB::serviceName" + is_tag = true + [[inputs.snmp.table.field]] + name = "serviceUsers" + oid = "SYNOLOGY-SERVICES-MIB::serviceUsers" + + # --- HA --- + [[inputs.snmp.field]] + name = "ha.activeNodeName" + oid = "SYNOLOGY-SHA-MIB::activeNodeName" + [[inputs.snmp.field]] + name = "ha.passiveNodeName" + oid = "SYNOLOGY-SHA-MIB::passiveNodeName" + [[inputs.snmp.field]] + name = "ha.clusterAutoFailover" + oid = "SYNOLOGY-SHA-MIB::clusterAutoFailover" + [[inputs.snmp.field]] + name = "ha.clusterName" + oid = "SYNOLOGY-SHA-MIB::clusterName" + [[inputs.snmp.field]] + name = "ha.clusterStatus" + oid = "SYNOLOGY-SHA-MIB::clusterStatus" + [[inputs.snmp.field]] + name = "ha.heartbeatStatus" + oid = "SYNOLOGY-SHA-MIB::heartbeatStatus" + [[inputs.snmp.field]] + name = "ha.heartbeatTxRate" + oid = "SYNOLOGY-SHA-MIB::heartbeatTxRate" + [[inputs.snmp.field]] + name = "ha.heartbeatLatency" + oid = "SYNOLOGY-SHA-MIB::heartbeatLatency" +{% endif %} diff --git a/roles/wireguard/defaults/main.yml b/roles/wireguard/defaults/main.yml new file mode 100644 index 0000000..1d7e7b6 --- /dev/null +++ b/roles/wireguard/defaults/main.yml @@ -0,0 +1,5 @@ +--- +wireguard_endpoint: "tunnel.sascha-lutz.de:51820" +wireguard_vps_pubkey: "{{ vault_wireguard_vps_pubkey }}" +wireguard_mtu: 1420 +wireguard_persistent_keepalive: 25 diff --git a/roles/wireguard/handlers/main.yml b/roles/wireguard/handlers/main.yml new file mode 100644 index 0000000..1dda2ff --- /dev/null +++ b/roles/wireguard/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart wireguard + systemd: + name: wg-quick@wg0 + state: restarted diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml new file mode 100644 index 0000000..a64563f --- /dev/null +++ b/roles/wireguard/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: WireGuard und resolvconf installieren + apt: + name: + - wireguard + - resolvconf + state: present + update_cache: yes + +- name: WireGuard Config deployen + copy: + dest: /etc/wireguard/wg0.conf + content: | + [Interface] + PrivateKey = {{ wireguard_private_key }} + Address = {{ wireguard_address }} + DNS = 8.8.8.8 + MTU = {{ wireguard_mtu }} + + [Peer] + PublicKey = {{ wireguard_vps_pubkey }} + Endpoint = {{ wireguard_endpoint }} + AllowedIPs = {{ wireguard_allowed_ips }} + PersistentKeepalive = {{ wireguard_persistent_keepalive }} + mode: "0600" + notify: restart wireguard + +- name: WireGuard aktivieren und starten + systemd: + name: wg-quick@wg0 + enabled: true + state: started diff --git a/site.yml b/site.yml new file mode 100644 index 0000000..f359ccd --- /dev/null +++ b/site.yml @@ -0,0 +1,19 @@ +--- +# Neue VM komplett einrichten +- name: VM Setup + hosts: all + become: yes + roles: + - base + - docker + - borg + - hawser + - sysctl + +# Proxmox Hosts +- name: Proxmox Tuning + hosts: proxmox + become: yes + roles: + - sysctl_proxmox + - telegraf diff --git a/sysctl-proxmox.yaml b/sysctl-proxmox.yaml index 43487cf..3f9ad2d 100644 --- a/sysctl-proxmox.yaml +++ b/sysctl-proxmox.yaml @@ -1,27 +1,6 @@ --- - name: Sysctl Tuning fuer Proxmox Hosts hosts: proxmox - become: true - - tasks: - - - name: Sysctl Parameter setzen - ansible.posix.sysctl: - name: "{{ item.key }}" - value: "{{ item.value }}" - sysctl_file: /etc/sysctl.d/99-proxmox-tuning.conf - reload: true - state: present - loop: - # KVM / Virtualisierung - - { key: vm.overcommit_memory, value: "1" } - - { key: vm.swappiness, value: "1" } - # Viele VMs = viele File Handles - - { key: fs.file-max, value: "9999999" } - - { key: fs.inotify.max_user_watches, value: "524288" } - - { key: fs.inotify.max_user_instances, value: "512" } - # Routing zwischen VMs / Bridges - - { key: net.ipv4.ip_forward, value: "1" } - # WireGuard MTU-Anpassung - # TODO: entfernen sobald WireGuard abgeschaltet wird - - { key: net.ipv4.tcp_mtu_probing, value: "1" } + become: yes + roles: + - sysctl_proxmox diff --git a/sysctl.yaml b/sysctl.yaml index dad3c5c..c64823e 100644 --- a/sysctl.yaml +++ b/sysctl.yaml @@ -1,41 +1,6 @@ --- -- name: Sysctl Tuning fuer Emby +- name: Sysctl Tuning fuer Streaming-VMs hosts: all - become: true - - tasks: - - - name: BBR Kernel Modul laden - ansible.builtin.modprobe: - name: tcp_bbr - state: present - - - name: BBR Modul beim Boot laden - ansible.builtin.copy: - content: "tcp_bbr\n" - dest: /etc/modules-load.d/bbr.conf - mode: "0644" - - - name: Sysctl Parameter setzen - ansible.posix.sysctl: - name: "{{ item.key }}" - value: "{{ item.value }}" - sysctl_file: /etc/sysctl.d/99-net-tuning.conf - reload: true - state: present - loop: - - { key: net.core.rmem_default, value: "262144" } - - { key: net.core.wmem_default, value: "262144" } - - { key: net.core.rmem_max, value: "67108864" } - - { key: net.core.wmem_max, value: "67108864" } - - { key: net.ipv4.tcp_rmem, value: "4096 87380 67108864" } - - { key: net.ipv4.tcp_wmem, value: "4096 65536 67108864" } - - { key: net.ipv4.tcp_window_scaling, value: "1" } - - { key: net.ipv4.tcp_congestion_control, value: "bbr" } - - { key: net.ipv4.tcp_slow_start_after_idle, value: "0" } - - { key: net.ipv4.tcp_fastopen, value: "3" } - - { key: net.core.netdev_max_backlog, value: "16384" } - # RAM ist reichlich vorhanden, Transcoding auf tmpfs - - { key: vm.swappiness, value: "1" } - - { key: vm.dirty_ratio, value: "15" } - - { key: vm.dirty_background_ratio, value: "5" } + become: yes + roles: + - sysctl diff --git a/telegraf.yml b/telegraf.yml new file mode 100644 index 0000000..7beda92 --- /dev/null +++ b/telegraf.yml @@ -0,0 +1,6 @@ +--- +- name: Telegraf Monitoring Setup + hosts: proxmox + become: yes + roles: + - telegraf diff --git a/tmp/n8n b/tmp/n8n new file mode 100644 index 0000000..1b08b22 --- /dev/null +++ b/tmp/n8n @@ -0,0 +1 @@ +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwNTBlYzdjZC0yNTgzLTQ0ZjEtOTIzZS02N2NlYWY0Y2FlYTEiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwianRpIjoiYTUxNDA4MjQtOTJlMC00MzA0LTg2OGUtMDc4ZmNhNTNjZjIxIiwiaWF0IjoxNzc0Njk5NzI4fQ.DTs-IlULYHVR52WVqBGPkEz0ieHc5tuhT0KRdUN6N6o diff --git a/tmp/radarr b/tmp/radarr new file mode 100644 index 0000000..7c76f80 --- /dev/null +++ b/tmp/radarr @@ -0,0 +1 @@ +b417c7461d4942e1b8530d80d68c3717 diff --git a/tmp/radarr1080p b/tmp/radarr1080p new file mode 100644 index 0000000..f1e0b6f --- /dev/null +++ b/tmp/radarr1080p @@ -0,0 +1,2 @@ +http://10.2.1.100:7879/ +dadb191cff9c4b4ab309653f3f9da5ce diff --git a/tmp/seer b/tmp/seer new file mode 100644 index 0000000..f36ff79 --- /dev/null +++ b/tmp/seer @@ -0,0 +1 @@ +MTczODM1NzY3NjczMTYxMzc4ZDZlLWFiYjgtNGQwNi05ZTRjLWMyNTQ1Zjk0M2Y4ZA== diff --git a/tmp/seer-webhook b/tmp/seer-webhook new file mode 100644 index 0000000..eecc252 --- /dev/null +++ b/tmp/seer-webhook @@ -0,0 +1,13 @@ +url: + +http://10.4.1.113:5678/webhook/seerr-notify + +Webhook: + +{ + "session": "default", + "chatId": "120363404705299449@newsletter", + "text": "*🎬 Jetzt Verfügbar*\n\n *Titel:* {{subject}}\n\n *Beschreibung:* {{message}}\n\n *Link zum Poster:* {{image}} \n\n ➡️ Viel Spaß!! \n\n", + "linkPreview": true, + "linkPreviewHighQuality": true +} diff --git a/tmp/semaphore b/tmp/semaphore new file mode 100644 index 0000000..4447e1d --- /dev/null +++ b/tmp/semaphore @@ -0,0 +1 @@ +z0yv8u3qswftq8lowwvjb4hm5iwrbwfg5i3gpnryu7u= diff --git a/tmp/sonarr b/tmp/sonarr new file mode 100644 index 0000000..e4761b1 --- /dev/null +++ b/tmp/sonarr @@ -0,0 +1 @@ +cf2599df0a094dc388a62fb671f9d139 diff --git a/tmp/sonarr1080p b/tmp/sonarr1080p new file mode 100644 index 0000000..010d4c9 --- /dev/null +++ b/tmp/sonarr1080p @@ -0,0 +1,2 @@ +http://10.2.1.100:8990/ +b679d30cbf0d4641948b76659de1a02a diff --git a/update.yml b/update.yml index bf97314..0c7ae87 100644 --- a/update.yml +++ b/update.yml @@ -8,3 +8,30 @@ update_cache: yes upgrade: dist autoremove: yes + + - name: Pruefen ob Reboot noetig ist + ansible.builtin.stat: + path: /var/run/reboot-required + register: reboot_required + +- name: NVIDIA Kernel Headers nach Upgrade sicherstellen + hosts: nvidia + become: yes + tasks: + - name: Kernel Headers und DKMS installieren und Module bauen + ansible.builtin.shell: | + export PATH=$PATH:/usr/sbin + apt-get install -y linux-headers-$(uname -r) dkms + dkms autoinstall + register: headers_result + changed_when: "'newly installed' in headers_result.stdout" + +- name: Reboot falls noetig + hosts: all + become: yes + tasks: + - name: Reboot durchfuehren + ansible.builtin.reboot: + msg: "Reboot nach Update" + reboot_timeout: 300 + when: hostvars[inventory_hostname].reboot_required.stat.exists diff --git a/wireguard.yml b/wireguard.yml new file mode 100644 index 0000000..d2a334a --- /dev/null +++ b/wireguard.yml @@ -0,0 +1,6 @@ +--- +- name: WireGuard deployen + hosts: wireguard + become: yes + roles: + - wireguard diff --git a/wstunnel-cleanup.yml b/wstunnel-cleanup.yml new file mode 100644 index 0000000..c8c9c5a --- /dev/null +++ b/wstunnel-cleanup.yml @@ -0,0 +1,32 @@ +--- +- name: wstunnel entfernen + hosts: hysteria2 + become: yes + tasks: + - name: wstunnel Service stoppen und deaktivieren + systemd: + name: wstunnel + state: stopped + enabled: false + ignore_errors: true + + - name: wstunnel systemd Unit entfernen + file: + path: /etc/systemd/system/wstunnel.service + state: absent + notify: reload systemd + + - name: wstunnel Binary entfernen + file: + path: /usr/local/bin/wstunnel + state: absent + + - name: wstunnel Config entfernen + file: + path: /etc/wstunnel + state: absent + + handlers: + - name: reload systemd + systemd: + daemon_reload: true