new major update

This commit is contained in:
Alex Tavarez committed 2026-09-26 14:18:27 -04:00
1 parent 161f8fc94e
commit 3f69aa6af1
60 files changed
+2228 -615

No files matched your search

@@ -0,0 +1,7 @@
- name: Starting and enabling SystemD service
become: true
ansible.builtin.systemd_service:
name: "avahi-daemon"
scope: system
enabled: true
state: started
@@ -18,22 +18,19 @@
- name: Creating domain arguments for certbot
ansible.builtin.set_fact:
certbot_domains: "{{ ['-d'] | product(web_fqdns) | map('join', '=') | list }}"
- name: Getting public IP
- name: Getting public IPv4 address
community.general.ipify_facts:
validate_certs: false
timeout: 20
- name: Getting public IPv6 address
when: ipv6_enabled
ansible.builtin.shell:
cmd: curl -6 icanhazip.com
register: ipify_public_ip6
- name: Starting domain name registration with standalone DNS
when: "certbot.auth_method == 'dns' and not certbot.containerized"
ignore_errors: true
block:
- name: Opening port 53
become: true
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
destination_port: 53
jump: ACCEPT
comment: Opening up port 53
# @NOTE https://github.com/siilike/certbot-dns-standalone
- name: Exemplifying needed ACME record
ansible.builtin.set_fact:
@@ -42,6 +39,14 @@
_acme-challenge.{{ fqdn | default(inventory_hostname) }} IN CNAME {{ fqdn | default(inventory_hostname) }}.acme.{{ fqdn | default(inventory_hostname) }}.
acme.{{ fqdn | default(inventory_hostname) }} IN NS ns.acme.{{ fqdn | default(inventory_hostname) }}.
ns.acme.{{ fqdn | default(inventory_hostname) }} IN A {{ ipify_public_ip }}
- name: Exemplifying needed ACME record
when: ipv6_enabled
ansible.builtin.set_fact:
acme_record: |
{{ fqdn | default(inventory_hostname) }} IN A {{ ipify_public_ip6.stdout }}
_acme-challenge.{{ fqdn | default(inventory_hostname) }} IN CNAME {{ fqdn | default(inventory_hostname) }}.acme.{{ fqdn | default(inventory_hostname) }}.
acme.{{ fqdn | default(inventory_hostname) }} IN NS ns.acme.{{ fqdn | default(inventory_hostname) }}.
ns.acme.{{ fqdn | default(inventory_hostname) }} IN A {{ ipify_public_ip6.stdout }}
- name: Informing user of need to set up ACME record
ansible.builtin.debug:
msg: "Please set ACME record in domain name provider:\n {{ acme_record }}"
@@ -49,7 +54,7 @@
ansible.builtin.pause:
- name: Running certbot to authenticate and acquire domain name certificates
become: true
when: "certbot.mode == 'dev'"
when: "certbot.mode == 'dev' and not ipv6_enabled"
ansible.builtin.command:
argv:
- certbot
@@ -61,13 +66,30 @@
- "--agree-tos"
- "--non-interactive"
- "--dns-standalone-address={{ ipify_public_ip }}"
# - "--dns-standalone-ipv6-address={{ ansible_default_ipv6.address | default(ansible_all_ipv6_addresses[0]) }}"
- "--dns-standalone-port={{ certbot.port }}"
- "{{ certbot_domains[0] }}"
- "{{ certbot_domains[1] }}"
- name: Running certbot to authenticate and acquire domain name certificates
become: true
when: "certbot.mode == 'prod'"
when: "certbot.mode == 'dev' and ipv6_enabled"
ansible.builtin.command:
argv:
- certbot
- certonly
- "--staging"
- "--debug"
- "--authenticator=dns-standalone"
- "--email={{ certbot.email }}"
- "--agree-tos"
- "--non-interactive"
- "--dns-standalone-address={{ ipify_public_ip }}"
- "--dns-standalone-ipv6-address={{ ipify_public_ip6.stdout }}"
- "--dns-standalone-port={{ certbot.port }}"
- "{{ certbot_domains[0] }}"
- "{{ certbot_domains[1] }}"
- name: Running certbot to authenticate and acquire domain name certificates
become: true
when: "certbot.mode == 'prod' and not ipv6_enabled"
ansible.builtin.command:
argv:
- certbot
@@ -77,7 +99,22 @@
- "--agree-tos"
- "--non-interactive"
- "--dns-standalone-address={{ ipify_public_ip }}"
# - "--dns-standalone-ipv6-address={{ ansible_default_ipv6.address | default(ansible_all_ipv6_addresses[0]) }}"
- "--dns-standalone-port={{ certbot.port }}"
- "{{ certbot_domains[0] }}"
- "{{ certbot_domains[1] }}"
- name: Running certbot to authenticate and acquire domain name certificates
become: true
when: "certbot.mode == 'prod' and ipv6_enabled"
ansible.builtin.command:
argv:
- certbot
- certonly
- "--authenticator=dns-standalone"
- "--email={{ certbot.email }}"
- "--agree-tos"
- "--non-interactive"
- "--dns-standalone-address={{ ipify_public_ip }}"
- "--dns-standalone-ipv6-address={{ ipify_public_ip6.stdout }}"
- "--dns-standalone-port={{ certbot.port }}"
- "{{ certbot_domains[0] }}"
- "{{ certbot_domains[1] }}"
@@ -85,14 +122,6 @@
when: "certbot.auth_method == 'standalone' and not certbot.containerized"
ignore_errors: true
block:
- name: Opening port 80
become: true
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
destination_port: 80
jump: ACCEPT
comment: Open up port 80
- name: Acquiring domain certificates
become: true
when: "certbot.mode == 'dev'"
@@ -37,6 +37,7 @@
name: crowdsec
scope: system
state: restarted
enabled: true
- name: Adding remediation component or bouncer
ansible.builtin.command:
cmd: "cscli bouncers add {{ item }}"
+110 -20
View File
@@ -8,6 +8,32 @@
ansible.builtin.shell:
cmd: "echo {{ ansible_user }}"
register: current_user
- name: Checking if ZFS filesystem is present
ansible.builtin.shell:
cmd: "findmnt -D | awk '{ print $2 }' | tail -n +2"
register: fs_result
- name: Logging presence of ZFS filesystem
when: "'zfs' in fs_result.stdout"
ansible.builtin.set_fact:
zfs_present: true
- name: Logging absence of ZFS filesystem
when: "'zfs' not in fs_result.stdout"
ansible.builtin.set_fact:
zfs_present: false
- name: Configuring ZFS support
when: zfs_present
block:
- name: Getting available pools
ansible.builtin.shell:
cmd: "zpool list | awk '{ print $1 }' | tail -n +2"
register: zpools
- name: Turning available pools into list
ansible.builtin.set_fact:
zpool_list: "{{ zpools | replace('\n', ' ') | split(' ') }}"
- name: Allowing choice of zpool
ansible.builtin.pause:
prompt: "Type preferred zpool from available (i.e., {{ zpool_list | join(', ') }})"
register: preferred_zpool
- name: Initializing DSNet
become: true
ansible.builtin.command:
@@ -16,16 +42,35 @@
become: true
ansible.builtin.command:
cmd: dsnet up
- name: Creating a ZFS dataset for DSNet configuration
when: zfs_present
become: true
community.general.zfs:
name: "{{ preferred_zpool.user_input }}/wireguard_clients"
state: present
extra_zfs_properties:
canmount: "on"
mountpoint: "{{ ansible_user_home.stdout }}/.wg"
- name: Creating a directory to house VPN service client configurations
become: true
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.wg"
recurse: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "700"
state: directory
- name: Creating a directory to house VPN service client configurations
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d"
recurse: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "755"
mode: "700"
state: directory
- name: Adding peer device for DSNet VPN service interface
become: true
when: "((fqdn is defined and fqdn != None) and fqdn in item.name) or (item.name in groups.homeserver or item.name in groups['homeserver.test'])"
ansible.builtin.shell:
cmd: "dsnet add {{ item.name }}{{ idx }} --owner {{ current_user.stdout }} --description 'For {{ item.name }}--{{ item.desc }}' --confirm > {{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
creates: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ idx }}.conf"
@@ -33,6 +78,7 @@
loop_control:
index_var: idx
- name: Changing ownership of consequent DSNet VPN service client configurations
when: "((fqdn is defined and fqdn != None) and fqdn in item.name) or (item.name in groups.homeserver or item.name in groups['homeserver.test'])"
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
owner: "{{ ansible_user }}"
@@ -42,6 +88,39 @@
loop: "{{ vpn.clients }}"
loop_control:
index_var: idx
- name: Acquiring VPN server subnet
block:
- name: Acquiring VPN server IPv4 subnet
ansible.builtin.shell:
cmd: echo "$(</etc/dsnetconfig.json )" | awk '/^ {4}"Network":/ { print $2 }' | sed 's/[",]//g;s/\/[0-9]*/\/24/g'
register: masq_target_net_ip
- name: Acquiring VPN server IPv6 subnet
when: ipv6_enabled
ansible.builtin.shell:
cmd: echo "$(</etc/dsnetconfig.json )" | awk '/^ {4}"Network6":/ { print $2 }' | sed 's/[",]//g'
register: masq_target_net_ip6
- name: Getting public IP addresses
block:
- name: Getting public IPv4 address
community.general.ipify_facts:
validate_certs: false
timeout: 20
- name: Getting public IPv6 address
when: ipv6_enabled
ansible.builtin.shell:
cmd: curl -6 icanhazip.com
register: ipify_public_ip6
- name: Getting VPN client IP addresses
block:
- name: Getting VPN client IPv4 address
ansible.builtin.shell:
cmd: wg showconf dsnet | awk -F ' = |, ' '/^AllowedIPs/ { print $2 }' | sed 's/\/[0-9]*//g'
register: vpn_client_ip
- name: Getting VPN client IPv4 address
when: ipv6_enabled
ansible.builtin.shell:
cmd: wg showconf dsnet | awk -F ' = |, ' '/^AllowedIPs/ { print $3 }' | sed 's/\/[0-9]*//g'
register: vpn_client_ip6
- name: Pausing to inquire about how to proceed
ansible.builtin.pause:
prompt: "Type \"fetch\" to get the DSNet VPN service client configuration files, or \"show\" to see their contents for manual copying instead"
@@ -51,6 +130,7 @@
when: data_method.user_input == "show"
block:
- name: Acquiring contents of DSNet VPN service client configuration files
when: "((fqdn is defined and fqdn != None) and fqdn in item.name) or (item.name in groups.homeserver or item.name in groups['homeserver.test'])"
ansible.builtin.slurp:
src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
loop: "{{ vpn.clients }}"
@@ -58,6 +138,7 @@
index_var: idx
register: vpn_client_configs
- name: Presenting contents of DSNet VPN service client configurations to control node
when: "((fqdn is defined and fqdn != None) and fqdn in item.name) or (item.name in groups.homeserver or item.name in groups['homeserver.test'])"
ansible.builtin.debug:
msg: "Copy this client configuration of the DSNet VPN service:\n {{ item.content | b64decode }}"
loop: "{{ vpn_client_configs.results }}"
@@ -67,12 +148,12 @@
when: data_method.user_input == "fetch"
block:
- name: Informing user of inventory requirements for VPN clients
when: ((fqdn is undefined or fqdn == None) and item.name != fqdn) or not item.name in groups.homeserver
when: ((fqdn is undefined or fqdn == None) or fqdn not in item.name) and (item.name not in groups.homeserver and item.name not in groups['homeserver.test'])
ansible.builtin.fail:
msg: The VPN client must be the name of an inventory host in a homeserver group
loop: "{{ vpn.clients }}"
- name: Dupliciating DSNet VPN service client configuration files to control node
when: ((fqdn is defined and fqdn != None) and item.name == fqdn) or item.name in groups.homeserver
when: "((fqdn is defined and fqdn != None) and fqdn in item.name) or (item.name in groups.homeserver or item.name in groups['homeserver.test'])"
ansible.builtin.fetch:
src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
dest: "./.tmp/{{ inventory_hostname }}-dsnet/"
@@ -100,13 +181,16 @@
- name: Ensuring IP forwarding is allowed
become: true
ansible.posix.sysctl:
name: "net.{{ item }}.ip_forward"
name: "{{ item }}"
value: "1"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
loop:
- ipv4
# - ipv6
- net.ipv4.ip_forward
- net.ipv6.conf.all.forwarding
- net.ipv4.conf.all.src_valid_mark
- name: Creating SystemD unit for placing up DSNet interface
become: true
ansible.builtin.copy:
@@ -120,13 +204,30 @@
become: true
ansible.builtin.systemd_service:
name: dsnet
scope: system
enabled: true
daemon_reload: true
- name: Copying script for DSNet iptables rules
become: true
when: ipv6_enabled
ansible.builtin.template:
src: usr/local/bin/dsnet-forward.sh.j2
dest: /usr/local/bin/dsnet-forward.sh
src: usr/local/bin/dsnet-routing6.sh.j2
dest: /usr/local/bin/dsnet-routing.sh
variable_start_string: "<%"
variable_end_string: "%>"
owner: root
group: root
mode: "755"
force: true
backup: true
- name: Copying script for DSNet iptables rules
become: true
when: not ipv6_enabled
ansible.builtin.template:
src: usr/local/bin/dsnet-routing.sh.j2
dest: /usr/local/bin/dsnet-routing.sh
variable_start_string: "<%"
variable_end_string: "%>"
owner: root
group: root
mode: "755"
@@ -144,16 +245,5 @@
- name: Reloading SystemD
become: true
ansible.builtin.systemd_service:
name: thrunet
scope: system
daemon_reload: true
- name: Opening port 51820
become: true
ansible.builtin.iptables:
chain: INPUT
protocol: "{{ item }}"
destination_port: 51820
jump: ACCEPT
comment: Open up port 51820
loop:
- udp
- tcp
@@ -82,9 +82,13 @@
- name: Placing Headscale authentication key into file on control node
ansible.builtin.fetch:
src: "{{ tailscale_admin_authkey_file.dest }}"
dest: "./.tmp/{{ inventory_hostname }}-{{ headscale.users.admin.username }}@headscale/headscale.key"
dest: "./.tmp/{{ item.name }}-{{ headscale.users.admin.username }}@headscale/headscale{{ (idx | string) }}.key"
flat: true
loop: "{{ headscale.clients }}"
loop_control:
index_var: idx
- name: Placing Headscale authentication key into file on control node
when: "((fqdn is defined and fqdn != None) and fqdn in item.name) or (item.name in groups.homeserver or item.name in groups['homeserver.test'])"
ansible.builtin.fetch:
src: "{{ tailscale_admin_authkey_file.dest }}"
dest: "./roles/init-server/files/{{ item.name }}-{{ headscale.users.admin.username }}@headscale/headscale{{ (idx | string) }}.key"
@@ -94,7 +98,10 @@
index_var: idx
- name: Informing control node of acquired files
ansible.builtin.debug:
msg: "The Headscale authentication key files have been duplicated to './.tmp/{{ inventory_hostname }}-{{ headscale.users.admin.username }}@headscale/headscale.key' at the control node."
msg: "The Headscale authentication key files have been duplicated to {{ item }} at the control node."
loop:
- "./roles/init-server/files/"
- "./.tmp/"
- name: Giving control node user time to read the aforementiioned message
ansible.builtin.pause:
seconds: 30
@@ -0,0 +1,101 @@
- name: Getting public IP addresses
block:
- name: Getting public IPv4 address
community.general.ipify_facts:
validate_certs: false
timeout: 20
- name: Getting public IPv6 address
when: ipv6_enabled
ansible.builtin.shell:
cmd: curl -6 icanhazip.com
register: ipify_public_ip6
- name: Getting available network interfaces
ansible.builtin.shell:
cmd: "ip link show | awk '/^[0-9]+: [a-z]/ { print $2 }' | grep -vE 'lo[0-9]*|wg[0-9]+-mullvad' | sed 's/://g'"
register: intrfaces
- name: Turning acquired network interfaces into list
ansible.builtin.set_fact:
main_interfaces: "{{ intrfaces.stdout | replace('\n', ' ') | split(' ') }}"
- name: Pre-emptively allowing inbound connections already established and related to outbound requests
ansible.builtin.iptables:
ip_version: both
chain: INPUT
match:
- conntrack
ctstate:
- ESTABLISHED
- RELATED
jump: ACCEPT
comment: allowing inbound replies
- name: Pre-emptively establishing fiirewall rules for inbound ICMP requests
become: true
block:
- name: Pre-emptively allowing inbound IPv4 ICMP connections
ansible.builtin.iptables:
ip_version: ipv4
chain: INPUT
destination: "! {{ ipify_public_ip }}"
protocol: icmp
jump: ACCEPT
comment: ping
- name: Pre-emptively allowing inbound IPv6 ICMP connections
when: ipv6_enabled
ansible.builtin.iptables:
ip_version: ipv6
chain: INPUT
destination: "! {{ ipify_public_ip6.stdout }}"
protocol: icmp
jump: ACCEPT
comment: ping
- name: Pre-emptively establishing firewall rules for loopback interface
become: true
block:
- name: Pre-emptively allowing all inbound connections on loopback device
ansible.builtin.iptables:
ip_version: both
chain: INPUT
in_interface: lo
jump: ACCEPT
comment: loopback
- name: Pre-emptively allowing inbound SSH
become: true
ansible.builtin.iptables:
ip_version: both
chain: INPUT
protocol: tcp
destination_port: 22
in_interface: "{{ item }}"
jump: ACCEPT
comment: ssh
loop: "{{ main_interfaces }}"
- name: Crafting additional exceptions to the inbound default policy
become: true
when: iptables.allow.inbound is defined and iptables.allow.inbound != None
ansible.builtin.iptables:
ip_version: both
chain: INPUT
protocol: "{{ item[1].protocol | default('tcp') }}"
destination_port: "{{ item[1].port }}"
in_interface: "{{ item[1].interface | default(item[0]) }}"
jump: ACCEPT
comment: "{{ item[1].desc | default('srvr') }}"
loop: "{{ main_interfaces | product(iptables.allow.inbound) }}"
- name: Setting default policy for inbound connections
become: true
ansible.builtin.iptables:
chain: INPUT
policy: DROP
- name: Setting default policy for outbound connections
become: true
ansible.builtin.iptables:
chain: OUTPUT
policy: ACCEPT
- name: Backing up firewall rules
become: true
community.general.iptables_state:
ip_version: "{{ item[0] }}"
state: saved
path: /etc/iptables/initial_rules.{{ item[1] }}
loop:
- ["ipv4", "v4"]
- ["ipv6", "v6"]
@@ -67,12 +67,13 @@
owner: root
group: root
mode: "644"
- name: Prioritizing authentication methods in SSH
- name: Allowing interactive keyboard authentication
become: true
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/auth.conf
line: "KbdInteractiveAuthentication yes # enable if implementing TOTP 2FA"
regexp: "^KbdInteractiveAuthentication"
line: "KbdInteractiveAuthentication yes # enable if implementing TOTP 2FA"
insertafter: EOF
owner: root
group: root
mode: "644"
@@ -80,12 +81,20 @@
become: true
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/auth.conf
regexp: "^AuthenticationMethods"
line: "AuthenticationMethods publickey keyboard-interactive:pam"
insertafter: "^KbdInteractiveAuthentication"
owner: root
group: root
mode: "644"
# - name: Adding Google Authenticator OTP module PAM authentication line for SSH
- name: Restarting SystemD SSH service
become: true
ansible.builtin.systemd_service:
name: sshd
scope: system
state: restarted
enabled: true
# - name: Adding Google Authenticator OTP module PAM authentication line for sudo
# become: true
# ansible.builtin.lineinfile:
# path: /etc/pam.d/sudo
@@ -94,7 +103,7 @@
# owner: root
# group: root
# mode: "644"
# - name: Adding Google Authenticator OTP module PAM authentication line for SSH
# - name: Adding Google Authenticator OTP module PAM authentication line for sudo
# become: true
# ansible.builtin.lineinfile:
# path: /etc/pam.d/su
@@ -102,9 +111,4 @@
# insertafter: "include common-auth$"
# owner: root
# group: root
# mode: "644"
- name: Restarting SystemD SSH service
become: true
ansible.builtin.systemd_service:
name: sshd
state: restarted
# mode: "644"
@@ -9,19 +9,49 @@
ansible.builtin.shell:
cmd: "echo {{ ansible_user }}"
register: current_user
- name: Checking if ZFS filesystem is present
ansible.builtin.shell:
cmd: "findmnt -D | awk '{ print $2 }' | tail -n +2"
register: fs_result
- name: Logging presence of ZFS filesystem
when: "'zfs' in fs_result.stdout"
ansible.builtin.set_fact:
zfs_present: true
- name: Logging absence of ZFS filesystem
when: "'zfs' not in fs_result.stdout"
ansible.builtin.set_fact:
zfs_present: false
- name: Configuring ZFS support
when: zfs_present
block:
- name: Getting available pools
ansible.builtin.shell:
cmd: "zpool list | awk '{ print $1 }' | tail -n +2"
register: zpools
- name: Turning available pools into list
ansible.builtin.set_fact:
zpool_list: "{{ zpools | replace('\n', ' ') | split(' ') }}"
- name: Allowing choice of zpool
ansible.builtin.pause:
prompt: "Type preferred zpool from available (i.e., {{ zpool_list | join(', ') }})"
register: preferred_zpool
- name: Ensuring user namespace support is enabled
become: true
ansible.posix.sysctl:
name: kernel.unprivileged_userns_clone
value: "1"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
- name: Ensuring user namespace support is enabled
become: true
ansible.posix.sysctl:
name: net.ipv4.ip_unprivileged_port_start
value: "0"
value: "20"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
- name: Creating container directory
ansible.builtin.file:
@@ -31,6 +61,24 @@
group: "{{ ansible_user }}"
mode: "755"
state: directory
- name: Creating a ZFS dataset for container secrets
become: true
when: zfs_present
community.general.zfs:
name: "{{ preferred_zpool.user_input }}/container_volumes"
state: present
extra_zfs_properties:
canmount: "on"
mountpoint: "{{ ansible_user_home.stdout }}/volumes"
- name: Configuring container image registries
become: true
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/volumes"
recurse: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "755"
state: directory
- name: Configuring container storage
become: true
become_user: "{{ current_user.stdout }}"
@@ -36,7 +36,7 @@
become_user: "{{ current_user.stdout }}"
community.general.npm:
path: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
state: latest
state: present
- name: Configuring quartz software
block:
- name: Creating path for Quartz content files (path for Obsidian vaults)
@@ -97,6 +97,13 @@
- plugin
- install
chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
- name: Creating directory for caddy configuration
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/srv/notes.{{ web_fqdn }}"
recurse: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
state: directory
- name: Starting quartz site web server
become: true
become_user: "{{ current_user.stdout }}"
@@ -15,13 +15,12 @@
ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/radicle-install.sh"
creates: "{{ ansible_user_home.stdout }}/.radicle"
async: 600
async: 300
poll: 5
- name: Bootstrapping Radicle
become: true
block:
- name: Linking binaries to directories already in PATH environment variable
ignore_errors: true
ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/.radicle/bin/{{ item }}"
dest: "/usr/bin/{{ item }}"
@@ -15,7 +15,7 @@
ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/rustup-install.sh -yq"
creates: "{{ ansible_user_home.stdout }}/.cargo/bin"
async: 600
async: 300
poll: 5
- name: Linking binaries to directories already in PATH environment variable
become: true
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,72 @@
- name: Getting public IP addresses
block:
- name: Getting public IPv4 address
community.general.ipify_facts:
validate_certs: false
timeout: 20
- name: Getting public IPv6 address
when: ipv6_enabled
ansible.builtin.shell:
cmd: curl -6 icanhazip.com
register: ipify_public_ip6
- name: Getting available network interfaces
ansible.builtin.shell:
cmd: "ip link show | awk '/^[0-9]+: [a-z]/ { print $2 }' | grep -vE 'lo[0-9]*|wg[0-9]+-mullvad' | sed 's/://g'"
register: intrfaces
- name: Turning acquired network interfaces into list
ansible.builtin.set_fact:
main_interfaces: "{{ intrfaces.stdout | replace('\n', ' ') | split(' ') }}"
- name: Enabling UFW startup
become: true
ansible.builtin.systemd_service:
name: ufw
scope: system
state: started
enabled: true
- name: Enabling firewall startup
community.general.ufw:
state: enabled
- name: Pre-emptively establishing firewall rules for loopback interface
become: true
block:
- name: Pre-emptively allowing inbound connections on loopback interface
community.general.ufw:
rule: allow
direction: in
interface: lo
- name: Allowing outbound connections on loopback interface
community.general.ufw:
rule: allow
direction: out
interface: lo
- name: Denying inbound connections from loopback address on rest of interfaces
community.general.ufw:
rule: deny
direction: in
interface: "{{ item[1] }}"
from_ip: "{{ item[0] }}"
loop: "{{ ['127.0.0.0/8', '::/128'] | product(main_interfaces) }}"
- name: Pre-emptively allowing rate-limited inbound SSH
become: true
community.general.ufw:
rule: allow
name: ssh
- name: Crafting additional exceptions to the inbound default policy
become: true
community.general.ufw:
rule: allow
direction: in
proto: "{{ item[1].protocol | default('tcp') }}"
interface: "{{ item[1].interface | default(item[0]) }}"
port: "{{ item[1].port }}"
loop: "{{ main_interfaces | product(iptables.allow.inbound) }}"
- name: Setting default policy for inbound connections
become: true
community.general.ufw:
direction: incoming
default: deny
- name: Setting default policy for outbound connections
become: true
community.general.ufw:
direction: outgoing
default: allow
@@ -15,7 +15,7 @@
ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/uv-install.sh"
creates: "{{ ansible_user_home.stdout }}/.local/bin/uv"
async: 600
async: 300
poll: 5
- name: Linking binaries to directories already in PATH environment variable
become: true
@@ -13,25 +13,33 @@
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: "1"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
- name: Marking IPv4 forwarded traffic as valid
ansible.posix.sysctl:
name: net.ipv4.conf.all.src_valid_mark
value: "1"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
- name: Enabling IPv6 forwarding
ansible.posix.sysctl:
name: net.ipv6.conf.all.forwarding
value: "1"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
- name: Marking IPv6 traffic as valid
ansible.posix.sysctl:
name: net.ipv6.conf.all.src_valid_mark
value: "1"
sysctl_file: /etc/sysctl.d/10-security.conf
sysctl_set: true
reload: true
state: present
- name: Preparing to allow Wireguard logging
when: "wireguard.debug"