| Age | Commit message (Collapse) | Author | Lines |
|
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>
|
|
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>
|
|
- 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>
|
|
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>
|
|
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>
|
|
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>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
- 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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
- 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>
|
|
network_mode: host では /proc/sys への書き込みが制限されるため、
sysctl の失敗を無視してホスト側の設定値を確認するよう変更。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- vpn/: Dockerfile, docker-compose.yml, swanctl.conf.tpl, entrypoint.sh
- install.sh: Caddy 証明書流用 + コンテナ起動
- renew-cert.sh: 証明書更新 + swanctl ホットリロード
- caddy/Caddyfile: vpn.yyamashita.com 追加(Let's Encrypt 証明書取得用)
- post-receive: vpn/deploy.sh を追加
- setup-route53.py: WEB_SUBDOMAINS に vpn を追加
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Caddy: route blog.yyamashita.com → microblog-app:3000
- git: add microblog post-receive hook and update work tree path to /app/microblog
- DNS: add blog subdomain to Route 53 WEB_SUBDOMAINS
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- caddy/Caddyfile: admin.yyamashita.com → hetzner-admin.yyamashita.com
- mail/dns/setup-route53.py: add A record for primary, CNAME records for
all web service subdomains pointing to hetzner.yyamashita.com
- CLAUDE.md: update access URL
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Basic Auth protected web UI with buttons to restart services and reboot.
SSH key with authorized_keys command= restriction limits executable commands.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Register mosquitone-admin as a managed git repo with post-receive checkout
hook, and add yyamashita:mosquitone-admin to the Claude Code session list.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Port 25 outbound is no longer blocked on Hetzner, so SES relay is
unnecessary. Remove relayhost, SASL auth config, and libsasl2-modules.
Postfix now delivers directly to recipient MX; inet_protocols=ipv4
already present to avoid IPv6 PTR issues.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
This reverts commit 5e9ed4fe05eda672293dbfe6bf10da6d9635261b.
|
|
Registers daily scrape (05:00 JST) and recap email (08:00 JST) jobs
for tokyo-livehouse-events via idempotent crontab install.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Required for smtp_sasl_auth_enable with Amazon SES.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
SES credentials are injected via .env file (not committed). entrypoint.sh
creates sasl_passwd at runtime from SES_ACCESS_KEY_ID / SES_SMTP_PASSWORD.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
smtp プロセスは chroot 環境で動くため /etc/resolv.conf が見えず
MX ルックアップが失敗していた。chroot (/var/spool/postfix/etc/) に
resolv.conf / hosts / services / nsswitch.conf をコピーして解決。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|