summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
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