refactor(deployment): Remove WireGuard VPN dependency and restore public service access

Remove WireGuard integration from production deployment to simplify infrastructure:
- Remove docker-compose-direct-access.yml (VPN-bound services)
- Remove VPN-only middlewares from Grafana, Prometheus, Portainer
- Remove WireGuard middleware definitions from Traefik
- Remove WireGuard IPs (10.8.0.0/24) from Traefik forwarded headers

All monitoring services now publicly accessible via subdomains:
- grafana.michaelschiemer.de (with Grafana native auth)
- prometheus.michaelschiemer.de (with Basic Auth)
- portainer.michaelschiemer.de (with Portainer native auth)

All services use Let's Encrypt SSL certificates via Traefik.
This commit is contained in:
2025-11-05 12:48:25 +01:00
parent 7c52065aae
commit 95147ff23e
215 changed files with 29490 additions and 368 deletions

View File

@@ -179,6 +179,141 @@ sudo ufw allow 51820/udp comment 'WireGuard VPN'
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
```
## Split-Tunnel Routing & NAT Fix
### A. Quick Fix Commands (manuell auf dem Server)
```bash
WAN_IF=${WAN_IF:-eth0}
WG_IF=${WG_IF:-wg0}
WG_NET=${WG_NET:-10.8.0.0/24}
WG_PORT=${WG_PORT:-51820}
EXTRA_NETS=${EXTRA_NETS:-"192.168.178.0/24 172.20.0.0/16"}
sudo sysctl -w net.ipv4.ip_forward=1
sudo tee /etc/sysctl.d/99-${WG_IF}-forward.conf >/dev/null <<'EOF'
# WireGuard Forwarding
net.ipv4.ip_forward=1
EOF
sudo sysctl --system
# iptables Variante
sudo iptables -t nat -C POSTROUTING -s ${WG_NET} -o ${WAN_IF} -j MASQUERADE 2>/dev/null \
|| sudo iptables -t nat -A POSTROUTING -s ${WG_NET} -o ${WAN_IF} -j MASQUERADE
sudo iptables -C FORWARD -i ${WG_IF} -s ${WG_NET} -o ${WAN_IF} -j ACCEPT 2>/dev/null \
|| sudo iptables -A FORWARD -i ${WG_IF} -s ${WG_NET} -o ${WAN_IF} -j ACCEPT
sudo iptables -C FORWARD -o ${WG_IF} -d ${WG_NET} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null \
|| sudo iptables -A FORWARD -o ${WG_IF} -d ${WG_NET} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
for NET in ${EXTRA_NETS}; do
sudo iptables -C FORWARD -i ${WG_IF} -d ${NET} -j ACCEPT 2>/dev/null || sudo iptables -A FORWARD -i ${WG_IF} -d ${NET} -j ACCEPT
done
# nftables Variante
sudo nft list table inet wireguard_${WG_IF} >/dev/null 2>&1 || sudo nft add table inet wireguard_${WG_IF}
sudo nft list chain inet wireguard_${WG_IF} postrouting >/dev/null 2>&1 \
|| sudo nft add chain inet wireguard_${WG_IF} postrouting '{ type nat hook postrouting priority srcnat; }'
sudo nft list chain inet wireguard_${WG_IF} forward >/dev/null 2>&1 \
|| sudo nft add chain inet wireguard_${WG_IF} forward '{ type filter hook forward priority filter; policy accept; }'
sudo nft list chain inet wireguard_${WG_IF} postrouting | grep -q "${WAN_IF}" \
|| sudo nft add rule inet wireguard_${WG_IF} postrouting oifname "${WAN_IF}" ip saddr ${WG_NET} masquerade
sudo nft list chain inet wireguard_${WG_IF} forward | grep -q "iifname \"${WG_IF}\"" \
|| sudo nft add rule inet wireguard_${WG_IF} forward iifname "${WG_IF}" ip saddr ${WG_NET} counter accept
sudo nft list chain inet wireguard_${WG_IF} forward | grep -q "oifname \"${WG_IF}\"" \
|| sudo nft add rule inet wireguard_${WG_IF} forward oifname "${WG_IF}" ip daddr ${WG_NET} ct state established,related counter accept
for NET in ${EXTRA_NETS}; do
sudo nft list chain inet wireguard_${WG_IF} forward | grep -q "${NET}" \
|| sudo nft add rule inet wireguard_${WG_IF} forward iifname "${WG_IF}" ip daddr ${NET} counter accept
done
# Firewall Hooks
if command -v ufw >/dev/null && sudo ufw status | grep -iq "Status: active"; then
sudo sed -i 's/^DEFAULT_FORWARD_POLICY=.*/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
sudo ufw allow ${WG_PORT}/udp
sudo ufw route allow in on ${WG_IF} out on ${WAN_IF} to any
fi
if command -v firewall-cmd >/dev/null && sudo firewall-cmd --state >/dev/null 2>&1; then
sudo firewall-cmd --permanent --zone=${FIREWALLD_ZONE:-public} --add-port=${WG_PORT}/udp
sudo firewall-cmd --permanent --zone=${FIREWALLD_ZONE:-public} --add-masquerade
sudo firewall-cmd --reload
fi
sudo systemctl enable --now wg-quick@${WG_IF}
sudo wg show
```
### B. Skript: `deployment/ansible/scripts/setup-wireguard-routing.sh`
```bash
cd deployment/ansible
sudo WAN_IF=eth0 WG_IF=wg0 WG_NET=10.8.0.0/24 EXTRA_NETS="192.168.178.0/24 172.20.0.0/16" \
./scripts/setup-wireguard-routing.sh
```
*Erkennt automatisch iptables/nftables und konfiguriert optional UFW/Firewalld.*
### C. Ansible Playbook: `playbooks/wireguard-routing.yml`
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml playbooks/wireguard-routing.yml \
-e "wg_interface=wg0 wg_addr=10.8.0.1/24 wg_net=10.8.0.0/24 wan_interface=eth0" \
-e '{"extra_nets":["192.168.178.0/24","172.20.0.0/16"],"firewall_backend":"iptables","manage_ufw":true}'
```
*Variablen:* `wg_interface`, `wg_addr`, `wg_net`, `wan_interface`, `extra_nets`, `firewall_backend` (`iptables|nftables`), `manage_ufw`, `manage_firewalld`, `firewalld_zone`.
### D. Beispiel `wg0.conf` Ausschnitt
```ini
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <ServerPrivateKey>
# iptables
PostUp = iptables -t nat -C POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
PostUp = iptables -C FORWARD -i wg0 -s 10.8.0.0/24 -j ACCEPT 2>/dev/null || iptables -A FORWARD -i wg0 -s 10.8.0.0/24 -j ACCEPT
PostUp = iptables -C FORWARD -o wg0 -d 10.8.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || iptables -A FORWARD -o wg0 -d 10.8.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || true
PostDown = iptables -D FORWARD -i wg0 -s 10.8.0.0/24 -j ACCEPT 2>/dev/null || true
PostDown = iptables -D FORWARD -o wg0 -d 10.8.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true
# nftables (stattdessen)
# PostUp = nft -f /etc/nftables.d/wireguard-wg0.nft
# PostDown = nft delete table inet wireguard_wg0 2>/dev/null || true
[Peer]
PublicKey = <ClientPublicKey>
AllowedIPs = 10.8.0.5/32, 192.168.178.0/24, 172.20.0.0/16
PersistentKeepalive = 25
```
### E. Windows Client (AllowedIPs & Tests)
```ini
[Interface]
Address = 10.8.0.5/32
DNS = 10.8.0.1 # optional
[Peer]
PublicKey = <ServerPublicKey>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.178.0/24, 172.20.0.0/16
PersistentKeepalive = 25
```
PowerShell:
```powershell
wg show
Test-Connection -Source 10.8.0.5 -ComputerName 10.8.0.1
Test-Connection 192.168.178.1
Test-NetConnection -ComputerName 192.168.178.10 -Port 22
```
Optional: `Set-DnsClientNrptRule -Namespace "internal.lan" -NameServers 10.8.0.1`.
### F. Troubleshooting & Rollback
- Checks: `ip r`, `ip route get <target>`, `iptables -t nat -S`, `nft list ruleset`, `sysctl net.ipv4.ip_forward`, `wg show`, `tcpdump -i wg0`, `tcpdump -i eth0 host 10.8.0.5`.
- Häufige Fehler: falsches WAN-Interface, Forwarding/NAT fehlt, doppelte Firewalls (iptables + nftables), Docker-NAT kollidiert, Policy-Routing aktiv.
- Rollback:
- `sudo rm /etc/sysctl.d/99-wg0-forward.conf && sudo sysctl -w net.ipv4.ip_forward=0`
- iptables: Regeln mit `iptables -D` entfernen (siehe oben).
- nftables: `sudo nft delete table inet wireguard_wg0`.
- UFW: `sudo ufw delete allow 51820/udp`, Route-Regeln entfernen, `DEFAULT_FORWARD_POLICY` zurücksetzen.
- Firewalld: `firewall-cmd --permanent --remove-port=51820/udp`, `--remove-masquerade`, `--reload`.
- Dienst: `sudo systemctl disable --now wg-quick@wg0`.
## Troubleshooting
### WireGuard startet nicht
@@ -281,4 +416,4 @@ Bei Problemen:
1. Prüfe Logs: `sudo journalctl -u wg-quick@wg0`
2. Prüfe Status: `sudo wg show`
3. Prüfe Firewall: `sudo ufw status`
4. Teste Connectivity: `ping 10.8.0.1` (vom Client)
4. Teste Connectivity: `ping 10.8.0.1` (vom Client)

View File

@@ -0,0 +1,229 @@
---
# WireGuard Client Configuration Generator
# Usage: ansible-playbook playbooks/generate-wireguard-client.yml -e "client_name=michael-laptop"
- name: Generate WireGuard Client Configuration
hosts: server
become: true
gather_facts: true
vars:
# Default values (can be overridden with -e)
wireguard_config_dir: "/etc/wireguard"
wireguard_interface: "wg0"
wireguard_server_endpoint: "{{ ansible_default_ipv4.address }}"
wireguard_server_port: 51820
wireguard_vpn_network: "10.8.0.0/24"
wireguard_server_ip: "10.8.0.1"
# Client output directory (local)
client_config_dir: "{{ playbook_dir }}/../wireguard/configs"
# Required variable (must be passed via -e)
# client_name: "device-name"
tasks:
- name: Validate client_name is provided
assert:
that:
- client_name is defined
- client_name | length > 0
fail_msg: "ERROR: client_name must be provided via -e client_name=<name>"
success_msg: "Generating config for client: {{ client_name }}"
- name: Validate client_name format (alphanumeric and hyphens only)
assert:
that:
- client_name is match('^[a-zA-Z0-9-]+$')
fail_msg: "ERROR: client_name must contain only letters, numbers, and hyphens"
success_msg: "Client name format is valid"
- name: Check if WireGuard server is configured
stat:
path: "{{ wireguard_config_dir }}/{{ wireguard_interface }}.conf"
register: server_config
- name: Fail if server config doesn't exist
fail:
msg: "WireGuard server config not found. Run setup-wireguard-host.yml first."
when: not server_config.stat.exists
- name: Read server public key
slurp:
src: "{{ wireguard_config_dir }}/server_public.key"
register: server_public_key_raw
- name: Set server public key fact
set_fact:
server_public_key: "{{ server_public_key_raw.content | b64decode | trim }}"
- name: Get next available IP address
shell: |
# Parse existing peer IPs from wg0.conf
existing_ips=$(grep -oP 'AllowedIPs\s*=\s*\K[0-9.]+' {{ wireguard_config_dir }}/{{ wireguard_interface }}.conf 2>/dev/null || echo "")
# Start from .2 (server is .1)
i=2
while [ $i -le 254 ]; do
ip="10.8.0.$i"
if ! echo "$existing_ips" | grep -q "^$ip$"; then
echo "$ip"
exit 0
fi
i=$((i + 1))
done
echo "ERROR: No free IP addresses" >&2
exit 1
register: next_ip_result
changed_when: false
- name: Set client IP fact
set_fact:
client_ip: "{{ next_ip_result.stdout | trim }}"
- name: Display client IP assignment
debug:
msg: "Assigned IP for {{ client_name }}: {{ client_ip }}"
- name: Check if client already exists
shell: |
grep -q "# Client: {{ client_name }}" {{ wireguard_config_dir }}/{{ wireguard_interface }}.conf
register: client_exists
changed_when: false
failed_when: false
- name: Warn if client already exists
debug:
msg: "WARNING: Client '{{ client_name }}' already exists in server config. Creating new keys anyway."
when: client_exists.rc == 0
- name: Generate client private key
shell: wg genkey
register: client_private_key_result
changed_when: true
no_log: true
- name: Generate client public key
shell: echo "{{ client_private_key_result.stdout }}" | wg pubkey
register: client_public_key_result
changed_when: false
no_log: true
- name: Generate preshared key
shell: wg genpsk
register: preshared_key_result
changed_when: true
no_log: true
- name: Set client key facts
set_fact:
client_private_key: "{{ client_private_key_result.stdout | trim }}"
client_public_key: "{{ client_public_key_result.stdout | trim }}"
preshared_key: "{{ preshared_key_result.stdout | trim }}"
no_log: true
- name: Create client config directory on control node
delegate_to: localhost
file:
path: "{{ client_config_dir }}"
state: directory
mode: '0755'
become: false
- name: Generate client WireGuard configuration
delegate_to: localhost
copy:
content: |
[Interface]
# Client: {{ client_name }}
# Generated: {{ ansible_date_time.iso8601 }}
PrivateKey = {{ client_private_key }}
Address = {{ client_ip }}/32
DNS = 1.1.1.1, 8.8.8.8
[Peer]
# WireGuard Server
PublicKey = {{ server_public_key }}
PresharedKey = {{ preshared_key }}
Endpoint = {{ wireguard_server_endpoint }}:{{ wireguard_server_port }}
AllowedIPs = {{ wireguard_vpn_network }}
PersistentKeepalive = 25
dest: "{{ client_config_dir }}/{{ client_name }}.conf"
mode: '0600'
become: false
no_log: true
- name: Add client peer to server configuration
blockinfile:
path: "{{ wireguard_config_dir }}/{{ wireguard_interface }}.conf"
marker: "# {mark} ANSIBLE MANAGED BLOCK - Client: {{ client_name }}"
block: |
[Peer]
# Client: {{ client_name }}
PublicKey = {{ client_public_key }}
PresharedKey = {{ preshared_key }}
AllowedIPs = {{ client_ip }}/32
no_log: true
- name: Reload WireGuard configuration
shell: wg syncconf {{ wireguard_interface }} <(wg-quick strip {{ wireguard_interface }})
args:
executable: /bin/bash
- name: Generate QR code (ASCII)
delegate_to: localhost
shell: |
qrencode -t ansiutf8 < {{ client_config_dir }}/{{ client_name }}.conf > {{ client_config_dir }}/{{ client_name }}.qr.txt
become: false
changed_when: true
- name: Generate QR code (PNG)
delegate_to: localhost
shell: |
qrencode -t png -o {{ client_config_dir }}/{{ client_name }}.qr.png < {{ client_config_dir }}/{{ client_name }}.conf
become: false
changed_when: true
- name: Display QR code for mobile devices
delegate_to: localhost
shell: cat {{ client_config_dir }}/{{ client_name }}.qr.txt
register: qr_code_output
become: false
changed_when: false
- name: Client configuration summary
debug:
msg:
- "========================================="
- "WireGuard Client Configuration Created!"
- "========================================="
- ""
- "Client: {{ client_name }}"
- "IP Address: {{ client_ip }}/32"
- "Public Key: {{ client_public_key }}"
- ""
- "Configuration Files:"
- " Config: {{ client_config_dir }}/{{ client_name }}.conf"
- " QR Code (ASCII): {{ client_config_dir }}/{{ client_name }}.qr.txt"
- " QR Code (PNG): {{ client_config_dir }}/{{ client_name }}.qr.png"
- ""
- "Server Configuration:"
- " Endpoint: {{ wireguard_server_endpoint }}:{{ wireguard_server_port }}"
- " Allowed IPs: {{ wireguard_vpn_network }}"
- ""
- "Next Steps:"
- " Linux/macOS: sudo cp {{ client_config_dir }}/{{ client_name }}.conf /etc/wireguard/ && sudo wg-quick up {{ client_name }}"
- " Windows: Import {{ client_name }}.conf in WireGuard GUI"
- " iOS/Android: Scan QR code with WireGuard app"
- ""
- "Test Connection:"
- " ping {{ wireguard_server_ip }}"
- " curl -k https://{{ wireguard_server_ip }}:8080 # Traefik Dashboard"
- ""
- "========================================="
- name: Display QR code
debug:
msg: "{{ qr_code_output.stdout_lines }}"

View File

@@ -0,0 +1,309 @@
---
# Ansible Playbook: WireGuard Host-based VPN Setup
# Purpose: Deploy minimalistic WireGuard VPN for admin access
# Architecture: Host-based (systemd), no Docker, no DNS
- name: Setup WireGuard VPN (Host-based)
hosts: all
become: yes
vars:
# WireGuard Configuration
wg_interface: wg0
wg_network: 10.8.0.0/24
wg_server_ip: 10.8.0.1
wg_netmask: 24
wg_port: 51820
# Network Configuration
wan_interface: eth0 # Change to your WAN interface (eth0, ens3, etc.)
# Admin Service Ports (VPN-only access)
admin_service_ports:
- 8080 # Traefik Dashboard
- 9090 # Prometheus
- 3001 # Grafana
- 9000 # Portainer
- 8001 # Redis Insight
# Public Service Ports
public_service_ports:
- 80 # HTTP
- 443 # HTTPS
- 22 # SSH
# Rate Limiting
wg_enable_rate_limit: true
# Paths
wg_config_dir: /etc/wireguard
wg_backup_dir: /root/wireguard-backup
nft_config_file: /etc/nftables.d/wireguard.nft
tasks:
# ========================================
# 1. Pre-flight Checks
# ========================================
- name: Check if running as root
assert:
that: ansible_user_id == 'root'
fail_msg: "This playbook must be run as root"
- name: Detect WAN interface
shell: ip route | grep default | awk '{print $5}' | head -n1
register: detected_wan_interface
changed_when: false
- name: Set WAN interface if not specified
set_fact:
wan_interface: "{{ detected_wan_interface.stdout }}"
when: wan_interface == 'eth0' and detected_wan_interface.stdout != ''
- name: Display detected network configuration
debug:
msg:
- "WAN Interface: {{ wan_interface }}"
- "VPN Network: {{ wg_network }}"
- "VPN Server IP: {{ wg_server_ip }}"
# ========================================
# 2. Backup Existing Configuration
# ========================================
- name: Create backup directory
file:
path: "{{ wg_backup_dir }}"
state: directory
mode: '0700'
- name: Backup existing WireGuard config (if exists)
shell: |
if [ -d {{ wg_config_dir }} ]; then
tar -czf {{ wg_backup_dir }}/wireguard-backup-$(date +%Y%m%d-%H%M%S).tar.gz {{ wg_config_dir }}
echo "Backup created"
else
echo "No existing config"
fi
register: backup_result
changed_when: "'Backup created' in backup_result.stdout"
# ========================================
# 3. Install WireGuard
# ========================================
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
when: ansible_os_family == 'Debian'
- name: Install WireGuard and dependencies
apt:
name:
- wireguard
- wireguard-tools
- qrencode # For QR code generation
- nftables
state: present
when: ansible_os_family == 'Debian'
- name: Ensure WireGuard kernel module is loaded
modprobe:
name: wireguard
state: present
- name: Verify WireGuard module is available
shell: lsmod | grep -q wireguard
register: wg_module_check
failed_when: wg_module_check.rc != 0
changed_when: false
# ========================================
# 4. Generate Server Keys (if not exist)
# ========================================
- name: Create WireGuard config directory
file:
path: "{{ wg_config_dir }}"
state: directory
mode: '0700'
- name: Check if server private key exists
stat:
path: "{{ wg_config_dir }}/server_private.key"
register: server_private_key_stat
- name: Generate server private key
shell: wg genkey > {{ wg_config_dir }}/server_private.key
when: not server_private_key_stat.stat.exists
- name: Set server private key permissions
file:
path: "{{ wg_config_dir }}/server_private.key"
mode: '0600'
- name: Generate server public key
shell: cat {{ wg_config_dir }}/server_private.key | wg pubkey > {{ wg_config_dir }}/server_public.key
when: not server_private_key_stat.stat.exists
- name: Read server private key
slurp:
src: "{{ wg_config_dir }}/server_private.key"
register: server_private_key_content
- name: Read server public key
slurp:
src: "{{ wg_config_dir }}/server_public.key"
register: server_public_key_content
- name: Set server key facts
set_fact:
wg_server_private_key: "{{ server_private_key_content.content | b64decode | trim }}"
wg_server_public_key: "{{ server_public_key_content.content | b64decode | trim }}"
- name: Display server public key
debug:
msg: "Server Public Key: {{ wg_server_public_key }}"
# ========================================
# 5. Configure WireGuard
# ========================================
- name: Deploy WireGuard server configuration
template:
src: ../templates/wg0.conf.j2
dest: "{{ wg_config_dir }}/wg0.conf"
mode: '0600'
notify: restart wireguard
- name: Enable IP forwarding
sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: yes
state: present
reload: yes
# ========================================
# 6. Configure nftables Firewall
# ========================================
- name: Create nftables config directory
file:
path: /etc/nftables.d
state: directory
mode: '0755'
- name: Deploy WireGuard firewall rules
template:
src: ../templates/wireguard-host-firewall.nft.j2
dest: "{{ nft_config_file }}"
mode: '0644'
notify: reload nftables
- name: Include WireGuard rules in main nftables config
lineinfile:
path: /etc/nftables.conf
line: 'include "{{ nft_config_file }}"'
create: yes
state: present
notify: reload nftables
- name: Enable nftables service
systemd:
name: nftables
enabled: yes
state: started
# ========================================
# 7. Enable and Start WireGuard
# ========================================
- name: Enable WireGuard interface
systemd:
name: wg-quick@wg0
enabled: yes
state: started
- name: Verify WireGuard is running
command: wg show wg0
register: wg_status
changed_when: false
- name: Display WireGuard status
debug:
msg: "{{ wg_status.stdout_lines }}"
# ========================================
# 8. Health Checks
# ========================================
- name: Check WireGuard interface exists
command: ip link show wg0
register: wg_interface_check
failed_when: wg_interface_check.rc != 0
changed_when: false
- name: Check firewall rules applied
command: nft list ruleset
register: nft_rules
failed_when: "'wireguard_firewall' not in nft_rules.stdout"
changed_when: false
- name: Verify admin ports are blocked from public
shell: nft list chain inet wireguard_firewall input | grep -q "admin_service_ports.*drop"
register: admin_port_block_check
failed_when: admin_port_block_check.rc != 0
changed_when: false
# ========================================
# 9. Post-Installation Summary
# ========================================
- name: Create post-installation summary
debug:
msg:
- "========================================="
- "WireGuard VPN Setup Complete!"
- "========================================="
- ""
- "Server Configuration:"
- " Interface: wg0"
- " Server IP: {{ wg_server_ip }}/{{ wg_netmask }}"
- " Listen Port: {{ wg_port }}"
- " Public Key: {{ wg_server_public_key }}"
- ""
- "Network Configuration:"
- " VPN Network: {{ wg_network }}"
- " WAN Interface: {{ wan_interface }}"
- ""
- "Admin Service Access (VPN-only):"
- " Traefik Dashboard: https://{{ wg_server_ip }}:8080"
- " Prometheus: http://{{ wg_server_ip }}:9090"
- " Grafana: https://{{ wg_server_ip }}:3001"
- " Portainer: http://{{ wg_server_ip }}:9000"
- " Redis Insight: http://{{ wg_server_ip }}:8001"
- ""
- "Next Steps:"
- " 1. Generate client config: ./scripts/generate-client-config.sh <device-name>"
- " 2. Import config on client device"
- " 3. Connect and verify access"
- ""
- "Firewall Status: ACTIVE (nftables)"
- " - Public ports: 80, 443, 22"
- " - VPN port: {{ wg_port }}"
- " - Admin services: VPN-only access"
- ""
- "========================================="
handlers:
- name: restart wireguard
systemd:
name: wg-quick@wg0
state: restarted
- name: reload nftables
systemd:
name: nftables
state: reloaded

View File

@@ -0,0 +1,212 @@
---
- name: Configure WireGuard split tunnel routing
hosts: production
become: true
gather_facts: true
vars:
wg_interface: wg0
wg_addr: 10.8.0.1/24
wg_net: 10.8.0.0/24
wan_interface: eth0
listening_port: 51820
extra_nets:
- 192.168.178.0/24
- 172.20.0.0/16
firewall_backend: iptables # or nftables
manage_ufw: false
manage_firewalld: false
firewalld_zone: public
pre_tasks:
- name: Ensure required collections are installed (documentation note)
debug:
msg: >
Install collections if missing:
ansible-galaxy collection install ansible.posix community.general
when: false
tasks:
- name: Ensure WireGuard config directory exists
ansible.builtin.file:
path: "/etc/wireguard"
state: directory
mode: "0700"
owner: root
group: root
- name: Persist IPv4 forwarding
ansible.builtin.copy:
dest: "/etc/sysctl.d/99-{{ wg_interface }}-forward.conf"
owner: root
group: root
mode: "0644"
content: |
# Managed by Ansible - WireGuard {{ wg_interface }}
net.ipv4.ip_forward=1
- name: Enable IPv4 forwarding runtime
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: "1"
state: present
reload: true
- name: Configure MASQUERADE (iptables)
community.general.iptables:
table: nat
chain: POSTROUTING
out_interface: "{{ wan_interface }}"
source: "{{ wg_net }}"
jump: MASQUERADE
state: present
when: firewall_backend == "iptables"
- name: Allow forwarding wg -> wan (iptables)
community.general.iptables:
table: filter
chain: FORWARD
in_interface: "{{ wg_interface }}"
out_interface: "{{ wan_interface }}"
source: "{{ wg_net }}"
jump: ACCEPT
state: present
when: firewall_backend == "iptables"
- name: Allow forwarding wan -> wg (iptables)
community.general.iptables:
table: filter
chain: FORWARD
out_interface: "{{ wg_interface }}"
destination: "{{ wg_net }}"
ctstate: RELATED,ESTABLISHED
jump: ACCEPT
state: present
when: firewall_backend == "iptables"
- name: Allow forwarding to extra nets (iptables)
community.general.iptables:
table: filter
chain: FORWARD
in_interface: "{{ wg_interface }}"
destination: "{{ item }}"
jump: ACCEPT
state: present
loop: "{{ extra_nets }}"
when: firewall_backend == "iptables"
- name: Allow return from extra nets (iptables)
community.general.iptables:
table: filter
chain: FORWARD
source: "{{ item }}"
out_interface: "{{ wg_interface }}"
ctstate: RELATED,ESTABLISHED
jump: ACCEPT
state: present
loop: "{{ extra_nets }}"
when: firewall_backend == "iptables"
- name: Deploy nftables WireGuard rules
ansible.builtin.template:
src: "{{ playbook_dir }}/../templates/wireguard-nftables.nft.j2"
dest: "/etc/nftables.d/wireguard-{{ wg_interface }}.nft"
owner: root
group: root
mode: "0644"
when: firewall_backend == "nftables"
notify: Reload nftables
- name: Ensure nftables main config includes WireGuard rules
ansible.builtin.lineinfile:
path: /etc/nftables.conf
regexp: '^include "/etc/nftables.d/wireguard-{{ wg_interface }}.nft";$'
line: 'include "/etc/nftables.d/wireguard-{{ wg_interface }}.nft";'
create: true
when: firewall_backend == "nftables"
notify: Reload nftables
- name: Manage UFW forward policy
ansible.builtin.lineinfile:
path: /etc/default/ufw
regexp: '^DEFAULT_FORWARD_POLICY='
line: 'DEFAULT_FORWARD_POLICY="ACCEPT"'
when: manage_ufw
- name: Allow WireGuard port in UFW
community.general.ufw:
rule: allow
port: "{{ listening_port }}"
proto: udp
comment: "WireGuard VPN"
when: manage_ufw
- name: Allow routed traffic via UFW (wg -> wan)
ansible.builtin.command:
cmd: "ufw route allow in on {{ wg_interface }} out on {{ wan_interface }} to any"
register: ufw_route_result
changed_when: "'Skipping' not in ufw_route_result.stdout"
when: manage_ufw
- name: Allow extra nets via UFW
ansible.builtin.command:
cmd: "ufw route allow in on {{ wg_interface }} to {{ item }}"
loop: "{{ extra_nets }}"
register: ufw_extra_result
changed_when: "'Skipping' not in ufw_extra_result.stdout"
when: manage_ufw
- name: Allow WireGuard port in firewalld
ansible.posix.firewalld:
zone: "{{ firewalld_zone }}"
port: "{{ listening_port }}/udp"
permanent: true
state: enabled
when: manage_firewalld
- name: Enable firewalld masquerade
ansible.posix.firewalld:
zone: "{{ firewalld_zone }}"
masquerade: true
permanent: true
state: enabled
when: manage_firewalld
- name: Allow forwarding from WireGuard via firewalld
ansible.posix.firewalld:
permanent: true
state: enabled
immediate: false
rich_rule: 'rule family="ipv4" source address="{{ wg_net }}" accept'
when: manage_firewalld
- name: Allow extra nets via firewalld
ansible.posix.firewalld:
permanent: true
state: enabled
immediate: false
rich_rule: 'rule family="ipv4" source address="{{ item }}" accept'
loop: "{{ extra_nets }}"
when: manage_firewalld
- name: Ensure wg-quick service enabled and restarted
ansible.builtin.systemd:
name: "wg-quick@{{ wg_interface }}"
enabled: true
state: restarted
- name: Show WireGuard status
ansible.builtin.command: "wg show {{ wg_interface }}"
register: wg_status
changed_when: false
failed_when: false
- name: Render routing summary
ansible.builtin.debug:
msg: |
WireGuard routing updated for {{ wg_interface }}
{{ wg_status.stdout }}
handlers:
- name: Reload nftables
ansible.builtin.command: nft -f /etc/nftables.conf

View File

@@ -0,0 +1,156 @@
#!/usr/bin/env bash
# setup-wireguard-routing.sh
# Idempotent WireGuard split-tunnel routing helper.
# Detects iptables/nftables and optional UFW/Firewalld to configure forwarding + NAT.
set -euo pipefail
WAN_IF=${WAN_IF:-eth0}
WG_IF=${WG_IF:-wg0}
WG_NET=${WG_NET:-10.8.0.0/24}
WG_ADDR=${WG_ADDR:-10.8.0.1/24}
WG_PORT=${WG_PORT:-51820}
EXTRA_NETS_DEFAULT="192.168.178.0/24 172.20.0.0/16"
EXTRA_NETS="${EXTRA_NETS:-$EXTRA_NETS_DEFAULT}"
FIREWALL_BACKEND=${FIREWALL_BACKEND:-auto}
FIREWALLD_ZONE=${FIREWALLD_ZONE:-public}
read -r -a EXTRA_NETS_ARRAY <<< "${EXTRA_NETS}"
abort() {
echo "Error: $1" >&2
exit 1
}
require_root() {
if [[ "${EUID}" -ne 0 ]]; then
abort "please run as root (sudo ./setup-wireguard-routing.sh)"
fi
}
detect_backend() {
case "${FIREWALL_BACKEND}" in
iptables|nftables) echo "${FIREWALL_BACKEND}"; return 0 ;;
auto)
if command -v nft >/dev/null 2>&1; then
echo "nftables"; return 0
fi
if command -v iptables >/dev/null 2>&1; then
echo "iptables"; return 0
fi
;;
esac
abort "no supported firewall backend found (install iptables or nftables)"
}
ensure_sysctl() {
local sysctl_file="/etc/sysctl.d/99-${WG_IF}-forward.conf"
cat <<EOF > "${sysctl_file}"
# Managed by setup-wireguard-routing.sh
net.ipv4.ip_forward=1
EOF
sysctl -w net.ipv4.ip_forward=1 >/dev/null
sysctl --system >/dev/null
}
apply_iptables() {
iptables -t nat -C POSTROUTING -s "${WG_NET}" -o "${WAN_IF}" -j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING -s "${WG_NET}" -o "${WAN_IF}" -j MASQUERADE
iptables -C FORWARD -i "${WG_IF}" -s "${WG_NET}" -o "${WAN_IF}" -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -i "${WG_IF}" -s "${WG_NET}" -o "${WAN_IF}" -j ACCEPT
iptables -C FORWARD -o "${WG_IF}" -d "${WG_NET}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -o "${WG_IF}" -d "${WG_NET}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
for net in "${EXTRA_NETS_ARRAY[@]}"; do
[[ -z "${net}" ]] && continue
iptables -C FORWARD -i "${WG_IF}" -d "${net}" -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -i "${WG_IF}" -d "${net}" -j ACCEPT
iptables -C FORWARD -s "${net}" -o "${WG_IF}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -s "${net}" -o "${WG_IF}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
done
}
apply_nftables() {
local table="inet wireguard_${WG_IF}"
nft list table ${table} >/dev/null 2>&1 || nft add table ${table}
nft list chain ${table} postrouting >/dev/null 2>&1 || \
nft add chain ${table} postrouting '{ type nat hook postrouting priority srcnat; }'
nft list chain ${table} forward >/dev/null 2>&1 || \
nft add chain ${table} forward '{ type filter hook forward priority filter; policy accept; }'
nft list chain ${table} postrouting | grep -q "oifname \"${WAN_IF}\" ip saddr ${WG_NET}" || \
nft add rule ${table} postrouting oifname "${WAN_IF}" ip saddr ${WG_NET} masquerade
nft list chain ${table} forward | grep -q "iifname \"${WG_IF}\" ip saddr ${WG_NET}" || \
nft add rule ${table} forward iifname "${WG_IF}" ip saddr ${WG_NET} counter accept
nft list chain ${table} forward | grep -q "oifname \"${WG_IF}\" ip daddr ${WG_NET}" || \
nft add rule ${table} forward oifname "${WG_IF}" ip daddr ${WG_NET} ct state established,related counter accept
for net in "${EXTRA_NETS_ARRAY[@]}"; do
[[ -z "${net}" ]] && continue
nft list chain ${table} forward | grep -q "iifname \"${WG_IF}\" ip daddr ${net}" || \
nft add rule ${table} forward iifname "${WG_IF}" ip daddr ${net} counter accept
done
}
configure_ufw() {
if command -v ufw >/dev/null 2>&1 && ufw status | grep -iq "Status: active"; then
sed -i 's/^DEFAULT_FORWARD_POLICY=.*/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
ufw allow "${WG_PORT}"/udp >/dev/null
ufw route allow in on "${WG_IF}" out on "${WAN_IF}" to any >/dev/null 2>&1 || true
for net in "${EXTRA_NETS_ARRAY[@]}"; do
[[ -z "${net}" ]] && continue
ufw route allow in on "${WG_IF}" to "${net}" >/dev/null 2>&1 || true
done
ufw reload >/dev/null
fi
}
configure_firewalld() {
if command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then
firewall-cmd --permanent --zone="${FIREWALLD_ZONE}" --add-port=${WG_PORT}/udp >/dev/null
firewall-cmd --permanent --zone="${FIREWALLD_ZONE}" --add-masquerade >/dev/null
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
"iif ${WG_IF} oif ${WAN_IF} -s ${WG_NET} -j ACCEPT" >/dev/null 2>&1 || true
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
"oif ${WG_IF} -d ${WG_NET} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" >/dev/null 2>&1 || true
for net in "${EXTRA_NETS_ARRAY[@]}"; do
[[ -z "${net}" ]] && continue
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
"iif ${WG_IF} -d ${net} -j ACCEPT" >/dev/null 2>&1 || true
done
firewall-cmd --reload >/dev/null
fi
}
ensure_service() {
systemctl enable "wg-quick@${WG_IF}" >/dev/null
systemctl restart "wg-quick@${WG_IF}"
}
show_status() {
echo "WireGuard routing configured with ${WG_IF} (${WG_ADDR}) via ${WAN_IF}"
wg show "${WG_IF}" || true
ip route show table main | grep "${WG_NET}" || true
}
main() {
require_root
ensure_sysctl
backend=$(detect_backend)
case "${backend}" in
iptables) apply_iptables ;;
nftables) apply_nftables ;;
esac
configure_ufw
configure_firewalld
ensure_service
show_status
}
main "$@"

View File

@@ -0,0 +1,50 @@
# WireGuard Server Configuration
# Interface: wg0
# Network: {{ wg_network }}
# Server IP: {{ wg_server_ip }}
[Interface]
PrivateKey = {{ wg_server_private_key }}
Address = {{ wg_server_ip }}/{{ wg_netmask }}
ListenPort = {{ wg_port | default(51820) }}
# Enable IP forwarding for VPN routing
PostUp = sysctl -w net.ipv4.ip_forward=1
# nftables: Setup VPN routing and firewall
PostUp = nft add table inet wireguard
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
PostUp = nft add chain inet wireguard forward { type filter hook forward priority filter\; }
# NAT for VPN traffic (masquerade to WAN)
PostUp = nft add rule inet wireguard postrouting oifname "{{ wan_interface }}" ip saddr {{ wg_network }} masquerade
# Allow VPN traffic forwarding
PostUp = nft add rule inet wireguard forward iifname "wg0" ip saddr {{ wg_network }} accept
PostUp = nft add rule inet wireguard forward oifname "wg0" ip daddr {{ wg_network }} ct state established,related accept
# Cleanup on shutdown
PostDown = nft delete table inet wireguard
# Peers (automatically managed)
# Format:
# [Peer]
# # Description: device-name
# PublicKey = peer_public_key
# PresharedKey = peer_preshared_key
# AllowedIPs = 10.8.0.X/32
# PersistentKeepalive = 25 # Optional: for clients behind NAT
{% for peer in wg_peers | default([]) %}
[Peer]
# {{ peer.name }}
PublicKey = {{ peer.public_key }}
{% if peer.preshared_key is defined %}
PresharedKey = {{ peer.preshared_key }}
{% endif %}
AllowedIPs = {{ peer.allowed_ips }}
{% if peer.persistent_keepalive | default(true) %}
PersistentKeepalive = 25
{% endif %}
{% endfor %}

View File

@@ -0,0 +1,116 @@
#!/usr/sbin/nft -f
# WireGuard VPN Firewall Rules
# Purpose: Isolate admin services behind VPN, allow public access only to ports 80, 443, 22
# Generated by Ansible - DO NOT EDIT MANUALLY
table inet wireguard_firewall {
# Define sets for easy management
set vpn_network {
type ipv4_addr
flags interval
elements = { {{ wg_network }} }
}
set admin_service_ports {
type inet_service
elements = {
8080, # Traefik Dashboard
9090, # Prometheus
3001, # Grafana
9000, # Portainer
8001, # Redis Insight
{% for port in additional_admin_ports | default([]) %}
{{ port }}, # {{ port }}
{% endfor %}
}
}
set public_service_ports {
type inet_service
elements = {
80, # HTTP
443, # HTTPS
22, # SSH
{% for port in additional_public_ports | default([]) %}
{{ port }}, # {{ port }}
{% endfor %}
}
}
# Input chain - Handle incoming traffic
chain input {
type filter hook input priority filter; policy drop;
# Allow established/related connections
ct state established,related accept
# Allow loopback
iifname "lo" accept
# Allow ICMP (ping)
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# Allow SSH (public)
tcp dport 22 accept
# Allow WireGuard port (public)
udp dport {{ wg_port | default(51820) }} accept comment "WireGuard VPN"
# Allow public web services (HTTP/HTTPS)
tcp dport @public_service_ports accept comment "Public services"
# Allow VPN network to access admin services
ip saddr @vpn_network tcp dport @admin_service_ports accept comment "VPN admin access"
# Block public access to admin services
tcp dport @admin_service_ports counter log prefix "BLOCKED_ADMIN_SERVICE: " drop
# Log and drop all other traffic
counter log prefix "BLOCKED_INPUT: " drop
}
# Forward chain - Handle routed traffic (VPN to services)
chain forward {
type filter hook forward priority filter; policy drop;
# Allow established/related connections
ct state established,related accept
# Allow VPN clients to access local services
iifname "wg0" ip saddr @vpn_network accept comment "VPN to services"
# Allow return traffic to VPN clients
oifname "wg0" ip daddr @vpn_network ct state established,related accept
# Log and drop all other forwarded traffic
counter log prefix "BLOCKED_FORWARD: " drop
}
# Output chain - Allow all outgoing traffic
chain output {
type filter hook output priority filter; policy accept;
}
# NAT chain - Masquerade VPN traffic to WAN
chain postrouting {
type nat hook postrouting priority srcnat;
# Masquerade VPN traffic going to WAN
oifname "{{ wan_interface }}" ip saddr @vpn_network masquerade comment "VPN NAT"
}
}
# Optional: Rate limiting for VPN port (DDoS protection)
{% if wg_enable_rate_limit | default(true) %}
table inet wireguard_ratelimit {
chain input {
type filter hook input priority -10;
# Rate limit WireGuard port: 10 connections per second per IP
udp dport {{ wg_port | default(51820) }} \
meter vpn_ratelimit { ip saddr limit rate over 10/second } \
counter log prefix "VPN_RATELIMIT: " drop
}
}
{% endif %}

View File

@@ -0,0 +1,15 @@
table inet wireguard_{{ wg_interface }} {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname "{{ wan_interface }}" ip saddr {{ wg_net }} masquerade
}
chain forward {
type filter hook forward priority filter;
iifname "{{ wg_interface }}" ip saddr {{ wg_net }} counter accept
oifname "{{ wg_interface }}" ip daddr {{ wg_net }} ct state established,related counter accept
{% for net in extra_nets %}
iifname "{{ wg_interface }}" ip daddr {{ net }} counter accept
{% endfor %}
}
}

View File

@@ -0,0 +1,14 @@
[Interface]
# Client: michael-pc
# Generated: 2025-11-05T01:02:14Z
PrivateKey = MHgxUzmEHQ15EB3v4TaXEcJAZNRaBd54/ZDcN6nN8lI=
Address = 10.8.0.2/32
DNS = 1.1.1.1, 8.8.8.8
[Peer]
# WireGuard Server
PublicKey = SFxxHe4bunfQ1Xid5AMXbBgY+AjlxNtRHQ5uYjSib3E=
PresharedKey = WsnvFp6WrF/y9fQwn3RgOTmwMS2UHoqIBRKrTPZ5lW8=
Endpoint = 94.16.110.151:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25

View File

@@ -0,0 +1,206 @@
#!/bin/bash
# Cleanup Old WireGuard Docker Setup
# Purpose: Remove old WireGuard Docker stack and CoreDNS before migrating to host-based setup
# WARNING: This will stop and remove the old VPN setup!
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# ========================================
# Configuration
# ========================================
DEPLOYMENT_DIR="/home/michael/dev/michaelschiemer/deployment"
WIREGUARD_STACK_DIR="${DEPLOYMENT_DIR}/stacks/wireguard"
COREDNS_STACK_DIR="${DEPLOYMENT_DIR}/stacks/coredns"
ARCHIVE_DIR="${DEPLOYMENT_DIR}/wireguard-docker-archive-$(date +%Y%m%d)"
# ========================================
# Pre-flight Checks
# ========================================
print_info "WireGuard Docker Setup Cleanup Script"
echo ""
print_warning "This script will:"
echo " - Stop WireGuard Docker container"
echo " - Stop CoreDNS container (if exists)"
echo " - Archive old configuration"
echo " - Remove Docker stacks"
echo ""
print_warning "VPN access will be lost until new host-based setup is deployed!"
echo ""
read -p "Continue? (type 'yes' to proceed): " -r
if [[ ! $REPLY == "yes" ]]; then
print_info "Aborted by user"
exit 0
fi
# ========================================
# Stop Docker Containers
# ========================================
print_info "Stopping WireGuard Docker container..."
if [ -d "$WIREGUARD_STACK_DIR" ]; then
cd "$WIREGUARD_STACK_DIR"
if [ -f "docker-compose.yml" ]; then
docker-compose down || print_warning "WireGuard container already stopped or not found"
fi
else
print_warning "WireGuard stack directory not found: $WIREGUARD_STACK_DIR"
fi
print_info "Stopping CoreDNS Docker container (if exists)..."
if [ -d "$COREDNS_STACK_DIR" ]; then
cd "$COREDNS_STACK_DIR"
if [ -f "docker-compose.yml" ]; then
docker-compose down || print_warning "CoreDNS container already stopped or not found"
fi
else
print_info "CoreDNS stack directory not found (may not have existed)"
fi
# ========================================
# Archive Old Configuration
# ========================================
print_info "Creating archive of old configuration..."
mkdir -p "$ARCHIVE_DIR"
# Archive WireGuard stack
if [ -d "$WIREGUARD_STACK_DIR" ]; then
print_info "Archiving WireGuard stack..."
cp -r "$WIREGUARD_STACK_DIR" "$ARCHIVE_DIR/wireguard-stack"
print_success "WireGuard stack archived to: $ARCHIVE_DIR/wireguard-stack"
fi
# Archive CoreDNS stack
if [ -d "$COREDNS_STACK_DIR" ]; then
print_info "Archiving CoreDNS stack..."
cp -r "$COREDNS_STACK_DIR" "$ARCHIVE_DIR/coredns-stack"
print_success "CoreDNS stack archived to: $ARCHIVE_DIR/coredns-stack"
fi
# Archive old Ansible files
print_info "Archiving old Ansible playbooks..."
if [ -d "${DEPLOYMENT_DIR}/wireguard-old" ]; then
cp -r "${DEPLOYMENT_DIR}/wireguard-old" "$ARCHIVE_DIR/ansible-old"
fi
# Archive nftables templates
if [ -f "${DEPLOYMENT_DIR}/ansible/templates/wireguard-nftables.nft.j2" ]; then
mkdir -p "$ARCHIVE_DIR/ansible-templates"
cp "${DEPLOYMENT_DIR}/ansible/templates/wireguard-nftables.nft.j2" "$ARCHIVE_DIR/ansible-templates/"
fi
# Create archive summary
cat > "$ARCHIVE_DIR/ARCHIVE_INFO.txt" <<EOF
WireGuard Docker Setup Archive
Created: $(date)
This archive contains the old WireGuard Docker-based setup that was replaced
with a host-based WireGuard configuration.
Contents:
- wireguard-stack/: Docker Compose stack for WireGuard
- coredns-stack/: Docker Compose stack for CoreDNS (if existed)
- ansible-old/: Old Ansible playbooks and configs
- ansible-templates/: Old nftables templates
To restore old setup (NOT RECOMMENDED):
1. Stop new host-based WireGuard: systemctl stop wg-quick@wg0
2. Copy stacks back: cp -r wireguard-stack ../stacks/
3. Start container: cd ../stacks/wireguard && docker-compose up -d
For new host-based setup, see:
- deployment/wireguard/README.md
- deployment/ansible/playbooks/setup-wireguard-host.yml
EOF
print_success "Archive created at: $ARCHIVE_DIR"
# ========================================
# Remove Docker Stacks
# ========================================
print_info "Removing old Docker stacks..."
read -p "Remove WireGuard Docker stack directory? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
if [ -d "$WIREGUARD_STACK_DIR" ]; then
rm -rf "$WIREGUARD_STACK_DIR"
print_success "WireGuard Docker stack removed"
fi
fi
read -p "Remove CoreDNS Docker stack directory? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
if [ -d "$COREDNS_STACK_DIR" ]; then
rm -rf "$COREDNS_STACK_DIR"
print_success "CoreDNS Docker stack removed"
fi
fi
# ========================================
# Clean up Docker Resources
# ========================================
print_info "Cleaning up Docker resources..."
# Remove WireGuard network
docker network rm wireguard-net 2>/dev/null || print_info "WireGuard network already removed"
# Remove unused volumes
print_info "Removing unused Docker volumes..."
docker volume prune -f || print_warning "Could not prune volumes"
# ========================================
# Summary
# ========================================
echo ""
print_success "=========================================="
print_success "Cleanup Complete!"
print_success "=========================================="
echo ""
echo "Archive Location: $ARCHIVE_DIR"
echo ""
print_info "Next Steps:"
echo " 1. Deploy host-based WireGuard:"
echo " cd ${DEPLOYMENT_DIR}/ansible"
echo " ansible-playbook playbooks/setup-wireguard-host.yml"
echo ""
echo " 2. Generate client configs:"
echo " cd ${DEPLOYMENT_DIR}/scripts"
echo " sudo ./generate-client-config.sh <device-name>"
echo ""
echo " 3. Verify new setup:"
echo " sudo wg show wg0"
echo " sudo systemctl status wg-quick@wg0"
echo ""
print_warning "Old Docker-based VPN is now inactive!"
print_info "VPN access will be restored after deploying host-based setup"
echo ""

View File

@@ -0,0 +1,282 @@
#!/bin/bash
# WireGuard Client Configuration Generator
# Purpose: Generate client configs with QR codes for easy mobile import
# Usage: ./generate-client-config.sh <client-name>
set -euo pipefail
# ========================================
# Configuration
# ========================================
WG_CONFIG_DIR="/etc/wireguard"
CLIENT_CONFIG_DIR="$(dirname "$0")/../wireguard/configs"
WG_INTERFACE="wg0"
WG_SERVER_CONFIG="${WG_CONFIG_DIR}/${WG_INTERFACE}.conf"
WG_NETWORK="10.8.0.0/24"
WG_SERVER_IP="10.8.0.1"
WG_PORT="51820"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ========================================
# Helper Functions
# ========================================
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
check_root() {
if [ "$EUID" -ne 0 ]; then
print_error "This script must be run as root (for server config modifications)"
exit 1
fi
}
check_dependencies() {
local deps=("wg" "wg-quick" "qrencode")
local missing=()
for dep in "${deps[@]}"; do
if ! command -v "$dep" &> /dev/null; then
missing+=("$dep")
fi
done
if [ ${#missing[@]} -ne 0 ]; then
print_error "Missing dependencies: ${missing[*]}"
print_info "Install with: apt install wireguard wireguard-tools qrencode"
exit 1
fi
}
get_next_client_ip() {
# Find highest used IP in last octet and add 1
if [ ! -f "$WG_SERVER_CONFIG" ]; then
echo "10.8.0.2"
return
fi
local last_octet=$(grep -oP 'AllowedIPs\s*=\s*10\.8\.0\.\K\d+' "$WG_SERVER_CONFIG" 2>/dev/null | sort -n | tail -1)
if [ -z "$last_octet" ]; then
echo "10.8.0.2"
else
echo "10.8.0.$((last_octet + 1))"
fi
}
get_server_public_key() {
if [ ! -f "${WG_CONFIG_DIR}/server_public.key" ]; then
print_error "Server public key not found at ${WG_CONFIG_DIR}/server_public.key"
print_info "Run the Ansible playbook first: ansible-playbook setup-wireguard-host.yml"
exit 1
fi
cat "${WG_CONFIG_DIR}/server_public.key"
}
get_server_endpoint() {
# Try to detect public IP
local public_ip
public_ip=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
echo "${public_ip}:${WG_PORT}"
}
# ========================================
# Main Script
# ========================================
main() {
print_info "WireGuard Client Configuration Generator"
echo ""
# Validate input
if [ $# -ne 1 ]; then
print_error "Usage: $0 <client-name>"
echo ""
echo "Example:"
echo " $0 michael-laptop"
echo " $0 iphone"
echo " $0 office-desktop"
exit 1
fi
local client_name="$1"
# Validate client name (alphanumeric + dash/underscore only)
if ! [[ "$client_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
print_error "Client name must contain only alphanumeric characters, dashes, and underscores"
exit 1
fi
# Pre-flight checks
check_root
check_dependencies
# Create client config directory
mkdir -p "$CLIENT_CONFIG_DIR"
# Check if client already exists
if [ -f "${CLIENT_CONFIG_DIR}/${client_name}.conf" ]; then
print_warning "Client config for '${client_name}' already exists"
read -p "Regenerate? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Aborted"
exit 0
fi
fi
print_info "Generating configuration for client: ${client_name}"
echo ""
# Generate client keys
print_info "Generating client keys..."
local client_private_key=$(wg genkey)
local client_public_key=$(echo "$client_private_key" | wg pubkey)
local client_preshared_key=$(wg genpsk)
# Get server information
print_info "Reading server configuration..."
local server_public_key=$(get_server_public_key)
local server_endpoint=$(get_server_endpoint)
# Assign client IP
local client_ip=$(get_next_client_ip)
print_info "Assigned client IP: ${client_ip}"
# Create client config file
print_info "Creating client configuration file..."
cat > "${CLIENT_CONFIG_DIR}/${client_name}.conf" <<EOF
[Interface]
# Client: ${client_name}
# Generated: $(date)
PrivateKey = ${client_private_key}
Address = ${client_ip}/32
# DNS: Use Cloudflare/Quad9 (change if needed)
DNS = 1.1.1.1, 9.9.9.9
[Peer]
# Server
PublicKey = ${server_public_key}
PresharedKey = ${client_preshared_key}
Endpoint = ${server_endpoint}
# Route only VPN network through tunnel (split-tunnel)
AllowedIPs = ${WG_NETWORK}
# Keep connection alive (NAT traversal)
PersistentKeepalive = 25
EOF
chmod 600 "${CLIENT_CONFIG_DIR}/${client_name}.conf"
# Add peer to server configuration
print_info "Adding peer to server configuration..."
# Check if peer already exists in server config
if grep -q "# ${client_name}" "$WG_SERVER_CONFIG" 2>/dev/null; then
print_info "Removing old peer entry..."
# Remove old peer entry (from comment to next empty line or end of file)
sed -i "/# ${client_name}/,/^$/d" "$WG_SERVER_CONFIG"
fi
# Append new peer
cat >> "$WG_SERVER_CONFIG" <<EOF
[Peer]
# ${client_name}
PublicKey = ${client_public_key}
PresharedKey = ${client_preshared_key}
AllowedIPs = ${client_ip}/32
PersistentKeepalive = 25
EOF
# Reload WireGuard to apply changes
print_info "Reloading WireGuard configuration..."
systemctl reload wg-quick@${WG_INTERFACE}
# Verify peer is active
sleep 1
if wg show ${WG_INTERFACE} | grep -q "$client_public_key"; then
print_success "Peer successfully added to server"
else
print_warning "Peer added to config but not yet active (will activate when client connects)"
fi
# Generate QR code for mobile devices
print_info "Generating QR code for mobile import..."
qrencode -t ansiutf8 < "${CLIENT_CONFIG_DIR}/${client_name}.conf" > "${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
qrencode -t png -o "${CLIENT_CONFIG_DIR}/${client_name}.qr.png" < "${CLIENT_CONFIG_DIR}/${client_name}.conf"
# Display success summary
echo ""
print_success "=========================================="
print_success "Client Configuration Created!"
print_success "=========================================="
echo ""
echo "Client Name: ${client_name}"
echo "Client IP: ${client_ip}"
echo "Config File: ${CLIENT_CONFIG_DIR}/${client_name}.conf"
echo "QR Code (text): ${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
echo "QR Code (PNG): ${CLIENT_CONFIG_DIR}/${client_name}.qr.png"
echo ""
echo "Server Endpoint: ${server_endpoint}"
echo "VPN Network: ${WG_NETWORK}"
echo ""
print_info "=========================================="
print_info "Import Instructions:"
print_info "=========================================="
echo ""
echo "Desktop (Linux/macOS):"
echo " sudo cp ${CLIENT_CONFIG_DIR}/${client_name}.conf /etc/wireguard/"
echo " sudo wg-quick up ${client_name}"
echo ""
echo "Desktop (Windows):"
echo " 1. Open WireGuard GUI"
echo " 2. Click 'Import tunnel(s) from file'"
echo " 3. Select: ${CLIENT_CONFIG_DIR}/${client_name}.conf"
echo ""
echo "Mobile (iOS/Android):"
echo " 1. Open WireGuard app"
echo " 2. Tap '+' > 'Create from QR code'"
echo " 3. Scan QR code below or from: ${CLIENT_CONFIG_DIR}/${client_name}.qr.png"
echo ""
print_info "QR Code (scan with phone):"
echo ""
cat "${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
echo ""
print_info "=========================================="
print_info "Verify Connection:"
print_info "=========================================="
echo ""
echo "After connecting:"
echo " ping ${WG_SERVER_IP}"
echo " curl -k https://${WG_SERVER_IP}:8080 # Traefik Dashboard"
echo ""
print_success "Configuration complete! Client is ready to connect."
}
# Run main function
main "$@"

View File

@@ -0,0 +1,307 @@
#!/bin/bash
# Manual WireGuard Setup Script
# Purpose: Step-by-step WireGuard installation and configuration
# This script shows what needs to be done - review before executing!
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
print_step() {
echo -e "${BLUE}[STEP]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# ========================================
# Configuration
# ========================================
WG_INTERFACE="wg0"
WG_NETWORK="10.8.0.0/24"
WG_SERVER_IP="10.8.0.1"
WG_PORT="51820"
WG_CONFIG_DIR="/etc/wireguard"
WAN_INTERFACE="eth0" # ANPASSEN an dein System!
# ========================================
# Pre-flight Checks
# ========================================
print_step "Pre-flight Checks"
if [ "$EUID" -ne 0 ]; then
print_error "This script must be run as root"
exit 1
fi
# Check if WireGuard is installed
if ! command -v wg &> /dev/null; then
print_error "WireGuard is not installed"
echo "Install with: apt update && apt install -y wireguard wireguard-tools qrencode nftables"
exit 1
fi
print_success "Pre-flight checks passed"
# ========================================
# Step 1: Create WireGuard Directory
# ========================================
print_step "Creating WireGuard directory"
mkdir -p ${WG_CONFIG_DIR}
chmod 700 ${WG_CONFIG_DIR}
print_success "Directory created: ${WG_CONFIG_DIR}"
# ========================================
# Step 2: Generate Server Keys
# ========================================
print_step "Generating server keys"
cd ${WG_CONFIG_DIR}
if [ ! -f server_private.key ]; then
wg genkey | tee server_private.key | wg pubkey > server_public.key
chmod 600 server_private.key
chmod 644 server_public.key
print_success "Server keys generated"
else
print_warning "Server keys already exist - skipping generation"
fi
SERVER_PRIVATE_KEY=$(cat server_private.key)
SERVER_PUBLIC_KEY=$(cat server_public.key)
echo ""
echo "Server Public Key: ${SERVER_PUBLIC_KEY}"
echo ""
# ========================================
# Step 3: Create WireGuard Configuration
# ========================================
print_step "Creating WireGuard configuration"
cat > ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf <<EOF
[Interface]
# Server Configuration
PrivateKey = ${SERVER_PRIVATE_KEY}
Address = ${WG_SERVER_IP}/24
ListenPort = ${WG_PORT}
# Enable IP forwarding
PostUp = sysctl -w net.ipv4.ip_forward=1
# NAT Configuration with nftables
PostUp = nft add table inet wireguard
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
PostUp = nft add rule inet wireguard postrouting oifname "${WAN_INTERFACE}" ip saddr ${WG_NETWORK} masquerade
# Cleanup on shutdown
PostDown = nft delete table inet wireguard
# Peers will be added here via generate-client-config.sh
EOF
chmod 600 ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf
print_success "Configuration created: ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf"
# ========================================
# Step 4: Create nftables Firewall Rules
# ========================================
print_step "Creating nftables firewall rules"
cat > /etc/nftables.d/wireguard.nft <<'EOF'
#!/usr/sbin/nft -f
# WireGuard Host-based Firewall Configuration
# Purpose: Secure VPN access with admin service protection
table inet wireguard_firewall {
# Define sets for efficient rule matching
set vpn_network {
type ipv4_addr
flags interval
elements = { 10.8.0.0/24 }
}
set admin_service_ports {
type inet_service
elements = {
8080, # Traefik Dashboard
9090, # Prometheus
3001, # Grafana
9000, # Portainer
8001, # Redis Insight
}
}
set public_service_ports {
type inet_service
elements = {
80, # HTTP
443, # HTTPS
22, # SSH
}
}
# Input chain - Control incoming connections
chain input {
type filter hook input priority filter; policy drop;
# Allow established/related connections
ct state established,related accept
# Allow loopback
iif lo accept
# Allow ICMP (ping)
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# Allow WireGuard port
udp dport 51820 accept
# Allow VPN network to access admin services
ip saddr @vpn_network tcp dport @admin_service_ports accept
# Allow public access to public services
tcp dport @public_service_ports accept
# Block public access to admin services (with logging)
tcp dport @admin_service_ports counter log prefix "BLOCKED_ADMIN_SERVICE: " drop
# Rate limit SSH to prevent brute force
tcp dport 22 ct state new limit rate 10/minute accept
# Drop everything else
counter log prefix "BLOCKED_INPUT: " drop
}
# Forward chain - Control packet forwarding
chain forward {
type filter hook forward priority filter; policy drop;
# Allow established/related connections
ct state established,related accept
# Allow VPN network to forward
ip saddr @vpn_network accept
# Drop everything else
counter log prefix "BLOCKED_FORWARD: " drop
}
# Output chain - Allow all outgoing by default
chain output {
type filter hook output priority filter; policy accept;
}
}
EOF
chmod 755 /etc/nftables.d/wireguard.nft
print_success "Firewall rules created: /etc/nftables.d/wireguard.nft"
# ========================================
# Step 5: Enable IP Forwarding
# ========================================
print_step "Enabling IP forwarding"
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf
sysctl -p /etc/sysctl.d/99-wireguard.conf
print_success "IP forwarding enabled"
# ========================================
# Step 6: Apply nftables Rules
# ========================================
print_step "Applying nftables firewall rules"
if [ -f /etc/nftables.d/wireguard.nft ]; then
nft -f /etc/nftables.d/wireguard.nft
print_success "Firewall rules applied"
else
print_error "Firewall rules file not found"
exit 1
fi
# ========================================
# Step 7: Enable and Start WireGuard
# ========================================
print_step "Enabling and starting WireGuard service"
systemctl enable wg-quick@${WG_INTERFACE}
systemctl start wg-quick@${WG_INTERFACE}
print_success "WireGuard service enabled and started"
# ========================================
# Step 8: Verify Installation
# ========================================
print_step "Verifying installation"
echo ""
echo "WireGuard Status:"
wg show ${WG_INTERFACE}
echo ""
echo "Service Status:"
systemctl status wg-quick@${WG_INTERFACE} --no-pager
echo ""
echo "nftables Rules:"
nft list table inet wireguard_firewall
# ========================================
# Summary
# ========================================
echo ""
print_success "=========================================="
print_success "WireGuard Installation Complete!"
print_success "=========================================="
echo ""
echo "Server IP: ${WG_SERVER_IP}"
echo "Listen Port: ${WG_PORT}"
echo "VPN Network: ${WG_NETWORK}"
echo "Interface: ${WG_INTERFACE}"
echo ""
print_step "Next Steps:"
echo " 1. Generate client configs:"
echo " cd /home/michael/dev/michaelschiemer/deployment/scripts"
echo " sudo ./generate-client-config.sh <client-name>"
echo ""
echo " 2. Import client config on your device"
echo ""
echo " 3. Connect and test access to admin services:"
echo " - Traefik Dashboard: https://10.8.0.1:8080"
echo " - Prometheus: http://10.8.0.1:9090"
echo " - Grafana: https://10.8.0.1:3001"
echo " - Portainer: http://10.8.0.1:9000"
echo " - Redis Insight: http://10.8.0.1:8001"
echo ""

View File

@@ -1,14 +0,0 @@
services:
coredns:
image: coredns/coredns:1.11.1
container_name: coredns
restart: unless-stopped
network_mode: host
command: -conf /etc/coredns/Corefile
volumes:
- ./Corefile:/etc/coredns/Corefile:ro
healthcheck:
# Disable healthcheck - CoreDNS is a minimal image without shell
# CoreDNS runs fine (verified by DNS queries working correctly)
# If needed, health can be checked externally via dig
disable: true

View File

@@ -1,141 +0,0 @@
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
# DIRECT ACCESS: Bind only to VPN gateway IP
ports:
- "10.8.0.1:9002:9000" # Port 9002 to avoid conflict with MinIO (port 9000)
networks:
- monitoring-internal
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- portainer-data:/data
# Removed Traefik labels - direct access only
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
user: "65534:65534"
# DIRECT ACCESS: Bind only to VPN gateway IP
ports:
- "10.8.0.1:9090:9090"
networks:
- monitoring-internal
- app-internal
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
- '--web.enable-lifecycle'
# Removed Traefik labels - direct access only
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
interval: 30s
timeout: 10s
retries: 3
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
# DIRECT ACCESS: Bind only to VPN gateway IP
ports:
- "10.8.0.1:3001:3000"
networks:
- monitoring-internal
- app-internal
environment:
# Updated root URL for direct IP access
- GF_SERVER_ROOT_URL=http://10.8.0.1:3001
- GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER}
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
- GF_INSTALL_PLUGINS=${GRAFANA_PLUGINS}
- GF_LOG_LEVEL=info
- GF_ANALYTICS_REPORTING_ENABLED=false
# Performance: Disable external connections to grafana.com
- GF_PLUGIN_GRAFANA_COM_URL=
- GF_CHECK_FOR_UPDATES=false
- GF_CHECK_FOR_PLUGIN_UPDATES=false
# Disable background plugin installer completely
- GF_FEATURE_TOGGLES_ENABLE=disablePluginInstaller
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/grafana.ini:/etc/grafana/grafana.ini:ro
- ./grafana/provisioning:/etc/grafana/provisioning:ro
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
# Removed Traefik labels - direct access only
depends_on:
prometheus:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
networks:
- app-internal
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9100/metrics"]
interval: 30s
timeout: 10s
retries: 3
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
privileged: true
networks:
- app-internal
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
devices:
- /dev/kmsg
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/healthz"]
interval: 30s
timeout: 10s
retries: 3
volumes:
portainer-data:
name: portainer-data
prometheus-data:
name: prometheus-data
grafana-data:
name: grafana-data
networks:
# New internal network for monitoring services
monitoring-internal:
name: monitoring-internal
driver: bridge
app-internal:
external: true

View File

@@ -41,7 +41,7 @@ services:
- "traefik.http.routers.prometheus.entrypoints=websecure"
- "traefik.http.routers.prometheus.tls=true"
- "traefik.http.routers.prometheus.tls.certresolver=letsencrypt"
- "traefik.http.routers.prometheus.middlewares=prometheus-auth"
- "traefik.http.routers.prometheus.middlewares=prometheus-auth@docker"
- "traefik.http.middlewares.prometheus-auth.basicauth.users=${PROMETHEUS_AUTH}"
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
healthcheck:
@@ -75,9 +75,6 @@ services:
- "traefik.http.routers.grafana.entrypoints=websecure"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
# VPN IP whitelist: Use middleware defined in Traefik dynamic config
# Middleware is defined in deployment/stacks/traefik/dynamic/middlewares.yml
- "traefik.http.routers.grafana.middlewares=grafana-vpn-only@file"
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
depends_on:
prometheus:

View File

@@ -52,25 +52,6 @@ http:
# - "127.0.0.1/32"
# - "10.0.0.0/8"
# VPN-only IP allowlist for Grafana and other monitoring services
# Restrict access strictly to the WireGuard network
# Note: ipAllowList checks the real client IP from the connection
# When connected via VPN, client IP should be from 10.8.0.0/24
# If client IP shows public IP, the traffic is NOT going through VPN
# TEMPORARY: Added public IP for testing - REMOVE after fixing VPN routing!
grafana-vpn-only:
ipAllowList:
sourceRange:
- "10.8.0.0/24" # WireGuard VPN network (10.8.0.1 = server, 10.8.0.x = clients)
- "89.246.96.244/32" # TEMPORARY: Public IP for testing - REMOVE after VPN routing is fixed!
# VPN-only IP allowlist for general use (Traefik Dashboard, etc.)
# Restrict access strictly to the WireGuard network
vpn-only:
ipAllowList:
sourceRange:
- "10.8.0.0/24" # WireGuard VPN network
# Chain multiple middlewares
default-chain:
chain:

View File

@@ -64,10 +64,8 @@ providers:
# Forwarded Headers Configuration
# This ensures Traefik correctly identifies the real client IP
# Important for VPN access where requests come from WireGuard interface
forwardedHeaders:
trustedIPs:
- "10.8.0.0/24" # WireGuard VPN network
- "127.0.0.1/32" # Localhost
- "172.17.0.0/16" # Docker bridge network
- "172.18.0.0/16" # Docker user-defined networks

View File

@@ -0,0 +1,22 @@
# WireGuard VPN Configuration
# Server endpoint (auto-detected or set manually)
SERVERURL=auto
# WireGuard port
SERVERPORT=51820
# VPN network subnet
INTERNAL_SUBNET=10.8.0.0/24
# Allowed IPs (VPN network only - no split tunneling)
ALLOWEDIPS=10.8.0.0/24
# DNS configuration (use host DNS)
PEERDNS=auto
# Timezone
TZ=Europe/Berlin
# Peers (managed manually)
PEERS=0

View File

@@ -0,0 +1,49 @@
services:
wireguard:
image: linuxserver/wireguard:1.0.20210914
container_name: wireguard
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
- SERVERURL=auto
- SERVERPORT=51820
- PEERS=0 # Managed manually via config files
- PEERDNS=auto # Use host DNS
- INTERNAL_SUBNET=10.8.0.0/24
- ALLOWEDIPS=10.8.0.0/24 # VPN network only
- LOG_CONFS=true
volumes:
- ./config:/config
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
healthcheck:
test: ["CMD", "bash", "-c", "wg show wg0 | grep -q interface"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
default:
name: wireguard-net
driver: bridge

View File

@@ -0,0 +1,370 @@
# WireGuard Client Import & Connection Guide
Anleitung zum Importieren und Verbinden der generierten WireGuard Client-Konfiguration.
## Generierte Konfiguration
**Client Name**: michael-pc
**Config File**: `/home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/michael-pc.conf`
**Client IP**: 10.8.0.2/32
**Server Endpoint**: 94.16.110.151:51820
**VPN Network**: 10.8.0.0/24
---
## Import auf verschiedenen Plattformen
### Linux (Ubuntu/Debian)
```bash
# 1. Konfiguration nach /etc/wireguard/ kopieren
sudo cp /home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/michael-pc.conf /etc/wireguard/
# 2. Berechtigungen setzen
sudo chmod 600 /etc/wireguard/michael-pc.conf
# 3. VPN-Verbindung starten
sudo wg-quick up michael-pc
# 4. Status prüfen
sudo wg show michael-pc
# 5. Bei Boot automatisch starten (optional)
sudo systemctl enable wg-quick@michael-pc
```
**Verbindung trennen**:
```bash
sudo wg-quick down michael-pc
```
---
### macOS
```bash
# 1. WireGuard installieren (falls nicht vorhanden)
brew install wireguard-tools
# 2. Konfiguration importieren
sudo cp /home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/michael-pc.conf /etc/wireguard/
# 3. VPN starten
sudo wg-quick up michael-pc
# 4. Status prüfen
sudo wg show michael-pc
```
**Alternative**: WireGuard GUI App für macOS verwenden
- Download: https://apps.apple.com/app/wireguard/id1451685025
- "Add Tunnel from File" → `michael-pc.conf` auswählen
- Verbindung aktivieren
---
### Windows
**Via WireGuard GUI** (empfohlen):
1. **WireGuard GUI installieren**:
- Download: https://www.wireguard.com/install/
- Installer ausführen
2. **Konfiguration importieren**:
- WireGuard GUI öffnen
- "Import tunnel(s) from file"
- `michael-pc.conf` auswählen
3. **Verbindung aktivieren**:
- Tunnel "michael-pc" in der Liste anklicken
- "Activate" Button drücken
4. **Status prüfen**:
- Status sollte "Active" zeigen
- Transfer-Statistiken werden angezeigt
---
### Android
**Via WireGuard App**:
1. **WireGuard App installieren**:
- Google Play Store: "WireGuard"
2. **Konfiguration importieren**:
- Option 1: `michael-pc.conf` auf Gerät übertragen und importieren
- Option 2: QR Code scannen (falls generiert)
3. **Verbindung aktivieren**:
- Tunnel antippen
- Toggle aktivieren
---
### iOS
**Via WireGuard App**:
1. **WireGuard App installieren**:
- App Store: "WireGuard"
2. **Konfiguration importieren**:
- Option 1: `michael-pc.conf` via AirDrop/iCloud übertragen
- Option 2: QR Code scannen (falls generiert)
3. **Verbindung aktivieren**:
- Tunnel antippen
- Toggle aktivieren
---
## Konnektivitätstest
Nach erfolgreicher Verbindung:
### 1. VPN Gateway Ping
```bash
ping 10.8.0.1
```
**Erwartete Ausgabe**:
```
PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data.
64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=1.23 ms
64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=1.15 ms
```
**Erfolg**: VPN-Verbindung funktioniert
---
### 2. Admin Services Zugriff
**Traefik Dashboard** (HTTPS):
```bash
curl -k https://10.8.0.1:8080
```
**Prometheus** (HTTP):
```bash
curl http://10.8.0.1:9090
```
**Grafana** (HTTPS):
```bash
curl -k https://10.8.0.1:3001
```
**Portainer** (HTTP):
```bash
curl http://10.8.0.1:9000
```
**Redis Insight** (HTTP):
```bash
curl http://10.8.0.1:8001
```
**Browser-Zugriff**:
- Traefik: https://10.8.0.1:8080
- Prometheus: http://10.8.0.1:9090
- Grafana: https://10.8.0.1:3001
- Portainer: http://10.8.0.1:9000
- Redis Insight: http://10.8.0.1:8001
---
## Troubleshooting
### Problem: Keine Verbindung zum Server
**Symptome**:
- `ping 10.8.0.1` timeout
- WireGuard Status zeigt "Handshake failed"
**Lösungen**:
1. **Server Endpoint prüfen**:
```bash
# Prüfe ob Server erreichbar ist
ping 94.16.110.151
# Prüfe ob Port 51820 offen ist
nc -zvu 94.16.110.151 51820
```
2. **Firewall auf Server prüfen**:
```bash
# Auf Server ausführen
sudo nft list ruleset | grep 51820
```
3. **WireGuard Server Status prüfen**:
```bash
# Auf Server ausführen
sudo systemctl status wg-quick@wg0
sudo wg show wg0
```
---
### Problem: VPN verbindet, aber kein Zugriff auf Admin Services
**Symptome**:
- `ping 10.8.0.1` funktioniert
- `curl http://10.8.0.1:9090` timeout
**Lösungen**:
1. **Routing prüfen**:
```bash
# Auf Client
ip route | grep 10.8.0
```
2. **Firewall-Rules auf Server prüfen**:
```bash
# Auf Server
sudo nft list table inet wireguard_firewall
```
3. **Service-Status prüfen**:
```bash
# Auf Server - Services sollten laufen
docker ps | grep prometheus
docker ps | grep grafana
```
---
### Problem: DNS funktioniert nicht
**Symptome**:
- Kann keine Domains auflösen
**Lösung**:
```bash
# DNS-Server in Client-Config prüfen
grep DNS /etc/wireguard/michael-pc.conf
# Sollte sein: DNS = 1.1.1.1, 8.8.8.8
# DNS-Resolver testen
nslookup google.com 1.1.1.1
```
---
### Problem: Verbindung bricht ständig ab
**Symptome**:
- Verbindung disconnected nach einigen Minuten
**Lösungen**:
1. **PersistentKeepalive prüfen**:
```bash
grep PersistentKeepalive /etc/wireguard/michael-pc.conf
# Sollte sein: PersistentKeepalive = 25
```
2. **NAT/Router-Timeout**:
- PersistentKeepalive verhindert NAT-Timeout
- Wert auf 25 Sekunden gesetzt
---
## Firewall-Validierung
### Public Access sollte blockiert sein
**Von außerhalb des VPNs testen** (z.B. vom Internet):
```bash
# Diese Requests sollten FEHLSCHLAGEN (timeout oder connection refused):
curl --max-time 5 http://94.16.110.151:9090 # Prometheus
curl --max-time 5 http://94.16.110.151:8080 # Traefik Dashboard
curl --max-time 5 http://94.16.110.151:9000 # Portainer
# Nur Public Services sollten erreichbar sein:
curl http://94.16.110.151:80 # HTTP (funktioniert)
curl https://94.16.110.151:443 # HTTPS (funktioniert)
```
**Erwartetes Ergebnis**:
- ❌ Admin-Ports (8080, 9090, 3001, 9000, 8001): Timeout oder Connection Refused
- ✅ Public-Ports (80, 443): Erreichbar
### Firewall-Logs prüfen
**Auf Server**:
```bash
# Geblockte Zugriffe auf Admin-Services loggen
sudo journalctl -k | grep "BLOCKED_ADMIN_SERVICE"
# Beispiel-Ausgabe:
# [ 123.456] BLOCKED_ADMIN_SERVICE: IN=eth0 OUT= SRC=203.0.113.42 DST=94.16.110.151 PROTO=TCP DPT=8080
```
---
## Sicherheitshinweise
### ✅ Best Practices
1. **Private Keys schützen**:
- Niemals Private Keys committen oder teilen
- Berechtigungen: `chmod 600` für .conf Dateien
2. **Regelmäßige Key-Rotation**:
- Empfohlen: Jährlich neue Keys generieren
- Bei Kompromittierung: Sofort neue Keys erstellen
3. **Client-Zugriff widerrufen**:
```bash
# Auf Server: Peer aus Konfiguration entfernen
sudo nano /etc/wireguard/wg0.conf
# [Peer]-Block für michael-pc entfernen
# WireGuard neu laden
sudo wg syncconf wg0 <(wg-quick strip wg0)
```
4. **VPN-Monitoring**:
```bash
# Aktive Verbindungen prüfen
sudo wg show wg0
# Letzte Handshake-Zeit prüfen
sudo wg show wg0 latest-handshakes
```
---
## Nächste Schritte
Nach erfolgreicher VPN-Verbindung:
1. ✅ **VPN-Zugriff verifizieren**: Gateway ping + Admin Services Zugriff
2. ✅ **Firewall-Rules validieren**: Public Access blockiert, VPN Access erlaubt
3. ⏭️ **Weitere Clients hinzufügen** (optional):
```bash
ansible-playbook playbooks/generate-wireguard-client.yml -e "client_name=laptop"
ansible-playbook playbooks/generate-wireguard-client.yml -e "client_name=phone"
```
4. ⏭️ **Backup der Client-Configs**:
```bash
# Configs sind in .gitignore - manuelles Backup notwendig
tar -czf wireguard-client-configs-backup-$(date +%Y%m%d).tar.gz \
/home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/
```
---
**Erstellt**: 2025-11-05
**Client Config**: michael-pc (10.8.0.2/32)
**Server Endpoint**: 94.16.110.151:51820
**VPN Network**: 10.8.0.0/24

View File

@@ -0,0 +1,259 @@
# WireGuard Setup - Dokumentations-Index
Kompletter Index aller Dokumentation und Scripts für das minimalistic WireGuard Setup.
## 📚 Dokumentation
### Haupt-Dokumentation
| Datei | Zweck | Zielgruppe |
|-------|-------|------------|
| **README.md** | Vollständige Dokumentation mit Architektur, Setup, Troubleshooting | Alle Nutzer |
| **QUICKSTART.md** | 5-Minuten Quick Start Guide | Neue Nutzer |
| **INSTALLATION-LOG.md** | Schritt-für-Schritt Installations-Log | Systemadministratoren |
| **INDEX.md** (diese Datei) | Übersicht aller Dateien | Navigation |
### Client-Dokumentation
| Datei | Zweck |
|-------|-------|
| **configs/README.md** | Client Config Verzeichnis Dokumentation und Sicherheitshinweise |
| **configs/.gitignore** | Verhindert Commit von sensitiven Client Configs |
## 🛠️ Scripts
### Setup Scripts
| Script | Zweck | Ausführung |
|--------|-------|------------|
| **scripts/manual-wireguard-setup.sh** | Manuelles Setup-Script für Host-Installation | `sudo ./manual-wireguard-setup.sh` |
| **scripts/generate-client-config.sh** | Client Config Generator mit QR Codes | `sudo ./generate-client-config.sh <client-name>` |
| **scripts/cleanup-old-wireguard.sh** | Cleanup des alten Docker-basierten Setups | `sudo ./cleanup-old-wireguard.sh` |
### Ansible Automation
| Datei | Zweck |
|-------|-------|
| **ansible/playbooks/setup-wireguard-host.yml** | Vollständiges Ansible Playbook für automatisches Deployment |
| **ansible/templates/wg0.conf.j2** | WireGuard Server Config Template |
| **ansible/templates/wireguard-host-firewall.nft.j2** | nftables Firewall Rules Template |
## 🚀 Quick Start - Welche Datei nutzen?
### Für Anfänger: QUICKSTART.md
```bash
cat deployment/wireguard/QUICKSTART.md
```
- 5-Minuten Setup
- Einfache Schritt-für-Schritt Anleitung
- Für Linux, Windows, macOS, iOS, Android
### Für Erfahrene: README.md
```bash
cat deployment/wireguard/README.md
```
- Vollständige Architektur-Übersicht
- Detaillierte Konfigurationsoptionen
- Troubleshooting-Guide
- Sicherheits-Best-Practices
### Für Automatisierung: Ansible
```bash
cd deployment/ansible
ansible-playbook playbooks/setup-wireguard-host.yml
```
- Vollautomatisches Deployment
- Idempotent und wiederholbar
- Backup und Rollback-Support
### Für manuelle Installation: manual-wireguard-setup.sh
```bash
cd deployment/scripts
sudo ./manual-wireguard-setup.sh
```
- Interaktives Setup
- Zeigt alle Schritte
- Verifikation nach jedem Schritt
## 📋 Installations-Workflow
### Methode 1: Automatisiert (Empfohlen)
```bash
# 1. Cleanup altes Setup (falls vorhanden)
cd deployment/scripts
sudo ./cleanup-old-wireguard.sh
# 2. Automatisches Deployment
cd ../ansible
ansible-playbook playbooks/setup-wireguard-host.yml
# 3. Client Config generieren
cd ../scripts
sudo ./generate-client-config.sh michael-laptop
# 4. Client verbinden und testen
# (Siehe QUICKSTART.md)
```
### Methode 2: Manuell
```bash
# 1. Setup-Script ausführen
cd deployment/scripts
sudo ./manual-wireguard-setup.sh
# 2. INSTALLATION-LOG.md durchgehen
cat ../wireguard/INSTALLATION-LOG.md
# 3. Client Config generieren
sudo ./generate-client-config.sh michael-laptop
# 4. Client verbinden und testen
# (Siehe QUICKSTART.md)
```
## 🔍 Nach Installation
### Verifikation
```bash
# WireGuard Status
sudo wg show wg0
# Service Status
sudo systemctl status wg-quick@wg0
# Firewall Rules
sudo nft list table inet wireguard_firewall
# IP Forwarding
cat /proc/sys/net/ipv4/ip_forward
```
### Client Zugriff testen
Nach VPN-Verbindung:
```bash
# VPN-Gateway ping
ping 10.8.0.1
# Admin Services
curl -k https://10.8.0.1:8080 # Traefik Dashboard
curl http://10.8.0.1:9090 # Prometheus
curl https://10.8.0.1:3001 # Grafana
curl http://10.8.0.1:9000 # Portainer
curl http://10.8.0.1:8001 # Redis Insight
```
## 🛡️ Sicherheit
### Vor Deployment lesen
1. **README.md → Security Architecture**
- Defense in Depth Strategie
- Zero Trust Network Prinzipien
- Moderne Kryptographie
2. **README.md → Security Best Practices**
- Key Rotation
- Client Config Sicherung
- Firewall Monitoring
3. **configs/.gitignore**
- Client Configs NIEMALS committen
- Private Keys schützen
## 📊 Monitoring & Troubleshooting
### Logs überwachen
```bash
# WireGuard Service Logs
sudo journalctl -u wg-quick@wg0 -f
# Firewall Block Logs
sudo journalctl -k | grep "BLOCKED"
# System Logs
sudo dmesg | grep wireguard
```
### Häufige Probleme
Siehe **README.md → Troubleshooting Section** für:
- Connection refused
- Firewall blockiert Zugriff
- Routing-Probleme
- Performance-Issues
## 🔄 Wartung
### Regelmäßige Tasks
```bash
# Client Config generieren (neue Geräte)
cd deployment/scripts
sudo ./generate-client-config.sh <device-name>
# Client revoken
# (Siehe README.md → Revoke Client Access)
# Backup durchführen
tar -czf wireguard-backup-$(date +%Y%m%d).tar.gz /etc/wireguard/
# Firewall Rules updaten
# (Siehe README.md → Firewall Configuration)
```
### Updates
```bash
# WireGuard Update
sudo apt update && sudo apt upgrade wireguard wireguard-tools
# Konfiguration reload
sudo systemctl reload wg-quick@wg0
# Oder restart
sudo systemctl restart wg-quick@wg0
```
## 📖 Weitere Ressourcen
### Externe Dokumentation
- [WireGuard Official Docs](https://www.wireguard.com/)
- [nftables Wiki](https://wiki.nftables.org/)
- [systemd Documentation](https://www.freedesktop.org/software/systemd/man/)
### Framework Integration
- **Event System**: WireGuard-Events können über Framework Event System geloggt werden
- **Monitoring**: Integration mit Framework Performance Monitoring
- **Alerts**: Benachrichtigungen bei VPN-Problemen über Framework Alert System
## 🎯 Nächste Schritte (Phase 2 - Optional)
Falls DNS gewünscht:
1. **CoreDNS Minimal Setup**
- Siehe User's CoreDNS Konfigurationsbeispiel
- Integration mit WireGuard
- `.internal` Domain für Services
2. **Service Discovery**
- Automatische DNS-Einträge für Docker Services
- Load Balancing über DNS
3. **Monitoring**
- DNS Query Logs
- Performance Metriken
---
**Erstellt**: 2025-11-05
**Framework Version**: 2.x
**WireGuard Version**: 1.0.20210914
**Zielplattform**: Debian/Ubuntu Linux mit systemd

View File

@@ -0,0 +1,275 @@
# WireGuard Installation Log
Dokumentation der manuellen WireGuard Installation auf dem Host-System.
## Systemumgebung
```bash
# System prüfen
uname -a
# Linux hostname 6.6.87.2-microsoft-standard-WSL2 #1 SMP ...
# WireGuard Version
wg --version
# wireguard-tools v1.0.20210914
# Netzwerk Interface
ip addr show
# Haupt-Interface für WAN: eth0
```
## Installation durchgeführt am
**Datum**: [WIRD BEIM AUSFÜHREN GESETZT]
**Benutzer**: root (via sudo)
**Methode**: Manual Setup Script
## Installationsschritte
### ✅ Schritt 1: Verzeichnis erstellen
```bash
sudo mkdir -p /etc/wireguard
sudo chmod 700 /etc/wireguard
```
**Status**: Bereit für Ausführung
**Zweck**: Sicheres Verzeichnis für WireGuard-Konfiguration
### ✅ Schritt 2: Server Keys generieren
```bash
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
sudo chmod 600 server_private.key
sudo chmod 644 server_public.key
```
**Status**: Bereit für Ausführung
**Zweck**: Kryptographische Schlüssel für Server generieren
**Ausgabe**:
- `server_private.key` - Privater Schlüssel (geheim!)
- `server_public.key` - Öffentlicher Schlüssel (für Clients)
### ✅ Schritt 3: WireGuard Konfiguration erstellen
**Datei**: `/etc/wireguard/wg0.conf`
```ini
[Interface]
# Server Configuration
PrivateKey = [GENERATED_SERVER_PRIVATE_KEY]
Address = 10.8.0.1/24
ListenPort = 51820
# Enable IP forwarding
PostUp = sysctl -w net.ipv4.ip_forward=1
# NAT Configuration with nftables
PostUp = nft add table inet wireguard
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
PostUp = nft add rule inet wireguard postrouting oifname "eth0" ip saddr 10.8.0.0/24 masquerade
# Cleanup on shutdown
PostDown = nft delete table inet wireguard
# Peers will be added here via generate-client-config.sh
```
**Status**: Template erstellt
**Permissions**: `chmod 600 /etc/wireguard/wg0.conf`
### ✅ Schritt 4: nftables Firewall Rules
**Datei**: `/etc/nftables.d/wireguard.nft`
Features:
- VPN Network Set: `10.8.0.0/24`
- Admin Service Ports: `8080, 9090, 3001, 9000, 8001`
- Public Service Ports: `80, 443, 22`
- Rate Limiting für SSH: `10/minute`
- Logging für blockierte Zugriffe
**Status**: Template erstellt
**Anwendung**: `sudo nft -f /etc/nftables.d/wireguard.nft`
### ✅ Schritt 5: IP Forwarding aktivieren
```bash
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
```
**Status**: Bereit für Ausführung
**Zweck**: Ermöglicht Paket-Weiterleitung zwischen VPN und Host-Netzwerk
### ✅ Schritt 6: WireGuard Service aktivieren
```bash
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
```
**Status**: Bereit für Ausführung
**Zweck**: WireGuard als systemd Service starten und bei Boot aktivieren
## Verifikation
### WireGuard Status prüfen
```bash
sudo wg show wg0
# Erwartete Ausgabe:
# interface: wg0
# public key: [SERVER_PUBLIC_KEY]
# private key: (hidden)
# listening port: 51820
```
### Service Status prüfen
```bash
sudo systemctl status wg-quick@wg0
# Erwartete Ausgabe:
# ● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
# Loaded: loaded
# Active: active (exited) since ...
```
### nftables Rules prüfen
```bash
sudo nft list table inet wireguard_firewall
# Sollte alle Rules anzeigen
```
### Netzwerk-Konnektivität prüfen
```bash
# Interface prüfen
ip addr show wg0
# Sollte 10.8.0.1/24 zeigen
# Routing prüfen
ip route | grep wg0
# Sollte Route für 10.8.0.0/24 zeigen
# Firewall prüfen
sudo nft list ruleset | grep wireguard
```
## Nächste Schritte
### 1. Client-Konfiguration generieren
```bash
cd /home/michael/dev/michaelschiemer/deployment/scripts
sudo ./generate-client-config.sh michael-laptop
```
### 2. Client-Config importieren
- **Linux/macOS**: Copy `.conf` file to `/etc/wireguard/`
- **Windows**: Import via WireGuard GUI
- **iOS/Android**: Scan QR code
### 3. Verbindung testen
```bash
# Vom Client aus:
ping 10.8.0.1
# Admin-Services testen:
curl -k https://10.8.0.1:8080 # Traefik Dashboard
curl http://10.8.0.1:9090 # Prometheus
```
## Troubleshooting
### WireGuard startet nicht
```bash
# Logs prüfen
sudo journalctl -u wg-quick@wg0 -f
# Konfiguration prüfen
sudo wg-quick up wg0
```
### Keine Verbindung möglich
```bash
# Port prüfen
sudo ss -ulnp | grep 51820
# Firewall prüfen
sudo nft list ruleset | grep 51820
# IP Forwarding prüfen
cat /proc/sys/net/ipv4/ip_forward
# Sollte "1" sein
```
### Client kann keine Admin-Services erreichen
```bash
# nftables Rules prüfen
sudo nft list table inet wireguard_firewall
# VPN-Routing prüfen
ip route show table main | grep wg0
# NAT prüfen
sudo nft list chain inet wireguard postrouting
```
## Rollback-Prozedur
Falls etwas schiefgeht:
```bash
# WireGuard stoppen
sudo systemctl stop wg-quick@wg0
sudo systemctl disable wg-quick@wg0
# nftables Rules entfernen
sudo nft delete table inet wireguard_firewall
sudo nft delete table inet wireguard
# Konfiguration entfernen
sudo rm -rf /etc/wireguard/*
sudo rm /etc/nftables.d/wireguard.nft
# IP Forwarding zurücksetzen
sudo rm /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p
```
## Sicherheitshinweise
- ✅ Private Keys niemals committen oder teilen
- ✅ Regelmäßige Key-Rotation (empfohlen: jährlich)
- ✅ Client-Configs nach Generierung sicher speichern
- ✅ Firewall-Logs regelmäßig überprüfen
- ✅ VPN-Zugriffe monitoren
## Performance-Metriken
Nach Installation zu überwachen:
- CPU-Auslastung: WireGuard ist sehr effizient (<5% bei normaler Last)
- Netzwerk-Durchsatz: Nahezu Leitungsgeschwindigkeit
- Latenz: Minimal (+1-2ms Overhead)
- Speicher: ~10MB RAM für WireGuard-Prozess
## Status
**Installation Status**: ⏳ BEREIT FÜR AUSFÜHRUNG
**Nächster Schritt**: Script ausführen mit:
```bash
cd /home/michael/dev/michaelschiemer/deployment/scripts
sudo ./manual-wireguard-setup.sh
```
**Oder manuell durchführen**: Jeden Schritt einzeln wie oben dokumentiert ausführen.

View File

@@ -0,0 +1,194 @@
# WireGuard VPN - Quick Start Guide
Minimalistisches Host-based WireGuard Setup in 5 Minuten.
## Prerequisites
- Debian/Ubuntu Server mit Root-Zugriff
- Public IP oder DynDNS
- Ports 51820/udp offen in Firewall/Router
## Installation (Server)
### Option 1: Automated (Ansible) - Empfohlen
```bash
# 1. Cleanup altes Docker-Setup (falls vorhanden)
cd /home/michael/dev/michaelschiemer/deployment/scripts
sudo ./cleanup-old-wireguard.sh
# 2. Deploy WireGuard Host-based
cd /home/michael/dev/michaelschiemer/deployment/ansible
ansible-playbook playbooks/setup-wireguard-host.yml
# 3. Verify Installation
sudo wg show wg0
sudo systemctl status wg-quick@wg0
```
### Option 2: Manual Installation
```bash
# Install WireGuard
sudo apt update
sudo apt install wireguard wireguard-tools qrencode nftables
# Generate Server Keys
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
# Create Config (replace YOUR_SERVER_IP)
sudo tee /etc/wireguard/wg0.conf <<EOF
[Interface]
PrivateKey = $(sudo cat server_private.key)
Address = 10.8.0.1/24
ListenPort = 51820
PostUp = sysctl -w net.ipv4.ip_forward=1
EOF
# Enable and Start
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
# Apply Firewall
# See: deployment/ansible/templates/wireguard-host-firewall.nft.j2
```
## Client Setup
### Generate Client Config
```bash
# On server
cd /home/michael/dev/michaelschiemer/deployment/scripts
sudo ./generate-client-config.sh michael-laptop
# Script outputs:
# - Config file: ../wireguard/configs/michael-laptop.conf
# - QR code (text): ../wireguard/configs/michael-laptop.qr.txt
# - QR code (PNG): ../wireguard/configs/michael-laptop.qr.png
```
### Import on Client
**Linux/macOS:**
```bash
# Copy config to client
scp server:/path/to/michael-laptop.conf /etc/wireguard/
# Connect
sudo wg-quick up michael-laptop
# Verify
ping 10.8.0.1
curl -k https://10.8.0.1:8080 # Traefik Dashboard
```
**Windows:**
1. Download WireGuard from https://www.wireguard.com/install/
2. Open WireGuard GUI
3. Click "Import tunnel(s) from file"
4. Select `michael-laptop.conf`
5. Click "Activate"
**iOS/Android:**
1. Install WireGuard app from App Store/Play Store
2. Tap "+" → "Create from QR code"
3. Scan QR code (shown in terminal or PNG file)
4. Tap "Activate"
## Service Access
Nach VPN-Verbindung sind folgende Services erreichbar:
| Service | URL | Purpose |
|---------|-----|---------|
| Traefik Dashboard | https://10.8.0.1:8080 | Reverse Proxy Management |
| Prometheus | http://10.8.0.1:9090 | Metrics Collection |
| Grafana | https://10.8.0.1:3001 | Monitoring Dashboards |
| Portainer | http://10.8.0.1:9000 | Docker Management |
| Redis Insight | http://10.8.0.1:8001 | Redis Debugging |
## Verification
```bash
# On Client after connecting VPN
# Test VPN connectivity
ping 10.8.0.1
# Test service access
curl -k https://10.8.0.1:8080 # Traefik Dashboard (should return HTML)
curl http://10.8.0.1:9090 # Prometheus (should return HTML)
# Check routing
ip route | grep 10.8.0.0
# Verify WireGuard interface
sudo wg show
```
## Troubleshooting
### Cannot connect to VPN
```bash
# On Server
sudo wg show wg0 # Check if interface exists
sudo systemctl status wg-quick@wg0 # Check if service running
sudo ss -ulnp | grep 51820 # Check if listening on port
# Check firewall allows WireGuard port
sudo nft list ruleset | grep 51820
# View logs
sudo journalctl -u wg-quick@wg0 -f
```
### VPN connected but cannot access services
```bash
# On Client
ping 10.8.0.1 # Should work
# On Server
sudo nft list ruleset | grep "10.8.0.0" # Check VPN network allowed
# Check service is listening
sudo ss -tlnp | grep 8080 # Traefik Dashboard
sudo docker ps # Check containers running
```
### Slow connection
```bash
# Check MTU settings (on client)
sudo wg show michael-laptop
# Try reducing MTU if packet loss
# Edit config: MTU = 1420 (in [Interface] section)
```
## Security
- ✅ All admin services **only** accessible via VPN
- ✅ Public ports limited to 80, 443, 22
- ✅ Modern crypto (ChaCha20, Poly1305)
- ✅ Preshared keys for quantum resistance
- ✅ nftables firewall with explicit rules
## Next Steps
- [ ] Add more clients: `sudo ./generate-client-config.sh <device-name>`
- [ ] Setup monitoring alerts for VPN
- [ ] Optional: Add minimal CoreDNS for `.internal` domains
- [ ] Schedule key rotation (recommended: annually)
## Support
Full documentation: `deployment/wireguard/README.md`
For issues, check:
- `sudo journalctl -u wg-quick@wg0`
- `sudo dmesg | grep wireguard`
- `sudo nft list ruleset`

View File

@@ -0,0 +1,352 @@
# Minimalistic WireGuard VPN Setup
**Purpose**: Secure admin access to internal services (Traefik Dashboard, Prometheus, Grafana, etc.)
**Architecture**: Host-based WireGuard with IP-based service access (no DNS required)
## Overview
```
Public Internet
┌─────────────────────────────────────────┐
│ Server (Public IP) │
│ │
│ Public Ports: │
│ 80/443 → Traefik (Public Apps) │
│ 22 → SSH │
│ 51820 → WireGuard │
│ │
│ VPN Network (10.8.0.0/24): │
│ 10.8.0.1 → Server (VPN Gateway) │
│ │
│ Admin Services (VPN-only): │
│ https://10.8.0.1:8080 → Traefik │
│ http://10.8.0.1:9090 → Prometheus │
│ https://10.8.0.1:3001 → Grafana │
│ http://10.8.0.1:9000 → Portainer │
│ http://10.8.0.1:8001 → Redis Insight│
│ │
└─────────────────────────────────────────┘
```
## Components
### 1. WireGuard (Host-based)
- **Interface**: wg0
- **Server IP**: 10.8.0.1/24
- **Port**: 51820/udp
- **Management**: systemd + wg-quick
### 2. nftables Firewall
- **VPN Access**: 10.8.0.0/24 → All admin services
- **Public Access**: Only ports 80, 443, 22
- **Default Policy**: DROP all other traffic
### 3. Service Access (IP-based)
| Service | URL | Purpose |
|---------|-----|---------|
| Traefik Dashboard | https://10.8.0.1:8080 | Reverse Proxy Management |
| Prometheus | http://10.8.0.1:9090 | Metrics Collection |
| Grafana | https://10.8.0.1:3001 | Monitoring Dashboards |
| Portainer | http://10.8.0.1:9000 | Docker Management |
| Redis Insight | http://10.8.0.1:8001 | Redis Debugging |
## Quick Start
### Server Setup (Automated)
```bash
# Deploy WireGuard + Firewall
cd deployment/ansible
ansible-playbook playbooks/setup-wireguard-host.yml
```
### Client Setup
```bash
# Generate new client config
cd deployment/scripts
./generate-client-config.sh michael-laptop
# Import config (Linux/macOS)
sudo wg-quick up ./configs/michael-laptop.conf
# Import config (Windows)
# 1. Open WireGuard GUI
# 2. Import Tunnel from File
# 3. Select ./configs/michael-laptop.conf
# Import config (iOS/Android)
# Scan QR code generated by script
```
### Verify Connection
```bash
# Check VPN connection
ping 10.8.0.1
# Access Traefik Dashboard
curl -k https://10.8.0.1:8080
```
## Manual Server Setup
If you prefer manual installation:
### 1. Install WireGuard
```bash
# Ubuntu/Debian
sudo apt update
sudo apt install wireguard wireguard-tools qrencode
# Check kernel module
sudo modprobe wireguard
lsmod | grep wireguard
```
### 2. Generate Server Keys
```bash
# Create config directory
sudo mkdir -p /etc/wireguard
cd /etc/wireguard
# Generate keys
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
# Save keys
SERVER_PRIVATE_KEY=$(cat server_private.key)
SERVER_PUBLIC_KEY=$(cat server_public.key)
```
### 3. Create Server Config
```bash
sudo tee /etc/wireguard/wg0.conf <<EOF
[Interface]
PrivateKey = $SERVER_PRIVATE_KEY
Address = 10.8.0.1/24
ListenPort = 51820
# Firewall: Allow VPN traffic forwarding
PostUp = nft add table inet wireguard
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
PostUp = nft add chain inet wireguard forward { type filter hook forward priority filter\; }
PostUp = nft add rule inet wireguard postrouting oifname "eth0" ip saddr 10.8.0.0/24 masquerade
PostUp = nft add rule inet wireguard forward iifname "wg0" accept
PostUp = nft add rule inet wireguard forward oifname "wg0" ct state established,related accept
PostDown = nft delete table inet wireguard
# Peers will be added here
EOF
# Secure permissions
sudo chmod 600 /etc/wireguard/wg0.conf
```
### 4. Enable WireGuard
```bash
# Enable IP forwarding
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Start WireGuard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
# Check status
sudo wg show
sudo systemctl status wg-quick@wg0
```
### 5. Apply Firewall Rules
See `deployment/ansible/templates/wireguard-firewall.nft.j2` for complete firewall configuration.
```bash
# Allow WireGuard port
sudo nft add rule inet filter input udp dport 51820 accept
# Allow VPN network to access admin services
sudo nft add rule inet filter input ip saddr 10.8.0.0/24 tcp dport { 8080, 9090, 3001, 9000, 8001 } accept
# Block public access to admin services
sudo nft add rule inet filter input tcp dport { 8080, 9090, 3001, 9000, 8001 } drop
```
## Client Configuration
### Generate Client
```bash
# Generate client keys
umask 077
wg genkey | tee client_private.key | wg pubkey > client_public.key
wg genpsk > client_preshared.key
CLIENT_PRIVATE_KEY=$(cat client_private.key)
CLIENT_PUBLIC_KEY=$(cat client_public.key)
CLIENT_PSK=$(cat client_preshared.key)
```
### Add Client to Server
```bash
# Add peer to server config
sudo tee -a /etc/wireguard/wg0.conf <<EOF
[Peer]
# michael-laptop
PublicKey = $CLIENT_PUBLIC_KEY
PresharedKey = $CLIENT_PSK
AllowedIPs = 10.8.0.2/32
EOF
# Reload WireGuard
sudo systemctl reload wg-quick@wg0
```
### Create Client Config File
```bash
# Create client config
cat > michael-laptop.conf <<EOF
[Interface]
PrivateKey = $CLIENT_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 1.1.1.1, 9.9.9.9
[Peer]
PublicKey = $SERVER_PUBLIC_KEY
PresharedKey = $CLIENT_PSK
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
EOF
```
## Troubleshooting
### VPN Not Connecting
```bash
# Check WireGuard status
sudo wg show
# Check firewall
sudo nft list ruleset | grep 51820
# Check logs
sudo journalctl -u wg-quick@wg0 -f
# Test connectivity
ping 10.8.0.1 # From client
```
### Cannot Access Services
```bash
# Verify firewall allows VPN network
sudo nft list ruleset | grep "10.8.0.0"
# Check service is listening
sudo ss -tlnp | grep 8080 # Traefik Dashboard
# Test from VPN
curl -k https://10.8.0.1:8080 # From client
```
### Key Rotation
Recommended: Rotate keys annually
```bash
# Generate new server keys
cd /etc/wireguard
wg genkey | tee server_private_new.key | wg pubkey > server_public_new.key
# Update server config
# ... update PrivateKey in wg0.conf
# Regenerate all client configs with new server PublicKey
# ... update clients
# Restart WireGuard
sudo systemctl restart wg-quick@wg0
```
## Security Best Practices
### 1. Strong Cryptography
- ✅ WireGuard uses modern crypto (ChaCha20, Poly1305, Curve25519)
- ✅ Preshared keys for quantum resistance
- ✅ Perfect forward secrecy
### 2. Firewall Isolation
- ✅ Admin services only accessible via VPN
- ✅ Explicit ALLOW rules, default DROP
- ✅ Rate limiting on VPN port (optional)
### 3. Key Management
- ✅ Private keys never leave server/client
- ✅ Preshared keys for each peer
- ✅ Annual key rotation recommended
### 4. Monitoring
- ✅ Log all VPN connections
- ✅ Alert on unusual traffic patterns
- ✅ Regular security audits
## Performance
- **Latency Overhead**: <1ms (kernel-native)
- **Throughput**: Near-native (minimal encryption overhead)
- **Concurrent Peers**: 10-20 recommended
- **Keepalive**: 25 seconds (NAT traversal)
## Maintenance
### Add New Client
```bash
./deployment/scripts/generate-client-config.sh new-device-name
```
### Remove Client
```bash
# Edit server config
sudo nano /etc/wireguard/wg0.conf
# Remove [Peer] section
# Reload
sudo systemctl reload wg-quick@wg0
```
### Backup Configuration
```bash
# Backup keys and configs
sudo tar -czf wireguard-backup-$(date +%Y%m%d).tar.gz /etc/wireguard/
```
## Next Steps
- [ ] Deploy WireGuard on server
- [ ] Generate client configs for all devices
- [ ] Test VPN connectivity
- [ ] Verify admin service access
- [ ] Optional: Add minimal CoreDNS for `.internal` domains (Phase 2)
## Support
- **WireGuard Docs**: https://www.wireguard.com/quickstart/
- **nftables Wiki**: https://wiki.nftables.org/
- **Framework Issues**: https://github.com/your-repo/issues

11
deployment/wireguard/configs/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
# WireGuard Client Configurations
# These contain private keys and should NEVER be committed!
*.conf
*.key
*.qr.txt
*.qr.png
# Allow README
!README.md
!.gitignore

View File

@@ -0,0 +1,47 @@
# WireGuard Client Configurations
This directory stores generated client configuration files.
## Security Notice
⚠️ **NEVER commit client configs to Git!**
Client configs contain:
- Private keys
- Preshared keys
- Network topology information
`.gitignore` is configured to exclude all `.conf`, `.key`, `.qr.txt`, and `.qr.png` files.
## Generate New Client
```bash
cd ../../scripts
sudo ./generate-client-config.sh <device-name>
```
Configs will be created here:
- `<device-name>.conf` - WireGuard configuration
- `<device-name>.qr.txt` - QR code (ASCII)
- `<device-name>.qr.png` - QR code (PNG)
## Backup Client Configs
```bash
# Securely backup configs (encrypted)
tar -czf - *.conf | gpg --symmetric --cipher-algo AES256 -o wireguard-clients-backup-$(date +%Y%m%d).tar.gz.gpg
```
## Revoke Client Access
```bash
# On server
sudo nano /etc/wireguard/wg0.conf
# Remove [Peer] section for client
# Reload WireGuard
sudo systemctl reload wg-quick@wg0
# Delete client config
rm <device-name>.*
```