Files
Gan, Jimmy 755a0b6ae9
Deploy Dashboard (Dev) / deploy-dev (push) Has been cancelled
Deploy Claude Dev (Dev) / deploy-claude-dev-dev (push) Has started running
feat: add CI-gated claude-dev image package
Define claude-dev capabilities as a tested contract and deploy immutable tags only after smoke checks so daily tooling upgrades remain CI-first and rollback-safe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 23:40:44 +08:00

3.2 KiB

NAS Tools Project

Architecture

  • Synology DS224+ (x86_64, 18GB RAM), Tailscale IP: 100.78.131.124, LAN: 192.168.31.221
  • Docker: /volume1/@appstore/ContainerManager/usr/bin/docker, compose dirs: /volume1/docker/*
  • Caddy VPS (161.33.182.109, Tailscale: 100.109.198.126): reverse proxy for nas.jimmygan.com → NAS:4000, music.jimmygan.com → NAS:4533
  • Build VPS (server2, 158.101.140.85, Tailscale: 100.70.115.1): podman, fast network for pulling images

Dashboard

  • Backend: Python FastAPI (dashboard/backend/)
  • Frontend: Svelte 5 + Tailwind CSS (dashboard/frontend/)
  • Svelte 5 runes: use $state, $props, $bindable (not legacy export let)
  • Sidebar: categorized as Main (Overview, Docker, Files, Terminal), Media (Navidrome, Jellyfin, Audiobookshelf, Immich), Tools (OpenClaw, Repos, Gitea Web, Stirling PDF, Vaultwarden, Speedtest)
  • New pages: create route in src/routes/, import in App.svelte, add to appropriate category in Sidebar.svelte

Build & Deploy

  • Build images on Mac: docker build --platform linux/amd64
  • Transfer: docker save <image> | ssh zjgump@100.78.131.124 "/volume1/@appstore/ContainerManager/usr/bin/docker load"
  • Deploy: git push triggers Gitea Actions CI (docker compose up -d --pull never) — do NOT manually restart
  • CI workflows are in .gitea/workflows/ in this repo

claude-dev CI Contract

  • Source package lives in claude-dev/ (Dockerfile, required-tools.txt, and smoke scripts under claude-dev/scripts/)
  • CI-first only: update claude-dev/* in git, then push; do not do ad-hoc local image rebuild/redeploy for normal changes
  • Required capabilities are declared in claude-dev/required-tools.txt; adding tools must update this file and related smoke checks
  • Build/deploy gate (.gitea/workflows/deploy-claude-dev-dev.yml) uses NAS runner with DOCKER_BUILDKIT=0, then runs:
    • tools smoke (smoke-tools.sh)
    • network smoke (smoke-network.sh)
    • auth/mount smoke (smoke-auth.sh with required runtime mounts)
  • Deployment only happens after smoke pass, using immutable tag format claude-dev:dev-<timestamp>-<sha>
  • Runtime compose definition is claude-dev/docker-compose.yml; CI syncs it to /volume1/docker/claude-dev/docker-compose.yml
  • Runtime requirements preserved: network_mode: host, /volume1/repos mount, /root/.claude mount, /root/.claude.json mount, /root/.gitea_token mount
  • Rollback: run workflow manually with rollback_image (for example the value in /volume1/docker/claude-dev/previous-image.txt) to redeploy a known-good immutable tag via CI

Synology Quirks

  • No crontab — edit /etc/crontab with sudo + printf, restart crond
  • No scp subsystem — use cat file | ssh ... 'cat > dest'
  • ACLs override Unix perms — use sudo chmod 777 + synoacltool -enforce-inherit for bind mounts

DNS

  • dnsmasq on NAS resolves *.jimmygan.com161.33.182.109 (Caddy VPS)
  • Tailscale split DNS: jimmygan.com → NAS (queries hit dnsmasq)
  • All paths (LAN, Tailscale, public) route through Caddy for TLS

Proxy API

  • URL: https://www.bytecatcode.org
  • Models: claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5-20251001 (no date-suffixed names)