lint / yamllint + ansible-lint + syntax-check (push) Canceled after 0s
Rolled back per the user's request. Three variants were tried on ru-vps
(static key; TLS peer-fingerprint p2p; server mode with push routes and an
inline <ca>). The server side worked each time, but the "OpenVPN for
Android" client consistently failed at config build ("Used 101 tries to
get current version of the profile"), which looks like an app/OS issue
rather than the config.
Repo: remove playbooks/openvpn-phone.yml, its Make target, and the shared
homelab_vpn_client_routes var; restore openvpn-laptop.yml to its prior
state (its pre-existing `become: false` on delegate_to: localhost is noted
in plan.md, left untouched). ru-vps teardown done out of band: unit, tun2,
ufw/nat rules for 9444 and 10.80.0.0/29, and /etc/openvpn/homelab-phone
removed; the site tunnel (homelab-openvpn, tun0) was not touched and is
verified active.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbuZrUoevfBgCpf5DCF4DG
198 lines
6.4 KiB
YAML
198 lines
6.4 KiB
YAML
- name: Configure OpenVPN laptop access through ru-vps
|
|
hosts: ru-vps
|
|
gather_facts: true
|
|
become: true
|
|
vars:
|
|
laptop_profile_name: ada-x1
|
|
laptop_openvpn_dir: /etc/openvpn/homelab-laptop
|
|
laptop_openvpn_config: /etc/openvpn/homelab-laptop/server.conf
|
|
laptop_openvpn_key: /etc/openvpn/homelab-laptop/static.key
|
|
laptop_openvpn_service: homelab-openvpn-laptop
|
|
laptop_openvpn_port: 9443
|
|
laptop_openvpn_interface: tun1
|
|
laptop_openvpn_site_interface: tun0
|
|
laptop_openvpn_network_cidr: 10.79.0.0/30
|
|
laptop_openvpn_server_ip: 10.79.0.1
|
|
laptop_openvpn_client_ip: 10.79.0.2
|
|
laptop_openvpn_remote: 157.22.231.198
|
|
laptop_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ laptop_profile_name }}.ovpn"
|
|
laptop_openvpn_home_routes:
|
|
- network: 192.168.1.5
|
|
netmask: 255.255.255.255
|
|
- network: 192.168.1.6
|
|
netmask: 255.255.255.254
|
|
- network: 192.168.1.8
|
|
netmask: 255.255.255.248
|
|
- network: 192.168.1.16
|
|
netmask: 255.255.255.240
|
|
- network: 192.168.1.32
|
|
netmask: 255.255.255.248
|
|
- network: 192.168.1.40
|
|
netmask: 255.255.255.255
|
|
|
|
tasks:
|
|
- name: Install OpenVPN packages
|
|
ansible.builtin.apt:
|
|
name:
|
|
- openvpn
|
|
- iptables
|
|
state: present
|
|
update_cache: true
|
|
|
|
- name: Ensure laptop OpenVPN config directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ laptop_openvpn_dir }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0700"
|
|
|
|
- name: Generate laptop static key if missing
|
|
ansible.builtin.command: "openvpn --genkey secret {{ laptop_openvpn_key }}"
|
|
args:
|
|
creates: "{{ laptop_openvpn_key }}"
|
|
no_log: true
|
|
|
|
- name: Enable IPv4 forwarding on ru-vps
|
|
ansible.posix.sysctl:
|
|
name: net.ipv4.ip_forward
|
|
value: "1"
|
|
state: present
|
|
reload: true
|
|
|
|
- name: Allow laptop OpenVPN TCP in UFW
|
|
ansible.builtin.command: "ufw allow {{ laptop_openvpn_port }}/tcp"
|
|
register: ufw_allow_laptop_openvpn
|
|
changed_when: "'Rule added' in ufw_allow_laptop_openvpn.stdout or 'Rules updated' in ufw_allow_laptop_openvpn.stdout"
|
|
failed_when: false
|
|
|
|
- name: Render laptop OpenVPN server config
|
|
ansible.builtin.copy:
|
|
dest: "{{ laptop_openvpn_config }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0600"
|
|
content: |
|
|
dev {{ laptop_openvpn_interface }}
|
|
ifconfig {{ laptop_openvpn_server_ip }} {{ laptop_openvpn_client_ip }}
|
|
secret {{ laptop_openvpn_key }}
|
|
cipher AES-256-CBC
|
|
auth SHA256
|
|
proto tcp-server
|
|
port {{ laptop_openvpn_port }}
|
|
persist-key
|
|
persist-tun
|
|
verb 3
|
|
keepalive 10 60
|
|
notify: restart laptop openvpn
|
|
|
|
- name: Render laptop OpenVPN up script
|
|
ansible.builtin.copy:
|
|
dest: "{{ laptop_openvpn_dir }}/up.sh"
|
|
owner: root
|
|
group: root
|
|
mode: "0700"
|
|
content: |
|
|
#!/bin/sh
|
|
iptables -t nat -C POSTROUTING -s {{ laptop_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ laptop_openvpn_site_interface }} -j MASQUERADE 2>/dev/null || \
|
|
iptables -t nat -A POSTROUTING -s {{ laptop_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ laptop_openvpn_site_interface }} -j MASQUERADE
|
|
notify: restart laptop openvpn
|
|
|
|
- name: Render laptop OpenVPN down script
|
|
ansible.builtin.copy:
|
|
dest: "{{ laptop_openvpn_dir }}/down.sh"
|
|
owner: root
|
|
group: root
|
|
mode: "0700"
|
|
content: |
|
|
#!/bin/sh
|
|
iptables -t nat -D POSTROUTING -s {{ laptop_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ laptop_openvpn_site_interface }} -j MASQUERADE 2>/dev/null || true
|
|
notify: restart laptop openvpn
|
|
|
|
- name: Render laptop OpenVPN systemd service
|
|
ansible.builtin.copy:
|
|
dest: "/etc/systemd/system/{{ laptop_openvpn_service }}.service"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
content: |
|
|
[Unit]
|
|
Description=HomeLab OpenVPN laptop access
|
|
After=network-online.target homelab-openvpn.service
|
|
Wants=network-online.target
|
|
Requires=homelab-openvpn.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStartPre={{ laptop_openvpn_dir }}/up.sh
|
|
ExecStart=/usr/sbin/openvpn --config {{ laptop_openvpn_config }}
|
|
ExecStopPost={{ laptop_openvpn_dir }}/down.sh
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
notify:
|
|
- reload systemd
|
|
- restart laptop openvpn
|
|
|
|
- name: Flush handlers before starting laptop OpenVPN
|
|
ansible.builtin.meta: flush_handlers
|
|
|
|
- name: Enable and start laptop OpenVPN
|
|
ansible.builtin.systemd:
|
|
name: "{{ laptop_openvpn_service }}"
|
|
state: started
|
|
enabled: true
|
|
|
|
- name: Read laptop static key for client profile
|
|
ansible.builtin.slurp:
|
|
src: "{{ laptop_openvpn_key }}"
|
|
register: laptop_openvpn_static_key_raw
|
|
no_log: true
|
|
|
|
- name: Ensure local generated directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ playbook_dir }}/../generated"
|
|
state: directory
|
|
mode: "0700"
|
|
become: false
|
|
delegate_to: localhost
|
|
|
|
- name: Write local laptop OpenVPN profile
|
|
ansible.builtin.copy:
|
|
dest: "{{ laptop_openvpn_client_config_local }}"
|
|
mode: "0600"
|
|
content: |
|
|
client
|
|
dev tun
|
|
proto tcp-client
|
|
remote {{ laptop_openvpn_remote }} {{ laptop_openvpn_port }}
|
|
ifconfig {{ laptop_openvpn_client_ip }} {{ laptop_openvpn_server_ip }}
|
|
cipher AES-256-CBC
|
|
auth SHA256
|
|
persist-key
|
|
persist-tun
|
|
resolv-retry infinite
|
|
nobind
|
|
verb 3
|
|
{% for route in laptop_openvpn_home_routes %}
|
|
route {{ route.network }} {{ route.netmask }}
|
|
{% endfor %}
|
|
<secret>
|
|
{{ laptop_openvpn_static_key_raw.content | b64decode }}
|
|
</secret>
|
|
become: false
|
|
delegate_to: localhost
|
|
no_log: true
|
|
|
|
handlers:
|
|
- name: reload systemd
|
|
ansible.builtin.systemd:
|
|
daemon_reload: true
|
|
|
|
- name: restart laptop openvpn
|
|
ansible.builtin.systemd:
|
|
name: "{{ laptop_openvpn_service }}"
|
|
state: restarted
|