diff options
author | 2023-06-01 22:40:36 +0100 | |
---|---|---|
committer | 2023-07-24 14:42:09 +0100 | |
commit | 0d8bb6829dfe9358ad29ac7f0bf9ef80fd553e3d (patch) | |
tree | 5b586b477335e08d5f8b6e9f62f59599c1c2cade | |
parent | Remove bad default fail2ban ignore IP (diff) |
Re-add previous ansible roles
Co-authored-by: Hassan Abouelela <[email protected]>
Co-authored-by: Johannes Christ <[email protected]>
Co-authored-by: Joe Banks <[email protected]>
Co-authored-by: MarkKoz <[email protected]>
30 files changed, 435 insertions, 93 deletions
diff --git a/inventory/.gitignore b/inventory/.gitignore deleted file mode 100644 index aa29d08..0000000 --- a/inventory/.gitignore +++ /dev/null @@ -1 +0,0 @@ -credentials/ diff --git a/inventory/README.md b/inventory/README.md deleted file mode 100644 index 294d80b..0000000 --- a/inventory/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Inventory -The main inventory for the pydis cluster. - -## Content -This directory is not covered by ansible-lint, and should generally not be used to add new configuration. -Instead, that should be placed appropriately within the project as normal. -- `hosts.yaml`: The main hosts file for our infrastructure. - -## Deployment -To deploy the kuberspray roles on our infrastructure, run the following commands in the root directory. - -### Environment -Run the following commands, then enter your sudo password in the file that opens: - -```shell -python3.10 -m venv venv -source venv/bin/activate -pip install -r kubespray/requirements-2.12.txt -export ANSIBLE_CONFIG=ansible.cfg -``` - -### Deployment -Enter your username into the command below, and run (this will take a while, so go grab a drink): - -``` -ansible-playbook kubespray/cluster.yml -v -u <user> -``` - -One useful argument for the command above is `--become-password-file` -which should point to a file with your sudo password for seamless execution. - -Additionally, you may find it helpful to pre-configure all hosts in known_hosts -to prevent the prompt from timing out during execution. This can be achieved by SSHing -into the machines beforehand, or running an ad-hoc command and confirming all hosts. diff --git a/inventory/hosts.yaml b/inventory/hosts.yaml index c9f597c..a6938c5 100644 --- a/inventory/hosts.yaml +++ b/inventory/hosts.yaml @@ -1,25 +1,20 @@ all: hosts: turing: - ansible_host: 89.58.25.151 - ip: 89.58.25.151 - access_ip: 89.58.25.151 - hopper: - ansible_host: 89.58.24.117 - ip: 89.58.24.117 - access_ip: 89.58.24.117 + ansible_host: turing.box.pydis.wtf + wireguard_subnet: 10.1.0.0/16 lovelace: - ansible_host: 89.58.26.118 - ip: 89.58.26.118 - access_ip: 89.58.26.118 + ansible_host: lovelace.box.pydis.wtf + wireguard_subnet: 10.2.0.0/16 + hopper: + ansible_host: hopper.box.pydis.wtf + wireguard_subnet: 10.3.0.0/16 ritchie: - ansible_host: 89.58.25.224 - ip: 89.58.25.224 - access_ip: 89.58.25.224 + ansible_host: ritchie.box.pydis.wtf + wireguard_subnet: 10.4.0.0/16 neumann: - ansible_host: 89.58.12.244 - ip: 89.58.12.244 - access_ip: 89.58.12.244 + ansible_host: neumann.box.pydis.wtf + wireguard_subnet: 10.5.0.0/16 children: podman: hosts: @@ -29,3 +24,5 @@ all: nginx: hosts: turing: + vars: + wireguard_port: 46850 diff --git a/inventory/inventory.ini b/inventory/inventory.ini deleted file mode 100644 index 99a6309..0000000 --- a/inventory/inventory.ini +++ /dev/null @@ -1,38 +0,0 @@ -# ## Configure 'ip' variable to bind kubernetes services on a -# ## different ip than the default iface -# ## We should set etcd_member_name for etcd cluster. The node that is not a etcd member do not need to set the value, or can set the empty string value. -[all] -# node1 ansible_host=95.54.0.12 # ip=10.3.0.1 etcd_member_name=etcd1 -# node2 ansible_host=95.54.0.13 # ip=10.3.0.2 etcd_member_name=etcd2 -# node3 ansible_host=95.54.0.14 # ip=10.3.0.3 etcd_member_name=etcd3 -# node4 ansible_host=95.54.0.15 # ip=10.3.0.4 etcd_member_name=etcd4 -# node5 ansible_host=95.54.0.16 # ip=10.3.0.5 etcd_member_name=etcd5 -# node6 ansible_host=95.54.0.17 # ip=10.3.0.6 etcd_member_name=etcd6 - -# ## configure a bastion host if your nodes are not directly reachable -# [bastion] -# bastion ansible_host=x.x.x.x ansible_user=some_user - -[kube_control_plane] -# node1 -# node2 -# node3 - -[etcd] -# node1 -# node2 -# node3 - -[kube_node] -# node2 -# node3 -# node4 -# node5 -# node6 - -[calico_rr] - -[k8s_cluster:children] -kube_control_plane -kube_node -calico_rr diff --git a/playbook.yml b/playbook.yml index 91a025c..995dc0b 100644 --- a/playbook.yml +++ b/playbook.yml @@ -4,6 +4,7 @@ - common - ufw - prometheus-node-exporter + - wireguard - fail2ban - name: Deploy our monitoring stack @@ -11,6 +12,15 @@ roles: - prometheus +- name: Deploy nginx & certbot to hosts + hosts: nginx + roles: + - certbot + - nginx + - nginx-geoip + - nginx-ufw + - nginx-cloudflare-mtls + - name: Deploy podman to container service hosts hosts: podman roles: diff --git a/roles/certbot/README.md b/roles/certbot/README.md new file mode 100644 index 0000000..b9d3e36 --- /dev/null +++ b/roles/certbot/README.md @@ -0,0 +1,3 @@ +# Role "certbot" + +Installs certbot and the Cloudflare DNS plugin for certbot to provision and deploy TLS certificates for web properties. diff --git a/roles/certbot/files/rsync.sh b/roles/certbot/files/rsync.sh new file mode 100644 index 0000000..fa9b27b --- /dev/null +++ b/roles/certbot/files/rsync.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Start the rsync server and perform the transfer +rrsync -wo /etc/letsencrypt/live + +# Reload NGINX +systemctl reload nginx diff --git a/roles/certbot/tasks/main.yml b/roles/certbot/tasks/main.yml new file mode 100644 index 0000000..abe22cc --- /dev/null +++ b/roles/certbot/tasks/main.yml @@ -0,0 +1,110 @@ +--- +- name: Install certbot and certbot Cloudflare plugin + when: inventory_hostname == ansible_play_hosts_all[0] + package: + name: + - python3-certbot + - python3-certbot-dns-cloudflare + state: present + tags: + - role::certbot + +- name: Install rsync on certbot hosts + package: + name: rsync + state: present + tags: + - role::certbot + +- name: Generate Cloudflare credentials file on designated leader + when: inventory_hostname == ansible_play_hosts_all[0] + copy: + content: | + # This file is managed by Ansible + dns_cloudflare_api_token = {{ certbot_cloudflare_token }} + dest: /etc/letsencrypt/cloudflare.ini + owner: root + group: root + mode: 0400 + tags: + - role::certbot + +- name: Generate SSH key for certificate distribution + when: inventory_hostname == ansible_play_hosts_all[0] + community.crypto.openssh_keypair: + path: /root/.ssh/cert_{{ item }}_key_ed25519 + type: ed25519 + state: present + comment: certificate distribution key for {{ item }} + with_items: + - "{{ ansible_play_hosts | reject('in', [inventory_hostname]) }}" + tags: + - role::certbot + register: generated_keys + +- name: Create certificate directories on replica certificate hosts + when: inventory_hostname != ansible_play_hosts[0] + file: + path: /etc/letsencrypt/live + recurse: true + state: directory + owner: root + group: root + mode: 0700 + tags: + - role::certbot + +- name: Install rsync + nginx reload script to replica servers + when: inventory_hostname != ansible_play_hosts[0] + copy: + src: rsync.sh + dest: /opt/cert_rsync.sh + owner: root + group: root + mode: 0500 + tags: + - role::certbot + +- name: Install certificate distribution keys to other NGINX nodes + when: inventory_hostname != ansible_play_hosts[0] + ansible.posix.authorized_key: + user: root + state: present + key: | + {{ hostvars[ansible_play_hosts_all[0]]['generated_keys']['results'] + | selectattr('item', 'equalto', inventory_hostname) + | map(attribute='public_key') + | first }} + comment: "certificate distribution key" + key_options: 'from="{{ hostvars[ansible_play_hosts_all[0]]["wireguard_subnet"] }}",restrict,command="/opt/cert_rsync.sh"' + tags: + - role::certbot + +- name: Create renewal hook to synchronize certificates + when: inventory_hostname == ansible_play_hosts_all[0] + template: + src: renewal-hook.sh.j2 + dest: /etc/letsencrypt/renewal-hooks/deploy/distribute-certs + owner: root + group: root + mode: 0700 + tags: + - role::certbot + +- name: Request certificates for configured domains + when: inventory_hostname == ansible_play_hosts_all[0] + command: | + certbot certonly + --agree-tos + --non-interactive + --email {{ certbot_email }} + --dns-cloudflare + --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini + --deploy-hook /etc/letsencrypt/renewal-hooks/deploy/distribute-certs + -d {{ item }} -d *.{{ item }} -d cloud.native.is.fun.and.easy.pydis.wtf + args: + creates: "/etc/letsencrypt/live/{{ item }}/fullchain.pem" + with_items: + - "{{ certbot_domains }}" + tags: + - role::certbot diff --git a/roles/certbot/templates/renewal-hook.sh.j2 b/roles/certbot/templates/renewal-hook.sh.j2 new file mode 100644 index 0000000..7fa7252 --- /dev/null +++ b/roles/certbot/templates/renewal-hook.sh.j2 @@ -0,0 +1,6 @@ +#!/bin/sh +set -ex + +{% for host in ansible_play_hosts if host != inventory_hostname %} +rsync --copy-links --delete --recursive -e "ssh -i /root/.ssh/cert_{{ host }}_key_ed25519 -o StrictHostKeyChecking=accept-new" /etc/letsencrypt/live/* root@{{ hostvars[host]['wireguard_subnet'] | split("/") | first }}:/etc/letsencrypt/live +{% endfor %} diff --git a/roles/certbot/vars/main/main.yml b/roles/certbot/vars/main/main.yml new file mode 100644 index 0000000..fdfc7b1 --- /dev/null +++ b/roles/certbot/vars/main/main.yml @@ -0,0 +1,6 @@ +--- +certbot_cloudflare_token: "{{ encrypted_cloudflare_token }}" +certbot_email: "[email protected]" +certbot_domains: + - pydis.wtf + - pythondiscord.com diff --git a/roles/certbot/vars/main/vault.yml b/roles/certbot/vars/main/vault.yml new file mode 100644 index 0000000..c669b69 --- /dev/null +++ b/roles/certbot/vars/main/vault.yml @@ -0,0 +1,9 @@ +$ANSIBLE_VAULT;1.1;AES256 +66336535306366333038666137306135663438346366643735383962623339636236343438633766 +6565343931306531623330373936313730353539303264390a333031363634663236636232386461 +34353239643364653464373531653236383963303137326438343239313136376537336636326162 +3537383737323732310a623836363138646434636165643130366362656661393937346534313632 +37663966613031363036623838326666636231313462363831396366363837343632646131303863 +35363032386463346164623733656463633735376161653361343231326166313466643236623762 +31343562323362353238663666303435353138643463656531373466336639316464376632623731 +32646464393438656134 diff --git a/roles/nginx-cloudflare-mtls/README.md b/roles/nginx-cloudflare-mtls/README.md new file mode 100644 index 0000000..081cacb --- /dev/null +++ b/roles/nginx-cloudflare-mtls/README.md @@ -0,0 +1,16 @@ +# Role "nginx-cloudflare-mtls" + +Installs the certificate required for performing mutual TLS authentication +between NGINX and Cloudflare. + +To use mutual TLS in your NGINX virtual hosts, add this configuration snippet: + +```nginx +ssl_client_certificate {{ nginx_cloudflare_mtls_certificate_path }}; +ssl_verify_client on; +``` + + +## Variables + +See [role defaults](./defaults/main.yml) for an annotated overview. diff --git a/roles/nginx-cloudflare-mtls/defaults/main.yml b/roles/nginx-cloudflare-mtls/defaults/main.yml new file mode 100644 index 0000000..ff1c667 --- /dev/null +++ b/roles/nginx-cloudflare-mtls/defaults/main.yml @@ -0,0 +1,3 @@ +--- +# The path at which to install the certificate. +nginx_cloudflare_mtls_certificate_path: /etc/nginx/certs/cloudflare.crt diff --git a/roles/nginx-cloudflare-mtls/files/cloudflare.crt b/roles/nginx-cloudflare-mtls/files/cloudflare.crt new file mode 100644 index 0000000..965f0bf --- /dev/null +++ b/roles/nginx-cloudflare-mtls/files/cloudflare.crt @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGCjCCA/KgAwIBAgIIV5G6lVbCLmEwDQYJKoZIhvcNAQENBQAwgZAxCzAJBgNV +BAYTAlVTMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMRQwEgYDVQQLEwtPcmln +aW4gUHVsbDEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv +cm5pYTEjMCEGA1UEAxMab3JpZ2luLXB1bGwuY2xvdWRmbGFyZS5uZXQwHhcNMTkx +MDEwMTg0NTAwWhcNMjkxMTAxMTcwMDAwWjCBkDELMAkGA1UEBhMCVVMxGTAXBgNV +BAoTEENsb3VkRmxhcmUsIEluYy4xFDASBgNVBAsTC09yaWdpbiBQdWxsMRYwFAYD +VQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMSMwIQYDVQQD +ExpvcmlnaW4tcHVsbC5jbG91ZGZsYXJlLm5ldDCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAN2y2zojYfl0bKfhp0AJBFeV+jQqbCw3sHmvEPwLmqDLqynI +42tZXR5y914ZB9ZrwbL/K5O46exd/LujJnV2b3dzcx5rtiQzso0xzljqbnbQT20e +ihx/WrF4OkZKydZzsdaJsWAPuplDH5P7J82q3re88jQdgE5hqjqFZ3clCG7lxoBw +hLaazm3NJJlUfzdk97ouRvnFGAuXd5cQVx8jYOOeU60sWqmMe4QHdOvpqB91bJoY +QSKVFjUgHeTpN8tNpKJfb9LIn3pun3bC9NKNHtRKMNX3Kl/sAPq7q/AlndvA2Kw3 +Dkum2mHQUGdzVHqcOgea9BGjLK2h7SuX93zTWL02u799dr6Xkrad/WShHchfjjRn +aL35niJUDr02YJtPgxWObsrfOU63B8juLUphW/4BOjjJyAG5l9j1//aUGEi/sEe5 +lqVv0P78QrxoxR+MMXiJwQab5FB8TG/ac6mRHgF9CmkX90uaRh+OC07XjTdfSKGR +PpM9hB2ZhLol/nf8qmoLdoD5HvODZuKu2+muKeVHXgw2/A6wM7OwrinxZiyBk5Hh +CvaADH7PZpU6z/zv5NU5HSvXiKtCzFuDu4/Zfi34RfHXeCUfHAb4KfNRXJwMsxUa ++4ZpSAX2G6RnGU5meuXpU5/V+DQJp/e69XyyY6RXDoMywaEFlIlXBqjRRA2pAgMB +AAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1Ud +DgQWBBRDWUsraYuA4REzalfNVzjann3F6zAfBgNVHSMEGDAWgBRDWUsraYuA4REz +alfNVzjann3F6zANBgkqhkiG9w0BAQ0FAAOCAgEAkQ+T9nqcSlAuW/90DeYmQOW1 +QhqOor5psBEGvxbNGV2hdLJY8h6QUq48BCevcMChg/L1CkznBNI40i3/6heDn3IS +zVEwXKf34pPFCACWVMZxbQjkNRTiH8iRur9EsaNQ5oXCPJkhwg2+IFyoPAAYURoX +VcI9SCDUa45clmYHJ/XYwV1icGVI8/9b2JUqklnOTa5tugwIUi5sTfipNcJXHhgz +6BKYDl0/UP0lLKbsUETXeTGDiDpxZYIgbcFrRDDkHC6BSvdWVEiH5b9mH2BON60z +0O0j8EEKTwi9jnafVtZQXP/D8yoVowdFDjXcKkOPF/1gIh9qrFR6GdoPVgB3SkLc +5ulBqZaCHm563jsvWb/kXJnlFxW+1bsO9BDD6DweBcGdNurgmH625wBXksSdD7y/ +fakk8DagjbjKShYlPEFOAqEcliwjF45eabL0t27MJV61O/jHzHL3dknXeE4BDa2j +bA+JbyJeUMtU7KMsxvx82RmhqBEJJDBCJ3scVptvhDMRrtqDBW5JShxoAOcpFQGm +iYWicn46nPDjgTU0bX1ZPpTpryXbvciVL5RkVBuyX2ntcOLDPlZWgxZCBp96x07F +AnOzKgZk4RzZPNAxCXERVxajn/FLcOhglVAKo5H0ac+AitlQ0ip55D2/mf8o72tM +fVQ6VpyjEXdiIXWUq/o= +-----END CERTIFICATE----- diff --git a/roles/nginx-cloudflare-mtls/meta/main.yml b/roles/nginx-cloudflare-mtls/meta/main.yml new file mode 100644 index 0000000..72b1bd7 --- /dev/null +++ b/roles/nginx-cloudflare-mtls/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - nginx diff --git a/roles/nginx-cloudflare-mtls/tasks/main.yml b/roles/nginx-cloudflare-mtls/tasks/main.yml new file mode 100644 index 0000000..d5ef7f4 --- /dev/null +++ b/roles/nginx-cloudflare-mtls/tasks/main.yml @@ -0,0 +1,20 @@ +--- +- name: Create nginx certificates directory + file: + path: /etc/nginx/certs + state: directory + owner: root + group: root + mode: 0444 + tags: + - role::nginx-cloudflare-mtls + +- name: Copy the cloudflare mutual TLS certificate + copy: + src: cloudflare.crt + dest: /etc/nginx/certs/cloudflare.crt + owner: root + group: root + mode: 0444 + tags: + - role::nginx-cloudflare-mtls diff --git a/roles/nginx-geoip/meta/main.yml b/roles/nginx-geoip/meta/main.yml new file mode 100644 index 0000000..72b1bd7 --- /dev/null +++ b/roles/nginx-geoip/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - nginx diff --git a/roles/nginx-geoip/tasks/main.yml b/roles/nginx-geoip/tasks/main.yml new file mode 100644 index 0000000..f772278 --- /dev/null +++ b/roles/nginx-geoip/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: Configure the geoip module + copy: + # ref https://nginx.org/en/docs/http/ngx_http_geoip_module.html + content: geoip_country /usr/share/GeoIP/GeoIP.dat; + dest: /etc/nginx/conf.d/geoip.conf + owner: root + group: root + mode: 0444 + tags: + - role::nginx-geoip + notify: + - reload the nginx service diff --git a/roles/nginx-ufw/README.md b/roles/nginx-ufw/README.md new file mode 100644 index 0000000..e657afb --- /dev/null +++ b/roles/nginx-ufw/README.md @@ -0,0 +1,3 @@ +# Role "nginx-ufw" + +Allows NGINX HTTP and HTTPS traffic through the UFW firewall. diff --git a/roles/nginx-ufw/meta/main.yml b/roles/nginx-ufw/meta/main.yml new file mode 100644 index 0000000..dac7049 --- /dev/null +++ b/roles/nginx-ufw/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - nginx + - ufw diff --git a/roles/nginx-ufw/tasks/main.yml b/roles/nginx-ufw/tasks/main.yml new file mode 100644 index 0000000..fb703bf --- /dev/null +++ b/roles/nginx-ufw/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Allow http(s) traffic through the firewall + ufw: + app: Nginx Full + rule: allow + tags: + - role::nginx-ufw diff --git a/roles/nginx/README.md b/roles/nginx/README.md new file mode 100644 index 0000000..9961a69 --- /dev/null +++ b/roles/nginx/README.md @@ -0,0 +1,3 @@ +# Role "nginx" + +Installs nginx on target hosts and provides a handler for reloading nginx, for instance on configuration change. diff --git a/roles/nginx/files/default_server.conf b/roles/nginx/files/default_server.conf new file mode 100644 index 0000000..13e74a0 --- /dev/null +++ b/roles/nginx/files/default_server.conf @@ -0,0 +1,24 @@ +# Managed by Ansible +server { + listen 443 ssl http2 default_server; + + ssl_certificate /etc/letsencrypt/live/pydis.wtf/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/pydis.wtf/privkey.pem; + + location / { + set_by_lua_block $url { + local urls = { + "https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-ride", + "https://en.wikipedia.org/wiki/Tax_evasion", + "https://jchri.st/blog/apfs-sadness-on-macos-big-sur.html", + "https://cdn.discordapp.com/attachments/675756741417369640/852688961516077086/Screenshot_2021-06-11_at_00.21.22.png", + "https://news.ycombinator.com/", + "https://www.hertfordshire.gov.uk/latest/letchworth-webcam.jpg", + "https://media.discordapp.net/attachments/922169059175444501/952929630459924501/1svkf3xto3n61.png" + } + return urls [ math.random(#urls) ] + } + + return 302 $url; + } +} diff --git a/roles/nginx/handlers/main.yml b/roles/nginx/handlers/main.yml new file mode 100644 index 0000000..376d85a --- /dev/null +++ b/roles/nginx/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: reload the nginx service + service: + name: nginx + state: reloaded + tags: + - role::nginx diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml new file mode 100644 index 0000000..3419cb3 --- /dev/null +++ b/roles/nginx/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- name: Install NGINX & modules + package: + name: + - nginx + - libnginx-mod-http-lua + state: present + tags: + - role::nginx + +- name: Copy NGINX default config + copy: + src: default_server.conf + dest: /etc/nginx/conf.d/default_server.conf + group: root + owner: root + mode: 0644 + tags: + - role::nginx + notify: + - reload the nginx service diff --git a/roles/postgres/tasks/main.yml b/roles/postgres/tasks/main.yml index 01638af..9551c4e 100644 --- a/roles/postgres/tasks/main.yml +++ b/roles/postgres/tasks/main.yml @@ -1,4 +1,4 @@ -- name: Install postgres packages. +- name: Install postgres packages apt: name: - python3-psycopg2 @@ -9,7 +9,7 @@ tags: - role::postgres -- name: Check postgres is started and enabled on boot. +- name: Check postgres is started and enabled on boot service: name: '{{ postgresql_daemon }}' state: started @@ -17,7 +17,7 @@ tags: - role::postgres -- name: Add postgres users. +- name: Add postgres users community.postgresql.postgresql_user: "{{ item }}" with_items: "{{ postgresql_users }}" become: true @@ -25,7 +25,7 @@ tags: - role::postgres -- name: Add postgres databases. +- name: Add postgres databases community.postgresql.postgresql_db: "{{ item }}" with_items: "{{ postgresql_databases }}" become: true diff --git a/roles/wireguard/defaults/main/vars.yml b/roles/wireguard/defaults/main/vars.yml new file mode 100644 index 0000000..10c80ae --- /dev/null +++ b/roles/wireguard/defaults/main/vars.yml @@ -0,0 +1,4 @@ +extra_keys: + - name: Joe + pubkey: /dJ+tKXzxv7nrUleNlF+CGyq7OIVlqL8/9Sn8j+cEAc= + subnet: 10.0.1.0/24 diff --git a/roles/wireguard/handlers/main.yml b/roles/wireguard/handlers/main.yml new file mode 100644 index 0000000..0edcf3a --- /dev/null +++ b/roles/wireguard/handlers/main.yml @@ -0,0 +1,4 @@ +- name: reload wg-quick + service: + name: wg-quick@wg0 + state: reloaded diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml new file mode 100644 index 0000000..46ff3e9 --- /dev/null +++ b/roles/wireguard/tasks/main.yml @@ -0,0 +1,72 @@ +- name: Install WireGuard + apt: + update_cache: true + cache_valid_time: 3600 + pkg: + - wireguard + - wireguard-tools + - linux-headers-{{ ansible_kernel }} + tags: + - role::wireguard + +- name: Generate WireGuard private key + shell: set -o pipefail && wg genkey > /etc/wireguard/key.priv + args: + executable: /bin/bash + creates: /etc/wireguard/key.priv + tags: + - role::wireguard + +- name: Generate WireGuard public key + shell: set -o pipefail && cat /etc/wireguard/key.priv | wg pubkey > /etc/wireguard/key.pub + args: + executable: /bin/bash + creates: /etc/wireguard/key.pub + tags: + - role::wireguard + +- name: Ensure file permissions for keys set correctly + file: + path: '{{ item }}' + owner: root + group: root + mode: '0600' + with_items: + - /etc/wireguard/key.priv + - /etc/wireguard/key.pub + tags: + - role::wireguard + +- name: Fetch private key for all hosts + slurp: + src: /etc/wireguard/key.priv + register: wg_priv_key + tags: + - role::wireguard + +- name: Fetch public key for all hosts + slurp: + src: /etc/wireguard/key.pub + register: wg_pub_key + tags: + - role::wireguard + +- name: Generate WireGuard configuration file + template: + src: wg0.conf.j2 + dest: /etc/wireguard/wg0.conf + mode: '0600' + group: root + owner: root + notify: + - reload wg-quick + tags: + - role::wireguard + +- name: Start and enable the WireGuard service + service: + name: wg-quick@wg0 + enabled: true + state: started + tags: + - role::wireguard diff --git a/roles/wireguard/templates/wg0.conf.j2 b/roles/wireguard/templates/wg0.conf.j2 new file mode 100644 index 0000000..647854a --- /dev/null +++ b/roles/wireguard/templates/wg0.conf.j2 @@ -0,0 +1,25 @@ +# Configuration managed by Ansible +[Interface] +Address = {{ wireguard_subnet }} +ListenPort = {{ wireguard_port }} +PrivateKey = {{ wg_priv_key['content'] | b64decode | trim }} + +PostUp = ip route add local {{ wireguard_subnet }} dev eth0 + +{% for host in hostvars.keys() if not host == inventory_hostname %} +# Peer config for: {{ host }} +[Peer] +AllowedIPs = {{ hostvars[host]['wireguard_subnet'] }} +PublicKey = {{ hostvars[host]['wg_pub_key']['content'] | b64decode | trim }} +Endpoint = {{ host }}.box.pydis.wtf:{{ wireguard_port }} +PersistentKeepalive = 30 + +{% endfor %} + +{% for key in extra_keys %} +# DevOps config for: {{ key.name }} +[Peer] +AllowedIPs = {{ key.subnet }} +PublicKey = {{ key.pubkey }} + +{% endfor %} |