From 12299ccb173c378ae80234500d5a322eeddf2db7 Mon Sep 17 00:00:00 2001 From: Bianca Nenciu Date: Thu, 19 Sep 2024 20:01:14 +0300 Subject: [PATCH] Use Nginx config with outlets This config has several 'include' statements that serve as extension outlets. Most of the "find & replace" instructions from templates files have been replaced to use outlets. This commit also deprecates IPv6 template in favour of an automatic implementation that relies on container's connectivity. --- samples/standalone.yml | 2 - samples/web_only.yml | 2 - templates/offline-page.template.yml | 19 ++-- templates/sshd.template.yml | 4 + templates/web.ipv6.template.yml | 12 +-- templates/web.letsencrypt.ssl.template.yml | 22 ++--- templates/web.ratelimited.template.yml | 17 ++-- templates/web.socketed.template.yml | 10 +- templates/web.ssl.template.yml | 105 ++++++++++----------- templates/web.template.yml | 31 +++--- 10 files changed, 102 insertions(+), 122 deletions(-) diff --git a/samples/standalone.yml b/samples/standalone.yml index e6d946f03..a4c3bd5d6 100644 --- a/samples/standalone.yml +++ b/samples/standalone.yml @@ -11,8 +11,6 @@ templates: - "templates/postgres.template.yml" - "templates/redis.template.yml" - "templates/web.template.yml" - ## Uncomment the next line to enable the IPv6 listener - #- "templates/web.ipv6.template.yml" - "templates/web.ratelimited.template.yml" ## Uncomment these two lines if you wish to add Lets Encrypt (https) #- "templates/web.ssl.template.yml" diff --git a/samples/web_only.yml b/samples/web_only.yml index c4753dde0..d335c847e 100644 --- a/samples/web_only.yml +++ b/samples/web_only.yml @@ -3,8 +3,6 @@ templates: - "templates/web.template.yml" - ## Uncomment the next line to enable the IPv6 listener - #- "templates/web.ipv6.template.yml" - "templates/web.ratelimited.template.yml" ## Uncomment these two lines if you wish to add Lets Encrypt (https) #- "templates/web.ssl.template.yml" diff --git a/templates/offline-page.template.yml b/templates/offline-page.template.yml index 9bcd7723f..6741f07be 100644 --- a/templates/offline-page.template.yml +++ b/templates/offline-page.template.yml @@ -7,17 +7,14 @@ params: offline_page_repository: https://github.com/discourse/discourse-offline-page.git run: - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - global: true - from: /server.+{/ - to: | - server { - error_page 502 /error_page.html; - location /error_page.html { - root /var/www/discourse-offline-page/html; - internal; - } + - file: + path: "/etc/nginx/conf.d/outlets/server/offline-page.conf" + contents: | + error_page 502 /error_page.html; + location /error_page.html { + root /var/www/discourse-offline-page/html; + internal; + } - exec: cmd: git clone $offline_page_repository /var/www/discourse-offline-page diff --git a/templates/sshd.template.yml b/templates/sshd.template.yml index d9bf57c2a..b8f3f1587 100644 --- a/templates/sshd.template.yml +++ b/templates/sshd.template.yml @@ -1,2 +1,6 @@ # This file is deprecated; you can remove it from your app.yml +# TODO(2026-01-01): Remove this file run: + - exec: |- + echo "Deprecation warning: sshd is no longer supported" + echo "Remove templates/sshd.template.yml from your containers/*.yml files" diff --git a/templates/web.ipv6.template.yml b/templates/web.ipv6.template.yml index bf589fe24..c429fc31c 100644 --- a/templates/web.ipv6.template.yml +++ b/templates/web.ipv6.template.yml @@ -1,8 +1,6 @@ +# This file is deprecated; you can remove it from your app.yml +# TODO(2026-01-01): Remove this file run: - - exec: echo "Enabling IPv6 listener" - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: listen 80; - to: | - listen 80; - listen [::]:80; + - exec: |- + echo "Deprecation warning: IPv6 is enabled by default when possible" + echo "Remove templates/web.ipv6.template.yml from your containers/*.yml files" diff --git a/templates/web.letsencrypt.ssl.template.yml b/templates/web.letsencrypt.ssl.template.yml index ba5f55178..ff96657e8 100644 --- a/templates/web.letsencrypt.ssl.template.yml +++ b/templates/web.letsencrypt.ssl.template.yml @@ -106,13 +106,6 @@ hooks: /usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /ssl_certificate.+/ - to: | - ssl_certificate /shared/ssl/$$ENV_DISCOURSE_HOSTNAME.cer; - ssl_certificate /shared/ssl/$$ENV_DISCOURSE_HOSTNAME_ecc.cer; - - replace: filename: /shared/letsencrypt/account.conf from: /#?ACCOUNT_EMAIL=.+/ @@ -120,14 +113,15 @@ hooks: ACCOUNT_EMAIL=$$ENV_LETSENCRYPT_ACCOUNT_EMAIL - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /ssl_certificate_key.+/ + filename: "/etc/nginx/conf.d/outlets/server/https.conf" + from: /ssl_certificate.+/ to: | - ssl_certificate_key /shared/ssl/$$ENV_DISCOURSE_HOSTNAME.key; - ssl_certificate_key /shared/ssl/$$ENV_DISCOURSE_HOSTNAME_ecc.key; + ssl_certificate /shared/ssl/$$ENV_DISCOURSE_HOSTNAME.cer; + ssl_certificate /shared/ssl/$$ENV_DISCOURSE_HOSTNAME_ecc.cer; - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /add_header.+/ + filename: "/etc/nginx/conf.d/outlets/server/https.conf" + from: /ssl_certificate_key.+/ to: | - add_header Strict-Transport-Security 'max-age=63072000'; + ssl_certificate_key /shared/ssl/$$ENV_DISCOURSE_HOSTNAME.key; + ssl_certificate_key /shared/ssl/$$ENV_DISCOURSE_HOSTNAME_ecc.key; diff --git a/templates/web.ratelimited.template.yml b/templates/web.ratelimited.template.yml index ae9cd636c..ca4cd4b2c 100644 --- a/templates/web.ratelimited.template.yml +++ b/templates/web.ratelimited.template.yml @@ -6,21 +6,18 @@ params: conn_per_ip: 20 run: - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /server.+{/ - to: | + - file: + path: "/etc/nginx/conf.d/outlets/before-server/ratelimited.conf" + contents: | limit_req_zone $binary_remote_addr zone=flood:10m rate=$reqs_per_secondr/s; limit_req_zone $binary_remote_addr zone=bot:10m rate=$reqs_per_minuter/m; limit_req_status 429; limit_conn_zone $binary_remote_addr zone=connperip:10m; limit_conn_status 429; - server { - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: "/location @discourse {/" - to: | - location @discourse { + + - file: + path: "/etc/nginx/conf.d/outlets/discourse/ratelimited.conf" + contents: | limit_conn connperip $conn_per_ip; limit_req zone=flood burst=$burst_per_second nodelay; limit_req zone=bot burst=$burst_per_minute nodelay; diff --git a/templates/web.socketed.template.yml b/templates/web.socketed.template.yml index ff4f87a1b..28787814d 100644 --- a/templates/web.socketed.template.yml +++ b/templates/web.socketed.template.yml @@ -12,14 +12,14 @@ run: #!/bin/bash rm -rf /shared/nginx.http*.sock - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /listen 80;/ + filename: "/etc/nginx/conf.d/outlets/server/http.conf" + from: /listen 80;(\nlisten \[::\]:80;)?/ to: | listen unix:/shared/nginx.http.sock; set_real_ip_from unix:; - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /listen 443 ssl http2;/ + filename: "/etc/nginx/conf.d/outlets/server/https.conf" + from: /listen 443 ssl;(\nlisten \[::\]:443 ssl;)?/ to: | - listen unix:/shared/nginx.https.sock ssl http2; + listen unix:/shared/nginx.https.sock ssl; set_real_ip_from unix:; diff --git a/templates/web.ssl.template.yml b/templates/web.ssl.template.yml index cc6a66fe0..9a3fc0b44 100644 --- a/templates/web.ssl.template.yml +++ b/templates/web.ssl.template.yml @@ -1,58 +1,51 @@ run: - exec: - cmd: - - "mkdir -p /shared/ssl/" - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /server.+{/ - to: | - server { - listen 80; - return 301 https://$$ENV_DISCOURSE_HOSTNAME$request_uri; - } - server { - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /listen 80;\s+gzip on;/m - to: | - listen 443 ssl; - http2 on; - SSL_TEMPLATE_SSL_BLOCK - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /listen 80;\s+listen \[::\]:80;\s+gzip on;/m - to: | - listen 443 ssl; - listen [::]:443 ssl; - http2 on; - SSL_TEMPLATE_SSL_BLOCK - - replace: - hook: ssl - filename: "/etc/nginx/conf.d/discourse.conf" - from: /SSL_TEMPLATE_SSL_BLOCK/ - to: | - - ssl_protocols TLSv1.2 TLSv1.3; - 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_certificate /shared/ssl/ssl.crt; - ssl_certificate_key /shared/ssl/ssl.key; - - ssl_session_tickets off; - ssl_session_timeout 1d; - ssl_session_cache shared:SSL:1m; - - gzip on; - - add_header Strict-Transport-Security 'max-age=31536000'; # remember the certificate for a year and automatically connect to HTTPS for this domain - - if ($http_host != $$ENV_DISCOURSE_HOSTNAME) { - rewrite (.*) https://$$ENV_DISCOURSE_HOSTNAME$1 permanent; - } - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: "location @discourse {" - to: | - location @discourse { - add_header Strict-Transport-Security 'max-age=31536000'; # remember the certificate for a year and automatically connect to HTTPS for this domain + cmd: + - "mkdir -p /shared/ssl/" + + - file: + path: "/etc/nginx/conf.d/outlets/before-server/redirect-http-to-https.conf" + contents: | + server { + listen 80; + return 301 https://$$ENV_DISCOURSE_HOSTNAME$request_uri; + } + + - exec: rm /etc/nginx/conf.d/outlets/server/http.conf + + - file: + hook: ssl + path: "/etc/nginx/conf.d/outlets/server/https.conf" + contents: | + listen 443 ssl; + http2 on; + + ssl_protocols TLSv1.2 TLSv1.3; + 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_certificate /shared/ssl/ssl.crt; + ssl_certificate_key /shared/ssl/ssl.key; + + ssl_session_tickets off; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:1m; + + add_header Strict-Transport-Security 'max-age=31536000'; + + if ($http_host != $$ENV_DISCOURSE_HOSTNAME) { + rewrite (.*) https://$$ENV_DISCOURSE_HOSTNAME$1 permanent; + } + + - file: + path: "/etc/nginx/conf.d/outlets/discourse/https.conf" + contents: | + add_header Strict-Transport-Security 'max-age=31536000'; + + - exec: + cmd: + - |- + if [ -f "/proc/net/if_inet6" ] ; then + sed -i 's/listen 80;/listen 80;\nlisten [::]:80;/g' /etc/nginx/conf.d/outlets/before-server/redirect-http-to-https.conf + sed -i 's/listen 443 ssl;/listen 443 ssl;\nlisten [::]:443 ssl;/g' /etc/nginx/conf.d/outlets/server/https.conf + fi diff --git a/templates/web.template.yml b/templates/web.template.yml index 9b541c9c2..0e1feae75 100644 --- a/templates/web.template.yml +++ b/templates/web.template.yml @@ -135,6 +135,9 @@ run: - "cp $home/config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf" - "rm /etc/nginx/sites-enabled/default" - "mkdir -p /var/nginx/cache" + - "mkdir -p /etc/nginx/conf.d/outlets/before-server" + - "mkdir -p /etc/nginx/conf.d/outlets/server" + - "mkdir -p /etc/nginx/conf.d/outlets/discourse" - replace: filename: /etc/nginx/nginx.conf @@ -142,26 +145,23 @@ run: to: daemon off; - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /upstream[^\}]+\}/m - to: "upstream discourse { - server 127.0.0.1:3000; - }" - - - replace: - filename: "/etc/nginx/conf.d/discourse.conf" - from: /server_name.+$/ - to: server_name _ ; + filename: "/etc/nginx/nginx.conf" + from: /worker_connections.+$/ + to: worker_connections $nginx_worker_connections; - replace: filename: "/etc/nginx/conf.d/discourse.conf" from: /client_max_body_size.+$/ - to: client_max_body_size $upload_size ; + to: client_max_body_size $upload_size; - - replace: - filename: "/etc/nginx/nginx.conf" - from: /worker_connections.+$/ - to: worker_connections $nginx_worker_connections ; + - exec: + cmd: + - |- + if [ -f "/proc/net/if_inet6" ]; then + echo "listen 80;\nlisten [::]:80;" > /etc/nginx/conf.d/outlets/server/http.conf + else + echo "listen 80;" > /etc/nginx/conf.d/outlets/server/http.conf + fi - exec: cmd: echo "done configuring web" @@ -222,6 +222,7 @@ run: hook: assets_precompile cmd: - su discourse -c 'SKIP_EMBER_CLI_COMPILE=1 bundle exec rake themes:update assets:precompile' + - replace: tag: precompile filename: /etc/service/unicorn/run