chore: track Codex/Antigravity agent config (.agents skills + .codex)
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
---
|
||||
name: homelab-apply
|
||||
description: Deploy changes to the valhalla homelab. For application stacks (foundry, media, owncloud, etc.), commit and push — Portainer git-polls every 5 min. For the management plane (portainer, vault, watchtower, runner), Caddyfile, or .env on the server, use the apply-compose.ps1 helper. Use after editing any homelab config to get it deployed.
|
||||
---
|
||||
|
||||
# homelab-apply
|
||||
|
||||
The repo is canonical. Different config layers deploy through different channels:
|
||||
|
||||
| Edit | Deployment channel | Lag |
|
||||
|---|---|---|
|
||||
| `stacks/<domain>/docker-compose.yml` or `stacks/<domain>/.env` | **git push** → Portainer polls every 5 min and redeploys that stack | up to 5 min |
|
||||
| `Caddyfile` | git push triggers `.github/workflows/deploy.yml` → runner pushes file + `docker exec caddy caddy reload` | seconds (if workflow is enabled) |
|
||||
| `portainer-compose.yml` (mgmt plane: portainer, vault, watchtower, runner) | `apply-compose.ps1 -Portainer` — Portainer can't manage itself | seconds |
|
||||
| `vault.hcl` | `apply-compose.ps1 -Portainer` (bundled with mgmt plane push) | seconds |
|
||||
| `.env` at `~/valhalla-lab/.env` (only used by mgmt plane + vault unseal) | `apply-compose.ps1 -EnvFile` | seconds |
|
||||
|
||||
## For application stack edits — just push
|
||||
|
||||
```powershell
|
||||
git add stacks/media/.env
|
||||
git commit -m "..."
|
||||
git push
|
||||
```
|
||||
|
||||
Portainer's per-stack auto-update will pick up the new commit within 5 minutes and redeploy. Watch progress:
|
||||
|
||||
```powershell
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker compose -f /data/compose/<id>/stacks/<domain>/docker-compose.yml ps"
|
||||
```
|
||||
|
||||
Or just `docker ps` and filter by name. To force an immediate redeploy without waiting, trigger it from the Portainer UI ("Update the stack").
|
||||
|
||||
## For Caddyfile edits — push and wait for the runner
|
||||
|
||||
Workflow is gated by `paths: [Caddyfile, .github/workflows/deploy.yml]` so only Caddyfile commits trigger it.
|
||||
|
||||
If you don't want to wait (or the workflow is disabled), the manual fallback is:
|
||||
|
||||
```powershell
|
||||
powershell -File apply-compose.ps1 -Caddy
|
||||
```
|
||||
|
||||
This `scp`s the local Caddyfile to `/config/caddy/Caddyfile` and runs `docker exec caddy caddy reload --config /etc/caddy/Caddyfile`. Invalid Caddyfile → reload fails, old config keeps running; read the output.
|
||||
|
||||
## For management-plane edits
|
||||
|
||||
```powershell
|
||||
powershell -File apply-compose.ps1 -Portainer # portainer-compose.yml + vault.hcl + up -d
|
||||
powershell -File apply-compose.ps1 -EnvFile # ~/valhalla-lab/.env only
|
||||
powershell -File apply-compose.ps1 -VaultUnseal # unseal vault after restart (keys from .env)
|
||||
```
|
||||
|
||||
No flags = `-EnvFile` + `-Caddy` (the two ad-hoc pushes you'd want for a quick manual deploy).
|
||||
|
||||
## Verify after applying
|
||||
|
||||
```powershell
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker ps --format 'table {{.Names}}\t{{.Status}}'"
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker logs --tail 50 <container>"
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Compose is **v2** (`docker compose`, space).
|
||||
- There is no monolithic `dc` alias anymore — each stack has its own compose dir under `/data/compose/<id>/stacks/<domain>/`. Address services by container name with `docker logs`, `docker exec`, etc. — `docker compose ...` only makes sense when you explicitly point at a per-stack compose file.
|
||||
- A **GateGuard hook** blocks the first `Bash` and every `Write`/`Edit` until you state the user request + what the operation does/affects. State them, retry.
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
name: homelab-ssh
|
||||
description: Connect to and run commands on the valhalla homelab server (ginnoir@valhalla) over SSH. Use when inspecting the live per-domain stacks, tailing logs, restarting a container, reloading Caddy, or checking container/network/volume state. There is no `dc` alias anymore — services are addressed by container name with plain `docker` commands.
|
||||
---
|
||||
|
||||
# homelab-ssh
|
||||
|
||||
The production homelab runs on a headless Ubuntu host reachable at `ssh ginnoir@valhalla` (key-based auth; resolves and works from this Windows host directly).
|
||||
|
||||
## Connect (non-interactive / safe for automation)
|
||||
|
||||
Always pass `-o BatchMode=yes` so a missing key or password prompt fails fast instead of hanging:
|
||||
|
||||
```powershell
|
||||
ssh -o BatchMode=yes -o ConnectTimeout=8 ginnoir@valhalla "<command>"
|
||||
```
|
||||
|
||||
The first `Bash` of a session is gated by a GateGuard hook — state the user request + what the command does, then retry.
|
||||
|
||||
## The estate is now 11 Portainer-managed stacks + the management plane
|
||||
|
||||
| Stack (Portainer project name) | Containers |
|
||||
|---|---|
|
||||
| `proxy` | `caddy` |
|
||||
| `media` | `deluge`, `nzbget`, `sonarr`, `radarr`, `bazarr`, `prowlarr`, `overseerr`, `tautulli`, `qbittorrent`, `whisparr`, `stash` |
|
||||
| `foundry` | `foundry`, `foundry2`, `5etools` |
|
||||
| `owncloud` | `owncloud_server`, `owncloud_mariadb`, `owncloud_redis` |
|
||||
| `resume` | `resume`, `postgres_resume`, `minio_resume`, `chrome` |
|
||||
| `famapp` | `famapp`, `postgres_famapp`, `minio_famapp` |
|
||||
| `authentik` | `authentik_server`, `authentik_worker`, `postgres_authentik`, `redis_authentik` |
|
||||
| `notify` | `ntfy`, `freshrss`, `vigilant` |
|
||||
| `monitoring` | `uptime_kuma`, `homarr` |
|
||||
| `remote` | `hbbr`, `hbbs` |
|
||||
| `dev` | `gitea`, `code_server`, `bookstack`, `mariadb_bookstack`, `dbx`, `registry`, `postgres_gitea`, `postgres_plane`, `redis_plane`, `plane_minio`, `plane_api`, `plane_web`, `plane_worker`, `plane_beat`, `plane_create_bucket` |
|
||||
| management plane (raw compose at `~/valhalla-lab/portainer-compose.yml`, project name `valhalla-lab`) | `portainer`, `vault`, `github_runner`, `watchtower` |
|
||||
|
||||
## Common ops by container name
|
||||
|
||||
There's no umbrella `dc` alias. Use plain `docker`:
|
||||
|
||||
```powershell
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Label \"com.docker.compose.project\"}}'"
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker logs --tail 200 -f <container>"
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker restart <container>"
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker exec <container> <command>"
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker exec caddy caddy reload --config /etc/caddy/Caddyfile"
|
||||
```
|
||||
|
||||
## Per-stack `docker compose` operations
|
||||
|
||||
Each Portainer git stack lives at `/data/compose/<id>/stacks/<domain>/docker-compose.yml` (Portainer chooses the `<id>` when the stack is created). To inspect a stack's resolved config or run a one-off compose op:
|
||||
|
||||
```powershell
|
||||
# Pick the stack file from its label
|
||||
ssh ginnoir@valhalla "docker inspect <container> --format '{{ index .Config.Labels \"com.docker.compose.project.config_files\"}}'"
|
||||
# Then point compose at it
|
||||
ssh ginnoir@valhalla "docker compose -f /data/compose/14/stacks/owncloud/docker-compose.yml ps"
|
||||
```
|
||||
|
||||
For management plane only:
|
||||
|
||||
```powershell
|
||||
ssh ginnoir@valhalla "docker compose -f ~/valhalla-lab/portainer-compose.yml --env-file ~/valhalla-lab/.env ps"
|
||||
```
|
||||
|
||||
## Key paths on the server
|
||||
|
||||
- `~/valhalla-lab/portainer-compose.yml` + `~/valhalla-lab/.env` — management plane (raw compose, applied via `apply-compose.ps1 -Portainer`)
|
||||
- `/config/caddy/Caddyfile` — Caddy config (mounted into `caddy` at `/etc/caddy/Caddyfile`)
|
||||
- `/config/<service>/` — per-service persisted config (SSD tier: configs + Postgres + Redis)
|
||||
- `/storage1/labdata/<service>/` — high-density data on the ZFS pool (MinIO buckets, registry layers, gitea repos)
|
||||
- `/storage1/` — media library (Books, Tabletop, etc.)
|
||||
- `/data/compose/<id>/stacks/<domain>/` — Portainer's working copy of each stack (Portainer auto-pulls these from git every 5 min)
|
||||
|
||||
## Networks
|
||||
|
||||
- `edge` — shared reverse-proxy network. `caddy` + every service Caddy proxies. Anything new that needs to be public must join this.
|
||||
- `<domain>` (e.g. `media`, `authentik`, `dev`) — per-stack private network for intra-stack traffic (app ↔ its db/cache/minio).
|
||||
- `portainer_proxy`, `valhalla-lab_default` — management-plane networks (legacy names, kept).
|
||||
- `bridge`, `host`, `none` — Docker defaults.
|
||||
|
||||
## Notes
|
||||
|
||||
- Read-only exploration of `/config`, `/storage1`, and container state is fine for answering questions.
|
||||
- For destructive ops (`docker rm -f`, network/volume pruning), get explicit confirmation first.
|
||||
- To deploy config changes, use the `homelab-apply` skill (per-domain stacks → git push; mgmt plane / Caddyfile → `apply-compose.ps1`).
|
||||
- `htpc-download-box_*` and `valhalla-lab_*` named volumes still exist as a data safety net from the pre-split monolith — every per-domain stack uses bind mounts now, so those orphans can be reaped once you're confident in the new persistence.
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
name: vault
|
||||
description: Read and write notes in ginnoir's self-hosted Obsidian vault via the Obsidian MCP server. Use when loading persistent context for a session, saving new context, writing a note, or querying vault contents. The vault is the canonical persistent-context store across Codex sessions.
|
||||
---
|
||||
|
||||
# vault
|
||||
|
||||
Obsidian vault accessed via the **`mcp__obsidian__*` MCP tools**. Do not attempt to connect to CouchDB directly — use MCP only.
|
||||
|
||||
The MCP server is configured in `~/.mcp.json` and is available in every Codex session. If the tools are listed as deferred, load them with `ToolSearch` before calling.
|
||||
|
||||
## Core tools
|
||||
|
||||
| Tool | Use |
|
||||
|---|---|
|
||||
| `mcp__obsidian__vault_list` | List files/dirs in a directory (omit path for vault root) |
|
||||
| `mcp__obsidian__vault_read` | Read a file's full content + metadata (tags, frontmatter, links, backlinks) |
|
||||
| `mcp__obsidian__vault_write` | Create or overwrite a file |
|
||||
| `mcp__obsidian__vault_patch` | Append or patch a section without a full rewrite |
|
||||
| `mcp__obsidian__vault_delete` | Delete a file |
|
||||
| `mcp__obsidian__vault_move` | Move or rename a file |
|
||||
| `mcp__obsidian__search_simple` | Full-text search across the vault |
|
||||
| `mcp__obsidian__search_query` | Advanced query search |
|
||||
| `mcp__obsidian__tag_list` | List all tags |
|
||||
|
||||
## Load context at session start
|
||||
|
||||
```
|
||||
1. mcp__obsidian__vault_read path="Codex/Context.md"
|
||||
2. Follow [[wikilinks]] to read specific notes as needed
|
||||
```
|
||||
|
||||
`Codex/Context.md` is the master index. It links to all other context notes under `Codex/`.
|
||||
|
||||
## Read a note
|
||||
|
||||
```
|
||||
mcp__obsidian__vault_read path="Codex/Homelab.md"
|
||||
```
|
||||
|
||||
Returns: `content` (full markdown), `tags`, `frontmatter`, `links`, `backlinks`, `stat`.
|
||||
|
||||
To read only a section:
|
||||
```
|
||||
mcp__obsidian__vault_read path="Codex/Services.md" targetType="heading" target="BookStack"
|
||||
```
|
||||
|
||||
## Write a note
|
||||
|
||||
```
|
||||
mcp__obsidian__vault_write path="Codex/MyNote.md" content="# Title\n\nContent here."
|
||||
```
|
||||
|
||||
Creates parent directories automatically. Overwrites without warning.
|
||||
|
||||
## Append to a note
|
||||
|
||||
```
|
||||
mcp__obsidian__vault_patch path="Codex/Context.md" ...
|
||||
```
|
||||
|
||||
Use `vault_patch` when adding a section to an existing note to avoid rewriting the whole file.
|
||||
|
||||
## Search the vault
|
||||
|
||||
```
|
||||
mcp__obsidian__search_simple query="portainer env vars"
|
||||
```
|
||||
|
||||
## Vault structure
|
||||
|
||||
```
|
||||
Codex/
|
||||
Context.md — master index, session start guide, quick nav
|
||||
Homelab.md — topology, stacks, networks, paths
|
||||
Deploy.md — deployment channels
|
||||
SSH.md — SSH ops, container management
|
||||
Portainer.md — env interpolation gotcha, new stack registration
|
||||
Services.md — per-service quirks (BookStack, Caddy, secrets policy)
|
||||
ROM Library.md — RomM, igir, Pokémon romhacks, EmuDeck tree
|
||||
Monitoring.md — Uptime Kuma v2 socket technique
|
||||
Vault.md — this stack's infrastructure, MCP access
|
||||
testing.md — original connectivity test note
|
||||
Pokémon ROM Hacks/ — Pokémon romhack KB in the live vault; catalog + build
|
||||
scripts live in the standalone Documents\pokemon repo
|
||||
```
|
||||
|
||||
## Load tool schemas (if deferred)
|
||||
|
||||
If `mcp__obsidian__vault_read` is not yet callable, run:
|
||||
```
|
||||
ToolSearch query="select:mcp__obsidian__vault_list,mcp__obsidian__vault_read,mcp__obsidian__vault_write"
|
||||
```
|
||||
@@ -0,0 +1,17 @@
|
||||
[shell_environment_policy]
|
||||
inherit = "core"
|
||||
|
||||
[shell_environment_policy.set]
|
||||
ECC_GATEGUARD = "off"
|
||||
|
||||
[mcp_servers.portainer]
|
||||
command = "uvx"
|
||||
args = [
|
||||
"--from",
|
||||
"mcp-portainer~=2.42.0",
|
||||
"mcp-portainer",
|
||||
]
|
||||
|
||||
[mcp_servers.portainer.env]
|
||||
PORTAINER_URL = "https://portainer.ginnoir.com"
|
||||
PORTAINER_API_KEY = "ptr_Ep2pXkdoT6y2Pn8AAt4gRdUr7NFMyE06S8WYR+ciNq4="
|
||||
@@ -11,5 +11,9 @@ Thumbs.db
|
||||
*.tmp
|
||||
*.log
|
||||
|
||||
# Loose scratch scripts agents drop at the .agents/ root (RomM/igir DB one-offs etc.).
|
||||
# Keep .agents/skills/ tracked; ignore stray top-level scripts.
|
||||
.agents/*.py
|
||||
|
||||
# Personal, per-machine Claude Code overrides (not team config)
|
||||
.claude/settings.local.json
|
||||
|
||||
Reference in New Issue
Block a user