summaryrefslogtreecommitdiff
path: root/linux/nginx/etc
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-08-03 15:47:25 -0500
committerChristian Cleberg <[email protected]>2026-08-03 15:47:25 -0500
commit3e8b89ec7012ab1766b2458a38d5ac32cb748446 (patch)
tree9ac2d7419f5b4e6b609112bcba4c824f84dfb47e /linux/nginx/etc
parent7628832bfe9aaf3deafc2787e596e0ca65b0cad0 (diff)
downloaddotfiles-3e8b89ec7012ab1766b2458a38d5ac32cb748446.tar.gz
dotfiles-3e8b89ec7012ab1766b2458a38d5ac32cb748446.tar.bz2
dotfiles-3e8b89ec7012ab1766b2458a38d5ac32cb748446.zip
nginx: make cleberg.net self-contained on the onion
Serve images same-origin via a `location /img/ { alias /var/www/img/; }` block on cleberg.net, so the .onion no longer pulls subresources from the clearnet. Deliberately an nginx alias rather than a filesystem symlink. A symlink at /var/www/cleberg.net/img worked but was destroyed by the very next deploy -- the site deploys with `rsync --delete`, which removes anything in the destination that is not in the source tree, and that silently 404'd every image on the site. Config-level aliasing cannot be removed by a deploy. Tighten the cleberg.* CSP now that the site loads nothing cross-origin. The weblorg source was changed to emit root-relative stylesheet and image URLs, and the bubbles.town script was dropped, so parsing all deployed HTML returns zero absolute subresources. Dropped img-src https://img.cleberg.net, style-src and font-src https://cleberg.net, and script-src/connect-src https://bubbles.town; the policy is now default-src 'self' with no host allowances. upgrade-insecure-requests stays omitted: this vhost also serves the .onion over plain http, where it would upgrade same-origin subresource URLs to https and break them. Set Referrer-Policy to same-origin, restoring the value Cloudflare's security-headers toggle had been supplying. Removing that toggle silently regressed it to strict-origin-when-cross-origin, which still sends the origin to external sites; same-origin sends no referrer cross-origin at all. Verified over a real Tor circuit: article pages carry 4 relative subresources and 0 absolute, and images serve 200 from the onion.
Diffstat (limited to 'linux/nginx/etc')
-rw-r--r--linux/nginx/etc/nginx/conf.d/cleberg.net.conf15
-rw-r--r--linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf51
2 files changed, 52 insertions, 14 deletions
diff --git a/linux/nginx/etc/nginx/conf.d/cleberg.net.conf b/linux/nginx/etc/nginx/conf.d/cleberg.net.conf
index fb24a37..cc6aa19 100644
--- a/linux/nginx/etc/nginx/conf.d/cleberg.net.conf
+++ b/linux/nginx/etc/nginx/conf.d/cleberg.net.conf
@@ -20,6 +20,21 @@ server {
add_header Onion-Location "http://paske4urhs6nttrtlkuwa5cowum3fjkc6yv6kl4ncx3mjxcd77764nqd.onion$request_uri" always;
+ # Images live in the img.cleberg.net docroot and are served same-origin here
+ # so the .onion is self-contained (see the onion-containment work, 2026-08-03).
+ #
+ # This is an nginx alias, NOT a filesystem symlink, on purpose. A symlink at
+ # /var/www/cleberg.net/img worked but was DESTROYED by the very next deploy:
+ # the site deploys with `rsync --delete`, which removes anything in the
+ # destination that is not in the source tree. That silently 404'd every image
+ # on the site. An alias lives in nginx config, so no deploy can remove it.
+ location /img/ {
+ alias /var/www/img/;
+ # This block sets no add_header of its own, so it inherits the
+ # server-level security headers. Do not add one without re-including
+ # custom.d/security/headers_in_location.conf -- nginx does not merge.
+ }
+
location /org/ {
internal;
alias /var/www/cleberg.net/org/;
diff --git a/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf b/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf
index f8a5e84..737eea3 100644
--- a/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf
+++ b/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf
@@ -53,20 +53,30 @@ map $sent_http_content_type $content_security_policy {
~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' data:; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'";
}
-# cleberg.* only. Mirrors what the site actually loads, verified by grepping
-# the served HTML: <img src> -> img.cleberg.net (151), <script src> ->
-# bubbles.town (174), stylesheets -> https://cleberg.net (180, absolute).
-#
-# `https://cleberg.net` must be allowed explicitly: the HTML uses ABSOLUTE
-# stylesheet URLs, so on the .onion (a different origin) they are cross-origin
-# and 'self' would block them.
-#
-# `upgrade-insecure-requests` is deliberately OMITTED: this vhost also serves
-# the .onion over plain http, where UIR would upgrade same-origin subresource
-# URLs to https and break them. Cloudflare already sets UIR on the clearnet
-# path. See the onion self-containment note in the project record.
+# cleberg.* only.
+#
+# TIGHTENED 2026-08-03 after the weblorg source was made onion-self-contained.
+# Stylesheets and images are now ROOT-RELATIVE, so they resolve to whichever
+# origin served the page and `'self'` covers them on both clearnet and the
+# .onion. Verified against the deployed HTML (181 files, parsed): **0** absolute
+# stylesheet refs, **0** absolute `img.cleberg.net` subresource refs.
+# Consequently dropped: `img-src https://img.cleberg.net`,
+# `style-src https://cleberg.net`, `font-src https://cleberg.net`.
+#
+# `bubbles.town` DROPPED 2026-08-03 — the site was redeployed without its
+# script. Verified against the deployed HTML: **0** `<script>` refs remain. The
+# 174 surviving mentions are `<a href>` comment links, which browsers do not
+# fetch and CSP does not govern.
+#
+# The site now loads **nothing** cross-origin: parsing all deployed HTML returns
+# zero absolute subresources. `default-src 'self'` is therefore the whole story
+# and script-src/connect-src need no host allowances at all.
+#
+# `upgrade-insecure-requests` is still deliberately OMITTED: this vhost also
+# serves the .onion over plain http, where UIR would upgrade same-origin
+# subresource URLs to https and break them.
map $sent_http_content_type $content_security_policy_cmc {
- ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' https://img.cleberg.net data:; script-src 'self' https://bubbles.town; connect-src 'self' https://bubbles.town; style-src 'self' https://cleberg.net; font-src 'self' https://cleberg.net; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'";
+ ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' data:; script-src 'self'; connect-src 'self'; style-src 'self'; font-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'";
}
# krz.sh only. Derived from the served HTML after the img.cleberg.net removal
@@ -141,8 +151,21 @@ map $sent_http_content_type $permissions_policy {
}
# Add Referrer-Policy for HTML documents.
+# `same-origin`, not `strict-origin-when-cross-origin`.
+#
+# Cloudflare's now-removed "security headers" toggle was setting `same-origin`,
+# and dropping the toggle silently regressed this to nginx's weaker value.
+# Restored deliberately 2026-08-03.
+#
+# The difference: `strict-origin-when-cross-origin` still sends the ORIGIN
+# (`https://cleberg.net`) to external sites; `same-origin` sends **no referrer
+# at all** cross-origin. On a site whose outbound links are the main cross-origin
+# traffic, that is the meaningful setting — external hosts learn nothing about
+# where the visitor came from.
+#
+# Same-origin navigation still sends a full referrer, so nothing internal breaks.
map $sent_http_content_type $referrer_policy {
- ~*text/(css|html|javascript)|application\/pdf|xml "strict-origin-when-cross-origin";
+ ~*text/(css|html|javascript)|application\/pdf|xml "same-origin";
}
# Add Cross-Origin-Policies for HTML documents.