tenseleyflow/shithub / 1e26641

Browse files

S38: deploy/docs-site — Caddyfile snippet + Spaces sync script

Authored by espadonne
SHA
1e26641e6f1c9f555a03328ea227a9361ea56438
Parents
b9cbab1
Tree
4cbdb3d

2 changed files

StatusFile+-
A deploy/docs-site/Caddyfile.snippet 58 0
A deploy/docs-site/sync-to-spaces.sh 37 0
deploy/docs-site/Caddyfile.snippetadded
@@ -0,0 +1,58 @@
1
+# Caddy snippet for the docs subdomain. Either include this file
2
+# from the main Caddyfile (`import deploy/docs-site/Caddyfile.snippet`)
3
+# or run a separate Caddy instance dedicated to docs serving.
4
+#
5
+# The site itself is static — built by `make docs` and synced to
6
+# Spaces by `deploy/docs-site/sync-to-spaces.sh`. Caddy fetches
7
+# pages from Spaces with a short TTL so a new release is visible
8
+# within a minute of the sync.
9
+
10
+docs.shithub.example {
11
+    encode gzip zstd
12
+
13
+    # Docs come from a Spaces bucket fronted by Caddy. We use the
14
+    # reverse_proxy so we can layer cache headers and a sane 404.
15
+    reverse_proxy https://shithub-docs.nyc3.digitaloceanspaces.com {
16
+        header_up Host {http.reverse_proxy.upstream.host}
17
+        header_up -X-Forwarded-Host
18
+        transport http {
19
+            tls
20
+        }
21
+    }
22
+
23
+    header {
24
+        # Static content; let browsers + CDN cache for 5 min and
25
+        # revalidate.
26
+        Cache-Control          "public, max-age=300, stale-while-revalidate=86400"
27
+        # Standard HSTS posture; assumes the apex serves HTTPS too.
28
+        Strict-Transport-Security "max-age=31536000; includeSubDomains"
29
+        # Drop the default Caddy server header.
30
+        -Server                ""
31
+        # Tighten the embed/clickjack surface.
32
+        X-Frame-Options        "DENY"
33
+        X-Content-Type-Options "nosniff"
34
+        Referrer-Policy        "strict-origin-when-cross-origin"
35
+        # Docs include code samples; no scripts beyond mdBook's own
36
+        # bundled ones. CSP is conservative.
37
+        Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'"
38
+    }
39
+
40
+    # Surface a friendly page for missing docs.
41
+    handle_errors {
42
+        @404 expression {http.error.status_code} == 404
43
+        handle @404 {
44
+            rewrite * /404.html
45
+            file_server {
46
+                root /var/lib/shithub/docs-fallback
47
+            }
48
+        }
49
+    }
50
+
51
+    log {
52
+        output file /var/log/caddy/docs-access.log {
53
+            roll_size  100MiB
54
+            roll_keep  10
55
+        }
56
+        format json
57
+    }
58
+}
deploy/docs-site/sync-to-spaces.shadded
@@ -0,0 +1,37 @@
1
+#!/usr/bin/env bash
2
+# SPDX-License-Identifier: AGPL-3.0-or-later
3
+#
4
+# Build the public docs site and sync it to the Spaces bucket
5
+# that Caddy serves docs.shithub.example from.
6
+#
7
+# Run from CI on every push to main, or from an operator's
8
+# workstation as a one-off. Idempotent: rclone sync only touches
9
+# changed files.
10
+
11
+set -euo pipefail
12
+
13
+ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
14
+cd "$ROOT"
15
+
16
+BUCKET="${SHITHUB_DOCS_BUCKET:-spaces-docs:shithub-docs}"
17
+
18
+if ! command -v mdbook >/dev/null 2>&1; then
19
+  echo "fatal: mdbook not on PATH; install from https://rust-lang.github.io/mdBook/" >&2
20
+  exit 2
21
+fi
22
+
23
+# Build into the configured build-dir from book.toml (build/docs/).
24
+echo "building docs..."
25
+cd docs/public && mdbook build && cd "$ROOT"
26
+
27
+if [[ ! -d build/docs ]]; then
28
+  echo "fatal: mdbook build did not produce build/docs/" >&2
29
+  exit 2
30
+fi
31
+
32
+echo "syncing to $BUCKET..."
33
+rclone --config /root/.config/rclone/rclone.conf \
34
+       sync --transfers 8 --checkers 16 \
35
+       build/docs "$BUCKET"
36
+
37
+echo "docs sync complete"