Files
calendar-lite/bridge/pangolin-vps-setup.txt
T

114 lines
6.2 KiB
Plaintext

TASK FOR CLAUDE CODE (on the Pangolin server, 141.227.129.182)
Add a raw TCP resource on port 8443 so the GingerCal app (Android 2.3) can reach Nextcloud CalDAV
==================================================================================================
CONTEXT
-------
- This server runs Pangolin (Pangolin + Gerbil + Traefik in Docker). Traefik terminates HTTPS for
every public site with Let's Encrypt certificates, TLS 1.2 minimum, routed by SNI.
- Android 2.3 can't use that: TLS 1.0 only, no ISRG Root X1, unreliable SNI. So the TLS for this
app is NOT terminated here. The home server (172.30.1.123, site connector "newt") runs a
container "caldav-bridge" (nginx) on 172.30.1.123:8443. It speaks TLS 1.0 with a self-signed
certificate the app pins, and forwards only /remote.php/dav/ to Nextcloud (nxc.anosanube.ovh).
That part is already done and tested.
- This server only has to pass raw TCP on port 8443 through the newt tunnel to that bridge:
phone --TLS 1.0--> VPS :8443 (gerbil/traefik, raw TCP) --WireGuard--> newt
--> 172.30.1.123:8443 (caldav-bridge) --HTTP--> nextcloud-aio-apache:11000
- Certificate fingerprint the bridge serves (SHA-256):
56:70:CE:E5:41:6D:B1:31:E8:74:51:52:66:8C:70:27:96:AE:28:8F:69:3E:AB:EE:4A:FD:FD:6B:6C:21:17:65
RULES
-----
- Read the existing config before changing anything. Don't assume paths or service names; find them.
- Back up every file before editing it (cp file file.bak-YYYYMMDD-HHMM).
- Show the user the exact diff and get their OK before restarting any container or editing
docker-compose.yml.
- Don't change TLS options, routers, entrypoints or certificates used by any existing site.
- Don't touch Pangolin's database.
STEPS
-----
1. Find the Pangolin install directory (docker-compose.yml defining pangolin, gerbil, traefik).
Note the Pangolin version (raw TCP/UDP resources need Pangolin 1.4 or later; if it's older,
stop and tell the user).
Check that nothing on the VPS already listens on 8443:
ss -ltnp | grep ':8443 '
If 8443 is taken, stop and tell the user; another public port works too (any port, as long as
steps 2-5 use the same number), and the phone address changes to match.
2. config/config.yml: enable raw resources. MERGE into an existing "flags:" key if there is one;
never create a duplicate top-level key.
flags:
allow_raw_resources: true
3. docker-compose.yml, the "gerbil" service (Traefik shares gerbil's network namespace, so
public ports are published on gerbil): add to its ports list
- 8443:8443
4. config/traefik/traefik_config.yml, "entryPoints": add (the name MUST be tcp-<port>; Pangolin
generates its TCP routers against that name)
entryPoints:
tcp-8443:
address: ":8443/tcp"
5. Firewall: allow inbound TCP 8443.
- On the host: e.g. `ufw allow 8443/tcp` if ufw is active (check `ufw status`), or the
equivalent for nftables/iptables if that's what's in use.
- The cloud provider's firewall / security group, if there is one: tell the user to open
TCP 8443 there; you probably can't do that from the shell.
6. Validate the YAML files:
python3 -c 'import yaml,sys;[yaml.safe_load(open(f)) for f in sys.argv[1:]]' \
config/config.yml config/traefik/traefik_config.yml docker-compose.yml
Show the diff of all three files and ask the user before applying. Then:
docker compose down && docker compose up -d
(a plain restart won't pick up the new gerbil port). Check
docker compose ps
docker logs --since 2m traefik 2>&1 | grep -iE 'error|tcp-8443'
docker logs --since 2m pangolin 2>&1 | grep -iE 'error'
and confirm every existing site still loads.
7. Pangolin dashboard (the user does this, or guide them through it):
- Org of the home server, Resources, Add Resource, type "Raw TCP/UDP resource".
- Name: GingerCal CalDAV. Protocol: TCP. Public port: 8443.
- Site: the site whose newt runs on the home server 172.30.1.123 (most likely the "casa" site).
- Target: IP 172.30.1.123, port 8443. Leave "Enable Proxy Protocol" OFF (the bridge doesn't
expect it; enabling only one side breaks every connection).
- Pangolin SSO doesn't apply to raw TCP resources. That's expected: Nextcloud asks for its
own login (the phone will use a Nextcloud app password).
8. VERIFY from the VPS (or anywhere with OpenSSL 3):
# TLS 1.0 with a plain-RSA cipher (what Android 2.3 uses) must work:
echo | openssl s_client -connect 141.227.129.182:8443 -tls1 -cipher 'AES128-SHA:@SECLEVEL=0' 2>&1 \
| grep -E 'Protocol *:|Cipher is|alert'
# expect: Protocol: TLSv1 / Cipher is AES128-SHA
# It must be the bridge's certificate (not a Let's Encrypt one):
echo | openssl s_client -connect 141.227.129.182:8443 2>/dev/null | openssl x509 -noout -fingerprint -sha256
# expect: 56:70:CE:E5:41:6D:B1:31:E8:74:51:52:66:8C:70:27:96:AE:28:8F:69:3E:AB:EE:4A:FD:FD:6B:6C:21:17:65
# Nextcloud must answer CalDAV through it:
curl -sk -o /dev/null -w '%{http_code}\n' -X PROPFIND -H 'Depth: 0' https://141.227.129.182:8443/remote.php/dav/
# expect: 401 (and "/" should give 404: the web UI is deliberately not exposed)
# Existing sites must be unaffected, e.g.:
curl -sI https://nxc.anosanube.ovh | head -1
If the TLS test times out: check firewall (step 5), the gerbil port (step 3), and that the
resource's site/target are right (step 7). If it connects but shows a different certificate,
the target is wrong.
9. ROLLBACK if anything breaks: restore the .bak files, `docker compose down && docker compose up -d`,
delete the resource in the dashboard.
10. REPORT to the user: files changed (with diff), backup paths, firewall changes, output of every
check in step 8, and anything left to do (e.g. the cloud firewall).
PHONE SETUP (after step 8 passes)
---------------------------------
GingerCal, Menu, Settings:
Server: https://141.227.129.182:8443 (any *.oxose.org name works too, e.g.
https://cal-old.oxose.org:8443: raw TCP ignores the hostname and the app pins the
certificate, not the name)
User: your Nextcloud user
Password: a Nextcloud app password (Nextcloud, Settings, Security, Devices & sessions)
Save and test connection. Tap Trust only if the fingerprint shown is the one above.