Files
michaelschiemer/deployment/ansible/playbooks/setup-wireguard-host.yml
Michael Schiemer 95147ff23e 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.
2025-11-05 12:48:25 +01:00

310 lines
9.1 KiB
YAML

---
# 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