omalocal: update baked Claude context for the omalocal-server skill
Two changes to the host conventions baked into provisioned boxes:
- CLAUDE.md: add a "custom-image deploy" section covering how to get a
locally-built image onto Once as a .local app without root — registry:2
on 127.0.0.1:5000 (Once always docker-pulls), then deploy against
localhost and `once update localhost --host <name>.local` to skip the
re-verification that would need the /etc/hosts sudo edit. Plus the /up
200 health probe, the remove->deploy->update redeploy dance, and the
nginx {n,} quantifier parse gotcha.
- Skill: drop Once's upstream AGENTS.md (kamal-proxy architecture, Go
build/style, "don't make commits"). That's about hacking on the Once
codebase, not operating this host — noise in a host-admin skill. The
skill now ships only SKILL.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f66b62c551
commit
fea046ab3d
1 changed files with 37 additions and 61 deletions
98
omalocal.sh
98
omalocal.sh
|
|
@ -920,67 +920,6 @@ journalctl -b -p warning # warnings since last boot
|
||||||
The build script that produced this image lives at `~/Projects/omalocal/omalocal.sh` on the master machine (not on this host). To rebuild and reinstall: run that script there, `dd` the output ISO to a USB, boot from it. The build is reproducible — same inputs (stock Arch ISO + master's SSH key) give the same output.
|
The build script that produced this image lives at `~/Projects/omalocal/omalocal.sh` on the master machine (not on this host). To rebuild and reinstall: run that script there, `dd` the output ISO to a USB, boot from it. The build is reproducible — same inputs (stock Arch ISO + master's SSH key) give the same output.
|
||||||
SKILL_EOF
|
SKILL_EOF
|
||||||
|
|
||||||
cat > "/mnt/home/$USERNAME/.claude/skills/omalocal-server/AGENTS.md" <<'AGENTS_EOF'
|
|
||||||
# Project Overview
|
|
||||||
|
|
||||||
Once is a CLI/TUI tool for installing and managing web applications from Docker images. It's designed to make self-hosting as easy as possible.
|
|
||||||
|
|
||||||
Once uses a proxy server (github.com/basecamp/kamal-proxy) to route traffic to the application containers, which allows it to provide zero-downtime restarts and upgrades, automatic SSL, and multiple applications running on a single server. A single instance of Once may deploy one proxy container, along with multiple application containers. Host-based routing is used inside the proxy to route traffic to the correct application container.
|
|
||||||
|
|
||||||
# Code Architecture
|
|
||||||
|
|
||||||
## Design and Concepts
|
|
||||||
|
|
||||||
### Container Naming
|
|
||||||
|
|
||||||
All containers are namespaced (default namespace: "once"):
|
|
||||||
|
|
||||||
- Proxy: `{namespace}-proxy`
|
|
||||||
- Apps: `{namespace}-app-{appName}-{shortID}`
|
|
||||||
|
|
||||||
This allows us to easily identify the app containers, but still allows us to boot a second app container without naming collisions when we want to deploy a new version without downtime.
|
|
||||||
|
|
||||||
### Data and State
|
|
||||||
|
|
||||||
Once deals primarily with two classes of state:
|
|
||||||
|
|
||||||
**Application data**: this is stored in Docker volumes to provide persistent storage between versions of the app container. Once provides one volume for each app, which it will mount into two locations (`/storage` and `/rails/storage`) to match typical app conventions. Once may provide backup and restore features on the contents of those volumes. But it does not otherwise touch the volume contents, or have any opinions about what should be in there -- this data is entirely for each app's own use.
|
|
||||||
|
|
||||||
**Configuration**: this keeps track of the applications and settings that have been set up using Once itself. For example, the list of applications that are deployed, the hostname and TLS settings for each, any custom port settings for the proxy, and so on. Once stores this information as JSON strings in an `once` label on the containers and volumes, so that everything is stored within the Docker state. Application settings go with the app container; proxy settings go with the proxy container; volume settings (like encryption keys) go with the volume.
|
|
||||||
|
|
||||||
# Build Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make build # Build binary to bin/ (CGO disabled)
|
|
||||||
make test # Run unit tests (internal/ packages)
|
|
||||||
make integration # Run integration tests (requires Docker)
|
|
||||||
make lint # Run golangci-lint
|
|
||||||
```
|
|
||||||
|
|
||||||
Run a single test:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go test -v -run TestName ./internal/...
|
|
||||||
```
|
|
||||||
|
|
||||||
# Coding Style
|
|
||||||
|
|
||||||
- Always follow idiomatic Go style
|
|
||||||
- Don't use excessive comments. Try to make the code speak for itself; only resort to adding comments where the meaning or intention may otherwise be unclear, or a subtle detail may be missed.
|
|
||||||
- Organize imports in sections: stdlib imports, 3rd-party imports, and project imports. Each section should be sorted alphabetically, and the sections should be separated from each other by 1 blank line.
|
|
||||||
- Where a struct type has both public and private methods, arrange the public methods first, then add a comment line of `// Private` and put the private methods below that comment. In the public section, put any constructor methods first, followed by simple accessor methods, followed by the rest.
|
|
||||||
- Private functions that are not methods of a type should go last in the file, and should be separated with a `// Helpers` comment.
|
|
||||||
- Prefer modern Go constructs where possible (for example, ranging over numbers is better than a for loop). If the LSP suggests there is an option to modernize something you should generally do so.
|
|
||||||
- Write tests to cover changes where possible, but don't go overboard trying to cover every single case. Prefer using helper functions (including functions defined locally inside the test) over table-driven tests, except in cases where the latter would be more readable.
|
|
||||||
- When writing tests, use github.com/stretchr/testify's assert and require packages, to make test conditions more readable. Don't add descriptions to the assertions unless they would add meaningful context over what the default failure message would be).
|
|
||||||
- Regularly check your work with the linter and LSP to ensure it follows conventions, and run tests as needed to ensure they pass.
|
|
||||||
- Consider opportunities to refactor large methods into smaller pieces, and spot opportunities where it's worth extracting functionality into a new type. But do not go overboard with this.
|
|
||||||
|
|
||||||
# Agent behaviour
|
|
||||||
|
|
||||||
Don't make commits, or push changes to remotes. I will take care of this myself.
|
|
||||||
AGENTS_EOF
|
|
||||||
|
|
||||||
# CLAUDE.md is loaded into EVERY Claude Code session on this host regardless of
|
# CLAUDE.md is loaded into EVERY Claude Code session on this host regardless of
|
||||||
# working directory, unlike the skill (invoked on demand). Put the few rules an
|
# working directory, unlike the skill (invoked on demand). Put the few rules an
|
||||||
# agent must always respect here — most importantly the Once deploy-domain
|
# agent must always respect here — most importantly the Once deploy-domain
|
||||||
|
|
@ -1026,6 +965,43 @@ Avoid: multi-label names like `book.devbox.local` (Linux clients' `mdns_minimal`
|
||||||
only resolves single-label `.local`), `*.localhost` (only this box can reach it),
|
only resolves single-label `.local`), `*.localhost` (only this box can reach it),
|
||||||
and TLS/https (no cert on a private box).
|
and TLS/https (no cert on a private box).
|
||||||
|
|
||||||
|
## Deploying a locally-built image to Once, sudo-free (custom-image deploy)
|
||||||
|
|
||||||
|
`once-add` covers public images. To put your OWN locally-built image on Once as a
|
||||||
|
`.local` app WITHOUT root, you have to work around two facts: Once always
|
||||||
|
`docker pull`s (so a plain local tag fails), and a fresh deploy edits
|
||||||
|
`/etc/hosts` (which needs sudo). Both are dodgeable:
|
||||||
|
|
||||||
|
1. **Loopback registry** — Once pulls, so serve the image from a registry it can
|
||||||
|
reach. Run one on loopback and push to it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --restart=always -p 127.0.0.1:5000:5000 --name registry registry:2
|
||||||
|
docker tag myapp:latest 127.0.0.1:5000/myapp:latest
|
||||||
|
docker push 127.0.0.1:5000/myapp:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Deploy against `localhost`, then `update` to the real host** — a fresh
|
||||||
|
deploy re-verifies the host (and would need the `/etc/hosts` sudo edit), but
|
||||||
|
`localhost` already resolves to `127.0.0.1`, so verification passes with no
|
||||||
|
root. Then point it at the `.local` name with `once update`, which **skips
|
||||||
|
re-verification**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
once deploy 127.0.0.1:5000/myapp:latest --host localhost --disable-tls
|
||||||
|
once update localhost --host blog.local
|
||||||
|
# -> reachable at http://blog.local once once-mdns-sync publishes it
|
||||||
|
```
|
||||||
|
|
||||||
|
Gotchas:
|
||||||
|
- The image MUST answer `GET /up` with **HTTP 200** — that's Once's health probe.
|
||||||
|
A broken/unhealthy image fails with `failed to become healthy within 2m`.
|
||||||
|
- **Redeploy** (new image build) = `once remove <name>` → `once deploy ... --host
|
||||||
|
localhost` → `once update localhost --host <name>.local`. You can't deploy over
|
||||||
|
a live app.
|
||||||
|
- If the app is nginx-based, avoid `{n,}` regex quantifiers in the nginx config —
|
||||||
|
they break config parse and the container never goes healthy.
|
||||||
|
|
||||||
## Files sent to this box (Omarchy-Send)
|
## Files sent to this box (Omarchy-Send)
|
||||||
|
|
||||||
If `omarchy-send` is installed (offered at first login), it's a
|
If `omarchy-send` is installed (offered at first login), it's a
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue