duckeighty: init (one-time per-host ingress bootstrap)
This skill walks the user through the four steps needed to make
https://*.duckeighty.test resolvable and TLS-trusted on their machine.
The ingress stack is host-wide: one install per developer, shared by
every app repo they work in.
Confirm prerequisites before starting
macOS. The current duckeighty resolver step writes to
/etc/resolver/, which is macOS-specific.Docker daemon is running (
docker versionsucceeds).mkcertis installed. If not:brew install mkcert nssInstall it and confirm before proceeding.
Step 1 — decide where duckeighty lives (always ask the user)
Do not hardcode a path. Developers use different checkout layouts and the
skill has no business assuming which one. The only auto-accepted value
is an explicit DUCKEIGHTY_CHECKOUT env var the user has set previously.
1a. Honor an explicit override
if [ -n "${DUCKEIGHTY_CHECKOUT:-}" ] && [ -d "$DUCKEIGHTY_CHECKOUT/.git" ]; then
CHECKOUT="$DUCKEIGHTY_CHECKOUT"
fi
If set and valid, confirm with the user ("Use the clone at $CHECKOUT?").
If yes, skip to step 2.
1b. Otherwise, present the choice
Always present these options to the user and let them pick. Do not guess based on filesystem layout or tool availability.
| # | Path | When it fits |
|---|---|---|
| 1 | ~/.duckeighty |
No existing convention. Shortest path, skill-owned. |
| 2 | ~/src/github.com/mackee/duckeighty |
You keep repos under ~/src/<host>/<owner>/<repo>. |
| 3 | A custom path the user types | Any other layout the user prefers. |
If the user picks option 3, ask them for the absolute path.
Once the path is chosen:
CHECKOUT="<chosen>"
mkdir -p "$(dirname "$CHECKOUT")"
git clone https://github.com/mackee/duckeighty "$CHECKOUT"
If $CHECKOUT exists but is not a git clone, stop and ask the user. Do
not overwrite.
1c. Persist the choice (optional but recommended)
Suggest the user add this to their shell rc so later init / doctor
runs skip the prompt:
export DUCKEIGHTY_CHECKOUT="$CHECKOUT"
All subsequent steps run from $CHECKOUT. Surface the final value in
the summary to the user.
Step 2 — install local CA and wildcard certificate
./duckeighty.sh setup-ca
This runs mkcert -install (installs the mkcert root CA into the system
keychain) and writes infra/certs/duckeighty.test.pem +
infra/certs/duckeighty.test-key.pem. Do not re-run on every init; only
run when certs are missing or the user explicitly asks to re-issue.
If mkcert -install asks for a password, that is the normal macOS
keychain prompt — proceed.
Step 3 — install the macOS resolver entry (sudo)
./duckeighty.sh setup-resolver
This writes /etc/resolver/duckeighty.test pointing at 127.0.0.1:5354.
It needs sudo. Tell the user the command and what it writes before
running it — do not silently escalate.
Browser restart is usually not required, but if the user opened
https://*.duckeighty.test before setup the browser may cache the
failure; suggest a tab reload.
Step 4 — bring up the ingress stack
./duckeighty.sh up
This creates the external shared_ingress network (if missing) and runs
docker compose -f infra/compose.yaml up -d. The compose file declares
name: duckeighty, so docker compose ls lists it as the duckeighty
project. After startup, two containers should be running with
restart: unless-stopped:
duckeighty-traefik-1— reverse proxy + TLS terminator on 127.0.0.1:80 / 443duckeighty-dnsmasq-1— DNS for*.duckeighty.teston 127.0.0.1:5354
Both survive reboots as long as Docker restarts.
Step 5 — verify
Suggest running the duckeighty-doctor skill next, or manually:
"$CHECKOUT"/duckeighty.sh check probe.duckeighty.test
Expected output:
127.0.0.1
HTTP 404
The 404 means TLS + DNS + Traefik all work and the hostname simply has no router yet — which is correct before any app is onboarded.
After init
From any application repo with a compose.yaml, use the duckeighty-integrate skill
to generate docker-compose.local.yaml. The ingress stack stays running
in the background; no per-app changes under infra/ are ever needed.
Do not
- Do not re-run
setup-caon every init call. Re-issuing the CA forces the user to re-trust it in every browser. Only re-run when the certs are actually missing or expired. - Do not run these commands from inside a random application repo — they
must run in the duckeighty checkout (
$CHECKOUT). - Do not copy
infra/into the user's app repo. The ingress is host-wide and shared; duplication breaks the port 80/443 assumption. - Do not silently run
sudo. Surface the command, explain what it writes, ask before proceeding.