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.
310 lines
9.1 KiB
YAML
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
|