Migrated to multiple nginx servers for better service isolation
This commit is contained in:
parent
bc78dbe6e1
commit
258feb3c97
75
group_vars/ext_nginx.yml
Normal file
75
group_vars/ext_nginx.yml
Normal file
@ -0,0 +1,75 @@
|
||||
cert_domains:
|
||||
- files.ezri.dev
|
||||
- git.ezri.dev
|
||||
- idm.ezri.dev
|
||||
- jellyfin.ezri.dev
|
||||
- mail.ezri.dev
|
||||
- navidrome.ezri.dev
|
||||
- vtt.ezri.dev
|
||||
|
||||
sites_available:
|
||||
- fqdn: files.ezri.dev
|
||||
enabled: yes
|
||||
upstream: http://10.242.202.90:9001
|
||||
max_upload: 0
|
||||
|
||||
- fqdn: git.ezri.dev
|
||||
enabled: yes
|
||||
upstream: http://10.242.202.90:30008
|
||||
|
||||
- fqdn: jellyfin.ezri.dev
|
||||
enabled: yes
|
||||
upstream: http://10.242.202.90:30013
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
- 10.242.4.0/24
|
||||
|
||||
- fqdn: navidrome.ezri.dev
|
||||
enabled: yes
|
||||
upstream: http://10.242.202.90:30043
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
- 10.242.4.0/24
|
||||
|
||||
- fqdn: mail.ezri.dev
|
||||
enabled: yes
|
||||
upstream: http://10.242.203.13:8000
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
|
||||
- fqdn: vtt.ezri.dev
|
||||
enabled: no
|
||||
upstream: http://10.242.203.13:3000
|
||||
max_upload: 512M
|
||||
|
||||
- fqdn: idm.ezri.dev
|
||||
enabled: yes
|
||||
upstream: https://10.242.203.13:8443
|
||||
|
||||
streams_available:
|
||||
- fqdn: git.ezri.dev
|
||||
enabled: yes
|
||||
listen_port: 22
|
||||
ssl: no
|
||||
upstream: 10.242.202.90:30009
|
||||
|
||||
- fqdn: idm.ezri.dev
|
||||
enabled: yes
|
||||
listen_port: 636
|
||||
ssl: yes
|
||||
cert_domain: idm.ezri.dev
|
||||
upstream: 10.242.203.13:3636
|
||||
upstream_ssl: yes
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.200.0/24
|
||||
- 10.242.0.1
|
||||
- 10.242.203.1
|
||||
- 10.242.203.13
|
||||
- 10.242.3.0/24
|
||||
59
group_vars/int_nginx.yml
Normal file
59
group_vars/int_nginx.yml
Normal file
@ -0,0 +1,59 @@
|
||||
cert_domains:
|
||||
- vw.ezri.dev
|
||||
|
||||
wildcard_domains:
|
||||
- internal.ezri.dev
|
||||
|
||||
sites_available:
|
||||
- fqdn: lidarr.internal.ezri.dev
|
||||
enabled: yes
|
||||
cert_domain: internal.ezri.dev
|
||||
upstream: http://10.242.201.3:8686
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
|
||||
- fqdn: radarr.internal.ezri.dev
|
||||
enabled: yes
|
||||
cert_domain: internal.ezri.dev
|
||||
upstream: http://10.242.201.3:7878
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
|
||||
- fqdn: sonarr.internal.ezri.dev
|
||||
enabled: yes
|
||||
cert_domain: internal.ezri.dev
|
||||
upstream: https://10.242.201.3:8989
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
|
||||
- fqdn: prowlarr.internal.ezri.dev
|
||||
enabled: yes
|
||||
cert_domain: internal.ezri.dev
|
||||
upstream: http://10.242.201.3:9696
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
|
||||
- fqdn: qbittorrent.internal.ezri.dev
|
||||
enabled: yes
|
||||
cert_domain: internal.ezri.dev
|
||||
upstream: http://10.242.201.2:8080
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
|
||||
- fqdn: vw.ezri.dev
|
||||
enabled: yes
|
||||
upstream: http://10.242.202.90:30032
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/23
|
||||
- 10.242.3.0/24
|
||||
@ -29,6 +29,9 @@ sites_available:
|
||||
cert_domain: ezri.dev
|
||||
upstream: http://10.242.2.2:30013
|
||||
restricted: yes
|
||||
allowed_ips:
|
||||
- 10.242.0.0/16
|
||||
- 68.5.180.44/32
|
||||
|
||||
- fqdn: lidarr.internal.ezri.dev
|
||||
enabled: yes
|
||||
@ -125,6 +128,7 @@ sites_available:
|
||||
allowed_ips:
|
||||
- 10.242.0.0/16
|
||||
- 129.123.107.0/24
|
||||
- 50.39.97.200/32
|
||||
|
||||
streams_available:
|
||||
- fqdn: git.ezri.dev
|
||||
|
||||
14
inventory
14
inventory
@ -50,4 +50,16 @@ sysadmin_exercise:
|
||||
nginx:
|
||||
hosts:
|
||||
peoples-home.servers.ezri.dev:
|
||||
|
||||
|
||||
ext_nginx:
|
||||
hosts:
|
||||
assurance-of-peace.ext.ezri.dev:
|
||||
ansible_port: 2231
|
||||
ansible_user: localadmin
|
||||
ansible_become: yes
|
||||
|
||||
int_nginx:
|
||||
hosts:
|
||||
peoples-home.int.ezri.dev:
|
||||
ansible_user: localadmin
|
||||
ansible_become: yes
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
---
|
||||
|
||||
- name: Configure Nginx proxy
|
||||
hosts: nginx
|
||||
hosts:
|
||||
- ext_nginx
|
||||
- int_nginx
|
||||
vars_prompt:
|
||||
- name: admin_password
|
||||
prompt: Enter the administrator password that will be used for this system
|
||||
|
||||
- name: cloudflare_api_token
|
||||
prompt: Enter the cloudflare API token to manage DNS records for certs
|
||||
|
||||
roles:
|
||||
- common
|
||||
- nginx
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
---
|
||||
|
||||
- name: Create wheel group
|
||||
ansible.builtin.group:
|
||||
name: wheel
|
||||
state: present
|
||||
system: yes
|
||||
# - name: Create wheel group
|
||||
# ansible.builtin.group:
|
||||
# name: wheel
|
||||
# state: present
|
||||
# system: yes
|
||||
|
||||
- name: Create local administrator
|
||||
ansible.builtin.user:
|
||||
state: present
|
||||
name: localadmin
|
||||
uid: 1000
|
||||
groups:
|
||||
- wheel
|
||||
create_home: yes
|
||||
# Salt the password with the inventory name, this should be static between runs
|
||||
password: '{{ admin_password|password_hash("sha512", "thisisabadsalt") }}'
|
||||
# - name: Create local administrator
|
||||
# ansible.builtin.user:
|
||||
# state: present
|
||||
# name: localadmin
|
||||
# uid: 1000
|
||||
# groups:
|
||||
# - wheel
|
||||
# create_home: yes
|
||||
# # Salt the password with the inventory name, this should be static between runs
|
||||
# password: '{{ admin_password|password_hash("sha512", "thisisabadsalt") }}'
|
||||
|
||||
- name: Load Arch tasks
|
||||
import_tasks: arch.yml
|
||||
@ -46,12 +46,12 @@
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Configure SSH server
|
||||
ansible.builtin.template:
|
||||
src: sshd_config.j2
|
||||
dest: /etc/ssh/sshd_config
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart SSH
|
||||
# - name: Configure SSH server
|
||||
# ansible.builtin.template:
|
||||
# src: sshd_config.j2
|
||||
# dest: /etc/ssh/sshd_config
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: "0644"
|
||||
# notify: Restart SSH
|
||||
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
---
|
||||
|
||||
- name: Install Nginx
|
||||
- name: Install Nginx and certbot
|
||||
ansible.builtin.apt:
|
||||
name: nginx
|
||||
name:
|
||||
- nginx
|
||||
- libnginx-mod-stream
|
||||
- certbot
|
||||
- python3-dnspython
|
||||
- python3-certbot-dns-cloudflare
|
||||
state: present
|
||||
|
||||
- name: Allow ports 80 and 443
|
||||
@ -13,6 +18,72 @@
|
||||
rule: allow
|
||||
to_port: '{{ item }}'
|
||||
|
||||
- name: Check for existence of certificates
|
||||
ansible.builtin.stat:
|
||||
path: /etc/letsencrypt/live/{{ item }}/fullchain.pem
|
||||
loop: '{{ [cert_domains | default([]), wildcard_domains | default([]) ] | flatten }}'
|
||||
register: cert_check
|
||||
|
||||
- name: Deploy cloudflare secret
|
||||
ansible.builtin.template:
|
||||
src: certbot_secrets.j2
|
||||
dest: /etc/letsencrypt/secrets
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
# Only run this when it is defined
|
||||
when: cloudflare_api_token is defined and not cloudflare_api_token == ""
|
||||
|
||||
- name: Verify cloudflare secret exists
|
||||
# This is so the above conditional works; we only need to specify the API token on first run or when it changes; that said, if the variable
|
||||
# is undefined and we haven't deployed the secret before, that's a problem.
|
||||
ansible.builtin.stat:
|
||||
path: /etc/letsencrypt/secrets
|
||||
register: check_secret
|
||||
failed_when: not check_secret.stat.exists
|
||||
|
||||
- name: Request acmedns challenges for uncertified domains
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- certbot
|
||||
- certonly
|
||||
- '--dns-cloudflare'
|
||||
- '--non-interactive'
|
||||
- '--agree-tos'
|
||||
- '-m'
|
||||
- 'sysadmins@ezri.dev'
|
||||
- '--dns-cloudflare-propagation-seconds'
|
||||
- '30'
|
||||
- '--dns-cloudflare-credentials'
|
||||
- '/etc/letsencrypt/secrets'
|
||||
- '-d'
|
||||
- '{{ item }}'
|
||||
loop: '{{ cert_domains | default([]) }}'
|
||||
loop_control:
|
||||
index_var: idx
|
||||
when: not cert_check.results[idx].stat.exists
|
||||
|
||||
- name: Request acmedns challenges for uncertified wildcard domains
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- certbot
|
||||
- certonly
|
||||
- '--dns-cloudflare'
|
||||
- '--non-interactive'
|
||||
- '--agree-tos'
|
||||
- '-m'
|
||||
- 'sysadmins@ezri.dev'
|
||||
- '--dns-cloudflare-propagation-seconds'
|
||||
- '30'
|
||||
- '--dns-cloudflare-credentials'
|
||||
- '/etc/letsencrypt/secrets'
|
||||
- '-d'
|
||||
- '*.{{ item }}'
|
||||
loop: '{{ wildcard_domains | default([]) }}'
|
||||
loop_control:
|
||||
index_var: idx
|
||||
when: not cert_check.results[idx + ((cert_domains | default([])) | length)].stat.exists
|
||||
|
||||
- name: Create config directories
|
||||
loop:
|
||||
- /etc/nginx
|
||||
@ -48,16 +119,26 @@
|
||||
|
||||
- name: Enable site configurations
|
||||
loop: '{{ sites_available }}'
|
||||
when: item.enabled
|
||||
ansible.builtin.file:
|
||||
src: ../sites-available/{{ item.fqdn }}.conf
|
||||
dest: /etc/nginx/sites-enabled/{{ item.fqdn }}.conf
|
||||
state: '{{ item.enabled|ternary("link", "absent") }}'
|
||||
state: link
|
||||
owner: root
|
||||
group: root
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Disable site configurations
|
||||
loop: '{{ sites_available }}'
|
||||
when: not item.enabled
|
||||
ansible.builtin.file:
|
||||
dest: /etc/nginx/sites-enabled/{{ item.fqdn }}.conf
|
||||
state: absent
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Deploy stream configurations
|
||||
loop: '{{ streams_available }}'
|
||||
when: streams_available is defined
|
||||
ansible.builtin.template:
|
||||
src: stream.j2
|
||||
dest: /etc/nginx/streams-available/{{ item.fqdn }}.conf
|
||||
@ -67,17 +148,27 @@
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Enable stream configurations
|
||||
loop: '{{ streams_available }}'
|
||||
loop: '{{ streams_available | default([]) }}'
|
||||
when: item.enabled
|
||||
ansible.builtin.file:
|
||||
src: ../streams-available/{{ item.fqdn }}.conf
|
||||
dest: /etc/nginx/streams-enabled/{{ item.fqdn }}.conf
|
||||
state: '{{ item.enabled|ternary("link", "absent") }}'
|
||||
state: link
|
||||
owner: root
|
||||
group: root
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Disable stream configurations
|
||||
loop: '{{ streams_available | default([]) }}'
|
||||
when: not item.enabled
|
||||
ansible.builtin.file:
|
||||
dest: /etc/nginx/streams-enabled/{{ item.fqdn }}.conf
|
||||
state: absent
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Allow connections to enabled streams
|
||||
loop: '{{ streams_available }}'
|
||||
when: streams_available is defined
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
to_port: '{{ item.listen_port }}'
|
||||
|
||||
1
playbooks/roles/nginx/templates/certbot_secrets.j2
Normal file
1
playbooks/roles/nginx/templates/certbot_secrets.j2
Normal file
@ -0,0 +1 @@
|
||||
dns_cloudflare_api_token = {{ cloudflare_api_token }}
|
||||
@ -10,8 +10,8 @@ server {
|
||||
|
||||
server_name {{ item.fqdn }};
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/{{ item.cert_domain }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ item.cert_domain }}/privkey.pem;
|
||||
ssl_certificate /etc/letsencrypt/live/{{ item.cert_domain|default(item.fqdn) }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ item.cert_domain|default(item.fqdn) }}/privkey.pem;
|
||||
|
||||
if ($scheme = "http") {
|
||||
return 301 https://$host$request_uri;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user