From 8fc81fc4f4a23ea86d58215be0cf815ad91a5737 Mon Sep 17 00:00:00 2001 From: disqualifier Date: Mon, 29 Jun 2026 20:16:02 -0400 Subject: [PATCH] add Gitea-style admonitions, code annotations, callouts Make the things that matter stand out, matching the Gitea callout look: - extra.css: brand-orange warning admonitions (#f57c00, the lambda orange), hotter danger (#e8590c), blue note/info and cyan tip/example, plus blue code-annotation markers. - deploy.md: footgun -> danger callout, secrets -> orange warning, eligible -> tip; Dockerfile and compose gain numbered code annotations explaining each magic line; paths/mounts as a table; a restart snippet for rotation. - workflow.md: warning on setting per-repo git identity before first commit; tip elevating verify-by-executing. Verified in-browser: computed border colors match (warning #f57c00, danger #e8590c), 4 annotation markers render in brand blue, admonition icons + tinted headers match the Gitea style. mkdocs build --strict clean. Signed-off-by: disqualifier --- docs/deploy.md | 97 ++++++++++++++++++++++---------------- docs/stylesheets/extra.css | 64 +++++++++++++++++++++++++ docs/workflow.md | 11 +++++ 3 files changed, 131 insertions(+), 41 deletions(-) diff --git a/docs/deploy.md b/docs/deploy.md index 4db00c1..a89e8fc 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -4,76 +4,88 @@ > **rethink-net** — our fleet of Ubuntu 26.x servers, ready to host whatever > you've built. -**Eligible:** APIs, websites, applets, bots, monitors. - -The whole network runs on a few simple, consistent rules. Get your container to -follow them and deploying is mostly handing us a `compose.yaml`. +!!! tip "Eligible" + APIs, websites, applets, bots, monitors. The whole network runs on a few + simple, consistent rules — get your container to follow them and deploying is + mostly handing us a `compose.yaml`. ## Docker — the services account Every service runs containerized as the shared **`services`** account: **uid/gid 1337**, fixed fleet-wide. Build your image to be **uid-agnostic** so it -runs cleanly as that account: - -- `user: "1337:1337"` in compose. -- `chmod -R a+rwX /app` in the Dockerfile (covers non-mounted dirs — see the - bind-mount note below). -- `HOME=/tmp`. -- **No** in-container `user`/`useradd` — don't bake a user into the image. +runs cleanly as that account. ```dockerfile FROM python:3.12-slim -ENV HOME=/tmp +ENV HOME=/tmp # (1)! WORKDIR /app -# git in the build if you pip-install from git -RUN apt-get update && apt-get install -y --no-install-recommends git \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update \ + && apt-get install -y --no-install-recommends git \ + && rm -rf /var/lib/apt/lists/* # (2)! COPY . . RUN pip install --no-cache-dir . \ - && chmod -R a+rwX /app + && chmod -R a+rwX /app # (3)! CMD ["python", "-m", "yourapp"] ``` +1. `HOME=/tmp` — the `services` account has no home dir; anything writing to + `$HOME` (caches, configs) needs a writable target. +2. Install `git` **only if** you `pip install` from git, then clean the apt lists + to keep the image small. +3. `chmod -R a+rwX /app` makes the app tree writable by **any** uid — this is + what "uid-agnostic" means. Note it only covers **non-mounted** dirs (see the + [footgun](#permissions-the-bind-mount-footgun)). + ```yaml services: yourapp: build: . - user: "1337:1337" + user: "1337:1337" # (1)! environment: HOME: /tmp volumes: - - /srv/configs/:/app/config:ro # host-managed, read-only - - /srv//:/app/logs # live + rolled logs - - yourapp-data:/app/data # named volume — the rest + - /srv/configs/:/app/config:ro # (2)! + - /srv//:/app/logs # (3)! + - yourapp-data:/app/data # (4)! volumes: yourapp-data: ``` +1. Run as the shared account. **No** in-container `user`/`useradd` — don't bake a + user into the image; set it here. +2. Configs: host-managed bind mount, mounted **read-only**. +3. Logs: bind mount — live and rolled, scraped for monitoring. +4. Everything else: a **named volume**. Docker owns it, so there are no host + permissions to fiddle with. + ## Paths and mounts -- **Configs** → `/srv/configs//` — bind mount, host-managed. -- **Logs** → `/srv///` — bind mount; live and rolled, scraped for - monitoring. -- **Everything else** (caches, browser profiles, scratch) → **named volumes**. - Docker manages ownership, so there are no host permissions to fiddle with. +| What | Where | How | +| --- | --- | --- | +| Configs | `/srv/configs//` | bind mount, host-managed | +| Logs | `/srv///` | bind mount; live + rolled, scraped | +| Caches, profiles, scratch | named volume | Docker manages ownership | ## Permissions — the bind-mount footgun -`docker compose up` does **not** create bind-mount directories as you. If a -bind-mount source is missing, the Docker daemon (**root**) creates it **as -root** — and your container (**1337**) then can't write it. Logs fall back to -console-only, caches re-download every run. +!!! danger "Bind-mount sources must exist and be 1337-owned *before* `up`" + `docker compose up` does **not** create bind-mount directories as you. If a + bind-mount source is missing, the Docker daemon (**root**) creates it **as + root** — and your container (**1337**) then can't write it. Logs silently fall + back to console-only; caches re-download every run. So: -- **Bind-mount sources (configs, logs) must EXIST and be 1337-owned _before_ - `up`.** This is handled at provisioning, not a per-deploy chown hook. +- **Bind-mount sources (configs, logs) must EXIST and be 1337-owned before `up`** + — handled at provisioning, not a per-deploy chown hook. - **Named volumes avoid this entirely** — use them for anything that doesn't need host visibility. -- The Dockerfile `chmod -R a+rwX /app` only covers **non-mounted** dirs. A bind - mount overrides the image directory with the host directory, so for mounted - paths the **host-side ownership wins**. + +!!! note "Why `chmod a+rwX /app` doesn't save you here" + The Dockerfile `chmod` only covers **non-mounted** dirs. A bind mount + overrides the image directory with the host directory, so for mounted paths + the **host-side ownership wins** — the image's permissions are irrelevant. ## What your compose / Dockerfile needs @@ -87,12 +99,15 @@ So: ## Secrets -We do **not** commit secrets (usually, lol). The rule: - -- Secrets stay **gitignored**. -- They're placed on the host at `/srv/configs//`. -- They're bind-mounted **read-only** at runtime. -- **Never** baked into the image — add them to `.dockerignore` so `COPY . .` - can't grab them. +!!! warning "Secrets never go in the image" + We do **not** commit secrets (usually, lol). They stay **gitignored**, live on + the host at `/srv/configs//`, and are bind-mounted **read-only** at + runtime. Add them to `.dockerignore` so a `COPY . .` can't sweep them into a + layer. Rotating a secret = edit the host file and restart. No rebuild. + +```bash +vim /srv/configs//secrets.env # edit on the host +docker compose restart yourapp # pick up the change — no rebuild +``` diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 9c91de3..259864b 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -93,6 +93,70 @@ color: rgba(238, 241, 246, 0.6); } +/* Admonitions — Gitea-style: brand-orange warning, blue note, etc. + The lambda logo's orange (#ffae42 -> #f57c00) drives the warning/danger look. */ +.md-typeset .admonition, +.md-typeset details { + border-width: 0 0 0 .2rem; + background-color: var(--rt-surface); +} + +/* warning / caution: the orange Gitea callout */ +.md-typeset .admonition.warning, +.md-typeset details.warning, +.md-typeset .admonition.caution, +.md-typeset details.caution { + border-color: #f57c00; +} +.md-typeset .warning > .admonition-title, +.md-typeset .warning > summary, +.md-typeset .caution > .admonition-title, +.md-typeset .caution > summary { + background-color: rgba(245, 124, 0, 0.12); +} +.md-typeset .warning > .admonition-title::before, +.md-typeset .caution > .admonition-title::before { + background-color: #f57c00; +} + +/* danger: a hotter orange-red for true footguns */ +.md-typeset .admonition.danger, +.md-typeset details.danger { + border-color: #e8590c; +} +.md-typeset .danger > .admonition-title, +.md-typeset .danger > summary { + background-color: rgba(232, 89, 12, 0.14); +} + +/* note / info / tip: blue + cyan from the rethink palette */ +.md-typeset .admonition.note, +.md-typeset details.note, +.md-typeset .admonition.info, +.md-typeset details.info { + border-color: var(--rt-primary); +} +.md-typeset .note > .admonition-title, +.md-typeset .info > .admonition-title { + background-color: rgba(86, 155, 204, 0.12); +} +.md-typeset .admonition.tip, +.md-typeset details.tip, +.md-typeset .admonition.example, +.md-typeset details.example { + border-color: var(--rt-accent); +} +.md-typeset .tip > .admonition-title, +.md-typeset .example > summary { + background-color: rgba(85, 187, 255, 0.1); +} + +/* Code annotation markers (the (1) callouts) in brand blue. */ +.md-typeset .md-annotation__index { + background-color: var(--rt-primary); + color: var(--rt-body); +} + /* Landing-page cards: surface tint + blue border like Gitea panels. */ .md-typeset .grid.cards > :is(ul, ol) > li, .md-typeset .grid > .card { diff --git a/docs/workflow.md b/docs/workflow.md index fde9036..a0c1f35 100644 --- a/docs/workflow.md +++ b/docs/workflow.md @@ -68,6 +68,12 @@ Our conventions, in short: - **Libraries install from git by tag** — pin a version in your deps, bump the tag when the lib releases. +!!! warning "Set your per-repo identity *before* the first commit" + One machine often carries more than one Gitea identity/key. If you forget to + run `gitsetup` in a fresh clone, your commits attribute to the wrong + user — or push with the wrong key and bounce. Run it right after cloning; + see [per-project git identity](#handy-shell-setup). + ## Git basics (our-flavored) Not a git tutorial — just how the everyday loop looks against our Gitea. For the @@ -154,6 +160,11 @@ git diff | clip.exe # then paste the diff straight into the chat Use AI for the plan and the spec, let the agent build, and always **prove it works by running it** — don't accept "this should work." +!!! tip "Verify by executing, not asserting" + The single habit that separates good AI-assisted work from plausible-looking + nonsense: **run it**. A passing build, a real screenshot, actual output — that + is proof. "It should work" is not. + ## Recommended setup - **WSL2 (Ubuntu) + VS Code + Claude Code.** Develop in WSL, edit in VS Code over