287 lines
8.9 KiB
YAML
Executable File
287 lines
8.9 KiB
YAML
Executable File
---
|
|
- name: Setup WireGuard VPN Server
|
|
hosts: production
|
|
become: yes
|
|
gather_facts: yes
|
|
|
|
vars:
|
|
# WireGuard variables are defined in group_vars/production.yml
|
|
# Can be overridden via -e flag if needed
|
|
wireguard_port: "{{ wireguard_port_default | default(51820) }}"
|
|
wireguard_network: "{{ wireguard_network_default | default('10.8.0.0/24') }}"
|
|
wireguard_server_ip: "{{ wireguard_server_ip_default | default('10.8.0.1') }}"
|
|
|
|
pre_tasks:
|
|
|
|
- name: Optionally load wireguard secrets from vault
|
|
include_vars:
|
|
file: "{{ playbook_dir }}/../secrets/production.vault.yml"
|
|
no_log: yes
|
|
ignore_errors: yes
|
|
delegate_to: localhost
|
|
become: no
|
|
|
|
tasks:
|
|
- name: Check if WireGuard is already installed
|
|
command: which wg
|
|
register: wireguard_installed
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Update package cache
|
|
apt:
|
|
update_cache: yes
|
|
cache_valid_time: 3600
|
|
when: not wireguard_installed.rc == 0
|
|
|
|
- name: Install WireGuard
|
|
apt:
|
|
name:
|
|
- wireguard
|
|
- wireguard-tools
|
|
- qrencode
|
|
state: present
|
|
when: not wireguard_installed.rc == 0
|
|
notify: restart wireguard
|
|
|
|
- name: Ensure WireGuard config directory exists
|
|
file:
|
|
path: "{{ wireguard_config_path }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Ensure WireGuard client configs directory exists
|
|
file:
|
|
path: "{{ wireguard_client_configs_path }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Check if WireGuard server keys exist
|
|
stat:
|
|
path: "{{ wireguard_private_key_file }}"
|
|
register: server_private_key_exists
|
|
|
|
- name: Generate WireGuard server private key
|
|
command: "wg genkey"
|
|
register: server_private_key
|
|
changed_when: true
|
|
when: not server_private_key_exists.stat.exists
|
|
no_log: yes
|
|
|
|
- name: Save WireGuard server private key
|
|
copy:
|
|
content: "{{ server_private_key.stdout }}"
|
|
dest: "{{ wireguard_private_key_file }}"
|
|
mode: '0600'
|
|
owner: root
|
|
group: root
|
|
when: not server_private_key_exists.stat.exists
|
|
no_log: yes
|
|
|
|
- name: Read WireGuard server private key
|
|
slurp:
|
|
src: "{{ wireguard_private_key_file }}"
|
|
register: server_private_key_content
|
|
when: server_private_key_exists.stat.exists
|
|
|
|
- name: Generate WireGuard server public key
|
|
command: "wg pubkey"
|
|
args:
|
|
stdin: "{{ server_private_key.stdout if not server_private_key_exists.stat.exists else server_private_key_content.content | b64decode | trim }}"
|
|
register: server_public_key
|
|
changed_when: false
|
|
when: not server_private_key_exists.stat.exists
|
|
no_log: yes
|
|
|
|
- name: Get existing server public key
|
|
shell: "cat {{ wireguard_private_key_file }} | wg pubkey"
|
|
register: existing_server_public_key
|
|
changed_when: false
|
|
when: server_private_key_exists.stat.exists
|
|
no_log: yes
|
|
failed_when: false
|
|
|
|
- name: Set server public key fact
|
|
set_fact:
|
|
server_public_key_value: "{{ server_public_key.stdout if not server_private_key_exists.stat.exists else existing_server_public_key.stdout }}"
|
|
|
|
- name: Save WireGuard server public key
|
|
copy:
|
|
content: "{{ server_public_key_value }}"
|
|
dest: "{{ wireguard_public_key_file }}"
|
|
mode: '0644'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Enable IP forwarding
|
|
sysctl:
|
|
name: net.ipv4.ip_forward
|
|
value: '1'
|
|
state: present
|
|
sysctl_set: yes
|
|
reload: yes
|
|
when: wireguard_enable_ip_forwarding
|
|
|
|
- name: Make IP forwarding persistent
|
|
lineinfile:
|
|
path: /etc/sysctl.conf
|
|
regexp: '^net\.ipv4\.ip_forward'
|
|
line: 'net.ipv4.ip_forward=1'
|
|
state: present
|
|
when: wireguard_enable_ip_forwarding
|
|
|
|
- name: Get server external IP address
|
|
uri:
|
|
url: https://api.ipify.org
|
|
return_content: yes
|
|
register: server_external_ip
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Set server external IP from inventory if API fails
|
|
set_fact:
|
|
server_external_ip_content: "{{ ansible_host | default(server_external_ip.content | default('')) }}"
|
|
when: server_external_ip.content is defined
|
|
|
|
- name: Get server external IP from ansible_host
|
|
set_fact:
|
|
server_external_ip_content: "{{ ansible_host }}"
|
|
when: server_external_ip.content is not defined
|
|
|
|
- name: Read server private key for config
|
|
slurp:
|
|
src: "{{ wireguard_private_key_file }}"
|
|
register: server_private_key_file_content
|
|
when: server_private_key_exists.stat.exists
|
|
|
|
- name: Set server private key for template (new key)
|
|
set_fact:
|
|
server_private_key_for_config: "{{ server_private_key.stdout }}"
|
|
when: not server_private_key_exists.stat.exists
|
|
|
|
- name: Set server private key for template (existing key)
|
|
set_fact:
|
|
server_private_key_for_config: "{{ server_private_key_file_content.content | b64decode | trim }}"
|
|
when: server_private_key_exists.stat.exists
|
|
|
|
- name: Get network interface name
|
|
shell: "ip route | grep default | awk '{print $5}' | head -1"
|
|
register: default_interface
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Set default interface
|
|
set_fact:
|
|
wireguard_interface_name: "{{ default_interface.stdout | default('eth0') }}"
|
|
|
|
- name: Check if WireGuard config exists
|
|
stat:
|
|
path: "{{ wireguard_config_file }}"
|
|
register: wireguard_config_exists
|
|
|
|
- name: Create WireGuard server configuration
|
|
template:
|
|
src: "{{ playbook_dir }}/../templates/wireguard-server.conf.j2"
|
|
dest: "{{ wireguard_config_file }}"
|
|
mode: '0600'
|
|
owner: root
|
|
group: root
|
|
notify: restart wireguard
|
|
|
|
- name: Check if WireGuard service is enabled
|
|
systemd:
|
|
name: "wg-quick@{{ wireguard_interface }}"
|
|
register: wireguard_service_status
|
|
failed_when: false
|
|
changed_when: false
|
|
|
|
- name: Enable WireGuard service
|
|
systemd:
|
|
name: "wg-quick@{{ wireguard_interface }}"
|
|
enabled: yes
|
|
daemon_reload: yes
|
|
when: not wireguard_service_status.status.ActiveState is defined or wireguard_service_status.status.ActiveState != 'active'
|
|
|
|
- name: Start WireGuard service
|
|
systemd:
|
|
name: "wg-quick@{{ wireguard_interface }}"
|
|
state: started
|
|
notify: restart wireguard
|
|
|
|
- name: Check if UFW firewall is installed
|
|
command: which ufw
|
|
register: ufw_installed
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Verify SSH access is allowed in UFW
|
|
command: "ufw status | grep -q '22/tcp' || echo 'SSH not found'"
|
|
register: ssh_ufw_check
|
|
changed_when: false
|
|
failed_when: false
|
|
when: ufw_installed.rc == 0
|
|
|
|
- name: Warn if SSH is not explicitly allowed
|
|
debug:
|
|
msg: |
|
|
?? WARNING: SSH (port 22) might not be explicitly allowed in UFW!
|
|
Please ensure SSH access is configured before proceeding.
|
|
Run: sudo ufw allow 22/tcp
|
|
when: ufw_installed.rc == 0 and 'SSH not found' in ssh_ufw_check.stdout
|
|
|
|
- name: Allow WireGuard port in UFW firewall
|
|
ufw:
|
|
rule: allow
|
|
port: "{{ wireguard_port }}"
|
|
proto: udp
|
|
comment: "WireGuard VPN"
|
|
when: ufw_installed.rc == 0
|
|
|
|
- name: Allow WireGuard port in UFW firewall (alternative)
|
|
shell: "ufw allow {{ wireguard_port }}/udp comment 'WireGuard VPN'"
|
|
when: ufw_installed.rc == 0
|
|
failed_when: false
|
|
changed_when: false
|
|
|
|
- name: Check WireGuard status
|
|
command: "wg show {{ wireguard_interface }}"
|
|
register: wireguard_status
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Display WireGuard status
|
|
debug:
|
|
msg: |
|
|
WireGuard Status:
|
|
{{ wireguard_status.stdout if wireguard_status.rc == 0 else 'WireGuard interface not active' }}
|
|
|
|
- name: Display server public key
|
|
debug:
|
|
msg: |
|
|
========================================
|
|
WireGuard Server Setup Complete!
|
|
========================================
|
|
|
|
Server Public Key:
|
|
{{ server_public_key_value }}
|
|
|
|
Server IP: {{ wireguard_server_ip }}
|
|
Server Endpoint: {{ server_external_ip_content }}:{{ wireguard_port }}
|
|
Network: {{ wireguard_network }}
|
|
|
|
To add a client, run:
|
|
ansible-playbook -i inventory/production.yml playbooks/add-wireguard-client.yml -e "client_name=myclient"
|
|
|
|
Client configs are stored in:
|
|
{{ wireguard_client_configs_path }}/
|
|
========================================
|
|
|
|
handlers:
|
|
- name: restart wireguard
|
|
systemd:
|
|
name: "wg-quick@{{ wireguard_interface }}"
|
|
state: restarted |