From a83d34b7bbcf04374eb2e0228e86c12bc93fc057 Mon Sep 17 00:00:00 2001 From: Bakhomious Basta Date: Tue, 27 Oct 2026 23:08:02 +0100 Subject: [PATCH] docs: keep the tailnet's name out of the repo The image workflow takes the registry from Gitea's own address. --- .gitea/workflows/image.yaml | 7 +++++-- docs/plan.md | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/image.yaml b/.gitea/workflows/image.yaml index 428f440..03b70f3 100644 --- a/.gitea/workflows/image.yaml +++ b/.gitea/workflows/image.yaml @@ -23,8 +23,6 @@ jobs: timeout-minutes: 15 env: BUILDKIT_HOST: tcp://buildkitd.buildkit.svc:1234 - REGISTRY: git.tail9e9088.ts.net - IMAGE: git.tail9e9088.ts.net/codedogapp/nudge # renovate: datasource=github-releases depName=moby/buildkit BUILDKIT_VERSION: v0.34.1 steps: @@ -32,6 +30,11 @@ jobs: with: fetch-depth: 0 persist-credentials: false + - name: Name the registry + run: | + # Gitea's own address, so that the tailnet's name stays out of this public repo. + echo "REGISTRY=${GITHUB_SERVER_URL#https://}" >> "$GITHUB_ENV" + echo "IMAGE=${GITHUB_SERVER_URL#https://}/codedogapp/nudge" >> "$GITHUB_ENV" - name: Install buildctl run: | curl -fsSL "https://github.com/moby/buildkit/releases/download/$BUILDKIT_VERSION/buildkit-$BUILDKIT_VERSION.linux-amd64.tar.gz" \ diff --git a/docs/plan.md b/docs/plan.md index ea27fcc..2d84621 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -61,7 +61,7 @@ This document is the source of truth for scope and the work breakdown. How we wo | `ingress-check` | A throwaway pod behind a `tailscale` Ingress in the homelab: does the proxy send `Tailscale-User-Login` and the Ingress's name as `Host`, and does it keep a request open for hours (risk 12). Done: the proxy sends both; a request held 330 s was answered; hours untested | Done | | `container-image` | A Dockerfile in this repo: a static `linux/amd64` Go binary, non-root, `nudge serve` as the entrypoint. Done: it cross-compiles on the build host (QEMU crashed the Go toolchain on a Mac); 5.7 MB; ran with a read-only root and answered 200 with the login header and 403 without | Done | | `server-setting` | A `server` key in the settings file, read by `nudge ask` and `nudge mcp` as `NUDGE_SERVER` is (decision 36). `nudge setup` doesn't write it yet; the user adds it to the settings file by hand | Done | -| `image-workflow` | `.gitea/workflows/image.yaml`: builds with BuildKit and pushes `git.tail9e9088.ts.net/codedogapp/nudge` (`:main` and `:sha-<7>` for main, `:vX.Y.Z` for a tag) from the Gitea mirror. Needs the mirror with Actions on (the user, in Gitea); untested until then | Todo | +| `image-workflow` | `.gitea/workflows/image.yaml`: builds with BuildKit and pushes `git..ts.net/codedogapp/nudge` (`:main` and `:sha-<7>` for main, `:vX.Y.Z` for a tag) from the Gitea mirror. Needs the mirror with Actions on (the user, in Gitea); untested until then | Todo | | `k8s-manifests` | `cluster/nudge/` in the homelab repo (plain YAML, Flux): Deployment, volume, Service, Ingress, and a doc there (decision 36). `codedogapp/homelab#7`, for the user's review; the namespace and the Secret `nudge` already exist in the cluster | In review | | `setup-client` | `nudge setup SERVER` becomes the client setup: it writes the `server` setting, writes the skill from the binary, and adds both to Copilot CLI (decision 37) | Done | | `cutover` | The cluster serves the phone and the agents (checked 2026-10-27). The Mac's brew service, `tailscale serve`, formula and tap are retired; the binary comes from `go install`. Left for the user: delete the GitHub repo `codedogapp/homebrew-tap` (`gh auth refresh -s delete_repo`, then `gh repo delete`) | In review | @@ -167,7 +167,7 @@ sequenceDiagram 33. **`nudge setup`**: my design for decision 32's command, for the user's review. It is idempotent and never touches the running service. It (1) writes the settings file with the login and host from `tailscale status --json`, unless the file exists, which it leaves alone; (2) runs `tailscale serve --bg --https=8443 8700`, which Tailscale itself accepts a second time; (3) runs `copilot mcp add --timeout 86400000 nudge -- mcp`, unless `copilot mcp get nudge` finds it, because `add` fails on an existing server; and (4) runs `copilot skill add `, which accepts a second time. `` and `` are under `brew --prefix codedogapp/tap/nudge`, the path that survives upgrades. Each step prints one line. A missing tool (`tailscale`, `copilot`, `brew`) fails that step with its name. The Home Screen and notifications stay manual, and `nudge setup` ends by saying so. The steps run external tools through a small function, which is the tests' seam. 34. **Multi-device**: the user's choice (2026-10-25): one nudge server, on the personal Mac, and one page with every question labelled by its machine; the work laptop is on the same tailnet and runs only `nudge ask` and `nudge mcp`, with no server. Proposal, for the user's review: the phone door gets an agent API under `/agent/`, with the endpoints of the agent door, and the same lock (the Tailscale login), so a laptop on the tailnet under the same login can reach it through `tailscale serve`. `nudge ask` and `nudge mcp` then read `NUDGE_SERVER` (an https URL) in place of the socket, and send the machine's name, which the page shows next to each question and session. It breaks "Two doors, two locks" (AGENTS.md), and any process that holds the login can then ask or answer; so it stays unbuilt until the user accepts it (ยง6 question 7). 35. **Multi-device, where the server runs**: the user's choices (2026-10-26): they accept agents on other machines reaching the server through the tailnet door, with the same Tailscale login on every machine (AGENTS.md's two-doors rule is amended). The server will run in an always-on local Kubernetes cluster on another laptop, and the tailnet will reach the whole cluster, so the Tailscale Kubernetes operator (or a sidecar) can publish it and add the login headers. Consequences, my design for the user's review: the VAPID key and the settings come from a file or the environment where there is no Keychain (a Kubernetes Secret), the subscriptions need a small volume or devices subscribe again after a restart, and the image is built from this repo. The Mac's `brew services` install stays for a single-machine setup. The agent API lies under `/agent/` on the phone door and is no different for a local agent that chooses `NUDGE_SERVER`. -36. **Hosting in the homelab** (the user's choices, 2026-10-27): the k3s homelab is ready (single node, `linux/amd64`, Flux from GitHub, Gitea with a registry and BuildKit, the Tailscale operator). Plan, my design for the user's review: the image is built by a Gitea workflow from the mirror of this repo and lives in Gitea's registry; the manifests are plain YAML in the homelab repo's `cluster/nudge/` (that repo's convention), written by me and reviewed by the user; an Ingress of class `tailscale` publishes the page on `https://nudge.tail9e9088.ts.net`, so `NUDGE_HOST` becomes that name and devices subscribe again at the new address; one replica with the `Recreate` strategy, because the server keeps questions in memory; a small volume holds the VAPID key and the subscriptions (`NUDGE_VAPID_KEY_FILE`, `NUDGE_SUBSCRIPTIONS`); client machines get the server from a `server` key in their settings file, which `nudge ask` and `nudge mcp` read. After the user confirms the cluster works, the Mac's service and `tailscale serve` are retired. +36. **Hosting in the homelab** (the user's choices, 2026-10-27): the k3s homelab is ready (single node, `linux/amd64`, Flux from GitHub, Gitea with a registry and BuildKit, the Tailscale operator). Plan, my design for the user's review: the image is built by a Gitea workflow from the mirror of this repo and lives in Gitea's registry; the manifests are plain YAML in the homelab repo's `cluster/nudge/` (that repo's convention), written by me and reviewed by the user; an Ingress of class `tailscale` publishes the page on `https://nudge..ts.net`, so `NUDGE_HOST` becomes that name and devices subscribe again at the new address; one replica with the `Recreate` strategy, because the server keeps questions in memory; a small volume holds the VAPID key and the subscriptions (`NUDGE_VAPID_KEY_FILE`, `NUDGE_SUBSCRIPTIONS`); client machines get the server from a `server` key in their settings file, which `nudge ask` and `nudge mcp` read. After the user confirms the cluster works, the Mac's service and `tailscale serve` are retired. 37. **Homebrew retired** (the user's choices, 2026-10-27): with the server in the cluster, nothing runs on a Mac but `nudge mcp` and `nudge ask`, so the tap, the formula and `brew services` go, and clients install with `go install github.com/codedogapp/nudge@latest` (the user chose it over release binaries and over an HTTP MCP endpoint). `nudge setup SERVER` replaces the Mac setup of decision 33: no `tailscale serve`, no settings from `tailscale status`; the skill is embedded in the binary, since no formula installs its folder. Decisions 33 and the Homebrew facts and risk 11 are history. The Mac's Keychain VAPID key and the local subscriptions file were deleted; the cluster has its own key, so each phone subscribed again. ## 5. Risks