From 1a7b5adf8484ec0f2b6feb350b578142e186ab26 Mon Sep 17 00:00:00 2001 From: yyamashita Date: Thu, 2 Jul 2026 23:08:58 +0900 Subject: Move forward proxy from Squid to Caddy (port 80/443) 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 --- CLAUDE.md | 33 ++++++++++++++++++--------------- caddy/Caddyfile | 7 +------ caddy/Dockerfile | 9 +++++++++ caddy/docker-compose.yml | 3 ++- caddy/entrypoint.sh | 35 +++++++++++++++++++++++++++++++++++ git/hooks/hetzner-infra/post-receive | 1 - mail/dns/setup-route53.py | 1 + proxy/Dockerfile | 6 ------ proxy/deploy.sh | 10 ---------- proxy/docker-compose.yml | 9 --------- proxy/entrypoint.sh | 13 ------------- proxy/install.sh | 12 ------------ proxy/renew-cert.sh | 22 ---------------------- proxy/squid.conf | 21 --------------------- 14 files changed, 66 insertions(+), 116 deletions(-) create mode 100644 caddy/Dockerfile create mode 100644 caddy/entrypoint.sh delete mode 100644 proxy/Dockerfile delete mode 100644 proxy/deploy.sh delete mode 100644 proxy/docker-compose.yml delete mode 100644 proxy/entrypoint.sh delete mode 100644 proxy/install.sh delete mode 100644 proxy/renew-cert.sh delete mode 100644 proxy/squid.conf diff --git a/CLAUDE.md b/CLAUDE.md index 9f2890b..3a5188f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,20 +5,19 @@ Hetzner VPS 上で動くサービス群のインフラ管理リポジトリ。 ## ディレクトリ構成 ``` -caddy/ リバースプロキシ(Caddyfile, docker-compose.yml, deploy.sh) +caddy/ リバースプロキシ + フォワードプロキシ(Caddyfile, Dockerfile, entrypoint.sh, docker-compose.yml, deploy.sh) cgit/ cgit Web UI(Dockerfile, lighttpd.conf, cgitrc, deploy.sh) git/ ベアリポジトリ・フック管理(repos.txt, hooks/, install.sh) claude/ Claude Code セッション管理(sessions.txt, systemd unit, sync.sh) hetzner-admin/ サーバー管理 Web UI(app.py, Dockerfile, docker-compose.yml, deploy.sh) mail/ MTA(Postfix + OpenDKIM, docker-compose.yml, install.sh, dns/setup-route53.py) vpn/ strongSwan IKEv2 VPN(Dockerfile, docker-compose.yml, install.sh, renew-cert.sh) -proxy/ HTTPS フォワードプロキシ(Squid, Dockerfile, docker-compose.yml, install.sh, renew-cert.sh) server/ サーバー共通設定(authorized_keys, requirements.md) ``` ## デプロイの仕組み -- `git push origin master` → post-receive フック → `caddy/deploy.sh` / `cgit/deploy.sh` / `mail/deploy.sh` / `hetzner-admin/deploy.sh` / `vpn/deploy.sh` / `proxy/deploy.sh` を実行 +- `git push origin master` → post-receive フック → `caddy/deploy.sh` / `cgit/deploy.sh` / `mail/deploy.sh` / `hetzner-admin/deploy.sh` / `vpn/deploy.sh` を実行 - cgit の `lighttpd.conf` / `Dockerfile` 変更はイメージ再ビルドが必要(`deploy.sh` で `--build` するため push だけで反映される) - cgit の `cgitrc` はボリュームマウントのため push だけで反映される - フック・リポジトリの変更は push 後に `bash /app/infra/git/install.sh` を手動実行 @@ -110,17 +109,21 @@ ssh root@ vi /app/infra/vpn/users.conf # 1行1ユーザー: "username password" docker compose -f /app/infra/vpn/docker-compose.yml restart -# Proxy 初回セットアップ(サーバー上で実行) -# 前提: ファイアウォールで TCP 8443 を開放済み、DNS A レコードで proxy.yyamashita.com を設定済み -git push origin master -ssh root@ 'bash /app/infra/git/install.sh' # post-receive フック更新 -# → Caddy が proxy.yyamashita.com の証明書を取得するまで数分待つ -ssh root@ 'bash /app/infra/proxy/install.sh' -# → Caddy の証明書を流用 + コンテナ起動 -# → proxy.yyamashita.com:8443 (HTTPS) で接続可能 +# Proxy 初回セットアップ(Caddy に統合済み。追加作業なし) +# → push するだけで Caddy が proxy.yyamashita.com の証明書を自動取得 +# → proxy.yyamashita.com:80 (HTTP) / :443 (HTTPS) でフォワードプロキシとして動作 +# → 認証は VPN と同じ users.conf を共有 + +# Proxy ユーザー追加・変更(VPN と同じ users.conf を編集) +ssh root@ +vi /app/infra/vpn/users.conf +docker compose -f /app/infra/caddy/docker-compose.yml restart # Caddy 再起動で反映 -# Proxy 証明書更新(Let's Encrypt 更新後 90 日ごと) -ssh root@ 'bash /app/infra/proxy/renew-cert.sh' +# DNS 登録(初回のみ。setup-route53.py に proxy が含まれている) +ssh root@ +export AWS_ACCESS_KEY_ID=... +export AWS_SECRET_ACCESS_KEY=... +python3 /app/infra/mail/dns/setup-route53.py ``` ## VPN クライアント設定 @@ -142,6 +145,6 @@ ssh root@ 'bash /app/infra/proxy/renew-cert.sh' ## Proxy クライアント設定 -- アドレス: `proxy.yyamashita.com:8443` -- プロトコル: HTTPS (CONNECT トンネリング) +- HTTP プロキシ: `proxy.yyamashita.com:80` +- HTTPS プロキシ: `proxy.yyamashita.com:443` - 認証: Basic 認証(VPN と同じユーザー名/パスワード) diff --git a/caddy/Caddyfile b/caddy/Caddyfile index 5ab87a7..3cf3547 100644 --- a/caddy/Caddyfile +++ b/caddy/Caddyfile @@ -41,12 +41,7 @@ blog.yyamashita.com { reverse_proxy microblog-app:3000 } -proxy.yyamashita.com { - tls { - key_type rsa4096 - } - respond "Proxy Server" 200 -} +import /tmp/proxy_forward.caddy vpn.yyamashita.com { tls { diff --git a/caddy/Dockerfile b/caddy/Dockerfile new file mode 100644 index 0000000..295437b --- /dev/null +++ b/caddy/Dockerfile @@ -0,0 +1,9 @@ +FROM caddy:2-builder-alpine AS builder +RUN xcaddy build --with github.com/caddyserver/forwardproxy@caddy2 + +FROM caddy:2-alpine +COPY --from=builder /usr/bin/caddy /usr/bin/caddy +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] diff --git a/caddy/docker-compose.yml b/caddy/docker-compose.yml index 3e9385d..e23d25a 100644 --- a/caddy/docker-compose.yml +++ b/caddy/docker-compose.yml @@ -1,6 +1,6 @@ services: caddy: - image: caddy:2-alpine + build: . ports: - "80:80" - "443:443" @@ -9,6 +9,7 @@ services: - ./:/etc/caddy/ - caddy_data:/data - caddy_config:/config + - /app/infra/vpn/users.conf:/etc/proxy/users.conf:ro restart: unless-stopped networks: - web diff --git a/caddy/entrypoint.sh b/caddy/entrypoint.sh new file mode 100644 index 0000000..cf123ce --- /dev/null +++ b/caddy/entrypoint.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -e + +PROXY_CONF=/tmp/proxy_forward.caddy + +# Build basicauth lines from shared users.conf +AUTH_LINES="" +if [ -f /etc/proxy/users.conf ]; then + while IFS=' ' read -r user pass || [ -n "$user" ]; do + [ -z "$user" ] && continue + case "$user" in \#*) continue ;; esac + AUTH_LINES="${AUTH_LINES} basicauth ${user} ${pass}\n" + done < /etc/proxy/users.conf +fi +AUTH_BLOCK=$(printf '%b' "$AUTH_LINES") + +cat > "$PROXY_CONF" < /etc/squid/passwd -while IFS=' ' read -r user pass || [ -n "$user" ]; do - [ -z "$user" ] && continue - case "$user" in \#*) continue ;; esac - echo "${user}:$(openssl passwd -apr1 "$pass")" >> /etc/squid/passwd -done < /etc/proxy/users.conf -chmod 600 /etc/squid/passwd - -exec squid -N -f /etc/squid/squid.conf diff --git a/proxy/install.sh b/proxy/install.sh deleted file mode 100644 index 58a8e53..0000000 --- a/proxy/install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -cd "$(dirname "$0")" - -echo "=== Proxy Install: proxy.yyamashita.com ===" -bash "$(pwd)/renew-cert.sh" - -echo "" -echo "=== Proxy 起動完了 ===" -echo " アドレス: https://proxy.yyamashita.com:8443" -echo " 認証: VPN と同じユーザー名/パスワード (Basic 認証)" -echo " 証明書の更新: bash /app/infra/proxy/renew-cert.sh" diff --git a/proxy/renew-cert.sh b/proxy/renew-cert.sh deleted file mode 100644 index 8924d9b..0000000 --- a/proxy/renew-cert.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -cd "$(dirname "$0")" - -DOMAIN="proxy.yyamashita.com" -CADDY_DIR="/app/infra/caddy" -CADDY_CERT_BASE="/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${DOMAIN}/${DOMAIN}" - -echo "証明書を更新中..." -mkdir -p certs - -if ! docker compose -f "$CADDY_DIR/docker-compose.yml" exec -T caddy \ - cat "${CADDY_CERT_BASE}.crt" > certs/server.crt; then - echo "Error: 証明書の取得に失敗しました。Caddyfile に ${DOMAIN} が設定されているか確認してください。" - exit 1 -fi -docker compose -f "$CADDY_DIR/docker-compose.yml" exec -T caddy \ - cat "${CADDY_CERT_BASE}.key" > certs/server.key -chmod 600 certs/server.key - -echo "証明書を更新しました。" -bash "$(pwd)/deploy.sh" diff --git a/proxy/squid.conf b/proxy/squid.conf deleted file mode 100644 index 29ebd05..0000000 --- a/proxy/squid.conf +++ /dev/null @@ -1,21 +0,0 @@ -https_port 8443 cert=/etc/squid/certs/server.crt key=/etc/squid/certs/server.key - -auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd -auth_param basic realm "Proxy" -auth_param basic credentialsttl 2 hours - -acl authenticated proxy_auth REQUIRED -http_access allow authenticated -http_access deny all - -forwarded_for delete -via off - -dns_nameservers 1.1.1.1 8.8.8.8 - -cache_dir null /tmp -cache deny all -access_log stdio:/dev/stdout -cache_log stdio:/dev/stderr -cache_store_log none -coredump_dir /tmp -- cgit v1.2.3