diff --git a/README.md b/README.md index dc8c225..ca06c4e 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Prerequisites: - Traefik attached to the existing external Docker network `internal`; - a Traefik HTTPS entrypoint named `websecure`; - a certificate resolver named `netcup`; -- DNS for `toolbax.add-ideas.de` pointing to that Traefik instance; and +- DNS for `toolbox.add-ideas.de` pointing to that Traefik instance; and - outbound HTTPS access to `git.add-ideas.de` while the image is built. Deploy a fresh clone with: @@ -90,11 +90,11 @@ docker compose ps ``` No host port is published. Traefik routes -`https://toolbax.add-ideas.de` to nginx on the shared network at port 8080 and +`https://toolbox.add-ideas.de` to nginx on the shared network at port 8080 and obtains its TLS certificate through `netcup`. The hostname, network, resolver, release version, and matching checksum can be overridden through environment variables; copy `.env.example` to `.env` only when an override is needed. For -example, set `TOOLBOX_HOST=toolbox.add-ideas.de` if that spelling is preferred. +example, set `TOOLBOX_HOST=staging.toolbox.add-ideas.de` for a staging host. The external network is deliberately not created by this project. Creating a private project-local network would prevent an independently managed Traefik diff --git a/deploy/nginx.conf b/deploy/nginx.conf index 2b27362..b90d21f 100644 --- a/deploy/nginx.conf +++ b/deploy/nginx.conf @@ -1,6 +1,6 @@ map $uri $toolbox_cache_control { default "no-cache"; - ~^/(?:.*/)?assets/.*-[A-Za-z0-9_-]{8,}\.[^/]+$ "public, max-age=31536000, immutable"; + "~^/(?:.*/)?assets/.*-[A-Za-z0-9_-]{8,}\.[^/]+$" "public, max-age=31536000, immutable"; } server { diff --git a/scripts/deployment.test.ts b/scripts/deployment.test.ts index 41b34a5..eb95b75 100644 --- a/scripts/deployment.test.ts +++ b/scripts/deployment.test.ts @@ -8,6 +8,10 @@ const containerfile = readFileSync( path.join(projectRoot, 'Containerfile.release'), 'utf8' ); +const nginxConfig = readFileSync( + path.join(projectRoot, 'deploy', 'nginx.conf'), + 'utf8' +); const releaseLock = JSON.parse( readFileSync(path.join(projectRoot, 'release', 'toolbox.lock.json'), 'utf8') ) as { releaseVersion: string }; @@ -51,7 +55,7 @@ describe('production deployment', () => { 'traefik.docker.network: "${TRAEFIK_NETWORK:-internal}"' ); expect(compose).toContain( - 'traefik.http.routers.addideas-toolbox.rule: "Host(`${TOOLBOX_HOST:-toolbax.add-ideas.de}`)"' + 'traefik.http.routers.addideas-toolbox.rule: "Host(`${TOOLBOX_HOST:-toolbox.add-ideas.de}`)"' ); expect(compose).toContain( 'traefik.http.routers.addideas-toolbox.entrypoints: websecure' @@ -62,4 +66,11 @@ describe('production deployment', () => { expect(compose).toContain('external: true'); expect(compose).not.toMatch(/^\s+ports:/mu); }); + + it('quotes nginx regular expressions that contain brace quantifiers', () => { + expect(nginxConfig).toContain( + '"~^/(?:.*/)?assets/.*-[A-Za-z0-9_-]{8,}\\.[^/]+$"' + ); + expect(nginxConfig).not.toMatch(/^\s*~[^\n]*\{\d/mu); + }); });