- Update Ansible playbooks and roles for application deployment - Add new Gitea/Traefik troubleshooting playbooks - Update Docker Compose configurations (base, local, staging, production) - Enhance EncryptedEnvLoader with improved error handling - Add deployment scripts (autossh setup, migration, secret testing) - Update CI/CD workflows and documentation - Add Semaphore stack configuration
206 lines
7.0 KiB
YAML
Executable File
206 lines
7.0 KiB
YAML
Executable File
---
|
|
- name: Add WireGuard Client
|
|
hosts: production
|
|
become: yes
|
|
gather_facts: yes
|
|
|
|
vars:
|
|
wireguard_interface: "wg0"
|
|
wireguard_config_path: "/etc/wireguard"
|
|
wireguard_config_file: "{{ wireguard_config_path }}/{{ wireguard_interface }}.conf"
|
|
wireguard_client_configs_path: "/etc/wireguard/clients"
|
|
wireguard_local_client_configs_dir: "{{ playbook_dir }}/../wireguard-clients"
|
|
wireguard_dns_servers: []
|
|
|
|
pre_tasks:
|
|
- name: Set WireGuard network
|
|
set_fact:
|
|
wireguard_network: "{{ wireguard_network | default('10.8.0.0/24') }}"
|
|
|
|
- name: Set WireGuard other variables with defaults
|
|
set_fact:
|
|
wireguard_port: "{{ wireguard_port | default(51820) }}"
|
|
client_ip: "{{ client_ip | default('') }}"
|
|
# IMPORTANT: Default to VPN network only (not 0.0.0.0/0)
|
|
# This ensures SSH access via normal IP remains available
|
|
allowed_ips: "{{ allowed_ips | default(wireguard_network) }}"
|
|
|
|
tasks:
|
|
- name: Validate client name
|
|
fail:
|
|
msg: "client_name is required. Usage: ansible-playbook ... -e 'client_name=myclient'"
|
|
when: client_name is not defined or client_name == ""
|
|
|
|
- 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
|
|
set_fact:
|
|
server_external_ip_content: "{{ ansible_host | default(server_external_ip.content | default('')) }}"
|
|
|
|
- name: Check if WireGuard config exists
|
|
stat:
|
|
path: "{{ wireguard_config_file }}"
|
|
register: wireguard_config_exists
|
|
|
|
- name: Fail if WireGuard not configured
|
|
fail:
|
|
msg: "WireGuard server not configured. Please run setup-wireguard.yml first."
|
|
when: not wireguard_config_exists.stat.exists
|
|
|
|
- name: Read WireGuard server config
|
|
slurp:
|
|
src: "{{ wireguard_config_file }}"
|
|
register: wireguard_server_config_read
|
|
|
|
- name: Extract server IP from config
|
|
set_fact:
|
|
server_vpn_ip: "{{ (wireguard_server_config_read.content | b64decode | regex_search('Address = ([0-9.]+)', '\\1')) | first | default('10.8.0.1') }}"
|
|
|
|
- name: Extract WireGuard server IP octets
|
|
set_fact:
|
|
wireguard_server_ip_octets: "{{ server_vpn_ip.split('.') }}"
|
|
when: client_ip == ""
|
|
|
|
- name: Gather existing client addresses
|
|
set_fact:
|
|
existing_client_ips: "{{ (wireguard_server_config_read.content | b64decode | regex_findall('AllowedIPs = ([0-9A-Za-z.]+)/32', '\\1')) }}"
|
|
when: client_ip == ""
|
|
|
|
- name: Calculate client IP if not provided
|
|
vars:
|
|
existing_last_octets: "{{ (existing_client_ips | default([])) | map('regex_replace', '^(?:\\d+\\.\\d+\\.\\d+\\.)', '') | select('match', '^[0-9]+$') | map('int') | list }}"
|
|
server_last_octet: "{{ wireguard_server_ip_octets[3] | int }}"
|
|
next_octet_candidate: "{{ (existing_last_octets + [server_last_octet]) | map('int') | list | max + 1 if (existing_last_octets + [server_last_octet]) else server_last_octet + 1 }}"
|
|
set_fact:
|
|
client_ip: "{{ [
|
|
wireguard_server_ip_octets[0],
|
|
wireguard_server_ip_octets[1],
|
|
wireguard_server_ip_octets[2],
|
|
next_octet_candidate
|
|
] | join('.') }}"
|
|
when: client_ip == ""
|
|
|
|
- name: Generate client private key
|
|
command: "wg genkey"
|
|
register: client_private_key
|
|
changed_when: true
|
|
no_log: yes
|
|
|
|
- name: Generate client public key
|
|
command: "wg pubkey"
|
|
args:
|
|
stdin: "{{ client_private_key.stdout }}"
|
|
register: client_public_key
|
|
changed_when: false
|
|
no_log: yes
|
|
|
|
- name: Add client to WireGuard server config
|
|
blockinfile:
|
|
path: "{{ wireguard_config_file }}"
|
|
block: |
|
|
# Client: {{ client_name }}
|
|
[Peer]
|
|
PublicKey = {{ client_public_key.stdout }}
|
|
AllowedIPs = {{ client_ip }}/32
|
|
marker: "# {mark} ANSIBLE MANAGED BLOCK - Client: {{ client_name }}"
|
|
register: wireguard_client_block
|
|
|
|
- name: Ensure client configs directory exists
|
|
file:
|
|
path: "{{ wireguard_client_configs_path }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Ensure local client configs directory exists
|
|
file:
|
|
path: "{{ wireguard_local_client_configs_dir }}"
|
|
state: directory
|
|
mode: '0700'
|
|
delegate_to: localhost
|
|
become: no
|
|
run_once: true
|
|
|
|
- name: Get server public key
|
|
shell: "cat {{ wireguard_config_path }}/{{ wireguard_interface }}_private.key | wg pubkey"
|
|
register: server_public_key_cmd
|
|
changed_when: false
|
|
no_log: yes
|
|
failed_when: false
|
|
|
|
- name: Create client configuration file
|
|
template:
|
|
src: "{{ playbook_dir }}/../templates/wireguard-client.conf.j2"
|
|
dest: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf"
|
|
mode: '0600'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Download client configuration to control machine
|
|
fetch:
|
|
src: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf"
|
|
dest: "{{ wireguard_local_client_configs_dir }}/{{ client_name }}.conf"
|
|
flat: yes
|
|
mode: '0600'
|
|
|
|
- name: Ensure local client configuration has strict permissions
|
|
file:
|
|
path: "{{ wireguard_local_client_configs_dir }}/{{ client_name }}.conf"
|
|
mode: '0600'
|
|
delegate_to: localhost
|
|
become: no
|
|
|
|
- name: Read WireGuard server config to find server IP
|
|
slurp:
|
|
src: "{{ wireguard_config_file }}"
|
|
register: wireguard_server_config_read
|
|
|
|
- name: Restart WireGuard service
|
|
systemd:
|
|
name: "wg-quick@{{ wireguard_interface }}"
|
|
state: restarted
|
|
when: wireguard_client_block.changed
|
|
|
|
- name: Display client configuration
|
|
debug:
|
|
msg: |
|
|
========================================
|
|
WireGuard Client Added: {{ client_name }}
|
|
========================================
|
|
|
|
Client Configuration File:
|
|
{{ wireguard_client_configs_path }}/{{ client_name }}.conf
|
|
|
|
Local Copy:
|
|
{{ wireguard_local_client_configs_dir }}/{{ client_name }}.conf
|
|
|
|
Client IP: {{ client_ip }}
|
|
Server Endpoint: {{ server_external_ip_content }}:{{ wireguard_port }}
|
|
|
|
To use this configuration:
|
|
1. Copy the config file to your client machine
|
|
2. Install WireGuard client
|
|
3. Run: sudo wg-quick up {{ client_name }}
|
|
|
|
Or scan the QR code (if qrencode installed):
|
|
qrencode -t ansiutf8 < {{ wireguard_client_configs_path }}/{{ client_name }}.conf
|
|
========================================
|
|
|
|
- name: Generate QR code for client config
|
|
command: "qrencode -t ansiutf8 -r {{ wireguard_client_configs_path }}/{{ client_name }}.conf"
|
|
register: qr_code
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Display QR code
|
|
debug:
|
|
msg: "{{ qr_code.stdout }}"
|
|
when: qr_code.rc == 0
|