summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorMike Wild <mike@mikeanthonywild.com>2026-08-25 23:04:10 -0500
committerMike Wild <mike@mikeanthonywild.com>2026-08-25 23:04:10 -0500
commit025a365a23f5ed2b3df4df71cbff9689575968d9 (patch)
tree1a1f93de4163a3a452d0dd4ed4499fe2084d2db7 /README.md
parent2a9ca0577ecdbee8b5a4bc8886c112dbc4260eab (diff)
Split per-app dataset into OS/data layers, add skiff rebuild
Each app now gets two ZFS datasets - a disposable OS layer (zroot/skiff/appbase/<app>) cloned from base, and a persistent data layer (zroot/skiff/appdata/<app>) holding releases/current/env/ meta.json/data.db. `skiff rebuild --app|--all` discards and reclones the OS layer to pick up an OS/toolchain/config-template upgrade, guarded by the same snapshot-and-rollback safety net as deploy and config changes; the data layer is never touched. Also fixes stale docs (builds already run via jexec inside the jail, not on the host; --iface already auto-aliases the jail's IP, so the manual ifconfig step and its troubleshooting entry are gone) found while updating the same sections for this feature. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'README.md')
-rw-r--r--README.md45
1 files changed, 37 insertions, 8 deletions
diff --git a/README.md b/README.md
index ba51aba..4373008 100644
--- a/README.md
+++ b/README.md
@@ -20,10 +20,10 @@ needs to provide](#what-an-app-needs-to-provide).
- `jail_enable="YES"` in `/etc/rc.conf` (`sysrc jail_enable=YES`) - `service
jail start`/`restart` refuse to run without it
- Whatever toolchain your apps' Makefiles invoke to build - `go`, `python`,
- `rustc`, `node`, etc. - installed on the **host** (builds run outside the
- jail; see [One-time host setup](#one-time-host-setup)). `make` itself is
- already in FreeBSD base (bmake), so it's the one build tool Skiff never
- asks you to install.
+ `rustc`, `node`, etc. - baked into the base jail image (see [One-time host
+ setup](#one-time-host-setup)); builds run inside the jail via `jexec`, not
+ on the host itself. `make` itself is already in FreeBSD base (bmake), so
+ it's the one build tool Skiff never asks you to install.
## One-time host setup
@@ -34,16 +34,28 @@ needs to provide](#what-an-app-needs-to-provide).
# zfs create -o mountpoint=/skiff/base zroot/skiff/base
# bsdinstall jail /skiff/base
# zfs snapshot zroot/skiff/base@ready
-# zfs create -o mountpoint=/skiff/apps zroot/skiff/apps
+# zfs create -o mountpoint=none zroot/skiff/appbase
+# zfs create -o mountpoint=none zroot/skiff/appdata
+# mkdir -p /skiff/apps
```
`ready` is the snapshot every app's dataset gets cloned from. Re-snapshot
under a new tag after patching the base (e.g. `security-2026-08`) and pass
`--base-snapshot` to `new-app` to pick it up.
-`zroot/skiff/apps` must exist as its own dataset, not a plain directory -
-`new-app` clones straight into it (`zroot/skiff/apps/<name>`), and `zfs
-clone` requires the parent dataset to already exist.
+`zroot/skiff/appbase` and `zroot/skiff/appdata` must each exist as their own
+dataset, not a plain directory - `new-app` clones/creates straight into them
+(`zroot/skiff/appbase/<name>`, `zroot/skiff/appdata/<name>`), and `zfs
+clone`/`zfs create` require the parent dataset to already exist. Their own
+mountpoint doesn't matter (`none` is fine) since every per-app dataset sets
+its own explicit mountpoint under `/skiff/apps/<name>` - `appbase/<name>` at
+`/skiff/apps/<name>` itself (the jail's root), `appdata/<name>` at
+`/skiff/apps/<name>/app`. `/skiff/apps` itself is a plain directory, like
+`/skiff/repos` - nothing needs to be a dataset at that exact path.
+
+Keeping the OS layer (`appbase`) and the app's persistent data (`appdata`)
+on separate datasets is what lets `skiff rebuild` destroy and reclone the
+former without any risk to the latter.
### Repos directory
@@ -125,6 +137,23 @@ target** - ZFS can't roll back past one otherwise. Rolling back to an old
snapshot permanently discards the ability to return to anything deployed
in between; there's no separate "undo the rollback."
+### Rebuilding a jail
+
+```
+# skiff rebuild --app myapp
+# skiff rebuild --all
+```
+
+Discards the app's OS layer (`/etc`, `/usr`, `/bin`, `jail.conf`, the jail's
+rc.d script, `dma.conf`) and reclones it fresh from the base image, leaving
+`/app` (releases, current, env, `meta.json`, `data.db`) completely
+untouched - the two live on separate ZFS datasets. Use this to pick up a
+patched/upgraded base image (`--base-snapshot`) on an app that already
+exists, or to regenerate stale jail config after a Skiff upgrade, without
+touching the app's own data. Guarded exactly like a deploy: the old OS
+layer is kept until the rebuilt jail passes its health check, and swapped
+back automatically if it doesn't.
+
## What an app needs to provide
A `Makefile` in the repo root, and nothing else Skiff cares about - no