Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sylve

Build Status Last Commit

Modern, open-source management platform for FreeBSD managing Virtual Machines (Bhyve), Jails, and ZFS storage.

!!! tip "What is Sylve?" Sylve is a modern, open-source management platform for FreeBSD: Bhyve VMs, jails, ZFS, and networking behind one web UI. It manages the host from inside its own jail, so it needs host access a normal container never gets -- kernel modules, devfs entries like /dev/pf and /dev/vmm, ZFS delegation, and allow.vmm. Both deploy methods below wire that up for you.

Version Tags

Both tags ship Sylve's prebuilt native-FreeBSD binary from a GitHub release; they differ only in which release they track.

Tag Description Best For
latest The latest tagged release (AlchemillaHQ/Sylve). Most deployments.
nightly The rolling tip release, tracking upstream master. Early access to unreleased fixes.

Prerequisites

Requirements:

  • FreeBSD 15+ and root
  • A ZFS pool (a sylve dataset gets delegated to the jail)
  • AppJail path: appjail 5.4+, sysutils/py-director -- Podman path: podman, ocijail, podman-compose

Deploy

!!! warning "Experimental" Both the Podman and AppJail deployments of Sylve are experimental on our end.

=== ":appjail-appjail: AppJail Director"

!!! warning "`load-kld` hook is required"
    [load-kld](https://github.com/DtxdF/AppJail/blob/main/share/examples/appjail/hooks/pre.d/load-kld.sh) hook is required for the kernel-module handling this deployment relies on.

    1. Be sure to set `HOOKSDIR` in your `appjail.conf(5)` file.
       ```console
       $ grep '^HOOKSDIR' /usr/local/etc/appjail/appjail.conf
       HOOKSDIR=/usr/local/etc/appjail/hooks
       ```
    2. Create the hooks directory if it does not exist.
       ```console
       $ mkdir -p /usr/local/etc/appjail/hooks/pre.d/
       ```
    3. Install the `load-kld` hook and set the execute bit.
       ```console
       $ fetch -o /usr/local/etc/appjail/hooks/pre.d/load-kld.sh https://github.com/DtxdF/AppJail/blob/main/share/examples/appjail/hooks/pre.d/load-kld.sh
       $ chmod +x /usr/local/etc/appjail/hooks/pre.d/load-kld.sh
       ```

**1.** Prepare the host (one time). Kernel modules are loaded automatically at jail start via `load-kld` labels; only the boot-only `kern.racct` tunable touches `loader.conf`:

```bash
pkg install -y appjail sysutils/py-director
[ "$(sysctl -n kern.racct.enable)" = "1" ] || echo 'kern.racct.enable="1"' >> /boot/loader.conf
# reboot if `sysctl -n kern.racct.enable` is still 0 (Sylve requires racct)
sysrc appjail_enable=YES
```

**2.** Save as `.env`:

``` { data-zip-bundle="sylve-appjail" data-zip-filename=".env" }
# Host path for Sylve's data
SYLVE_DATA_LOCATION=/var/appjail-volumes/sylve/data
DIRECTOR_PROJECT=sylve
```

**3.** Save as `appjail-director.yml`:

```yaml { data-zip-bundle="sylve-appjail" data-zip-filename="appjail-director.yml" }
options:
  # Equivalent to 'network_host: host'.
  # Use it only if you don't have problems with Sylve managing your pf(4).
  #- alias:
  #- ip4_inherit:
  #
  # The jail will use its own network stack without touching with the host's;
  # in addition, AppJail will configure an IPv4 address that you can use to
  # communicate with Sylve via the jail's IPv4 address or hostname (if you
  # have enabled DNS in AppJail).
  - virtualnet: ':<random> default'
  - nat:
services:
  sylve:
    name: sylve
    options:
      - from: ghcr.io/daemonless/sylve:nightly
      - template: !ENV '${PWD}/sylve-template.conf'
      - container: 'args:--pull'
      - label: 'load-kld:1'
      - label: 'load-kld.load-vmm:vmm'
      - label: 'load-kld.load-if-bridge:if_bridge'
      - label: 'load-kld.load-cryptodev:cryptodev'
      - label: 'load-kld.load-if-epair:if_epair'
      - label: 'load-kld.load-nullfs:nullfs'
      - label: 'load-kld.load-netlink:netlink'
      - label: 'load-kld.load-nlsysevent:nlsysevent'
      - label: 'load-kld.load-nmdm:nmdm'
      - label: 'load-kld.load-pf:pf'
      - label: 'load-kld.load-pflog:pflog'
      - label: 'load-kld.load-if-wg:if_wg'
      - label: 'load-kld.load-linux:linux'
      - label: 'load-kld.load-linux.module:linuxelf'
      - label: 'load-kld.load-linux64:linux64'
      - label: 'load-kld.load-linux64.module:linux64elf'
      - label: 'load-kld.load-pty:pty'
      - label: 'load-kld.load-linprocfs:linprocfs'
      - label: 'load-kld.load-linsysfs:linsysfs'
      - label: 'load-kld.load-ctl:ctl'
      - label: 'load-kld.load-iscsi:iscsi'
      - device: 'include $devfsrules_hide_all'
      - device: 'include $devfsrules_unhide_basic'
      - device: 'include $devfsrules_unhide_login'
      - device: 'include $devfsrules_jail'
      - device: 'include $devfsrules_jail_vnet'
      - device: 'path zfs unhide'
      - device: 'path zvol unhide'
      - device: "path 'zvol/*' unhide"
      - device: "path 'zvol/*/*' unhide"
      - device: "path 'zvol/*/*/*' unhide"
      - device: "path 'zvol/*/*/*/*' unhide"
      - device: "path 'zvol/*/*/*/*/*' unhide"
      - device: 'path shm unhide'
      - device: 'path pf unhide'
      - device: 'path pflog unhide'
      - device: 'path bpf unhide'
      - device: "path 'bpf*' unhide"
      - device: 'path vmm unhide'
      - device: "path 'vmm/*' unhide"
      - device: 'path vmm.io unhide'
      - device: "path 'vmm.io/*' unhide"
      - device: 'path vmmctl unhide'
      - device: "path 'nmdm*' unhide"
      - device: "path 'tap*' unhide"
      - device: 'path mem unhide'
      - device: 'path kmem unhide'
      - device: 'path pci unhide'
      - device: 'path io unhide'
      - device: 'path cam unhide'
      - device: "path 'cam/ctl' unhide"
      - device: "path 'da*' unhide"
      - device: "path 'ada*' unhide"
      - device: "path 'nda*' unhide"
      - device: "path 'pass*' unhide"
      - device: "path 'xpt*' unhide"
      - device: "path 'nvme*' unhide"
      - device: 'path iscsi unhide'
    volumes:
      - sylve-data: /var/db/sylve
volumes:
  sylve-data:
    device: !ENV '${SYLVE_DATA_LOCATION}'
```

**4.** Save as `sylve-template.conf`:

``` { data-zip-bundle="sylve-appjail" data-zip-filename="sylve-template.conf" }
# EDIT: the ZFS dataset created during host prep
${dataset}: zroot/sylve
# Number of child jails allowed to be created by this jail.
${children_max}: 100

exec.start: "/bin/sh /etc/rc"
exec.stop: "/bin/sh /etc/rc.shutdown jail"
mount.devfs
persist
allow.vmm
allow.vmm_ppt
stop.timeout: 30
allow.chflags
allow.raw_sockets
allow.routing
allow.nfsd
allow.unprivileged_proc_debug
enforce_statfs: 1
allow.mount
allow.mount.devfs
allow.mount.fdescfs
allow.mount.linprocfs
allow.mount.linsysfs
allow.mount.tmpfs
allow.mount.zfs
zfs.mount_snapshot
children.max: ${children_max}
allow.socket_af
allow.sysvipc
allow.reserved_ports
allow.set_hostname
allow.suser
exec.created+: "zfs create -p -o jailed=on ${dataset}"
exec.created+: "zfs jail ${name} ${dataset}"
exec.created+: "jexec -l ${name} zfs list -t fs -Hro name ${dataset} | xargs -L 1 jexec -l ${name} zfs mount"
exec.prestop+: "jexec -l ${name} zfs list -t fs -Hro name ${dataset} | tail -r | xargs -L 1 jexec -l ${name} zfs umount"
exec.clean
```

**5.** Save as `Makejail`:

``` { data-zip-bundle="sylve-appjail" data-zip-filename="Makejail" }
OPTION container=boot
OPTION overwrite=force
```

**6.** Create the data directory and deploy:

```bash
appjail-director up
```

=== ":material-tune: Podman Compose"

**1.** Prepare the host (one time). Generate the setup script, review it, then run it -- it loads the kernel modules, adds a devfs ruleset, creates the ZFS dataset, and installs the OCI `createRuntime` hook (`ocijail` can't express devfs rulesets or ZFS delegation through annotations). Each step asks before running; already-configured steps are skipped:

```bash
podman run --rm ghcr.io/daemonless/sylve:latest host-setup > sylve-setup.sh
less sylve-setup.sh          # review exactly what it will change
sh sylve-setup.sh            # or: sh sylve-setup.sh -y
```

If it reports that `kern.racct` needs a reboot, reboot before continuing (Sylve requires it).

**2.** Create the deployment files. `init` writes `compose.yaml` and `.env` into the current directory (it refuses to overwrite existing files without `--force`):

```bash
podman run --rm -v "$PWD:/out" ghcr.io/daemonless/sylve:latest init
vi .env
```

**3.** Start:

```bash
mkdir -p "$SYLVE_DATA_LOCATION"   # FreeBSD won't auto-create a bind-mount source
podman compose up -d
```

Access Sylve at: https://your-host:8181 (first login: admin / admin)

Environment Variables

Variable Default Description
SYLVE_HOSTNAME -- The jail's hostname (node-identity check). Podman: hostname: in compose.yaml.
SYLVE_DATA_LOCATION -- Host path for Sylve's data (/var/db/sylve in the jail).
SYLVE_DATASET zroot/sylve ZFS dataset delegated to Sylve. AppJail: ${dataset} in sylve-template.conf.
TZ System default Timezone.

Ports

Port Service Description
8181 sylve Web UI (HTTPS)

!!! note "Network Mode" The Podman path shares the host network (network_mode: host) so Sylve manages the host's interfaces, firewall, and VMs directly. The AppJail path defaults to its own vnet + NAT to avoid clobbering the host's pf(4) rules -- uncomment alias/ip4_inherit in appjail-director.yml for host networking instead.

FreeBSD-Specific Notes

selected_node_not_found

If requests fail with selected_node_not_found, Sylve's EnsureCorrectHost check is comparing its configured hostname against the one you're browsing to -- set the jail's hostname to the name you reach it at.

Never bind-mount /dev

A nullfs /dev (-v /dev:/dev) makes Bhyve guest-memory mmap fail with ENXIO (Unable to setup memory (6)) -- VM creation succeeds but the guest never boots. Both deploy methods mount a real devfs via a ruleset; don't override it.

Undo (Podman host-setup)

sh sylve-setup.sh --undo removes Sylve's OCI hook and devfs ruleset. It never touches your ZFS dataset (it prints the zfs destroy command if you want it gone).


Registry ghcr.io/daemonless/sylve
Upstream https://github.com/AlchemillaHQ/Sylve
Website https://sylve.io

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages