Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLeitwolf112026-10-15 18:28:17 +0300
committerLeitwolf112026-10-15 18:28:17 +0300
commita460c4c7e922f37705b2be3f1fa7c789f514cd51 (patch)
treebf5eeb2c283222c96890c37078537e1251f32f8e
parent18951f0c5c6e3f54ccd8757cec040a40bd2b5068 (diff)
downloadwebsite-a460c4c7e922f37705b2be3f1fa7c789f514cd51.tar.gz
Treat tala.run as an HSTS-preloaded domain
.run has no HSTS requirement of its own, but tala.run is served as if it had one: every HTTPS response of tala.run, www, talac, tazel and forum sends max-age=63072000; includeSubDomains; preload, and plain HTTP only answers the ACME challenge and otherwise redirects to HTTPS. A test checks both for every tala.run block of the three Nginx files. The redirects of the former .xyz domain keep their header.
-rw-r--r--frontend/tests/site-integrity.test.mjs21
-rw-r--r--ops/nginx/forum.conf2
-rw-r--r--ops/nginx/tala-maintenance.conf2
-rw-r--r--ops/nginx/tala.conf8
4 files changed, 27 insertions, 6 deletions
diff --git a/frontend/tests/site-integrity.test.mjs b/frontend/tests/site-integrity.test.mjs
index 588755c..922c03d 100644
--- a/frontend/tests/site-integrity.test.mjs
+++ b/frontend/tests/site-integrity.test.mjs
@@ -309,3 +309,24 @@ test("the former domain is left to the server: the page carries no notice about
assert.doesNotMatch(app, /domainNotice|domain-notice|onDepartingDomain/);
assert.doesNotMatch(read("src/styles/site.css"), /\.domain-notice/);
});
+
+test("every tala.run host behaves as if HSTS were preloaded for its top-level domain", () => {
+ for (const file of ["tala.conf", "forum.conf", "tala-maintenance.conf"]) {
+ const config = readFileSync(join(websiteRoot, "ops/nginx", file), "utf8");
+ const blocks = config.split(/\nserver \{/).slice(1);
+ for (const block of blocks) {
+ const names = block.match(/server_name ([^;]+);/)?.[1] ?? "";
+ if (!/\btala\.run\b/.test(names)) continue;
+ if (/listen 443/.test(block)) {
+ assert.match(
+ block,
+ /add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;/,
+ `${file}: ${names} must send the preload header`,
+ );
+ } else {
+ // Plain HTTP answers only the ACME challenge and otherwise sends the visitor to HTTPS.
+ assert.match(block, /return 308 https:\/\//, `${file}: ${names} must redirect to HTTPS`);
+ }
+ }
+ }
+});
diff --git a/ops/nginx/forum.conf b/ops/nginx/forum.conf
index e77be65..5ae383c 100644
--- a/ops/nginx/forum.conf
+++ b/ops/nginx/forum.conf
@@ -29,7 +29,7 @@ server {
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
add_header X-Robots-Tag "noindex, nofollow" always;
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'" always;
diff --git a/ops/nginx/tala-maintenance.conf b/ops/nginx/tala-maintenance.conf
index d712808..35e78d9 100644
--- a/ops/nginx/tala-maintenance.conf
+++ b/ops/nginx/tala-maintenance.conf
@@ -29,7 +29,7 @@ server {
add_header Retry-After "3600" always;
add_header Cache-Control "no-store" always;
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; frame-ancestors 'none'" always;
diff --git a/ops/nginx/tala.conf b/ops/nginx/tala.conf
index 6bb7f83..7f67bce 100644
--- a/ops/nginx/tala.conf
+++ b/ops/nginx/tala.conf
@@ -57,7 +57,7 @@ server {
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
@@ -120,7 +120,7 @@ server {
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
@@ -166,7 +166,7 @@ server {
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
@@ -207,7 +207,7 @@ server {
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
return 308 https://tala.run$request_uri;
}