From b61dea12db2f05bbaa312859a0dfe2096e813be3 Mon Sep 17 00:00:00 2001 From: Ezri Brimhall Date: Sun, 15 Sep 2024 11:34:46 -0600 Subject: [PATCH] Nginx is now managed through ansible --- group_vars/nginx.yml | 140 ++++++++++++++++++++++ inventory | 3 + playbooks/deploy-nginx.yml | 6 + playbooks/roles/nginx/files/nginx.conf | 91 ++++++++++++++ playbooks/roles/nginx/handlers/main.yml | 6 + playbooks/roles/nginx/tasks/main.yml | 76 ++++++++++++ playbooks/roles/nginx/templates/site.j2 | 44 +++++++ playbooks/roles/nginx/templates/stream.j2 | 29 +++++ 8 files changed, 395 insertions(+) create mode 100644 group_vars/nginx.yml create mode 100644 playbooks/deploy-nginx.yml create mode 100644 playbooks/roles/nginx/files/nginx.conf create mode 100644 playbooks/roles/nginx/handlers/main.yml create mode 100644 playbooks/roles/nginx/tasks/main.yml create mode 100644 playbooks/roles/nginx/templates/site.j2 create mode 100644 playbooks/roles/nginx/templates/stream.j2 diff --git a/group_vars/nginx.yml b/group_vars/nginx.yml new file mode 100644 index 0000000..3573578 --- /dev/null +++ b/group_vars/nginx.yml @@ -0,0 +1,140 @@ +sites_available: + - fqdn: ds9.internal.ezri.dev + enabled: yes + cert_domain: internal.ezri.dev + upstream: https://10.242.2.10:8006 + restricted: yes + allowed_ips: + - 10.242.0.2 + - 10.242.3.0/24 + + - fqdn: files.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.2:9001 + + - fqdn: git.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.2:30008 + + - fqdn: idm.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: https://10.242.2.13:8443 + + - fqdn: jellyfin.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.2:30013 + restricted: yes + + - fqdn: lidarr.internal.ezri.dev + enabled: yes + cert_domain: internal.ezri.dev + upstream: http://10.242.2.12:8686 + restricted: yes + allowed_ips: + # Wired and wireless + - 10.242.0.0/23 + # VPN + - 10.242.3.0/24 + + - fqdn: mail.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.13:8000 + restricted: yes + allowed_ips: + # Wired, wireless, VPN + - 10.242.0.0/23 + - 10.242.3.0/24 + + - fqdn: navidrome.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.2:30043 + restricted: yes + + - fqdn: prowlarr.internal.ezri.dev + enabled: yes + cert_domain: internal.ezri.dev + upstream: http://10.242.2.12: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.2.11:8080 + 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.2.12: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: http://10.242.2.12:8989 + restricted: yes + allowed_ips: + - 10.242.0.0/23 + - 10.242.3.0/24 + + - fqdn: spacedock.internal.ezri.dev + enabled: yes + cert_domain: internal.ezri.dev + upstream: http://10.242.2.2:80 + restricted: yes + allowed_ips: + - 10.242.0.2 + - 10.242.3.0/24 + + - fqdn: vtt.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.13:3000 + max_upload: 512M + + - fqdn: vw.ezri.dev + enabled: yes + cert_domain: ezri.dev + upstream: http://10.242.2.2:30032 + allowed_ips: + - 10.242.0.0/23 + - 10.242.3.0/24 + +streams_available: + - fqdn: git.ezri.dev + enabled: yes + listen_port: 2231 + ssl: no + upstream: 10.242.2.2:30009 + upstream_ssl: no + + - fqdn: idm.ezri.dev + enabled: yes + listen_port: 636 + ssl: yes + cert_domain: ezri.dev + upstream: 10.242.2.13:3636 + upstream_ssl: yes + restricted: yes + allowed_ips: + - 10.242.2.2 + - 10.242.0.1 + - 10.242.2.1 + - 10.242.0.2 + - 10.242.2.13 + - 10.242.3.0/24 diff --git a/inventory b/inventory index d79b625..b05515f 100644 --- a/inventory +++ b/inventory @@ -16,3 +16,6 @@ serenity.wlan.ezri.dev ;normandy ansible_connection=ssh ansible_become=true serenity ansible_connection=ssh ansible_become=true +[nginx] +peoples-home.servers.ezri.dev ansible_connection=ssh ansible_port=2231 ansible_user=root + diff --git a/playbooks/deploy-nginx.yml b/playbooks/deploy-nginx.yml new file mode 100644 index 0000000..1013b34 --- /dev/null +++ b/playbooks/deploy-nginx.yml @@ -0,0 +1,6 @@ +--- + +- name: Configure Nginx proxy + hosts: nginx + roles: + - nginx diff --git a/playbooks/roles/nginx/files/nginx.conf b/playbooks/roles/nginx/files/nginx.conf new file mode 100644 index 0000000..979b5d1 --- /dev/null +++ b/playbooks/roles/nginx/files/nginx.conf @@ -0,0 +1,91 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +error_log /var/log/nginx/error.log; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + types_hash_max_size 2048; + # server_tokens off; + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # SSL Settings + ## + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + ## + # Gzip Settings + ## + + gzip on; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/sites-enabled/*; +} + +stream { + include /etc/nginx/streams-enabled/*; +} + + +#mail { +# # See sample authentication script at: +# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript +# +# # auth_http localhost/auth.php; +# # pop3_capabilities "TOP" "USER"; +# # imap_capabilities "IMAP4rev1" "UIDPLUS"; +# +# server { +# listen localhost:110; +# protocol pop3; +# proxy on; +# } +# +# server { +# listen localhost:143; +# protocol imap; +# proxy on; +# } +#} + diff --git a/playbooks/roles/nginx/handlers/main.yml b/playbooks/roles/nginx/handlers/main.yml new file mode 100644 index 0000000..38417eb --- /dev/null +++ b/playbooks/roles/nginx/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: Reload nginx + ansible.builtin.systemd_service: + name: nginx + state: reloaded diff --git a/playbooks/roles/nginx/tasks/main.yml b/playbooks/roles/nginx/tasks/main.yml new file mode 100644 index 0000000..ab29115 --- /dev/null +++ b/playbooks/roles/nginx/tasks/main.yml @@ -0,0 +1,76 @@ +--- + +- name: Install Nginx + ansible.builtin.apt: + name: nginx + state: present + +- name: Create config directories + loop: + - /etc/nginx + - /etc/nginx/sites-available + - /etc/nginx/sites-enabled + - /etc/nginx/streams-available + - /etc/nginx/streams-enabled + ansible.builtin.file: + state: directory + dest: '{{ item }}' + owner: root + group: root + mode: "0755" + +- name: Deploy base config file + ansible.builtin.copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: "0644" + notify: Reload nginx + +- name: Deploy site configurations + loop: '{{ sites_available }}' + ansible.builtin.template: + src: site.j2 + dest: /etc/nginx/sites-available/{{ item.fqdn }}.conf + owner: root + group: root + mode: "0644" + notify: Reload nginx + +- name: Enable site configurations + loop: '{{ sites_available }}' + ansible.builtin.file: + src: ../sites-available/{{ item.fqdn }}.conf + dest: /etc/nginx/sites-enabled/{{ item.fqdn }}.conf + state: '{{ item.enabled|ternary("link", "absent") }}' + owner: root + group: root + notify: Reload nginx + +- name: Deploy stream configurations + loop: '{{ streams_available }}' + ansible.builtin.template: + src: stream.j2 + dest: /etc/nginx/streams-available/{{ item.fqdn }}.conf + owner: root + group: root + mode: "0644" + notify: Reload nginx + +- name: Enable stream configurations + loop: '{{ streams_available }}' + when: item.enabled + ansible.builtin.file: + src: ../streams-available/{{ item.fqdn }}.conf + dest: /etc/nginx/streams-enabled/{{ item.fqdn }}.conf + state: link + owner: root + group: root + notify: Reload nginx + +- name: Enable nginx + ansible.builtin.systemd_service: + name: nginx + enabled: yes + state: started diff --git a/playbooks/roles/nginx/templates/site.j2 b/playbooks/roles/nginx/templates/site.j2 new file mode 100644 index 0000000..a5111b4 --- /dev/null +++ b/playbooks/roles/nginx/templates/site.j2 @@ -0,0 +1,44 @@ +# This file is managed by Ansible. Do not make configuration changes directly. + +map $scheme $hsts_header { + https "max-age=63072000; preload"; +} + +server { + listen 80; + listen 443 ssl http2; + + 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; + + if ($scheme = "http") { + return 301 https://$host$request_uri; + } + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + proxy_http_version 1.1; + add_header Strict-Transport-Security $hsts_header always; + + {% if item.restricted|default(false) %} + {% for ip in (item.allowed_ips|default(["10.242.0.0/16"])) %} + allow {{ ip }}; + {% endfor %} + deny all; + satisfy all; + {% endif %} + + client_max_body_size {{ item.max_upload|default("1M") }}; + + location / { + add_header X-Served-By $host; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Scheme $scheme; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_pass {{ item.upstream }}$request_uri; + } +} diff --git a/playbooks/roles/nginx/templates/stream.j2 b/playbooks/roles/nginx/templates/stream.j2 new file mode 100644 index 0000000..2a3a01a --- /dev/null +++ b/playbooks/roles/nginx/templates/stream.j2 @@ -0,0 +1,29 @@ +# This file is managed by Ansible. Do not make configuration changes directly. + +server { + + {% if item.ssl|default(false) %} + # Listen using SSL + listen {{ item.listen_port }} ssl; + ssl_certificate /etc/letsencrypt/live/{{ item.cert_domain }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ item.cert_domain }}/privkey.pem; + {% else %} + # Listen without SSL + listen {{ item.listen_port }}; + {% endif %} + # Proxy the connection to upstream + proxy_pass {{ item.upstream }}; + {% if item.upstream_ssl|default(false) %} + # The upstream uses SSL, so enable support for that + proxy_ssl on; + {% endif %} + + {% if item.restricted|default(false) %} + # This stream has restricted access: + {% for ip in (item.allowed_ips|default(["10.242.0.0/16"])) %} + allow {{ ip }}; + {% endfor %} + deny all; + {% endif %} + +} \ No newline at end of file