vibed-infra 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/github/__pycache__/notify-vps-pull.cpython-312.pyc +0 -0
- package/lib/__pycache__/generate.cpython-312.pyc +0 -0
- package/lib/__pycache__/github_oidc.cpython-312.pyc +0 -0
- package/lib/__pycache__/load_config.cpython-312.pyc +0 -0
- package/lib/__pycache__/product_config.cpython-312.pyc +0 -0
- package/lib/__pycache__/webhook.cpython-312.pyc +0 -0
- package/lib/package.py +4 -0
- package/lib/persistlog/__pycache__/__init__.cpython-312.pyc +0 -0
- package/package.json +1 -1
- package/schema/packageconfig.md +9 -4
- package/skills/infra-cicd/SKILL.md +4 -4
- package/skills/infra-packager/SKILL.md +7 -6
- package/skills/infra-update-agent/SKILL.md +28 -21
- package/skills/system-gateway/SKILL.md +2 -2
- package/templates/update-agent/__pycache__/webhook_server.cpython-312.pyc +0 -0
package/README.md
CHANGED
|
@@ -41,10 +41,17 @@ Multi-app: further products’ `install-gateway.sh` only add `apps/{other}/sites
|
|
|
41
41
|
| Path | Purpose |
|
|
42
42
|
|------|---------|
|
|
43
43
|
| `~/services/gateway` | Host nginx (`GATEWAY_HOME`) |
|
|
44
|
-
| `~/services/vibed-infra/update-agent` | Serial pull queue
|
|
44
|
+
| `~/services/vibed-infra/update-agent` | Serial pull queue; GHCR notify via GitHub Actions OIDC |
|
|
45
45
|
| `~/services/vibed-infra/persist-logs` | Per-app WALs + optional R2/S3 ship |
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
## Image updates (docker pull)
|
|
48
|
+
|
|
49
|
+
Install registers each role in the machine **update-agent**. Two paths enqueue work; the agent runs **one pull at a time** (`update-*.sh` is digest-gated — no restart if the image digest is unchanged):
|
|
50
|
+
|
|
51
|
+
1. **Immediate** — push `:main` with the reusable GHCR workflow (`id-token: write`). CI mints an OIDC JWT and POSTs `https://{site host}/_vibed/hooks/ghcr` (fallback `http://{publicIp}/…`). No GitHub webhook UI or `VIBED_WEBHOOK_SECRET`.
|
|
52
|
+
2. **Cron** — if `*_AUTO_UPDATE=1`, periodic enqueue (backup if notify is missed).
|
|
53
|
+
|
|
54
|
+
See [`skills/infra-update-agent/SKILL.md`](skills/infra-update-agent/SKILL.md). After a successful update, dangling images are pruned (`DOCKER_AUTO_PRUNE=1`).
|
|
48
55
|
|
|
49
56
|
## Layout
|
|
50
57
|
|
|
@@ -55,7 +62,7 @@ Auto-update cron **enqueues** work; the agent processes one job at a time. After
|
|
|
55
62
|
| `templates/update-agent/` | Queue agent + webhook |
|
|
56
63
|
| `templates/persist-logs/` | Shipper install |
|
|
57
64
|
| `lib/persistlog/` | Python append / seal / replay |
|
|
58
|
-
| `skills/` | system-gateway, infra-update-agent, persist-logs, dns-configure |
|
|
65
|
+
| `skills/` | system-gateway, infra-update-agent, infra-cicd, infra-packager, persist-logs, dns-configure |
|
|
59
66
|
|
|
60
67
|
## Environment
|
|
61
68
|
|
|
@@ -63,6 +70,7 @@ Auto-update cron **enqueues** work; the agent processes one job at a time. After
|
|
|
63
70
|
|----------|---------|
|
|
64
71
|
| `GATEWAY_HOME` | Host gateway dir (default `~/services/gateway`) |
|
|
65
72
|
| `VIBED_HOME` | Machine vibed root (default `~/services/vibed-infra`) |
|
|
73
|
+
| `VIBED_UPDATE_AGENT` | Override update-agent dir (default `$VIBED_HOME/update-agent`) |
|
|
66
74
|
| `GATEWAY_PUBLIC_IP` | VPS IPv4 (from `gateway.publicIp`) |
|
|
67
75
|
| `TLS_EMAIL` / `TLS_MODE` | Let’s Encrypt email; `lab` or `letsencrypt` |
|
|
68
76
|
| `PERSIST_LOG_DIR` | Per-service event log dir |
|
|
@@ -72,6 +80,7 @@ Auto-update cron **enqueues** work; the agent processes one job at a time. After
|
|
|
72
80
|
|
|
73
81
|
```bash
|
|
74
82
|
npm test
|
|
83
|
+
npm run test:oidc # real GitHub OIDC mint; skips locally unless ACTIONS_ID_TOKEN_* set
|
|
75
84
|
npm run test:dist
|
|
76
85
|
npm run test:e2e-multi # two apps, localhost wget|bash, shared host gateway
|
|
77
86
|
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/package.py
CHANGED
|
@@ -351,6 +351,10 @@ wget -qO- https://raw.githubusercontent.com/ORG/REPO/main/dist/install-gateway.s
|
|
|
351
351
|
Network: `{meta['network']}` (shared host edge). API container: `{meta['apiContainer']}`.
|
|
352
352
|
Gateway install bootstraps `~/services/gateway` once, then drops `apps/{{product}}/sites.conf`.
|
|
353
353
|
|
|
354
|
+
## Image updates
|
|
355
|
+
|
|
356
|
+
wget install registers this product with the machine update-agent. A GHCR `:main` push (reusable workflow + `id-token: write`) POSTs `/_vibed/hooks/ghcr` so the VPS pulls immediately. Cron `*_AUTO_UPDATE` is a backup. See the packager’s infra-update-agent skill.
|
|
357
|
+
|
|
354
358
|
## DNS (AU agent)
|
|
355
359
|
|
|
356
360
|
Copy [`DNS-SKILL.md`](DNS-SKILL.md) into an AU agent browser extension. Domains and `gateway.publicIp` are baked in when configured; confirm the IP with the operator.
|
|
Binary file
|
package/package.json
CHANGED
package/schema/packageconfig.md
CHANGED
|
@@ -39,7 +39,7 @@ Compiled `packageconfig.yaml` also includes `webhook.url` / `fallbackUrl` (from
|
|
|
39
39
|
| Path | Purpose |
|
|
40
40
|
|------|---------|
|
|
41
41
|
| `install-*.sh` | wget entrypoints |
|
|
42
|
-
| `notify-vps-pull.py` |
|
|
42
|
+
| `notify-vps-pull.py` | GHCR workflow: mint OIDC JWT and POST webhook URLs from `webhook:` |
|
|
43
43
|
| `DNS-SKILL.md` | Paste into AU browser agent; includes domains + `publicIp` when set |
|
|
44
44
|
| `packageconfig.yaml` | compiled config |
|
|
45
45
|
| `start-*.sh` / `update-*.sh` | lifecycle |
|
|
@@ -47,11 +47,15 @@ Compiled `packageconfig.yaml` also includes `webhook.url` / `fallbackUrl` (from
|
|
|
47
47
|
|
|
48
48
|
Gateway install writes `$GATEWAY_HOME/apps/{name}/sites.conf` (host-extension mode).
|
|
49
49
|
|
|
50
|
-
## Auto-update
|
|
50
|
+
## Auto-update and docker pull
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Install registers each role with the machine **update-agent**. Pulls are serial and digest-gated (`update-*.sh`).
|
|
53
53
|
|
|
54
|
-
Immediate
|
|
54
|
+
- **Immediate:** reusable GHCR workflow on the default branch mints a GitHub Actions OIDC JWT and POSTs `https://{host}/_vibed/hooks/ghcr` (fallback `http://{publicIp}/_vibed/hooks/ghcr`). Caller needs `id-token: write`. See [`skills/infra-update-agent/SKILL.md`](../skills/infra-update-agent/SKILL.md).
|
|
55
|
+
- **Cron:** when `*_AUTO_UPDATE=1`, cron enqueues on an interval (backup if notify is missed). Fallback: direct `update-*.sh` if the agent is missing.
|
|
56
|
+
- After update: dangling image prune (`DOCKER_AUTO_PRUNE`).
|
|
57
|
+
|
|
58
|
+
`webhook.token` in compiled packageconfig is only for local curl; CI does not need `VIBED_WEBHOOK_SECRET`.
|
|
55
59
|
|
|
56
60
|
## Persist logs
|
|
57
61
|
|
|
@@ -63,6 +67,7 @@ Immediate pulls: install registers the app. The reusable docker-build workflow m
|
|
|
63
67
|
|----------|---------|
|
|
64
68
|
| `GATEWAY_HOME` | Host gateway (default `~/services/gateway`) |
|
|
65
69
|
| `VIBED_HOME` | `~/services/vibed-infra` |
|
|
70
|
+
| `VIBED_UPDATE_AGENT` | Override update-agent dir (default `$VIBED_HOME/update-agent`) |
|
|
66
71
|
| `GATEWAY_PUBLIC_IP` / `TLS_EMAIL` / `TLS_MODE` | Host TLS (`setup-tls.sh`) |
|
|
67
72
|
| `PACKAGER_RAW` / `PRODUCT_RAW` / `PACKAGECONFIG_URL` | as before |
|
|
68
73
|
| `INFRA_PROFILE` | `api`, `ui`, `nodes`, `gateway` |
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
name: infra-cicd
|
|
3
3
|
description: >-
|
|
4
4
|
Set up GitHub Actions CI/CD for infra-packaged products: GHCR image build,
|
|
5
|
-
package validation, and dist e2e
|
|
6
|
-
pipelines for Backend/UI/worker images.
|
|
5
|
+
OIDC notify for immediate VPS pulls, package validation, and dist e2e.
|
|
7
6
|
---
|
|
8
7
|
|
|
9
8
|
# Infra packager CI/CD
|
|
@@ -39,13 +38,14 @@ On the default branch, the reusable workflow mints a GitHub Actions OIDC JWT (au
|
|
|
39
38
|
## Product repo CI
|
|
40
39
|
|
|
41
40
|
1. Run `./package.sh` and fail if `dist/` drifted from templates (optional `git diff --exit-code dist`).
|
|
42
|
-
2. Build/push images to GHCR (reusable workflow notifies the VPS
|
|
41
|
+
2. Build/push images to GHCR (reusable workflow notifies the VPS; requires `id-token: write`).
|
|
43
42
|
3. Optional job: `test-dist.sh --profile api` on a Docker-enabled runner.
|
|
44
43
|
|
|
45
44
|
## Checklist
|
|
46
45
|
|
|
47
46
|
- [ ] Four YAML templates under `templates/` (`gateway.publicIp` / `tlsEmail` / `sites[]` set for production)
|
|
48
47
|
- [ ] Committed `dist/` matches `./package.sh` output (including `DNS-SKILL.md`)
|
|
49
|
-
- [ ] Image names in configs match GHCR
|
|
48
|
+
- [ ] Image names in configs match GHCR (`ghcr.io/{owner}/…` so OIDC `repository_owner` can match)
|
|
49
|
+
- [ ] GHCR reusable job has `permissions.id-token: write`
|
|
50
50
|
- [ ] `npm test` / install dry-run passes
|
|
51
51
|
- [ ] Secrets not in templates — only `.env.*.example` placeholders (publicIp/domain are OK to commit)
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: infra-packager
|
|
3
3
|
description: >-
|
|
4
4
|
Wire a new product to the infra VPS packager: four YAML configs, package.sh →
|
|
5
|
-
committed dist/, Docker images, and CI. Use when adding
|
|
6
|
-
deploy to a repo or migrating from ad-hoc
|
|
5
|
+
committed dist/, Docker images, GHCR OIDC pulls, and CI. Use when adding
|
|
6
|
+
Backend/UI/worker deploy to a repo or migrating from ad-hoc install scripts.
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Infra packager — onboard a product
|
|
@@ -17,7 +17,7 @@ description: >-
|
|
|
17
17
|
|
|
18
18
|
1. **Depend on** [`vibed-infra`](https://www.npmjs.com/package/vibed-infra) or clone this repo for `package.sh`.
|
|
19
19
|
|
|
20
|
-
2. **Create** `templates/` with four files — see [`schema/packageconfig.md`](../../schema/packageconfig.md) and [`examples/vps-hello/templates/`](../../examples/vps-hello/templates/). Set `gateway.publicIp`, `gateway.tlsEmail`, and `gateway.sites[].host` for DNS-SKILL + HTTPS.
|
|
20
|
+
2. **Create** `templates/` with four files — see [`schema/packageconfig.md`](../../schema/packageconfig.md) and [`examples/vps-hello/templates/`](../../examples/vps-hello/templates/). Set `gateway.publicIp`, `gateway.tlsEmail`, and `gateway.sites[].host` for DNS-SKILL + HTTPS (those values are also the GHCR notify URLs).
|
|
21
21
|
|
|
22
22
|
3. **Add** a tiny product `package.sh`:
|
|
23
23
|
|
|
@@ -27,7 +27,7 @@ PACKAGER="$(node -e "console.log(require('path').dirname(require.resolve('vibed-
|
|
|
27
27
|
exec bash "$PACKAGER/package.sh" --product "$ROOT" --out "$ROOT/dist"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
4. **
|
|
30
|
+
4. **Images** — Dockerfiles in `app/`; tag `:local` for dev; GHCR `:main` for prod (names in `*-config.yaml`). Immediate VPS pull uses the reusable GHCR workflow with `id-token: write` — see infra-cicd and infra-update-agent. No extra GitHub secret.
|
|
31
31
|
|
|
32
32
|
5. **Package and commit** `dist/` (includes `DNS-SKILL.md` with domains + public IP):
|
|
33
33
|
|
|
@@ -36,9 +36,9 @@ exec bash "$PACKAGER/package.sh" --product "$ROOT" --out "$ROOT/dist"
|
|
|
36
36
|
git add dist && git commit && git push
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
6. **CI** —
|
|
39
|
+
6. **CI** — product repo: package drift check + GHCR build (notifies VPS). Packager repo: `npm test`, `oidc-webhook-e2e`, `test-dist.sh`, `npm run test:e2e-multi`.
|
|
40
40
|
|
|
41
|
-
7. **VPS** — DNS first (paste `dist/DNS-SKILL.md` into AU agent), then wget:
|
|
41
|
+
7. **VPS** — DNS first (paste `dist/DNS-SKILL.md` into AU agent), then wget. Install registers the app with the update-agent so the next GHCR push can pull immediately:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
wget -qO- .../dist/install-api.sh | bash
|
|
@@ -56,3 +56,4 @@ wget -qO- .../dist/install-gateway.sh | bash # bootstraps host + setup-tls.sh
|
|
|
56
56
|
- Gateway container names in `gateway.sites[]` must match running API/UI container names on `network.edge`.
|
|
57
57
|
- UI is a separate profile; gateway is nginx-only and does not start the UI.
|
|
58
58
|
- Prefer Let's Encrypt via `gateway.tlsEmail`; use `TLS_MODE=lab` only for CI/lab.
|
|
59
|
+
- Product GHCR workflow must set `id-token: write` or the VPS will not get an immediate pull.
|
|
@@ -3,44 +3,50 @@ name: infra-update-agent
|
|
|
3
3
|
description: >-
|
|
4
4
|
Machine-level serial Docker update queue for vibed-infra apps. Use when
|
|
5
5
|
multiple products share one VPS and must not pull images in parallel; includes
|
|
6
|
-
GHCR
|
|
6
|
+
immediate GHCR pulls via GitHub Actions OIDC (no extra GitHub secrets).
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Serial update agent
|
|
10
10
|
|
|
11
11
|
## Why
|
|
12
12
|
|
|
13
|
-
Five apps with auto-update cron would each `docker pull` at once and overload the box. The **update-agent** is installed once; apps only **enqueue** jobs.
|
|
13
|
+
Five apps with auto-update cron would each `docker pull` at once and overload the box. The **update-agent** is installed once; apps only **enqueue** jobs. The agent runs `update-*.sh`, which is **digest-gated**: pull if the registry digest changed, restart only if the running container is stale.
|
|
14
14
|
|
|
15
15
|
## Layout
|
|
16
16
|
|
|
17
17
|
```
|
|
18
18
|
~/services/vibed-infra/update-agent/
|
|
19
19
|
queue/ processing/ done/ failed/
|
|
20
|
-
registry/{app}/{role}.json
|
|
21
|
-
tokens/{app}
|
|
20
|
+
registry/{app}/{role}.json # image + installDir (written at wget install)
|
|
21
|
+
tokens/{app} # optional local curl; CI uses OIDC
|
|
22
22
|
agent.sh
|
|
23
23
|
enqueue.sh
|
|
24
|
-
webhook_server.py
|
|
24
|
+
webhook_server.py # 0.0.0.0:19200 — do not open this port publicly
|
|
25
25
|
lib/github_oidc.py
|
|
26
|
-
.env
|
|
26
|
+
.env # WEBHOOK_PORT=19200
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Override the directory with `VIBED_UPDATE_AGENT` (wins over `VIBED_HOME`).
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
2. Cron enqueues; agent cron (`*/5`) processes **serially**.
|
|
33
|
-
3. Image push: reusable GHCR workflow mints a GitHub Actions OIDC JWT (audience = webhook URL) and POSTs `{package,tag}` to `/_vibed/hooks/ghcr`.
|
|
34
|
-
4. Webhook verifies the JWT against GitHub’s JWKS (`iss`, `aud`, `exp`, RS256), then enqueues only registry images whose name contains `repository_owner`.
|
|
35
|
-
5. Agent runs `update-*.sh` immediately.
|
|
31
|
+
## Pull paths
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
```
|
|
34
|
+
git push main
|
|
35
|
+
→ reusable GHCR workflow builds/pushes :main
|
|
36
|
+
→ notify-vps-pull.py mints OIDC JWT (aud = webhook URL)
|
|
37
|
+
→ POST https://{host}/_vibed/hooks/ghcr (fallback http://{publicIp}/…)
|
|
38
|
+
→ nginx → webhook_server (verify GitHub JWKS)
|
|
39
|
+
→ enqueue matching registry entries (owner must appear in image name)
|
|
40
|
+
→ agent.sh → update-{role}.sh → docker pull + restart if digest changed
|
|
41
|
+
```
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
- **Immediate:** default-branch image push. Caller job needs `id-token: write`. No GitHub Packages webhook and no `VIBED_WEBHOOK_SECRET`.
|
|
44
|
+
- **Cron backup:** `*_AUTO_UPDATE=1` enqueues on an interval; agent cron `*/5` drains the queue if notify was missed.
|
|
45
|
+
- **Manual:** `bash ~/services/vibed-infra/update-agent/enqueue.sh /path/to/api-install`
|
|
40
46
|
|
|
41
|
-
|
|
47
|
+
Gateway HTTP (`00-default.conf`) and each HTTPS site proxy `/_vibed/hooks/` to `host.docker.internal:19200`. Keep **19200** off the public firewall; only 80/443.
|
|
42
48
|
|
|
43
|
-
Product
|
|
49
|
+
## Product CI
|
|
44
50
|
|
|
45
51
|
```yaml
|
|
46
52
|
jobs:
|
|
@@ -55,10 +61,11 @@ jobs:
|
|
|
55
61
|
image: ghcr.io/${{ github.repository_owner }}/my-api
|
|
56
62
|
```
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
URLs come from `gateway.publicIp` + `gateway.sites[].host` already in config (`dist/packageconfig.yaml` `webhook.url` / `fallbackUrl`). Disable notify with `notify: false`.
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
Local curl can send `X-Vibed-Secret` from `tokens/{app}` (compiled hash). Optional `WEBHOOK_SECRET` still works as an override.
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
## Tests
|
|
69
|
+
|
|
70
|
+
- `npm test` — openssl-signed JWT (same verifier) + enqueue under `VIBED_UPDATE_AGENT`
|
|
71
|
+
- `npm run test:oidc` / CI job `oidc-webhook-e2e` — real GitHub OIDC mint against a local webhook
|
|
@@ -58,9 +58,9 @@ cd ~/services/gateway
|
|
|
58
58
|
- **Production:** certbot (webroot if gateway is up, else standalone). On failure, fix DNS then re-run `setup-tls.sh`.
|
|
59
59
|
- **Lab/CI:** `TLS_MODE=lab` → multi-SAN self-signed under `./certs/`.
|
|
60
60
|
|
|
61
|
-
## Webhook path
|
|
61
|
+
## Webhook path (immediate docker pull)
|
|
62
62
|
|
|
63
|
-
Host `00-default.conf` (HTTP) and each app `sites.conf` (HTTPS) proxy `/_vibed/hooks/` to the update-agent on `host.docker.internal:19200`.
|
|
63
|
+
Host `00-default.conf` (HTTP) and each app `sites.conf` (HTTPS) proxy `/_vibed/hooks/` to the update-agent on `host.docker.internal:19200`. After a GHCR `:main` push, CI POSTs a GitHub Actions OIDC JWT to `/_vibed/hooks/ghcr` — see infra-update-agent. Do not expose port 19200 on the public firewall.
|
|
64
64
|
|
|
65
65
|
## Pitfalls
|
|
66
66
|
|
|
Binary file
|