From ef6dbdd2ac273dc4a01c70437ee7984cea9f2a3c Mon Sep 17 00:00:00 2001 From: yyamashita Date: Sun, 17 May 2026 11:29:27 +0900 Subject: Reorganize repo into caddy/, git/, claude/ directories - caddy/: Caddyfile, docker-compose.yml, deploy.sh (hook runs this only) - git/: repos.txt, hooks/*/post-receive, install.sh, server-setup.sh - claude/: sessions.txt, systemd/claude-code@.service, sync.sh Post-receive hook is now: checkout + bash caddy/deploy.sh Co-Authored-By: Claude Sonnet 4.6 --- Caddyfile | 24 -------- caddy/Caddyfile | 24 ++++++++ caddy/deploy.sh | 6 ++ caddy/docker-compose.yml | 23 ++++++++ claude-code-sessions.txt | 6 -- claude/sessions.txt | 5 ++ claude/sync.sh | 67 +++++++++++++++++++++++ claude/systemd/claude-code@.service | 17 ++++++ docker-compose.yml | 23 -------- git/hooks/hetzner-infra/post-receive | 5 ++ git/hooks/tokyo-livehouse-events/post-receive | 8 +++ git/hooks/whois-band/post-receive | 8 +++ git/install.sh | 60 ++++++++++++++++++++ git/repos.txt | 5 ++ git/server-setup.sh | 30 ++++++++++ repos.txt | 6 -- scripts/claude-daemon-setup.sh | 63 --------------------- scripts/install.sh | 62 --------------------- scripts/server-setup.sh | 42 -------------- scripts/sync-claude-services.sh | 70 ------------------------ server-hooks/hetzner-infra/post-receive | 14 ----- server-hooks/tokyo-livehouse-events/post-receive | 8 --- server-hooks/whois-band/post-receive | 8 --- systemd/user/claude-code@.service | 17 ------ 24 files changed, 258 insertions(+), 343 deletions(-) delete mode 100644 Caddyfile create mode 100644 caddy/Caddyfile create mode 100755 caddy/deploy.sh create mode 100644 caddy/docker-compose.yml delete mode 100644 claude-code-sessions.txt create mode 100644 claude/sessions.txt create mode 100755 claude/sync.sh create mode 100644 claude/systemd/claude-code@.service delete mode 100644 docker-compose.yml create mode 100755 git/hooks/hetzner-infra/post-receive create mode 100755 git/hooks/tokyo-livehouse-events/post-receive create mode 100755 git/hooks/whois-band/post-receive create mode 100755 git/install.sh create mode 100644 git/repos.txt create mode 100755 git/server-setup.sh delete mode 100644 repos.txt delete mode 100644 scripts/claude-daemon-setup.sh delete mode 100755 scripts/install.sh delete mode 100644 scripts/server-setup.sh delete mode 100755 scripts/sync-claude-services.sh delete mode 100755 server-hooks/hetzner-infra/post-receive delete mode 100755 server-hooks/tokyo-livehouse-events/post-receive delete mode 100755 server-hooks/whois-band/post-receive delete mode 100644 systemd/user/claude-code@.service diff --git a/Caddyfile b/Caddyfile deleted file mode 100644 index 7e05478..0000000 --- a/Caddyfile +++ /dev/null @@ -1,24 +0,0 @@ -golive.yyamashita.com { - header Referrer-Policy "no-referrer" - header X-Robots-Tag "noindex, nofollow" - - @crawler_bypass header X-Crawler-Access "f9a3c1e847b2d056" - header @crawler_bypass -X-Robots-Tag - - reverse_proxy tokyo-app:3000 -} - -whoisband.yyamashita.com { - header Referrer-Policy "no-referrer" - header X-Robots-Tag "noindex, nofollow" - - @crawler_bypass header X-Crawler-Access "f9a3c1e847b2d056" - header @crawler_bypass -X-Robots-Tag - - reverse_proxy whois-app:3000 -} -code.yyamashita.com { - header Referrer-Policy "no-referrer" - header X-Robots-Tag "noindex, nofollow" - reverse_proxy 172.19.0.1:8080 -} diff --git a/caddy/Caddyfile b/caddy/Caddyfile new file mode 100644 index 0000000..7e05478 --- /dev/null +++ b/caddy/Caddyfile @@ -0,0 +1,24 @@ +golive.yyamashita.com { + header Referrer-Policy "no-referrer" + header X-Robots-Tag "noindex, nofollow" + + @crawler_bypass header X-Crawler-Access "f9a3c1e847b2d056" + header @crawler_bypass -X-Robots-Tag + + reverse_proxy tokyo-app:3000 +} + +whoisband.yyamashita.com { + header Referrer-Policy "no-referrer" + header X-Robots-Tag "noindex, nofollow" + + @crawler_bypass header X-Crawler-Access "f9a3c1e847b2d056" + header @crawler_bypass -X-Robots-Tag + + reverse_proxy whois-app:3000 +} +code.yyamashita.com { + header Referrer-Policy "no-referrer" + header X-Robots-Tag "noindex, nofollow" + reverse_proxy 172.19.0.1:8080 +} diff --git a/caddy/deploy.sh b/caddy/deploy.sh new file mode 100755 index 0000000..698cd68 --- /dev/null +++ b/caddy/deploy.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")" +docker network create web 2>/dev/null || true +docker compose up -d +docker compose exec -T caddy caddy reload --config /etc/caddy/Caddyfile 2>/dev/null || true diff --git a/caddy/docker-compose.yml b/caddy/docker-compose.yml new file mode 100644 index 0000000..3e9385d --- /dev/null +++ b/caddy/docker-compose.yml @@ -0,0 +1,23 @@ +services: + caddy: + image: caddy:2-alpine + ports: + - "80:80" + - "443:443" + - "443:443/udp" + volumes: + - ./:/etc/caddy/ + - caddy_data:/data + - caddy_config:/config + restart: unless-stopped + networks: + - web + +networks: + web: + external: true + name: web + +volumes: + caddy_data: + caddy_config: diff --git a/claude-code-sessions.txt b/claude-code-sessions.txt deleted file mode 100644 index 250c3e8..0000000 --- a/claude-code-sessions.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Claude Code セッション設定 -# 形式: : -# repo は /home//workspaces/repos/ が存在すること -yyamashita:hetzner-infra -yyamashita:tokyo-livehouse-events -yyamashita:whois-band diff --git a/claude/sessions.txt b/claude/sessions.txt new file mode 100644 index 0000000..6df2af0 --- /dev/null +++ b/claude/sessions.txt @@ -0,0 +1,5 @@ +# Claude Code セッション設定 +# 形式: : +yyamashita:hetzner-infra +yyamashita:tokyo-livehouse-events +yyamashita:whois-band diff --git a/claude/sync.sh b/claude/sync.sh new file mode 100755 index 0000000..26f3da1 --- /dev/null +++ b/claude/sync.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# サーバー上で root として手動実行する +# 各ユーザーの Claude Code systemd user service を sessions.txt に基づいて同期する +set -euo pipefail + +APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" +TEMPLATE_SRC="$APP_DIR/claude/systemd/claude-code@.service" +SESSIONS_FILE="$APP_DIR/claude/sessions.txt" + +declare -A user_repos + +while IFS= read -r line; do + [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue + user="${line%%:*}" + repo="${line#*:}" + user_repos["$user"]+=" $repo" +done < "$SESSIONS_FILE" + +for user in "${!user_repos[@]}"; do + uid=$(id -u "$user" 2>/dev/null) || { echo "WARNING: user $user not found, skipping"; continue; } + runtime_dir="/run/user/$uid" + systemd_dir="/home/$user/.config/systemd/user" + + mkdir -p "$systemd_dir" + chown "$user:$user" "$systemd_dir" + + if ! diff -q "$TEMPLATE_SRC" "$systemd_dir/claude-code@.service" >/dev/null 2>&1; then + echo "[$user] Updating claude-code@.service template" + cp "$TEMPLATE_SRC" "$systemd_dir/claude-code@.service" + chown "$user:$user" "$systemd_dir/claude-code@.service" + runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ + systemctl --user daemon-reload + fi + + desired=() + for repo in ${user_repos[$user]}; do + [[ -z "$repo" ]] && continue + desired+=("$repo") + repo_path="/home/$user/workspaces/repos/$repo" + if [[ ! -d "$repo_path" ]]; then + echo "[$user] WARNING: $repo_path not found, skipping $repo" + continue + fi + runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ + systemctl --user enable "claude-code@${repo}.service" 2>/dev/null || true + if ! runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ + systemctl --user is-active "claude-code@${repo}.service" >/dev/null 2>&1; then + echo "[$user] Starting claude-code@${repo}.service" + runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ + systemctl --user start "claude-code@${repo}.service" || true + fi + done + + while IFS= read -r unit; do + instance="${unit#claude-code@}" + instance="${instance%.service}" + if ! printf '%s\n' "${desired[@]}" | grep -qx "$instance"; then + echo "[$user] Disabling claude-code@${instance}.service" + runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ + systemctl --user disable --now "claude-code@${instance}.service" || true + fi + done < <(runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ + systemctl --user list-unit-files --plain --no-legend 'claude-code@*.service' 2>/dev/null \ + | awk '$2 == "enabled" {print $1}') +done + +echo "Claude Code session sync complete." diff --git a/claude/systemd/claude-code@.service b/claude/systemd/claude-code@.service new file mode 100644 index 0000000..e3983b6 --- /dev/null +++ b/claude/systemd/claude-code@.service @@ -0,0 +1,17 @@ +[Unit] +Description=Claude Code Remote Session (%i) +After=network.target + +[Service] +Type=oneshot +RemainAfterExit=yes +WorkingDirectory=/home/yyamashita/workspaces/repos/%i +ExecStart=/usr/bin/tmux new-session -d -s claude-%i -c /home/yyamashita/workspaces/repos/%i /usr/local/bin/claude --remote-control %i --dangerously-skip-permissions +ExecStop=/usr/bin/tmux kill-session -t claude-%i +Environment=HOME=/home/yyamashita +Environment=USER=yyamashita +Environment=XDG_RUNTIME_DIR=/run/user/1000 +Environment=TMUX_TMPDIR=/tmp + +[Install] +WantedBy=default.target diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 3e9385d..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,23 +0,0 @@ -services: - caddy: - image: caddy:2-alpine - ports: - - "80:80" - - "443:443" - - "443:443/udp" - volumes: - - ./:/etc/caddy/ - - caddy_data:/data - - caddy_config:/config - restart: unless-stopped - networks: - - web - -networks: - web: - external: true - name: web - -volumes: - caddy_data: - caddy_config: diff --git a/git/hooks/hetzner-infra/post-receive b/git/hooks/hetzner-infra/post-receive new file mode 100755 index 0000000..d41659b --- /dev/null +++ b/git/hooks/hetzner-infra/post-receive @@ -0,0 +1,5 @@ +#!/bin/bash +set -e +GIT_WORK_TREE=/app/infra git checkout -f +bash /app/infra/caddy/deploy.sh +echo "Deploy complete: hetzner-infra" diff --git a/git/hooks/tokyo-livehouse-events/post-receive b/git/hooks/tokyo-livehouse-events/post-receive new file mode 100755 index 0000000..ca64767 --- /dev/null +++ b/git/hooks/tokyo-livehouse-events/post-receive @@ -0,0 +1,8 @@ +#!/bin/bash +set -e +APP_DIR=/app/tokyo-livehouse-events +GIT_WORK_TREE=$APP_DIR git checkout -f +cd $APP_DIR +mkdir -p data +docker compose up -d --build +echo "Deploy complete: tokyo-livehouse-events" diff --git a/git/hooks/whois-band/post-receive b/git/hooks/whois-band/post-receive new file mode 100755 index 0000000..60b368f --- /dev/null +++ b/git/hooks/whois-band/post-receive @@ -0,0 +1,8 @@ +#!/bin/bash +set -e +APP_DIR=/app/whois-band +GIT_WORK_TREE=$APP_DIR git checkout -f +cd $APP_DIR +mkdir -p data +docker compose up -d --build +echo "Deploy complete: whois-band" diff --git a/git/install.sh b/git/install.sh new file mode 100755 index 0000000..12f561c --- /dev/null +++ b/git/install.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# サーバー上で root として手動実行する +# repos.txt に基づいてベアリポジトリとワークツリーを作成し、 +# git/hooks/ のフックを /var/git/*/hooks/ に展開する +set -euo pipefail + +APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" +REPOS_FILE="$APP_DIR/git/repos.txt" +HOOKS_SRC="$APP_DIR/git/hooks" + +if [[ "$(id -u)" -ne 0 ]]; then + echo "ERROR: root として実行してください" >&2 + exit 1 +fi + +echo "=== Repositories ===" +while IFS=: read -r repo_name work_tree; do + [[ "$repo_name" =~ ^#.*$ || -z "$repo_name" ]] && continue + bare_repo="/var/git/${repo_name}.git" + + if [[ ! -d "$bare_repo" ]]; then + echo " create: $bare_repo" + mkdir -p "$bare_repo" + git init --bare "$bare_repo" + else + echo " exists: $bare_repo" + fi + + if [[ ! -d "$work_tree" ]]; then + echo " mkdir: $work_tree" + mkdir -p "$work_tree" + fi +done < "$REPOS_FILE" + +echo "" +echo "=== Hooks ===" +for repo_src in "$HOOKS_SRC"/*/; do + repo_name="$(basename "$repo_src")" + git_hooks_dir="/var/git/${repo_name}.git/hooks" + + if [[ ! -d "$git_hooks_dir" ]]; then + echo " SKIP: $git_hooks_dir not found ($repo_name)" + continue + fi + + for hook_file in "$repo_src"*; do + hook_name="$(basename "$hook_file")" + dst="$git_hooks_dir/$hook_name" + if diff -q "$hook_file" "$dst" >/dev/null 2>&1; then + echo " unchanged: $repo_name/$hook_name" + else + cp "$hook_file" "$dst" + chmod +x "$dst" + echo " installed: $repo_name/$hook_name" + fi + done +done + +echo "" +echo "Done." diff --git a/git/repos.txt b/git/repos.txt new file mode 100644 index 0000000..58ab877 --- /dev/null +++ b/git/repos.txt @@ -0,0 +1,5 @@ +# リポジトリ定義 +# 形式: : +hetzner-infra:/app/infra +tokyo-livehouse-events:/app/tokyo-livehouse-events +whois-band:/app/whois-band diff --git a/git/server-setup.sh b/git/server-setup.sh new file mode 100755 index 0000000..a575628 --- /dev/null +++ b/git/server-setup.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Run once on a fresh Hetzner VPS (as root). +# hetzner-infra のみブートストラップとして作成する。 +# 他のリポジトリは最初の push 後に git/install.sh が作成する。 +set -e + +REPO_DIR=/var/git/hetzner-infra.git +APP_DIR=/app/infra + +curl -fsSL https://get.docker.com | sh +docker network create web || true + +mkdir -p "$REPO_DIR" "$APP_DIR" +git init --bare "$REPO_DIR" + +# 最初の push を受け取るための最小限のフック(git/install.sh 実行後に上書きされる) +cat > "$REPO_DIR/hooks/post-receive" << 'HOOK' +#!/bin/bash +set -e +GIT_WORK_TREE=/app/infra git checkout -f +bash /app/infra/caddy/deploy.sh +echo "Deploy complete: hetzner-infra" +HOOK +chmod +x "$REPO_DIR/hooks/post-receive" + +echo "" +echo "Next steps:" +echo " 1. git remote add origin root@:$REPO_DIR" +echo " 2. git push origin master" +echo " 3. ssh root@ 'bash $APP_DIR/git/install.sh'" diff --git a/repos.txt b/repos.txt deleted file mode 100644 index e7cd697..0000000 --- a/repos.txt +++ /dev/null @@ -1,6 +0,0 @@ -# リポジトリ定義 -# 形式: : -# /var/git/.git が bare repo、 が checkout 先 -hetzner-infra:/app/infra -tokyo-livehouse-events:/app/tokyo-livehouse-events -whois-band:/app/whois-band diff --git a/scripts/claude-daemon-setup.sh b/scripts/claude-daemon-setup.sh deleted file mode 100644 index 0652e27..0000000 --- a/scripts/claude-daemon-setup.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -# Set up Claude Code remote-control daemons for each app repo (run as root on Hetzner VPS). -set -e - -# Install Claude Code if not present -if ! command -v claude &>/dev/null; then - npm install -g @anthropic-ai/claude-code -fi - -# Create non-root user for claude sessions (root is blocked by claude security policy) -if ! id claude-agent &>/dev/null; then - useradd -r -m -s /bin/bash claude-agent -fi -usermod -aG docker claude-agent -chown -R claude-agent:claude-agent /app - -# Copy credentials from root to claude-agent -cp /root/.claude.json /home/claude-agent/.claude.json -chown claude-agent:claude-agent /home/claude-agent/.claude.json - -declare -A REPOS=( - ["infra"]="/app/infra" - ["tokyo"]="/app" - ["whoisband"]="/app/whois-band" -) - -for NAME in "${!REPOS[@]}"; do - DIR="${REPOS[$NAME]}" - SERVICE="claude-${NAME}.service" - - cat > "/etc/systemd/system/${SERVICE}" << EOF -[Unit] -Description=Claude Code Remote Session - ${NAME} -After=network.target - -[Service] -Type=simple -User=claude-agent -WorkingDirectory=${DIR} -ExecStart=/usr/bin/script -q -c "claude --remote-control ${NAME}" /dev/null -Restart=always -RestartSec=15 -StandardOutput=journal -StandardError=journal - -[Install] -WantedBy=multi-user.target -EOF - - systemctl daemon-reload - systemctl enable "${SERVICE}" - systemctl restart "${SERVICE}" - echo "Started: ${SERVICE} (WorkingDirectory: ${DIR})" -done - -echo "" -echo "All Claude Code daemons running. Connect via https://claude.ai/code" -echo "" -echo "Useful commands:" -echo " systemctl status claude-infra" -echo " systemctl status claude-tokyo" -echo " systemctl status claude-whoisband" -echo " journalctl -u claude-tokyo -f" diff --git a/scripts/install.sh b/scripts/install.sh deleted file mode 100755 index 9f06489..0000000 --- a/scripts/install.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash -# サーバー上で root として手動実行する -# repos.txt に基づいてベアリポジトリとワークツリーを作成し、 -# server-hooks/ のフックを /var/git/*/hooks/ に展開する -set -euo pipefail - -APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" -REPOS_FILE="$APP_DIR/repos.txt" -HOOKS_SRC="$APP_DIR/server-hooks" - -if [[ "$(id -u)" -ne 0 ]]; then - echo "ERROR: root として実行してください" >&2 - exit 1 -fi - -# ベアリポジトリ・ワークツリー作成 -echo "=== Repositories ===" -while IFS=: read -r repo_name work_tree; do - [[ "$repo_name" =~ ^#.*$ || -z "$repo_name" ]] && continue - bare_repo="/var/git/${repo_name}.git" - - if [[ ! -d "$bare_repo" ]]; then - echo " create: $bare_repo" - mkdir -p "$bare_repo" - git init --bare "$bare_repo" - else - echo " exists: $bare_repo" - fi - - if [[ ! -d "$work_tree" ]]; then - echo " mkdir: $work_tree" - mkdir -p "$work_tree" - fi -done < "$REPOS_FILE" - -# フック展開 -echo "" -echo "=== Hooks ===" -for repo_src in "$HOOKS_SRC"/*/; do - repo_name="$(basename "$repo_src")" - git_hooks_dir="/var/git/${repo_name}.git/hooks" - - if [[ ! -d "$git_hooks_dir" ]]; then - echo " SKIP: $git_hooks_dir not found ($repo_name)" - continue - fi - - for hook_file in "$repo_src"*; do - hook_name="$(basename "$hook_file")" - dst="$git_hooks_dir/$hook_name" - if diff -q "$hook_file" "$dst" >/dev/null 2>&1; then - echo " unchanged: $repo_name/$hook_name" - else - cp "$hook_file" "$dst" - chmod +x "$dst" - echo " installed: $repo_name/$hook_name" - fi - done -done - -echo "" -echo "Done." diff --git a/scripts/server-setup.sh b/scripts/server-setup.sh deleted file mode 100644 index ca9a3f9..0000000 --- a/scripts/server-setup.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# Run once on a fresh Hetzner VPS (as root). -# hetzner-infra のみブートストラップとして作成する。 -# 他のリポジトリは最初の push 後に install.sh が作成する。 -set -e - -REPO_DIR=/var/git/hetzner-infra.git -APP_DIR=/app/infra - -# Install Docker -curl -fsSL https://get.docker.com | sh - -# Create shared Docker network -docker network create web || true - -# hetzner-infra bare repo をブートストラップ -mkdir -p "$REPO_DIR" "$APP_DIR" -git init --bare "$REPO_DIR" - -# 最初の push を受け取るための最小限のフック(install.sh 実行後に上書きされる) -cat > "$REPO_DIR/hooks/post-receive" << 'HOOK' -#!/bin/bash -set -e -APP_DIR=/app/infra -GIT_WORK_TREE=$APP_DIR git checkout -f -cd $APP_DIR -docker network create web 2>/dev/null || true -docker compose up -d -docker compose exec -T caddy caddy reload --config /etc/caddy/Caddyfile 2>/dev/null || true -echo "Deploy complete: hetzner-infra" -if [ -f "$APP_DIR/scripts/sync-claude-services.sh" ]; then - bash "$APP_DIR/scripts/sync-claude-services.sh" -fi -HOOK -chmod +x "$REPO_DIR/hooks/post-receive" - -echo "" -echo "Next steps:" -echo " 1. git remote add origin root@:$REPO_DIR" -echo " 2. git push origin master" -echo " 3. ssh root@ 'bash $APP_DIR/scripts/install.sh'" -echo " (他のリポジトリ作成 + 全フックの正式インストール)" diff --git a/scripts/sync-claude-services.sh b/scripts/sync-claude-services.sh deleted file mode 100755 index a9a76fb..0000000 --- a/scripts/sync-claude-services.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -# サーバー側で root として実行し、各ユーザーの Claude Code systemd user service を同期する -set -euo pipefail - -APP_DIR="$(cd "$(dirname "$0")/.." && pwd)" -TEMPLATE_SRC="$APP_DIR/systemd/user/claude-code@.service" -SESSIONS_FILE="$APP_DIR/claude-code-sessions.txt" - -# sessions.txt をパースして user -> repos のマップを構築 -declare -A user_repos - -while IFS= read -r line; do - [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue - user="${line%%:*}" - repo="${line#*:}" - user_repos["$user"]+=" $repo" -done < "$SESSIONS_FILE" - -for user in "${!user_repos[@]}"; do - uid=$(id -u "$user" 2>/dev/null) || { echo "WARNING: user $user not found, skipping"; continue; } - runtime_dir="/run/user/$uid" - systemd_dir="/home/$user/.config/systemd/user" - - mkdir -p "$systemd_dir" - chown "$user:$user" "$systemd_dir" - - # テンプレートを更新(差分があれば) - if ! diff -q "$TEMPLATE_SRC" "$systemd_dir/claude-code@.service" >/dev/null 2>&1; then - echo "[$user] Updating claude-code@.service template" - cp "$TEMPLATE_SRC" "$systemd_dir/claude-code@.service" - chown "$user:$user" "$systemd_dir/claude-code@.service" - runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ - systemctl --user daemon-reload - fi - - # sessions.txt で指定されたリポジトリを enable & start - desired=() - for repo in ${user_repos[$user]}; do - [[ -z "$repo" ]] && continue - desired+=("$repo") - repo_path="/home/$user/workspaces/repos/$repo" - if [[ ! -d "$repo_path" ]]; then - echo "[$user] WARNING: $repo_path not found, skipping $repo" - continue - fi - runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ - systemctl --user enable "claude-code@${repo}.service" 2>/dev/null || true - if ! runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ - systemctl --user is-active "claude-code@${repo}.service" >/dev/null 2>&1; then - echo "[$user] Starting claude-code@${repo}.service" - runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ - systemctl --user start "claude-code@${repo}.service" || true - fi - done - - # sessions.txt にないが enabled になっているインスタンスを無効化 - while IFS= read -r unit; do - instance="${unit#claude-code@}" - instance="${instance%.service}" - if ! printf '%s\n' "${desired[@]}" | grep -qx "$instance"; then - echo "[$user] Disabling claude-code@${instance}.service (not in sessions.txt)" - runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ - systemctl --user disable --now "claude-code@${instance}.service" || true - fi - done < <(runuser -u "$user" -- env XDG_RUNTIME_DIR="$runtime_dir" DBUS_SESSION_BUS_ADDRESS="unix:path=$runtime_dir/bus" \ - systemctl --user list-unit-files --plain --no-legend 'claude-code@*.service' 2>/dev/null \ - | awk '$2 == "enabled" {print $1}') -done - -echo "Claude Code session sync complete." diff --git a/server-hooks/hetzner-infra/post-receive b/server-hooks/hetzner-infra/post-receive deleted file mode 100755 index cc3fa8e..0000000 --- a/server-hooks/hetzner-infra/post-receive +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -e -APP_DIR=/app/infra -GIT_WORK_TREE=$APP_DIR git checkout -f -cd $APP_DIR -docker network create web 2>/dev/null || true -docker compose up -d -docker compose exec -T caddy caddy reload --config /etc/caddy/Caddyfile 2>/dev/null || true -echo "Deploy complete: hetzner-infra" - -# Claude Code セッション同期 -if [ -f "$APP_DIR/scripts/sync-claude-services.sh" ]; then - bash "$APP_DIR/scripts/sync-claude-services.sh" -fi diff --git a/server-hooks/tokyo-livehouse-events/post-receive b/server-hooks/tokyo-livehouse-events/post-receive deleted file mode 100755 index ca64767..0000000 --- a/server-hooks/tokyo-livehouse-events/post-receive +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e -APP_DIR=/app/tokyo-livehouse-events -GIT_WORK_TREE=$APP_DIR git checkout -f -cd $APP_DIR -mkdir -p data -docker compose up -d --build -echo "Deploy complete: tokyo-livehouse-events" diff --git a/server-hooks/whois-band/post-receive b/server-hooks/whois-band/post-receive deleted file mode 100755 index 60b368f..0000000 --- a/server-hooks/whois-band/post-receive +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e -APP_DIR=/app/whois-band -GIT_WORK_TREE=$APP_DIR git checkout -f -cd $APP_DIR -mkdir -p data -docker compose up -d --build -echo "Deploy complete: whois-band" diff --git a/systemd/user/claude-code@.service b/systemd/user/claude-code@.service deleted file mode 100644 index e3983b6..0000000 --- a/systemd/user/claude-code@.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Claude Code Remote Session (%i) -After=network.target - -[Service] -Type=oneshot -RemainAfterExit=yes -WorkingDirectory=/home/yyamashita/workspaces/repos/%i -ExecStart=/usr/bin/tmux new-session -d -s claude-%i -c /home/yyamashita/workspaces/repos/%i /usr/local/bin/claude --remote-control %i --dangerously-skip-permissions -ExecStop=/usr/bin/tmux kill-session -t claude-%i -Environment=HOME=/home/yyamashita -Environment=USER=yyamashita -Environment=XDG_RUNTIME_DIR=/run/user/1000 -Environment=TMUX_TMPDIR=/tmp - -[Install] -WantedBy=default.target -- cgit v1.2.3