Communitygithub.com

homelab-wireguard-vpn

Einrichtung eines WireGuard-VPN-Servers, Peer-Konfiguration, Schlüsselerzeugung, Split-Tunneling vs. Full-Tunnel-Routing und Fernzugriff auf ein Heimnetzwerk von Mobilgeräten und Laptops aus. Verwende dies, wenn du WireGuard für den Fernzugriff auf dein Heimnetzwerk einrichtest oder zwischen Split- und Full-Tunnel-Routing entscheiden musst.

Was ist homelab-wireguard-vpn?

Dieses Skill unterstützt Entwickler und Systemadministratoren bei der Einrichtung und Verwaltung eines WireGuard-VPN-Servers im Homelab. Es bietet eine vollständige Anleitung von der Serverinstallation auf Linux (z.B. Raspberry Pi) über die Generierung von Schlüsselpaaren bis hin zur Konfiguration mobiler Clients. Der Skill erklärt detailliert den Unterschied zwischen Split-Tunneling (nur Heimnetzverkehr) und Full-Tunnel (gesamter Verkehr über das Heimnetz) und enthält Python-Code zur Automatisierung der Peer-Konfiguration. Er behandelt auch die Integration mit pfSense/OPNsense, dynamische DNS-Updates und gängige Fehlerbehebung. Der Fokus liegt auf Sicherheit und Best Practices wie der Verwendung von bereichsspezifischen iptables-Regeln, individuellen Clientschlüsseln und der Speicherung von Secrets außerhalb von Versionskontrollsystemen. Besonders nützlich ist der WireGuard-Troubleshooting-Bereich, der häufige Verbindungsprobleme wie Firewall-Regeln, IP-Forwarding und falsche AllowedIPs behandelt.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/homelab-wireguard-vpn

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Homelab WireGuard VPN

WireGuard ist ein schnelles, modernes VPN-Protokoll. Es ist die richtige Wahl für den Fernzugriff auf ein Heimnetzwerk – einfacher zu konfigurieren als OpenVPN und schneller als die meisten Alternativen.

Alle Konfigurationsbeispiele zeigen gängige Einrichtungen. Überprüfe jeden Befehl – insbesondere die iptables-Weiterleitungsregeln und die Dateiberechtigungen für Schlüssel – bevor du sie auf deinem System anwendest, und führe Änderungen in einem Wartungsfenster durch.

Wann verwenden

  • Einrichten eines WireGuard-Servers auf einem Raspberry Pi, Linux-Host, pfSense oder Router
  • Generieren von WireGuard-Schlüsselpaaren und Schreiben von Peer-Konfigurationsdateien
  • Konfigurieren des Fernzugriffs von einem Telefon oder Laptop auf ein Heimnetzwerk
  • Erklären von Split-Tunneling (nur Heimverkehr routen) vs. Full-Tunnel (gesamten Verkehr routen)
  • Fehlerbehebung bei WireGuard-Verbindungen, die nicht aufgebaut werden
  • Automatisieren der Peer-Konfigurationsgenerierung für mehrere Clients

Wie WireGuard funktioniert

Dein Telefon (WireGuard-Client)
    │
    │  Verschlüsselter UDP-Tunnel (Port 51820)
    │
Dein Heimrouter (WireGuard-Server – benötigt eine öffentliche IP oder DDNS)
    │
    Dein Heimnetzwerk (192.168.1.0/24, NAS, Pi, etc.)

Jedes Gerät hat ein Schlüsselpaar (öffentlicher + privater Schlüssel).
Der Server kennt den öffentlichen Schlüssel jedes Clients.
Der Client kennt den öffentlichen Schlüssel des Servers + Endpunkt (IP:Port).
Der Datenverkehr wird Ende-zu-Ende verschlüsselt, ohne zentralen Server oder Zertifizierungsstelle.

Server-Einrichtung (Linux)

# WireGuard installieren
sudo apt update && sudo apt install wireguard -y

# Server-Schlüsselpaar generieren – Dateien von Anfang an mit privaten Berechtigungen erstellen
sudo mkdir -p /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server_private.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server_private.key > /etc/wireguard/server_public.key'

# Server-Konfiguration schreiben – den tatsächlichen privaten Schlüsselwert ersetzen
# Private Schlüssel nicht in Versionskontrolle speichern oder teilen
sudo tee /etc/wireguard/wg0.conf << 'EOF'
[Interface]
Address = 10.8.0.1/24              # VPN-Subnetz – Server bekommt .1
ListenPort = 51820
PrivateKey = <server_private_key_einfügen>

# Bereichsspezifische Weiterleitungsregeln: VPN-Verkehr rein/raus erlauben, kein pauschales FORWARD ACCEPT
PostUp   = iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
PostUp   = iptables -A FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostUp   = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# Telefon – durch den tatsächlichen öffentlichen Schlüssel des Telefons ersetzen
PublicKey = <telefon_public_key>
AllowedIPs = 10.8.0.2/32

[Peer]
# Laptop – durch den tatsächlichen öffentlichen Schlüssel des Laptops ersetzen
PublicKey = <laptop_public_key>
AllowedIPs = 10.8.0.3/32
EOF
sudo chmod 600 /etc/wireguard/wg0.conf

# Ersetze eth0 durch den tatsächlichen Namen der ausgehenden Schnittstelle
# Überprüfen mit: ip route show default

# IP-Weiterleitung aktivieren (erforderlich für das Routen von Verkehr durch den Server)
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

# WireGuard starten und beim Booten aktivieren
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

Client-Konfiguration

# Ein eindeutiges Schlüsselpaar für jedes Client-Gerät generieren
# Auf dem Client oder dem Server ausführen und den privaten Schlüssel sicher übertragen – niemals im Klartext
umask 077
wg genkey | tee phone_private.key | wg pubkey > phone_public.key

# Client-Konfigurationsdatei (phone_wg0.conf):
[Interface]
PrivateKey = <telefon_private_key>
Address = 10.8.0.2/32
DNS = 192.168.1.2                  # Optional: Pi-hole für DNS über den Tunnel verwenden

[Peer]
PublicKey = <server_public_key>
Endpoint = your-home-ip.ddns.net:51820  # Deine öffentliche IP oder DDNS-Hostname
AllowedIPs = 192.168.1.0/24            # Split-Tunnel: nur Heimnetzverkehr
# AllowedIPs = 0.0.0.0/0, ::/0        # Full-Tunnel: gesamter Verkehr über VPN

PersistentKeepalive = 25              # NAT-Loch offen halten (erforderlich für mobile Clients)

Split-Tunnel vs. Full-Tunnel

# Split-Tunnel: AllowedIPs = 192.168.1.0/24
  Nur Verkehr, der für dein Heimnetzwerk bestimmt ist, geht durch das VPN.
  Internetverkehr (YouTube, Spotify) geht direkt – bessere Leistung auf Mobilgeräten.
  Am besten für: "Ich möchte einfach von überall auf mein NAS und Pi zugreifen."

# Full-Tunnel: AllowedIPs = 0.0.0.0/0, ::/0
  Der GESAMTE Verkehr geht über deine Heim-Internetverbindung.
  Nützlich für: Nutzung des heimischen DNS/Pi-hole-Werbeblockers.
  Nachteil: Die Upload-Geschwindigkeit zu Hause wird überall zum Engpass.

# Multi-Subnetz-Split-Tunnel (häufigster Homelab-Anwendungsfall):
  AllowedIPs = 192.168.10.0/24, 192.168.20.0/24, 192.168.30.0/24, 10.8.0.0/24
  Leitet alle deine VLANs durch den Tunnel; Internet bleibt direkt.

Schlüsselerzeugung und Peer-Verwaltung

import subprocess

def generate_keypair() -> tuple[str, str]:
    """Generiert ein WireGuard-Schlüsselpaar. Gibt (privater_schlüssel, öffentlicher_schlüssel) zurück."""
    private = subprocess.check_output(["wg", "genkey"]).decode().strip()
    public = subprocess.run(
        ["wg", "pubkey"], input=private.encode(), capture_output=True
    ).stdout.decode().strip()
    return private, public

def generate_preshared_key() -> str:
    return subprocess.check_output(["wg", "genpsk"]).decode().strip()

def build_client_config(
    client_private_key: str,
    client_vpn_ip: str,       # z. B. "10.8.0.3"
    server_public_key: str,
    server_endpoint: str,     # z. B. "home.example.com:51820"
    allowed_ips: str = "192.168.1.0/24",
    dns: str = "",
) -> str:
    dns_line = f"DNS = {dns}\n" if dns else ""
    return f"""[Interface]
PrivateKey = {client_private_key}
Address = {client_vpn_ip}/32
{dns_line}
[Peer]
PublicKey = {server_public_key}
Endpoint = {server_endpoint}
AllowedIPs = {allowed_ips}
PersistentKeepalive = 25
"""

def build_server_peer_block(
    client_public_key: str,
    client_vpn_ip: str,
    comment: str = "",
) -> str:
    comment_line = f"# {comment}\n" if comment else ""
    return f"""
{comment_line}[Peer]
PublicKey = {client_public_key}
AllowedIPs = {client_vpn_ip}/32
"""

Halte private Schlüssel außerhalb der Versionskontrolle. Wenn du dieses Skript verwendest, schreibe Schlüsselmaterial in Dateien mit Modus 600 und protokolliere oder drucke es niemals.

pfSense / OPNsense WireGuard

# pfSense: VPN → WireGuard → Tunnel hinzufügen
  Interface-Keys: Generieren (erzeugt automatisch ein Schlüsselpaar)
  Listen-Port: 51820
  Interface-Adresse: 10.8.0.1/24

# Peer hinzufügen (einer pro Client):
  Public Key: <client_public_key>
  Allowed IPs: 10.8.0.2/32

# WireGuard-Schnittstelle zuweisen:
  Interfaces → Assignments → Hinzufügen (wg0 auswählen)
  Schnittstelle aktivieren, keine IP benötigt (wird in der Tunnel-Konfiguration gesetzt)

# Firewall-Regeln:
  WAN → UDP-Port 51820 eingehend erlauben (damit Clients den Server erreichen können)
  WireGuard-Schnittstelle → Verkehr zu LAN-Netzwerken erlauben, die erreichbar sein sollen

DDNS (Dynamic DNS) für Heimserver

Die meisten Heim-Internetverbindungen haben eine dynamische IP. Verwende DDNS, damit dein VPN-Endpunkt auch nach einem IP-Wechsel erreichbar bleibt.

# Option 1: Cloudflare DDNS – Anmeldedaten in einer Secrets-Datei speichern, nicht inline
# docker-compose-Eintrag mit einer Env-Datei:
  ddns-updater:
    image: qmcgaw/ddns-updater
    env_file: ./ddns.env   # Zone-ID und Token hier speichern, nicht in compose
    restart: unless-stopped

# ddns.env (chmod 600, nicht in Git einchecken):
# SETTINGS_CLOUDFLARE_ZONE_ID=deine_zone_id
# SETTINGS_CLOUDFLARE_TOKEN=dein_api_token

# Option 2: DuckDNS (kostenlos, einfach)
  Registrieren auf duckdns.org → Token und Subdomain erhalten (myhome.duckdns.org)
  Token in /etc/ddns.env (Modus 600) speichern, dann ein kleines, root-eigenes Skript verwenden:

  # /usr/local/bin/update-duckdns
  #!/bin/sh
  set -eu
  . /etc/ddns.env
  curl --fail --silent --show-error --max-time 10 \
    --get "https://www.duckdns.org/update" \
    --data-urlencode "domains=myhome" \
    --data-urlencode "token=${DUCKDNS_TOKEN}" \
    --data-urlencode "ip="

  # Cron-Job:
  */5 * * * * /usr/local/bin/update-duckdns >/dev/null 2>&1

Fehlerbehebung

# WireGuard-Status und letzten Handshake überprüfen
sudo wg show

# Wenn "latest handshake" nie oder sehr alt ist, ist der Tunnel nicht verbunden.
# Überprüfe:
# 1. Ist UDP-Port 51820 auf dem Router/der Firewall geöffnet?
sudo ufw status  # oder pfSense/UniFi-Firewall-Regeln überprüfen

# 2. Ist der öffentliche Schlüssel des Servers in der Client-Konfiguration korrekt?
sudo wg show wg0 public-key   # Mit dem in der Client-Konfiguration vergleichen

# 3. Ist IP-Weiterleitung auf dem Server aktiviert?
cat /proc/sys/net/ipv4/ip_forward  # Sollte 1 sein

# 4. Deckt die Client-AllowedIPs die IP ab, die du erreichen willst?
# Wenn AllowedIPs = 192.168.1.0/24 und du versuchst, 192.168.3.5 zu erreichen, wird es nicht routen.

# Kernel-Logs auf WireGuard-Fehler überprüfen
dmesg | grep wireguard

# WireGuard neu starten
sudo wg-quick down wg0 && sudo wg-quick up wg0

Anti-Patterns

# SCHLECHT: Private Schlüssel in Versionskontrolle speichern oder teilen
# Private Schlüssel sind gleichwertig zu Passwörtern – niemals in Git einchecken

# SCHLECHT: AllowedIPs = 0.0.0.0/0 auf Mobilgeräten ohne Berücksichtigung der Auswirkungen
# Full-Tunnel leitet den gesamten mobilen Datenverkehr über deinen Heim-Upload – normalerweise langsam

# SCHLECHT: PersistentKeepalive auf mobilen Clients nicht setzen
# Mobile Clients hinter NAT lassen inaktive Tunnel ohne Keepalive abbrechen

# SCHLECHT: Port 51820 in der Firewall öffnen, aber IP-Weiterleitung auf dem Server vergessen
# Tunnel verbindet, aber kein Verkehr wird geroutet – verwirrend zu debuggen

# SCHLECHT: Ein Schlüsselpaar für mehrere Client-Geräte teilen
# Jedes Gerät muss sein eigenes eindeutiges Schlüsselpaar haben – geteilte Schlüssel brechen das Sicherheitsmodell

# SCHLECHT: Eine breite "FORWARD ACCEPT"-iptables-Regel verwenden
# Weiterleitungsregeln auf die wg0-Schnittstelle und -Richtung beschränken

Best Practices

  • Generiere ein eindeutiges Schlüsselpaar pro Client-Gerät – verwende Schlüssel niemals wieder
  • Verwende Split-Tunneling (AllowedIPs = <heim-subnetze>) für Mobilgeräte
  • Setze PersistentKeepalive = 25 auf allen mobilen Clients
  • Verwende DDNS, wenn dein ISP eine dynamische IP vergibt; speichere Anmeldedaten in Env-Dateien, nicht inline
  • Verwende bereichsspezifische iptables-Weiterleitungsregeln (nur eingehend auf wg0) anstelle eines pauschalen FORWARD ACCEPT
  • Füge die IP des Pi-hole als DNS = in den Client-Konfigurationen hinzu, um Werbeblockierung über das VPN zu erhalten
  • Rotiere das Server-Schlüsselpaar regelmäßig und aktualisiere alle Client-Konfigurationen

Verwandte Skills

  • homelab-network-setup
  • homelab-vlan-segmentation
  • homelab-pihole-dns

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Verwandte Skills