Compare commits

15 Commits

Author SHA1 Message Date
kai fb3f39126e pingu-status Block hinzugefügt 2026-05-14 17:37:28 +00:00
kai b03b8f8b6d Status Script 2026-05-14 17:35:50 +00:00
kai 8107545ca2 scripts/test gelöscht 2026-05-14 17:31:23 +00:00
kai a9afc88140 scripts/README.md aktualisiert 2026-05-14 15:31:14 +00:00
kai 07e384e17f Logrotate Integriert
um keinen eigenen Cronjob anlegen zu müssen, wurde hier die Installation von Logrotate integriert
2026-05-14 14:34:18 +00:00
kai 1c099616d5 Logrotate Funktion hinzugefügt 2026-05-14 14:32:53 +00:00
kai fb6065ad7f Logrotae Funktion 2026-05-14 14:31:24 +00:00
kai e809744fa2 scripts/README.md aktualisiert 2026-05-14 14:17:28 +00:00
kai b82d192b54 README hinzugefügt 2026-05-14 14:15:39 +00:00
kai 60d84ba9fa README.md aktualisiert 2026-05-14 13:39:59 +00:00
kai 6e3603a9c4 README.md hinzugefügt 2026-05-14 13:39:17 +00:00
kai 94060b1ba2 Zeitstempel, Cron-sicheres SSH
Zeitstempel pro Alarm
vorher: kein Zeitpunkt
jetzt: exakte Event-Zeit

Cron-sicheres SSH
BatchMode (kein Hängen)
known_hosts sauber genutzt
accept-new für neue Nodes
2026-04-26 20:35:48 +00:00
kai 145c8b9ae7 umbau SSH und kommentare 2026-04-26 18:13:10 +00:00
kai d77b0a2af1 IPs fix und SSH stabilisiert
zudem Hostabfrage optimiert
2026-04-26 17:06:02 +00:00
kai 4d6f786f9d check_pihole_update Funktion
Funktion zum updaten von Pihole einegfügt
2026-04-26 09:42:12 +00:00
9 changed files with 636 additions and 16 deletions
+1
View File
@@ -0,0 +1 @@
git clone ssh://git@10.200.200.2:2222/kai/pingu-infra.git /opt/pingu/repo
+8
View File
@@ -0,0 +1,8 @@
/opt/pingu/logs/*.log {
weekly
rotate 4
compress
missingok
notifempty
copytruncate
}
+421
View File
@@ -0,0 +1,421 @@
# Pingu Infrastructure
Zentrale Infrastruktur- und Deployment-Repository für:
- Raspberry Pis
- Linux Server
- Cloudsysteme
- Docker Hosts
- Automatisierte Updates & Deployments
Die Systeme ziehen regelmäßig automatisch den aktuellen Stand aus dem Gitea-Repository und synchronisieren Skripte und Konfigurationen.
---
# Architektur
```text
+-------------------+
| Gitea Server |
| 10.200.200.2:2222 |
+---------+---------+
|
WireGuard VPN
|
+-----------------+-----------------+
| |
+-------+--------+ +---------+--------+
| Raspberry Pis | | Cloud / VPS |
| Heimnetz | | IONOS / Internet |
+----------------+ +------------------+
```
# Voraussetzungen
## Allgemein
Debian / Ubuntu basiertes Linux
Netzwerkzugriff auf den Gitea-Server
SSH-Key in Gitea hinterlegt
Git installiert
## Optional
Docker + Docker Compose
WireGuard VPN
# SSH-Key vorbereiten
## SSH-Key erzeugen
```
ssh-keygen -t ed25519
```
## Public Key anzeigen
```
cat ~/.ssh/id_ed25519.pub
```
## Key in Gitea hinzufügen
Gitea:
Profil -> Settings -> SSH Keys -> Add Key
---
# Git installieren
```
sudo apt update
sudo apt install git -y
```
---
# Repository klonen
## Standard
```
sudo mkdir -p /opt/pingu
sudo chown -R $USER:$USER /opt/pingu
git clone ssh://git@10.200.200.2:2222/kai/pingu-infra.git /opt/pingu/repo
```
---
# Verzeichnisstruktur
/opt/pingu/
├── logs/
│ ├── deploy.log
│ └── update.log
└── repo/
├── scripts/
├── docker/
└── configs/
---
# Deploy-Prozess
Das Deploy-Skript aktualisiert:
- Repository
- Skripte
- Berechtigungen
## Deploy manuell starten
```
bash /opt/pingu/repo/scripts/deploy.sh
```
# Deploy per Cronjob
## Raspberry / interne Systeme
```
*/15 * * * * /opt/pingu/repo/scripts/deploy.sh >> /opt/pingu/logs/deploy.log 2>&1
```
## Cloudserver
```
0 * * * * /opt/pingu/repo/scripts/deploy.sh >> /opt/pingu/logs/deploy.log 2>&1
```
Cronjob bearbeiten:
```
crontab -e
```
---
# Update-Prozess
Das Update-Skript:
- führt apt updates durch
- prüft Docker Updates
- aktualisiert Systempakete
- loggt Ergebnisse
## Manuell starten
```
- bash /opt/pingu/repo/scripts/update.sh
```
---
# Sudo-Rechte für Update-Skript
Damit apt ohne Passwort funktioniert:
```
sudo visudo
```
Hinzufügen:
```
kai ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get
```
---
# WireGuard Setup (Cloudzugriff)
## Ziel
Cloudserver greifen sicher auf interne Dienste zu:
- Gitea
- Pi-hole
- Interne APIs
- Docker Services
---
# Beispiel Netzwerk
## Gerät WireGuard IP
Gitea/Home Server 10.200.200.2
Cloudserver 10.200.200.1
---
# Heimserver Config
Datei:
```
/etc/wireguard/wg0.conf
```
```
[Interface]
Address = 10.200.200.2/24
PrivateKey = HOME_PRIVATE_KEY
[Peer]
PublicKey = CLOUD_PUBLIC_KEY
AllowedIPs = 10.200.200.1/32
Endpoint = CLOUD_IP:51820
PersistentKeepalive = 25
```
Cloudserver Config
```
[Interface]
Address = 10.200.200.1/24
PrivateKey = CLOUD_PRIVATE_KEY
ListenPort = 51820
[Peer]
PublicKey = HOME_PUBLIC_KEY
AllowedIPs = 10.200.200.2/32
PersistentKeepalive = 25
```
---
# WireGuard starten
```
sudo systemctl enable wg-quick@wg0
sudo systemctl restart wg-quick@wg0
```
---
# Verbindung testen
```
ping 10.200.200.2
sudo wg
```
---
# Docker Systeme
## Docker installieren
```
sudo apt install docker.io docker-compose-plugin -y
```
---
# Docker Compose Update Workflow
## Compose-Verzeichnis öffnen
```
cd /opt/paperless
```
---
# Backup erstellen
## PostgreSQL Dump
```
sudo bash -c 'docker exec paperless-db-1 pg_dump -U paperless paperless > ~/paperless_backup.sql'
```
---
# Neue Images herunterladen
```
sudo docker compose pull
```
---
# Container neu erstellen
```
sudo docker compose up -d
```
---
# Status prüfen
```
sudo docker ps
```
---
# Logs prüfen
```
sudo docker logs -f paperless-webserver-1
```
---
# Docker Cleanup
Nicht mehr benötigte Images entfernen:
```
sudo docker image prune -a
```
---
# Logrotate
## Konfiguration erstellen
```
sudo nano /etc/logrotate.d/pingu-deploy
```
Inhalt:
```
/opt/pingu/logs/*.log {
weekly
rotate 4
compress
missingok
notifempty
copytruncate
}
```
---
# Nützliche Befehle
## Git Status
```
git -C /opt/pingu/repo status
```
## Remote prüfen
```
git -C /opt/pingu/repo remote -v
```
## Repository aktualisieren
```
git -C /opt/pingu/repo pull
```
## Docker Container anzeigen
```
sudo docker ps
```
## WireGuard Status
```
sudo wg
```
## Troubleshooting
Permission denied bei apt
Script nicht als root gestartet oder fehlende sudo-Regeln.
Git fragt nach Passwort
SSH-Key fehlt oder nicht in Gitea hinterlegt.
WireGuard kein Handshake
Prüfen:
Firewall
UDP 51820
Endpoint
AllowedIPs
Hinweise
Deploy-Skripte laufen absichtlich simpel.
Docker Updates werden bewusst nicht automatisch durchgeführt.
Produktivsysteme sollten vor Updates gesichert werden.
WireGuard ermöglicht sicheren Zugriff ohne öffentliche Freigaben interner Dienste.
Philosophie
Kleine Infrastruktur.
Wenig Overhead.
Maximal nachvollziehbar.
Lieber einfache Bash-Skripte als unnötige Komplexität.
# Logrotate
Die Deploy- und Update-Logs wachsen dauerhaft mit.
Um zu verhindern, dass Logdateien über Monate oder Jahre unendlich groß werden, wird logrotate verwendet.
Die Logrotate-Konfiguration wird zentral über das Git-Repository verteilt und automatisch installiert.
---
# Repository Struktur
```text
repo/
├── scripts/
│ ├── deploy.sh
│ ├── update.sh
│ └── install-logrotate.sh
├── configs/
│ └── logrotate/
│ └── pingu
Logrotate Konfiguration
Datei im Repository:
configs/logrotate/pingu
Inhalt:
/opt/pingu/logs/*.log {
weekly
rotate 4
compress
missingok
notifempty
copytruncate
}
Installationsskript
Datei:
scripts/install-logrotate.sh
Inhalt:
#!/bin/bash
set -euo pipefail
REPO_DIR="/opt/pingu/repo"
echo "[INFO] Installiere logrotate config..."
sudo cp "$REPO_DIR/configs/logrotate/pingu" /etc/logrotate.d/pingu
sudo chmod 644 /etc/logrotate.d/pingu
echo "[OK] Logrotate config installiert"
Integration in deploy.sh
Im deploy.sh wird das Installationsskript automatisch ausgeführt.
Beispiel:
echo "Install logrotate config..."
bash "$REPO_DIR/scripts/install-logrotate.sh"
Dadurch werden Änderungen an der Logrotate-Konfiguration automatisch auf alle Systeme verteilt.
Funktion
Die Konfiguration sorgt dafür:
Rotation einmal pro Woche
4 alte Logs werden behalten
alte Logs werden komprimiert
fehlende Logs erzeugen keinen Fehler
laufende Prozesse können weiterloggen
Logrotate testen
Konfiguration prüfen:
sudo logrotate -d /etc/logrotate.d/pingu
Rotation erzwingen:
sudo logrotate -f /etc/logrotate.d/pingu
Typische Logdateien
/opt/pingu/logs/deploy.log
/opt/pingu/logs/update.log
Vorteile dieses Ansatzes
zentrale Verwaltung über Git
automatische Verteilung
keine manuelle Pflege auf einzelnen Systemen
identisches Verhalten auf allen Hosts
leicht erweiterbar für weitere Systemconfigs
+4
View File
@@ -22,4 +22,8 @@ rsync -av --delete "$REPO_DIR/scripts/" "$TARGET_DIR/"
echo "Set permissions..."
chmod +x "$TARGET_DIR"/*.sh
#logrotate Integration
echo "Install logrotate config..."
bash "$REPO_DIR/scripts/install-logrotate.sh"
echo "==== Deploy fertig ===="
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
set -euo pipefail
REPO_DIR="/opt/pingu/repo"
echo "[INFO] Installiere logrotate config..."
sudo cp "$REPO_DIR/configs/logrotate/pingu" /etc/logrotate.d/pingu
sudo chmod 644 /etc/logrotate.d/pingu
echo "[OK] Logrotate config installiert"
+66
View File
@@ -0,0 +1,66 @@
#!/bin/bash
echo "=============================="
echo " 🐧 PINGU STATUS"
echo " Host: $(hostname)"
echo " Time: $(date)"
echo "=============================="
echo ""
# --- Git / Deploy ---
echo "📦 DEPLOY (Git)"
if [ -d /opt/pingu/repo ]; then
cd /opt/pingu/repo
echo "Branch: $(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
echo "Commit: $(git log -1 --format='%h - %s' 2>/dev/null)"
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
echo "State: CLEAN ✅"
else
echo "State: DIRTY ⚠️"
fi
else
echo "Repo missing ❌"
fi
echo ""
# --- WireGuard (optional) ---
echo "🔐 WIREGUARD"
if command -v wg >/dev/null 2>&1; then
if sudo wg show >/dev/null 2>&1; then
sudo wg show 2>/dev/null | grep -E "interface|peer|transfer|endpoint" || echo "WireGuard active"
else
echo "WireGuard installed but no config active"
fi
else
echo "Not installed"
fi
echo ""
# --- Docker (optional) ---
echo "🐳 DOCKER"
if command -v docker >/dev/null 2>&1; then
if docker ps >/dev/null 2>&1; then
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
echo "Docker not running or permission denied"
fi
else
echo "Not installed"
fi
echo ""
# --- System ---
echo "💾 SYSTEM"
df -h / | tail -n 1
echo ""
echo "=============================="
+65 -11
View File
@@ -1,12 +1,21 @@
#!/bin/bash
#############################################
# 🔐 CONFIG
#############################################
TOKEN="8101319618:AAHboFVVgmLPccJB0MDr_R2g0K90hkGqkRw"
CHAT_ID="581059353"
PIS=("192.168.178.2" "192.168.178.3" "localhost")
PIS=("192.168.178.2" "192.168.178.3" "192.168.178.5" "localhost")
STATE_FILE="/home/kai/.ssh-monitor-lastcheck"
#############################################
# 🧠 INITIALISIERUNG
#############################################
if [ ! -f "$STATE_FILE" ]; then
date --iso-8601=seconds > "$STATE_FILE"
fi
@@ -14,27 +23,66 @@ fi
LAST_CHECK=$(cat "$STATE_FILE")
NOW=$(date --iso-8601=seconds)
#############################################
# 🔧 SSH SETTINGS (CRON SAFE)
#############################################
SSH_OPTS="-o ConnectTimeout=5 \
-o StrictHostKeyChecking=accept-new \
-o BatchMode=yes \
-o UserKnownHostsFile=/home/kai/.ssh/known_hosts"
#############################################
# 🔁 HAUPTSCHLEIFE
#############################################
for PI in "${PIS[@]}"
do
if [ "$PI" == "localhost" ]; then
LOG=$(journalctl -u ssh --since "$LAST_CHECK" --no-pager)
HOST=$(hostname)
else
LOG=$(ssh -o ConnectTimeout=5 kai@$PI \
"journalctl -u ssh --since \"$LAST_CHECK\" --no-pager")
HOST=$(ssh kai@$PI hostname)
#########################################
# 🏠 LOCAL HOST
#########################################
if [ "$PI" == "localhost" ]; then
LOG=$(journalctl -u ssh --since "$LAST_CHECK" --no-pager 2>/dev/null || true)
HOST=$(hostname)
else
#########################################
# 🌐 REMOTE HOST
#########################################
LOG=$(ssh $SSH_OPTS kai@$PI \
"journalctl -u ssh --since \"$LAST_CHECK\" --no-pager" 2>/dev/null || true)
HOST=$(ssh $SSH_OPTS kai@$PI hostname 2>/dev/null || echo "$PI")
fi
FAILS=$(echo "$LOG" | grep "Failed password" | wc -l)
#############################################
# 🚨 ANALYSE (sauber gefiltert)
#############################################
FAILS=$(echo "$LOG" | grep "Failed password for" | wc -l)
#############################################
# 🚨 ALERT LOGIC
#############################################
if [ "$FAILS" -gt 0 ]; then
IPS=$(echo "$LOG" | grep "Failed password" \
EVENT_TIME=$(date '+%Y-%m-%d %H:%M:%S')
IPS=$(echo "$LOG" | grep "Failed password for" \
| awk '{print $(NF-3)}' \
| sort | uniq -c | sort -nr)
MESSAGE="🚨 SSH Angriff erkannt!
Zeit: $EVENT_TIME
Host: $HOST ($PI)
Fehlversuche: $FAILS
@@ -43,8 +91,14 @@ $IPS"
curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \
-d chat_id="$CHAT_ID" \
-d text="$MESSAGE"
-d text="$MESSAGE" >/dev/null
fi
done
#############################################
# 💾 STATE UPDATE
#############################################
echo "$NOW" > "$STATE_FILE"
-1
View File
@@ -1 +0,0 @@
Deploy-Test
+54
View File
@@ -12,6 +12,10 @@ DOCKER_UPDATES=0
DOCKER_UPDATE_LIST=""
DOCKER_MSG=""
PIHOLE_INSTALLED=0
PIHOLE_UPDATED=0
PIHOLE_MSG=""
log() {
echo "[$(date '+%F %T')] $1" | tee -a "$LOG"
}
@@ -78,6 +82,38 @@ check_docker_updates() {
fi
}
check_pihole_update() {
if ! command -v pihole >/dev/null 2>&1; then
PIHOLE_MSG=""
return
fi
PIHOLE_INSTALLED=1
log "Pi-hole detected → checking update"
local output
if output="$(pihole -up 2>&1)"; then
if echo "$output" | grep -q "Everything is up to date"; then
PIHOLE_MSG="🧱 Pi-hole: aktuell"
else
PIHOLE_UPDATED=1
PIHOLE_MSG="🧱 Pi-hole: Update durchgeführt"
fi
else
PIHOLE_MSG="❌ Pi-hole: Update fehlgeschlagen"
log "$output"
fi
}
# Pihole Check
if [ "$PIHOLE_INSTALLED" -eq 1 ]; then
if ! pihole status | grep -q "enabled"; then
PIHOLE_MSG="❌ Pi-hole: läuft nicht korrekt"
fi
fi
main() {
mkdir -p "$(dirname "$LOG")"
@@ -99,6 +135,7 @@ main() {
fi
check_docker_updates
check_pihole_update
local msg
msg=$(cat <<EOF
@@ -109,6 +146,8 @@ main() {
$( [ "$REBOOT" -eq 1 ] && echo "🔄 Reboot: erforderlich" || echo "✔ Reboot: nicht nötig" )
${DOCKER_MSG}
$( [ "$PIHOLE_INSTALLED" -eq 1 ] && echo "" )
${PIHOLE_MSG}
━━━━━━━━━━━━━━━
📅 $(date '+%F %T')
@@ -125,4 +164,19 @@ EOF
fi
}
# pingu-status Block
echo "[INFO] Installiere pingu-status..."
STATUS_SRC="/opt/pingu/repo/scripts/pingu-status.sh"
STATUS_DST="/usr/local/bin/pingu-status"
if [ -f "$STATUS_SRC" ]; then
cp "$STATUS_SRC" "$STATUS_DST"
chmod 755 "$STATUS_DST"
chown root:root "$STATUS_DST"
echo "[OK] pingu-status installiert"
else
echo "[WARN] pingu-status.sh nicht gefunden im Repo"
fi
main "$@"