Skip to content

Commit 1ccb1a6

Browse files
nextlevelshitMichael Czechowski
authored andcommitted
docs: Cloudflare dormant setup runbook (free tier, single-toggle activation) (#206)
Co-authored-by: Michael Czechowski <mail@dailysh.it> Co-committed-by: Michael Czechowski <mail@dailysh.it>
1 parent 86f475c commit 1ccb1a6

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

docs/CLOUDFLARE-PREP.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Cloudflare dormant setup (free tier)
2+
3+
Pre-configured Cloudflare account for codecrispi.es. **Proxy stays OFF** (gray cloud, DNS-only). Traffic goes direct to netcup. When HN/reddit spike forces it, flip one toggle per record to **orange cloud** → traffic now absorbed by CF edge.
4+
5+
## Why dormant?
6+
7+
- Zero behavior change vs current state — traffic still direct
8+
- CF account configured, nameservers transferred, rules ready
9+
- Activation = single toggle in CF dashboard. No code change, no DNS propagation wait. ~5 min from spike → mitigation.
10+
- Revertible — flip back to gray cloud → back to direct origin
11+
12+
## One-time setup (user-only, ~30 min)
13+
14+
### 1. Create Cloudflare account
15+
16+
- https://dash.cloudflare.com/sign-up
17+
- Use a real email (LE renewals + abuse alerts route here)
18+
- Enable 2FA at account level
19+
20+
### 2. Add site
21+
22+
- "Add a Site" → enter `codecrispi.es`
23+
- Plan: **Free**
24+
- CF scans current DNS at netcup; verify it imports:
25+
- A `codecrispi.es``37.120.174.54`
26+
- AAAA `codecrispi.es``2a03:4000:6:776d:34d0:3dff:feb9:d51a`
27+
- A `www.codecrispi.es``37.120.174.54`
28+
- AAAA `www.codecrispi.es``2a03:4000:6:776d:34d0:3dff:feb9:d51a`
29+
- (No MX — no email at apex)
30+
- (Any TXT records for DKIM/SPF/verification — preserve)
31+
32+
### 3. Set ALL records to DNS-only (gray cloud)
33+
34+
Critical step. Per record in the DNS list:
35+
- Toggle the orange cloud icon → **gray cloud**
36+
- This means: CF answers DNS queries but does NOT proxy the traffic
37+
- Traffic flows: client → CF DNS resolution → direct connect to netcup
38+
- CF sees the DNS query but never the HTTP request
39+
40+
### 4. Change nameservers at netcup
41+
42+
- CF dashboard shows the two NS records to set (e.g. `nina.ns.cloudflare.com` + `walt.ns.cloudflare.com`)
43+
- Log into netcup customer portal → DNS → change nameservers for `codecrispi.es`
44+
- Wait for propagation (~5min–24h depending on TTL of current netcup NS records)
45+
- CF dashboard turns "Active" once it detects the NS change
46+
47+
### 5. Pre-configure cache rules (dormant)
48+
49+
These rules ONLY take effect when proxy is ON (orange). Configuring now = ready to flip:
50+
51+
**Cache Rule 1: Cache everything static**
52+
- Hostname: `codecrispi.es` OR `www.codecrispi.es`
53+
- AND URI Path matches `\.(js|css|png|jpg|svg|ico|webmanifest|woff2?|ttf|map)$`
54+
- THEN: Cache eligibility → Eligible for cache, Edge TTL → 1 year
55+
56+
**Cache Rule 2: Cache HTML for 5 minutes**
57+
- Hostname matches
58+
- AND URI Path matches `\.html$` OR ends with `/`
59+
- THEN: Edge TTL → 5 min
60+
61+
**Bypass: API + auth**
62+
- URI Path starts with `/api/` OR `/auth/` OR `/health`
63+
- THEN: Cache eligibility → Bypass
64+
65+
### 6. Verify direct origin still works
66+
67+
```bash
68+
# DNS now from CF (gray cloud = same IP)
69+
dig +short codecrispi.es @1.1.1.1
70+
# expect: 37.120.174.54
71+
72+
# HTTPS still hits netcup (Caddy cert)
73+
curl -sI https://codecrispi.es/ | grep -i server
74+
# expect: Server: Caddy (NOT Cloudflare)
75+
```
76+
77+
## Activation (when ready, ~5 min)
78+
79+
For each of the 4 records (apex A+AAAA, www A+AAAA):
80+
81+
1. CF dashboard → DNS → Records
82+
2. Click the gray cloud icon next to the record
83+
3. It turns **orange** → CF is now proxying
84+
85+
Verify:
86+
87+
```bash
88+
# DNS now returns CF anycast IPs
89+
dig +short codecrispi.es @1.1.1.1
90+
# expect: 104.x.x.x or 172.x.x.x (CF IPs)
91+
92+
curl -sI https://codecrispi.es/ | grep -i server
93+
# expect: Server: cloudflare
94+
```
95+
96+
CF requests new edge TLS cert automatically (~30s). HTTPS keeps working through the swap because CF Universal SSL provisions in parallel.
97+
98+
## Rollback (~30 sec)
99+
100+
Click orange cloud → gray cloud per record. Traffic immediately falls back to direct origin. CF cache continues serving stale content for ~30 seconds while routing transitions.
101+
102+
## What you give up
103+
104+
- **Origin TLS termination** → CF re-terminates at edge with their cert. Your Caddy LE cert still works in parallel; CF's just takes precedence at the edge
105+
- **Real client IPs** → arrive in `CF-Connecting-IP` header; nginx logs show CF IPs in `$remote_addr` unless you configure `real_ip_header` (see below)
106+
- **No JS injection** — CF doesn't inject scripts on free tier (Pro+ has the option for analytics; off by default)
107+
- **Privacy** — CF sees full URL + user IP for every cached miss
108+
109+
## Optional: real client IP at origin
110+
111+
If you want real IPs in nginx logs after CF activation, add to `nginx.conf` http block:
112+
113+
```nginx
114+
set_real_ip_from 173.245.48.0/20;
115+
set_real_ip_from 103.21.244.0/22;
116+
set_real_ip_from 103.22.200.0/22;
117+
set_real_ip_from 103.31.4.0/22;
118+
set_real_ip_from 141.101.64.0/18;
119+
set_real_ip_from 108.162.192.0/18;
120+
set_real_ip_from 190.93.240.0/20;
121+
set_real_ip_from 188.114.96.0/20;
122+
set_real_ip_from 197.234.240.0/22;
123+
set_real_ip_from 198.41.128.0/17;
124+
set_real_ip_from 162.158.0.0/15;
125+
set_real_ip_from 104.16.0.0/13;
126+
set_real_ip_from 104.24.0.0/14;
127+
set_real_ip_from 172.64.0.0/13;
128+
set_real_ip_from 131.0.72.0/22;
129+
real_ip_header CF-Connecting-IP;
130+
```
131+
132+
(CF IP list: https://www.cloudflare.com/ips/ — update on schedule)
133+
134+
Defer this until activation; works fine without for free-tier needs.
135+
136+
## Cost
137+
138+
**EUR 0/mo for free tier.** Unlimited bandwidth + requests. Pro ($20/mo) only adds WAF + image polish — not needed for this app.
139+
140+
## Activation triggers (when to flip)
141+
142+
- Show HN / reddit /r/programming / dev.to frontpage submission planned in <2 days
143+
- Sustained > 50 rps measured against current ceiling
144+
- DDoS attempt observed in nginx logs
145+
- Star count crosses 500 (likely future popularity)
146+
147+
## What this PR adds
148+
149+
`docs/CLOUDFLARE-PREP.md` — this file. No code change, no infra change.
150+
The user-side setup steps stay user-only (CF account, registrar nameserver change). Activation runbook documented for when needed.

docs/MULTI-INSTANCE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ Throughput ceiling = single nginx workers + Caddy CPU + VPS network. Tuned, but
3737
4. Cache rule: HTML respects `Cache-Control: max-age=300` (already set)
3838
5. Origin: keep current netcup IP, Cloudflare proxies
3939

40+
**Dormant prep:** see [`CLOUDFLARE-PREP.md`](./CLOUDFLARE-PREP.md) — full runbook to pre-configure CF in DNS-only mode (gray cloud), so activation is a single per-record toggle when traffic forces it. Zero behavior change until activated.
41+
4042
**Effect:** capacity multiplies ~20x for static (assets, blog OG). HN-frontpage no longer breaks the box.
4143

4244
**Cost:** $0 (free tier). Caveat: Cloudflare sees user IPs + can MITM TLS. Acceptable for an open-source educational site; not for a service handling financial data.

0 commit comments

Comments
 (0)