TASK FOR CLAUDE CODE (on the Pangolin server, 141.227.129.182) Add a raw TCP resource on port 8443 so the Calendar Lite 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-; 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: Calendar Lite 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) --------------------------------- Calendar Lite, 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.