Compare commits
No commits in common. "0c8d18dcce0c30327a76ed543bb352ae8d53ba0f" and "58a2a1526bec3e9efa37af82e27628f07ed6ed9f" have entirely different histories.
0c8d18dcce
...
58a2a1526b
@ -32,8 +32,6 @@ The playbook assumes fresh Arch Linux ARM images installed on machines in your L
|
||||
They should start off with default credentials (i.e. `alarm:alarm`, `root:root`).
|
||||
This repo takes care of everything else.
|
||||
The intended topology is a bastion host facing the Internet, with reverse proxies forwarding traffic to a service host inside the firewall.
|
||||
The servers are all on a WireGuard network.
|
||||
This network also serves as the typical "encrypted tunnel" for devices on the go.
|
||||
|
||||
- Flash all your machines with Arch Linux ARM.
|
||||
- Copy `inventory.example.yml` to `inventory.yml`.
|
||||
|
@ -28,20 +28,14 @@ form_secret: ""
|
||||
paperless_secret: ""
|
||||
|
||||
wireguard_secret:
|
||||
# server secrets
|
||||
# server secret
|
||||
# generate with `wg genkey`, available in the 'wireguard-tools' package
|
||||
servers:
|
||||
your_bastion_host:
|
||||
# see inventory.yml to set the vpn address
|
||||
priv: ""
|
||||
# pipe the secret key (see secret_template in group_vars/) into `wg pubkey` to get this
|
||||
pub: ""
|
||||
your_fleet_host:
|
||||
priv: ""
|
||||
pub: ""
|
||||
server_key: ""
|
||||
# pipe the secret key (see secret_template in group_vars/) into `wg pubkey` to get this
|
||||
server_pub_key: ""
|
||||
|
||||
# list of clients to generate configs for on the bastion host
|
||||
clients:
|
||||
# list of clients to generate configs for
|
||||
peers:
|
||||
# name of the client
|
||||
- name: test_client
|
||||
addr: "10.66.77.2"
|
||||
|
@ -19,11 +19,6 @@ dataroot: /var/lib/serv_data
|
||||
dyndns_domain: null
|
||||
# dyndns_domain: d.nerdpol.ovh
|
||||
|
||||
# limit this to, for example, your VPN subnet or your local subnet
|
||||
# alternatively, 0.0.0.0/0 to open up the internal services to all
|
||||
# for multiple subnets, separate with spaces
|
||||
internal_cidr: "{{ local_subnet }}"
|
||||
|
||||
# this is set true in group_vars/bastion/vars.yml
|
||||
enable_ddclient: false
|
||||
|
||||
@ -43,6 +38,3 @@ escalation_method: doas
|
||||
|
||||
# set up static IP
|
||||
enable_connection: yes
|
||||
|
||||
# use a wireguard network between bastion and fleet host for the reverse proxy
|
||||
wireguard_services: true
|
||||
|
@ -3,10 +3,7 @@
|
||||
|
||||
# fallback_host is only used during setup before the static IP (local_ip) is configured.
|
||||
# Set fallback_host using `nmap 192.168.0.0/24 -p 22` to find the dynamic IP of your Pi
|
||||
#
|
||||
# local_ip is used after first setup.
|
||||
#
|
||||
# vpn_ip is used for the WireGuard network.
|
||||
|
||||
# Make entries in your .ssh/config for ease of use
|
||||
# Example:
|
||||
@ -22,7 +19,6 @@ all:
|
||||
your_bastion_host:
|
||||
fallback_host: 192.168.0.123
|
||||
local_ip: 192.168.0.3
|
||||
vpn_ip: 10.66.77.1
|
||||
ansible_port: 2500
|
||||
ansible_connection: ssh
|
||||
ansible_ssh_private_key_file: ~/.ssh/keys/your_bastion_host
|
||||
@ -30,7 +26,6 @@ all:
|
||||
your_fleet_host:
|
||||
fallback_host: 192.168.0.124
|
||||
local_ip: 192.168.0.86
|
||||
vpn_ip: 10.66.77.86
|
||||
ansible_port: 2500
|
||||
ansible_connection: ssh
|
||||
ansible_ssh_private_key_file: ~/.ssh/keys/your_fleet_host
|
||||
@ -70,7 +65,6 @@ all:
|
||||
wireguard:
|
||||
hosts:
|
||||
your_bastion_host:
|
||||
your_fleet_host:
|
||||
sshd:
|
||||
hosts:
|
||||
your_bastion_host:
|
||||
|
@ -10,10 +10,6 @@
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
(external) {
|
||||
@external not remote_ip {{ internal_cidr }}
|
||||
}
|
||||
|
||||
import conf.d/*
|
||||
|
||||
{% if "website" in group_names %}
|
||||
@ -31,9 +27,6 @@ www.{{ domain }} {
|
||||
|
||||
{% if groups["navidrome"] | length > 0 %}
|
||||
{{ navidrome_domain }} {
|
||||
import external
|
||||
respond @external 403
|
||||
|
||||
reverse_proxy {{ groups["navidrome"][0] }}:4533
|
||||
}
|
||||
{% endif %}
|
||||
@ -50,9 +43,6 @@ www.{{ domain }} {
|
||||
|
||||
{% if groups["paperless"] | length > 0 %}
|
||||
{{ paperless_domain }} {
|
||||
import external
|
||||
respond @external 403
|
||||
|
||||
reverse_proxy {{ groups["paperless"][0] }}:8000
|
||||
}
|
||||
{% endif %}
|
||||
|
@ -126,10 +126,6 @@
|
||||
register: user_synapse
|
||||
when: '"synapse" in groups'
|
||||
|
||||
- name: Figure out local IP address
|
||||
set_fact:
|
||||
docker_ip: "{{ vpn_ip if wireguard_services else local_ip }}"
|
||||
|
||||
- name: Generate docker-compose.yml
|
||||
template:
|
||||
src: "docker-compose.yml.j2"
|
||||
|
@ -1,6 +1,8 @@
|
||||
# vim: ft=yaml
|
||||
---
|
||||
|
||||
version: "3"
|
||||
|
||||
networks:
|
||||
gitea:
|
||||
driver: bridge
|
||||
@ -20,8 +22,8 @@ services:
|
||||
- GITEA__server__DOMAIN={{ gitea_domain }}
|
||||
- GITEA__server__SSH_DOMAIN={{ gitea_domain }}
|
||||
ports:
|
||||
- "{{ docker_ip }}:3000:3000"
|
||||
- "{{ docker_ip }}:2498:22"
|
||||
- "3000:3000"
|
||||
- "2498:22"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- {{ dataroot }}/gitea:/data
|
||||
@ -63,7 +65,7 @@ services:
|
||||
networks:
|
||||
- navidrome
|
||||
ports:
|
||||
- "{{ docker_ip }}:4533:4533"
|
||||
- "4533:4533"
|
||||
|
||||
{% endif %}
|
||||
{% if "synapse" in group_names %}
|
||||
@ -80,7 +82,7 @@ services:
|
||||
networks:
|
||||
- navidrome
|
||||
ports:
|
||||
- "{{ docker_ip }}:8008:8008/tcp"
|
||||
- "8008:8008/tcp"
|
||||
|
||||
{% endif %}
|
||||
|
||||
@ -99,7 +101,7 @@ services:
|
||||
depends_on:
|
||||
- paperless-broker
|
||||
ports:
|
||||
- "{{ docker_ip }}:8000:8000"
|
||||
- "8000:8000"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
|
@ -8,4 +8,3 @@ local_subnet: 192.168.0.0/24
|
||||
sshd_port: 2500
|
||||
|
||||
bastion_ip: "{{ hostvars[groups['bastion'][0]]['local_ip'] }}"
|
||||
bastion_vpn_ip: "{{ hostvars[groups['bastion'][0]]['vpn_ip'] }}"
|
||||
|
@ -14,10 +14,9 @@
|
||||
|
||||
- name: Set default sources (fleet server)
|
||||
set_fact:
|
||||
default_firewall_src: "{{ bastion_vpn_ip if wireguard_services else bastion_ip }}"
|
||||
default_firewall_src: "{{ bastion_ip }}"
|
||||
when: '"fleet" in group_names'
|
||||
|
||||
# this is actually kind of useless because docker bypasses this
|
||||
- name: Allow service ports
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
|
@ -5,9 +5,5 @@
|
||||
# Modifications will be lost!
|
||||
|
||||
{% for host in groups["all"] %}
|
||||
{% if wireguard_services %}
|
||||
{{ hostvars[host]["vpn_ip"] }} {{ host }}
|
||||
{% else %}
|
||||
{{ hostvars[host]["local_ip"] }} {{ host }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
@ -11,6 +11,8 @@ wireguard:
|
||||
- "{{ dns_forward }}"
|
||||
interface: "wg0"
|
||||
ip:
|
||||
# address for the server
|
||||
address: "10.66.77.1/32"
|
||||
# cidr range in tunnel
|
||||
cidr: "10.66.77.0/24"
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
value: 1
|
||||
state: present
|
||||
reload: yes
|
||||
when: '"bastion" in group_names'
|
||||
|
||||
- name: Setup UFW rules to accept VPN traffic
|
||||
community.general.ufw:
|
||||
@ -23,7 +22,6 @@
|
||||
direction: in
|
||||
src: "{{ wireguard.ip.cidr }}"
|
||||
dest: any
|
||||
when: '"bastion" in group_names'
|
||||
|
||||
- name: Deploy wireguard server config
|
||||
template:
|
||||
@ -44,7 +42,6 @@
|
||||
group: root
|
||||
mode: 0700
|
||||
state: directory
|
||||
when: '"bastion" in group_names'
|
||||
|
||||
- name: Create wireguard client configs
|
||||
template:
|
||||
@ -55,7 +52,6 @@
|
||||
mode: 0600
|
||||
lstrip_blocks: true
|
||||
no_log: true
|
||||
with_items: "{{ wireguard_secret.clients }}"
|
||||
with_items: "{{ wireguard_secret.peers }}"
|
||||
notify:
|
||||
- Start wireguard
|
||||
when: '"bastion" in group_names'
|
||||
|
@ -3,12 +3,14 @@
|
||||
Address = {{ item.addr }}
|
||||
# device privkey
|
||||
PrivateKey = {{ item.priv_key }}
|
||||
DNS = {{ hostvars[groups["bastion"][0]].vpn_ip }}
|
||||
DNS = {{ wireguard.ip.address }}
|
||||
|
||||
[Peer]
|
||||
# server stuff
|
||||
PublicKey = {{ wireguard_secret.servers[groups["bastion"][0]].pub }}
|
||||
PublicKey = {{ wireguard_secret.server_pub_key }}
|
||||
Endpoint = {{ wireguard.ip.server_public }}:{{ wireguard.ip.port }}
|
||||
|
||||
# allow traffic for all subnets into the VPN
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
|
||||
PersistentKeepalive = 25
|
||||
|
@ -1,27 +1,14 @@
|
||||
[Interface]
|
||||
Address = {{ hostvars[inventory_hostname]["vpn_ip"] }}/32
|
||||
PrivateKey = {{ wireguard_secret.servers[inventory_hostname].priv }}
|
||||
Address = {{ wireguard.ip.address }}
|
||||
PrivateKey = {{ wireguard_secret.server_key }}
|
||||
ListenPort = {{ wireguard.ip.port }}
|
||||
|
||||
{% if "bastion" in group_names %}
|
||||
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o {{ net_interface }} -j MASQUERADE
|
||||
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o {{ net_interface }} -j MASQUERADE
|
||||
{% endif %}
|
||||
SaveConfig = false
|
||||
|
||||
{% for server_peer in wireguard_secret.servers %}
|
||||
{% if not server_peer == inventory_hostname %}
|
||||
[Peer]
|
||||
PublicKey = {{ wireguard_secret.servers[server_peer].pub }}
|
||||
AllowedIPs = {{ hostvars[server_peer]["vpn_ip"] }}
|
||||
Endpoint = {{ hostvars[server_peer]["local_ip"] }}:{{ wireguard.ip.port }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if "bastion" in group_names %}
|
||||
{% for peer in wireguard_secret.clients %}
|
||||
{% for peer in wireguard_secret.peers %}
|
||||
[Peer]
|
||||
PublicKey = {{ peer.pub_key }}
|
||||
AllowedIPs = {{ peer.addr }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
Loading…
Reference in New Issue
Block a user