diff options
| author | Jan Tuomi <jan@jantuomi.fi> | 2026-02-16 12:59:14 +0200 |
|---|---|---|
| committer | Jan Tuomi <jan@jantuomi.fi> | 2026-02-16 12:59:14 +0200 |
| commit | 5f46fde558c467414fa151ad962caaf7f07628fa (patch) | |
| tree | 247d6fd45ddbc811fb71d2009fbbd2042e158791 /docs | |
Initial commit
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/CONFIG.md | 65 | ||||
| -rw-r--r-- | docs/PLAN.md | 78 | ||||
| -rw-r--r-- | docs/USAGE.md | 20 |
3 files changed, 163 insertions, 0 deletions
diff --git a/docs/CONFIG.md b/docs/CONFIG.md new file mode 100644 index 0000000..bdc5b02 --- /dev/null +++ b/docs/CONFIG.md @@ -0,0 +1,65 @@ +# jprov Configuration + +This document defines the main configuration file and per-jail TOML schema. + +## Main Config +Default locations (first found wins): +- `/usr/local/etc/jprov.conf` +- `/etc/jprov.conf` + +Schema (TOML): +```toml +base_dir = "/usr/local/jails" + +[datasets] +templates_prefix = "zroot/jails/templates/" +containers_prefix = "zroot/jails/containers/" + +jail_conf_dir = "/etc/jail.conf.d" +log_dir = "/var/log/jprov" +``` + +Notes: +- `base_dir` contains `templates/` and `defs/`. +- `templates_prefix` and `containers_prefix` are ZFS dataset name prefixes (must end with `/`). +- `log_dir` is where per-run logs are written. + +## Per-jail Config +Location: +- `base_dir/defs/<jailname>/jprov.conf` + +Schema (TOML): +```toml +# Required +# Relative to datasets.templates_prefix +# Example: "RELEASE-15.0-p3" resolves to "zroot/jails/templates/RELEASE-15.0-p3" +template = "RELEASE-15.0-p3" + +# Required +# Command executed inside the jail via: jexec <jailname> <cmd> +cmd = "/bin/sh /usr/local/sbin/provision.sh" + +# Optional +# Overlay defaults to base_dir/defs/<jailname>/overlay/ +overlay = "overlay" + +# Optional: environment variables passed to the provisioning command +[env] +FOO = "bar" + +# Optional: append raw jail.conf content +extra_jail_conf = """ +allow.raw_sockets = 1; +""" + +# Optional: nullfs mounts +[[mounts]] +host = "/usr/local/jails/volumes/foo" +jail = "/mnt/foo" +readonly = false +``` + +Notes: +- `cmd` is executed as a direct command (no implicit shell wrapping); jprov only checks its exit code. +- `overlay` is copied into the jail root after it is created. +- All `mounts[*].host` paths must exist on the host and are mounted via `nullfs`. diff --git a/docs/PLAN.md b/docs/PLAN.md new file mode 100644 index 0000000..81a4b81 --- /dev/null +++ b/docs/PLAN.md @@ -0,0 +1,78 @@ +# jprov Plan + +Date: 2026-02-14 + +## Goal +Build `jprov`, a FreeBSD jail provisioning tool that treats jails as nearly stateless, recreating them from a template, copying a filesystem overlay, and running a provisioning command inside the jail. If provisioning fails, the run fails. If the jail already exists, it is deleted and recreated. `-y` skips confirmation. + +## Current Understanding +- Primary command: `jprov [jailname]`. +- Reads a main config from `/etc/jprov.conf` (or `/usr/local/etc/jprov.conf`) which defines where per-jail configs live. +- Per-jail config is TOML and includes at least: template, provisioning command, and nullfs mounts. +- Creates a new thin jail as a ZFS clone of the template dataset. +- Deep-copies a tree into the jail filesystem (e.g. `jailname/usr/local/bin/foo` -> `/usr/local/bin/foo`). +- Runs a provisioning command inside the jail; provisioning success depends on this command's exit status. +- If jail already exists, delete it and recreate it. `-y` skips all confirmations. +- Backend is plain `jail(8)` + ZFS (potentially via `jail.conf.d` emission). +- Volume mounts are `nullfs` from host ZFS datasets mounted on the host. +- Example directory layout under a configurable base (e.g., `/usr/local/jails/`): + - `templates/RELEASE-15.0-p3/` + - `defs/<jailname>/jprov.conf` + - `defs/<jailname>/overlay/usr/...` +- `jprov` is intended to be run after system/template upgrades, not on every jail restart. +- Implementation language: Python 3. +- Destructive operations should be delayed as late as possible; validate configs and paths first to avoid tearing down a working jail on config errors. +- N+1 provisioning is not used; jprov stops and destroys the existing jail before creating and provisioning the new jail. +- Provide clear, informative progress output so the user can see each step at a glance. +- Capture all script output to log files in a configurable log dir (default `/var/log/jprov/`); on fatal error, print: "script logs written to <logpath>.log". + +## Open Questions (Need Confirmation) +None. + +## Milestones +1. Confirm requirements and config schema. +2. Define operational workflow and backend commands. +3. Implement config parsing and validation. +4. Implement jail lifecycle (delete, create, overlay copy). +5. Implement provisioning execution and failure handling. +6. Add CLI flags, confirmations, and logging. +7. Add tests and documentation. + +## Architecture (Proposed) +Files and purposes: +- `bin/jprov` (entrypoint): CLI argument parsing, `-y` handling, top-level orchestration. +- `jprov/main.py`: main flow controller; calls config loading, validation, and provisioning steps. +- `jprov/config.py`: parse and validate main config and per-jail TOML; resolve paths; normalize defaults. +- `jprov/jailconf.py`: generate `jail.conf.d/<name>.conf` from config, including `extra_jail_conf`. +- `jprov/zfs.py`: ZFS operations (clone, destroy, dataset existence checks). +- `jprov/mounts.py`: nullfs mount/unmount operations and validation of host paths. +- `jprov/overlay.py`: deep copy overlay into jail root. +- `jprov/provision.py`: run provisioning command via `jexec <name> <cmd>` with env vars. +- `jprov/runner.py`: subprocess wrapper (stdout logging, error handling, and uniform exit code behavior). +- `docs/PLAN.md`: evolving plan and decisions. +- `docs/CONFIG.md`: user-facing config reference (main and per-jail TOML). +- `docs/USAGE.md`: CLI usage and examples. + +Notes: +- Keep module boundaries small and testable; all shell commands go through `runner.py`. +- Provide a dry-run mode later if desired (not in v1 unless requested). + +## Next Actions +1. Finalize main config schema and defaults. +2. Draft per-jail TOML schema and document in `docs/CONFIG.md`. +3. Scaffold Python package and CLI entrypoint. + +## Main Config (Proposed) +```toml +base_dir = "/usr/local/jails" + +[datasets] +templates_prefix = "zroot/jails/templates/" +containers_prefix = "zroot/jails/containers/" + +jail_conf_dir = "/etc/jail.conf.d" +log_dir = "/var/log/jprov" +``` + +Notes: +- `assume_yes` is CLI-only via `-y`. diff --git a/docs/USAGE.md b/docs/USAGE.md new file mode 100644 index 0000000..295ae0b --- /dev/null +++ b/docs/USAGE.md @@ -0,0 +1,20 @@ +# jprov Usage + +## Synopsis +```bash +jprov [-y] [--dry-run] <jailname> +``` + +## Behavior Summary +- Validates configs and referenced paths. +- Stops and destroys any existing jail named `<jailname>`. +- Clones the template dataset into a new jail dataset. +- Generates `/etc/jail.conf.d/<jailname>.conf` (or configured path). +- Mounts nullfs volumes, copies overlay, and executes the provisioning command. + +## Exit Codes +- `0`: success +- `1`: failure + +## Dry Run +`--dry-run` logs actions without executing destructive or provisioning steps. |
