summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorLines
11 daysgit: studio-slots リポジトリを追加yyamashita-0/+6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 dayshetzner-admin: show CPU load / memory / disk / uptime, add Container Stats ↵yyamashita-0/+55
command Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N5eS3SG9dxKszFC7t3QZn9
12 dayshetzner-admin: stop/start code-server (systemd) from the admin panelyyamashita-7/+19
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 dayshetzner-admin: stop/start individual services, shown as STOPPED on status pageyyamashita-17/+203
- run-command.sh: services / stop <name> / start <name> for app and infra stacks (not caddy, hetzner-admin, status). Stopped names go to status/stopped.txt (gitignored). - status: a stopped service that does not respond is STOPPED (gray), excluded from uptime and DOWN alerts. If it responds it is UP as usual. - Infra deploy.sh skips stopped stacks; app repo pushes clear the flag. - claude-code@.service: Restart=on-failure, and restart-sessions.sh restarts one unit at a time, to avoid the tmux "server exited unexpectedly" race. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N5eS3U54gzjRXzm65Np1RS
12 daysgit/install.sh: keep hetzner-admin SSH key when installing authorized_keysyyamashita-3/+13
install.sh overwrote /root/.ssh/authorized_keys with server/authorized_keys, dropping the restricted hetzner-admin key and making every admin UI command fail with an SSH authentication error. Append it on install. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 dayshetzner-admin: add passkey login (password login kept)yyamashita-12/+227
Replace Basic auth with a session-cookie login page. After password login, register a passkey from the bottom of the page; later logins can use it. Passkeys are stored in hetzner-admin/data/ (gitignored). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 daysdocs: document status/ntfy setup, Caddy reload, and DNS key locationyyamashita-13/+23
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 daysntfy: allow anonymous read on status topic (publish still requires token)yyamashita-4/+7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 daysstatus: add ntfy app deep link to status pageyyamashita-1/+7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 dayscaddy: reload config on deploy so Caddyfile changes take effectyyamashita-0/+2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 daysConsolidate status pages into status.yyamashita.comyyamashita-124/+13
Drop Uptime Kuma (uptime.yyamashita.com) and the hetzner-admin /status page; status-app + ntfy alerts is the single status site. hetzner-admin now just links to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 daysstatus: send daily uptime summary to ntfy at 08:00 JSTyyamashita-8/+50
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 daysAdd status pages, ntfy alerts, and license-slot-checker repoyyamashita-4/+478
- status/: lightweight status checker (status.yyamashita.com, /api/status) with ntfy DOWN/recovered alerts after consecutive failures - uptime-kuma/: Uptime Kuma at uptime.yyamashita.com - hetzner-admin: authenticated /status page (status-app results + docker ps -a) - ntfy/: self-hosted ntfy at ntfy.yyamashita.com (deny-all auth, install.sh creates admin user and status-app token) - Caddyfile, DNS, post-receive hook, tests/check.sh, docs updated - license-slot-checker: add to repos.txt, hook, and Claude sessions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-08-22Add todo service: Caddyfile, repos.txt, hook, DNS entryyyamashita-0/+15
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11Fix ExecStop failure when tmux session has already exitedyyamashita-1/+1
The `-` prefix tells systemd to ignore the exit code of tmux kill-session, so restart succeeds even when the claude process has crashed and the session no longer exists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11UI: stack admin buttons verticallyyyamashita-1/+1
Change button layout from inline (margin-right) to block (margin-bottom) for better mobile/readability on hetzner-admin web interface. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-11Dedupe Caddyfile with snippets, sync docs with reality, add tests/check.shyyamashita-28/+156
- Caddyfile: extract repeated header blocks into (noindex)/(crawler_bypass) snippets (adapted JSON verified byte-identical to previous config) - CLAUDE.md: add mosquitone-admin/microblog to repos table; document that proxy auth is disabled (PROXY_NO_AUTH=1) with JP-only IP filter instead - Deploy.md/caddy/README.md: reflect all-service deploy and forward proxy - tests/check.sh: shell/python syntax, repos.txt<->hooks<->sessions.txt consistency, app.py COMMANDS vs run-command.sh whitelist, secrets check Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-03Restrict proxy to Japan IPs using ipdeny.com CIDR listyyamashita-15/+12
Downloads jp-aggregated.zone from ipdeny.com at container startup (no account required). Falls back to open access if download fails. Removed caddy-maxmind-geoip module (no longer needed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03Add GeoIP Japan-only filter to forward proxyyyamashita-6/+27
Uses caddy-maxmind-geoip module to restrict proxy access to JP IPs. DB file (GeoLite2-Country.mmdb) must be placed manually on the server. Filter is inactive when DB file is absent, allowing safe rollout. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03Fix HTTP proxy directive order: forward_proxy must run before rediryyamashita-1/+1
Caddy's default directive ordering places redir before forward_proxy, causing HTTP proxy requests to be redirected to HTTPS instead of being forwarded. Changing order to forward_proxy before redir fixes this. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03caddy: add --build to deploy.sh so entrypoint changes are picked upyyamashita-2/+1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03Fix HTTP proxy: use catch-all http:// block for port 80yyamashita-1/+2
The forward_proxy site block must catch all hosts on port 80 because proxy clients send Host: <target> not Host: proxy.yyamashita.com. Non-proxy requests fall through to the redir for HTTPS upgrade. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03Disable proxy auth permanently (PROXY_NO_AUTH=1)yyamashita-0/+2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03Re-enable proxy auth (remove PROXY_NO_AUTH=1)yyamashita-2/+0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Add global order option for forward_proxy directiveyyamashita-0/+4
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Fix forward_proxy config: remove unsupported hide_ip/hide_via directivesyyamashita-6/+2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Temporarily disable proxy auth (PROXY_NO_AUTH=1)yyamashita-2/+4
Add PROXY_NO_AUTH env var support to entrypoint.sh to skip basicauth generation. Set to 1 in docker-compose.yml to allow unauthenticated access. Revert by removing the environment block from docker-compose.yml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Move forward proxy from Squid to Caddy (port 80/443)yyamashita-116/+66
Replace standalone Squid container with caddy-forwardproxy plugin so the proxy shares Caddy's existing ports and TLS. HTTP on :80 and HTTPS on :443. Auth is read from the same vpn/users.conf at Caddy startup via entrypoint.sh. DNS: add proxy to setup-route53.py WEB_SUBDOMAINS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Add HTTPS forward proxy service (Squid on port 8443)yyamashita-1/+121
- proxy/: Squid container with HTTPS port, Basic auth from vpn/users.conf - caddy/Caddyfile: add proxy.yyamashita.com block (RSA cert for compat) - git/hooks: add proxy/deploy.sh to post-receive hook - CLAUDE.md: document proxy setup and client config Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Re-enable IKE fragmentation (remove fragmentation=no)yyamashita-1/+0
Android 12 IKEv2 may handle IKE-level fragments better than IP-level fragmentation. iOS was failing with IKE fragmentation previously (ECDSA cert era) — test if RSA cert + IKE fragmentation now works for both platforms. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Force send ISRG Root X1 via local.cacerts for Android compatyyamashita-0/+1
strongSwan skips self-signed root CAs from CERT payloads by default. Setting cacerts = chain-3.crt in the local section forces it to include ISRG Root X1 explicitly so Android 12 can complete trust chain validation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Append issuer root CA to cert chain for Android IKEv2 compatyyamashita-0/+14
Android 12 native IKEv2 requires the presented cert chain to include a cert that is directly in the device trust store. Fetch the issuer root CA (ISRG Root X1) via AIA from the last intermediate cert and append it to server-chain.crt so strongSwan sends 4 CERT payloads: Leaf + YR1 + Root YR + ISRG Root X1 (trusted on all Android versions). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Remove cert logic duplication from vpn/install.shyyamashita-58/+17
install.sh and renew-cert.sh had identical cert fetch/split code. install.sh now delegates to renew-cert.sh, which in turn calls deploy.sh. Flow: install.sh → renew-cert.sh → deploy.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Unify install.sh pattern: always delegate to deploy.shyyamashita-4/+4
Both hetzner-admin and vpn install.sh were calling docker compose directly instead of going through their own deploy.sh, unlike mail which already followed the correct pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Force RSA4096 cert for VPN domain to fix iOS IKEv2yyamashita-0/+3
ECDSA chain (YE1→Root YE→ISRG Root X2) is not trusted by iOS IKEv2. RSA chain (Leaf→R10→ISRG Root X1) is universally trusted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Send full cert chain to fix iOS IKEv2 validationyyamashita-3/+3
iOS IKEv2 does not look up intermediates from the system trust store (unlike TLS/HTTPS). Send all 3 certs: YE1 + Root YE + cross-signed ISRG Root X2, so iOS can build the full chain through to ISRG Root X1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Disable IKE fragmentation, use IP-level fragmentation for iOSyyamashita-1/+2
iOS may have a bug where it advertises N(FRAG_SUP) but fails to reassemble IKE fragments in IKE_AUTH responses. Switching to fragmentation=no forces the large IKE_AUTH response to be sent as a single UDP packet with IP-level fragmentation, which iOS's standard IP stack handles correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Send only YE1+RootYE intermediates, skip cross-signed ISRG Root X2yyamashita-0/+3
iOS 14+ and Android 11+ have ISRG Root X2 in their trust store. Sending the cross-signed ISRG Root X2 alongside the trusted self-signed version can confuse the cert path-building algorithm. Chain: leaf -> YE1 -> Root YE -> [ISRG Root X2 from trust store] Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Fix VPN cert chain: split multi-cert PEM for strongSwanyyamashita-1/+18
Caddy's cert chain contains 4 certs: 1. leaf (signed by YE1) 2. YE1 (signed by Root YE) 3. Root YE (cross-signed by ISRG Root X2) 4. ISRG Root X2 (cross-signed by ISRG Root X1) iOS/Android trust ISRG Root X1 but not Root YE directly. The full cross-signed chain must be sent in IKE_AUTH. strongSwan only reads the first cert from a multi-cert PEM file, so entrypoint.sh now splits server-chain.crt into individual files in x509ca/ before starting charon. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02Restore intermediate cert + reduce IKE fragment size to 512 bytesyyamashita-0/+2
iOS/Android VPN stacks don't follow AIA to download intermediate certs, so YE1 must be sent by the server for cert chain validation. The original 1236-byte IKE fragment was being dropped mid-path. Setting fragment_size=512 splits the 1776-byte IKE_AUTH into ~4 fragments of ≤560 bytes each, which should traverse any NAT/router. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Remove intermediate CA cert to fix IKE fragmentationyyamashita-1/+0
YE1 intermediate cert was inflating IKE_AUTH response to 1776 bytes, causing it to be split into 2 IKE fragments that iOS/Android clients could not reassemble. Both iOS and Android 12 (Beam Pro) have Let's Encrypt trust chain in their system store, so the intermediate cert is not needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Revert VPN file logging (caused container crash)yyamashita-9/+0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Add file logging to VPN container for diagnosticsyyamashita-0/+9
Logs to /home/yyamashita/vpn-logs/charon.log (readable without root) to diagnose iPhone IKEv2 connection failures. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Revert fragmentation=no to restore iPhone VPN connectivityyyamashita-1/+0
fragmentation=no caused IP-level fragmentation (1808-byte packets) which is blocked by mobile networks. Default IKE fragmentation (RFC 7383) works for iOS/macOS with 2 fragments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Fix IKE fragmentation: use fragmentation=no instead of fragment_size=0yyamashita-1/+1
fragment_size=0 was interpreted as minimum fragment size (resulting in 4 tiny fragments), not disabled. fragmentation=no in swanctl.conf is the correct per-connection setting to disable IKE fragmentation entirely. The server now sends a single large UDP packet; the OS kernel handles IP fragmentation instead of the IKE layer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Restore intermediate CA cert, disable IKE fragmentationyyamashita-0/+2
Android (XREAL Beam Pro) fails to reassemble IKE fragments even though FRAG_SUP is negotiated. IP-level fragmentation (handled by the OS kernel) works better. Removing the intermediate cert broke macOS/iOS. This config: - Sends leaf cert + YE1 intermediate (so any client can verify the chain) - fragment_size=0 disables IKE fragmentation; the 1776-byte IKE_AUTH response is sent as one large UDP packet (OS handles IP fragmentation) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Serve YE1 intermediate CA cert for Android VPN trust chainyyamashita-1/+18
Android (XREAL Beam Pro) can't validate the server cert because it lacks the Let's Encrypt YE1 hierarchy in its system trust store. The fix: - Serve YE1 cert at https://vpn.yyamashita.com/ca.pem via Caddy - Android VPN profile: set CA certificate to this downloaded cert - install.sh / renew-cert.sh now extract and copy YE1 to caddy dir Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Remove intermediate CA cert mount to fix Android IKEv2 fragmentationyyamashita-1/+0
Android (XREAL Beam Pro) advertises FRAG_SUP but fails to reassemble IKE fragments. The IKE_AUTH response was 1776 bytes (leaf + YE1 intermediate) requiring fragmentation into 2 packets. Without x509ca mount, only the leaf cert is sent (~886 bytes total), fitting in a single packet without fragmentation. Android fetches the intermediate CA (YE1) via AIA extension before tunnel setup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01Fix VPN: send certificate always, split cert chain, fix entrypointyyamashita-15/+20
- swanctl.conf.tpl: send_cert = always (fix Android cert verification failure) - docker-compose.yml: mount intermediate CAs to /etc/swanctl/x509ca/ - install.sh: split server.crt into leaf + chain for proper chain distribution - entrypoint.sh: run charon directly for Docker log visibility, fix sysctl error handling, fix charon binary path - strongswan.conf: increase IKE log level to 4 for debugging Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30Fix VPN entrypoint: handle sysctl read-only in host network modeyyamashita-3/+7
network_mode: host では /proc/sys への書き込みが制限されるため、 sysctl の失敗を無視してホスト側の設定値を確認するよう変更。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>