wireguard, stash, docker debian, jellyfin
This commit is contained in:
@@ -11,3 +11,14 @@
|
|||||||
- name: reload systemd
|
- name: reload systemd
|
||||||
systemd:
|
systemd:
|
||||||
daemon_reload: yes
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: reload systemd-networkd
|
||||||
|
systemd:
|
||||||
|
name: systemd-networkd
|
||||||
|
state: reloaded
|
||||||
|
|
||||||
|
- name: save iptables
|
||||||
|
shell: |
|
||||||
|
iptables-save > /etc/iptables/rules.v4
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
|||||||
@@ -91,6 +91,11 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- import_tasks: tasks/vcmp_timer.yml
|
- import_tasks: tasks/vcmp_timer.yml
|
||||||
- import_tasks: tasks/audiobookshelf.yml
|
- import_tasks: tasks/audiobookshelf.yml
|
||||||
|
- import_tasks: tasks/stash.yml
|
||||||
|
- import_tasks: tasks/jellyfin.yml
|
||||||
|
- import_tasks: tasks/wireguard.yml
|
||||||
|
handlers:
|
||||||
|
- import_tasks: handlers/main.yml
|
||||||
tags: leaf
|
tags: leaf
|
||||||
- name: Vaermina install
|
- name: Vaermina install
|
||||||
hosts: vaermina
|
hosts: vaermina
|
||||||
|
|||||||
Executable
+177
@@ -0,0 +1,177 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Generate WireGuard vanity keys and update the vault file
|
||||||
|
# Usage: ./generate-wireguard-keys.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
VAULT_FILE="$REPO_DIR/vault/wireguard.yml"
|
||||||
|
TEMP_FILE=$(mktemp)
|
||||||
|
|
||||||
|
echo "==================================="
|
||||||
|
echo "WireGuard Vanity Key Generator"
|
||||||
|
echo "==================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if wireguard-vanity-address is installed
|
||||||
|
if ! command -v wireguard-vanity-address &> /dev/null; then
|
||||||
|
echo "Error: wireguard-vanity-address not found"
|
||||||
|
echo "Install it with: cargo install wireguard-vanity-address"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if wg is installed
|
||||||
|
if ! command -v wg &> /dev/null; then
|
||||||
|
echo "Error: wg (wireguard-tools) not found"
|
||||||
|
echo "Install it with: sudo apt install wireguard-tools"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to generate a vanity keypair
|
||||||
|
generate_vanity_key() {
|
||||||
|
local name=$1
|
||||||
|
local search=$2
|
||||||
|
local search_len=${#search}
|
||||||
|
local timeout=${3:-120}
|
||||||
|
|
||||||
|
echo "Generating vanity key for $name (searching for '$search')..."
|
||||||
|
|
||||||
|
# Try to generate vanity key with timeout
|
||||||
|
local output=$(timeout $timeout wireguard-vanity-address --in $search_len "$search" 2>&1 | grep "^private" | head -n 1 || true)
|
||||||
|
|
||||||
|
if [ -n "$output" ]; then
|
||||||
|
local private_key=$(echo "$output" | awk '{print $2}')
|
||||||
|
local public_key=$(echo "$output" | awk '{print $4}')
|
||||||
|
echo " ✓ Found vanity key: $public_key"
|
||||||
|
else
|
||||||
|
echo " ⚠ No vanity key found in ${timeout}s, generating regular key..."
|
||||||
|
local private_key=$(wg genkey)
|
||||||
|
local public_key=$(echo "$private_key" | wg pubkey)
|
||||||
|
echo " ✓ Generated regular key: $public_key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$private_key|$public_key"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "This will generate new WireGuard keys. This will:"
|
||||||
|
echo " 1. Generate vanity keys for all peers"
|
||||||
|
echo " 2. Update vault/wireguard.yml with the new keys"
|
||||||
|
echo ""
|
||||||
|
read -p "Continue? (y/N) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Aborted."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Generate keys
|
||||||
|
echo "Generating keys (this may take a few minutes)..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
SERVER_KEYS=$(generate_vanity_key "server" "talos" 180)
|
||||||
|
SERVER_PRIVATE=$(echo "$SERVER_KEYS" | cut -d'|' -f1)
|
||||||
|
SERVER_PUBLIC=$(echo "$SERVER_KEYS" | cut -d'|' -f2)
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CLIENT1_KEYS=$(generate_vanity_key "client1" "lptp" 120)
|
||||||
|
CLIENT1_PRIVATE=$(echo "$CLIENT1_KEYS" | cut -d'|' -f1)
|
||||||
|
CLIENT1_PUBLIC=$(echo "$CLIENT1_KEYS" | cut -d'|' -f2)
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CLIENT2_KEYS=$(generate_vanity_key "client2" "phon" 120)
|
||||||
|
CLIENT2_PRIVATE=$(echo "$CLIENT2_KEYS" | cut -d'|' -f1)
|
||||||
|
CLIENT2_PUBLIC=$(echo "$CLIENT2_KEYS" | cut -d'|' -f2)
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
MASSER_KEYS=$(generate_vanity_key "masser" "mssr" 120)
|
||||||
|
MASSER_PRIVATE=$(echo "$MASSER_KEYS" | cut -d'|' -f1)
|
||||||
|
MASSER_PUBLIC=$(echo "$MASSER_KEYS" | cut -d'|' -f2)
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create the vault file content
|
||||||
|
cat > "$TEMP_FILE" << EOF
|
||||||
|
---
|
||||||
|
# WireGuard VPN Keys
|
||||||
|
# These are encrypted with ansible-vault
|
||||||
|
# To edit: ansible-vault edit vault/wireguard.yml
|
||||||
|
|
||||||
|
wireguard_server:
|
||||||
|
private_key: "$SERVER_PRIVATE"
|
||||||
|
public_key: "$SERVER_PUBLIC"
|
||||||
|
vanity_search: "talos"
|
||||||
|
|
||||||
|
wireguard_clients:
|
||||||
|
- name: client1
|
||||||
|
private_key: "$CLIENT1_PRIVATE"
|
||||||
|
public_key: "$CLIENT1_PUBLIC"
|
||||||
|
vanity_search: "lptp"
|
||||||
|
ip_address: "10.8.0.2/24"
|
||||||
|
description: "Example laptop client"
|
||||||
|
|
||||||
|
- name: client2
|
||||||
|
private_key: "$CLIENT2_PRIVATE"
|
||||||
|
public_key: "$CLIENT2_PUBLIC"
|
||||||
|
vanity_search: "phon"
|
||||||
|
ip_address: "10.8.0.3/24"
|
||||||
|
description: "Example phone client"
|
||||||
|
|
||||||
|
- name: masser
|
||||||
|
private_key: "$MASSER_PRIVATE"
|
||||||
|
public_key: "$MASSER_PUBLIC"
|
||||||
|
vanity_search: "mssr"
|
||||||
|
ip_address: "10.8.0.4/24"
|
||||||
|
description: "Masser phone"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "==================================="
|
||||||
|
echo "Keys generated successfully!"
|
||||||
|
echo "==================================="
|
||||||
|
echo ""
|
||||||
|
echo "Summary:"
|
||||||
|
echo " Server: $SERVER_PUBLIC"
|
||||||
|
echo " Client1: $CLIENT1_PUBLIC"
|
||||||
|
echo " Client2: $CLIENT2_PUBLIC"
|
||||||
|
echo " Masser: $MASSER_PUBLIC"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if vault file should be encrypted
|
||||||
|
if [ -f "$VAULT_FILE" ]; then
|
||||||
|
# Check if existing file is encrypted
|
||||||
|
if head -n 1 "$VAULT_FILE" | grep -q '^\$ANSIBLE_VAULT'; then
|
||||||
|
echo "Encrypting with ansible-vault..."
|
||||||
|
ansible-vault encrypt "$TEMP_FILE" --output="$VAULT_FILE"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
echo "✓ Keys saved to $VAULT_FILE (encrypted)"
|
||||||
|
else
|
||||||
|
echo "⚠ Warning: Existing vault file is not encrypted"
|
||||||
|
echo "Saving unencrypted keys to $VAULT_FILE"
|
||||||
|
mv "$TEMP_FILE" "$VAULT_FILE"
|
||||||
|
echo ""
|
||||||
|
echo "To encrypt the file, run:"
|
||||||
|
echo " ansible-vault encrypt $VAULT_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Do you want to encrypt the vault file with ansible-vault? (recommended)"
|
||||||
|
read -p "Encrypt? (Y/n) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
ansible-vault encrypt "$TEMP_FILE" --output="$VAULT_FILE"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
echo "✓ Keys saved to $VAULT_FILE (encrypted)"
|
||||||
|
else
|
||||||
|
mv "$TEMP_FILE" "$VAULT_FILE"
|
||||||
|
echo "✓ Keys saved to $VAULT_FILE (unencrypted)"
|
||||||
|
echo ""
|
||||||
|
echo "⚠ Warning: Keys are stored unencrypted!"
|
||||||
|
echo "To encrypt them later, run:"
|
||||||
|
echo " ansible-vault encrypt $VAULT_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Run the playbook to deploy: ansible-playbook -i inventory.yml playbook.yml --limit talos --tags leaf"
|
||||||
|
echo " 2. Update your WireGuard clients with the new server public key"
|
||||||
|
echo ""
|
||||||
@@ -17,5 +17,6 @@
|
|||||||
key: "{{ lookup('file', '/home/' + item + '/.ssh/id_rsa.pub')}}"
|
key: "{{ lookup('file', '/home/' + item + '/.ssh/id_rsa.pub')}}"
|
||||||
when:
|
when:
|
||||||
- users is defined
|
- users is defined
|
||||||
- lookup('first_found', '/home/' + item + '/.ssh/id_rsa.pub', errors='ignore')
|
- lookup('first_found', dict(files=['/home/' + item + '/.ssh/id_rsa.pub'], skip=true)) | length > 0
|
||||||
|
#- lookup('first_found', '/home/' + item + '/.ssh/id_rsa.pub', errors='ignore')
|
||||||
loop: "{{ users }}"
|
loop: "{{ users }}"
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
block:
|
block:
|
||||||
- name: Include service vault
|
- name: Include service vault
|
||||||
include_vars:
|
include_vars:
|
||||||
file: "{{ service_name }}/vault.yml"
|
dir: "{{ service_name }}"
|
||||||
|
files_matching: vault.yml
|
||||||
- name: Create service directory
|
- name: Create service directory
|
||||||
file:
|
file:
|
||||||
path: "/opt/{{ service_name }}"
|
path: "/opt/{{ service_name }}"
|
||||||
|
|||||||
@@ -39,3 +39,6 @@
|
|||||||
name: nerevar
|
name: nerevar
|
||||||
groups: docker
|
groups: docker
|
||||||
append: yes
|
append: yes
|
||||||
|
- name: Create reverse proxy network
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: proxy
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
- name: Deploy Jellyfin
|
||||||
|
include_tasks: tasks/docker_service.yml
|
||||||
|
vars:
|
||||||
|
service_name: jellyfin
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
services:
|
||||||
|
jellyfin:
|
||||||
|
image: jellyfin/jellyfin:10.11
|
||||||
|
container_name: jellyfin
|
||||||
|
# Optional - specify the uid and gid you would like Jellyfin to use instead of root
|
||||||
|
user: 0:1003
|
||||||
|
ports:
|
||||||
|
- 8096:8096/tcp
|
||||||
|
- 7359:7359/udp
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
- ./cache:/cache
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/azura
|
||||||
|
target: /media
|
||||||
|
read_only: true
|
||||||
|
devices:
|
||||||
|
- /dev/dri:/dev/dri
|
||||||
|
restart: 'unless-stopped'
|
||||||
|
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
|
||||||
|
extra_hosts:
|
||||||
|
- 'host.docker.internal:host-gateway'
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
35646162643235336465636563653039656633313038313138323630336162373163626139613763
|
||||||
|
3862666462343762363332323231616666336339306138310a343666353834623430363535613866
|
||||||
|
30623233643664393466373734633734323334363761616665636161316432373333613130333164
|
||||||
|
3639636538353035620a396463666662373665613235373138623739613665656236633533646162
|
||||||
|
3765
|
||||||
+4
-52
@@ -1,52 +1,4 @@
|
|||||||
- name: Create temp directory
|
- name: Deploy Stash
|
||||||
tempfile:
|
include_tasks: tasks/docker_service.yml
|
||||||
state: directory
|
vars:
|
||||||
suffix: bininstall
|
service_name: stash
|
||||||
register: temp_dir
|
|
||||||
|
|
||||||
- name: Download binary
|
|
||||||
get_url:
|
|
||||||
url: "https://github.com/stashapp/stash/releases/latest/download/stash-linux"
|
|
||||||
dest: "{{ temp_dir.path }}/stash"
|
|
||||||
mode: 0755
|
|
||||||
|
|
||||||
- name: Move binary to system path
|
|
||||||
copy:
|
|
||||||
src: "{{ temp_dir.path }}/stash"
|
|
||||||
dest: "/usr/local/bin/"
|
|
||||||
mode: 0755
|
|
||||||
remote_src: yes
|
|
||||||
|
|
||||||
- name: Copy service file
|
|
||||||
copy:
|
|
||||||
src: stash/stash.service
|
|
||||||
dest: /etc/systemd/system/
|
|
||||||
mode: 0644
|
|
||||||
|
|
||||||
- name: Stash user
|
|
||||||
user:
|
|
||||||
name: stash
|
|
||||||
system: yes
|
|
||||||
create_home: no
|
|
||||||
shell: /sbin/nologin
|
|
||||||
groups: aurbis
|
|
||||||
|
|
||||||
- name: Create config dir
|
|
||||||
file:
|
|
||||||
path: /var/lib/stash
|
|
||||||
state: directory
|
|
||||||
mode: "0755"
|
|
||||||
owner: "stash"
|
|
||||||
group: "stash"
|
|
||||||
|
|
||||||
- name: Start and enable stash service
|
|
||||||
systemd:
|
|
||||||
name: stash
|
|
||||||
state: started
|
|
||||||
enabled: yes
|
|
||||||
daemon_reload: yes
|
|
||||||
|
|
||||||
- name: Clean up temp directory
|
|
||||||
file:
|
|
||||||
path: "{{ temp_dir.path }}"
|
|
||||||
state: absent
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
services:
|
||||||
|
stash:
|
||||||
|
image: stashapp/stash:latest
|
||||||
|
container_name: stash
|
||||||
|
restart: unless-stopped
|
||||||
|
## the container's port must be the same with the STASH_PORT in the environment section
|
||||||
|
ports:
|
||||||
|
- "9999:9999"
|
||||||
|
## If you intend to use stash's DLNA functionality uncomment the below network mode and comment out the above ports section
|
||||||
|
# network_mode: host
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-file: "10"
|
||||||
|
max-size: "2m"
|
||||||
|
environment:
|
||||||
|
- STASH_STASH=/data/
|
||||||
|
- STASH_GENERATED=/generated/
|
||||||
|
- STASH_METADATA=/metadata/
|
||||||
|
- STASH_CACHE=/cache/
|
||||||
|
## Adjust below to change default port (9999)
|
||||||
|
- STASH_PORT=9999
|
||||||
|
volumes:
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
## Adjust below paths (the left part) to your liking.
|
||||||
|
## E.g. you can change ./config:/root/.stash to ./stash:/root/.stash
|
||||||
|
## The left part is the path on your host, the right part is the path in the stash container.
|
||||||
|
|
||||||
|
## Keep configs, scrapers, and plugins here.
|
||||||
|
- ./config:/root/.stash
|
||||||
|
## Point this at your collection.
|
||||||
|
## The left side is where your collection is on your host, the right side is where it will be in stash.
|
||||||
|
- /mnt/nocturnal/share/downloads:/data
|
||||||
|
## This is where your stash's metadata lives
|
||||||
|
- ./metadata:/metadata
|
||||||
|
## Any other cache content.
|
||||||
|
- ./cache:/cache
|
||||||
|
## Where to store binary blob data (scene covers, images)
|
||||||
|
- ./blobs:/blobs
|
||||||
|
## Where to store generated content (screenshots,previews,transcodes,sprites)
|
||||||
|
- ./generated:/generated
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
- name: Load WireGuard keys from vault
|
||||||
|
include_vars:
|
||||||
|
file: vault/wireguard.yml
|
||||||
|
|
||||||
|
- name: Validate wireguard configuration
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- wireguard_server is defined
|
||||||
|
- wireguard_clients is defined
|
||||||
|
- wireguard_clients | length > 0
|
||||||
|
fail_msg: "wireguard_server and wireguard_clients must be defined in vault/wireguard.yml"
|
||||||
|
|
||||||
|
- name: Install WireGuard packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- wireguard
|
||||||
|
- wireguard-tools
|
||||||
|
- qrencode
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Create WireGuard directory structure
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0700"
|
||||||
|
loop:
|
||||||
|
- /etc/wireguard
|
||||||
|
- /etc/wireguard/clients
|
||||||
|
- /etc/wireguard/keys
|
||||||
|
|
||||||
|
- name: Generate key generation script
|
||||||
|
copy:
|
||||||
|
dest: /etc/wireguard/generate_key.sh
|
||||||
|
mode: "0700"
|
||||||
|
content: |
|
||||||
|
#!/bin/bash
|
||||||
|
# Generate a WireGuard keypair
|
||||||
|
# Usage: ./generate_key.sh <output_prefix>
|
||||||
|
|
||||||
|
OUTPUT_PREFIX="$1"
|
||||||
|
|
||||||
|
if [ -z "$OUTPUT_PREFIX" ]; then
|
||||||
|
echo "Usage: $0 <output_file_prefix>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Generating WireGuard keypair..."
|
||||||
|
umask 077
|
||||||
|
wg genkey | tee "${OUTPUT_PREFIX}.key" | wg pubkey > "${OUTPUT_PREFIX}.pub"
|
||||||
|
chmod 600 "${OUTPUT_PREFIX}.key"
|
||||||
|
chmod 644 "${OUTPUT_PREFIX}.pub"
|
||||||
|
echo "Keys generated: ${OUTPUT_PREFIX}.key and ${OUTPUT_PREFIX}.pub"
|
||||||
|
|
||||||
|
- name: Deploy add_client.sh script
|
||||||
|
copy:
|
||||||
|
src: wireguard/add_client.sh
|
||||||
|
dest: /etc/wireguard/add_client.sh
|
||||||
|
mode: "0755"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
|
||||||
|
- name: Create server private key file
|
||||||
|
copy:
|
||||||
|
content: "{{ wireguard_server.private_key }}"
|
||||||
|
dest: "/etc/wireguard/keys/server.key"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0600"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create server public key file
|
||||||
|
copy:
|
||||||
|
content: "{{ wireguard_server.public_key }}"
|
||||||
|
dest: "/etc/wireguard/keys/server.pub"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Create client private key files
|
||||||
|
copy:
|
||||||
|
content: "{{ item.private_key }}"
|
||||||
|
dest: "/etc/wireguard/keys/{{ item.name }}.key"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0600"
|
||||||
|
loop: "{{ wireguard_clients }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create client public key files
|
||||||
|
copy:
|
||||||
|
content: "{{ item.public_key }}"
|
||||||
|
dest: "/etc/wireguard/keys/{{ item.name }}.pub"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
loop: "{{ wireguard_clients }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}"
|
||||||
|
|
||||||
|
- name: Create systemd-networkd WireGuard netdev configuration
|
||||||
|
template:
|
||||||
|
src: wireguard/wg0.netdev.j2
|
||||||
|
dest: /etc/systemd/network/99-wg0.netdev
|
||||||
|
owner: root
|
||||||
|
group: systemd-network
|
||||||
|
mode: "0640"
|
||||||
|
notify: reload systemd-networkd
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create systemd-networkd WireGuard network configuration
|
||||||
|
template:
|
||||||
|
src: wireguard/wg0.network.j2
|
||||||
|
dest: /etc/systemd/network/99-wg0.network
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: reload systemd-networkd
|
||||||
|
|
||||||
|
- name: Enable IP forwarding
|
||||||
|
sysctl:
|
||||||
|
name: net.ipv4.ip_forward
|
||||||
|
value: "1"
|
||||||
|
state: present
|
||||||
|
sysctl_set: yes
|
||||||
|
reload: yes
|
||||||
|
|
||||||
|
- name: Install iptables-persistent for firewall rules
|
||||||
|
apt:
|
||||||
|
name: iptables-persistent
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Configure iptables masquerading for WireGuard
|
||||||
|
iptables:
|
||||||
|
table: nat
|
||||||
|
chain: POSTROUTING
|
||||||
|
out_interface: "{{ ansible_default_ipv4.interface }}"
|
||||||
|
source: 10.8.0.0/24
|
||||||
|
jump: MASQUERADE
|
||||||
|
comment: WireGuard masquerading
|
||||||
|
notify: save iptables
|
||||||
|
|
||||||
|
- name: Configure iptables forwarding for WireGuard
|
||||||
|
iptables:
|
||||||
|
chain: FORWARD
|
||||||
|
in_interface: wg0
|
||||||
|
jump: ACCEPT
|
||||||
|
comment: WireGuard forward in
|
||||||
|
notify: save iptables
|
||||||
|
|
||||||
|
- name: Configure iptables forwarding from WireGuard
|
||||||
|
iptables:
|
||||||
|
chain: FORWARD
|
||||||
|
out_interface: wg0
|
||||||
|
jump: ACCEPT
|
||||||
|
comment: WireGuard forward out
|
||||||
|
notify: save iptables
|
||||||
|
|
||||||
|
- name: Enable and start systemd-networkd
|
||||||
|
systemd:
|
||||||
|
name: systemd-networkd
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Generate client configuration files
|
||||||
|
template:
|
||||||
|
src: wireguard/client.conf.j2
|
||||||
|
dest: "/etc/wireguard/clients/{{ item.name }}.conf"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0600"
|
||||||
|
loop: "{{ wireguard_clients }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Generate QR codes for client configurations
|
||||||
|
shell: |
|
||||||
|
qrencode -t ansiutf8 -r /etc/wireguard/clients/{{ item.name }}.conf > /etc/wireguard/clients/{{ item.name }}.qr.txt
|
||||||
|
qrencode -t png -r /etc/wireguard/clients/{{ item.name }}.conf -o /etc/wireguard/clients/{{ item.name }}.qr.png
|
||||||
|
loop: "{{ wireguard_clients }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}"
|
||||||
|
|
||||||
|
- name: Display WireGuard setup information
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "=============================================="
|
||||||
|
- "WireGuard Server Setup Complete!"
|
||||||
|
- "=============================================="
|
||||||
|
- "Server public key: {{ wireguard_server.public_key }}"
|
||||||
|
- "Server endpoint: {{ ansible_host }}:51820"
|
||||||
|
- "WireGuard network: 10.8.0.0/24"
|
||||||
|
- "Server IP: 10.8.0.1"
|
||||||
|
- ""
|
||||||
|
- "Configured clients ({{ wireguard_clients | length }}):"
|
||||||
|
- "{% for client in wireguard_clients %} - {{ client.name }} ({{ client.ip_address }}) - {{ client.description }}{% endfor %}"
|
||||||
|
- ""
|
||||||
|
- "Client configurations:"
|
||||||
|
- "{% for client in wireguard_clients %} - /etc/wireguard/clients/{{ client.name }}.conf{% endfor %}"
|
||||||
|
- ""
|
||||||
|
- "To view QR code in terminal, run:"
|
||||||
|
- " cat /etc/wireguard/clients/<client_name>.qr.txt"
|
||||||
|
- ""
|
||||||
|
- "To generate additional client keys:"
|
||||||
|
- " /etc/wireguard/generate_key.sh /etc/wireguard/keys/<clientname>"
|
||||||
|
- "=============================================="
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# WireGuard VPN Server
|
||||||
|
|
||||||
|
Configures Talos as a WireGuard VPN server providing access to home network (192.168.178.0/24).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Clients are defined in `vault/wireguard.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
wireguard_server:
|
||||||
|
private_key: "..."
|
||||||
|
public_key: "..."
|
||||||
|
|
||||||
|
wireguard_clients:
|
||||||
|
- name: masser
|
||||||
|
private_key: "..."
|
||||||
|
public_key: "..."
|
||||||
|
ip_address: "10.8.0.2/24"
|
||||||
|
description: "Masser phone"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a Client
|
||||||
|
|
||||||
|
1. Generate vanity key:
|
||||||
|
```bash
|
||||||
|
timeout 120 wireguard-vanity-address --in 4 newc 2>&1 | grep "^private" | head -1
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Edit vault:
|
||||||
|
```bash
|
||||||
|
ansible-vault edit vault/wireguard.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Add to `wireguard_clients` list:
|
||||||
|
```yaml
|
||||||
|
- name: newclient
|
||||||
|
private_key: "paste_from_step_1"
|
||||||
|
public_key: "paste_from_step_1"
|
||||||
|
ip_address: "10.8.0.X/24"
|
||||||
|
description: "Description"
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Deploy:
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i inventory.yml playbook.yml --limit talos --tags leaf
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Get client config from server:
|
||||||
|
```bash
|
||||||
|
ssh nerevar@192.168.178.64 'sudo cat /etc/wireguard/clients/newclient.qr.txt'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Network Details
|
||||||
|
|
||||||
|
- WireGuard network: 10.8.0.0/24
|
||||||
|
- Server IP: 10.8.0.1
|
||||||
|
- Server endpoint: home.hoekveen.net:51820
|
||||||
|
- Server public key stored in vault
|
||||||
|
- Port forwarding required: UDP 51820 -> 192.168.178.64
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Helper script to add a new WireGuard client
|
||||||
|
# Usage: ./add_client.sh <client_name> <ip_suffix>
|
||||||
|
# Example: ./add_client.sh mylaptop 4
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CLIENT_NAME="$1"
|
||||||
|
IP_SUFFIX="$2"
|
||||||
|
|
||||||
|
if [ -z "$CLIENT_NAME" ] || [ -z "$IP_SUFFIX" ]; then
|
||||||
|
echo "Usage: $0 <client_name> <ip_suffix>"
|
||||||
|
echo "Example: $0 mylaptop 4"
|
||||||
|
echo ""
|
||||||
|
echo "This will:"
|
||||||
|
echo " - Generate WireGuard keys for the client"
|
||||||
|
echo " - Assign IP 10.8.0.$IP_SUFFIX to the client"
|
||||||
|
echo " - Add peer to WireGuard server config"
|
||||||
|
echo " - Generate client config file and QR codes"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
WG_DIR="/etc/wireguard"
|
||||||
|
KEYS_DIR="$WG_DIR/keys"
|
||||||
|
CLIENTS_DIR="$WG_DIR/clients"
|
||||||
|
NETDEV_FILE="/etc/systemd/network/99-wg0.netdev"
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if client already exists
|
||||||
|
if [ -f "$KEYS_DIR/${CLIENT_NAME}.key" ]; then
|
||||||
|
echo "Error: Client '$CLIENT_NAME' already exists!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if IP is already in use
|
||||||
|
if grep -q "10.8.0.${IP_SUFFIX}/32" "$NETDEV_FILE"; then
|
||||||
|
echo "Error: IP 10.8.0.${IP_SUFFIX} is already assigned!"
|
||||||
|
echo "Choose a different IP suffix."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Adding WireGuard Client: $CLIENT_NAME"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Client IP: 10.8.0.${IP_SUFFIX}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Generate keys
|
||||||
|
echo "Generating keys..."
|
||||||
|
cd "$KEYS_DIR"
|
||||||
|
"$WG_DIR/generate_key.sh" "$CLIENT_NAME"
|
||||||
|
|
||||||
|
CLIENT_PRIVATE_KEY=$(cat "${KEYS_DIR}/${CLIENT_NAME}.key")
|
||||||
|
CLIENT_PUBLIC_KEY=$(cat "${KEYS_DIR}/${CLIENT_NAME}.pub")
|
||||||
|
SERVER_PUBLIC_KEY=$(cat "${KEYS_DIR}/server.pub")
|
||||||
|
|
||||||
|
echo "Keys generated successfully!"
|
||||||
|
echo "Public key: $CLIENT_PUBLIC_KEY"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Add peer to netdev file
|
||||||
|
echo "Adding peer to server configuration..."
|
||||||
|
cat >> "$NETDEV_FILE" << EOF
|
||||||
|
|
||||||
|
# $CLIENT_NAME
|
||||||
|
[WireGuardPeer]
|
||||||
|
PublicKey=$CLIENT_PUBLIC_KEY
|
||||||
|
AllowedIPs=10.8.0.${IP_SUFFIX}/32
|
||||||
|
PersistentKeepalive=25
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Peer added to $NETDEV_FILE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get server endpoint (try to detect public IP)
|
||||||
|
SERVER_ENDPOINT=$(curl -s ifconfig.me 2>/dev/null || echo "YOUR_PUBLIC_IP")
|
||||||
|
if [ "$SERVER_ENDPOINT" = "YOUR_PUBLIC_IP" ]; then
|
||||||
|
# Fallback to ansible_host if available
|
||||||
|
SERVER_ENDPOINT=$(hostname -I | awk '{print $1}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create client config
|
||||||
|
echo "Creating client configuration..."
|
||||||
|
cat > "$CLIENTS_DIR/${CLIENT_NAME}.conf" << EOF
|
||||||
|
[Interface]
|
||||||
|
Address = 10.8.0.${IP_SUFFIX}/24
|
||||||
|
PrivateKey = $CLIENT_PRIVATE_KEY
|
||||||
|
DNS = 10.8.0.1
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = $SERVER_PUBLIC_KEY
|
||||||
|
Endpoint = ${SERVER_ENDPOINT}:51820
|
||||||
|
# Route home network traffic through WireGuard
|
||||||
|
# To route ALL traffic (full VPN), change to: 0.0.0.0/0
|
||||||
|
AllowedIPs = 192.168.178.0/24, 10.8.0.0/24
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 600 "$CLIENTS_DIR/${CLIENT_NAME}.conf"
|
||||||
|
echo "Client config created at $CLIENTS_DIR/${CLIENT_NAME}.conf"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Generate QR codes
|
||||||
|
echo "Generating QR codes..."
|
||||||
|
qrencode -t ansiutf8 -r "$CLIENTS_DIR/${CLIENT_NAME}.conf" > "$CLIENTS_DIR/${CLIENT_NAME}.qr.txt"
|
||||||
|
qrencode -t png -r "$CLIENTS_DIR/${CLIENT_NAME}.conf" -o "$CLIENTS_DIR/${CLIENT_NAME}.qr.png"
|
||||||
|
echo "QR codes generated!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Reload systemd-networkd
|
||||||
|
echo "Reloading systemd-networkd..."
|
||||||
|
networkctl reload
|
||||||
|
sleep 2
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Display summary
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Client Added Successfully!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Client name: $CLIENT_NAME"
|
||||||
|
echo "Client IP: 10.8.0.${IP_SUFFIX}"
|
||||||
|
echo "Public key: $CLIENT_PUBLIC_KEY"
|
||||||
|
echo ""
|
||||||
|
echo "Configuration files:"
|
||||||
|
echo " - $CLIENTS_DIR/${CLIENT_NAME}.conf"
|
||||||
|
echo " - $CLIENTS_DIR/${CLIENT_NAME}.qr.txt (terminal QR)"
|
||||||
|
echo " - $CLIENTS_DIR/${CLIENT_NAME}.qr.png (image QR)"
|
||||||
|
echo ""
|
||||||
|
echo "To view QR code in terminal:"
|
||||||
|
echo " cat $CLIENTS_DIR/${CLIENT_NAME}.qr.txt"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Copy the client config to your device"
|
||||||
|
echo " 2. Import into WireGuard client app"
|
||||||
|
echo " 3. Connect and test with: ping 10.8.0.1"
|
||||||
|
echo "=========================================="
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[Interface]
|
||||||
|
Address = {{ item.ip_address }}
|
||||||
|
PrivateKey = {{ item.private_key }}
|
||||||
|
DNS = 10.8.0.1
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = {{ wireguard_server.public_key }}
|
||||||
|
Endpoint = home.hoekveen.net:51820
|
||||||
|
# Route all home network traffic through WireGuard
|
||||||
|
# To route ALL traffic (full VPN), change to: 0.0.0.0/0
|
||||||
|
AllowedIPs = 192.168.178.0/24, 10.8.0.0/24
|
||||||
|
PersistentKeepalive = 25
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=wg0
|
||||||
|
Kind=wireguard
|
||||||
|
Description=WireGuard VPN tunnel for home network access
|
||||||
|
|
||||||
|
[WireGuard]
|
||||||
|
PrivateKey={{ wireguard_server.private_key }}
|
||||||
|
ListenPort=51820
|
||||||
|
|
||||||
|
{% for client in wireguard_clients %}
|
||||||
|
# {{ client.name }} - {{ client.description }}
|
||||||
|
[WireGuardPeer]
|
||||||
|
PublicKey={{ client.public_key }}
|
||||||
|
AllowedIPs={{ client.ip_address | regex_replace('/\d+$', '/32') }}
|
||||||
|
PersistentKeepalive=25
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Match]
|
||||||
|
Name=wg0
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Address=10.8.0.1/24
|
||||||
|
IPMasquerade=ipv4
|
||||||
|
IPForward=yes
|
||||||
|
|
||||||
|
[Route]
|
||||||
|
Destination=192.168.178.0/24
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
30643738326463306330626262343761663766623936653166373965643665626332613466633233
|
||||||
|
6364363836653735353630383134343662386237343961610a396530323364663237376665313539
|
||||||
|
61646263386432346461623338613132633935626630333338373634623164326632343261323336
|
||||||
|
6237646464356362630a653637393132626661386261313037366531316435643865356234323161
|
||||||
|
61643930313337653463373133386338386464306439383464343931303633336433363564653439
|
||||||
|
35383362656563653338623162663862623437373132636134633834623635356430363833313233
|
||||||
|
30396139613265653466303437373237343365626164386639303733336666653830393833336536
|
||||||
|
33616431663132643839366332383464396539653466613936353235323565626163613831356339
|
||||||
|
36636138366133323462346331323866323934366565616433323535356535313661613863623262
|
||||||
|
32373239613630666234613437343361373565386139363631656564363965323134666133626465
|
||||||
|
33643064323866663365616132366430303236336134323362646662313939656563383333613234
|
||||||
|
32396330636635656132653538653066333264663730613564373136346531323237653335366330
|
||||||
|
36333136343537616633333232363066336635636265326462306363346335333133653436636232
|
||||||
|
30363030646564333132643164303066386630323264393438356331303437303163666432306365
|
||||||
|
32643630336466663862623433326131633661396136663039663830383830633638393066666632
|
||||||
|
33613865636266663535636231666164383234323432656336396539393863623637373533336234
|
||||||
|
30656233323238316434356564653432363566386433326530636439663137353534643464323035
|
||||||
|
62626238626265323664626430303037653733316535326235663132376130643161303934303436
|
||||||
|
65653130306331313533343365643461366364376433626661626531323233373430373666356364
|
||||||
|
64613961326632623137663836656662656133303263613930366130333936633036303232636265
|
||||||
|
30353137376362643436333062343430323964613364366532616162636539306139323437633063
|
||||||
|
66623639666638363564386363336436626465353635666263396336323063333439626166343236
|
||||||
|
34303133613364666334326532356364343439656564336162663639323464666435376339356436
|
||||||
|
34346365303761353439646439353334303365633363613033303935633463316632346364303530
|
||||||
|
61303662393636383232333963313235643434323833636263666565396438343732366531656261
|
||||||
|
37306439623165363164613563303566313461633936363133316434313039363335353139356137
|
||||||
|
66613631383866653365623234353538646364323735353433336431323337316565353431613034
|
||||||
|
61333838356466343336323662343037656662333465306665333433626637356330393036363765
|
||||||
|
38333436333063356339636139653933373938373164646139333133393333386433323738616131
|
||||||
|
34393133313563316339336230316362363130366239313837323236303939353362636136343363
|
||||||
|
62383061353466323330383964333534366362666331393333373964316563633639393065366165
|
||||||
|
37636564313937393138396665303562633261396636616435636237336231306163326538623837
|
||||||
|
32313064343963356666653035623834306662366265373437316636373361636263356464373930
|
||||||
|
31356235313963383230663165303161643838356534353339643436323262326338386231383061
|
||||||
|
31303064356233303539356363653038656637646632313238366364383439393866326133653462
|
||||||
|
39303936373762323665333135393334343131313732616236363233396666616564366233383763
|
||||||
|
33663336316430333163333938653466353361633230396633353963303038353230643364356634
|
||||||
|
30616230613139656662303830303632366531653838396130313730663930616666336632623137
|
||||||
|
646436343130346531313934616132636234
|
||||||
Reference in New Issue
Block a user