8 changed files with 3 additions and 778 deletions
-20
View File
@@ -1,20 +0,0 @@
{
"permissions": {
"allow": [
"Bash(git init *)",
"Bash(git config *)",
"Bash(git remote *)",
"Bash(git checkout *)",
"Bash(git add *)",
"Bash(git commit -m 'v0.5.0 – Clownfischserver HomeIP Auto-Update: myfritz Automatik für SSH \\(5-Min Cron\\) *)",
"Bash(git push *)",
"Bash(bash -n install.sh)",
"Bash(bash -n scripts/clownfischserver-homeip-updater.sh)",
"Bash(python3 -m py_compile bot/*.py)",
"Bash(awk '{print \"Datei: \" $1 \" Größe: \" $5 \" Bytes\"}')",
"Bash(grep -oE '\\\\b\\([0-9]{1,3}\\\\.\\){3}[0-9]{1,3}\\\\b')",
"Bash(git commit -m 'Bugfix: Clownfischserver HomeIP Updater – Fehlerbehandlung & Fallbacks *)",
"Bash(git commit -m 'Feature: Multi-Distro Firewall-Support für HomeIP Updater *)"
]
}
}
-318
View File
@@ -1,318 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
---
## Project Overview
**Clownfischserver** is a self-hosted, AI-driven Linux server manager controlled exclusively via Telegram. The core principle: admins write naturally, the bot understands, generates commands, creates scripts, manages the server.
- **Version:** v0.5.0 (in development)
- **License:** GPL-3.0
- **Status:** Active Development (feature/homeip-auto-update branch)
- **Core Dev:** Mehlzoerwer-Claude (Thomas Matthes)
---
## Architecture & Key Patterns
### Core Data Flow
```
Telegram User → bot.py → {ollama_client, shell.py, aider_wrapper} → Server Actions
↓
Chat-Model (gemma3) + Coder-Model (qwen2.5-coder)
Fallback: OpenRouter Free (if Ollama unavailable)
```
### Central Patterns
**Multi-Distro Abstraction:** The codebase abstracts firewall & package managers:
- **install.sh Step 2:** Detects `apt`/`dnf`/`pacman` → installs appropriate packages
- **install.sh Step 4:** Installs firewall (`ufw` for apt, `firewalld` for dnf, manual for pacman)
- **homeip-updater.sh:** Detects active firewall at runtime (`detect_firewall()` at line 18-26) → adapts rule syntax
This is critical: **Any Firewall change must support all three backends** (ufw, firewalld, iptables).
**Dual-Model KI Strategy:**
- **Coder-Model (qwen2.5-coder:7b):** `/shell`, `/code`, command generation → requires good programming ability
- **Chat-Model (gemma3:4b):** Freetext, explanations, translations → requires good German + multilingual
- **Fallback:** OpenRouter free tier if Ollama times out (optional, configured in `.env`)
**Telegram Safety Patterns:**
- `safe_reply()` wraps all bot responses (Markdown fallback for special chars)
- Long responses auto-split (Telegram 4096 char limit)
- Command confirmation: `/shell` generates → `/ja` confirms → executes (no auto-exec)
---
## File Structure & Responsibilities
### `bot/` – Core Bot Logic
- **bot.py** (700+ lines): Main handler, all commands, auth guard, self-update dialog
- **ollama_client.py**: Dual-model manager, OpenRouter fallback, context-window config
- **openrouter_client.py**: Cloud fallback (openrouter/free auto-router)
- **shell.py**: Command execution (shlex.quote for safety), result capture
- **aider_wrapper.py**: Code agent wrapper (--edit-format diff, 600s timeout)
- **snapshot.py**: tar.gz backups, workspace tracking, package list snapshots
- **boot_notify.py**: Sends Telegram message 120s after server boot (systemd oneshot)
- **knock_notify.py**: Alerts on port-knock SSH access attempts
### `scripts/` – Utility Scripts (NEW in v0.5.0)
- **clownfischserver-homeip-updater.sh**: Auto-update firewall rule for home IP (5-min cron)
- Detects firewall type (ufw/firewalld/iptables)
- Resolves myfritz DNS (dig/nslookup/getent fallbacks)
- State-file tracking to skip redundant updates
- **Critical:** Must work on Ubuntu/Debian/Fedora/Arch/openSUSE
- **README-HOMEIP.md**: Complete homeip-updater documentation (setup, troubleshooting, firewall details)
### `install.sh` – Multi-Step Installation (900+ lines)
8-step installer with full automation:
1. **System checks** → RAM, disk, distro detection
2. **Packages** → distro-specific (apt/dnf/pacman)
3. **User setup** → custom username, passwordless sudo
4. **SSH + Firewall** → sshd_config tuning, ufw/firewalld setup, **NEW: myfritz prompt**
5. **Ollama** → download, models selection (RAM-aware defaults)
6. **Python venv** → bot + aider (separate venvs due to dependency conflicts)
7. **Telegram bot** → BotFather token, chat-ID, optional OpenRouter key
8. **Systemd** → clownfisch service + boot-notification service, **NEW: cron-job for homeip-updater**
**Key Pattern:** `install.sh` runs **as root** and manages root-level resources. The homeip-updater cron-job runs as root (for firewall access).
### Configuration & Data
- **config/.env** → All secrets, model choices, paths (generated by install.sh, permissions 0600)
- **config/.env.example** → Template (must be kept in sync with install.sh additions)
- **config/knockd.conf** → Port-knocking rules (7000→8000→9000)
- **systemd/clownfisch.service** → Bot service (User patched dynamically from MGMT_USER)
- **systemd/clownfisch-boot.service** → Boot notification (oneshot, 120s delay)
---
## Critical Design Decisions
### 1. Firewall Abstraction (New in v0.5.0)
The homeip-updater.sh demonstrates the new **multi-firewall abstraction pattern**:
```bash
detect_firewall() {
systemctl is-active ufw → use: ufw allow from X port 22
systemctl is-active firewalld → use: firewall-cmd rich-rule
command -v iptables → use: iptables -I INPUT
}
```
**Why this matters:** When adding firewall-dependent features, always implement for all three. This is not optional.
### 2. No Interactive Commands in /shell
The `/shell` command uses a "non-interactive only" prompt. Why?
- **Cron-friendly:** homeip-updater runs in cron, can't wait for user input
- **Safety:** No `nano`, `vim`, `crontab -e` (can't pipe credentials)
- **Pattern:** UFW delete needs `echo "y" |` confirmation (line 81 in homeip-updater.sh)
### 3. .env Parsing Robustness
Variable loading must handle CRLF (Windows git clones):
```bash
MYFRITZ_DOMAIN=$(grep "^VAR=" .env | cut -d= -f2 | tr -d '\r\n')
```
This trims trailing newlines/carriage returns. Critical for .env variables used in firewall rules.
### 4. State File Tracking in homeip-updater
The `/var/lib/clownfischserver-homeip-state` file prevents redundant UFW updates:
- If DNS resolves to same IP → skip rule updates (idempotent)
- If IP changed → remove old rule, add new rule
- Logging includes old IP vs new IP for audit trail
This is important because UFW rule deletion prompts interactively (hence the `echo "y" |` workaround).
### 5. Package Dependency Management
- **dnsutils** must be in apt install (Step 2) for `dig` command
- **firewalld** installed for dnf systems (handled in Step 4)
- **iptables** assumed on pacman (Arch) systems
- The homeip-updater has DNS fallbacks: dig → nslookup → getent (lines 43-52)
---
## Development Workflow
### Testing on Multiple Distros
The project must work on:
- **Ubuntu/Debian** (primary, uses ufw)
- **Fedora/RHEL** (uses firewalld)
- **Arch/Manjaro** (uses iptables/nftables)
- **openSUSE** (uses firewalld)
**Recommended setup (from project notes):**
- Pop!_OS on laptop → development & editing
- Homlab VMs (Arch, openSUSE) → local testing of install.sh + homeip-updater
- VPS Server (Ubuntu) → real-world myfritz testing
### Bash Script Syntax Check
```bash
bash -n install.sh
bash -n scripts/clownfischserver-homeip-updater.sh
```
Run before commits. CRLF warnings are harmless (Windows git clones), but scripts must be syntactically valid.
### Python Syntax Check
```bash
python3 -m py_compile bot/*.py
```
### Testing Firewall Rules
**ufw (Ubuntu/Debian):**
```bash
ufw status numbered
ufw allow from 192.168.1.100 to any port 22 comment "test"
echo "y" | ufw delete allow from 192.168.1.100 to any port 22
```
**firewalld (Fedora/openSUSE):**
```bash
firewall-cmd --list-all
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' port protocol='tcp' port='22' accept"
firewall-cmd --reload
```
**iptables (Arch):**
```bash
iptables -L INPUT -n
iptables -I INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT
iptables -D INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT
```
---
## Git Workflow & Policies
### Push Policy
**Maximum 4 pushes per hour** (one every ~15 minutes). This is documented in `memory/feedback_github_policy.md`.
**Why:** Reduces GitHub notification spam, allows batching commits logically, leaves review time between updates.
### Branch Strategy
- **main:** Stable releases only (v0.4.13, v0.5.0, etc.)
- **feature/*** → PR reviewed → merged to main after testing
- Current: `feature/homeip-auto-update` (v0.5.0 preparation)
### Commit Message Style
```
<Type>: <Title> – <Subtitle if complex>
Details paragraph (optional, multi-line OK)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
```
Examples:
- `v0.5.0 – Clownfischserver HomeIP Auto-Update: myfritz Automatik für SSH (5-Min Cron)`
- `Bugfix: Clownfischserver HomeIP Updater – Fehlerbehandlung & Fallbacks`
- `Feature: Multi-Distro Firewall-Support für HomeIP Updater`
---
## Important Gotchas & Caveats
### 1. iptables Persistence on Arch
The homeip-updater uses `iptables -I INPUT` to add rules. On some systems, these don't persist after reboot. **Future enhancement:** integrate with `iptables-persistent` or `nftables` for persistence. Current status: evaluating.
### 2. Firewall Rule Comments
UFW and firewalld support rule comments (`comment "..."`) for tracking. **iptables does not.** This makes tracking which rules were added by clownfischserver harder on Arch. Document this if implementing rule deletion on iptables.
### 3. systemd Service User Patching
The MGMT_USER (arbitrary username) must be patched into systemd service files during installation. This uses regex: `User=\S+` (line 822 in install.sh). If systemd syntax changes, update regex.
### 4. Ollama Model Download Brittleness
`ollama pull` can hang or timeout. The installer includes progress bars but no retry logic. Users on slow/intermittent connections may need manual intervention.
### 5. .env Variable Escaping
Variables like `CLOWNFISCHSERVER_HOME_IP_DOMAIN=vorname.myfritz.net` are read with `grep` and `cut`. They must not contain `=` characters. Document constraints in `.env.example`.
---
## Code Patterns to Follow
### Safe Telegram Replies
Always use `safe_reply()` wrapper (bot.py). Never call `send_message()` directly.
### Async Telegram Handlers
All message handlers must be `async def`. Use `@app.message_handler()` decorator pattern from existing code.
### Shell Command Safety
Use `shlex.quote()` for untrusted user input in shell.py. Example:
```python
cmd = f"rm {shlex.quote(user_path)}"
```
### Firewall Rule Matching
When detecting or modifying firewall rules, match exact patterns to avoid false positives:
- UFW: `"22.*ALLOW.*FROM\s+$IP"` (line 79, homeip-updater.sh)
- firewalld: exact rule with family + port + protocol
- iptables: exact `-s $IP -p tcp --dport 22` match
---
## Memory & Context Files
For other Claude instances working on this project:
- **project_status_v05.md** – Current v0.5.0 status, tested scenarios, known limitations
- **feedback_github_policy.md** – Push frequency policy, batching rules
These are in `.claude/projects/.../memory/`. They provide context for continued development.
---
## Key References
- **CLOWNFISCHSERVER.md** – Detailed project context (architecture, .env variables, roadmap)
- **README.md** – User-facing documentation
- **scripts/README-HOMEIP.md** – Complete homeip-updater guide
- **CONTRIBUTING.md** – Contribution guidelines (already aligned with multi-distro goals)
---
## Quick Commands
```bash
# Syntax check
bash -n install.sh
python3 -m py_compile bot/*.py
# Test homeip-updater (dry-run, logs to stdout)
bash -x scripts/clownfischserver-homeip-updater.sh
# Check git status
git status
git log --oneline -5
# Build release ZIP (from install.sh docs)
cd .. && zip -r v0.5.0-clownfischserver.zip clownfischserver/ -x "*__pycache__*" "*.pyc" ".git/*"
```
---
**Last Updated:** 2026-05-01 (v0.5.0 HomeIP Feature)
**Next Version:** v0.5.0 (pending VPS/VM testing, then merge to main)
-29
View File
@@ -113,35 +113,6 @@ SNAPSHOT_METHOD=tar
INSTALL_DIR=/opt/clownfischserver
MGMT_USER=clownfisch # Linux-User (beliebig wählbar)
AIDER_WORKDIR=/opt/clownfisch-workspace
CLOWNFISCHSERVER_HOME_IP_DOMAIN=vorname.myfritz.net # Optional: myfritz für Auto-SSH-Freigabe
```
### Clownfischserver HomeIP Auto (neu in v0.5.0)
**Feature:** Automatische SSH-Freigabe für deine Home-IP alle 5 Minuten
- **myfritz.net:** DynDNS-Service (AVM Fritz.Box) – kostenlos
- **Cron-Job:** Läuft als `root` alle 5 Min
- **Workflow:**
1. DNS-Auflösung: `vorname.myfritz.net` → IP-Adresse
2. Vergleich: Alte IP vs. neue IP
3. Bei Änderung: UFW-Regel aktualisieren
4. Logging: `/var/log/clownfischserver-homeip.log`
**Voraussetzungen:**
- myfritz-Account bei https://myfritz.net/ (kostenlos)
- `dig` oder `nslookup` für DNS-Auflösung (meist bereits installiert)
**Beispiel:**
```bash
# Installation: wird vom install.sh gefragt
? myfritz Home-IP permanent erlauben? [j/n]
→ j
? Deine myfritz Adresse:
→ mehlzoerwer.myfritz.net
# Dann läuft:
*/5 * * * * /opt/clownfischserver/scripts/clownfischserver-homeip-updater.sh >> /var/log/clownfischserver-homeip.log 2>&1
```
---
+2 -2
View File
@@ -56,8 +56,8 @@ Das Ziel: **Server-Administration so einfach wie eine Chat-Nachricht.** Heute ei
```bash
# Frisches Ubuntu/Debian – als root:
wget https://github.com/mehlzoerwer-claude/clownfischserver/releases/latest/download/clownfischserver.zip
unzip clownfischserver.zip && cd clownfischserver
wget https://github.com/mehlzoerwer-claude/clownfischserver/archive/refs/heads/main.zip
unzip main.zip && cd clownfischserver-main
bash install.sh
```
-5
View File
@@ -24,8 +24,3 @@ SNAPSHOT_METHOD=tar
INSTALL_DIR=/opt/clownfischserver
MGMT_USER=clownfish
AIDER_WORKDIR=/opt/clownfisch-workspace
# Clownfischserver HomeIP Automatik (optional)
# myfritz Adresse für automatische SSH-Freigabe von Zuhause
# Falls aktiviert: Cron-Job prüft alle 5 Min und aktualisiert ufw-Regeln
# CLOWNFISCHSERVER_HOME_IP_DOMAIN=vorname.myfritz.net
+1 -67
View File
@@ -168,7 +168,7 @@ step_packages() {
case "$PKG_MANAGER" in
apt)
run_with_spinner "Paketliste aktualisieren" apt-get update -qq || fail "apt update fehlgeschlagen"
run_with_spinner "Pakete installieren" apt-get install -y -qq curl wget git ufw python3 python3-pip python3-venv sudo htop net-tools lsof rsync openssl knockd dnsutils || warn "Einige Pakete konnten nicht installiert werden – siehe Log"
run_with_spinner "Pakete installieren" apt-get install -y -qq curl wget git ufw python3 python3-pip python3-venv sudo htop net-tools lsof rsync openssl knockd || warn "Einige Pakete konnten nicht installiert werden – siehe Log"
;;
dnf)
run_with_spinner "Pakete aktualisieren" dnf update -y -q
@@ -269,33 +269,6 @@ step_ssh() {
ok "SSH läuft – Passwort + Key erlaubt"
info "SSH wird erst gesperrt wenn du im Bot /ssh close sendest"
# Home IP Auto-Allow via myfritz
CLOWNFISCHSERVER_HOME_IP_DOMAIN=""
echo ""
echo -e " ${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${BOLD} myfritz Home-IP Automatik${NC}"
echo -e " ${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " SSH von Zuhause immer offen – ohne Port-Knocking."
echo -e " ${CYAN} Clownfischserver aktualisiert deine Home-IP alle 5 Min automatisch.${NC}"
echo ""
if ask_yn "myfritz Home-IP permanent erlauben?"; then
echo ""
echo -e " ${YELLOW}?${NC} ${BOLD}Deine myfritz Adresse:${NC}"
echo -e " ${CYAN} Format: vorname.myfritz.net${NC}"
read -r -p " → " CLOWNFISCHSERVER_HOME_IP_DOMAIN
if [[ -n "$CLOWNFISCHSERVER_HOME_IP_DOMAIN" ]]; then
ok "myfritz Adresse gespeichert: $CLOWNFISCHSERVER_HOME_IP_DOMAIN"
info "⏱ Clownfischserver-HomeIP Updater wird alle 5 Min gestartet"
else
warn "Leere Adresse – myfritz Automatik deaktiviert"
CLOWNFISCHSERVER_HOME_IP_DOMAIN=""
fi
else
info "myfritz Automatik deaktiviert"
fi
# Firewall
case "$PKG_MANAGER" in
apt)
@@ -708,7 +681,6 @@ SNAPSHOT_METHOD=$SNAPSHOT_METHOD
INSTALL_DIR=$INSTALL_DIR
MGMT_USER=$MGMT_USER
AIDER_WORKDIR=$WORKSPACE_DIR
CLOWNFISCHSERVER_HOME_IP_DOMAIN=$CLOWNFISCHSERVER_HOME_IP_DOMAIN
ENVEOF
chmod 600 "$INSTALL_DIR/config/.env"
@@ -790,30 +762,6 @@ BOOTEOF
run_with_spinner "Boot-Notification aktivieren" bash -c "systemctl daemon-reload && systemctl enable clownfisch-boot"
ok "Boot-Notification: Telegram-Meldung 2 Min nach Serverstart"
# Clownfischserver HomeIP Updater (wenn aktiviert)
if [[ -n "$CLOWNFISCHSERVER_HOME_IP_DOMAIN" ]]; then
mkdir -p "$INSTALL_DIR/scripts"
cp "$SCRIPT_DIR/scripts/clownfischserver-homeip-updater.sh" "$INSTALL_DIR/scripts/" 2>/dev/null || \
warn "homeip-updater.sh nicht gefunden – manuell nachträglich einrichten"
if [ -f "$INSTALL_DIR/scripts/clownfischserver-homeip-updater.sh" ]; then
chmod +x "$INSTALL_DIR/scripts/clownfischserver-homeip-updater.sh"
chown root:root "$INSTALL_DIR/scripts/clownfischserver-homeip-updater.sh"
# Cron-Job für root (da ufw sudo braucht)
CRON_JOB="*/5 * * * * $INSTALL_DIR/scripts/clownfischserver-homeip-updater.sh >> /var/log/clownfischserver-homeip.log 2>&1"
# Bestehende clownfischserver Cron-Jobs entfernen (install.sh läuft als root)
crontab -l 2>/dev/null | grep -v clownfischserver-homeip-updater | crontab - 2>/dev/null || true
# Neuen Job hinzufügen
(crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab - >> "$LOG_FILE" 2>&1
ok "Cron-Job aktiviert: alle 5 Min HomeIP prüfen"
info "Log: /var/log/clownfischserver-homeip.log"
fi
fi
}
# ZUSAMMENFASSUNG
@@ -830,13 +778,6 @@ print_summary() {
echo -e " ${BOLD}SSH User:${NC} $MGMT_USER (Passwort aktiv!)"
echo -e " ${BOLD}KI-Modell:${NC} $OLLAMA_MODEL"
echo -e " ${BOLD}Snapshots:${NC} $SNAPSHOT_DIR ($SNAPSHOT_METHOD)"
if [[ -n "$CLOWNFISCHSERVER_HOME_IP_DOMAIN" ]]; then
echo -e " ${BOLD}${GREEN}HomeIP Auto:${NC} $CLOWNFISCHSERVER_HOME_IP_DOMAIN (alle 5 Min aktualisiert)"
else
echo -e " ${BOLD}HomeIP Auto:${NC} nicht aktiviert"
fi
echo -e " ${BOLD}Logs:${NC} journalctl -u clownfisch -f"
echo -e " ${BOLD}Install-Log:${NC} $LOG_FILE"
echo ""
@@ -851,13 +792,6 @@ print_summary() {
echo -e " ${CYAN} /ssh open 1.2.3.4 -> SSH nur fuer deine IP${NC}"
echo -e " ${CYAN} /ssh close -> SSH sperren${NC}"
echo ""
if [[ -n "$CLOWNFISCHSERVER_HOME_IP_DOMAIN" ]]; then
echo -e " ${GREEN}${BOLD}🐠 Clownfischserver-HomeIP Status:${NC}"
echo -e " ${GREEN} Cron-Job aktiv: /var/log/clownfischserver-homeip.log${NC}"
echo ""
fi
echo -e " ${YELLOW}Install-Log (letzte 10 Zeilen):${NC}"
tail -10 "$LOG_FILE"
echo ""
-169
View File
@@ -1,169 +0,0 @@
# 🐠 Clownfischserver HomeIP Auto-Update
Automatische SSH-Freigabe für deine Home-IP – ohne Port-Knocking.
**Multi-Distro Support:** ✅ Ubuntu/Debian (ufw) | ✅ Fedora/RHEL (firewalld) | ✅ Arch/Manjaro (iptables) | ✅ openSUSE (firewalld)
## Wie es funktioniert
1. **Installation:** `install.sh` fragt nach deiner myfritz-Adresse
2. **Cron-Job:** Läuft alle 5 Minuten (root crontab)
3. **DNS-Auflösung:** Löst `vorname.myfritz.net` auf
4. **UFW-Update:** Aktualisiert die Firewall-Regel wenn IP sich ändert
## Multi-Distro Firewall-Support
| Distribution | Firewall | Support |
|--------------|----------|---------|
| Ubuntu/Debian | `ufw` | ✅ Vollständig |
| Fedora/RHEL/CentOS | `firewalld` | ✅ Vollständig |
| Arch/Manjaro | `iptables` | ✅ Vollständig |
| openSUSE | `firewalld` | ✅ Vollständig |
| Alpine | `ufw`/`iptables` | ✅ Fallback |
**Automatische Erkennung:** Das Script erkennt die aktive Firewall zur Laufzeit und nutzt die entsprechenden Kommandos.
## Setup während Installation
```bash
[4/8] SSH + Firewall
? myfritz Home-IP permanent erlauben? [j/n]
→ j
? Deine myfritz Adresse:
Format: vorname.myfritz.net
→ mehlzoerwer.myfritz.net
```
Das Script wird dann automatisch:
- In `/opt/clownfischserver/scripts/` installiert
- Executable gemacht
- In `root`-Crontab als 5-Minuten-Job eingetragen
- **Firewall automatisch erkannt** (ufw/firewalld/iptables)
## Manuelle Verwaltung
### Script manuell ausführen
```bash
sudo /opt/clownfischserver/scripts/clownfischserver-homeip-updater.sh
```
### Cron-Job prüfen
```bash
sudo crontab -l | grep clownfischserver-homeip
```
### Logs anschauen
```bash
tail -f /var/log/clownfischserver-homeip.log
```
### Manuell aktivieren/deaktivieren
**Aktivieren** (wenn nicht aktiviert während Installation):
```bash
# myfritz-Adresse in .env eintragen
sudo nano /opt/clownfischserver/config/.env
# CLOWNFISCHSERVER_HOME_IP_DOMAIN=vorname.myfritz.net
# Cron-Job hinzufügen
(sudo crontab -l 2>/dev/null; echo "*/5 * * * * /opt/clownfischserver/scripts/clownfischserver-homeip-updater.sh >> /var/log/clownfischserver-homeip.log 2>&1") | sudo crontab -
```
**Deaktivieren:**
```bash
# Aus .env entfernen
sudo nano /opt/clownfischserver/config/.env
# CLOWNFISCHSERVER_HOME_IP_DOMAIN= (leer lassen)
# Cron-Job entfernen
sudo crontab -l 2>/dev/null | grep -v clownfischserver-homeip | sudo crontab -
# UFW-Regeln cleanup (optional)
sudo ufw status | grep "clownfischserver-homeip"
sudo ufw delete allow from [IP] to any port 22
```
## Was die myfritz-Adresse ist
**myfritz** ist ein DynDNS-Service der AVM (Fritz.Box Hersteller):
- `https://myfritz.net/`
- Deine Home-IP bekommst darin immer einen stabilen Hostnamen
- Auch wenn deine DSL-IP sich ändert, bleibt `vorname.myfritz.net` gleich
- ✅ Das Script prüft alle 5 Min und aktualisiert die UFW-Regel automatisch
## Sicherheit
- **UFW-Kommentar:** `clownfischserver-homeip-vorname.myfritz.net`
- Zeigt in `ufw status` an woher die Regel kommt
- **Logging:**
- `/var/log/clownfischserver-homeip.log` – vollständiger Audit-Trail
- Timestamp + alte IP + neue IP + Aktion
- **State-File:**
- `/var/lib/clownfischserver-homeip-state` – speichert die letzte bekannte IP
- Verhindert unnötige UFW-Updates bei gleicher IP
## Troubleshooting
### Cron-Job läuft nicht
```bash
# Status prüfen
sudo crontab -l | grep clownfischserver-homeip
# Logs prüfen
sudo tail -20 /var/log/clownfischserver-homeip.log
# Manuell testen
sudo /opt/clownfischserver/scripts/clownfischserver-homeip-updater.sh
```
### DNS-Auflösung schlägt fehl
```bash
# myfritz-Adresse testen
dig vorname.myfritz.net
# Oder mit nslookup
nslookup vorname.myfritz.net
# In .env prüfen
grep CLOWNFISCHSERVER_HOME_IP /opt/clownfischserver/config/.env
```
### UFW-Regel wird nicht hinzugefügt
```bash
# UFW Status prüfen
sudo ufw status
# Manuelle Regel hinzufügen (Debugging)
sudo ufw allow from 1.2.3.4 to any port 22 comment "clownfischserver-homeip-test"
# Logs prüfen
sudo journalctl -u ufw -n 20
```
## Technische Details – Firewall-Kommandos
### ufw (Ubuntu/Debian)
```bash
ufw allow from 192.168.1.100 to any port 22 comment "clownfischserver-homeip-vorname.myfritz.net"
ufw delete allow from 192.168.1.100 to any port 22
```
### firewalld (Fedora/openSUSE)
```bash
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' port protocol='tcp' port='22' accept"
firewall-cmd --reload
```
### iptables (Arch/Manjaro)
```bash
iptables -I INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT
iptables -D INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT
```
---
**Script-Info:** Clownfischserver v0.5.0+ | GPL-3.0 | Multi-Distro Support
-168
View File
@@ -1,168 +0,0 @@
#!/bin/bash
# =============================================================================
# 🐠 Clownfischserver HomeIP Updater
# Version: v0.5.0
# Purpose: Automatisch die Home-IP aktualisieren (alle 5 Min via Cron)
# Multi-Distro: ufw (Ubuntu/Debian), firewalld (Fedora/openSUSE), iptables (Arch)
# Author: Mehlzoerwer-Claude
# License: GPL-3.0
# =============================================================================
# Konfiguration
INSTALL_DIR="/opt/clownfischserver"
ENV_FILE="$INSTALL_DIR/config/.env"
STATE_FILE="/var/lib/clownfischserver-homeip-state"
LOG_FILE="/var/log/clownfischserver-homeip.log"
# Logging
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
}
log_error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >> "$LOG_FILE"
}
# Erkenne welche Firewall aktiv ist
detect_firewall() {
if systemctl is-active --quiet ufw 2>/dev/null; then
echo "ufw"
elif systemctl is-active --quiet firewalld 2>/dev/null; then
echo "firewalld"
elif command -v iptables &>/dev/null; then
echo "iptables"
else
echo "unknown"
fi
}
FIREWALL=$(detect_firewall)
log "Firewall erkannt: $FIREWALL"
# Prüfe ob .env existiert
if [[ ! -f "$ENV_FILE" ]]; then
log_error ".env nicht gefunden: $ENV_FILE"
exit 1
fi
# Erstelle Log-File wenn nicht existiert
touch "$LOG_FILE" 2>/dev/null || true
# Lade myfritz-Adresse aus .env (Zeilenumbrüche entfernen)
MYFRITZ_DOMAIN=$(grep "^CLOWNFISCHSERVER_HOME_IP_DOMAIN=" "$ENV_FILE" | cut -d= -f2 | tr -d '\r\n')
if [[ -z "$MYFRITZ_DOMAIN" ]]; then
log "Clownfischserver HomeIP: Deaktiviert (keine myfritz-Adresse)"
exit 0
fi
# Versuche IP aufzulösen (mit Fallback)
if command -v dig &>/dev/null; then
NEW_IP=$(dig +short "$MYFRITZ_DOMAIN" A 2>/dev/null | tail -1 | grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b')
elif command -v nslookup &>/dev/null; then
NEW_IP=$(nslookup "$MYFRITZ_DOMAIN" 2>/dev/null | grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' | tail -1)
elif command -v getent &>/dev/null; then
NEW_IP=$(getent hosts "$MYFRITZ_DOMAIN" 2>/dev/null | awk '{print $1}')
else
log_error "Kein DNS-Tool verfügbar (dig/nslookup/getent)"
exit 1
fi
if [[ -z "$NEW_IP" ]]; then
log_error "DNS-Auflösung fehlgeschlagen: $MYFRITZ_DOMAIN"
exit 1
fi
# Lese alte IP aus State-File
OLD_IP=""
if [[ -f "$STATE_FILE" ]]; then
OLD_IP=$(cat "$STATE_FILE")
fi
log "Domain: $MYFRITZ_DOMAIN | Neue IP: $NEW_IP | Alte IP: ${OLD_IP:-keine}"
# Wenn IP sich nicht geändert hat → nichts tun
if [[ "$NEW_IP" == "$OLD_IP" ]] && [[ -n "$OLD_IP" ]]; then
log "IP unverändert – keine Aktion nötig"
exit 0
fi
# IP hat sich geändert oder ist neue Installation
log "IP-Änderung erkannt! Aktualisiere Firewall-Regeln..."
# Firewall-spezifische Funktionen
remove_ufw_rule() {
if ufw status numbered | grep -qE "22.*ALLOW.*FROM\s+$1"; then
echo "y" | ufw delete allow from "$1" to any port 22 >> "$LOG_FILE" 2>&1
log "UFW: Alte Regel entfernt: allow from $1 to port 22"
fi
}
add_ufw_rule() {
ufw allow from "$1" to any port 22 comment "clownfischserver-homeip-$MYFRITZ_DOMAIN" >> "$LOG_FILE" 2>&1
log "UFW: Neue Regel hinzugefügt: allow from $1 to port 22"
}
remove_firewalld_rule() {
firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='$1' port protocol='tcp' port='22' accept" >> "$LOG_FILE" 2>&1
log "firewalld: Alte Regel entfernt: source address $1 port 22"
}
add_firewalld_rule() {
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='$1' port protocol='tcp' port='22' accept" >> "$LOG_FILE" 2>&1
firewall-cmd --reload >> "$LOG_FILE" 2>&1
log "firewalld: Neue Regel hinzugefügt: source address $1 port 22"
}
remove_iptables_rule() {
iptables -D INPUT -s "$1" -p tcp --dport 22 -j ACCEPT 2>> "$LOG_FILE" || true
log "iptables: Alte Regel entfernt: source $1 port 22"
}
add_iptables_rule() {
iptables -I INPUT -s "$1" -p tcp --dport 22 -j ACCEPT >> "$LOG_FILE" 2>&1
log "iptables: Neue Regel hinzugefügt: source $1 port 22"
}
# Entferne alte Regel falls vorhanden
if [[ -n "$OLD_IP" ]]; then
case "$FIREWALL" in
ufw) remove_ufw_rule "$OLD_IP" ;;
firewalld) remove_firewalld_rule "$OLD_IP" ;;
iptables) remove_iptables_rule "$OLD_IP" ;;
*) log_error "Unbekannte Firewall: $FIREWALL" && exit 1 ;;
esac
fi
# Füge neue Regel hinzu
case "$FIREWALL" in
ufw)
if ! add_ufw_rule "$NEW_IP"; then
log_error "UFW: Regel konnte nicht hinzugefügt werden"
exit 1
fi
;;
firewalld)
if ! add_firewalld_rule "$NEW_IP"; then
log_error "firewalld: Regel konnte nicht hinzugefügt werden"
exit 1
fi
;;
iptables)
if ! add_iptables_rule "$NEW_IP"; then
log_error "iptables: Regel konnte nicht hinzugefügt werden"
exit 1
fi
;;
*)
log_error "Unbekannte Firewall: $FIREWALL"
exit 1
;;
esac
# Speichere neue IP
echo "$NEW_IP" > "$STATE_FILE"
chmod 644 "$STATE_FILE"
log "✓ HomeIP Update erfolgreich: $MYFRITZ_DOMAIN → $NEW_IP ($FIREWALL)"
exit 0