From c42457cc745e2ce628b40dc6ac3cb5798c25518d Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 12 Oct 2023 23:23:01 +0100 Subject: [PATCH 01/76] Bumping version to 7.0.6 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c60ebc1..ec99716 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.5 \ No newline at end of file +7.0.6 \ No newline at end of file From 3ff932d4aa123c50312ea3860361a40239d32205 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 12 Oct 2023 23:23:06 +0100 Subject: [PATCH 02/76] Updating workflows --- .github/workflows/auto-pr.yml | 2 +- .github/workflows/dev.yml | 12 ++++++------ .github/workflows/publish.yml | 10 +++++----- .github/workflows/update-readme.yml | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index 213d5b8..ae26510 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout Branch ${{ github.ref_name }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create Pull Request uses: bfren/pull-request@v2 diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index dae7dab..503d2d2 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -12,13 +12,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 build: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get repository name run: echo "REPOSITORY_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" >> $GITHUB_ENV @@ -31,20 +31,20 @@ jobs: id: version - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: build-args: | BF_IMAGE=${{ env.REPOSITORY_NAME }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 61c2b18..b3d12cb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get repository name run: echo "REPOSITORY_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" >> $GITHUB_ENV @@ -36,20 +36,20 @@ jobs: id: version - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: build-args: | BF_IMAGE=${{ env.REPOSITORY_NAME }} diff --git a/.github/workflows/update-readme.yml b/.github/workflows/update-readme.yml index 14fd935..7fc7506 100644 --- a/.github/workflows/update-readme.yml +++ b/.github/workflows/update-readme.yml @@ -15,10 +15,10 @@ jobs: shell: bash - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} From aa36e960f3fda7ce2d07502cee747d66dc383979 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 9 Nov 2023 10:18:31 +0000 Subject: [PATCH 03/76] Bumping version to 8.0.0 --- VERSION | 2 +- VERSION_MAJOR | 2 +- VERSION_MINOR | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index ec99716..fa5fce0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.6 \ No newline at end of file +8.0.0 \ No newline at end of file diff --git a/VERSION_MAJOR b/VERSION_MAJOR index c793025..301160a 100644 --- a/VERSION_MAJOR +++ b/VERSION_MAJOR @@ -1 +1 @@ -7 \ No newline at end of file +8 \ No newline at end of file diff --git a/VERSION_MINOR b/VERSION_MINOR index 7104585..b293f64 100644 --- a/VERSION_MINOR +++ b/VERSION_MINOR @@ -1 +1 @@ -7.0 \ No newline at end of file +8.0 \ No newline at end of file From 983605f057ee8eb7e2a4fb7818fb60356eab1753 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 9 Nov 2023 10:18:39 +0000 Subject: [PATCH 04/76] Switching -beta to -dev tags --- .github/workflows/dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 503d2d2..f499720 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -53,7 +53,7 @@ jobs: platforms: linux/amd64,linux/arm/v7,linux/arm64 tags: | bfren/nginx-proxy:dev - bfren/nginx-proxy:${{ steps.version.outputs.contents }}-beta + bfren/nginx-proxy:${{ steps.version.outputs.contents }}-dev - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} From 0bd2900f5e4a053b8819c08a08181e59a18155f8 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 9 Nov 2023 10:18:45 +0000 Subject: [PATCH 05/76] Enforcing LF line endings --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4ff3bd7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Always use LF endings. +* text eol=lf \ No newline at end of file From 856bc020be9cc285525b501082738f624cc947ba Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 9 Nov 2023 10:23:20 +0000 Subject: [PATCH 06/76] Refactoring Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 877aeb6..bc389e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,8 @@ ARG BF_VERSION # port 80 is already exposed by the base image EXPOSE 443 +COPY ./overlay / + ENV \ # the base domain of the proxy server (will be used when SSL bindings fail) PROXY_DOMAIN= \ @@ -43,8 +45,6 @@ ENV \ # the number of seconds before the maintenance page will auto-refresh PROXY_MAINTENANCE_REFRESH_SECONDS=6 -COPY ./overlay / - RUN bf-install VOLUME [ "/ssl", "/sites" ] From 99540012dc6752b544788d3409ceed4370c1f7e1 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 9 Nov 2023 10:26:15 +0000 Subject: [PATCH 07/76] Updating Nginx build --- overlay/tmp/NGINX_BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overlay/tmp/NGINX_BUILD b/overlay/tmp/NGINX_BUILD index e9739b6..193e3db 100644 --- a/overlay/tmp/NGINX_BUILD +++ b/overlay/tmp/NGINX_BUILD @@ -1 +1 @@ -1.24.0-r6 \ No newline at end of file +1.24.0-r7 \ No newline at end of file From ad2e42d906554482f24518babaaf2b6f180826a8 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 29 Jan 2024 11:08:18 +0000 Subject: [PATCH 08/76] Updating copyright year to 2024 --- LICENSE | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 1674874..06c6f55 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2023 bfren +Copyright (c) 2020-2024 bfren Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 9d8102f..964041a 100644 --- a/README.md +++ b/README.md @@ -83,4 +83,4 @@ The image contains a handful of useful Nginx configuration 'helper' files, which ## Copyright -> Copyright (c) 2020-2023 [bfren](https://bfren.dev) (unless otherwise stated) +> Copyright (c) 2020-2024 [bfren](https://bfren.dev) (unless otherwise stated) From ec6214513ae30aca6515279d51e27c6bbc6253b3 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 29 Jan 2024 11:08:25 +0000 Subject: [PATCH 09/76] Updating copyright year to 2024 --- overlay/etc/bf/templates/nginx-proxy.conf.esh | 2 +- overlay/etc/bf/templates/nginx-site.conf.esh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/overlay/etc/bf/templates/nginx-proxy.conf.esh b/overlay/etc/bf/templates/nginx-proxy.conf.esh index 5f477c1..4f7e78a 100644 --- a/overlay/etc/bf/templates/nginx-proxy.conf.esh +++ b/overlay/etc/bf/templates/nginx-proxy.conf.esh @@ -4,7 +4,7 @@ # # Use environment variable PROXY_DOMAIN to change this file. # -# Copyright (c) 2021-2023 bfren +# Copyright (c) 2021-2024 bfren #====================================================================================================================== #====================================================================================================================== diff --git a/overlay/etc/bf/templates/nginx-site.conf.esh b/overlay/etc/bf/templates/nginx-site.conf.esh index 7dc46be..e422002 100644 --- a/overlay/etc/bf/templates/nginx-site.conf.esh +++ b/overlay/etc/bf/templates/nginx-site.conf.esh @@ -15,7 +15,7 @@ # "custom": true # This will cause this file to be regenerated next time the container is started. # -# Copyright (c) 2021-2023 bfren +# Copyright (c) 2021-2024 bfren #====================================================================================================================== <% else -%> #====================================================================================================================== @@ -29,7 +29,7 @@ # "custom": true # This will stop this file being generated next time the container is started. # -# Copyright (c) 2021-2023 bfren +# Copyright (c) 2021-2024 bfren #====================================================================================================================== <% fi %> #====================================================================================================================== From c7eaeaf32cc11aae75dee1683335d63761c45972 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 16 Jun 2024 10:37:48 +0100 Subject: [PATCH 10/76] Using new http2 config value --- Dockerfile | 2 +- overlay/etc/bf/templates/nginx-site.conf.esh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index bc389e0..2dca7a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.24-alpine3.18-5.0.16 +FROM bfren/nginx:nginx1.26-alpine3.20-6.3.1 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" diff --git a/overlay/etc/bf/templates/nginx-site.conf.esh b/overlay/etc/bf/templates/nginx-site.conf.esh index e422002..6a157fb 100644 --- a/overlay/etc/bf/templates/nginx-site.conf.esh +++ b/overlay/etc/bf/templates/nginx-site.conf.esh @@ -74,8 +74,9 @@ server { server_name <%= "${SERVER_NAMES}" %>; # listen on SSL port for both IPv4 and IPv6, and enable HTTP/2 - listen 443 ssl http2; - listen [::]:443 ssl http2; + listen 443 ssl; + listen [::]:443 ssl; + http2 on; <% if [ "${PROXY_SSL_REDIRECT_TO_CANONICAL}" = "1" ] ; then -%> # redirect to primary (canonical) domain name From bad3c251901fe080aaa45d2bb4ce4579e2b4a7fb Mon Sep 17 00:00:00 2001 From: bfren Date: Tue, 30 Jul 2024 16:42:58 +0100 Subject: [PATCH 11/76] Updating workflows --- .github/workflows/dev.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index f499720..a6bf80a 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -44,7 +44,7 @@ jobs: - name: Build and push id: docker_build - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: build-args: | BF_IMAGE=${{ env.REPOSITORY_NAME }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b3d12cb..fd6825e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -49,7 +49,7 @@ jobs: - name: Build and push id: docker_build - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: build-args: | BF_IMAGE=${{ env.REPOSITORY_NAME }} From 50912df03c39dc8fbe6d009bb99b7b66d7b5c882 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 09:17:58 +0000 Subject: [PATCH 12/76] Removing support for NAXSI --- Dockerfile | 2 - README.md | 3 +- overlay/etc/bf/ch.d/20-proxy | 1 - overlay/etc/bf/init.d/23-naxsi | 21 ---- overlay/etc/bf/templates/naxsi.conf.esh | 14 --- overlay/etc/bf/templates/nginx-site.conf.esh | 6 -- overlay/etc/naxsi/core.rules | 97 ------------------- .../nginx/helpers/nginx-block-ai-bots.conf | 4 +- overlay/etc/nginx/http.d/naxsi-rules.conf | 1 - 9 files changed, 3 insertions(+), 146 deletions(-) delete mode 100644 overlay/etc/bf/init.d/23-naxsi delete mode 100644 overlay/etc/bf/templates/naxsi.conf.esh delete mode 100644 overlay/etc/naxsi/core.rules delete mode 100644 overlay/etc/nginx/http.d/naxsi-rules.conf diff --git a/Dockerfile b/Dockerfile index 2dca7a9..caa67e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,8 +17,6 @@ ENV \ PROXY_CLEAN_INSTALL=0 \ # enable automatic certificate updating PROXY_ENABLE_AUTO_UPDATE=1 \ - # enable NAXSI web application firewall - PROXY_ENABLE_NAXSI=0 \ # use hardened mode (remove old / insecure ciphers and protocols) PROXY_HARDEN=0 \ # used for renewal notification emails diff --git a/README.md b/README.md index 964041a..b649c66 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [Docker Repository](https://hub.docker.com/r/bfren/nginx-proxy) - [bfren ecosystem](https://github.com/bfren/docker) -Nginx Proxy which uses [getssl](https://github.com/srvrco/getssl) to automate requesting and renewing SSL certificates via Let's Encrypt. Certificates are checked for renewal every day - the last check can be viewed in the `/ssl` volume. Also includes [NAXSI](https://github.com/nbs-system/naxsi), a web application firewall. +Nginx Proxy which uses [getssl](https://github.com/srvrco/getssl) to automate requesting and renewing SSL certificates via Let's Encrypt. Certificates are checked for renewal every day - the last check can be viewed in the `/ssl` volume. As of v4, configuration is handled via a JSON file - see ssl-conf-sample.json for an example and ssl-conf-schema.json for the full file definition. @@ -42,7 +42,6 @@ For SSL certificate requests to work correctly, ports 80 and 443 need mapping fr | `PROXY_AUTO_CUSTOM` | 0 or 1 | Mark the auto-generated SSL config to 'custom' so the Nginx configuration is not regenerated on startup. | 0 | | `PROXY_CLEAN_INSTALL` | 0 or 1 | If 1, all Nginx and SSL configuration and certificates will be deleted and regenerated. | 0 | | `PROXY_DOMAIN` | URI | The base domain of the proxy server - will be used to handle unbound requests. | *None* - **required** | -| `PROXY_ENABLE_NAXSI` | 0 or 1 | If 1, NAXSI web application firewall will be enabled for all sites. | 0 | | `PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK` | true or false | Set to true to enable `getssl`'s [skip HTTP token check](https://github.com/srvrco/getssl/wiki/Config-variables#skip_http_token_checkfalse). | false | | `PROXY_HARDEN` | 0 or 1 | If 1, only modern SSL ciphers and protocols will be enabled (some older devices may not be able to access it). | 0 | | `PROXY_LETS_ENCRYPT_EMAIL` | A valid email address | Used by Lets Encrypt for notification emails. | *None* - **required** | diff --git a/overlay/etc/bf/ch.d/20-proxy b/overlay/etc/bf/ch.d/20-proxy index fc78aca..5bf7c50 100644 --- a/overlay/etc/bf/ch.d/20-proxy +++ b/overlay/etc/bf/ch.d/20-proxy @@ -1,4 +1,3 @@ -/etc/naxsi www:www 0640 0750 /etc/nginx/sites www:www 0640 0750 /etc/ssl/certs www:www 0640 0750 /sites www:www 0640 0750 diff --git a/overlay/etc/bf/init.d/23-naxsi b/overlay/etc/bf/init.d/23-naxsi deleted file mode 100644 index 1c40f96..0000000 --- a/overlay/etc/bf/init.d/23-naxsi +++ /dev/null @@ -1,21 +0,0 @@ -#!/command/with-contenv bash - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Generate NAXSI configuration. -#====================================================================================================================== - -if [ "${PROXY_ENABLE_NAXSI-}" = "1" ] ; then - - bf-echo "Generating NAXSI files." - bf-esh ${BF_TEMPLATES}/naxsi.conf.esh /etc/nginx/helpers/naxsi.conf - bf-done - -else - - bf-echo "NAXSI not enabled." - -fi diff --git a/overlay/etc/bf/templates/naxsi.conf.esh b/overlay/etc/bf/templates/naxsi.conf.esh deleted file mode 100644 index f7b2728..0000000 --- a/overlay/etc/bf/templates/naxsi.conf.esh +++ /dev/null @@ -1,14 +0,0 @@ -<% if [ "${PROXY_ENABLE_NAXSI}" = "1" ] ; then -%> -# enable NAXSI -SecRulesEnabled; -# enable learning mode -LearningMode; -# define where blocked requests go -DeniedUrl "/denied.html"; -# checkRules, determining when naxsi needs to take action -CheckRule "$SQL >= 8" BLOCK; -CheckRule "$RFI >= 8" BLOCK; -CheckRule "$TRAVERSAL >= 4" BLOCK; -CheckRule "$EVADE >= 4" BLOCK; -CheckRule "$XSS >= 8" BLOCK; -<% fi %> diff --git a/overlay/etc/bf/templates/nginx-site.conf.esh b/overlay/etc/bf/templates/nginx-site.conf.esh index ec60521..df0037b 100644 --- a/overlay/etc/bf/templates/nginx-site.conf.esh +++ b/overlay/etc/bf/templates/nginx-site.conf.esh @@ -100,12 +100,6 @@ server { # block AI bots include helpers/nginx-block-ai-bots.conf; - <% if [ "${PROXY_ENABLE_NAXSI-}" = "1" ] ; then -%> - # enable NAXSI web application firewall with custom rules - include helpers/naxsi.conf; - include <%= "${CUSTOM_CONF}/*.rules" %>; - <% fi -%> - # use maintenance page (defined in helpers/proxy-maintenance.conf - see below) when there's an upstream error error_page 502 503 504 /maintenance.html; diff --git a/overlay/etc/naxsi/core.rules b/overlay/etc/naxsi/core.rules deleted file mode 100644 index 4e51aad..0000000 --- a/overlay/etc/naxsi/core.rules +++ /dev/null @@ -1,97 +0,0 @@ -# See https://github.com/wargio/naxsi/blob/main/naxsi_rules/naxsi_core.rules - -################################## -## INTERNAL RULES IDS:1-999 ## -################################## -#@MainRule "msg:weird request, unable to parse" id:1; -#@MainRule "msg:request too big, stored on disk and not parsed" id:2; -#@MainRule "msg:invalid hex encoding, null bytes" id:10; -#@MainRule "msg:unknown content-type" id:11; -#@MainRule "msg:invalid formatted url" id:12; -#@MainRule "msg:invalid POST format" id:13; -#@MainRule "msg:invalid POST boundary" id:14; -#@MainRule "msg:invalid JSON" id:15; -#@MainRule "msg:empty POST" id:16; -#@MainRule "msg:libinjection_sql" id:17; -#@MainRule "msg:libinjection_xss" id:18; -#@MainRule "msg:no generic rules" id:19; -#@MainRule "msg:bad utf8" id:20; -#@MainRule "msg:illegal host header" id:21; - -################################## -## SQL Injections IDs:1000-1099 ## -################################## -MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop|load_file|substr|group_concat|dumpfile|bigint" "msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000; -MainRule "str:\"" "msg:double quote" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8" id:1001; -MainRule "str:0x" "msg:0x, possible hex encoding" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:2" id:1002; -## Hardcore rules -MainRule "str:/*" "msg:mysql comment (/*)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003; -MainRule "str:*/" "msg:mysql comment (*/)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004; -MainRule "str:|" "msg:mysql keyword (|)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005; -MainRule "str:&&" "msg:mysql keyword (&&)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006; -## end of hardcore rules -MainRule "str:--" "msg:mysql comment (--)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007; -MainRule "str:;" "msg:semicolon" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008; -MainRule "str:=" "msg:equal sign in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009; -MainRule "str:(" "msg:open parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010; -MainRule "str:)" "msg:close parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011; -MainRule "str:'" "msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013; -MainRule "str:," "msg:comma" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015; -MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016; -MainRule "str:@@" "msg:double arobase (@@)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1017; -MainRule "rx:::json|to_json|jsonb?_build|jsonb?_object|jsonb?_each|jsonb?_extract|jsonb?_typeof|jsonb?_array|jsonb_set|json_query|json_keys" "msg:json functions and operators" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1018; - -############################### -## OBVIOUS RFI IDs:1100-1199 ## -############################### -MainRule "str:http://" "msg:http:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1100; -MainRule "str:https://" "msg:https:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1101; -MainRule "str:ftp://" "msg:ftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1102; -MainRule "str:php://" "msg:php:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1103; -MainRule "str:sftp://" "msg:sftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1104; -MainRule "str:zlib://" "msg:zlib:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1105; -MainRule "str:data://" "msg:data:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1106; -MainRule "str:glob://" "msg:glob:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1107; -MainRule "str:phar://" "msg:phar:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1108; -MainRule "str:file://" "msg:file:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1109; -MainRule "str:gopher://" "msg:gopher:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1110; -MainRule "str:zip://" "msg:zip:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1111; -MainRule "str:expect://" "msg:expect:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1112; -MainRule "str:input://" "msg:input:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1113; - -####################################### -## Directory traversal IDs:1200-1299 ## -####################################### -MainRule "str:.." "msg:double dot" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1200; -MainRule "str:/etc/passwd" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1202; -MainRule "str:c:\\" "msg:obvious windows path" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1203; -MainRule "str:cmd.exe" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1204; -MainRule "str:\\" "msg:backslash" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1205; -#MainRule "str:/" "msg:slash in args" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:2" id:1206; -MainRule "str:/..;/" "msg:dir traversal bypass" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:2" id:1207; -MainRule "str:/.;/" "msg:dir traversal bypass" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1208; -MainRule "str:/.%2e/" "msg:dir traversal bypass" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1209; -MainRule "str:/%2e./" "msg:dir traversal bypass" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1210; - -######################################## -## Cross Site Scripting IDs:1300-1399 ## -######################################## -MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302; -MainRule "str:>" "msg:html close tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1303; -MainRule "str:[" "msg:open square backet ([), possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1310; -MainRule "str:]" "msg:close square bracket (]), possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1311; -MainRule "str:~" "msg:tilde (~) character" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1312; -MainRule "str:`" "msg:grave accent (`)" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1314; -MainRule "rx:%[23]." "msg:double encoding" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1315; - -#################################### -## Evading tricks IDs: 1400-1500 ## -#################################### -MainRule "str:&#" "msg:utf7/8 encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1400; -MainRule "str:%U" "msg:M$ encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1401; - -############################# -## File uploads: 1500-1600 ## -############################# -MainRule "rx:\.ph|\.asp|\.ht|\.jsp" "msg:asp/php/jsp/htaccess file upload" "mz:FILE_EXT" "s:$UPLOAD:8" id:1500; -MainRule "rx:^[\.a-z0-9_\- ]+$" negative "msg:uploaded filename contains non-printable ascii chars" "mz:FILE_EXT" "s:$UPLOAD:8" id:1501; diff --git a/overlay/etc/nginx/helpers/nginx-block-ai-bots.conf b/overlay/etc/nginx/helpers/nginx-block-ai-bots.conf index 131eb34..288ed18 100644 --- a/overlay/etc/nginx/helpers/nginx-block-ai-bots.conf +++ b/overlay/etc/nginx/helpers/nginx-block-ai-bots.conf @@ -1,4 +1,4 @@ if ($http_user_agent ~* "(AdsBot-Google|Amazonbot|anthropic-ai|Applebot|Applebot-Extended|AwarioRssBot|AwarioSmartBot|Bytespider|CCBot|ChatGPT-User|Claude-Web|ClaudeBot|cohere-ai|DataForSeoBot|Diffbot|FacebookBot|FriendlyCrawler|Google-Extended|GoogleOther|GPTBot|ImagesiftBot|img2dataset|magpie-crawler|Meltwater|omgili|omgilibot|peer39_crawler|peer39_crawler/1.0|PerplexityBot|PiplBot|scoop.it|Seekr|SemrushBot|YandexBot|YouBot)"){ - access_log off; - return 403; + access_log off; + return 403; } diff --git a/overlay/etc/nginx/http.d/naxsi-rules.conf b/overlay/etc/nginx/http.d/naxsi-rules.conf deleted file mode 100644 index 69469aa..0000000 --- a/overlay/etc/nginx/http.d/naxsi-rules.conf +++ /dev/null @@ -1 +0,0 @@ -include /etc/naxsi/*.rules; \ No newline at end of file From e4ac8c580b2553dd3f6e76782d467c5dfa4ab1e1 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:38:30 +0000 Subject: [PATCH 13/76] Migrating init to nu --- overlay/etc/bf/ch.d/20-proxy | 2 - overlay/etc/bf/init.d/20-env | 43 ---------------------- overlay/etc/bf/init.d/20-env.nu | 35 ++++++++++++++++++ overlay/etc/bf/init.d/21-ssl-conf | 19 ---------- overlay/etc/bf/init.d/21-ssl-conf.nu | 15 ++++++++ overlay/etc/bf/init.d/22-ssl-init | 49 ------------------------- overlay/etc/bf/init.d/22-ssl-init.nu | 45 +++++++++++++++++++++++ overlay/etc/bf/init.d/23-maintenance.nu | 11 ++++++ overlay/etc/bf/init.d/24-maintenance | 14 ------- 9 files changed, 106 insertions(+), 127 deletions(-) delete mode 100644 overlay/etc/bf/init.d/20-env create mode 100644 overlay/etc/bf/init.d/20-env.nu delete mode 100644 overlay/etc/bf/init.d/21-ssl-conf create mode 100644 overlay/etc/bf/init.d/21-ssl-conf.nu delete mode 100644 overlay/etc/bf/init.d/22-ssl-init create mode 100644 overlay/etc/bf/init.d/22-ssl-init.nu create mode 100644 overlay/etc/bf/init.d/23-maintenance.nu delete mode 100644 overlay/etc/bf/init.d/24-maintenance diff --git a/overlay/etc/bf/ch.d/20-proxy b/overlay/etc/bf/ch.d/20-proxy index 5bf7c50..cc04658 100644 --- a/overlay/etc/bf/ch.d/20-proxy +++ b/overlay/etc/bf/ch.d/20-proxy @@ -1,4 +1,2 @@ -/etc/nginx/sites www:www 0640 0750 -/etc/ssl/certs www:www 0640 0750 /sites www:www 0640 0750 /ssl www:www 0640 0750 diff --git a/overlay/etc/bf/init.d/20-env b/overlay/etc/bf/init.d/20-env deleted file mode 100644 index 8a6f6dd..0000000 --- a/overlay/etc/bf/init.d/20-env +++ /dev/null @@ -1,43 +0,0 @@ -#!/command/with-contenv bash - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Define environment variables. -#====================================================================================================================== - -PROXY_LIB=${BF_LIB}/proxy -bf-env "PROXY_LIB" "${PROXY_LIB}" -bf-env "PROXY_GETSSL" "${PROXY_LIB}/getssl" - -PROXY_SSL=/ssl -bf-env "PROXY_SSL" ${PROXY_SSL} -bf-env "PROXY_SSL_CONF" "${PROXY_SSL}/conf.json" -bf-env "PROXY_SSL_DHPARAM" "${PROXY_SSL}/dhparam.pem" - -PROXY_SSL_CERTS=${PROXY_SSL}/certs -bf-env "PROXY_SSL_CERTS" "${PROXY_SSL_CERTS}" - -PROXY_GETSSL_CFG=getssl.cfg -bf-env "PROXY_GETSSL_CFG" "${PROXY_GETSSL_CFG}" -bf-env "PROXY_GETSSL_GLOBAL_CFG" "${PROXY_SSL_CERTS}/${PROXY_GETSSL_CFG}" -bf-env "PROXY_GETSSL_ACCOUNT_KEY" "${PROXY_SSL_CERTS}/account.key" - -bf-env "PROXY_SITES" "/sites" - -PROXY_ACME_CHALLENGE=.well-known/acme-challenge -bf-env "PROXY_ACME_CHALLENGE" "${PROXY_ACME_CHALLENGE}" -bf-env "PROXY_WWW_ACME_CHALLENGE" "${NGINX_WWW}/${PROXY_ACME_CHALLENGE}" - -if [ "${PROXY_GETSSL_DEBUG-}" = "1" ] ; then - bf-env "PROXY_GETSSL_FLAGS" "-d -U" -else - bf-env "PROXY_GETSSL_FLAGS" "-U" -fi - -if [ -n "${PROXY_URI-}" ] ; then - bf-notok "Please rename your PROXY_URI environment variable to PROXY_DOMAIN." - bf-env "PROXY_DOMAIN" "${PROXY_URI}" -fi diff --git a/overlay/etc/bf/init.d/20-env.nu b/overlay/etc/bf/init.d/20-env.nu new file mode 100644 index 0000000..4b83a25 --- /dev/null +++ b/overlay/etc/bf/init.d/20-env.nu @@ -0,0 +1,35 @@ +use bf +bf env load + +# Set environment variables +def main []: nothing -> nothing { + bf env set "PROXY_GETSSL" "/usr/bin/getssl" + + let proxy_ssl = "/ssl" + bf env set "PROXY_SSL" $proxy_ssl + bf env set "PROXY_SSL_CONF" $"($proxy_ssl)/conf.json" + bf env set "PROXY_SSL_DHPARAM" $"($proxy_ssl)/dhparam.pem" + + let proxy_ssl_certs = $"($proxy_ssl)/certs" + let proxy_getssl_config = "getssl.cfg" + bf env set "PROXY_SSL_CERTS" $proxy_ssl_certs + bf env set "PROXY_GETSSL_CFG" $proxy_getssl_config + bf env set "PROXY_GETSSL_GLOBAL_CFG" $"($proxy_ssl_certs)/($proxy_getssl_config)" + bf env set "PROXY_GETSSL_ACCOUNT_KEY" $"($proxy_ssl_certs)/account.key" + + let proxy_sites = "/sites" + bf env set "PROXY_SITES" $proxy_sites + + let proxy_acme_challenge = ".well-known/acme-challenge" + bf env set "PROXY_ACME_CHALLENGE" $proxy_acme_challenge + bf env set "PROXY_WWW_ACME_CHALLENGE" $"(bf env NGINX_WWW)/($proxy_acme_challenge)" + + let getssl_flags = match (bf env check PROXY_GETSSL_DEBUG) { + true => "-d -U" + false => "-U" + } + bf env set "PROXY_GETSSL_FLAGS" $getssl_flags + + # return nothing + return +} diff --git a/overlay/etc/bf/init.d/21-ssl-conf b/overlay/etc/bf/init.d/21-ssl-conf deleted file mode 100644 index 1d92e73..0000000 --- a/overlay/etc/bf/init.d/21-ssl-conf +++ /dev/null @@ -1,19 +0,0 @@ -#!/command/with-contenv bash - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Generate Nginx SSL configuration file. -#====================================================================================================================== - -if [ "${PROXY_HARDEN}" = "1" ] ; then - TEMPLATE="modern" -else - TEMPLATE="intermediate" -fi - -bf-echo "Using ${TEMPLATE} SSL configuration." -bf-esh ${BF_TEMPLATES}/ssl-${TEMPLATE}.conf.esh /etc/nginx/http.d/ssl.conf -bf-done diff --git a/overlay/etc/bf/init.d/21-ssl-conf.nu b/overlay/etc/bf/init.d/21-ssl-conf.nu new file mode 100644 index 0000000..9419e49 --- /dev/null +++ b/overlay/etc/bf/init.d/21-ssl-conf.nu @@ -0,0 +1,15 @@ +use bf +bf env load + +# Generate SSL configuration file +def main []: nothing -> nothing { + let template = match (bf env check PROXY_HARDEN) { + true => "modern" + false => "intermediate" + } + + bf write $"Using ($template) SSL configuration - see https://ssl-config.mozilla.org." + bf esh $"(bf env ETC_TEMPLATES)/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" + + return +} diff --git a/overlay/etc/bf/init.d/22-ssl-init b/overlay/etc/bf/init.d/22-ssl-init deleted file mode 100644 index 41baef6..0000000 --- a/overlay/etc/bf/init.d/22-ssl-init +++ /dev/null @@ -1,49 +0,0 @@ -#!/command/with-contenv bash - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Check for clean install. -#====================================================================================================================== - -if [ "${PROXY_CLEAN_INSTALL}" = "1" ] ; then - - bf-echo "Clean install detected..." - bf-rmrf "${PROXY_GETSSL_GLOBAL_CFG}" - bf-rmrf "${PROXY_SSL_DHPARAM}" - bf-rmrf "${PROXY_SSL_CERTS}/*" - bf-rmrf "${PROXY_SITES}/*" - bf-done - -fi - - -#====================================================================================================================== -# If there is no SSL configuration file, and auto environment variables are set, generate config. -#====================================================================================================================== - -if [ ! -f "${PROXY_SSL_CONF}" ] && [ -n "${PROXY_AUTO_PRIMARY-}" ] && [ -n "${PROXY_AUTO_UPSTREAM-}" ] ; then - - # generate conf - bf-echo "Generating conf.json using auto environment variables." - bf-esh ${BF_TEMPLATES}/conf.json.esh ${PROXY_SSL_CONF} - bf-env "PROXY_AUTO" "1" - - # if there are aliases enable canonical redirection - [[ -n "${PROXY_AUTO_ALIASES-}" ]] && bf-env "PROXY_SSL_REDIRECT_TO_CANONICAL" "1" - - # initialise all domains (proxy plus auto) - ssl-init -a - - -#====================================================================================================================== -# Run initialisation script only for the proxy domain. -#====================================================================================================================== - -else - - ssl-init -d "proxy" - -fi diff --git a/overlay/etc/bf/init.d/22-ssl-init.nu b/overlay/etc/bf/init.d/22-ssl-init.nu new file mode 100644 index 0000000..28f5589 --- /dev/null +++ b/overlay/etc/bf/init.d/22-ssl-init.nu @@ -0,0 +1,45 @@ +use bf +use bf/nginx/proxy +bf env load + +# Initialise SSL global config and proxy domain +def main []: nothing -> nothing { + # check for clean install + if (bf env check PROXY_CLEAN_INSTALL) { + bf write "Clean install detected - removing:" + bf env PROXY_GETSSL_GLOBAL_CFG | remove + bf env PROXY_SITES | $"$($in)/*" | remove + bf env PROXY_SSL_CERTS | $"$($in)/*" | remove + bf env PROXY_SSL_DHPARAM | remove + } + + # check for auto setup + let proxy_ssl_does_not_exist = bf env PROXY_SSL_CONF | bf fs is_not_file + let proxy_auto_primary_is_set = bf env -s PROXY_AUTO_PRIMARY | is-not-empty + let proxy_auto_upstream_is_set = bf env -s PROXY_AUTO_UPSTREAM | is-not-empty + + # if there is no SSL config, and auto environment variables are set, generate config and ssl + # otherwise, generate SSL for root domain only + if $proxy_ssl_does_not_exist and $proxy_auto_primary_is_set and $proxy_auto_upstream_is_set { + # set PROXY_AUTO so we know downstream that we are auto generating files + bf env set "PROXY_AUTO" "1" + + # generate conf.json + proxy conf generate_conf_json + + # if there are aliases enable canonical redirection + if (bf env check "PROXY_AUTO_ALIASES") { bf env set "PROXY_SSL_REDIRECT_TO_CANONICAL" "1" } + + # initialise all domains (effectively proxy plus auto) + proxy init all + } else { + proxy init root + } +} + +# Remove file(s) by converting input into a glob before calling `rm` +def remove []: string -> nothing { + let file = $in | into glob + bf write debug $" .. ($file)" + rm --force --recursive $file +} diff --git a/overlay/etc/bf/init.d/23-maintenance.nu b/overlay/etc/bf/init.d/23-maintenance.nu new file mode 100644 index 0000000..95b2067 --- /dev/null +++ b/overlay/etc/bf/init.d/23-maintenance.nu @@ -0,0 +1,11 @@ +use bf +bf env load + +# Generate maintenance page and config +def main []: nothing -> nothing { + bf write "Generating maintenance files." + bf esh template "/etc/nginx/helpers/proxy-maintenance.conf" + bf esh template $"(bf env NGINX_PUBLIC)/maintenance.html" + + return +} diff --git a/overlay/etc/bf/init.d/24-maintenance b/overlay/etc/bf/init.d/24-maintenance deleted file mode 100644 index 14c6521..0000000 --- a/overlay/etc/bf/init.d/24-maintenance +++ /dev/null @@ -1,14 +0,0 @@ -#!/command/with-contenv bash - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Generate maintenance configuration helper and page. -#====================================================================================================================== - -bf-echo "Generating maintenance files." -bf-esh ${BF_TEMPLATES}/proxy-maintenance.conf.esh /etc/nginx/helpers/proxy-maintenance.conf -bf-esh ${BF_TEMPLATES}/maintenance.html.esh ${NGINX_PUBLIC}/maintenance.html -bf-done From 987513175f233a3e86a82ab43c39e2149ea82e40 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:38:50 +0000 Subject: [PATCH 14/76] Updating SSL conf --- overlay/etc/bf/templates/ssl-intermediate.conf.esh | 5 +++-- overlay/etc/bf/templates/ssl-modern.conf.esh | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/overlay/etc/bf/templates/ssl-intermediate.conf.esh b/overlay/etc/bf/templates/ssl-intermediate.conf.esh index cfca0b2..460f54a 100644 --- a/overlay/etc/bf/templates/ssl-intermediate.conf.esh +++ b/overlay/etc/bf/templates/ssl-intermediate.conf.esh @@ -1,10 +1,11 @@ #====================================================================================================================== # SSL -# Using Mozilla's SSL Configuration Generator with 'Intermediate' settings - https://ssl-config.mozilla.org/ +# Using Mozilla's SSL Configuration Generator with 'Intermediate' settings +# See https://ssl-config.mozilla.org/#server=nginx&version=1.26.0&config=intermediate #====================================================================================================================== 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_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:DHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers off; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; diff --git a/overlay/etc/bf/templates/ssl-modern.conf.esh b/overlay/etc/bf/templates/ssl-modern.conf.esh index 9d476d8..6913f1b 100644 --- a/overlay/etc/bf/templates/ssl-modern.conf.esh +++ b/overlay/etc/bf/templates/ssl-modern.conf.esh @@ -1,6 +1,7 @@ #====================================================================================================================== # SSL -# Using Mozilla's SSL Configuration Generator with 'Modern' settings - https://ssl-config.mozilla.org/ +# Using Mozilla's SSL Configuration Generator with 'Modern' settings +# See https://ssl-config.mozilla.org/#server=nginx&version=1.26.0&config=modern #====================================================================================================================== ssl_protocols TLSv1.3; From 10d368009eac95fd4c0dedc919d8cee39e0fa574 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:39:07 +0000 Subject: [PATCH 15/76] Migrating install to nu --- overlay/tmp/install | 102 +++++++++++++------------------------------- 1 file changed, 30 insertions(+), 72 deletions(-) diff --git a/overlay/tmp/install b/overlay/tmp/install index 8090f3f..97d7dfd 100644 --- a/overlay/tmp/install +++ b/overlay/tmp/install @@ -1,72 +1,30 @@ -#!/bin/sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Get Nginx Version. -#====================================================================================================================== - -cd /tmp - -VERSION=$(cat NGINX_BUILD) -bf-echo "Nginx version ${VERSION}." - - -#====================================================================================================================== -# Install Nginx extensions. -#====================================================================================================================== - -bf-echo "Installing Nginx v${VERSION} extensions..." -apk add --no-cache \ - nginx-mod-http-naxsi=${VERSION} \ - nginx-mod-http-set-misc=${VERSION} -bf-done - - -#====================================================================================================================== -# Install additional packages. -#====================================================================================================================== - -bf-echo "Installing additional packages..." -apk add --no-cache \ - bash \ - curl \ - jq \ - openssl -bf-done - - -#====================================================================================================================== -# Download getssl script. -#====================================================================================================================== - -VERSION=`cat /tmp/GETSSL_VERSION` -bf-echo "Downloading getssl ${VERSION}." - -GETSSL=/usr/lib/bf/proxy/getssl -wget -O ${GETSSL} "https://raw.githubusercontent.com/srvrco/getssl/v${VERSION}/getssl" -chmod +x ${GETSSL} -bf-done - - -#====================================================================================================================== -# Cleanup. -#====================================================================================================================== - -bf-echo "Cleaning up Nginx sites definitions." -rm -rf /etc/nginx/sites -bf-done - - -#====================================================================================================================== -# Create and link Nginx directories. -#====================================================================================================================== - -bf-echo "Creating and linking Nginx directories." - -mkdir /sites -ln -s /sites /etc/nginx/sites - -mkdir -p /ssl/certs +#!/usr/bin/nu + +use bf + +# Setup and install getssl and depdencies +def main [] { + # get nginx version and install dependencies + cd /tmp + let nginx_version = bf fs read NGINX_BUILD + bf write $"Installing dependencies for getssl." + bf pkg install [ + "curl" + $"nginx-mod-http-set-misc=($nginx_version)" + "openssl" + ] + + # download getssl script and make executable + let getssl_version = bf fs read GETSSL_VERSION + let getssl_url = $"https://raw.githubusercontent.com/srvrco/getssl/v($getssl_version)/getssl" + let getssl_exe = "/usr/bin/getssl" + http get $getssl_url | save --raw $getssl_exe + ^chmod +x $getssl_exe + + # create and link directories + ^ln -s /sites /etc/nginx/sites + ^mkdir -p /ssl/certs + + # add bf-nginx-proxy module to config + bf config use bf-nginx-proxy +} From c142af916ec7bd29448e646b67b54e82c249e80e Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:39:15 +0000 Subject: [PATCH 16/76] Adding initial nu modules and tests --- overlay/etc/bf/templates/conf.json.esh | 6 ++-- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 22 +++++++++++++ overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 20 +++++++++++ overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu | 2 ++ overlay/etc/nu/scripts/tests/conf.nu | 33 +++++++++++++++++++ overlay/etc/nu/scripts/tests/mod.nu | 1 + 6 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/init.nu create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu create mode 100644 overlay/etc/nu/scripts/tests/conf.nu create mode 100644 overlay/etc/nu/scripts/tests/mod.nu diff --git a/overlay/etc/bf/templates/conf.json.esh b/overlay/etc/bf/templates/conf.json.esh index 2f2b840..f96c2a1 100644 --- a/overlay/etc/bf/templates/conf.json.esh +++ b/overlay/etc/bf/templates/conf.json.esh @@ -2,9 +2,9 @@ "$schema": "https://raw.githubusercontent.com/bfren/docker-nginx-proxy/main/ssl-conf-schema.json", "domains": [ { - "primary": "<%= ${PROXY_AUTO_PRIMARY} %>", - "upstream": "<%= ${PROXY_AUTO_UPSTREAM} %>"<% if [ -n "${PROXY_AUTO_ALIASES-}" ] ; then %>, - "aliases": [ "<%= ${PROXY_AUTO_ALIASES// /\", \"} %>" ]<% fi ; if [ "${PROXY_AUTO_CUSTOM-}" = "1" ] ; then %>, + "primary": "<%= ${PRIMARY} %>", + "upstream": "<%= ${UPSTREAM} %>"<% if [ -n "${ALIASES}" ] ; then %>, + "aliases": [ "<%= ${ALIASES} %>" ]<% fi ; if [ "${CUSTOM}" = "1" ] ; then %>, "custom": true<% fi %> } ] diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu new file mode 100644 index 0000000..f1c0786 --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -0,0 +1,22 @@ +use bf + +# Generate conf.json as part of auto setup +export def generate_conf_json []: nothing -> nothing { + # setup variables + let primary = bf env "PROXY_AUTO_PRIMARY" + let upstream = bf env "PROXY_AUTO_UPSTREAM" + let aliases = match (bf env -s "PROXY_AUTO_ALIASES") { + "" => "" + $a => $"'($a | split words | str join "', '")'" + } + let custom = bf env check "PROXY_AUTO_CUSTOM" + + # generate file + bf write "Generating conf.json using auto environment variables." + with-env { PRIMARY: $primary, UPSTREAM: $upstream, ALIASES: $aliases, CUSTOM: $custom } { + bf esh template (bf env "PROXY_SSL_CONF") + } + + # return nothing + return +} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu new file mode 100644 index 0000000..e830c39 --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -0,0 +1,20 @@ +use bf + +# Initialise SSL for all configured domains +export def all []: nothing -> nothing { + +} + +# Initialise SSL for the specified domain +export def domain [ + domain: string # the domain to initialise +]: nothing -> nothing { + +} + +# Initialise SSL for the root domain +export def root [ + +]: nothing -> nothing { + domain (bf env "PROXY_DOMAIN") +} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu new file mode 100644 index 0000000..644c8cf --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu @@ -0,0 +1,2 @@ +export module conf.nu +export module init.nu diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu new file mode 100644 index 0000000..6e01ae4 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -0,0 +1,33 @@ +use std assert +use ../bf/nginx/proxy conf * + +#====================================================================================================================== +# generate_conf_json +#====================================================================================================================== + +def get_e [ + primary?: string + upstream?: string + aliases?: string + custom?: string +]: nothing -> record { + return { + BF_ETC_TEMPLATES: "/etc/bf/templates" + BF_PROXY_AUTO_PRIMARY: (match $primary { null => (random chars), _ => $primary }) + BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) + BF_PROXY_AUTO_ALIASES: $aliases + BF_PROXY_AUTO_CUSTOM: $custom + BF_PROXY_SSL_CONF: "/tmp/conf.json" + } +} + +export def generate_conf_json__outputs_primary [] { + let primary = random chars + let upstream = random chars + let output = "/tmp/conf.json" + let e = get_e + + let result = with-env $e { generate_conf_json } | open $output + + echo $result +} diff --git a/overlay/etc/nu/scripts/tests/mod.nu b/overlay/etc/nu/scripts/tests/mod.nu new file mode 100644 index 0000000..ad3e7f5 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/mod.nu @@ -0,0 +1 @@ +export module conf.nu From 0a3308bdc75a4d5f2f444baf8d977897dd082d70 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:39:21 +0000 Subject: [PATCH 17/76] Adding test.sh --- test.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test.sh diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..6aeb2f0 --- /dev/null +++ b/test.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +IMAGE=`cat VERSION` + +docker buildx build \ + --load \ + --build-arg BF_IMAGE=nginx-proxy \ + --build-arg BF_VERSION=${IMAGE} \ + -f Dockerfile \ + -t nginx-proxy-test \ + . \ + && \ + docker run --entrypoint "/usr/bin/env" nginx-proxy-test env -i nu -c "use bf test ; test" From 21c3d8e01b9906e970674a37ecbfe72acf564635 Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:39:29 +0000 Subject: [PATCH 18/76] Updating to Nginx 1.26.2 --- overlay/tmp/NGINX_BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overlay/tmp/NGINX_BUILD b/overlay/tmp/NGINX_BUILD index 193e3db..05147ef 100644 --- a/overlay/tmp/NGINX_BUILD +++ b/overlay/tmp/NGINX_BUILD @@ -1 +1 @@ -1.24.0-r7 \ No newline at end of file +1.26.2-r0 \ No newline at end of file From 2c780f03c7bf79b4b6f000c5a8e027b92602e46a Mon Sep 17 00:00:00 2001 From: bfren Date: Thu, 21 Nov 2024 17:39:37 +0000 Subject: [PATCH 19/76] Adding BF prefix to environment variables --- Dockerfile | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index caa67e9..97b6456 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.20-6.3.1 +FROM bfren/nginx:nginx1.26-alpine3.20-6.3.13 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" @@ -12,36 +12,36 @@ COPY ./overlay / ENV \ # the base domain of the proxy server (will be used when SSL bindings fail) - PROXY_DOMAIN= \ + BF_PROXY_DOMAIN= \ # clean all config and certificates before doing anything else - PROXY_CLEAN_INSTALL=0 \ + BF_PROXY_CLEAN_INSTALL=0 \ # enable automatic certificate updating - PROXY_ENABLE_AUTO_UPDATE=1 \ - # use hardened mode (remove old / insecure ciphers and protocols) - PROXY_HARDEN=0 \ + BF_PROXY_ENABLE_AUTO_UPDATE=1 \ + # use hardened mode (e.g. remove old / insecure ciphers and protocols) + BF_PROXY_HARDEN=0 \ # used for renewal notification emails - PROXY_LETS_ENCRYPT_EMAIL= \ + BF_PROXY_LETS_ENCRYPT_EMAIL= \ # set to 1 to use live instead of staging server - PROXY_LETS_ENCRYPT_LIVE=0 \ + BF_PROXY_LETS_ENCRYPT_LIVE=0 \ # set to the number of bits to use for generating private key - PROXY_SSL_KEY_BITS=4096 \ + BF_PROXY_SSL_KEY_BITS=4096 \ # set to the number of bits to use for generating DHPARAM - PROXY_SSL_DHPARAM_BITS=4096 \ + BF_PROXY_SSL_DHPARAM_BITS=4096 \ # canonical domain name redirection - PROXY_SSL_REDIRECT_TO_CANONICAL=0 \ + BF_PROXY_SSL_REDIRECT_TO_CANONICAL=0 \ # set to true to skip local HTTP token check - PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK="false" \ + BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK="false" \ # if both are set, on first startup will generate SSL config and request certs - PROXY_AUTO_PRIMARY= \ - PROXY_AUTO_UPSTREAM= \ + BF_PROXY_AUTO_PRIMARY= \ + BF_PROXY_AUTO_UPSTREAM= \ # optional - add aliases to the auto-generated conf.json on first startup - PROXY_AUTO_ALIASES= \ + BF_PROXY_AUTO_ALIASES= \ # optional - mark the Nginx config as custom so it isn't regenerated on future startups - PROXY_AUTO_CUSTOM=0 \ + BF_PROXY_AUTO_CUSTOM=0 \ # upstream DNS resolver, set to Docker's internal resolver by default - PROXY_UPSTREAM_DNS_RESOLVER=127.0.0.11 \ + BF_PROXY_UPSTREAM_DNS_RESOLVER=127.0.0.11 \ # the number of seconds before the maintenance page will auto-refresh - PROXY_MAINTENANCE_REFRESH_SECONDS=6 + BF_PROXY_MAINTENANCE_REFRESH_SECONDS=6 RUN bf-install From b888bdcdbc58e84c6acaaae2161119eaf37ee837 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 10:36:02 +0000 Subject: [PATCH 20/76] Using latest base image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 97b6456..e446577 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.20-6.3.13 +FROM bfren/nginx:nginx1.26-alpine3.20-6.3.14 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" From ff75b9afe5c767952e43351f3eaa2459494f6cae Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 10:49:24 +0000 Subject: [PATCH 21/76] Updating test.sh --- test.env | 1 + test.sh | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 test.env mode change 100644 => 100755 test.sh diff --git a/test.env b/test.env new file mode 100644 index 0000000..1961c35 --- /dev/null +++ b/test.env @@ -0,0 +1 @@ +BF_PROXY_DOMAIN=localhost \ No newline at end of file diff --git a/test.sh b/test.sh old mode 100644 new mode 100755 index 6aeb2f0..c4199ad --- a/test.sh +++ b/test.sh @@ -1,13 +1,16 @@ #!/bin/sh -IMAGE=`cat VERSION` +IMAGE=nginx-proxy +VERSION=`cat VERSION` +ALPINE=${1:-3.20} +TAG=${IMAGE}-test docker buildx build \ --load \ - --build-arg BF_IMAGE=nginx-proxy \ - --build-arg BF_VERSION=${IMAGE} \ + --build-arg BF_IMAGE=${IMAGE} \ + --build-arg BF_VERSION=${VERSION} \ -f Dockerfile \ - -t nginx-proxy-test \ + -t ${TAG} \ . \ && \ - docker run --entrypoint "/usr/bin/env" nginx-proxy-test env -i nu -c "use bf test ; test" + docker run --env-file ./test.env --entrypoint /test ${TAG} From 344b143e39503a18c54e30b516b0ac5e238b10e0 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 10:49:41 +0000 Subject: [PATCH 22/76] Adding conf test --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 10 ++++++--- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 2 +- overlay/etc/nu/scripts/tests/conf.nu | 22 ++++++++++--------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index f1c0786..b435078 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -7,15 +7,19 @@ export def generate_conf_json []: nothing -> nothing { let upstream = bf env "PROXY_AUTO_UPSTREAM" let aliases = match (bf env -s "PROXY_AUTO_ALIASES") { "" => "" - $a => $"'($a | split words | str join "', '")'" + $a => ($a | split words | str join "\", \"" | $"\"($in)\"") } let custom = bf env check "PROXY_AUTO_CUSTOM" # generate file bf write "Generating conf.json using auto environment variables." - with-env { PRIMARY: $primary, UPSTREAM: $upstream, ALIASES: $aliases, CUSTOM: $custom } { - bf esh template (bf env "PROXY_SSL_CONF") + let e = { + PRIMARY: $primary + UPSTREAM: $upstream + ALIASES: $aliases + CUSTOM: $custom } + with-env $e { bf esh template (bf env "PROXY_SSL_CONF") } # return nothing return diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index e830c39..a097dd4 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -7,7 +7,7 @@ export def all []: nothing -> nothing { # Initialise SSL for the specified domain export def domain [ - domain: string # the domain to initialise + domain: string # The domain to initialise ]: nothing -> nothing { } diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 6e01ae4..2d3ef67 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -1,3 +1,4 @@ +use bf use std assert use ../bf/nginx/proxy conf * @@ -6,12 +7,12 @@ use ../bf/nginx/proxy conf * #====================================================================================================================== def get_e [ - primary?: string - upstream?: string - aliases?: string - custom?: string + --primary: string # Optional primary domain name + --upstream: string # Optional upstream server + --aliases: string # Optional domain aliases + --custom: string # Optional 'custom' conf switch ]: nothing -> record { - return { + { BF_ETC_TEMPLATES: "/etc/bf/templates" BF_PROXY_AUTO_PRIMARY: (match $primary { null => (random chars), _ => $primary }) BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) @@ -22,12 +23,13 @@ def get_e [ } export def generate_conf_json__outputs_primary [] { - let primary = random chars - let upstream = random chars + let primary = random chars --length 5 let output = "/tmp/conf.json" - let e = get_e + let e = get_e --primary $primary | bf dump -e -t "Env" + ls /etc/bf/templates | bf dump -e -t "Templ" + echo $env.PATH | bf dump -e -t "Path" - let result = with-env $e { generate_conf_json } | open $output + let result = with-env $e { generate_conf_json } | open $output | get domains.primary - echo $result + assert equal $primary $result } From 3406e7db72525e9079f883c11500c20b540308de Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 10:51:57 +0000 Subject: [PATCH 23/76] Finishing first conf test --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 2 +- overlay/etc/nu/scripts/tests/conf.nu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index b435078..6e5a296 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -9,7 +9,7 @@ export def generate_conf_json []: nothing -> nothing { "" => "" $a => ($a | split words | str join "\", \"" | $"\"($in)\"") } - let custom = bf env check "PROXY_AUTO_CUSTOM" + let custom = bf env -s "PROXY_AUTO_CUSTOM" # generate file bf write "Generating conf.json using auto environment variables." diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 2d3ef67..a648c4c 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -29,7 +29,7 @@ export def generate_conf_json__outputs_primary [] { ls /etc/bf/templates | bf dump -e -t "Templ" echo $env.PATH | bf dump -e -t "Path" - let result = with-env $e { generate_conf_json } | open $output | get domains.primary + let result = with-env $e { generate_conf_json } | open $output | get domains.primary | first assert equal $primary $result } From a8ff487b8bd3a40bf4662e7ad51a5639bcb53b6d Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 11:07:12 +0000 Subject: [PATCH 24/76] Finishing conf.json tests --- overlay/etc/bf/templates/conf.json.esh | 2 +- overlay/etc/nu/scripts/tests/conf.nu | 31 +++++++++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/overlay/etc/bf/templates/conf.json.esh b/overlay/etc/bf/templates/conf.json.esh index f96c2a1..59141ee 100644 --- a/overlay/etc/bf/templates/conf.json.esh +++ b/overlay/etc/bf/templates/conf.json.esh @@ -4,7 +4,7 @@ { "primary": "<%= ${PRIMARY} %>", "upstream": "<%= ${UPSTREAM} %>"<% if [ -n "${ALIASES}" ] ; then %>, - "aliases": [ "<%= ${ALIASES} %>" ]<% fi ; if [ "${CUSTOM}" = "1" ] ; then %>, + "aliases": [ <%= ${ALIASES} %> ]<% fi ; if [ "${CUSTOM}" = "1" ] ; then %>, "custom": true<% fi %> } ] diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index a648c4c..7d61892 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -6,6 +6,8 @@ use ../bf/nginx/proxy conf * # generate_conf_json #====================================================================================================================== +const OUTPUT = "/tmp/conf.json" + def get_e [ --primary: string # Optional primary domain name --upstream: string # Optional upstream server @@ -18,18 +20,35 @@ def get_e [ BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) BF_PROXY_AUTO_ALIASES: $aliases BF_PROXY_AUTO_CUSTOM: $custom - BF_PROXY_SSL_CONF: "/tmp/conf.json" + BF_PROXY_SSL_CONF: $OUTPUT } } export def generate_conf_json__outputs_primary [] { let primary = random chars --length 5 - let output = "/tmp/conf.json" - let e = get_e --primary $primary | bf dump -e -t "Env" - ls /etc/bf/templates | bf dump -e -t "Templ" - echo $env.PATH | bf dump -e -t "Path" + let e = get_e --primary $primary - let result = with-env $e { generate_conf_json } | open $output | get domains.primary | first + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.primary | first assert equal $primary $result } + +export def generate_conf_json__outputs_upstream [] { + let upstream = random chars --length 5 + let e = get_e --upstream $upstream + + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.upstream | first + + assert equal $upstream $result +} + +export def generate_conf_json__outputs_aliases [] { + let aliases = 0..2 | each {|| random chars --length 5 } | bf dump -e -t "aliases" + let aliases_in = $aliases | str join " " + let e = get_e --aliases $aliases_in + + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.aliases | first + + open --raw $OUTPUT | bf dump -e -t "conf" + assert equal $aliases $result +} From e6751e9e7e8e327968a56bf2b992c0b0918b7748 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 11:27:33 +0000 Subject: [PATCH 25/76] Removing old dump --- overlay/etc/nu/scripts/tests/conf.nu | 1 - 1 file changed, 1 deletion(-) diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 7d61892..b280b06 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -49,6 +49,5 @@ export def generate_conf_json__outputs_aliases [] { let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.aliases | first - open --raw $OUTPUT | bf dump -e -t "conf" assert equal $aliases $result } From 2a5506d0fdf822c5012bb878a3c926af055e5dc9 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 15:31:23 +0000 Subject: [PATCH 26/76] Adding custom tests --- overlay/etc/nu/scripts/tests/conf.nu | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index b280b06..23a9c2d 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -12,14 +12,14 @@ def get_e [ --primary: string # Optional primary domain name --upstream: string # Optional upstream server --aliases: string # Optional domain aliases - --custom: string # Optional 'custom' conf switch + --custom # Optional 'custom' conf switch ]: nothing -> record { { BF_ETC_TEMPLATES: "/etc/bf/templates" BF_PROXY_AUTO_PRIMARY: (match $primary { null => (random chars), _ => $primary }) BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) BF_PROXY_AUTO_ALIASES: $aliases - BF_PROXY_AUTO_CUSTOM: $custom + BF_PROXY_AUTO_CUSTOM: (match $custom { true => "1", false => "" }) BF_PROXY_SSL_CONF: $OUTPUT } } @@ -28,7 +28,7 @@ export def generate_conf_json__outputs_primary [] { let primary = random chars --length 5 let e = get_e --primary $primary - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.primary | first + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.primary assert equal $primary $result } @@ -37,17 +37,33 @@ export def generate_conf_json__outputs_upstream [] { let upstream = random chars --length 5 let e = get_e --upstream $upstream - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.upstream | first + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.upstream assert equal $upstream $result } export def generate_conf_json__outputs_aliases [] { - let aliases = 0..2 | each {|| random chars --length 5 } | bf dump -e -t "aliases" + let aliases = 0..2 | each {|| random chars --length 5 } let aliases_in = $aliases | str join " " let e = get_e --aliases $aliases_in - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.aliases | first + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.aliases assert equal $aliases $result } + +export def generate_conf_json__outputs_custom [] { + let e = get_e --custom + + let result = with-env $e { generate_conf_json } | open $OUTPUT | get -i domains.0.custom + + assert equal true $result +} + +export def generate_conf_json__does_not_output_custom [] { + let e = get_e + + let result = with-env $e { generate_conf_json } | open $OUTPUT | get -i domains.0.custom + + assert equal null $result +} From 544ba63fbb1cab0c000a10fa707d0ca669198f1e Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 22 Nov 2024 15:32:34 +0000 Subject: [PATCH 27/76] Test not outputting custom property --- overlay/etc/nu/scripts/tests/conf.nu | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 23a9c2d..5890c2f 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -52,10 +52,18 @@ export def generate_conf_json__outputs_aliases [] { assert equal $aliases $result } +export def generate_conf_json__does_not_output_aliases [] { + let e = get_e + + let result = with-env $e { generate_conf_json } | open $OUTPUT | get -i domains.0.aliases + + assert equal null $result +} + export def generate_conf_json__outputs_custom [] { let e = get_e --custom - let result = with-env $e { generate_conf_json } | open $OUTPUT | get -i domains.0.custom + let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.custom assert equal true $result } From 16c0d1403714bc5c500e872c0dd4e4b21bcf0e16 Mon Sep 17 00:00:00 2001 From: bfren Date: Sat, 23 Nov 2024 08:53:20 +0000 Subject: [PATCH 28/76] Moving generate Nginx conf to script and adding tests --- overlay/etc/bf/init.d/21-ssl-conf.nu | 14 +--- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 16 +++++ overlay/etc/nu/scripts/tests/conf.nu | 69 ++++++++++++++----- 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/overlay/etc/bf/init.d/21-ssl-conf.nu b/overlay/etc/bf/init.d/21-ssl-conf.nu index 9419e49..a2dc367 100644 --- a/overlay/etc/bf/init.d/21-ssl-conf.nu +++ b/overlay/etc/bf/init.d/21-ssl-conf.nu @@ -1,15 +1,5 @@ -use bf +use bf/nginx/proxy conf bf env load # Generate SSL configuration file -def main []: nothing -> nothing { - let template = match (bf env check PROXY_HARDEN) { - true => "modern" - false => "intermediate" - } - - bf write $"Using ($template) SSL configuration - see https://ssl-config.mozilla.org." - bf esh $"(bf env ETC_TEMPLATES)/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" - - return -} +def main []: nothing -> nothing { conf generate_nginx_ssl_conf } diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 6e5a296..b121bee 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -1,5 +1,21 @@ use bf +# Generate Nginx SSL config +export def generate_nginx_ssl_conf []: nothing -> nothing { + # get the template name + let template = match (bf env check PROXY_HARDEN) { + true => "modern" + false => "intermediate" + } + + # generate config file + bf write $"Using ($template) SSL configuration." + bf esh $"(bf env ETC_TEMPLATES)/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" + + # return nothing + return +} + # Generate conf.json as part of auto setup export def generate_conf_json []: nothing -> nothing { # setup variables diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 5890c2f..efbd495 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -2,42 +2,79 @@ use bf use std assert use ../bf/nginx/proxy conf * +const ETC_TEMPLATES = "/etc/bf/templates" + + +#====================================================================================================================== +# generate_nginx_ssl_conf +#====================================================================================================================== + +const NGINX_SSL_OUTPUT = "/etc/nginx/http.d/ssl.conf" + +def generate_nginx_ssl_conf_e [ + --harden # Optional harden switch +] { + { + BF_ETC_TEMPLATES: $ETC_TEMPLATES + BF_PROXY_HARDEN: (match $harden { true => "1", false => "" }) + } +} + +export def generate_nginx_ssl_conf__outputs_intermediate_conf [] { + let e = generate_nginx_ssl_conf_e + let expected = "c8864a579b0ec2cb4070f27affb4e05f" + + let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_OUTPUT | hash md5 + open $NGINX_SSL_OUTPUT | bf dump -e -t "ssl" + + assert equal $expected $result +} + +export def generate_nginx_ssl_conf__outputs_modern_conf [] { + let e = generate_nginx_ssl_conf_e --harden + let expected = "73f99a3458030a8dae265a10355032e3" + + let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_OUTPUT | hash md5 + + assert equal $expected $result +} + #====================================================================================================================== # generate_conf_json #====================================================================================================================== -const OUTPUT = "/tmp/conf.json" +const CONF_JSON_OUTPUT = "/tmp/conf.json" -def get_e [ +def get_conf_json_e [ --primary: string # Optional primary domain name --upstream: string # Optional upstream server --aliases: string # Optional domain aliases --custom # Optional 'custom' conf switch ]: nothing -> record { { - BF_ETC_TEMPLATES: "/etc/bf/templates" + BF_ETC_TEMPLATES: $ETC_TEMPLATES BF_PROXY_AUTO_PRIMARY: (match $primary { null => (random chars), _ => $primary }) BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) BF_PROXY_AUTO_ALIASES: $aliases BF_PROXY_AUTO_CUSTOM: (match $custom { true => "1", false => "" }) - BF_PROXY_SSL_CONF: $OUTPUT + BF_PROXY_SSL_CONF: $CONF_JSON_OUTPUT } } export def generate_conf_json__outputs_primary [] { let primary = random chars --length 5 - let e = get_e --primary $primary + let e = get_conf_json_e --primary $primary - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.primary + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.primary assert equal $primary $result } export def generate_conf_json__outputs_upstream [] { let upstream = random chars --length 5 - let e = get_e --upstream $upstream + let e = get_conf_json_e --upstream $upstream - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.upstream + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.upstream assert equal $upstream $result } @@ -45,33 +82,33 @@ export def generate_conf_json__outputs_upstream [] { export def generate_conf_json__outputs_aliases [] { let aliases = 0..2 | each {|| random chars --length 5 } let aliases_in = $aliases | str join " " - let e = get_e --aliases $aliases_in + let e = get_conf_json_e --aliases $aliases_in - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.aliases + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.aliases assert equal $aliases $result } export def generate_conf_json__does_not_output_aliases [] { - let e = get_e + let e = get_conf_json_e - let result = with-env $e { generate_conf_json } | open $OUTPUT | get -i domains.0.aliases + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.aliases assert equal null $result } export def generate_conf_json__outputs_custom [] { - let e = get_e --custom + let e = get_conf_json_e --custom - let result = with-env $e { generate_conf_json } | open $OUTPUT | get domains.0.custom + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.custom assert equal true $result } export def generate_conf_json__does_not_output_custom [] { - let e = get_e + let e = get_conf_json_e - let result = with-env $e { generate_conf_json } | open $OUTPUT | get -i domains.0.custom + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.custom assert equal null $result } From 50f50d634b7054aaad9346ce297906bd84fe0f42 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 10:32:25 +0000 Subject: [PATCH 29/76] Moving auto scripts and tests into separate module --- overlay/etc/bf/init.d/22-ssl-init.nu | 30 ++-- overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu | 37 +++++ overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 25 ---- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 16 +++ overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu | 1 + overlay/etc/nu/scripts/tests/auto.nu | 132 ++++++++++++++++++ overlay/etc/nu/scripts/tests/conf.nu | 74 ---------- overlay/etc/nu/scripts/tests/init.nu | 39 ++++++ overlay/etc/nu/scripts/tests/mod.nu | 2 + 9 files changed, 235 insertions(+), 121 deletions(-) create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu create mode 100644 overlay/etc/nu/scripts/tests/auto.nu create mode 100644 overlay/etc/nu/scripts/tests/init.nu diff --git a/overlay/etc/bf/init.d/22-ssl-init.nu b/overlay/etc/bf/init.d/22-ssl-init.nu index 28f5589..a29d7ae 100644 --- a/overlay/etc/bf/init.d/22-ssl-init.nu +++ b/overlay/etc/bf/init.d/22-ssl-init.nu @@ -4,42 +4,28 @@ bf env load # Initialise SSL global config and proxy domain def main []: nothing -> nothing { - # check for clean install + # setup for a clean install if (bf env check PROXY_CLEAN_INSTALL) { - bf write "Clean install detected - removing:" - bf env PROXY_GETSSL_GLOBAL_CFG | remove - bf env PROXY_SITES | $"$($in)/*" | remove - bf env PROXY_SSL_CERTS | $"$($in)/*" | remove - bf env PROXY_SSL_DHPARAM | remove + bf write "Clean install detected." + proxy init setup_clean_install } - # check for auto setup - let proxy_ssl_does_not_exist = bf env PROXY_SSL_CONF | bf fs is_not_file - let proxy_auto_primary_is_set = bf env -s PROXY_AUTO_PRIMARY | is-not-empty - let proxy_auto_upstream_is_set = bf env -s PROXY_AUTO_UPSTREAM | is-not-empty - - # if there is no SSL config, and auto environment variables are set, generate config and ssl + # if auto init is enabled, generate config and ssl # otherwise, generate SSL for root domain only - if $proxy_ssl_does_not_exist and $proxy_auto_primary_is_set and $proxy_auto_upstream_is_set { + if (proxy auto is_enabled) { # set PROXY_AUTO so we know downstream that we are auto generating files bf env set "PROXY_AUTO" "1" # generate conf.json - proxy conf generate_conf_json + proxy auto generate_conf_json # if there are aliases enable canonical redirection if (bf env check "PROXY_AUTO_ALIASES") { bf env set "PROXY_SSL_REDIRECT_TO_CANONICAL" "1" } - # initialise all domains (effectively proxy plus auto) + # initialise all domains (root plus auto) proxy init all } else { + # initialise only the root domain proxy init root } } - -# Remove file(s) by converting input into a glob before calling `rm` -def remove []: string -> nothing { - let file = $in | into glob - bf write debug $" .. ($file)" - rm --force --recursive $file -} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu new file mode 100644 index 0000000..0486f8f --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu @@ -0,0 +1,37 @@ +use bf + +# Generate conf.json as part of auto setup +export def generate_conf_json []: nothing -> nothing { + # setup variables + let primary = bf env "PROXY_AUTO_PRIMARY" + let upstream = bf env "PROXY_AUTO_UPSTREAM" + let aliases = match (bf env -s "PROXY_AUTO_ALIASES") { + "" => "" + $a => ($a | split words | str join "\", \"" | $"\"($in)\"") + } + let custom = bf env -s "PROXY_AUTO_CUSTOM" + + # generate file + bf write "Generating conf.json using auto environment variables." + let e = { + PRIMARY: $primary + UPSTREAM: $upstream + ALIASES: $aliases + CUSTOM: $custom + } + with-env $e { bf esh template (bf env "PROXY_SSL_CONF") } + + # return nothing + return +} + +# If SSL config does not exist and auto primary / upstream are set, returns true +export def is_enabled []: nothing -> bool { + # check conditions + let ssl_does_not_exist = bf env PROXY_SSL_CONF | bf fs is_not_file + let auto_primary_is_set = bf env -s PROXY_AUTO_PRIMARY | is-not-empty + let auto_upstream_is_set = bf env -s PROXY_AUTO_UPSTREAM | is-not-empty + + # all conditions must be true + return ($ssl_does_not_exist and $auto_primary_is_set and $auto_upstream_is_set) +} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index b121bee..d9332f0 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -15,28 +15,3 @@ export def generate_nginx_ssl_conf []: nothing -> nothing { # return nothing return } - -# Generate conf.json as part of auto setup -export def generate_conf_json []: nothing -> nothing { - # setup variables - let primary = bf env "PROXY_AUTO_PRIMARY" - let upstream = bf env "PROXY_AUTO_UPSTREAM" - let aliases = match (bf env -s "PROXY_AUTO_ALIASES") { - "" => "" - $a => ($a | split words | str join "\", \"" | $"\"($in)\"") - } - let custom = bf env -s "PROXY_AUTO_CUSTOM" - - # generate file - bf write "Generating conf.json using auto environment variables." - let e = { - PRIMARY: $primary - UPSTREAM: $upstream - ALIASES: $aliases - CUSTOM: $custom - } - with-env $e { bf esh template (bf env "PROXY_SSL_CONF") } - - # return nothing - return -} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index a097dd4..ff54d9a 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -1,5 +1,21 @@ use bf +# Check for clean install and delete +export def setup_clean_install []: nothing -> nothing { + bf write debug " .. removing SSL config and certificates:" + bf env PROXY_GETSSL_GLOBAL_CFG | remove + bf env PROXY_SITES | $"($in)/*" | remove + bf env PROXY_SSL_CERTS | $"($in)/*" | remove + bf env PROXY_SSL_DHPARAM | remove +} + +# Remove file(s) by converting input into a glob before calling `rm` +def remove []: string -> nothing { + let file = $in | into glob + bf write debug $" ($file)" + rm --force --recursive $file +} + # Initialise SSL for all configured domains export def all []: nothing -> nothing { diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu index 644c8cf..374cf9f 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu @@ -1,2 +1,3 @@ +export module auto.nu export module conf.nu export module init.nu diff --git a/overlay/etc/nu/scripts/tests/auto.nu b/overlay/etc/nu/scripts/tests/auto.nu new file mode 100644 index 0000000..f64b446 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/auto.nu @@ -0,0 +1,132 @@ +use bf +use std assert +use ../bf/nginx/proxy auto * + +const ETC_TEMPLATES = "/etc/bf/templates" + + +#====================================================================================================================== +# is_enabled +#====================================================================================================================== + +def is_enabled_e [ + --ssl_conf_exists + --auto_primary_is_empty + --auto_upstream_is_empty +] { + let ssl_conf = mktemp -t + if not $ssl_conf_exists { rm $ssl_conf } + { + BF_PROXY_SSL_CONF: $ssl_conf + BF_PROXY_AUTO_PRIMARY: (match ($auto_primary_is_empty) { true => "", false => "1" }) + BF_PROXY_AUTO_UPSTREAM: (match ($auto_upstream_is_empty) { true => "", false => "1" }) + } +} + +export def is_enabled__returns_false_when_ssl_conf_exists [] { + let e = is_enabled_e --ssl_conf_exists + + let result = with-env $e { is_enabled } + + assert equal false $result +} + +export def is_enabled__returns_false_when_auto_primary_is_empty [] { + let e = is_enabled_e --auto_primary_is_empty + + let result = with-env $e { is_enabled } + + assert equal false $result +} + +export def is_enabled__returns_false_when_auto_upstream_is_empty [] { + let e = is_enabled_e --auto_upstream_is_empty + + let result = with-env $e { is_enabled } + + assert equal false $result +} + +export def is_enabled__returns_true [] { + let e = is_enabled_e + + let result = with-env $e { is_enabled } + + assert equal true $result +} + + +#====================================================================================================================== +# generate_conf_json +#====================================================================================================================== + +const CONF_JSON_OUTPUT = "/tmp/conf.json" + +def get_conf_json_e [ + --primary: string # Optional primary domain name + --upstream: string # Optional upstream server + --aliases: string # Optional domain aliases + --custom # Optional 'custom' conf switch +]: nothing -> record { + { + BF_ETC_TEMPLATES: $ETC_TEMPLATES + BF_PROXY_AUTO_PRIMARY: (match $primary { null => (random chars), _ => $primary }) + BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) + BF_PROXY_AUTO_ALIASES: $aliases + BF_PROXY_AUTO_CUSTOM: (match $custom { true => "1", false => "" }) + BF_PROXY_SSL_CONF: $CONF_JSON_OUTPUT + } +} + +export def generate_conf_json__outputs_primary [] { + let primary = random chars --length 5 + let e = get_conf_json_e --primary $primary + + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.primary + + assert equal $primary $result +} + +export def generate_conf_json__outputs_upstream [] { + let upstream = random chars --length 5 + let e = get_conf_json_e --upstream $upstream + + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.upstream + + assert equal $upstream $result +} + +export def generate_conf_json__outputs_aliases [] { + let aliases = 0..2 | each {|| random chars --length 5 } + let aliases_in = $aliases | str join " " + let e = get_conf_json_e --aliases $aliases_in + + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.aliases + + assert equal $aliases $result +} + +export def generate_conf_json__does_not_output_aliases [] { + let e = get_conf_json_e + + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.aliases + + assert equal null $result +} + +export def generate_conf_json__outputs_custom [] { + let e = get_conf_json_e --custom + + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.custom + + assert equal true $result +} + +export def generate_conf_json__does_not_output_custom [] { + let e = get_conf_json_e + + let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.custom + + assert equal null $result +} + diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index efbd495..a021775 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -38,77 +38,3 @@ export def generate_nginx_ssl_conf__outputs_modern_conf [] { assert equal $expected $result } - -#====================================================================================================================== -# generate_conf_json -#====================================================================================================================== - -const CONF_JSON_OUTPUT = "/tmp/conf.json" - -def get_conf_json_e [ - --primary: string # Optional primary domain name - --upstream: string # Optional upstream server - --aliases: string # Optional domain aliases - --custom # Optional 'custom' conf switch -]: nothing -> record { - { - BF_ETC_TEMPLATES: $ETC_TEMPLATES - BF_PROXY_AUTO_PRIMARY: (match $primary { null => (random chars), _ => $primary }) - BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) - BF_PROXY_AUTO_ALIASES: $aliases - BF_PROXY_AUTO_CUSTOM: (match $custom { true => "1", false => "" }) - BF_PROXY_SSL_CONF: $CONF_JSON_OUTPUT - } -} - -export def generate_conf_json__outputs_primary [] { - let primary = random chars --length 5 - let e = get_conf_json_e --primary $primary - - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.primary - - assert equal $primary $result -} - -export def generate_conf_json__outputs_upstream [] { - let upstream = random chars --length 5 - let e = get_conf_json_e --upstream $upstream - - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.upstream - - assert equal $upstream $result -} - -export def generate_conf_json__outputs_aliases [] { - let aliases = 0..2 | each {|| random chars --length 5 } - let aliases_in = $aliases | str join " " - let e = get_conf_json_e --aliases $aliases_in - - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.aliases - - assert equal $aliases $result -} - -export def generate_conf_json__does_not_output_aliases [] { - let e = get_conf_json_e - - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.aliases - - assert equal null $result -} - -export def generate_conf_json__outputs_custom [] { - let e = get_conf_json_e --custom - - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.custom - - assert equal true $result -} - -export def generate_conf_json__does_not_output_custom [] { - let e = get_conf_json_e - - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.custom - - assert equal null $result -} diff --git a/overlay/etc/nu/scripts/tests/init.nu b/overlay/etc/nu/scripts/tests/init.nu new file mode 100644 index 0000000..c369660 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/init.nu @@ -0,0 +1,39 @@ +use bf +use std assert +use ../bf/nginx/proxy init * + + +#====================================================================================================================== +# setup_clean_install +#====================================================================================================================== + +export def setup_clean_install__removes_files [] { + let getssl_global_cfg = mktemp -t + let sites = mktemp -d -t + let ssl_certs = mktemp -d -t + let ssl_dhparam = mktemp -t + cd $sites ; mktemp ; mktemp + cd $ssl_certs ; mktemp ; mktemp + let e = { + BF_PROXY_GETSSL_GLOBAL_CFG: $getssl_global_cfg + BF_PROXY_SITES: $sites + BF_PROXY_SSL_CERTS: $ssl_certs + BF_PROXY_SSL_DHPARAM: $ssl_dhparam + } + + let result = with-env $e { setup_clean_install } | { + GETSSL_GLOBAL_CFG: ($getssl_global_cfg | path exists) + SITES: ($sites | path exists) + SITES_FILES: (ls $sites | length) + SSL_CERTS: ($ssl_certs | path exists) + SSL_CERTS_FILES: (ls $ssl_certs | length) + SSL_DHPARAM: ($ssl_dhparam | path exists) + } + + assert equal false $result.GETSSL_GLOBAL_CFG + assert equal true $result.SITES + assert equal 0 $result.SITES_FILES + assert equal true $result.SSL_CERTS + assert equal 0 $result.SSL_CERTS_FILES + assert equal false $result.SSL_DHPARAM +} diff --git a/overlay/etc/nu/scripts/tests/mod.nu b/overlay/etc/nu/scripts/tests/mod.nu index ad3e7f5..374cf9f 100644 --- a/overlay/etc/nu/scripts/tests/mod.nu +++ b/overlay/etc/nu/scripts/tests/mod.nu @@ -1 +1,3 @@ +export module auto.nu export module conf.nu +export module init.nu From 4ccbfb492faeface5b815cbf60b498b2357da924 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 10:53:07 +0000 Subject: [PATCH 30/76] Adding conf.json loader and tests --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 5 ++++ overlay/etc/nu/scripts/tests/conf.nu | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index d9332f0..0e2d9f1 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -1,5 +1,10 @@ use bf +# Load ssl configuration +export def load []: nothing -> record>> { + bf env "PROXY_SSL_CONF" | open --raw $in | from json +} + # Generate Nginx SSL config export def generate_nginx_ssl_conf []: nothing -> nothing { # get the template name diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index a021775..4a919de 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -5,6 +5,33 @@ use ../bf/nginx/proxy conf * const ETC_TEMPLATES = "/etc/bf/templates" +#====================================================================================================================== +# load +#====================================================================================================================== + +export def load__returns_ssl_conf_json [] { + let conf = { + "domains": [ + { + "primary": (random chars) + "upstream": (random chars) + "aliases": [(random chars) (random chars)] + "custom": (random bool) + } + ] + } + let file = mktemp -t + $conf | to json | save -f $file + let e = { + BF_PROXY_SSL_CONF: $file + } + + let result = with-env $e { load } + + assert equal $conf $result +} + + #====================================================================================================================== # generate_nginx_ssl_conf #====================================================================================================================== From 4aae68a39912cc01894a3d02c88977e52c3544e2 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 10:55:18 +0000 Subject: [PATCH 31/76] Renaming conf load to get_domains --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 4 ++-- overlay/etc/nu/scripts/tests/conf.nu | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 0e2d9f1..4a27569 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -1,8 +1,8 @@ use bf # Load ssl configuration -export def load []: nothing -> record>> { - bf env "PROXY_SSL_CONF" | open --raw $in | from json +export def get_domains []: nothing -> list> { + bf env "PROXY_SSL_CONF" | open --raw $in | from json | get domains } # Generate Nginx SSL config diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 4a919de..3a11be9 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -6,10 +6,10 @@ const ETC_TEMPLATES = "/etc/bf/templates" #====================================================================================================================== -# load +# get_domains #====================================================================================================================== -export def load__returns_ssl_conf_json [] { +export def get_domains__returns_list_of_domains [] { let conf = { "domains": [ { @@ -26,9 +26,9 @@ export def load__returns_ssl_conf_json [] { BF_PROXY_SSL_CONF: $file } - let result = with-env $e { load } + let result = with-env $e { get_domains } - assert equal $conf $result + assert equal $conf.domains $result } From 811e238fb70303c79d8337dee85ec744758e9e1d Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 11:20:20 +0000 Subject: [PATCH 32/76] Adding BF_ prefix to documentation --- Dockerfile | 14 +++++++------- README.md | 32 ++++++++++++++++---------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index e446577..dde1dac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,26 +11,26 @@ EXPOSE 443 COPY ./overlay / ENV \ - # the base domain of the proxy server (will be used when SSL bindings fail) + # the root domain of the proxy server (will be used when SSL bindings fail) BF_PROXY_DOMAIN= \ - # clean all config and certificates before doing anything else + # delete all config and certificates before doing anything else BF_PROXY_CLEAN_INSTALL=0 \ # enable automatic certificate updating BF_PROXY_ENABLE_AUTO_UPDATE=1 \ # use hardened mode (e.g. remove old / insecure ciphers and protocols) BF_PROXY_HARDEN=0 \ # used for renewal notification emails - BF_PROXY_LETS_ENCRYPT_EMAIL= \ + BF_PROXY_GETSSL_EMAIL= \ # set to 1 to use live instead of staging server - BF_PROXY_LETS_ENCRYPT_LIVE=0 \ + BF_PROXY_GETSSL_USE_LIVE_SERVER=0 \ + # set to true to skip local HTTP token check + BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK="false" \ # set to the number of bits to use for generating private key BF_PROXY_SSL_KEY_BITS=4096 \ # set to the number of bits to use for generating DHPARAM BF_PROXY_SSL_DHPARAM_BITS=4096 \ # canonical domain name redirection BF_PROXY_SSL_REDIRECT_TO_CANONICAL=0 \ - # set to true to skip local HTTP token check - BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK="false" \ # if both are set, on first startup will generate SSL config and request certs BF_PROXY_AUTO_PRIMARY= \ BF_PROXY_AUTO_UPSTREAM= \ @@ -40,7 +40,7 @@ ENV \ BF_PROXY_AUTO_CUSTOM=0 \ # upstream DNS resolver, set to Docker's internal resolver by default BF_PROXY_UPSTREAM_DNS_RESOLVER=127.0.0.11 \ - # the number of seconds before the maintenance page will auto-refresh + # the number of seconds before the maintenance page will automatically refresh BF_PROXY_MAINTENANCE_REFRESH_SECONDS=6 RUN bf-install diff --git a/README.md b/README.md index b649c66..b29a2c0 100644 --- a/README.md +++ b/README.md @@ -34,22 +34,22 @@ For SSL certificate requests to work correctly, ports 80 and 443 need mapping fr ## Environment Variables -| Variable | Values | Description | Default | -| ------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | -| `PROXY_AUTO_PRIMARY` | URI | If set (along with PROXY_AUTO_UPSTREAM) SSL config will be generated on first startup. | *None* | -| `PROXY_AUTO_UPSTREAM` | URI | If set (along with PROXY_AUTO_PRIMARY) SSL config will be generated on first startup. | *None* | -| `PROXY_AUTO_ALIASES` | string of URIs | Add aliases to the auto-generated conf.json on first startup. | *None* | -| `PROXY_AUTO_CUSTOM` | 0 or 1 | Mark the auto-generated SSL config to 'custom' so the Nginx configuration is not regenerated on startup. | 0 | -| `PROXY_CLEAN_INSTALL` | 0 or 1 | If 1, all Nginx and SSL configuration and certificates will be deleted and regenerated. | 0 | -| `PROXY_DOMAIN` | URI | The base domain of the proxy server - will be used to handle unbound requests. | *None* - **required** | -| `PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK` | true or false | Set to true to enable `getssl`'s [skip HTTP token check](https://github.com/srvrco/getssl/wiki/Config-variables#skip_http_token_checkfalse). | false | -| `PROXY_HARDEN` | 0 or 1 | If 1, only modern SSL ciphers and protocols will be enabled (some older devices may not be able to access it). | 0 | -| `PROXY_LETS_ENCRYPT_EMAIL` | A valid email address | Used by Lets Encrypt for notification emails. | *None* - **required** | -| `PROXY_LETS_ENCRYPT_LIVE` | 0 or 1 | Only set to 1 (to request live certificates) when your config is correct - Lets Encrypt rate limit certificate requests. | 0 | -| `PROXY_MAINTENANCE_REFRESH_SECONDS` | A valid integer | The number of seconds to count down before the maintenance page auto-refreshes. | 6 | -| `PROXY_SSL_DHPARAM_BITS` | A valid integer | The size of your DHPARAM variables - adjust down only if you have limited processing resources. | 4096 | -| `PROXY_SSL_REDIRECT_TO_CANONICAL` | 0 or 1 | If 1, all requests will be redirected to the primary domain (defined in `conf.json`). | 0 | -| `PROXY_UPSTREAM_DNS_RESOLVER` | IP address | Upstream DNS resolver - set to Docker's by default. | 127.0.0.11 | +| Variable | Values | Description | Default | +| ----------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| `BF_PROXY_AUTO_ALIASES` | string of URIs | Add aliases to the auto-generated conf.json on first startup. | *None* | +| `BF_PROXY_AUTO_CUSTOM` | 0 or 1 | Mark the auto-generated SSL config to 'custom' so the Nginx configuration is not regenerated on startup. | 0 | +| `BF_PROXY_AUTO_PRIMARY` | URI | If set (along with PROXY_AUTO_UPSTREAM) SSL config will be generated on first startup. | *None* | +| `BF_PROXY_AUTO_UPSTREAM` | URI | If set (along with PROXY_AUTO_PRIMARY) SSL config will be generated on first startup. | *None* | +| `BF_PROXY_CLEAN_INSTALL` | 0 or 1 | If 1, all Nginx and SSL configuration and certificates will be deleted and regenerated. | 0 | +| `BF_PROXY_DOMAIN` | URI | The base domain of the proxy server - will be used to handle unbound requests. | *None* - **required** | +| `BF_PROXY_GETSSL_EMAIL` | A valid email address | Used by Lets Encrypt for notification emails. | *None* - **required** | +| `BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK` | true or false | Set to true to enable `getssl`'s [skip HTTP token check](https://github.com/srvrco/getssl/wiki/Config-variables#skip_http_token_checkfalse). | false | +| `BF_PROXY_GETSSL_USE_LIVE_SERVER` | 0 or 1 | Only set to 1 (to request live certificates) when your config is correct - Lets Encrypt rate limit certificate requests. | 0 | +| `BF_PROXY_HARDEN` | 0 or 1 | If 1, only modern SSL ciphers and protocols will be enabled (some older devices may not be able to access it). | 0 | +| `BF_PROXY_MAINTENANCE_REFRESH_SECONDS` | A valid integer | The number of seconds to count down before the maintenance page auto-refreshes. | 6 | +| `BF_PROXY_SSL_DHPARAM_BITS` | A valid integer | The size of your DHPARAM variables - adjust down only if you have limited processing resources. | 4096 | +| `BF_PROXY_SSL_REDIRECT_TO_CANONICAL` | 0 or 1 | If 1, all requests will be redirected to the primary domain (defined in `conf.json`). | 0 | +| `BF_PROXY_UPSTREAM_DNS_RESOLVER` | IP address | Upstream DNS resolver - set to Docker's by default. | 127.0.0.11 | ## Helper Functions From 73bfd38f1139f7709ec4470473aeed3b7cc5a7dc Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 11:20:39 +0000 Subject: [PATCH 33/76] Adding namespacing to bf write --- overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu | 2 +- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu index 0486f8f..7d46afd 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu @@ -12,7 +12,7 @@ export def generate_conf_json []: nothing -> nothing { let custom = bf env -s "PROXY_AUTO_CUSTOM" # generate file - bf write "Generating conf.json using auto environment variables." + bf write "Generating conf.json using auto environment variables." auto/generate_conf_json let e = { PRIMARY: $primary UPSTREAM: $upstream diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 4a27569..0bc8b5f 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -14,7 +14,7 @@ export def generate_nginx_ssl_conf []: nothing -> nothing { } # generate config file - bf write $"Using ($template) SSL configuration." + bf write $"Using ($template) SSL configuration." conf/generate_nginx_ssl_conf bf esh $"(bf env ETC_TEMPLATES)/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" # return nothing From 459e7ac6ada9eea1963713220f8fabd0bba31cf8 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 15:33:13 +0000 Subject: [PATCH 34/76] Adding generate dhparam and tests --- overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu | 10 ++++++ overlay/etc/nu/scripts/tests/mod.nu | 1 + overlay/etc/nu/scripts/tests/ssl.nu | 37 ++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu create mode 100644 overlay/etc/nu/scripts/tests/ssl.nu diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu new file mode 100644 index 0000000..949b34a --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu @@ -0,0 +1,10 @@ +use bf + +# Generate a DHPARAM file if it does not already exist +export def generate_dhparam []: nothing -> nothing { + let dhparam = bf env PROXY_SSL_DHPARAM + if ($dhparam | bf fs is_not_file) { + bf write debug $"Creating dhparam file: ($dhparam)." ssl/generate_dhparam + ^openssl dhparam (bf env PROXY_SSL_DHPARAM_BITS) | save --force $dhparam + } +} diff --git a/overlay/etc/nu/scripts/tests/mod.nu b/overlay/etc/nu/scripts/tests/mod.nu index 374cf9f..8c00637 100644 --- a/overlay/etc/nu/scripts/tests/mod.nu +++ b/overlay/etc/nu/scripts/tests/mod.nu @@ -1,3 +1,4 @@ export module auto.nu export module conf.nu export module init.nu +export module ssl.nu diff --git a/overlay/etc/nu/scripts/tests/ssl.nu b/overlay/etc/nu/scripts/tests/ssl.nu new file mode 100644 index 0000000..375b679 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/ssl.nu @@ -0,0 +1,37 @@ +use bf +use std assert +use ../bf/nginx/proxy ssl * + + +#====================================================================================================================== +# generate_dhparam +#====================================================================================================================== + +def generate_dhparam_e [ + file: string +] { + { + BF_PROXY_SSL_DHPARAM: $file + BF_PROXY_SSL_DHPARAM_BITS: 1024 + } +} + +export def generate_dhparam__does_nothing_if_file_exists [] { + let file = mktemp -t + let content = random chars + $content | save --force $file + let e = generate_dhparam_e $file + + let result = with-env $e { generate_dhparam } | open --raw $file + + assert equal $content $result +} + +export def generate_dhparam__generates_dhparam_if_file_does_not_exist [] { + let file = $"/tmp/(random chars)" + let e = generate_dhparam_e $file + + let result = with-env $e { generate_dhparam } | open $file + + assert not equal "" $result +} From cef8f0195afdac1724cffc875c71e42350e61d75 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 16:15:36 +0000 Subject: [PATCH 35/76] Moving shared constants to vars module --- overlay/etc/nu/scripts/tests/mod.nu | 2 ++ overlay/etc/nu/scripts/tests/vars.nu | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 overlay/etc/nu/scripts/tests/vars.nu diff --git a/overlay/etc/nu/scripts/tests/mod.nu b/overlay/etc/nu/scripts/tests/mod.nu index 8c00637..beff031 100644 --- a/overlay/etc/nu/scripts/tests/mod.nu +++ b/overlay/etc/nu/scripts/tests/mod.nu @@ -1,4 +1,6 @@ export module auto.nu export module conf.nu +export module getssl.nu export module init.nu export module ssl.nu +export module vars.nu diff --git a/overlay/etc/nu/scripts/tests/vars.nu b/overlay/etc/nu/scripts/tests/vars.nu new file mode 100644 index 0000000..f73eef1 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/vars.nu @@ -0,0 +1,2 @@ +export const ETC_TEMPLATES = "/etc/bf/templates" +export const NGINX_SSL_CONF = "/etc/nginx/http.d/ssl.conf" From ed17494629725938b209f8325aa3e01e80a32620 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 16:15:52 +0000 Subject: [PATCH 36/76] Adding getssl and tests --- .../etc/nu/scripts/bf/nginx/proxy/getssl.nu | 20 ++++ overlay/etc/nu/scripts/tests/getssl.nu | 108 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu create mode 100644 overlay/etc/nu/scripts/tests/getssl.nu diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu new file mode 100644 index 0000000..7777a19 --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu @@ -0,0 +1,20 @@ +use bf + +# Generate getssl configuration file if it does not already exist +export def generate_conf []: nothing -> nothing { + let getssl_cfg = bf env PROXY_GETSSL_GLOBAL_CFG + if ($getssl_cfg | bf fs is_not_file) { + # get environment variables + let e = { + USE_LIVE_SERVER: (bf env PROXY_GETSSL_USE_LIVE_SERVER) + ACCOUNT_EMAIL: (bf env PROXY_GETSSL_EMAIL) + ACCOUNT_KEY: (bf env PROXY_GETSSL_ACCOUNT_KEY) + RENEW_ALLOW: (bf env PROXY_GETSSL_RENEW_WINDOW_DAYS) + SKIP_HTTP_TOKEN_CHECK: (bf env check PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK | into string) + } + + # generate configuration + bf write debug "Creating getssl global configuration file" getssl/generate_conf + with-env $e { bf esh template $getssl_cfg } + } +} diff --git a/overlay/etc/nu/scripts/tests/getssl.nu b/overlay/etc/nu/scripts/tests/getssl.nu new file mode 100644 index 0000000..e2a1711 --- /dev/null +++ b/overlay/etc/nu/scripts/tests/getssl.nu @@ -0,0 +1,108 @@ +use std assert +use bf +use bf/nginx/proxy getssl * +use vars.nu * + + +#====================================================================================================================== +# generate_conf +#====================================================================================================================== + +def generate_conf_e [ + --use-live-server + --email: string + --account-key: string + --renew-window: int + --skip-check + file: string +] { + { + BF_ETC_TEMPLATES: $ETC_TEMPLATES + BF_PROXY_GETSSL_GLOBAL_CFG: $file + BF_PROXY_GETSSL_USE_LIVE_SERVER: (match ($use_live_server) { true => "1" false => "0" }) + BF_PROXY_GETSSL_EMAIL: ($email | default (random chars)) + BF_PROXY_GETSSL_ACCOUNT_KEY: ($account_key | default (random chars)) + BF_PROXY_GETSSL_RENEW_WINDOW_DAYS: ($renew_window | default (random int 14..28)) + BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK: ($skip_check | default (random bool)) + } +} + +def get_tmp_file []: nothing -> string { $"/(mktemp -d -t)/getssl-global.conf" } + +export def generate_conf__does_nothing_if_file_exists [] { + let file = get_tmp_file + let content = random chars + $content | save $file + let e = generate_conf_e $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert equal $content $result +} + +export def generate_conf__generates_conf_if_file_does_not_exist [] { + let file = get_tmp_file + let e = generate_conf_e $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert not equal "" $result +} + +export def generate_conf__use_live_server_true_outputs_live_server [] { + let file = get_tmp_file + let e = generate_conf_e --use-live-server=true $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)CA=\"https://acme-v02.api.letsencrypt.org\"(char newline)" +} + +export def generate_conf__use_live_server_false_outputs_staging_server [] { + let file = get_tmp_file + let e = generate_conf_e --use-live-server=false $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)CA=\"https://acme-staging-v02.api.letsencrypt.org\"(char newline)" +} + +export def generate_conf__outputs_email [] { + let file = get_tmp_file + let email = random chars + let e = generate_conf_e --email $email $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)ACCOUNT_EMAIL=\"($email)\"(char newline)" +} + +export def generate_conf__outputs_account_key [] { + let file = get_tmp_file + let key = random chars + let e = generate_conf_e --account-key $key $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)ACCOUNT_KEY=\"($key)\"(char newline)" +} + +export def generate_conf__outputs_renew_allow [] { + let file = get_tmp_file + let renew = random int 14..28 + let e = generate_conf_e --renew-window $renew $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)RENEW_ALLOW=\"($renew)\"(char newline)" +} + +export def generate_conf__outputs_skip_http_check [] { + let file = get_tmp_file + let skip_check = random bool + let e = generate_conf_e --skip-check=($skip_check) $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)SKIP_HTTP_TOKEN_CHECK=\"($skip_check | into string)\"(char newline)" +} From 7be542d936b506456d66f33bad530c537853cb3f Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 16:16:10 +0000 Subject: [PATCH 37/76] Standardising use statement sort order --- overlay/etc/nu/scripts/tests/auto.nu | 19 +++++++++---------- overlay/etc/nu/scripts/tests/conf.nu | 15 ++++++--------- overlay/etc/nu/scripts/tests/init.nu | 4 ++-- overlay/etc/nu/scripts/tests/ssl.nu | 4 ++-- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/overlay/etc/nu/scripts/tests/auto.nu b/overlay/etc/nu/scripts/tests/auto.nu index f64b446..15edb59 100644 --- a/overlay/etc/nu/scripts/tests/auto.nu +++ b/overlay/etc/nu/scripts/tests/auto.nu @@ -1,8 +1,7 @@ -use bf use std assert -use ../bf/nginx/proxy auto * - -const ETC_TEMPLATES = "/etc/bf/templates" +use bf +use bf/nginx/proxy auto * +use vars.nu * #====================================================================================================================== @@ -10,9 +9,9 @@ const ETC_TEMPLATES = "/etc/bf/templates" #====================================================================================================================== def is_enabled_e [ - --ssl_conf_exists - --auto_primary_is_empty - --auto_upstream_is_empty + --ssl-conf-exists + --auto-primary-is-empty + --auto-upstream-is-empty ] { let ssl_conf = mktemp -t if not $ssl_conf_exists { rm $ssl_conf } @@ -24,7 +23,7 @@ def is_enabled_e [ } export def is_enabled__returns_false_when_ssl_conf_exists [] { - let e = is_enabled_e --ssl_conf_exists + let e = is_enabled_e --ssl-conf-exists let result = with-env $e { is_enabled } @@ -32,7 +31,7 @@ export def is_enabled__returns_false_when_ssl_conf_exists [] { } export def is_enabled__returns_false_when_auto_primary_is_empty [] { - let e = is_enabled_e --auto_primary_is_empty + let e = is_enabled_e --auto-primary-is-empty let result = with-env $e { is_enabled } @@ -40,7 +39,7 @@ export def is_enabled__returns_false_when_auto_primary_is_empty [] { } export def is_enabled__returns_false_when_auto_upstream_is_empty [] { - let e = is_enabled_e --auto_upstream_is_empty + let e = is_enabled_e --auto-upstream-is-empty let result = with-env $e { is_enabled } diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 3a11be9..ec17975 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -1,8 +1,7 @@ -use bf use std assert -use ../bf/nginx/proxy conf * - -const ETC_TEMPLATES = "/etc/bf/templates" +use bf +use bf/nginx/proxy conf * +use vars.nu * #====================================================================================================================== @@ -36,8 +35,6 @@ export def get_domains__returns_list_of_domains [] { # generate_nginx_ssl_conf #====================================================================================================================== -const NGINX_SSL_OUTPUT = "/etc/nginx/http.d/ssl.conf" - def generate_nginx_ssl_conf_e [ --harden # Optional harden switch ] { @@ -51,8 +48,8 @@ export def generate_nginx_ssl_conf__outputs_intermediate_conf [] { let e = generate_nginx_ssl_conf_e let expected = "c8864a579b0ec2cb4070f27affb4e05f" - let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_OUTPUT | hash md5 - open $NGINX_SSL_OUTPUT | bf dump -e -t "ssl" + let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_CONF | hash md5 + open $NGINX_SSL_CONF | bf dump -e -t "ssl" assert equal $expected $result } @@ -61,7 +58,7 @@ export def generate_nginx_ssl_conf__outputs_modern_conf [] { let e = generate_nginx_ssl_conf_e --harden let expected = "73f99a3458030a8dae265a10355032e3" - let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_OUTPUT | hash md5 + let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_CONF | hash md5 assert equal $expected $result } diff --git a/overlay/etc/nu/scripts/tests/init.nu b/overlay/etc/nu/scripts/tests/init.nu index c369660..6f5ec86 100644 --- a/overlay/etc/nu/scripts/tests/init.nu +++ b/overlay/etc/nu/scripts/tests/init.nu @@ -1,6 +1,6 @@ -use bf use std assert -use ../bf/nginx/proxy init * +use bf +use bf/nginx/proxy init * #====================================================================================================================== diff --git a/overlay/etc/nu/scripts/tests/ssl.nu b/overlay/etc/nu/scripts/tests/ssl.nu index 375b679..79da073 100644 --- a/overlay/etc/nu/scripts/tests/ssl.nu +++ b/overlay/etc/nu/scripts/tests/ssl.nu @@ -1,6 +1,6 @@ -use bf use std assert -use ../bf/nginx/proxy ssl * +use bf +use bf/nginx/proxy ssl * #====================================================================================================================== From c04cbeb99c5ed202ad2f5e1d474df2bae0c025f8 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 16:17:29 +0000 Subject: [PATCH 38/76] Using shorter environment variables --- overlay/etc/bf/templates/getssl-global.conf.esh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/overlay/etc/bf/templates/getssl-global.conf.esh b/overlay/etc/bf/templates/getssl-global.conf.esh index c3ffc93..b8ba48a 100644 --- a/overlay/etc/bf/templates/getssl-global.conf.esh +++ b/overlay/etc/bf/templates/getssl-global.conf.esh @@ -3,7 +3,7 @@ # Uncomment and modify any variables you need # see https://github.com/srvrco/getssl/wiki/Config-variables for details # -<% if [ "${PROXY_LETS_ENCRYPT_LIVE}" = "1" ] ; then %> +<% if [ "${USE_LIVE_SERVER}" = "1" ] ; then %> # The staging server is best for testing #CA="https://acme-staging-v02.api.letsencrypt.org" # This server issues full certificates, however has rate limits @@ -19,9 +19,9 @@ CA="https://acme-staging-v02.api.letsencrypt.org" #AGREEMENT="" # Set an email address associated with your account - generally set at account level rather than domain. -ACCOUNT_EMAIL=<%= ${PROXY_LETS_ENCRYPT_EMAIL} %> +ACCOUNT_EMAIL="<%= ${ACCOUNT_EMAIL} %>" ACCOUNT_KEY_LENGTH=4096 -ACCOUNT_KEY="<%= ${PROXY_GETSSL_ACCOUNT_KEY} %>" +ACCOUNT_KEY="<%= ${ACCOUNT_KEY} %>" # Account key and private key types - can be rsa, prime256v1, secp384r1 or secp521r1 #ACCOUNT_KEY_TYPE="rsa" @@ -29,13 +29,13 @@ PRIVATE_KEY_ALG="rsa" #REUSE_PRIVATE_KEY="true" # The command needed to reload apache / nginx or whatever you use -#RELOAD_CMD="" +RELOAD_CMD="nginx-reload" # The time period within which you want to allow renewal of a certificate # this prevents hitting some of the rate limits. # Creating a file called FORCE_RENEWAL in the domain directory allows one-off overrides # of this setting -RENEW_ALLOW="30" +RENEW_ALLOW="<%= "${RENEW_ALLOW}" %>" # Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp, # smtps_deprecated, smtps, smtp_submission, xmpp, xmpps, ldaps or a port number which @@ -49,4 +49,7 @@ CHECK_REMOTE="true" #DNS_ADD_COMMAND= #DNS_DEL_COMMAND= -SKIP_HTTP_TOKEN_CHECK=<%= ${PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK} %> +# If set to "true" then the script will not check that the url +# "http://yourdomain.com/.well-known/acme-challenge/token" can be reached after +# uploading the token. +SKIP_HTTP_TOKEN_CHECK="<%= ${SKIP_HTTP_TOKEN_CHECK} %>" From f02a318b769cc3fcb6a1dcdfdf1ca785dc9b0eb6 Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 16:20:19 +0000 Subject: [PATCH 39/76] Using latest base image --- Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index dde1dac..cd72556 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.20-6.3.14 +FROM bfren/nginx:nginx1.26-alpine3.20-6.3.15 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" @@ -23,8 +23,10 @@ ENV \ BF_PROXY_GETSSL_EMAIL= \ # set to 1 to use live instead of staging server BF_PROXY_GETSSL_USE_LIVE_SERVER=0 \ - # set to true to skip local HTTP token check - BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK="false" \ + # the renew window number of days (certificates with more than this will not renew) + BF_PROXY_GETSSL_RENEW_WINDOW_DAYS=14 \ + # set to 1 to skip local HTTP token check + BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK=0 \ # set to the number of bits to use for generating private key BF_PROXY_SSL_KEY_BITS=4096 \ # set to the number of bits to use for generating DHPARAM From 3337843e2f00f122c55553c97edd570a5df6af6a Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 24 Nov 2024 16:28:40 +0000 Subject: [PATCH 40/76] Adding main init function --- overlay/etc/bf/init.d/22-ssl-init.nu | 4 +- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 43 +++++++++++++++---- overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu | 2 + 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/overlay/etc/bf/init.d/22-ssl-init.nu b/overlay/etc/bf/init.d/22-ssl-init.nu index a29d7ae..f79cad0 100644 --- a/overlay/etc/bf/init.d/22-ssl-init.nu +++ b/overlay/etc/bf/init.d/22-ssl-init.nu @@ -23,9 +23,9 @@ def main []: nothing -> nothing { if (bf env check "PROXY_AUTO_ALIASES") { bf env set "PROXY_SSL_REDIRECT_TO_CANONICAL" "1" } # initialise all domains (root plus auto) - proxy init all + proxy init --all } else { # initialise only the root domain - proxy init root + proxy init --root } } diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index ff54d9a..97c1e78 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -1,8 +1,37 @@ use bf +use conf.nu +use getssl.nu +use ssl.nu + +# Initialise SSL for the specified domain(s). +#doc +# Order of precedence: +# 1. `init --all` +# 2. `init --root` +# 3. `init --domain xxxxxx` +export def main [ + --all (-a) # If set, will initialise root and all configured domains + --domain (-d): string # Specify the domain to be initialised + --root (-d) # If set, will initialise root domain +]: nothing -> nothing { + # generate getssl configuration + getssl generate_conf + + # generate DHPARAM file + ssl generate_dhparam + + # initialise domain(s) + if $all { all_domains } + else if $root { root } + else if $domain { domain $domain } + + # return nothing + return +} # Check for clean install and delete export def setup_clean_install []: nothing -> nothing { - bf write debug " .. removing SSL config and certificates:" + bf write debug " .. removing SSL config and certificates:" init/setup_clean_install bf env PROXY_GETSSL_GLOBAL_CFG | remove bf env PROXY_SITES | $"($in)/*" | remove bf env PROXY_SSL_CERTS | $"($in)/*" | remove @@ -12,25 +41,23 @@ export def setup_clean_install []: nothing -> nothing { # Remove file(s) by converting input into a glob before calling `rm` def remove []: string -> nothing { let file = $in | into glob - bf write debug $" ($file)" + bf write debug $" ($file)" init/remove rm --force --recursive $file } # Initialise SSL for all configured domains -export def all []: nothing -> nothing { - +def all_domains []: nothing -> nothing { + let domains = conf get_domains } # Initialise SSL for the specified domain -export def domain [ +def domain [ domain: string # The domain to initialise ]: nothing -> nothing { } # Initialise SSL for the root domain -export def root [ - -]: nothing -> nothing { +def root []: nothing -> nothing { domain (bf env "PROXY_DOMAIN") } diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu index 374cf9f..50b60af 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu @@ -1,3 +1,5 @@ export module auto.nu export module conf.nu +export module getssl.nu export module init.nu +export module ssl.nu From b65625f95e7de58c7d86808106f2df84043a994f Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 1 Dec 2024 12:05:31 +0000 Subject: [PATCH 41/76] Adding tests for nginx config output --- overlay/etc/bf/init.d/21-ssl-conf.nu | 2 +- .../templates/nginx-acme-challenge.part.esh | 2 +- ...inx-proxy.conf.esh => nginx-root.conf.esh} | 4 +- overlay/etc/bf/templates/nginx-site.conf.esh | 16 +- .../etc/bf/templates/nginx-ssl-certs.part.esh | 8 +- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 65 +++- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 44 ++- overlay/etc/nu/scripts/tests/conf.nu | 313 +++++++++++++++++- overlay/etc/nu/scripts/tests/getssl.nu | 18 +- overlay/etc/nu/scripts/tests/init.nu | 64 ++++ overlay/etc/nu/scripts/tests/vars.nu | 15 + 11 files changed, 498 insertions(+), 53 deletions(-) rename overlay/etc/bf/templates/{nginx-proxy.conf.esh => nginx-root.conf.esh} (94%) diff --git a/overlay/etc/bf/init.d/21-ssl-conf.nu b/overlay/etc/bf/init.d/21-ssl-conf.nu index a2dc367..5af8afd 100644 --- a/overlay/etc/bf/init.d/21-ssl-conf.nu +++ b/overlay/etc/bf/init.d/21-ssl-conf.nu @@ -2,4 +2,4 @@ use bf/nginx/proxy conf bf env load # Generate SSL configuration file -def main []: nothing -> nothing { conf generate_nginx_ssl_conf } +def main []: nothing -> nothing { conf generate_nginx_server_conf } diff --git a/overlay/etc/bf/templates/nginx-acme-challenge.part.esh b/overlay/etc/bf/templates/nginx-acme-challenge.part.esh index ee85cbc..c3a7595 100644 --- a/overlay/etc/bf/templates/nginx-acme-challenge.part.esh +++ b/overlay/etc/bf/templates/nginx-acme-challenge.part.esh @@ -1,6 +1,6 @@ # allow acme challenge from anywhere (so SSL certificates can still be requested, # but all other requests can be blocked from outside the local network, for example) - location ^~ /<%= "${PROXY_ACME_CHALLENGE}" %> { + location ^~ /<%= "${ACME_CHALLENGE}" %> { allow all; root <%= "${NGINX_WWW}" %>; } \ No newline at end of file diff --git a/overlay/etc/bf/templates/nginx-proxy.conf.esh b/overlay/etc/bf/templates/nginx-root.conf.esh similarity index 94% rename from overlay/etc/bf/templates/nginx-proxy.conf.esh rename to overlay/etc/bf/templates/nginx-root.conf.esh index 34099e7..58840d9 100644 --- a/overlay/etc/bf/templates/nginx-proxy.conf.esh +++ b/overlay/etc/bf/templates/nginx-root.conf.esh @@ -19,7 +19,7 @@ server { <%+ ./nginx-acme-challenge.part.esh %> location / { - # redirect all other requests to HTTPS using PROXY_DOMAIN + # redirect all other requests to HTTPS using DOMAIN_NAME return 301 <%= "https://${DOMAIN_NAME}" %>$request_uri; } } @@ -34,7 +34,7 @@ server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; - # redirect to PROXY_DOMAIN to avoid certificate errors + # redirect to DOMAIN_NAME to avoid certificate errors if ($host != <%= "${DOMAIN_NAME}" %>) { return 301 <%= "https://${DOMAIN_NAME}" %>$request_uri; } diff --git a/overlay/etc/bf/templates/nginx-site.conf.esh b/overlay/etc/bf/templates/nginx-site.conf.esh index df0037b..036f097 100644 --- a/overlay/etc/bf/templates/nginx-site.conf.esh +++ b/overlay/etc/bf/templates/nginx-site.conf.esh @@ -1,4 +1,4 @@ -<% if [ "${DOMAIN_NGXCONF}" = "true" ] ; then -%> +<% if [ "${IS_CUSTOM}" = "true" ] ; then -%> #====================================================================================================================== # You can make changes to this file. # @@ -44,8 +44,8 @@ include <%= "${CUSTOM_CONF}/${DOMAIN_NAME}[.]upstrea #====================================================================================================================== server { - # serve site for these domain names only - server_name <%= "${SERVER_NAMES}" %>; + # serve HTTP site for these domain names + server_name <%= "${DOMAIN_NAMES}" %>; # listen on HTTP port for both IPv4 and IPv6 listen 80; @@ -54,7 +54,7 @@ server { <%+ ./nginx-acme-challenge.part.esh %> location / { -<% if [ "${PROXY_SSL_REDIRECT_TO_CANONICAL}" = "1" ] ; then -%> +<% if [ "${REDIRECT_TO_CANONICAL}" = "true" ] ; then -%> # redirect all other requests to HTTPS using primary domain name return 301 <%= "https://${DOMAIN_NAME}" %>$request_uri; <% else -%> @@ -70,15 +70,15 @@ server { #====================================================================================================================== server { - # serve site for these domain names only - server_name <%= "${SERVER_NAMES}" %>; + # serve HTTPS site for these domain names + server_name <%= "${DOMAIN_NAMES}" %>; # listen on SSL port for both IPv4 and IPv6, and enable HTTP/2 listen 443 ssl; listen [::]:443 ssl; http2 on; -<% if [ "${PROXY_SSL_REDIRECT_TO_CANONICAL}" = "1" ] ; then -%> +<% if [ "${REDIRECT_TO_CANONICAL}" = "true" ] ; then -%> # redirect to primary (canonical) domain name if ($host != <%= "${DOMAIN_NAME}" %>) { return 301 <%= "https://${DOMAIN_NAME}" %>$request_uri; @@ -89,7 +89,7 @@ server { location / { # set resolver to Docker's internal DNS resolver and use an upstream variable so Nginx will always start, # even if $upstream is not available - h/t https://stackoverflow.com/a/54719226/8199362 - resolver <%= "${PROXY_UPSTREAM_DNS_RESOLVER}" %> valid=30s; + resolver <%= "${DNS_RESOLVER}" %> valid=30s; set $upstream <%= "${UPSTREAM}" %>; # proxy to the upstream server, enabling best-practice proxy and security headers diff --git a/overlay/etc/bf/templates/nginx-ssl-certs.part.esh b/overlay/etc/bf/templates/nginx-ssl-certs.part.esh index 5e1f26d..4fe2b53 100644 --- a/overlay/etc/bf/templates/nginx-ssl-certs.part.esh +++ b/overlay/etc/bf/templates/nginx-ssl-certs.part.esh @@ -1,5 +1,5 @@ # paths to SSL certificates and configuration - ssl_certificate <%= "${PROXY_SSL_CERTS}/${DOMAIN_NAME}/fullchain.crt" %>; - ssl_certificate_key <%= "${PROXY_SSL_CERTS}/${DOMAIN_NAME}.key" %>; - ssl_trusted_certificate <%= "${PROXY_SSL_CERTS}/${DOMAIN_NAME}/chain.crt" %>; - ssl_dhparam <%= "${PROXY_SSL_DHPARAM}" %>; \ No newline at end of file + ssl_trusted_certificate <%= "${CERTS}/${DOMAIN_NAME}/chain.crt" %>; + ssl_certificate <%= "${CERTS}/${DOMAIN_NAME}/fullchain.crt" %>; + ssl_certificate_key <%= "${CERTS}/${DOMAIN_NAME}.key" %>; + ssl_dhparam <%= "${DHPARAM}" %>; \ No newline at end of file diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 0bc8b5f..36cf46d 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -6,7 +6,7 @@ export def get_domains []: nothing -> list nothing { +export def generate_nginx_server_conf []: nothing -> nothing { # get the template name let template = match (bf env check PROXY_HARDEN) { true => "modern" @@ -14,9 +14,70 @@ export def generate_nginx_ssl_conf []: nothing -> nothing { } # generate config file - bf write $"Using ($template) SSL configuration." conf/generate_nginx_ssl_conf + bf write $"Using ($template) SSL configuration." conf/generate_nginx_server_conf bf esh $"(bf env ETC_TEMPLATES)/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" # return nothing return } + +# Generate Nginx site config +export def generate_nginx_site_conf [ + domain: record # the domain record to generate config for +]: nothing -> string { + # get type-hinted variables + let primary: string = $domain.primary + let upstream: string = $domain.upstream + let aliases: list = $domain.aliases + let custom: bool = $domain.custom + let is_root = $primary == (bf env "PROXY_DOMAIN") + + # generate paths + let site = $"(bf env PROXY_SITES)/($primary)" + let conf = $"($site).conf" + let dir = $"($site).d" + let template = $"(bf env "ETC_TEMPLATES")/nginx-(match ($is_root) { true => "root" false => "site" }).conf.esh" + + # output domain to log + bf write $"Generating Nginx configuration for ($primary)." conf/generate_nginx_site_conf + + # ensure custom site config directory exists + if ($dir | bf fs is_not_dir) { mkdir $dir } + + # check for existing configuration file + if ($conf | path exists) { + # if custom config is enabled, don't touch the file + if $custom { + bf write debug " .. keeping custom configuration" conf/generate_nginx_site_conf + return $conf + } + + # remove file so it can be regenerated + bf write debug " .. removing file so it can be regenerated." conf/generate_nginx_site_conf + rm -f $conf + } else { + bf write debug " .. site is not yet configured." conf/generate_nginx_site_conf + } + + # set environment values + let e = { + ACME_CHALLENGE: (bf env PROXY_ACME_CHALLENGE) + CERTS: (bf env PROXY_SSL_CERTS) + CUSTOM_CONF: $dir + DHPARAM: (bf env PROXY_SSL_DHPARAM) + DNS_RESOLVER: (bf env PROXY_UPSTREAM_DNS_RESOLVER) + DOMAIN_NAME: $primary + DOMAIN_NAMES: ($primary | append $aliases | str join " ") + IS_CUSTOM: ($custom | into string) + NGINX_PUBLIC: (bf env NGINX_PUBLIC) + NGINX_WWW: (bf env NGINX_WWW) + REDIRECT_TO_CANONICAL: (bf env check PROXY_SSL_REDIRECT_TO_CANONICAL | into string) + UPSTREAM: $upstream + } + + # generate config file + with-env $e { bf esh $template $conf } + + # return path to config file + return $conf +} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index 97c1e78..8a639fe 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -20,10 +20,28 @@ export def main [ # generate DHPARAM file ssl generate_dhparam + # closure to run init procedure + let init_domain = {|x| + # generate getssl config + getssl generate_conf + + # generate dhparam + ssl generate_dhparam + + # generate Nginx config + conf generate_nginx_site_conf $x + } + # initialise domain(s) - if $all { all_domains } - else if $root { root } - else if $domain { domain $domain } + if $all { + get_all | each $init_domain + } + else if $root { + $init_domain (get_root) + } + else if $domain { + $init_domain (get_single $domain) + } # return nothing return @@ -45,19 +63,13 @@ def remove []: string -> nothing { rm --force --recursive $file } -# Initialise SSL for all configured domains -def all_domains []: nothing -> nothing { - let domains = conf get_domains -} +# Retrieve all configured domain record +export def get_all []: nothing -> list { conf get_domains } -# Initialise SSL for the specified domain -def domain [ +# Retrieve a single domain record +export def get_single [ domain: string # The domain to initialise -]: nothing -> nothing { - -} +]: nothing -> record { conf get_domains | where primary == $domain | into record } -# Initialise SSL for the root domain -def root []: nothing -> nothing { - domain (bf env "PROXY_DOMAIN") -} +# Retrieve the root domain record +export def get_root []: nothing -> record { get_single (bf env "PROXY_DOMAIN") } diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index ec17975..7cfff04 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -9,16 +9,7 @@ use vars.nu * #====================================================================================================================== export def get_domains__returns_list_of_domains [] { - let conf = { - "domains": [ - { - "primary": (random chars) - "upstream": (random chars) - "aliases": [(random chars) (random chars)] - "custom": (random bool) - } - ] - } + let conf = { "domains": [ (generate_domain) ] } let file = mktemp -t $conf | to json | save -f $file let e = { @@ -32,7 +23,7 @@ export def get_domains__returns_list_of_domains [] { #====================================================================================================================== -# generate_nginx_ssl_conf +# generate_nginx_server_conf #====================================================================================================================== def generate_nginx_ssl_conf_e [ @@ -48,8 +39,7 @@ export def generate_nginx_ssl_conf__outputs_intermediate_conf [] { let e = generate_nginx_ssl_conf_e let expected = "c8864a579b0ec2cb4070f27affb4e05f" - let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_CONF | hash md5 - open $NGINX_SSL_CONF | bf dump -e -t "ssl" + let result = with-env $e { generate_nginx_server_conf } | open --raw $NGINX_SSL_CONF | hash md5 assert equal $expected $result } @@ -58,7 +48,302 @@ export def generate_nginx_ssl_conf__outputs_modern_conf [] { let e = generate_nginx_ssl_conf_e --harden let expected = "73f99a3458030a8dae265a10355032e3" - let result = with-env $e { generate_nginx_ssl_conf } | open --raw $NGINX_SSL_CONF | hash md5 + let result = with-env $e { generate_nginx_server_conf } | open --raw $NGINX_SSL_CONF | hash md5 assert equal $expected $result } + + +#====================================================================================================================== +# generate_nginx_site_conf +#====================================================================================================================== + +def generate_nginx_site_conf_e [ + --acme-challenge: string + --certs: string + --dhparam: string + --nginx-public: string + --nginx-www: string + --redirect-to-canonical + --resolver: string + --root-domain: string + sites_dir +] { + { + BF_ETC_TEMPLATES: $ETC_TEMPLATES + BF_NGINX_PUBLIC: ($nginx_public | default (random chars)) + BF_NGINX_WWW: ($nginx_www | default (random chars)) + BF_PROXY_ACME_CHALLENGE: ($acme_challenge | default (random chars)) + BF_PROXY_DOMAIN: ($root_domain | default (random chars)) + BF_PROXY_SSL_CERTS: ($certs | default (random chars)) + BF_PROXY_SSL_DHPARAM: ($dhparam | default (random chars)) + BF_PROXY_SSL_REDIRECT_TO_CANONICAL: (match $redirect_to_canonical { true => "1" false => "0" }) + BF_PROXY_SITES: $sites_dir + BF_PROXY_UPSTREAM_DNS_RESOLVER: ($resolver | default (random chars)) + } +} + +export def generate_nginx_site_conf__creates_site_directory_when_does_not_exist [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = $"/tmp/(random chars)" + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | echo $sites_dir | path exists + + assert equal true $result +} + +export def generate_nginx_site_conf__keeps_config_when_custom_is_true [] { + let primary = random chars + let domain = generate_domain --primary $primary true + let sites_dir = mktemp -d -t + let content = random chars + $content | save --force $"($sites_dir)/($primary).conf" + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert equal $content $result +} + +export def generate_nginx_site_conf__regenerates_config_when_custom_is_false [] { + let primary = random chars + let domain = generate_domain --primary $primary false + let sites_dir = mktemp -d -t + let content = random chars + $content | save --force $"($sites_dir)/($primary).conf" + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert not equal $content $result +} + +export def generate_nginx_site_conf__outputs_acme_challenge [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let acme_challenge = random chars + let e = generate_nginx_site_conf_e --acme-challenge $acme_challenge $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"location ^~ /($acme_challenge) {" +} + +export def generate_nginx_site_conf__outputs_acme_challenge_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let acme_challenge = random chars + let e = generate_nginx_site_conf_e --acme-challenge $acme_challenge --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"location ^~ /($acme_challenge) {" +} + +export def generate_nginx_site_conf__outputs_ssl_certs [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let certs = random chars + let e = generate_nginx_site_conf_e --certs $certs $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_trusted_certificate ($certs)/($primary)/chain.crt;" + assert str contains $result $"ssl_certificate ($certs)/($primary)/fullchain.crt;" + assert str contains $result $"ssl_certificate_key ($certs)/($primary).key;" +} + +export def generate_nginx_site_conf__outputs_ssl_certs_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let certs = random chars + let e = generate_nginx_site_conf_e --certs $certs --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_trusted_certificate ($certs)/($primary)/chain.crt;" + assert str contains $result $"ssl_certificate ($certs)/($primary)/fullchain.crt;" + assert str contains $result $"ssl_certificate_key ($certs)/($primary).key;" +} + +export def generate_nginx_site_conf__includes_custom_conf [] { + let primary = random chars + let domain = generate_domain --primary $primary true + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"include ($sites_dir)/($primary).d/*.conf;" +} + +export def generate_nginx_site_conf__includes_custom_conf_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary true + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"include ($sites_dir)/($primary).d/*.conf;" +} + +export def generate_nginx_site_conf__outputs_dhparam [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let dhparam = random chars + let e = generate_nginx_site_conf_e --dhparam $dhparam $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_dhparam ($dhparam);" +} + +export def generate_nginx_site_conf__outputs_dhparam_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let dhparam = random chars + let e = generate_nginx_site_conf_e --dhparam $dhparam --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_dhparam ($dhparam);" +} + +export def generate_nginx_site_conf__outputs_dns_resolver [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let resolver = random chars + let e = generate_nginx_site_conf_e --resolver $resolver $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"resolver ($resolver) valid=30s;" +} + +export def generate_nginx_site_conf__outputs_server_names [] { + let primary = random chars + let aliases = [(random chars) (random chars) (random chars)] + let server_names = $primary | append $aliases | str join " " + let domain = generate_domain --primary $primary --aliases $aliases + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"# serve HTTP site for these domain names + server_name ($server_names);" + assert str contains $result $"# serve HTTPS site for these domain names + server_name ($server_names);" +} + +export def generate_nginx_site_conf__allows_changes_when_custom_is_true [] { + let domain = generate_domain true + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result "# You can make changes to this file." +} + +export def generate_nginx_site_conf__disallows_changes_when_custom_is_false [] { + let domain = generate_domain false + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." +} + +export def generate_nginx_site_conf__outputs_nginx_public_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let nginx_public = random chars + let e = generate_nginx_site_conf_e --nginx-public $nginx_public --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"root ($nginx_public);" +} + +export def generate_nginx_site_conf__outputs_nginx_www [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let nginx_www = random chars + let e = generate_nginx_site_conf_e --nginx-www $nginx_www $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"root ($nginx_www);" +} + +export def generate_nginx_site_conf__outputs_nginx_www_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let nginx_www = random chars + let e = generate_nginx_site_conf_e --nginx-www $nginx_www --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"root ($nginx_www);" +} + +export def generate_nginx_site_conf__redirects_to_canonical [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e --redirect-to-canonical $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"return 301 https://($primary)$request_uri;" + assert str contains $result $"if \($host != ($primary)\) { + return 301 https://($primary)$request_uri; + }" +} + +export def generate_nginx_site_conf__redirects_to_canonical_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e --root-domain $primary $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"return 301 https://($primary)$request_uri;" + assert str contains $result $"if \($host != ($primary)\) { + return 301 https://($primary)$request_uri; + }" +} + +export def generate_nginx_site_conf__redirects_to_current_host [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result "return 301 https://$host$request_uri;" +} + +export def generate_nginx_site_conf__outputs_upstream [] { + let upstream = random chars + let domain = generate_domain --upstream $upstream + let sites_dir = mktemp -d -t + let nginx_www = random chars + let e = generate_nginx_site_conf_e --nginx-www $nginx_www $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"set $upstream ($upstream);" +} diff --git a/overlay/etc/nu/scripts/tests/getssl.nu b/overlay/etc/nu/scripts/tests/getssl.nu index e2a1711..cfdad1a 100644 --- a/overlay/etc/nu/scripts/tests/getssl.nu +++ b/overlay/etc/nu/scripts/tests/getssl.nu @@ -23,7 +23,7 @@ def generate_conf_e [ BF_PROXY_GETSSL_EMAIL: ($email | default (random chars)) BF_PROXY_GETSSL_ACCOUNT_KEY: ($account_key | default (random chars)) BF_PROXY_GETSSL_RENEW_WINDOW_DAYS: ($renew_window | default (random int 14..28)) - BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK: ($skip_check | default (random bool)) + BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK: (match $skip_check { true => "1" false => "0" }) } } @@ -97,12 +97,20 @@ export def generate_conf__outputs_renew_allow [] { assert str contains $result $"(char newline)RENEW_ALLOW=\"($renew)\"(char newline)" } -export def generate_conf__outputs_skip_http_check [] { +export def generate_conf__outputs_skip_http_check_false [] { let file = get_tmp_file - let skip_check = random bool - let e = generate_conf_e --skip-check=($skip_check) $file + let e = generate_conf_e --skip-check=false $file let result = with-env $e { generate_conf } | open --raw $file - assert str contains $result $"(char newline)SKIP_HTTP_TOKEN_CHECK=\"($skip_check | into string)\"(char newline)" + assert str contains $result $"(char newline)SKIP_HTTP_TOKEN_CHECK=\"false\"(char newline)" +} + +export def generate_conf__outputs_skip_http_check_true [] { + let file = get_tmp_file + let e = generate_conf_e --skip-check=true $file + + let result = with-env $e { generate_conf } | open --raw $file + + assert str contains $result $"(char newline)SKIP_HTTP_TOKEN_CHECK=\"true\"(char newline)" } diff --git a/overlay/etc/nu/scripts/tests/init.nu b/overlay/etc/nu/scripts/tests/init.nu index 6f5ec86..887b8ed 100644 --- a/overlay/etc/nu/scripts/tests/init.nu +++ b/overlay/etc/nu/scripts/tests/init.nu @@ -1,6 +1,7 @@ use std assert use bf use bf/nginx/proxy init * +use vars.nu * #====================================================================================================================== @@ -37,3 +38,66 @@ export def setup_clean_install__removes_files [] { assert equal 0 $result.SSL_CERTS_FILES assert equal false $result.SSL_DHPARAM } + + +#====================================================================================================================== +# get_all +#====================================================================================================================== + +export def get_all__returns_all_domains [] { + let conf = { + "domains": [ (generate_domain), (generate_domain), (generate_domain) ] + } + let file = mktemp -t + $conf | to json | save -f $file + let e = { + BF_PROXY_SSL_CONF: $file + } + + let result = with-env $e { get_all } + + assert equal $conf.domains $result +} + + +#====================================================================================================================== +# get_root +#====================================================================================================================== + +export def get_root__returns_root_domain [] { + let conf = { + "domains": [ (generate_domain), (generate_domain), (generate_domain) ] + } + let root = $conf.domains.1 + let file = mktemp -t + $conf | to json | save -f $file + let e = { + BF_PROXY_DOMAIN: $root.primary + BF_PROXY_SSL_CONF: $file + } + + let result = with-env $e { get_root } + + assert equal $root $result +} + + +#====================================================================================================================== +# get_single +#====================================================================================================================== + +export def get_single__returns_single_domain [] { + let conf = { + "domains": [ (generate_domain), (generate_domain), (generate_domain) ] + } + let single = $conf.domains.1 + let file = mktemp -t + $conf | to json | save -f $file + let e = { + BF_PROXY_SSL_CONF: $file + } + + let result = with-env $e { get_single $single.primary } + + assert equal $single $result +} diff --git a/overlay/etc/nu/scripts/tests/vars.nu b/overlay/etc/nu/scripts/tests/vars.nu index f73eef1..dbfb9b3 100644 --- a/overlay/etc/nu/scripts/tests/vars.nu +++ b/overlay/etc/nu/scripts/tests/vars.nu @@ -1,2 +1,17 @@ export const ETC_TEMPLATES = "/etc/bf/templates" export const NGINX_SSL_CONF = "/etc/nginx/http.d/ssl.conf" + +# Generate a random domain record +export def generate_domain [ + --aliases: list # set aliases instead of random list + --primary: string # set primary instead of random characters + --upstream: string # set upstream instead of random characters + custom?: bool # set custom instead of random boolean +]: nothing -> record { + { + "primary": ($primary | default (random chars)) + "upstream": ($upstream | default (random chars)) + "aliases": ($aliases | default [(random chars) (random chars)] ) + "custom": ($custom | default (random bool)) + } +} From b0ca81b3475ca7f2a5aa41f34f6df4d2182c4cda Mon Sep 17 00:00:00 2001 From: bfren Date: Sun, 1 Dec 2024 13:51:18 +0000 Subject: [PATCH 42/76] Adding getssl replace and tests --- .../etc/nu/scripts/bf/nginx/proxy/getssl.nu | 48 +++++++- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 14 ++- overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu | 7 ++ overlay/etc/nu/scripts/tests/getssl.nu | 111 ++++++++++++++++-- overlay/tmp/install | 1 + 5 files changed, 164 insertions(+), 17 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu index 7777a19..70baca2 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu @@ -1,7 +1,7 @@ use bf -# Generate getssl configuration file if it does not already exist -export def generate_conf []: nothing -> nothing { +# Generate getssl global configuration file if it does not already exist +export def generate_global_conf []: nothing -> nothing { let getssl_cfg = bf env PROXY_GETSSL_GLOBAL_CFG if ($getssl_cfg | bf fs is_not_file) { # get environment variables @@ -14,7 +14,49 @@ export def generate_conf []: nothing -> nothing { } # generate configuration - bf write debug "Creating getssl global configuration file" getssl/generate_conf + bf write debug "Creating getssl global configuration file" getssl/generate_global_conf with-env $e { bf esh template $getssl_cfg } } } + +# Generate getssl site configuration file +export def generate_site_conf [ + domain: record # the domain record to generate temporary SSL for +]: nothing -> string { + # check for existing getssl config + let certs = bf env "PROXY_SSL_CERTS" + let file = $"($certs)/($domain.primary)/(bf env PROXY_GETSSL_CFG)" + if ($file | path exists) { + bf write debug " .. getssl configuration file already exists." + return $file + } + + # build arguments + let args = [ + (bf env --safe "PROXY_GETSSL_FLAGS") + "-w" # set working directory + (bf env "PROXY_SSL_CERTS") + "-c" # create default configuration files + $domain.primary + ] | compact --empty | bf dump -t "args" + + # execute getssl + { ^getssl ...$args } | bf handle + + # return cfg file path + return $file +} + +# Replace a value in a given config file +export def replace [ + key: string # config key to replace + value: string # config value to set + file: string # file path to load / save +] { + # do nothing for empty key + if ($key | is-empty) { return } + + # replace value + let find = $"^#?($key).*$" | bf dump -t "regex" + open --raw $file | str replace --all --regex $find $"($key)=($value)" | save --force $file +} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index 8a639fe..d5e696e 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -15,21 +15,27 @@ export def main [ --root (-d) # If set, will initialise root domain ]: nothing -> nothing { # generate getssl configuration - getssl generate_conf + getssl generate_global_conf # generate DHPARAM file ssl generate_dhparam # closure to run init procedure - let init_domain = {|x| - # generate getssl config - getssl generate_conf + let init_domain = {|x: record| + # generate global getssl config + getssl generate_global_conf # generate dhparam ssl generate_dhparam # generate Nginx config conf generate_nginx_site_conf $x + + # generate site getssl conf + getssl generate_site_conf $x + + # generate temporary SSL + ssl generate_temp_certs $x } # initialise domain(s) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu index 949b34a..7379aa8 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu @@ -8,3 +8,10 @@ export def generate_dhparam []: nothing -> nothing { ^openssl dhparam (bf env PROXY_SSL_DHPARAM_BITS) | save --force $dhparam } } + +# Generate temporary SSL certificates for a domain +export def generate_temp_certs [ + domain: record # the domain record to generate temporary SSL for +]: nothing -> nothing { + +} diff --git a/overlay/etc/nu/scripts/tests/getssl.nu b/overlay/etc/nu/scripts/tests/getssl.nu index cfdad1a..a620488 100644 --- a/overlay/etc/nu/scripts/tests/getssl.nu +++ b/overlay/etc/nu/scripts/tests/getssl.nu @@ -5,7 +5,7 @@ use vars.nu * #====================================================================================================================== -# generate_conf +# generate_global_conf #====================================================================================================================== def generate_conf_e [ @@ -35,7 +35,7 @@ export def generate_conf__does_nothing_if_file_exists [] { $content | save $file let e = generate_conf_e $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert equal $content $result } @@ -44,7 +44,7 @@ export def generate_conf__generates_conf_if_file_does_not_exist [] { let file = get_tmp_file let e = generate_conf_e $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert not equal "" $result } @@ -53,7 +53,7 @@ export def generate_conf__use_live_server_true_outputs_live_server [] { let file = get_tmp_file let e = generate_conf_e --use-live-server=true $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)CA=\"https://acme-v02.api.letsencrypt.org\"(char newline)" } @@ -62,7 +62,7 @@ export def generate_conf__use_live_server_false_outputs_staging_server [] { let file = get_tmp_file let e = generate_conf_e --use-live-server=false $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)CA=\"https://acme-staging-v02.api.letsencrypt.org\"(char newline)" } @@ -72,7 +72,7 @@ export def generate_conf__outputs_email [] { let email = random chars let e = generate_conf_e --email $email $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)ACCOUNT_EMAIL=\"($email)\"(char newline)" } @@ -82,7 +82,7 @@ export def generate_conf__outputs_account_key [] { let key = random chars let e = generate_conf_e --account-key $key $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)ACCOUNT_KEY=\"($key)\"(char newline)" } @@ -92,7 +92,7 @@ export def generate_conf__outputs_renew_allow [] { let renew = random int 14..28 let e = generate_conf_e --renew-window $renew $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)RENEW_ALLOW=\"($renew)\"(char newline)" } @@ -101,7 +101,7 @@ export def generate_conf__outputs_skip_http_check_false [] { let file = get_tmp_file let e = generate_conf_e --skip-check=false $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)SKIP_HTTP_TOKEN_CHECK=\"false\"(char newline)" } @@ -110,7 +110,98 @@ export def generate_conf__outputs_skip_http_check_true [] { let file = get_tmp_file let e = generate_conf_e --skip-check=true $file - let result = with-env $e { generate_conf } | open --raw $file + let result = with-env $e { generate_global_conf } | open --raw $file assert str contains $result $"(char newline)SKIP_HTTP_TOKEN_CHECK=\"true\"(char newline)" } + + +#====================================================================================================================== +# replace +#====================================================================================================================== + +export def replace__does_nothing_if_key_is_empty [] { + let file = mktemp -t + let content = random chars + $content | save --force $file + + let result = replace "" (random chars) $file | open --raw $file + + assert equal $content $result +} + +export def replace__replaces_line_with_empty_value [] { + let key = random chars + let file = mktemp -t + echo $"#($key)=(random chars)" | save --force $file + let expected = $"($key)=" + + let result = replace $key "" $file | open --raw $file + + assert equal $expected $result +} + +export def replace__replaces_line_with_hash [] { + let key = random chars + let value = random chars + let file = mktemp -t + echo $"#($key)=(random chars)" | save --force $file + let expected = $"($key)=($value)" + + let result = replace $key $value $file | open --raw $file + + assert equal $expected $result +} + +export def replace__replaces_line_without_hash [] { + let key = random chars + let value = random chars + let file = mktemp -t + echo $"($key)=(random chars)" | save --force $file + let expected = $"($key)=($value)" + + let result = replace $key $value $file | open --raw $file + + assert equal $expected $result +} + + +#====================================================================================================================== +# generate_site_conf +#====================================================================================================================== + +export def generate_site_conf__does_nothing_when_config_exists [] { + let primary = random chars + let domain = generate_domain --primary $primary + let certs = mktemp -d -t + let cfg = random chars + let e = { + BF_PROXY_SSL_CERTS: $certs + BF_PROXY_GETSSL_CFG: $cfg + } + let content = random chars + let cfg = $"($certs)/($primary)/($cfg)" + $cfg | path dirname | mkdir $in + $content | save --force $cfg + + let result = with-env $e { generate_site_conf $domain } | open --raw + + assert equal $content $result +} + +export def generate_site_conf__creates_default_config [] { + let primary = "do not use random value or hash will break" + let domain = generate_domain --primary $primary + let certs = mktemp -d -t + let cfg = "getssl.cfg" + let e = { + BF_PROXY_SSL_CERTS: $certs + BF_PROXY_GETSSL_CFG: $cfg + } + let cfg = $"($certs)/($primary)/($cfg)" + let expected = "7146e789a83077202ab129d461959016" + + let result = with-env $e { generate_site_conf $domain } | open --raw | hash md5 + + assert equal $expected $result +} diff --git a/overlay/tmp/install b/overlay/tmp/install index 97d7dfd..7421965 100644 --- a/overlay/tmp/install +++ b/overlay/tmp/install @@ -9,6 +9,7 @@ def main [] { let nginx_version = bf fs read NGINX_BUILD bf write $"Installing dependencies for getssl." bf pkg install [ + "bash" "curl" $"nginx-mod-http-set-misc=($nginx_version)" "openssl" From fece084bc4a2a3a3482a7fff2f602a60cc0549a8 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 09:08:51 +0000 Subject: [PATCH 43/76] Quoting bf env --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 16 ++++++++-------- overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 36cf46d..734b364 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -15,7 +15,7 @@ export def generate_nginx_server_conf []: nothing -> nothing { # generate config file bf write $"Using ($template) SSL configuration." conf/generate_nginx_server_conf - bf esh $"(bf env ETC_TEMPLATES)/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" + bf esh $"(bf env "ETC_TEMPLATES")/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" # return nothing return @@ -61,17 +61,17 @@ export def generate_nginx_site_conf [ # set environment values let e = { - ACME_CHALLENGE: (bf env PROXY_ACME_CHALLENGE) - CERTS: (bf env PROXY_SSL_CERTS) + ACME_CHALLENGE: (bf env "PROXY_ACME_CHALLENGE") + CERTS: (bf env "PROXY_SSL_CERTS") CUSTOM_CONF: $dir - DHPARAM: (bf env PROXY_SSL_DHPARAM) - DNS_RESOLVER: (bf env PROXY_UPSTREAM_DNS_RESOLVER) + DHPARAM: (bf env "PROXY_SSL_DHPARAM") + DNS_RESOLVER: (bf env "PROXY_UPSTREAM_DNS_RESOLVER") DOMAIN_NAME: $primary DOMAIN_NAMES: ($primary | append $aliases | str join " ") IS_CUSTOM: ($custom | into string) - NGINX_PUBLIC: (bf env NGINX_PUBLIC) - NGINX_WWW: (bf env NGINX_WWW) - REDIRECT_TO_CANONICAL: (bf env check PROXY_SSL_REDIRECT_TO_CANONICAL | into string) + NGINX_PUBLIC: (bf env "NGINX_PUBLIC") + NGINX_WWW: (bf env "NGINX_WWW") + REDIRECT_TO_CANONICAL: (bf env check "PROXY_SSL_REDIRECT_TO_CANONICAL" | into string) UPSTREAM: $upstream } diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu index 7379aa8..bede3a4 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu @@ -2,10 +2,10 @@ use bf # Generate a DHPARAM file if it does not already exist export def generate_dhparam []: nothing -> nothing { - let dhparam = bf env PROXY_SSL_DHPARAM + let dhparam = bf env "PROXY_SSL_DHPARAM" if ($dhparam | bf fs is_not_file) { bf write debug $"Creating dhparam file: ($dhparam)." ssl/generate_dhparam - ^openssl dhparam (bf env PROXY_SSL_DHPARAM_BITS) | save --force $dhparam + ^openssl dhparam (bf env "PROXY_SSL_DHPARAM_BITS") | save --force $dhparam } } From 167b2fbd29900a1941033c6c66b6bfeb2a4a32e7 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 09:09:11 +0000 Subject: [PATCH 44/76] Adding option to quote output for getssl config --- Dockerfile | 2 +- .../etc/nu/scripts/bf/nginx/proxy/getssl.nu | 52 +++++++++++++++---- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 11 ++-- overlay/etc/nu/scripts/tests/getssl.nu | 18 +++++-- 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index cd72556..8ceda2f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.20-6.3.15 +FROM bfren/nginx:nginx1.26-alpine3.20-6.3.16 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu index 70baca2..34b709e 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu @@ -2,15 +2,15 @@ use bf # Generate getssl global configuration file if it does not already exist export def generate_global_conf []: nothing -> nothing { - let getssl_cfg = bf env PROXY_GETSSL_GLOBAL_CFG + let getssl_cfg = bf env "PROXY_GETSSL_GLOBAL_CFG" if ($getssl_cfg | bf fs is_not_file) { # get environment variables let e = { - USE_LIVE_SERVER: (bf env PROXY_GETSSL_USE_LIVE_SERVER) - ACCOUNT_EMAIL: (bf env PROXY_GETSSL_EMAIL) - ACCOUNT_KEY: (bf env PROXY_GETSSL_ACCOUNT_KEY) - RENEW_ALLOW: (bf env PROXY_GETSSL_RENEW_WINDOW_DAYS) - SKIP_HTTP_TOKEN_CHECK: (bf env check PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK | into string) + USE_LIVE_SERVER: (bf env "PROXY_GETSSL_USE_LIVE_SERVER") + ACCOUNT_EMAIL: (bf env "PROXY_GETSSL_EMAIL") + ACCOUNT_KEY: (bf env "PROXY_GETSSL_ACCOUNT_KEY") + RENEW_ALLOW: (bf env "PROXY_GETSSL_RENEW_WINDOW_DAYS") + SKIP_HTTP_TOKEN_CHECK: (bf env check "PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK" | into string) } # generate configuration @@ -21,11 +21,11 @@ export def generate_global_conf []: nothing -> nothing { # Generate getssl site configuration file export def generate_site_conf [ - domain: record # the domain record to generate temporary SSL for + domain: string # the domain to generate getssl config for ]: nothing -> string { # check for existing getssl config let certs = bf env "PROXY_SSL_CERTS" - let file = $"($certs)/($domain.primary)/(bf env PROXY_GETSSL_CFG)" + let file = $"($certs)/($domain)/(bf env "PROXY_GETSSL_CFG")" if ($file | path exists) { bf write debug " .. getssl configuration file already exists." return $file @@ -37,7 +37,7 @@ export def generate_site_conf [ "-w" # set working directory (bf env "PROXY_SSL_CERTS") "-c" # create default configuration files - $domain.primary + $domain ] | compact --empty | bf dump -t "args" # execute getssl @@ -47,16 +47,46 @@ export def generate_site_conf [ return $file } +# Update getssl site configuration file with domain-specific values +export def update_site_conf [ + domain: record # the domain to generate getssl config for +]: nothing -> string { + # get variables + let certs = bf env "PROXY_SSL_CERTS" + let file = $"($certs)/($domain)/(bf env "PROXY_GETSSL_CFG")" + + # SANS + let sans = $domain.aliases | str join "," + replace -q "SANS" $sans $file + + # certificate + let cert = $"($certs)/($domain.primary)" + replace -q "DOMAIN_CERT_LOCATION" $"($cert).crt" $file + replace -q "DOMAIN_KEY_LOCATION" $"($cert).key" $file + + # ACL + let acl = bf env "PROXY_WWW_ACME_CHALLENGE" + replace "ACL" $"\(\"($acl)\"\)" $file + replace -q "USE_SINGLE_ACL" "true" $file + + # return cfg file path + return $file +} + # Replace a value in a given config file export def replace [ key: string # config key to replace value: string # config value to set file: string # file path to load / save -] { + --add-quotes (-q) # add double quotes to the value before inserting +]: nothing -> nothing { # do nothing for empty key if ($key | is-empty) { return } + # add quotes + let quoted_value = match $add_quotes { true => $"\"($value)\"" false => $value } + # replace value let find = $"^#?($key).*$" | bf dump -t "regex" - open --raw $file | str replace --all --regex $find $"($key)=($value)" | save --force $file + open --raw $file | str replace --all --regex $find $"($key)=($quoted_value)" | save --force $file } diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index d5e696e..1b6b5ef 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -32,7 +32,8 @@ export def main [ conf generate_nginx_site_conf $x # generate site getssl conf - getssl generate_site_conf $x + getssl generate_site_conf $x.primary + getssl update_site_conf $x # generate temporary SSL ssl generate_temp_certs $x @@ -56,10 +57,10 @@ export def main [ # Check for clean install and delete export def setup_clean_install []: nothing -> nothing { bf write debug " .. removing SSL config and certificates:" init/setup_clean_install - bf env PROXY_GETSSL_GLOBAL_CFG | remove - bf env PROXY_SITES | $"($in)/*" | remove - bf env PROXY_SSL_CERTS | $"($in)/*" | remove - bf env PROXY_SSL_DHPARAM | remove + bf env "PROXY_GETSSL_GLOBAL_CFG" | remove + bf env "PROXY_SITES" | $"($in)/*" | remove + bf env "PROXY_SSL_CERTS" | $"($in)/*" | remove + bf env "PROXY_SSL_DHPARAM" | remove } # Remove file(s) by converting input into a glob before calling `rm` diff --git a/overlay/etc/nu/scripts/tests/getssl.nu b/overlay/etc/nu/scripts/tests/getssl.nu index a620488..8160e6f 100644 --- a/overlay/etc/nu/scripts/tests/getssl.nu +++ b/overlay/etc/nu/scripts/tests/getssl.nu @@ -165,6 +165,18 @@ export def replace__replaces_line_without_hash [] { assert equal $expected $result } +export def replace__adds_double_quotes [] { + let key = random chars + let value = random chars + let file = mktemp -t + echo $"#($key)=(random chars)" | save --force $file + let expected = $"($key)=\"($value)\"" + + let result = replace --add-quotes $key $value $file | open --raw $file + + assert equal $expected $result +} + #====================================================================================================================== # generate_site_conf @@ -172,7 +184,6 @@ export def replace__replaces_line_without_hash [] { export def generate_site_conf__does_nothing_when_config_exists [] { let primary = random chars - let domain = generate_domain --primary $primary let certs = mktemp -d -t let cfg = random chars let e = { @@ -184,14 +195,13 @@ export def generate_site_conf__does_nothing_when_config_exists [] { $cfg | path dirname | mkdir $in $content | save --force $cfg - let result = with-env $e { generate_site_conf $domain } | open --raw + let result = with-env $e { generate_site_conf $primary } | open --raw assert equal $content $result } export def generate_site_conf__creates_default_config [] { let primary = "do not use random value or hash will break" - let domain = generate_domain --primary $primary let certs = mktemp -d -t let cfg = "getssl.cfg" let e = { @@ -201,7 +211,7 @@ export def generate_site_conf__creates_default_config [] { let cfg = $"($certs)/($primary)/($cfg)" let expected = "7146e789a83077202ab129d461959016" - let result = with-env $e { generate_site_conf $domain } | open --raw | hash md5 + let result = with-env $e { generate_site_conf $primary } | open --raw | hash md5 assert equal $expected $result } From 6f2b1e23984a807f6d22402b8f65a61ee64a0767 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 16:54:39 +0000 Subject: [PATCH 45/76] Using latest base image --- Dockerfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8ceda2f..7885b36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.20-6.3.16 +FROM bfren/nginx:nginx1.26-alpine3.20-6.3.17 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" @@ -23,14 +23,16 @@ ENV \ BF_PROXY_GETSSL_EMAIL= \ # set to 1 to use live instead of staging server BF_PROXY_GETSSL_USE_LIVE_SERVER=0 \ - # the renew window number of days (certificates with more than this will not renew) - BF_PROXY_GETSSL_RENEW_WINDOW_DAYS=14 \ + # the renew window number of days - certificates with more than this will not renew (Nu duration) + BF_PROXY_GETSSL_RENEW_WINDOW=14day \ # set to 1 to skip local HTTP token check BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK=0 \ # set to the number of bits to use for generating private key BF_PROXY_SSL_KEY_BITS=4096 \ # set to the number of bits to use for generating DHPARAM BF_PROXY_SSL_DHPARAM_BITS=4096 \ + # the period of time before self-generated SSL certificates will expire (Nu duration) + BF_PROXY_SSL_EXPIRY=36500day \ # canonical domain name redirection BF_PROXY_SSL_REDIRECT_TO_CANONICAL=0 \ # if both are set, on first startup will generate SSL config and request certs @@ -42,8 +44,8 @@ ENV \ BF_PROXY_AUTO_CUSTOM=0 \ # upstream DNS resolver, set to Docker's internal resolver by default BF_PROXY_UPSTREAM_DNS_RESOLVER=127.0.0.11 \ - # the number of seconds before the maintenance page will automatically refresh - BF_PROXY_MAINTENANCE_REFRESH_SECONDS=6 + # the number of seconds before the maintenance page will automatically refresh (Nu duration) + BF_PROXY_MAINTENANCE_REFRESH=6sec RUN bf-install From 7b769a0be1fd7eeefa8712312cfbae8c75ac916a Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 16:55:00 +0000 Subject: [PATCH 46/76] Supporting parallel test execution --- overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu | 3 ++- overlay/etc/nu/scripts/tests/auto.nu | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu index 7d46afd..b71b39a 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/auto.nu @@ -10,6 +10,7 @@ export def generate_conf_json []: nothing -> nothing { $a => ($a | split words | str join "\", \"" | $"\"($in)\"") } let custom = bf env -s "PROXY_AUTO_CUSTOM" + let conf_json = bf env "PROXY_SSL_CONF" # generate file bf write "Generating conf.json using auto environment variables." auto/generate_conf_json @@ -19,7 +20,7 @@ export def generate_conf_json []: nothing -> nothing { ALIASES: $aliases CUSTOM: $custom } - with-env $e { bf esh template (bf env "PROXY_SSL_CONF") } + with-env $e { bf esh template $conf_json } # return nothing return diff --git a/overlay/etc/nu/scripts/tests/auto.nu b/overlay/etc/nu/scripts/tests/auto.nu index 15edb59..246eb66 100644 --- a/overlay/etc/nu/scripts/tests/auto.nu +++ b/overlay/etc/nu/scripts/tests/auto.nu @@ -59,7 +59,7 @@ export def is_enabled__returns_true [] { # generate_conf_json #====================================================================================================================== -const CONF_JSON_OUTPUT = "/tmp/conf.json" +const CONF_JSON = "conf.json" def get_conf_json_e [ --primary: string # Optional primary domain name @@ -73,15 +73,17 @@ def get_conf_json_e [ BF_PROXY_AUTO_UPSTREAM: (match $upstream { null => (random chars), _ => $upstream }) BF_PROXY_AUTO_ALIASES: $aliases BF_PROXY_AUTO_CUSTOM: (match $custom { true => "1", false => "" }) - BF_PROXY_SSL_CONF: $CONF_JSON_OUTPUT + BF_PROXY_SSL_CONF: (get_conf_json_file) } } +def get_conf_json_file [] { $"(mktemp -d -t)/($CONF_JSON)" } + export def generate_conf_json__outputs_primary [] { let primary = random chars --length 5 let e = get_conf_json_e --primary $primary - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.primary + let result = with-env $e { generate_conf_json } | open $e.BF_PROXY_SSL_CONF | get domains.0.primary assert equal $primary $result } @@ -90,7 +92,7 @@ export def generate_conf_json__outputs_upstream [] { let upstream = random chars --length 5 let e = get_conf_json_e --upstream $upstream - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.upstream + let result = with-env $e { generate_conf_json } | open $e.BF_PROXY_SSL_CONF | get domains.0.upstream assert equal $upstream $result } @@ -100,7 +102,7 @@ export def generate_conf_json__outputs_aliases [] { let aliases_in = $aliases | str join " " let e = get_conf_json_e --aliases $aliases_in - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.aliases + let result = with-env $e { generate_conf_json } | open $e.BF_PROXY_SSL_CONF | get domains.0.aliases assert equal $aliases $result } @@ -108,7 +110,7 @@ export def generate_conf_json__outputs_aliases [] { export def generate_conf_json__does_not_output_aliases [] { let e = get_conf_json_e - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.aliases + let result = with-env $e { generate_conf_json } | open $e.BF_PROXY_SSL_CONF | get -i domains.0.aliases assert equal null $result } @@ -116,7 +118,7 @@ export def generate_conf_json__does_not_output_aliases [] { export def generate_conf_json__outputs_custom [] { let e = get_conf_json_e --custom - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get domains.0.custom + let result = with-env $e { generate_conf_json } | open $e.BF_PROXY_SSL_CONF | get domains.0.custom assert equal true $result } @@ -124,7 +126,7 @@ export def generate_conf_json__outputs_custom [] { export def generate_conf_json__does_not_output_custom [] { let e = get_conf_json_e - let result = with-env $e { generate_conf_json } | open $CONF_JSON_OUTPUT | get -i domains.0.custom + let result = with-env $e { generate_conf_json } | open $e.BF_PROXY_SSL_CONF | get -i domains.0.custom assert equal null $result } From 89ddf4d45731a3a05192ade24c870bbb9091effa Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 16:55:26 +0000 Subject: [PATCH 47/76] Supporting duration in env variables --- overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu | 10 ++++++---- overlay/etc/nu/scripts/tests/getssl.nu | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu index 34b709e..0c8c9f5 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu @@ -9,13 +9,14 @@ export def generate_global_conf []: nothing -> nothing { USE_LIVE_SERVER: (bf env "PROXY_GETSSL_USE_LIVE_SERVER") ACCOUNT_EMAIL: (bf env "PROXY_GETSSL_EMAIL") ACCOUNT_KEY: (bf env "PROXY_GETSSL_ACCOUNT_KEY") - RENEW_ALLOW: (bf env "PROXY_GETSSL_RENEW_WINDOW_DAYS") + RENEW_ALLOW: (bf env "PROXY_GETSSL_RENEW_WINDOW" | into duration | $in / 1day) SKIP_HTTP_TOKEN_CHECK: (bf env check "PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK" | into string) } # generate configuration - bf write debug "Creating getssl global configuration file" getssl/generate_global_conf with-env $e { bf esh template $getssl_cfg } + } else { + bf write debug " .. getssl global configuration file already exists." getssl/generate_global_conf } } @@ -27,7 +28,7 @@ export def generate_site_conf [ let certs = bf env "PROXY_SSL_CERTS" let file = $"($certs)/($domain)/(bf env "PROXY_GETSSL_CFG")" if ($file | path exists) { - bf write debug " .. getssl configuration file already exists." + bf write debug " .. getssl configuration file already exists." getssl/generate_site_conf return $file } @@ -38,9 +39,10 @@ export def generate_site_conf [ (bf env "PROXY_SSL_CERTS") "-c" # create default configuration files $domain - ] | compact --empty | bf dump -t "args" + ] | compact --empty # in case BF_PROXY_GETSSL_FLAGS is not set # execute getssl + bf write debug " .. getssl configuration file already exists." getssl/generate_site_conf { ^getssl ...$args } | bf handle # return cfg file path diff --git a/overlay/etc/nu/scripts/tests/getssl.nu b/overlay/etc/nu/scripts/tests/getssl.nu index 8160e6f..3da68a0 100644 --- a/overlay/etc/nu/scripts/tests/getssl.nu +++ b/overlay/etc/nu/scripts/tests/getssl.nu @@ -12,7 +12,7 @@ def generate_conf_e [ --use-live-server --email: string --account-key: string - --renew-window: int + --renew-window: duration --skip-check file: string ] { @@ -22,7 +22,7 @@ def generate_conf_e [ BF_PROXY_GETSSL_USE_LIVE_SERVER: (match ($use_live_server) { true => "1" false => "0" }) BF_PROXY_GETSSL_EMAIL: ($email | default (random chars)) BF_PROXY_GETSSL_ACCOUNT_KEY: ($account_key | default (random chars)) - BF_PROXY_GETSSL_RENEW_WINDOW_DAYS: ($renew_window | default (random int 14..28)) + BF_PROXY_GETSSL_RENEW_WINDOW: ($renew_window | default (random int 14..28 | into duration --unit day)) BF_PROXY_GETSSL_SKIP_HTTP_TOKEN_CHECK: (match $skip_check { true => "1" false => "0" }) } } @@ -89,12 +89,12 @@ export def generate_conf__outputs_account_key [] { export def generate_conf__outputs_renew_allow [] { let file = get_tmp_file - let renew = random int 14..28 + let renew = random int 14..28 | into duration --unit day let e = generate_conf_e --renew-window $renew $file let result = with-env $e { generate_global_conf } | open --raw $file - assert str contains $result $"(char newline)RENEW_ALLOW=\"($renew)\"(char newline)" + assert str contains $result $"(char newline)RENEW_ALLOW=\"($renew / 1day | into string)\"(char newline)" } export def generate_conf__outputs_skip_http_check_false [] { From 6e9b2a31de314b343fc953a19314572746dc5654 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 16:55:40 +0000 Subject: [PATCH 48/76] Improving debug log output --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 734b364..57e13cf 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -38,9 +38,6 @@ export def generate_nginx_site_conf [ let dir = $"($site).d" let template = $"(bf env "ETC_TEMPLATES")/nginx-(match ($is_root) { true => "root" false => "site" }).conf.esh" - # output domain to log - bf write $"Generating Nginx configuration for ($primary)." conf/generate_nginx_site_conf - # ensure custom site config directory exists if ($dir | bf fs is_not_dir) { mkdir $dir } @@ -48,15 +45,15 @@ export def generate_nginx_site_conf [ if ($conf | path exists) { # if custom config is enabled, don't touch the file if $custom { - bf write debug " .. keeping custom configuration" conf/generate_nginx_site_conf + bf write debug " keeping custom configuration." conf/generate_nginx_site_conf return $conf } # remove file so it can be regenerated - bf write debug " .. removing file so it can be regenerated." conf/generate_nginx_site_conf + bf write debug " removing file so it can be regenerated." conf/generate_nginx_site_conf rm -f $conf } else { - bf write debug " .. site is not yet configured." conf/generate_nginx_site_conf + bf write debug " site is not yet configured." conf/generate_nginx_site_conf } # set environment values @@ -76,6 +73,7 @@ export def generate_nginx_site_conf [ } # generate config file + bf write debug " generating file." conf/generate_nginx_site_conf with-env $e { bf esh $template $conf } # return path to config file From cbca94d262905829f83404a54d6a9392221e64c3 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 16:55:49 +0000 Subject: [PATCH 49/76] Splitting out init functions --- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index 1b6b5ef..84307f5 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -4,7 +4,6 @@ use getssl.nu use ssl.nu # Initialise SSL for the specified domain(s). -#doc # Order of precedence: # 1. `init --all` # 2. `init --root` @@ -15,28 +14,30 @@ export def main [ --root (-d) # If set, will initialise root domain ]: nothing -> nothing { # generate getssl configuration + bf write "Creating getssl global configuration file." init getssl generate_global_conf # generate DHPARAM file + bf write "Generating DHPARAM." ssl generate_dhparam # closure to run init procedure let init_domain = {|x: record| - # generate global getssl config - getssl generate_global_conf - - # generate dhparam - ssl generate_dhparam + bf write $"Initialising ($x.primary)." init # generate Nginx config + bf write " .. generating Nginx configuration file." conf generate_nginx_site_conf $x # generate site getssl conf + bf write " .. generating getssl configuration file." getssl generate_site_conf $x.primary getssl update_site_conf $x - # generate temporary SSL - ssl generate_temp_certs $x + # generate temporary SSL files + bf write " .. generating temporary SSL certificates and keys." + ssl generate_temp_certs $x.primary + ssl create_pem $x.primary } # initialise domain(s) From 20323b5733854edce69da21617d84a83424be5ef Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 2 Dec 2024 16:55:54 +0000 Subject: [PATCH 50/76] Adding ssl functions and tests --- overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu | 67 ++++++++++- overlay/etc/nu/scripts/tests/ssl.nu | 115 +++++++++++++++++++ 2 files changed, 180 insertions(+), 2 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu index bede3a4..484bd4b 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/ssl.nu @@ -1,17 +1,80 @@ use bf +export const KEY_SUFFIX = ".key" +export const CRT_SUFFIX = "/fullchain.crt" +export const CHAIN_KEY_SUFFIX = "/chain.key" +export const CHAIN_CRT_SUFFIX = "/chain.crt" +export const PEM_SUFFIX = ".pem" + # Generate a DHPARAM file if it does not already exist export def generate_dhparam []: nothing -> nothing { let dhparam = bf env "PROXY_SSL_DHPARAM" if ($dhparam | bf fs is_not_file) { - bf write debug $"Creating dhparam file: ($dhparam)." ssl/generate_dhparam + # don't use bf handle here so we can see progress ^openssl dhparam (bf env "PROXY_SSL_DHPARAM_BITS") | save --force $dhparam + } else { + bf write debug $" .. ($dhparam) already exists." ssl/generate_dhparam } } # Generate temporary SSL certificates for a domain export def generate_temp_certs [ - domain: record # the domain record to generate temporary SSL for + domain: string # the domain to generate temporary SSL for ]: nothing -> nothing { + # get variables + let base = $"(bf env "PROXY_SSL_CERTS")/($domain)" + let key = $"($base)($KEY_SUFFIX)" + let crt = $"($base)($CRT_SUFFIX)" + let chain_key = $"($base)($CHAIN_KEY_SUFFIX)" + let chain_crt = $"($base)($CHAIN_CRT_SUFFIX)" + + # do nothing if the domain certificate already exists + if ($crt | path exists) { + bf write debug " .. certificate already exists." ssl/generate_temp_certs + return + } + + # closure to generate a certificate + let generate_cert = {|cn: string, keyout: string, crtout: string| + let args = [ + -x509 + -sha256 + -nodes + -days (bf env "PROXY_SSL_EXPIRY" | into duration | $in / 1day) + -newkey rsa:(bf env "PROXY_SSL_KEY_BITS") + -keyout $keyout + -out $crtout + -subj $"/C=NA/ST=NA/L=NA/O=NA/OU=NA/CN=($cn)" + ] + { ^openssl req ...$args } | bf handle + } + + # generate certificates + do $generate_cert $domain $key $crt + do $generate_cert $domain $chain_key $chain_crt +} + +# Create a PEM_SUFFIX file from a domain certificate and key +export def create_pem [ + domain: string # the domain to generate a PEM_SUFFIX file for +]: nothing -> string { + # get variables + let base = $"(bf env "PROXY_SSL_CERTS")/($domain)" + let key_file = $"($base)($KEY_SUFFIX)" + let crt_file = $"($base)($CRT_SUFFIX)" + let pem_file = $"($base)/($domain)($PEM_SUFFIX)" + + # return error if files do not exist + if ($key_file | bf fs is_not_file) or ($crt_file | bf fs is_not_file) { + bf write notok $"Unable to locate certificate or key file for ($domain)." ssl/create_pem + return "" + } + + # create pem file + let key = open --raw $key_file + let crt = open --raw $crt_file + echo $"($key)(char newline)($crt)" | save --force $pem_file + # return path to pem file + return $pem_file } diff --git a/overlay/etc/nu/scripts/tests/ssl.nu b/overlay/etc/nu/scripts/tests/ssl.nu index 79da073..3133734 100644 --- a/overlay/etc/nu/scripts/tests/ssl.nu +++ b/overlay/etc/nu/scripts/tests/ssl.nu @@ -35,3 +35,118 @@ export def generate_dhparam__generates_dhparam_if_file_does_not_exist [] { assert not equal "" $result } + + +#====================================================================================================================== +# generate_temp_certs +#====================================================================================================================== + +def generate_temp_certs_e [ + --bits: int = 1024 + --expiry: duration = 3650day + certs: string +] { + { + BF_PROXY_SSL_CERTS: $certs + BF_PROXY_SSL_EXPIRY: $expiry + BF_PROXY_SSL_KEY_BITS: $bits + } +} + +export def generate_temp_certs__does_nothing_if_crt_exists [] { + let certs = mktemp -d -t + let domain = random chars + mkdir $"($certs)/($domain)" + let content = random chars + let crt = $"($certs)/($domain)/($CRT_SUFFIX)" + echo $content | save --force $crt + let e = generate_temp_certs_e $certs + + let result = with-env $e { generate_temp_certs $domain } | open --raw $crt + + assert equal $content $result +} + +export def generate_temp_certs__generates_all_files [] { + let certs = mktemp -d -t + let domain = random chars + mkdir $"($certs)/($domain)" + let e = generate_temp_certs_e $certs + + let result = with-env $e { generate_temp_certs $domain } + + assert equal true ($"($certs)/($domain)($KEY_SUFFIX)" | path exists) + assert equal true ($"($certs)/($domain)($CRT_SUFFIX)" | path exists) + assert equal true ($"($certs)/($domain)($CHAIN_KEY_SUFFIX)" | path exists) + assert equal true ($"($certs)/($domain)($CHAIN_CRT_SUFFIX)" | path exists) +} + + +#====================================================================================================================== +# create_pem +#====================================================================================================================== + +export def create_pem__does_nothing_if_crt_does_not_exist [] { + let certs = mktemp -d -t + let domain = random chars + mkdir $"($certs)/($domain)" + random chars | save --force $"($certs)/($domain)($KEY_SUFFIX)" + let e = generate_temp_certs_e $certs + + let result = with-env $e { create_pem $domain } | echo $in | path exists + + assert equal false $result +} + +export def create_pem__does_nothing_if_key_does_not_exist [] { + let certs = mktemp -d -t + let domain = random chars + mkdir $"($certs)/($domain)" + random chars | save --force $"($certs)/($domain)($CRT_SUFFIX)" + let e = generate_temp_certs_e $certs + + let result = with-env $e { create_pem $domain } | echo $in | path exists + + assert equal false $result +} + +export def create_pem__merges_key_and_crt_files [] { + let certs = mktemp -d -t + let domain = random chars + let cert = $"($certs)/($domain)" + let key = random chars + let key_file = $"($cert)($KEY_SUFFIX)" + let crt = random chars + let crt_file = $"($cert)($CRT_SUFFIX)" + let pem = $"($key)(char newline)($crt)" + let pem_file = $"($cert)/($domain)($PEM_SUFFIX)" + let e = generate_temp_certs_e $certs + mkdir $cert + echo $key | save --force $key_file + echo $crt | save --force $crt_file + + let result = with-env $e { create_pem $domain } | open --raw $pem_file + + assert equal $pem $result +} + +export def create_pem__overwrites_existing_pem_file [] { + let certs = mktemp -d -t + let domain = random chars + let cert = $"($certs)/($domain)" + let key = random chars + let key_file = $"($cert)($KEY_SUFFIX)" + let crt = random chars + let crt_file = $"($cert)($CRT_SUFFIX)" + let pem = $"($key)(char newline)($crt)" + let pem_file = $"($cert)/($domain)($PEM_SUFFIX)" + let e = generate_temp_certs_e $certs + mkdir $cert + echo $key | save --force $key_file + echo $crt | save --force $crt_file + random chars | save --force $pem_file + + let result = with-env $e { create_pem $domain } | open --raw $pem_file + + assert equal $pem $result +} From a33373566c7da290f80b405aea7503807154468e Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:50:46 +0000 Subject: [PATCH 51/76] Removing lib files --- overlay/usr/lib/bf/inc/proxy-check.sh | 45 -------- overlay/usr/lib/bf/inc/proxy-init-domain.sh | 42 ------- overlay/usr/lib/bf/inc/proxy-load-conf.sh | 34 ------ overlay/usr/lib/bf/inc/proxy-replace.sh | 23 ---- overlay/usr/lib/bf/inc/proxy-setup-global.sh | 20 ---- overlay/usr/lib/bf/inc/proxy-setup-nginx.sh | 66 ----------- overlay/usr/lib/bf/inc/proxy-setup-ssl.sh | 111 ------------------- overlay/usr/lib/bf/proxy/init | 47 -------- overlay/usr/lib/bf/proxy/init-all | 52 --------- overlay/usr/lib/bf/proxy/request | 18 --- overlay/usr/lib/bf/proxy/request-all | 31 ------ overlay/usr/lib/bf/proxy/update | 32 ------ overlay/usr/lib/bf/proxy/update-all | 34 ------ 13 files changed, 555 deletions(-) delete mode 100644 overlay/usr/lib/bf/inc/proxy-check.sh delete mode 100644 overlay/usr/lib/bf/inc/proxy-init-domain.sh delete mode 100644 overlay/usr/lib/bf/inc/proxy-load-conf.sh delete mode 100644 overlay/usr/lib/bf/inc/proxy-replace.sh delete mode 100644 overlay/usr/lib/bf/inc/proxy-setup-global.sh delete mode 100644 overlay/usr/lib/bf/inc/proxy-setup-nginx.sh delete mode 100644 overlay/usr/lib/bf/inc/proxy-setup-ssl.sh delete mode 100644 overlay/usr/lib/bf/proxy/init delete mode 100644 overlay/usr/lib/bf/proxy/init-all delete mode 100644 overlay/usr/lib/bf/proxy/request delete mode 100644 overlay/usr/lib/bf/proxy/request-all delete mode 100644 overlay/usr/lib/bf/proxy/update delete mode 100644 overlay/usr/lib/bf/proxy/update-all diff --git a/overlay/usr/lib/bf/inc/proxy-check.sh b/overlay/usr/lib/bf/inc/proxy-check.sh deleted file mode 100644 index 44340b3..0000000 --- a/overlay/usr/lib/bf/inc/proxy-check.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Ensure PROXY_DOMAIN is set. -#====================================================================================================================== - -if [ -z "${PROXY_DOMAIN}" ] ; then - bf-error "PROXY_DOMAIN must be set before requesting SSL certificates." "inc/proxy-check.sh" - exit 1 -fi - - -#====================================================================================================================== -# Ensure email is set. -#====================================================================================================================== - -if [ -z "${PROXY_LETS_ENCRYPT_EMAIL}" ] ; then - bf-error "PROXY_LETS_ENCRYPT_EMAIL must be set before requesting SSL certificates." "inc/proxy-check.sh" - exit 1 -fi - - -#====================================================================================================================== -# Load configuration (creates DOMAINS array). -#====================================================================================================================== - -source ${BF_INC}/proxy-load-conf.sh - - -#====================================================================================================================== -# Check whether or not domains have been registered. -#====================================================================================================================== - -if [ "${#DOMAINS[*]}" = "0" ] ; then - bf-error "No domains have been registered for SSL - please add them to /ssl/conf.json." "inc/proxy-check.sh" - exit 1 -fi - - -#====================================================================================================================== -# Ensure certs directory exists. -#====================================================================================================================== - -[[ ! -d ${PROXY_SSL_CERTS} ]] && mkdir ${PROXY_SSL_CERTS} diff --git a/overlay/usr/lib/bf/inc/proxy-init-domain.sh b/overlay/usr/lib/bf/inc/proxy-init-domain.sh deleted file mode 100644 index f44bd6a..0000000 --- a/overlay/usr/lib/bf/inc/proxy-init-domain.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Initialise Nginx and SSL configuration for proxy domain. -#====================================================================================================================== - -init-proxy () { - - bf-echo " . Nginx..." "inc/proxy-init-domain.sh" - setup-nginx 1 ${PROXY_DOMAIN} "http://localhost" "" - - bf-echo " . SSL..." "inc/proxy-init-domain.sh" - setup-ssl ${PROXY_DOMAIN} "" - -} - - -#====================================================================================================================== -# Initialise Nginx and SSL configuration for a domain. -# -# Arguments -# 1 Domain name -#====================================================================================================================== - -init-domain () { - - # get domain configuration values - PRIMARY_DOMAIN=${1} - UPSTREAM_SERVER=`get-upstream ${PRIMARY_DOMAIN}` - DOMAIN_ALIASES=`get-aliases ${PRIMARY_DOMAIN}` - CUSTOM_NGINX_CONFIG=`get-custom ${PRIMARY_DOMAIN}` - - # add default Nginx configuration - bf-echo " . Nginx..." "inc/proxy-init-domain.sh" - setup-nginx 0 ${PRIMARY_DOMAIN} ${UPSTREAM_SERVER} "${DOMAIN_ALIASES}" ${CUSTOM_NGINX_CONFIG} - - # add default SSL files - bf-echo " . SSL..." "inc/proxy-init-domain.sh" - setup-ssl ${PRIMARY_DOMAIN} "${DOMAIN_ALIASES}" - -} diff --git a/overlay/usr/lib/bf/inc/proxy-load-conf.sh b/overlay/usr/lib/bf/inc/proxy-load-conf.sh deleted file mode 100644 index 47156eb..0000000 --- a/overlay/usr/lib/bf/inc/proxy-load-conf.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Check JSON configuration file exists. -#====================================================================================================================== - -if [ ! -f "${PROXY_SSL_CONF}" ] ; then - bf-error "You must create ${PROXY_SSL_CONF} - see ssl-conf-sample.json." "inc/proxy-load-conf.sh" - exit 1 -fi - - -#====================================================================================================================== -# Load JSON and create DOMAINS array by selecting primary keys. -#====================================================================================================================== - -JSON=`cat "${PROXY_SSL_CONF}" | jq '.'` - -declare -a DOMAINS=(`jq -r '.domains[].primary' <<< "${JSON}"`) - - -#====================================================================================================================== -# Gets a domain object from the JSON configuration. -# -# Arguments -# 1 Primary domain name to select -#====================================================================================================================== - -function get-domain() { jq --arg PRIMARY "${1}" '.domains[] | select(.primary == $PRIMARY)' <<< "${JSON}" ; } - -function get-upstream() { get-domain "${1}" | jq -r '.upstream' ; } -function get-aliases() { get-domain "${1}" | jq -r '.aliases[]?' ; } -function get-custom() { get-domain "${1}" | jq -r '.custom == true' ; } diff --git a/overlay/usr/lib/bf/inc/proxy-replace.sh b/overlay/usr/lib/bf/inc/proxy-replace.sh deleted file mode 100644 index adf1c76..0000000 --- a/overlay/usr/lib/bf/inc/proxy-replace.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Replace a key/value pair in a file. -# -# Arguments -# 1 Key -# 2 Value -# 3 File path -#====================================================================================================================== - -replace () { replace-d "${1}" "\"${2}\"" ${3}; } - -replace-d () { - - K=${1} - V=${2} - FILE=${3} - - [[ ! -z "${V}" ]] && sed -i "s|^#\?${K}.*$|${K}=${V}|i" ${FILE} - -} diff --git a/overlay/usr/lib/bf/inc/proxy-setup-global.sh b/overlay/usr/lib/bf/inc/proxy-setup-global.sh deleted file mode 100644 index 92027c5..0000000 --- a/overlay/usr/lib/bf/inc/proxy-setup-global.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Set up global configuration. -#====================================================================================================================== - -setup-global () { - - if [ ! -f ${PROXY_GETSSL_GLOBAL_CFG} ] ; then - bf-debug " .. creating global configuration file..." "inc/proxy-setup-global.sh" - bf-esh ${BF_TEMPLATES}/getssl-global.conf.esh ${PROXY_GETSSL_GLOBAL_CFG} - fi - - if [ ! -f ${PROXY_SSL_DHPARAM} ] ; then - bf-debug " .. generating dhparam..." "inc/proxy-setup-global.sh" - openssl dhparam -out ${PROXY_SSL_DHPARAM} ${PROXY_SSL_DHPARAM_BITS} - fi - -} diff --git a/overlay/usr/lib/bf/inc/proxy-setup-nginx.sh b/overlay/usr/lib/bf/inc/proxy-setup-nginx.sh deleted file mode 100644 index f435c46..0000000 --- a/overlay/usr/lib/bf/inc/proxy-setup-nginx.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Set up Nginx. -# -# Arguments -# 1 0 for proxied domain, 1 for domain of the proxy server itself -# 2 Domain name -# 3 Upstream URL -# 4 Name of Domain Aliases array -# 5 Blank (regenerate) or 'custom' (keep) Nginx configuration file -#====================================================================================================================== - -setup-nginx () { - - # give arguments friendly names - export IS_PROXY=${1} - export DOMAIN_NAME=${2} - export UPSTREAM=${3} - local DOMAIN_ALIASES=${4} - export DOMAIN_NGXCONF=${5} - - # paths to site configuration and custom config directory - local SITE="${PROXY_SITES}/${DOMAIN_NAME}" - local CONF="${SITE}.conf" - export CUSTOM_CONF="${SITE}.d" - - # check for custom site configuration directory - [[ ! -d ${CUSTOM_CONF} ]] && mkdir ${CUSTOM_CONF} - - # check for existing configuration file - if [ -f ${CONF} ] ; then - - # if true, leave file (allows custom config) - if [ "${DOMAIN_NGXCONF}" = "true" ] ; then - bf-debug " keeping existing configuration." "inc/proxy-setup-nginx.sh" - return 0 - - # otherwise, remove config so it can be regenerated - else - bf-debug " removing and regnerating Nginx configuration" "inc/proxy-setup-nginx.sh" - rm ${CONF} - fi - - else - - # no need to remove anything, be a good log citizen - bf-debug " generating default Nginx configuration" "inc/proxy-setup-nginx.sh" - - fi - - # build domain list and remove trailing / multiple spaces between domains - export SERVER_NAMES=$(echo "${DOMAIN_NAME} ${DOMAIN_ALIASES}" | xargs) - - # generate site configuration - if [ "${IS_PROXY}" = "1" ] ; then - NGINX_CONF="proxy" - else - NGINX_CONF="site" - fi - - # generate config - bf-esh ${BF_TEMPLATES}/nginx-${NGINX_CONF}.conf.esh ${CONF} > /dev/null 2>&1 - -} diff --git a/overlay/usr/lib/bf/inc/proxy-setup-ssl.sh b/overlay/usr/lib/bf/inc/proxy-setup-ssl.sh deleted file mode 100644 index da41385..0000000 --- a/overlay/usr/lib/bf/inc/proxy-setup-ssl.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Generate a temporary SSL certificate and key. -# -# Arguments -# 1 Base path -# 2 Domain name -#====================================================================================================================== - -generate-temp-cert () { - - openssl req \ - -x509 \ - -sha256 \ - -nodes \ - -days 3650 \ - -newkey rsa:${PROXY_SSL_KEY_BITS} \ - -keyout ${2} \ - -out ${1} \ - -subj "/C=NA/ST=NA/L=NA/O=NA/OU=NA/CN=${3}" - -} - - -#====================================================================================================================== -# Create PEM file out of the private key, server certificate, and intermediate certificate. -# -# Arguments -# 1 Domain name -#====================================================================================================================== - -create-pem () { - - local DOMAIN_NAME=${1} - local CERT=${PROXY_SSL_CERTS}/${DOMAIN_NAME} - local PEM=${CERT}/${DOMAIN_NAME}.pem - - cat ${CERT}.key > ${PEM} - cat ${CERT}/fullchain.crt >> ${PEM} - -} - - -#====================================================================================================================== -# Set up SSL for a domain. -# -# Arguments -# 1 Domain name -# 2 String containing Domain Aliases (separated by spaces) -#====================================================================================================================== - -setup-ssl () { - - local DOMAIN_NAME=${1} - local DOMAIN_ALIASES=(${2}) - local FILE=${PROXY_SSL_CERTS}/${DOMAIN_NAME}/${PROXY_GETSSL_CFG} - - # check for existing configuration - [[ -f ${FILE} ]] && bf-debug " already set up." "inc/proxy-setup-ssl.sh" && return 0 - - # getssl flags - # -d enable debug output - # -U stop upgrade checks - # -w set working directory - # -c create default configuration files - ${PROXY_GETSSL} ${PROXY_GETSSL_FLAGS} -w ${PROXY_SSL_CERTS} -c ${DOMAIN_NAME} - - # set default values - local SANS=$(printf ",%s" ${DOMAIN_ALIASES[@]}) - local CERT=${PROXY_SSL_CERTS}/${DOMAIN_NAME} - local ACL_DIR="'${PROXY_WWW_ACME_CHALLENGE}'" - local ACL_RPT=$((${#DOMAIN_ALIASES[@]} + 1)) - local ACL=$(yes ${ACL_DIR} | head -n ${ACL_RPT} | sed -n 'H;${x;s/\n/ /gp}') - - # replace config values with defaults - bf-debug " replacing configuration value" "inc/proxy-setup-ssl.sh" - replace "SANS" "${SANS:1}" ${FILE} - replace "DOMAIN_CERT_LOCATION" "${CERT}.crt" ${FILE} - replace "DOMAIN_KEY_LOCATION" "${CERT}.key" ${FILE} - replace-d "ACL" "(${ACL})" ${FILE} - - # create self-signed certificate so nginx will start before we request proper certificates - bf-debug " generating temporary SSL certificates" "inc/proxy-setup-ssl.sh" - generate-temp-cert ${CERT}/fullchain.crt ${CERT}.key ${DOMAIN_NAME} - generate-temp-cert ${CERT}/chain.crt ${CERT}/chain.key ${DOMAIN_NAME} - rm ${CERT}/chain.key - - # create pem file - create-pem "${DOMAIN_NAME}" - -} - - -#====================================================================================================================== -# Request certificate for a domain. -# -# getssl flags -# -d enable debug output -# -U stop upgrade checks -# -w set working directory -# -# Arguments -# 1 Domain name -#====================================================================================================================== - -request() { - ${PROXY_GETSSL} ${PROXY_GETSSL_FLAGS} -w ${PROXY_SSL_CERTS} "${1}" - create-pem "${1}" -} diff --git a/overlay/usr/lib/bf/proxy/init b/overlay/usr/lib/bf/proxy/init deleted file mode 100644 index 05ef50b..0000000 --- a/overlay/usr/lib/bf/proxy/init +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Run checks. -#====================================================================================================================== - -source ${BF_INC}/proxy-check.sh - - -#====================================================================================================================== -# Require source files. -#====================================================================================================================== - -source ${BF_INC}/proxy-init-domain.sh -source ${BF_INC}/proxy-replace.sh -source ${BF_INC}/proxy-setup-global.sh -source ${BF_INC}/proxy-setup-nginx.sh -source ${BF_INC}/proxy-setup-ssl.sh - - -#====================================================================================================================== -# Set up global SSL configuration. -#====================================================================================================================== - -bf-echo "Setting up getssl..." "proxy/init" -setup-global -bf-done "proxy/init" - - -#====================================================================================================================== -# Initialise Nginx and SSL for requested domain. -#====================================================================================================================== - -if [ "${1}" = "proxy" ] || [ "${1}" = "${PROXY_DOMAIN}" ] ; then - - bf-echo "Initialising Nginx and SSL for proxy domain ${PROXY_DOMAIN}..." "proxy/init" - init-proxy - -else - - bf-echo "Initialising Nginx and SSL for ${1}..." "proxy/init" - init-domain "${1}" - -fi - -bf-done "proxy/init" diff --git a/overlay/usr/lib/bf/proxy/init-all b/overlay/usr/lib/bf/proxy/init-all deleted file mode 100644 index 67bf97f..0000000 --- a/overlay/usr/lib/bf/proxy/init-all +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Run checks. -#====================================================================================================================== - -source ${BF_INC}/proxy-check.sh - - -#====================================================================================================================== -# Require source files. -#====================================================================================================================== - -source ${BF_INC}/proxy-init-domain.sh -source ${BF_INC}/proxy-replace.sh -source ${BF_INC}/proxy-setup-global.sh -source ${BF_INC}/proxy-setup-nginx.sh -source ${BF_INC}/proxy-setup-ssl.sh - - -#====================================================================================================================== -# Set up global SSL configuration. -#====================================================================================================================== - -bf-echo "Setting up getssl..." "proxy/init-all" -setup-global -bf-done "proxy/init-all" - - -#====================================================================================================================== -# Set up Nginx and SSL for proxy domain. -#====================================================================================================================== - -bf-echo "Initialising Nginx and SSL for proxy domain ${PROXY_DOMAIN}..." "proxy/init-all" -init-proxy -bf-done "proxy/init-all" - - -#====================================================================================================================== -# Set up Nginx and SSL for each domain. -#====================================================================================================================== - -bf-echo "Initialising Nginx and SSL for all domains..." "proxy/init-all" -for DN in "${DOMAINS[@]}" ; do - - bf-echo " .. ${DN}" "proxy/init-all" - init-domain "${DN}" - bf-ok " . done." "proxy/init-all" - -done -bf-done "proxy/init-all" diff --git a/overlay/usr/lib/bf/proxy/request b/overlay/usr/lib/bf/proxy/request deleted file mode 100644 index 8560a0d..0000000 --- a/overlay/usr/lib/bf/proxy/request +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Run checks and include ssl functions. -#====================================================================================================================== - -source ${BF_INC}/proxy-check.sh -source ${BF_INC}/proxy-setup-ssl.sh - - -#====================================================================================================================== -# Get certificates for requested domain. -#====================================================================================================================== - -bf-echo "Requesting domain certificate for ${1}..." "proxy/request" -request "${1}" -bf-done "proxy/request" diff --git a/overlay/usr/lib/bf/proxy/request-all b/overlay/usr/lib/bf/proxy/request-all deleted file mode 100644 index a09c063..0000000 --- a/overlay/usr/lib/bf/proxy/request-all +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Run checks and include ssl functions. -#====================================================================================================================== - -source ${BF_INC}/proxy-check.sh -source ${BF_INC}/proxy-setup-ssl.sh - - -#====================================================================================================================== -# Get certificate for the proxy domain. -#====================================================================================================================== - -bf-echo "Requesting proxy domain certificate..." "proxy/request-all" -bf-debug " .. ${PROXY_DOMAIN}" -request "${PROXY_DOMAIN}" -bf-done "proxy/request-all" - - -#====================================================================================================================== -# Get certificates for all registered domains. -#====================================================================================================================== - -bf-echo "Requesting domain certificates..." "proxy/request-all" -for DN in "${DOMAINS[@]}" ; do - bf-debug " .. ${DN}" "proxy/request-all" - request "${DN}" -done -bf-done "proxy/request-all" diff --git a/overlay/usr/lib/bf/proxy/update b/overlay/usr/lib/bf/proxy/update deleted file mode 100644 index 9b020eb..0000000 --- a/overlay/usr/lib/bf/proxy/update +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Run checks and include ssl functions. -#====================================================================================================================== - -source ${BF_INC}/proxy-check.sh -source ${BF_INC}/proxy-setup-ssl.sh - - -#====================================================================================================================== -# Run update. -# -# getssl flags -# -d enable debug output -# -U stop upgrade checks -# -w set working directory -#====================================================================================================================== - -bf-echo "Updating SSL certificate for ${1}..." "proxy/update" -${PROXY_GETSSL} ${PROXY_GETSSL_FLAGS} -w ${PROXY_SSL_CERTS} ${1} -bf-done "proxy/update" - - -#====================================================================================================================== -# Update pem file. -#====================================================================================================================== - -bf-echo "Updating pem file for ${1}..." "proxy/update" -create-pem "${1}" -bf-done "proxy/update" diff --git a/overlay/usr/lib/bf/proxy/update-all b/overlay/usr/lib/bf/proxy/update-all deleted file mode 100644 index f1a3d7b..0000000 --- a/overlay/usr/lib/bf/proxy/update-all +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - - -#====================================================================================================================== -# Run checks and include ssl functions. -#====================================================================================================================== - -source ${BF_INC}/proxy-check.sh -source ${BF_INC}/proxy-setup-ssl.sh - - -#====================================================================================================================== -# Run update. -# -# getssl flags -# -d enable debug output -# -U stop upgrade checks -# -w set working directory -# -a check all certificates -#====================================================================================================================== - -bf-echo "Updating all SSL certificates..." "proxy/update-all" -${PROXY_GETSSL} ${PROXY_GETSSL_FLAGS} -w ${PROXY_SSL_CERTS} -a -bf-done "proxy/update-all" - - -#====================================================================================================================== -# Update all pem files (easier than working out which have been changed). -#====================================================================================================================== - -bf-echo "Updating pem files..." "proxy/update-all" -create-pem ${PROXY_DOMAIN} -for DN in "${DOMAINS[@]}" ; do create-pem "${DN}" ; done -bf-done "proxy/update-all" From 797463e9099a824fb442306b5c4e39098f09cf12 Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:51:05 +0000 Subject: [PATCH 52/76] Renaming getssl global config template --- .../etc/bf/templates/{getssl-global.conf.esh => getssl.cfg.esh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename overlay/etc/bf/templates/{getssl-global.conf.esh => getssl.cfg.esh} (100%) diff --git a/overlay/etc/bf/templates/getssl-global.conf.esh b/overlay/etc/bf/templates/getssl.cfg.esh similarity index 100% rename from overlay/etc/bf/templates/getssl-global.conf.esh rename to overlay/etc/bf/templates/getssl.cfg.esh From 409f99c361148f37934ababea48473d3a3427e7d Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:51:12 +0000 Subject: [PATCH 53/76] Adding missing use --- overlay/etc/bf/init.d/21-ssl-conf.nu | 1 + 1 file changed, 1 insertion(+) diff --git a/overlay/etc/bf/init.d/21-ssl-conf.nu b/overlay/etc/bf/init.d/21-ssl-conf.nu index 5af8afd..ad387f4 100644 --- a/overlay/etc/bf/init.d/21-ssl-conf.nu +++ b/overlay/etc/bf/init.d/21-ssl-conf.nu @@ -1,3 +1,4 @@ +use bf use bf/nginx/proxy conf bf env load From bae51e8334216c168134d4ceb7f6f3226e94cf62 Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:51:36 +0000 Subject: [PATCH 54/76] Safely getting paths --- overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 57e13cf..83ac7ef 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -26,10 +26,10 @@ export def generate_nginx_site_conf [ domain: record # the domain record to generate config for ]: nothing -> string { # get type-hinted variables - let primary: string = $domain.primary - let upstream: string = $domain.upstream - let aliases: list = $domain.aliases - let custom: bool = $domain.custom + let primary: string = $domain | get primary + let upstream: string = $domain | get upstream + let aliases: list = $domain | get -i aliases | default [] + let custom: bool = $domain | get -i custom | default false let is_root = $primary == (bf env "PROXY_DOMAIN") # generate paths From 428606b7a74a03d64a1ae7b6075ef562444ee45c Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:51:51 +0000 Subject: [PATCH 55/76] Improving docs and output --- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index 84307f5..9934678 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -9,16 +9,16 @@ use ssl.nu # 2. `init --root` # 3. `init --domain xxxxxx` export def main [ - --all (-a) # If set, will initialise root and all configured domains - --domain (-d): string # Specify the domain to be initialised - --root (-d) # If set, will initialise root domain + --all (-a) # Initialise root and all configured domains + --domain (-d): string # The domain to be initialised + --root (-d) # Initialise root domain ]: nothing -> nothing { # generate getssl configuration bf write "Creating getssl global configuration file." init getssl generate_global_conf # generate DHPARAM file - bf write "Generating DHPARAM." + bf write "Generating DHPARAM." init ssl generate_dhparam # closure to run init procedure @@ -26,16 +26,16 @@ export def main [ bf write $"Initialising ($x.primary)." init # generate Nginx config - bf write " .. generating Nginx configuration file." + bf write " .. generating Nginx configuration file." init conf generate_nginx_site_conf $x # generate site getssl conf - bf write " .. generating getssl configuration file." + bf write " .. generating getssl configuration file." init getssl generate_site_conf $x.primary getssl update_site_conf $x # generate temporary SSL files - bf write " .. generating temporary SSL certificates and keys." + bf write " .. generating temporary SSL certificates and keys." init ssl generate_temp_certs $x.primary ssl create_pem $x.primary } @@ -45,17 +45,20 @@ export def main [ get_all | each $init_domain } else if $root { - $init_domain (get_root) + do $init_domain (get_root) } else if $domain { - $init_domain (get_single $domain) + do $init_domain (get_single $domain) + } + else { + main --help } - # return nothing - return + # done + bf write ok "Done." init } -# Check for clean install and delete +# Check for clean install and delete. export def setup_clean_install []: nothing -> nothing { bf write debug " .. removing SSL config and certificates:" init/setup_clean_install bf env "PROXY_GETSSL_GLOBAL_CFG" | remove @@ -64,20 +67,20 @@ export def setup_clean_install []: nothing -> nothing { bf env "PROXY_SSL_DHPARAM" | remove } -# Remove file(s) by converting input into a glob before calling `rm` +# Remove file(s) by converting input into a glob before calling `rm`. def remove []: string -> nothing { let file = $in | into glob bf write debug $" ($file)" init/remove rm --force --recursive $file } -# Retrieve all configured domain record +# Retrieve all configured domain record. export def get_all []: nothing -> list { conf get_domains } -# Retrieve a single domain record +# Retrieve a single domain record. export def get_single [ domain: string # The domain to initialise ]: nothing -> record { conf get_domains | where primary == $domain | into record } -# Retrieve the root domain record +# Retrieve the root domain record. export def get_root []: nothing -> record { get_single (bf env "PROXY_DOMAIN") } From f2bb52ee177fc148cab2414df9c073f1579be097 Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:52:08 +0000 Subject: [PATCH 56/76] Adding tests for update getssl config file --- .../etc/nu/scripts/bf/nginx/proxy/getssl.nu | 20 +++- overlay/etc/nu/scripts/tests/getssl.nu | 110 ++++++++++++++++-- overlay/etc/nu/scripts/tests/vars.nu | 1 + 3 files changed, 115 insertions(+), 16 deletions(-) diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu index 0c8c9f5..bf5e6f2 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/getssl.nu @@ -55,10 +55,10 @@ export def update_site_conf [ ]: nothing -> string { # get variables let certs = bf env "PROXY_SSL_CERTS" - let file = $"($certs)/($domain)/(bf env "PROXY_GETSSL_CFG")" + let file = $"($certs)/($domain.primary)/(bf env "PROXY_GETSSL_CFG")" # SANS - let sans = $domain.aliases | str join "," + let sans = $domain | get -i aliases | default [] | str join "," replace -q "SANS" $sans $file # certificate @@ -89,6 +89,18 @@ export def replace [ let quoted_value = match $add_quotes { true => $"\"($value)\"" false => $value } # replace value - let find = $"^#?($key).*$" | bf dump -t "regex" - open --raw $file | str replace --all --regex $find $"($key)=($quoted_value)" | save --force $file + let find = $"^#?($key).*$" + load_cfg $key $file | str replace --all --multiline --regex $find $"($key)=($quoted_value)" | save --force $file +} + +# Load cfg file and ensure the given key exists +export def load_cfg [ + key: string + file: string +] { + let cfg = open --raw $file + match ($cfg | str contains $key) { + true => $cfg + false => ($cfg | append $"#($key)=" | str join (char newline)) + } } diff --git a/overlay/etc/nu/scripts/tests/getssl.nu b/overlay/etc/nu/scripts/tests/getssl.nu index 3da68a0..fcb5121 100644 --- a/overlay/etc/nu/scripts/tests/getssl.nu +++ b/overlay/etc/nu/scripts/tests/getssl.nu @@ -27,7 +27,7 @@ def generate_conf_e [ } } -def get_tmp_file []: nothing -> string { $"/(mktemp -d -t)/getssl-global.conf" } +def get_tmp_file []: nothing -> string { $"/(mktemp -d -t)/getssl.cfg" } export def generate_conf__does_nothing_if_file_exists [] { let file = get_tmp_file @@ -182,18 +182,25 @@ export def replace__adds_double_quotes [] { # generate_site_conf #====================================================================================================================== +def generate_site_conf_e [ + --cfg: string + certs: string +] { + { + BF_PROXY_SSL_CERTS: $certs + BF_PROXY_GETSSL_CFG: ($cfg | default $GETSSL_CONF_BASENAME) + } +} + export def generate_site_conf__does_nothing_when_config_exists [] { let primary = random chars let certs = mktemp -d -t let cfg = random chars - let e = { - BF_PROXY_SSL_CERTS: $certs - BF_PROXY_GETSSL_CFG: $cfg - } let content = random chars - let cfg = $"($certs)/($primary)/($cfg)" + let cfg = $"($certs)/($primary)/(random chars)" $cfg | path dirname | mkdir $in $content | save --force $cfg + let e = generate_site_conf_e --cfg ($cfg | path basename) $certs let result = with-env $e { generate_site_conf $primary } | open --raw @@ -203,15 +210,94 @@ export def generate_site_conf__does_nothing_when_config_exists [] { export def generate_site_conf__creates_default_config [] { let primary = "do not use random value or hash will break" let certs = mktemp -d -t - let cfg = "getssl.cfg" - let e = { - BF_PROXY_SSL_CERTS: $certs - BF_PROXY_GETSSL_CFG: $cfg - } - let cfg = $"($certs)/($primary)/($cfg)" + let e = generate_site_conf_e $certs let expected = "7146e789a83077202ab129d461959016" let result = with-env $e { generate_site_conf $primary } | open --raw | hash md5 assert equal $expected $result } + + +#====================================================================================================================== +# update_site_conf +#====================================================================================================================== + +def update_site_conf_e [ + --acme: string + certs: string +] { + { + BF_PROXY_SSL_CERTS: $certs + BF_PROXY_GETSSL_CFG: $GETSSL_CONF_BASENAME + BF_PROXY_WWW_ACME_CHALLENGE: ($acme | default (random chars)) + } +} + +def update_site_conf_create_blank_file [ + certs: string + primary: string +] { + let cfg = $"($certs)/($primary)/($GETSSL_CONF_BASENAME)" + $cfg | path dirname | mkdir $in + echo $"#(random chars)=(random chars)" | save --force $cfg +} + +export def update_site_conf__outputs_aliases_as_sans [] { + let aliases = [(random chars) (random chars)] + let domain = generate_domain --aliases $aliases + let certs = mktemp -d -t + update_site_conf_create_blank_file $certs $domain.primary + let e = update_site_conf_e $certs + + let result = with-env $e { update_site_conf $domain } | open --raw $in + + assert str contains $result $"SANS=\"($aliases.0),($aliases.1)\"" +} + +export def update_site_conf__outputs_empty_sans_when_no_aliases [] { + let domain = generate_domain | reject aliases + let certs = mktemp -d -t + update_site_conf_create_blank_file $certs $domain.primary + let e = update_site_conf_e $certs + + let result = with-env $e { update_site_conf $domain } | open --raw $in + + assert str contains $result "SANS=\"\"" +} + +export def update_site_conf__outputs_certification_locations [] { + let domain = generate_domain + let certs = mktemp -d -t + update_site_conf_create_blank_file $certs $domain.primary + let e = update_site_conf_e $certs + + let result = with-env $e { update_site_conf $domain } | open --raw $in + + assert str contains $result $"DOMAIN_CERT_LOCATION=\"($certs)/($domain.primary).crt\"" + assert str contains $result $"DOMAIN_KEY_LOCATION=\"($certs)/($domain.primary).key\"" +} + +export def update_site_conf__outputs_acme_challenge [] { + let domain = generate_domain + let certs = mktemp -d -t + update_site_conf_create_blank_file $certs $domain.primary + let acme = random chars + let e = update_site_conf_e --acme $acme $certs + + let result = with-env $e { update_site_conf $domain } | open --raw $in + + assert str contains $result $"ACL=\(\"($acme)\"\)" +} + +export def update_site_conf__outputs_use_single_acl [] { + let domain = generate_domain + let certs = mktemp -d -t + update_site_conf_create_blank_file $certs $domain.primary + let e = update_site_conf_e $certs + + let result = with-env $e { update_site_conf $domain } | open --raw $in + + assert str contains $result "USE_SINGLE_ACL=\"true\"" +} + diff --git a/overlay/etc/nu/scripts/tests/vars.nu b/overlay/etc/nu/scripts/tests/vars.nu index dbfb9b3..e38d97c 100644 --- a/overlay/etc/nu/scripts/tests/vars.nu +++ b/overlay/etc/nu/scripts/tests/vars.nu @@ -1,4 +1,5 @@ export const ETC_TEMPLATES = "/etc/bf/templates" +export const GETSSL_CONF_BASENAME = "getssl.cfg" export const NGINX_SSL_CONF = "/etc/nginx/http.d/ssl.conf" # Generate a random domain record From 82af00dcb5b141cea91e47248186f136621dcde8 Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:52:43 +0000 Subject: [PATCH 57/76] Adding tests for when domain conf values are not set --- overlay/etc/nu/scripts/tests/conf.nu | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 7cfff04..56951ab 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -243,6 +243,19 @@ export def generate_nginx_site_conf__outputs_server_names [] { server_name ($server_names);" } +export def generate_nginx_site_conf__without_aliases_outputs_only_primary_to_server_names [] { + let domain = generate_domain | reject aliases + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result $"# serve HTTP site for these domain names + server_name ($domain.primary);" + assert str contains $result $"# serve HTTPS site for these domain names + server_name ($domain.primary);" +} + export def generate_nginx_site_conf__allows_changes_when_custom_is_true [] { let domain = generate_domain true let sites_dir = mktemp -d -t @@ -263,6 +276,16 @@ export def generate_nginx_site_conf__disallows_changes_when_custom_is_false [] { assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." } +export def generate_nginx_site_conf__disallows_changes_when_custom_is_not_set [] { + let domain = generate_domain | reject custom + let sites_dir = mktemp -d -t + let e = generate_nginx_site_conf_e $sites_dir + + let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in + + assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." +} + export def generate_nginx_site_conf__outputs_nginx_public_when_root [] { let primary = random chars let domain = generate_domain --primary $primary From d3a27d0595727f3a188dd9ee5b21d94bc91f00cd Mon Sep 17 00:00:00 2001 From: bfren Date: Wed, 4 Dec 2024 08:52:50 +0000 Subject: [PATCH 58/76] Adding run.sh --- run.sh | 13 +++++++++++++ test.env | 10 +++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 run.sh diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..6686a27 --- /dev/null +++ b/run.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +IMAGE=`cat VERSION` + +docker buildx build \ + --load \ + --build-arg BF_IMAGE=nginx-proxy \ + --build-arg BF_VERSION=${IMAGE} \ + -f Dockerfile \ + -t nginx-proxy-dev \ + . \ + && \ + docker run -it --env-file ./test.env nginx-proxy-dev sh diff --git a/test.env b/test.env index 1961c35..b298053 100644 --- a/test.env +++ b/test.env @@ -1 +1,9 @@ -BF_PROXY_DOMAIN=localhost \ No newline at end of file +BF_DEBUG=1 +BF_PROXY_AUTO_PRIMARY=test +BF_PROXY_AUTO_UPSTREAM=http://test +BF_PROXY_CLEAN_INSTALL=1 +BF_PROXY_DOMAIN=localhost +BF_PROXY_GETSSL_EMAIL=ben@bcgdesign.com +BF_PROXY_HARDEN=1 +BF_PROXY_SSL_DHPARAM_BITS=1024 +BF_PROXY_SSL_KEY_BITS=1024 \ No newline at end of file From f8d3c33665f94716c8f528b1849499a267048a35 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 6 Dec 2024 17:41:03 +0000 Subject: [PATCH 59/76] Using latest base image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7885b36..96b4bbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.20-6.3.17 +FROM bfren/nginx:nginx1.26-alpine3.21-6.4.0 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" From bed03754a9081afd7f396a468567b9bdeb126f40 Mon Sep 17 00:00:00 2001 From: bfren Date: Mon, 9 Dec 2024 10:54:27 +0000 Subject: [PATCH 60/76] Using latest Nginx build --- overlay/tmp/NGINX_BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overlay/tmp/NGINX_BUILD b/overlay/tmp/NGINX_BUILD index 05147ef..93a4968 100644 --- a/overlay/tmp/NGINX_BUILD +++ b/overlay/tmp/NGINX_BUILD @@ -1 +1 @@ -1.26.2-r0 \ No newline at end of file +1.26.2-r3 \ No newline at end of file From cfc637401da2ec2ae87ac8bd00ec19da9beeac7c Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 13 Dec 2024 11:59:05 +0000 Subject: [PATCH 61/76] Using latest base image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 96b4bbc..297ea66 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM bfren/nginx:nginx1.26-alpine3.21-6.4.0 +FROM bfren/nginx:nginx1.26-alpine3.21-6.4.1 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-nginx-proxy" From fa8db326b5959ace2a818ab17afd2dcd0e0eefc8 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 13 Dec 2024 15:11:00 +0000 Subject: [PATCH 62/76] Moving nginx conf to its own module --- overlay/etc/bf/init.d/21-nginx-conf.nu | 6 + overlay/etc/bf/init.d/21-ssl-conf.nu | 6 - overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu | 75 ---- overlay/etc/nu/scripts/bf/nginx/proxy/init.nu | 3 +- .../nu/scripts/bf/nginx/proxy/maintenance.nu | 0 overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu | 1 + .../etc/nu/scripts/bf/nginx/proxy/nginx.nu | 76 ++++ overlay/etc/nu/scripts/tests/conf.nu | 350 ----------------- overlay/etc/nu/scripts/tests/mod.nu | 1 + overlay/etc/nu/scripts/tests/nginx.nu | 354 ++++++++++++++++++ 10 files changed, 440 insertions(+), 432 deletions(-) create mode 100644 overlay/etc/bf/init.d/21-nginx-conf.nu delete mode 100644 overlay/etc/bf/init.d/21-ssl-conf.nu create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/maintenance.nu create mode 100644 overlay/etc/nu/scripts/bf/nginx/proxy/nginx.nu create mode 100644 overlay/etc/nu/scripts/tests/nginx.nu diff --git a/overlay/etc/bf/init.d/21-nginx-conf.nu b/overlay/etc/bf/init.d/21-nginx-conf.nu new file mode 100644 index 0000000..4e5f95a --- /dev/null +++ b/overlay/etc/bf/init.d/21-nginx-conf.nu @@ -0,0 +1,6 @@ +use bf +use bf/nginx/proxy nginx +bf env load + +# Generate Nginx server SSL configuration file +def main []: nothing -> nothing { nginx generate_server_conf } diff --git a/overlay/etc/bf/init.d/21-ssl-conf.nu b/overlay/etc/bf/init.d/21-ssl-conf.nu deleted file mode 100644 index ad387f4..0000000 --- a/overlay/etc/bf/init.d/21-ssl-conf.nu +++ /dev/null @@ -1,6 +0,0 @@ -use bf -use bf/nginx/proxy conf -bf env load - -# Generate SSL configuration file -def main []: nothing -> nothing { conf generate_nginx_server_conf } diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu index 83ac7ef..eabc9df 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/conf.nu @@ -4,78 +4,3 @@ use bf export def get_domains []: nothing -> list> { bf env "PROXY_SSL_CONF" | open --raw $in | from json | get domains } - -# Generate Nginx SSL config -export def generate_nginx_server_conf []: nothing -> nothing { - # get the template name - let template = match (bf env check PROXY_HARDEN) { - true => "modern" - false => "intermediate" - } - - # generate config file - bf write $"Using ($template) SSL configuration." conf/generate_nginx_server_conf - bf esh $"(bf env "ETC_TEMPLATES")/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" - - # return nothing - return -} - -# Generate Nginx site config -export def generate_nginx_site_conf [ - domain: record # the domain record to generate config for -]: nothing -> string { - # get type-hinted variables - let primary: string = $domain | get primary - let upstream: string = $domain | get upstream - let aliases: list = $domain | get -i aliases | default [] - let custom: bool = $domain | get -i custom | default false - let is_root = $primary == (bf env "PROXY_DOMAIN") - - # generate paths - let site = $"(bf env PROXY_SITES)/($primary)" - let conf = $"($site).conf" - let dir = $"($site).d" - let template = $"(bf env "ETC_TEMPLATES")/nginx-(match ($is_root) { true => "root" false => "site" }).conf.esh" - - # ensure custom site config directory exists - if ($dir | bf fs is_not_dir) { mkdir $dir } - - # check for existing configuration file - if ($conf | path exists) { - # if custom config is enabled, don't touch the file - if $custom { - bf write debug " keeping custom configuration." conf/generate_nginx_site_conf - return $conf - } - - # remove file so it can be regenerated - bf write debug " removing file so it can be regenerated." conf/generate_nginx_site_conf - rm -f $conf - } else { - bf write debug " site is not yet configured." conf/generate_nginx_site_conf - } - - # set environment values - let e = { - ACME_CHALLENGE: (bf env "PROXY_ACME_CHALLENGE") - CERTS: (bf env "PROXY_SSL_CERTS") - CUSTOM_CONF: $dir - DHPARAM: (bf env "PROXY_SSL_DHPARAM") - DNS_RESOLVER: (bf env "PROXY_UPSTREAM_DNS_RESOLVER") - DOMAIN_NAME: $primary - DOMAIN_NAMES: ($primary | append $aliases | str join " ") - IS_CUSTOM: ($custom | into string) - NGINX_PUBLIC: (bf env "NGINX_PUBLIC") - NGINX_WWW: (bf env "NGINX_WWW") - REDIRECT_TO_CANONICAL: (bf env check "PROXY_SSL_REDIRECT_TO_CANONICAL" | into string) - UPSTREAM: $upstream - } - - # generate config file - bf write debug " generating file." conf/generate_nginx_site_conf - with-env $e { bf esh $template $conf } - - # return path to config file - return $conf -} diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu index 9934678..b8c6631 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/init.nu @@ -1,6 +1,7 @@ use bf use conf.nu use getssl.nu +use nginx.nu use ssl.nu # Initialise SSL for the specified domain(s). @@ -27,7 +28,7 @@ export def main [ # generate Nginx config bf write " .. generating Nginx configuration file." init - conf generate_nginx_site_conf $x + nginx generate_site_conf $x # generate site getssl conf bf write " .. generating getssl configuration file." init diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/maintenance.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/maintenance.nu new file mode 100644 index 0000000..e69de29 diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu index 50b60af..af2297f 100644 --- a/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu @@ -2,4 +2,5 @@ export module auto.nu export module conf.nu export module getssl.nu export module init.nu +export module nginx.nu export module ssl.nu diff --git a/overlay/etc/nu/scripts/bf/nginx/proxy/nginx.nu b/overlay/etc/nu/scripts/bf/nginx/proxy/nginx.nu new file mode 100644 index 0000000..4c8ec23 --- /dev/null +++ b/overlay/etc/nu/scripts/bf/nginx/proxy/nginx.nu @@ -0,0 +1,76 @@ +use bf + +# Generate Nginx SSL config +export def generate_server_conf []: nothing -> nothing { + # get the template name + let template = match (bf env check PROXY_HARDEN) { + true => "modern" + false => "intermediate" + } + + # generate config file + bf write $"Using ($template) SSL configuration." nginx/generate_server_conf + bf esh $"(bf env "ETC_TEMPLATES")/ssl-($template).conf.esh" "/etc/nginx/http.d/ssl.conf" + + # return nothing + return +} + +# Generate Nginx site config +export def generate_site_conf [ + domain: record # the domain record to generate config for +]: nothing -> string { + # get type-hinted variables + let primary: string = $domain | get primary + let upstream: string = $domain | get upstream + let aliases: list = $domain | get -i aliases | default [] + let custom: bool = $domain | get -i custom | default false + let is_root = $primary == (bf env "PROXY_DOMAIN") + + # generate paths + let site = $"(bf env PROXY_SITES)/($primary)" + let conf = $"($site).conf" + let dir = $"($site).d" + let template = $"(bf env "ETC_TEMPLATES")/nginx-(match ($is_root) { true => "root" false => "site" }).conf.esh" + + # ensure custom site config directory exists + if ($dir | bf fs is_not_dir) { mkdir $dir } + + # check for existing configuration file + if ($conf | path exists) { + # if custom config is enabled, don't touch the file + if $custom { + bf write debug " keeping custom configuration." nginx/generate_site_conf + return $conf + } + + # remove file so it can be regenerated + bf write debug " removing file so it can be regenerated." nginx/generate_site_conf + rm -f $conf + } else { + bf write debug " site is not yet configured." nginx/generate_site_conf + } + + # set environment values + let e = { + ACME_CHALLENGE: (bf env "PROXY_ACME_CHALLENGE") + CERTS: (bf env "PROXY_SSL_CERTS") + CUSTOM_CONF: $dir + DHPARAM: (bf env "PROXY_SSL_DHPARAM") + DNS_RESOLVER: (bf env "PROXY_UPSTREAM_DNS_RESOLVER") + DOMAIN_NAME: $primary + DOMAIN_NAMES: ($primary | append $aliases | str join " ") + IS_CUSTOM: ($custom | into string) + NGINX_PUBLIC: (bf env "NGINX_PUBLIC") + NGINX_WWW: (bf env "NGINX_WWW") + REDIRECT_TO_CANONICAL: (bf env check "PROXY_SSL_REDIRECT_TO_CANONICAL" | into string) + UPSTREAM: $upstream + } + + # generate config file + bf write debug " generating file." nginx/generate_site_conf + with-env $e { bf esh $template $conf } + + # return path to config file + return $conf +} diff --git a/overlay/etc/nu/scripts/tests/conf.nu b/overlay/etc/nu/scripts/tests/conf.nu index 56951ab..c576a92 100644 --- a/overlay/etc/nu/scripts/tests/conf.nu +++ b/overlay/etc/nu/scripts/tests/conf.nu @@ -20,353 +20,3 @@ export def get_domains__returns_list_of_domains [] { assert equal $conf.domains $result } - - -#====================================================================================================================== -# generate_nginx_server_conf -#====================================================================================================================== - -def generate_nginx_ssl_conf_e [ - --harden # Optional harden switch -] { - { - BF_ETC_TEMPLATES: $ETC_TEMPLATES - BF_PROXY_HARDEN: (match $harden { true => "1", false => "" }) - } -} - -export def generate_nginx_ssl_conf__outputs_intermediate_conf [] { - let e = generate_nginx_ssl_conf_e - let expected = "c8864a579b0ec2cb4070f27affb4e05f" - - let result = with-env $e { generate_nginx_server_conf } | open --raw $NGINX_SSL_CONF | hash md5 - - assert equal $expected $result -} - -export def generate_nginx_ssl_conf__outputs_modern_conf [] { - let e = generate_nginx_ssl_conf_e --harden - let expected = "73f99a3458030a8dae265a10355032e3" - - let result = with-env $e { generate_nginx_server_conf } | open --raw $NGINX_SSL_CONF | hash md5 - - assert equal $expected $result -} - - -#====================================================================================================================== -# generate_nginx_site_conf -#====================================================================================================================== - -def generate_nginx_site_conf_e [ - --acme-challenge: string - --certs: string - --dhparam: string - --nginx-public: string - --nginx-www: string - --redirect-to-canonical - --resolver: string - --root-domain: string - sites_dir -] { - { - BF_ETC_TEMPLATES: $ETC_TEMPLATES - BF_NGINX_PUBLIC: ($nginx_public | default (random chars)) - BF_NGINX_WWW: ($nginx_www | default (random chars)) - BF_PROXY_ACME_CHALLENGE: ($acme_challenge | default (random chars)) - BF_PROXY_DOMAIN: ($root_domain | default (random chars)) - BF_PROXY_SSL_CERTS: ($certs | default (random chars)) - BF_PROXY_SSL_DHPARAM: ($dhparam | default (random chars)) - BF_PROXY_SSL_REDIRECT_TO_CANONICAL: (match $redirect_to_canonical { true => "1" false => "0" }) - BF_PROXY_SITES: $sites_dir - BF_PROXY_UPSTREAM_DNS_RESOLVER: ($resolver | default (random chars)) - } -} - -export def generate_nginx_site_conf__creates_site_directory_when_does_not_exist [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = $"/tmp/(random chars)" - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | echo $sites_dir | path exists - - assert equal true $result -} - -export def generate_nginx_site_conf__keeps_config_when_custom_is_true [] { - let primary = random chars - let domain = generate_domain --primary $primary true - let sites_dir = mktemp -d -t - let content = random chars - $content | save --force $"($sites_dir)/($primary).conf" - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert equal $content $result -} - -export def generate_nginx_site_conf__regenerates_config_when_custom_is_false [] { - let primary = random chars - let domain = generate_domain --primary $primary false - let sites_dir = mktemp -d -t - let content = random chars - $content | save --force $"($sites_dir)/($primary).conf" - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert not equal $content $result -} - -export def generate_nginx_site_conf__outputs_acme_challenge [] { - let domain = generate_domain - let sites_dir = mktemp -d -t - let acme_challenge = random chars - let e = generate_nginx_site_conf_e --acme-challenge $acme_challenge $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"location ^~ /($acme_challenge) {" -} - -export def generate_nginx_site_conf__outputs_acme_challenge_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let acme_challenge = random chars - let e = generate_nginx_site_conf_e --acme-challenge $acme_challenge --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"location ^~ /($acme_challenge) {" -} - -export def generate_nginx_site_conf__outputs_ssl_certs [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let certs = random chars - let e = generate_nginx_site_conf_e --certs $certs $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"ssl_trusted_certificate ($certs)/($primary)/chain.crt;" - assert str contains $result $"ssl_certificate ($certs)/($primary)/fullchain.crt;" - assert str contains $result $"ssl_certificate_key ($certs)/($primary).key;" -} - -export def generate_nginx_site_conf__outputs_ssl_certs_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let certs = random chars - let e = generate_nginx_site_conf_e --certs $certs --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"ssl_trusted_certificate ($certs)/($primary)/chain.crt;" - assert str contains $result $"ssl_certificate ($certs)/($primary)/fullchain.crt;" - assert str contains $result $"ssl_certificate_key ($certs)/($primary).key;" -} - -export def generate_nginx_site_conf__includes_custom_conf [] { - let primary = random chars - let domain = generate_domain --primary $primary true - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"include ($sites_dir)/($primary).d/*.conf;" -} - -export def generate_nginx_site_conf__includes_custom_conf_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary true - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"include ($sites_dir)/($primary).d/*.conf;" -} - -export def generate_nginx_site_conf__outputs_dhparam [] { - let domain = generate_domain - let sites_dir = mktemp -d -t - let dhparam = random chars - let e = generate_nginx_site_conf_e --dhparam $dhparam $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"ssl_dhparam ($dhparam);" -} - -export def generate_nginx_site_conf__outputs_dhparam_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let dhparam = random chars - let e = generate_nginx_site_conf_e --dhparam $dhparam --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"ssl_dhparam ($dhparam);" -} - -export def generate_nginx_site_conf__outputs_dns_resolver [] { - let domain = generate_domain - let sites_dir = mktemp -d -t - let resolver = random chars - let e = generate_nginx_site_conf_e --resolver $resolver $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"resolver ($resolver) valid=30s;" -} - -export def generate_nginx_site_conf__outputs_server_names [] { - let primary = random chars - let aliases = [(random chars) (random chars) (random chars)] - let server_names = $primary | append $aliases | str join " " - let domain = generate_domain --primary $primary --aliases $aliases - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"# serve HTTP site for these domain names - server_name ($server_names);" - assert str contains $result $"# serve HTTPS site for these domain names - server_name ($server_names);" -} - -export def generate_nginx_site_conf__without_aliases_outputs_only_primary_to_server_names [] { - let domain = generate_domain | reject aliases - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"# serve HTTP site for these domain names - server_name ($domain.primary);" - assert str contains $result $"# serve HTTPS site for these domain names - server_name ($domain.primary);" -} - -export def generate_nginx_site_conf__allows_changes_when_custom_is_true [] { - let domain = generate_domain true - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result "# You can make changes to this file." -} - -export def generate_nginx_site_conf__disallows_changes_when_custom_is_false [] { - let domain = generate_domain false - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." -} - -export def generate_nginx_site_conf__disallows_changes_when_custom_is_not_set [] { - let domain = generate_domain | reject custom - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." -} - -export def generate_nginx_site_conf__outputs_nginx_public_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let nginx_public = random chars - let e = generate_nginx_site_conf_e --nginx-public $nginx_public --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"root ($nginx_public);" -} - -export def generate_nginx_site_conf__outputs_nginx_www [] { - let domain = generate_domain - let sites_dir = mktemp -d -t - let nginx_www = random chars - let e = generate_nginx_site_conf_e --nginx-www $nginx_www $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"root ($nginx_www);" -} - -export def generate_nginx_site_conf__outputs_nginx_www_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let nginx_www = random chars - let e = generate_nginx_site_conf_e --nginx-www $nginx_www --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"root ($nginx_www);" -} - -export def generate_nginx_site_conf__redirects_to_canonical [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e --redirect-to-canonical $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"return 301 https://($primary)$request_uri;" - assert str contains $result $"if \($host != ($primary)\) { - return 301 https://($primary)$request_uri; - }" -} - -export def generate_nginx_site_conf__redirects_to_canonical_when_root [] { - let primary = random chars - let domain = generate_domain --primary $primary - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e --root-domain $primary $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"return 301 https://($primary)$request_uri;" - assert str contains $result $"if \($host != ($primary)\) { - return 301 https://($primary)$request_uri; - }" -} - -export def generate_nginx_site_conf__redirects_to_current_host [] { - let domain = generate_domain - let sites_dir = mktemp -d -t - let e = generate_nginx_site_conf_e $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result "return 301 https://$host$request_uri;" -} - -export def generate_nginx_site_conf__outputs_upstream [] { - let upstream = random chars - let domain = generate_domain --upstream $upstream - let sites_dir = mktemp -d -t - let nginx_www = random chars - let e = generate_nginx_site_conf_e --nginx-www $nginx_www $sites_dir - - let result = with-env $e { generate_nginx_site_conf $domain } | open --raw $in - - assert str contains $result $"set $upstream ($upstream);" -} diff --git a/overlay/etc/nu/scripts/tests/mod.nu b/overlay/etc/nu/scripts/tests/mod.nu index beff031..6979681 100644 --- a/overlay/etc/nu/scripts/tests/mod.nu +++ b/overlay/etc/nu/scripts/tests/mod.nu @@ -2,5 +2,6 @@ export module auto.nu export module conf.nu export module getssl.nu export module init.nu +export module nginx.nu export module ssl.nu export module vars.nu diff --git a/overlay/etc/nu/scripts/tests/nginx.nu b/overlay/etc/nu/scripts/tests/nginx.nu new file mode 100644 index 0000000..763f0de --- /dev/null +++ b/overlay/etc/nu/scripts/tests/nginx.nu @@ -0,0 +1,354 @@ +use std assert +use bf +use bf/nginx/proxy nginx * +use vars.nu * + + +#====================================================================================================================== +# generate_server_conf +#====================================================================================================================== + +def generate_nginx_ssl_conf_e [ + --harden # Optional harden switch +] { + { + BF_ETC_TEMPLATES: $ETC_TEMPLATES + BF_PROXY_HARDEN: (match $harden { true => "1", false => "" }) + } +} + +export def generate_nginx_ssl_conf__outputs_intermediate_conf [] { + let e = generate_nginx_ssl_conf_e + let expected = "c8864a579b0ec2cb4070f27affb4e05f" + + let result = with-env $e { generate_server_conf } | open --raw $NGINX_SSL_CONF | hash md5 + + assert equal $expected $result +} + +export def generate_nginx_ssl_conf__outputs_modern_conf [] { + let e = generate_nginx_ssl_conf_e --harden + let expected = "73f99a3458030a8dae265a10355032e3" + + let result = with-env $e { generate_server_conf } | open --raw $NGINX_SSL_CONF | hash md5 + + assert equal $expected $result +} + + +#====================================================================================================================== +# generate_site_conf +#====================================================================================================================== + +def generate_site_conf_e [ + --acme-challenge: string + --certs: string + --dhparam: string + --nginx-public: string + --nginx-www: string + --redirect-to-canonical + --resolver: string + --root-domain: string + sites_dir +] { + { + BF_ETC_TEMPLATES: $ETC_TEMPLATES + BF_NGINX_PUBLIC: ($nginx_public | default (random chars)) + BF_NGINX_WWW: ($nginx_www | default (random chars)) + BF_PROXY_ACME_CHALLENGE: ($acme_challenge | default (random chars)) + BF_PROXY_DOMAIN: ($root_domain | default (random chars)) + BF_PROXY_SSL_CERTS: ($certs | default (random chars)) + BF_PROXY_SSL_DHPARAM: ($dhparam | default (random chars)) + BF_PROXY_SSL_REDIRECT_TO_CANONICAL: (match $redirect_to_canonical { true => "1" false => "0" }) + BF_PROXY_SITES: $sites_dir + BF_PROXY_UPSTREAM_DNS_RESOLVER: ($resolver | default (random chars)) + } +} + +export def generate_site_conf__creates_site_directory_when_does_not_exist [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = $"/tmp/(random chars)" + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | echo $sites_dir | path exists + + assert equal true $result +} + +export def generate_site_conf__keeps_config_when_custom_is_true [] { + let primary = random chars + let domain = generate_domain --primary $primary true + let sites_dir = mktemp -d -t + let content = random chars + $content | save --force $"($sites_dir)/($primary).conf" + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert equal $content $result +} + +export def generate_site_conf__regenerates_config_when_custom_is_false [] { + let primary = random chars + let domain = generate_domain --primary $primary false + let sites_dir = mktemp -d -t + let content = random chars + $content | save --force $"($sites_dir)/($primary).conf" + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert not equal $content $result +} + +export def generate_site_conf__outputs_acme_challenge [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let acme_challenge = random chars + let e = generate_site_conf_e --acme-challenge $acme_challenge $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"location ^~ /($acme_challenge) {" +} + +export def generate_site_conf__outputs_acme_challenge_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let acme_challenge = random chars + let e = generate_site_conf_e --acme-challenge $acme_challenge --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"location ^~ /($acme_challenge) {" +} + +export def generate_site_conf__outputs_ssl_certs [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let certs = random chars + let e = generate_site_conf_e --certs $certs $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_trusted_certificate ($certs)/($primary)/chain.crt;" + assert str contains $result $"ssl_certificate ($certs)/($primary)/fullchain.crt;" + assert str contains $result $"ssl_certificate_key ($certs)/($primary).key;" +} + +export def generate_site_conf__outputs_ssl_certs_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let certs = random chars + let e = generate_site_conf_e --certs $certs --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_trusted_certificate ($certs)/($primary)/chain.crt;" + assert str contains $result $"ssl_certificate ($certs)/($primary)/fullchain.crt;" + assert str contains $result $"ssl_certificate_key ($certs)/($primary).key;" +} + +export def generate_site_conf__includes_custom_conf [] { + let primary = random chars + let domain = generate_domain --primary $primary true + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"include ($sites_dir)/($primary).d/*.conf;" +} + +export def generate_site_conf__includes_custom_conf_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary true + let sites_dir = mktemp -d -t + let e = generate_site_conf_e --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"include ($sites_dir)/($primary).d/*.conf;" +} + +export def generate_site_conf__outputs_dhparam [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let dhparam = random chars + let e = generate_site_conf_e --dhparam $dhparam $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_dhparam ($dhparam);" +} + +export def generate_site_conf__outputs_dhparam_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let dhparam = random chars + let e = generate_site_conf_e --dhparam $dhparam --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"ssl_dhparam ($dhparam);" +} + +export def generate_site_conf__outputs_dns_resolver [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let resolver = random chars + let e = generate_site_conf_e --resolver $resolver $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"resolver ($resolver) valid=30s;" +} + +export def generate_site_conf__outputs_server_names [] { + let primary = random chars + let aliases = [(random chars) (random chars) (random chars)] + let server_names = $primary | append $aliases | str join " " + let domain = generate_domain --primary $primary --aliases $aliases + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"# serve HTTP site for these domain names + server_name ($server_names);" + assert str contains $result $"# serve HTTPS site for these domain names + server_name ($server_names);" +} + +export def generate_site_conf__without_aliases_outputs_only_primary_to_server_names [] { + let domain = generate_domain | reject aliases + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"# serve HTTP site for these domain names + server_name ($domain.primary);" + assert str contains $result $"# serve HTTPS site for these domain names + server_name ($domain.primary);" +} + +export def generate_site_conf__allows_changes_when_custom_is_true [] { + let domain = generate_domain true + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result "# You can make changes to this file." +} + +export def generate_site_conf__disallows_changes_when_custom_is_false [] { + let domain = generate_domain false + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." +} + +export def generate_site_conf__disallows_changes_when_custom_is_not_set [] { + let domain = generate_domain | reject custom + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result "# WARNING: This file is generated. Do not make changes to this file." +} + +export def generate_site_conf__outputs_nginx_public_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let nginx_public = random chars + let e = generate_site_conf_e --nginx-public $nginx_public --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"root ($nginx_public);" +} + +export def generate_site_conf__outputs_nginx_www [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let nginx_www = random chars + let e = generate_site_conf_e --nginx-www $nginx_www $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"root ($nginx_www);" +} + +export def generate_site_conf__outputs_nginx_www_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let nginx_www = random chars + let e = generate_site_conf_e --nginx-www $nginx_www --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"root ($nginx_www);" +} + +export def generate_site_conf__redirects_to_canonical [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let e = generate_site_conf_e --redirect-to-canonical $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"return 301 https://($primary)$request_uri;" + assert str contains $result $"if \($host != ($primary)\) { + return 301 https://($primary)$request_uri; + }" +} + +export def generate_site_conf__redirects_to_canonical_when_root [] { + let primary = random chars + let domain = generate_domain --primary $primary + let sites_dir = mktemp -d -t + let e = generate_site_conf_e --root-domain $primary $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"return 301 https://($primary)$request_uri;" + assert str contains $result $"if \($host != ($primary)\) { + return 301 https://($primary)$request_uri; + }" +} + +export def generate_site_conf__redirects_to_current_host [] { + let domain = generate_domain + let sites_dir = mktemp -d -t + let e = generate_site_conf_e $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result "return 301 https://$host$request_uri;" +} + +export def generate_site_conf__outputs_upstream [] { + let upstream = random chars + let domain = generate_domain --upstream $upstream + let sites_dir = mktemp -d -t + let nginx_www = random chars + let e = generate_site_conf_e --nginx-www $nginx_www $sites_dir + + let result = with-env $e { generate_site_conf $domain } | open --raw $in + + assert str contains $result $"set $upstream ($upstream);" +} From 06cb2d06d40c190a2460062c4bc1889d6a96d199 Mon Sep 17 00:00:00 2001 From: bfren Date: Fri, 13 Dec 2024 15:48:33 +0000 Subject: [PATCH 63/76] Adding maintenance module --- overlay/etc/bf/init.d/23-maintenance.nu | 8 ++-- overlay/etc/bf/templates/maintenance.html.esh | 4 +- .../bf/templates/proxy-maintenance.conf.esh | 2 +- .../nu/scripts/bf/nginx/proxy/maintenance.nu | 18 ++++++++ overlay/etc/nu/scripts/bf/nginx/proxy/mod.nu | 1 + overlay/etc/nu/scripts/tests/maintenance.nu | 43 +++++++++++++++++++ overlay/etc/nu/scripts/tests/mod.nu | 1 + 7 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 overlay/etc/nu/scripts/tests/maintenance.nu diff --git a/overlay/etc/bf/init.d/23-maintenance.nu b/overlay/etc/bf/init.d/23-maintenance.nu index 95b2067..bdaf4d9 100644 --- a/overlay/etc/bf/init.d/23-maintenance.nu +++ b/overlay/etc/bf/init.d/23-maintenance.nu @@ -1,11 +1,11 @@ use bf +use bf/nginx/proxy maintenance bf env load -# Generate maintenance page and config +# Generate maintenance helper config and html page def main []: nothing -> nothing { bf write "Generating maintenance files." - bf esh template "/etc/nginx/helpers/proxy-maintenance.conf" - bf esh template $"(bf env NGINX_PUBLIC)/maintenance.html" - + maintenance generate_helper_conf + maintenance generate_html return } diff --git a/overlay/etc/bf/templates/maintenance.html.esh b/overlay/etc/bf/templates/maintenance.html.esh index 63ad1ad..3cad07a 100644 --- a/overlay/etc/bf/templates/maintenance.html.esh +++ b/overlay/etc/bf/templates/maintenance.html.esh @@ -11,9 +11,9 @@

Maintenance

The site you requested is temporarily down for maintenance. Please try again later.

-

This page will auto-refresh in <%= "${PROXY_MAINTENANCE_REFRESH_SECONDS}" %>s.

+

This page will auto-refresh in <%= "${REFRESH_SECONDS}" %>s.