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

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLeitwolf2026-11-06 09:36:33 +0300
committerGitHub2026-11-06 09:36:33 +0300
commit9660d2c5f0bda5d666ed076a0e18d5cb2dbe881d (patch)
tree52f3eb670a8fb6246de982b219d10a0346526736
parentfc3246f3eb404bc2c3132691d1161a95c5bfac76 (diff)
parent7d1ef624fd8842acab54fce6373b4ad2bbb25eb9 (diff)
downloadwebsite-9660d2c5f0bda5d666ed076a0e18d5cb2dbe881d.tar.gz
Merge pull request #55 from Progmasoft/ops/cloudflare-analytics
Let Cloudflare Web Analytics run on the Tala sites
-rw-r--r--Documents/ARCHITECTURE.md6
-rw-r--r--Documents/OPERATIONS.md12
-rw-r--r--ops/nginx/tala.conf9
3 files changed, 17 insertions, 10 deletions
diff --git a/Documents/ARCHITECTURE.md b/Documents/ARCHITECTURE.md
index 53a32ac..40d72eb 100644
--- a/Documents/ARCHITECTURE.md
+++ b/Documents/ARCHITECTURE.md
@@ -105,5 +105,7 @@ allows only its own script, stylesheet and two images.
## Security headers
Nginx sends a content security policy that allows only same-origin resources, plus HSTS, `X-Content-Type-Options`,
-`X-Frame-Options: DENY` and a referrer policy. The policy has no exception for third-party scripts; a script injected
-by an intermediary, such as an analytics beacon added by a CDN, is blocked by the browser.
+`X-Frame-Options: DENY` and a referrer policy. The policy of the four hosts of the site has one exception: Cloudflare
+Web Analytics, which Cloudflare adds to every page. Its beacon loads from `https://static.cloudflareinsights.com` and
+reports to `https://cloudflareinsights.com` and to `/cdn-cgi/rum` on the same host. Any other script injected by an
+intermediary is blocked by the browser. The forum placeholder keeps a policy of its own, same-origin only.
diff --git a/Documents/OPERATIONS.md b/Documents/OPERATIONS.md
index ce1a4ee..cf4db71 100644
--- a/Documents/OPERATIONS.md
+++ b/Documents/OPERATIONS.md
@@ -250,10 +250,14 @@ static files and 404 for other paths. Expected legacy redirect responses are
308. In maintenance mode the main domain answers 503 with `Retry-After`. A 200
from a retired login or registry route is a regression.
-Neither the static site nor the forum placeholder should send personal data
-to a third-party analytics service. The content security policy allows
-same-origin scripts only, so a script added by an intermediary is blocked by
-the browser rather than run. Theme and language preferences are kept
+The static site uses Cloudflare Web Analytics, which counts page views without
+cookies and without a fingerprint of the visitor. Its content security policy
+allows same-origin scripts and that beacon only: the beacon loads from
+`https://static.cloudflareinsights.com` and reports to
+`https://cloudflareinsights.com` and `/cdn-cgi/rum`. Any other script added by
+an intermediary is blocked by the browser rather than run. The forum
+placeholder allows same-origin scripts only and sends nothing to an analytics
+service. Theme and language preferences are kept
locally in the browser. Nginx and API logs still need normal retention
and access-control practices, but this repository does not define an account
database or a user profile store.
diff --git a/ops/nginx/tala.conf b/ops/nginx/tala.conf
index 2b75fdd..a8164ff 100644
--- a/ops/nginx/tala.conf
+++ b/ops/nginx/tala.conf
@@ -7,6 +7,7 @@
# name. xsharp-lang.xyz, the former domain, answers with a permanent redirect to
# the same path on tala.run. tazel.tala.run, where the build system was
# documented, answers with a permanent redirect to tazel.net, its own site.
+# The policies allow Cloudflare Web Analytics, which Cloudflare adds to each page.
server {
listen 80 default_server;
@@ -57,7 +58,7 @@ server {
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
- 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 Content-Security-Policy "default-src 'self'; script-src 'self' https://static.cloudflareinsights.com; connect-src 'self' https://cloudflareinsights.com; 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=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
@@ -134,7 +135,7 @@ server {
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
- 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 Content-Security-Policy "default-src 'self'; script-src 'self' https://static.cloudflareinsights.com; connect-src 'self' https://cloudflareinsights.com; 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=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
@@ -194,7 +195,7 @@ server {
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
- 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 Content-Security-Policy "default-src 'self'; script-src 'self' https://static.cloudflareinsights.com; connect-src 'self' https://cloudflareinsights.com; 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=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
@@ -254,7 +255,7 @@ server {
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
- 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 Content-Security-Policy "default-src 'self'; script-src 'self' https://static.cloudflareinsights.com; connect-src 'self' https://cloudflareinsights.com; 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=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;