Skip to content

Creation

Creating a Jail requires a CTID, name, ZFS pool, root filesystem source, network choice, and Jail type. The CLI accepts either core flags or a complete JSON request file.

Exactly one source is required:

  • A bootstrap managed under the selected ZFS pool.
  • A completed base-rootfs download, referenced by its UUID.

Do not supply both --base and --bootstrap.

List the bootstraps supported for a pool:

Terminal window
doas sylve jails bootstrap list --pool zroot

Inside the interactive console, the pool is positional:

jails bootstrap list zroot

Real output from the test node includes:

Name Version Type Status
15-0-Base 15.0 base not installed
15-0-Minimal 15.0 minimal not installed
15-1-Base 15.1 base not installed
15-1-Minimal 15.1 minimal not installed

Install a bootstrap asynchronously:

Terminal window
doas sylve jails bootstrap create \
--pool zroot \
--version 15.1 \
--type minimal

Add --wait to keep the command open until installation completes or fails:

jails bootstrap create zroot 15.1 minimal --wait

The version must use major.minor form, and the type must be base or minimal. Run the list command again to follow the reported status and phase.

List completed downloads and find one whose uType is base-rootfs:

Terminal window
doas sylve downloads list --json

Pass the download’s uuid to --base. Do not use its numeric list ID.

The core creation flags are:

Flag Required Purpose
--ctid <id> Yes Unique Jail ID from 1 through 9999.
--name <name> Yes Jail name. It cannot be empty.
--pool <pool> Yes ZFS pool that will contain the Jail dataset.
--base <uuid> One source required UUID of a completed base-rootfs download.
--bootstrap <name> One source required Name of an installed FreeBSD bootstrap in the selected pool.
--switch <name> Yes Switch name, none, or inherit.
--type <type> Yes Jail type: freebsd or linux.

Supply exactly one of --base and --bootstrap. These flags are also available as explicit overrides when --file is used. The separate --json flag changes command output and is not part of the creation request.

The following FreeBSD example uses a previously installed bootstrap and does not attach a network:

Terminal window
doas sylve jails create \
--ctid 101 \
--name web01 \
--pool zroot \
--bootstrap 15-1-Minimal \
--switch none \
--type freebsd

The console accepts the same named creation options:

jails create --ctid 101 --name web01 --pool zroot --bootstrap 15-1-Minimal --switch none --type freebsd

CTIDs must be unique integers from 1 through 9999. The type must be freebsd or linux. For --switch, supply a switch name, none, or inherit.

Configure DHCP and SLAAC on the selected switch

Section titled “Configure DHCP and SLAAC on the selected switch”

The core --switch flag selects the switch, but the core flags do not expose address configuration. Use a JSON request to enable DHCP, SLAAC, static addresses, a MAC address, or VLAN tagging on the initial attachment.

This example creates a FreeBSD Jail attached to TTT, obtains IPv4 configuration through DHCP, and obtains IPv6 configuration through SLAAC:

{
"name": "auto-net",
"ctId": 103,
"hostname": "auto-net.example.test",
"pool": "zroot",
"bootstrapName": "15-1-Minimal",
"switchName": "TTT",
"dhcp": true,
"slaac": true,
"type": "freebsd",
"allowedOptions": ["allow.mount.devfs"]
}

Save it as auto-net.json, then create the Jail:

Terminal window
doas sylve jails create --file ./auto-net.json

Sylve automatically generates a MAC object when neither mac nor macRaw is supplied. DHCP and SLAAC leave the corresponding static address and gateway fields unset.

allow.mount.devfs is required for DHCP because FreeBSD’s DHCP client needs access to a BPF device inside the Jail. Sylve applies its managed devfs ruleset, which exposes BPF while retaining the standard Jail device restrictions. Without this option, the Jail can start but dhclient cannot obtain a lease.

For a static IPv4 configuration, replace the automatic fields with raw address values:

{
"name": "static-net",
"ctId": 104,
"hostname": "static-net.example.test",
"pool": "zroot",
"bootstrapName": "15-1-Minimal",
"switchName": "TTT",
"dhcp": false,
"ipv4Raw": "10.20.0.10/24",
"ipv4GwRaw": "10.20.0.1",
"type": "freebsd"
}

You can use ipv4 and ipv4Gw object IDs instead of raw values. IPv6 follows the same pattern with ipv6, ipv6Gw, ipv6Raw, and ipv6GwRaw. Add vlan or macRaw to the same request when the attachment requires them.

Use a downloaded root filesystem by replacing the bootstrap option:

Terminal window
doas sylve jails create \
--ctid 102 \
--name service01 \
--pool zroot \
--base 42f7f8df-dcbc-5ff1-ad93-c45209d733f4 \
--switch WAN \
--type freebsd

The UUID shown above is real output from the test node and is only an example. Always obtain the current UUID from your own node.

A real Sylve 0.3.0 session verifying both FreeBSD 15.1 bootstraps and the DHCP and static Jails created from JSON requests.

Core flags intentionally expose only the common fields. Use a strict JSON request when you need hostname, address objects, resource limits, startup behavior, allowed options, hooks, or metadata.

{
"name": "web01",
"ctId": 101,
"hostname": "web01.example.test",
"description": "Documentation example",
"pool": "zroot",
"base": "",
"bootstrapName": "15-1-Minimal",
"switchName": "none",
"type": "freebsd",
"allowedOptions": [],
"hooks": {
"prestart": { "enabled": false, "script": "" },
"start": { "enabled": false, "script": "" },
"poststart": { "enabled": false, "script": "" },
"prestop": { "enabled": false, "script": "" },
"stop": { "enabled": false, "script": "" },
"poststop": { "enabled": false, "script": "" }
}
}

Create the Jail from that file:

Terminal window
doas sylve jails create --file ./web01.json

Explicit core flags override matching fields loaded from the file. Unknown JSON fields are rejected, which helps catch misspelled configuration keys.

The JSON document supports the complete CreateJailRequest implemented by Sylve. Fields marked as core are required after file values and command-line overrides are combined.

JSON field Value Purpose
name String Core. Non-empty Jail name.
ctId Integer Core. Unique CTID from 1 through 9999.
hostname String Hostname configured for the Jail.
description String Optional descriptive text.
pool String Core. ZFS pool used for Jail storage.
base String UUID of a completed base-rootfs download. Mutually exclusive with bootstrapName.
bootstrapName String Installed bootstrap name. Mutually exclusive with base.
fstab String Jail filesystem mount configuration.
resolvConf String Contents used for the Jail’s resolver configuration.

Exactly one of base and bootstrapName must be non-empty.

JSON field Value Purpose
switchName String Core. Switch name, none, or inherit.
inheritIPv4 Boolean Inherit the host’s IPv4 networking.
inheritIPv6 Boolean Inherit the host’s IPv6 networking.
dhcp Boolean Request IPv4 configuration through DHCP.
slaac Boolean Request IPv6 configuration through SLAAC.
ipv4 Integer IPv4 host-object ID.
ipv4Gw Integer IPv4 gateway host-object ID.
ipv4Raw String Manual IPv4 address value.
ipv4GwRaw String Manual IPv4 gateway value.
ipv6 Integer IPv6 host-object ID.
ipv6Gw Integer IPv6 gateway host-object ID.
ipv6Raw String Manual IPv6 address value.
ipv6GwRaw String Manual IPv6 gateway value.
mac Integer MAC-object ID.
macRaw String Manual MAC address.
vlan Integer VLAN identifier for the initial attachment.

Object ID fields and their corresponding raw fields provide two ways to express the same kind of value. Prefer reusable objects when an address will be shared across configurations or managed centrally.

JSON field Value Purpose
resourceLimits Boolean Enable Jail CPU and memory limits.
cores Integer Number of CPU cores assigned when limits are enabled.
memory Integer Memory allocation used by the Jail service.
startAtBoot Boolean Start the Jail during Sylve startup.
startOrder Integer Relative startup ordering value.
devfsRuleset String Additional FreeBSD devfs rule content appended to the managed Jail ruleset.
JSON field Value Purpose
type String Core. freebsd or linux.
allowedOptions String array Jail options explicitly allowed by the configuration.
cleanEnvironment Boolean Start with a clean Jail environment.
additionalOptions String Additional Jail configuration options.
JSON field Value Purpose
hooks.prestart Hook phase Runs before the Jail starts.
hooks.start Hook phase Runs during the start phase.
hooks.poststart Hook phase Runs after the Jail starts.
hooks.prestop Hook phase Runs before the Jail stops.
hooks.stop Hook phase Runs during the stop phase.
hooks.poststop Hook phase Runs after the Jail stops.
metadataMeta String Additional metadata stored with the Jail.
metadataEnv String Environment metadata stored with the Jail.

Each hook phase is an object containing an enabled boolean and a script string:

{
"enabled": true,
"script": "/usr/local/libexec/sylve/hooks/web01-prestart.sh"
}

Boolean and numeric fields represented as pointers in the Go request can be omitted when no explicit value is needed. This differs from sending false or 0, which explicitly selects that value.

Use --json when a script needs the created CTID and name as structured output.