From 6b459a26f0ff7bfee145ff3c268118db54bea822 Mon Sep 17 00:00:00 2001 From: Bastian de Byl Date: Fri, 11 Aug 2023 23:52:56 -0400 Subject: [PATCH] moved fulfillr w/ddns to https --- .../tasks/configuration-nginx-https.yml | 2 + .../roles/podman/tasks/container-awsddns.yml | 27 +++++++++ ansible/roles/podman/tasks/main.yml | 2 +- .../sites/fulfillr.debyltech.com.conf.j2 | 23 +++---- .../fulfillr.debyltech.com.https.conf.j2 | 57 ++++++++++++++++++ ansible/roles/ssl/tasks/certbot.yml | 2 +- ansible/vars/vault.yml | Bin 10550 -> 10745 bytes 7 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.https.conf.j2 diff --git a/ansible/roles/podman/tasks/configuration-nginx-https.yml b/ansible/roles/podman/tasks/configuration-nginx-https.yml index 1b3016b..5b3824a 100644 --- a/ansible/roles/podman/tasks/configuration-nginx-https.yml +++ b/ansible/roles/podman/tasks/configuration-nginx-https.yml @@ -37,6 +37,7 @@ - "{{ bookstack_server_name }}.https.conf" - "{{ ci_server_name }}.https.conf" - "{{ cloud_server_name }}.https.conf" + - "{{ fulfillr_server_name }}.https.conf" - "{{ parts_server_name }}.https.conf" - "{{ photos_server_name }}.https.conf" notify: @@ -56,6 +57,7 @@ - "{{ bookstack_server_name }}.https.conf" - "{{ ci_server_name }}.https.conf" - "{{ cloud_server_name }}.https.conf" + - "{{ fulfillr_server_name }}.https.conf" - "{{ parts_server_name }}.https.conf" - "{{ photos_server_name }}.https.conf" notify: diff --git a/ansible/roles/podman/tasks/container-awsddns.yml b/ansible/roles/podman/tasks/container-awsddns.yml index 489f294..0377158 100644 --- a/ansible/roles/podman/tasks/container-awsddns.yml +++ b/ansible/roles/podman/tasks/container-awsddns.yml @@ -52,3 +52,30 @@ include_tasks: podman/systemd-generate.yml vars: container_name: awsddns-skudak + +- import_tasks: podman/podman-check.yml + vars: + container_name: awsddns-fulfillr + container_image: "{{ image }}" + +- name: create fulfillr.debyltech.com awsddns server container + become: true + become_user: "{{ podman_user }}" + diff: false + containers.podman.podman_container: + name: awsddns-fulfillr + image: "{{ image }}" + restart_policy: on-failure:3 + log_driver: journald + env: + AWS_ZONE_TTL: 60 + AWS_ZONE_ID: "{{ fulfillr_zone_id }}" + AWS_ZONE_HOSTNAME: "{{ fulfillr_server_name }}" + AWS_ACCESS_KEY_ID: "{{ fulfillr_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ fulfillr_secret_key }}" + AWS_DEFAULT_REGION: "{{ fulfillr_region }}" + +- name: create systemd startup job for awsddns-fulfillr + include_tasks: podman/systemd-generate.yml + vars: + container_name: awsddns-fulfillr \ No newline at end of file diff --git a/ansible/roles/podman/tasks/main.yml b/ansible/roles/podman/tasks/main.yml index 6163925..f4a0e3d 100644 --- a/ansible/roles/podman/tasks/main.yml +++ b/ansible/roles/podman/tasks/main.yml @@ -51,7 +51,7 @@ - import_tasks: container-fulfillr.yml vars: - image: "{{ aws_ecr_endpoint }}/fulfillr:20230811.1904" + image: "{{ aws_ecr_endpoint }}/fulfillr:20230811.2059" tags: fulfillr - import_tasks: configuration-nginx.yml diff --git a/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.conf.j2 b/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.conf.j2 index 1fe3173..3cf0df6 100644 --- a/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.conf.j2 +++ b/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.conf.j2 @@ -1,24 +1,21 @@ -upstream fulfillr { - server 127.0.0.1:9054; +geo $whitelisted { + default 0; + 192.168.0.0/16 1; } + server { - resolver 192.168.1.10 ipv6=off; modsecurity on; modsecurity_rules_file /etc/nginx/modsec_includes.conf; listen 80; server_name {{ fulfillr_server_name }}; + location '/.well-known/acme-challenge' { + default_type "text/plain"; + root /srv/http/letsencrypt; + } + location / { - allow 192.168.0.0/16; - allow 127.0.0.1; - deny all; - - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - - proxy_buffering off; - proxy_pass http://fulfillr; + return 302 https://$host$request_uri; } } diff --git a/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.https.conf.j2 b/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.https.conf.j2 new file mode 100644 index 0000000..065beff --- /dev/null +++ b/ansible/roles/podman/templates/nginx/sites/fulfillr.debyltech.com.https.conf.j2 @@ -0,0 +1,57 @@ +geo $whitelisted { + default 0; + 192.168.0.0/16 1; +} + +upstream fulfillr { + server 127.0.0.1:9054; +} + +server { + modsecurity on; + modsecurity_rules_file /etc/nginx/modsec_includes.conf; + + resolver 127.0.0.1 127.0.0.53 9.9.9.9 valid=60s; + + listen 443 ssl http2; + server_name {{ fulfillr_server_name }}; + + ssl_certificate /etc/letsencrypt/live/{{ fulfillr_server_name }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ fulfillr_server_name }}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{{ fulfillr_server_name }}/fullchain.pem; + ssl_dhparam /etc/nginx/ssl/dhparam.pem; + + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_session_timeout 1d; + ssl_stapling on; + ssl_stapling_verify on; + + if ($whitelisted = 0) { + return 302 $scheme://bdebyl.net$request_uri; + } + + location / { + add_header Referrer-Policy "same-origin" always; + # add_header Strict-Transport-Security "max-age=630720000; includeSubDomains" always; + add_header X-Content-Type-Options "nosniff" always; + + # Sent from upstream: + # add_header X-Frame-Options "SAMEORIGIN"; + # add_header X-XSS-Protection "1; mode=block"; + + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_buffering off; + proxy_http_version 1.1; + proxy_pass http://fulfillr; + proxy_redirect off; + + chunked_transfer_encoding off; + } +} diff --git a/ansible/roles/ssl/tasks/certbot.yml b/ansible/roles/ssl/tasks/certbot.yml index a0ed4f2..78c5f95 100644 --- a/ansible/roles/ssl/tasks/certbot.yml +++ b/ansible/roles/ssl/tasks/certbot.yml @@ -11,9 +11,9 @@ - "{{ bookstack_server_name }}" - "{{ ci_server_name }}" - "{{ cloud_server_name }}" + - "{{ fulfillr_server_name }}" - "{{ parts_server_name }}" - "{{ photos_server_name }}" - - "{{ api_debyltech_server_name }}" tags: ssl - name: set group ownership for /etc/letsencrypt/ diff --git a/ansible/vars/vault.yml b/ansible/vars/vault.yml index 7c0105051940d2f4913ebd4abf69c339a2f7d937..f426886dcc0c5fd9f62f197314386aeb89cae9f9 100644 GIT binary patch literal 10745 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 literal 10550 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