Jail management tool for FreeBSD, written in Go. Support iocage jails, so they can coexist. Gocage is meant to be a complete jail management tool with network, snapshots, jail cloning support and a web interface.
Go to file
2024-09-22 19:35:46 +02:00
cmd Update release with -r and -d flags 2024-09-22 19:30:39 +02:00
jail Add Devfs_ruleset property to reflect generated RS 2022-10-15 16:33:29 +02:00
service Add service file 2022-10-15 15:16:26 +02:00
.gitignore rm blank line 2022-10-16 15:17:56 +02:00
CHANGELOG Add gocage destroy command, v0.35 2023-07-09 13:43:35 +02:00
go.mod Update viper and cobra versions 2024-09-22 15:18:15 +02:00
gocage.conf.yml freebsd-update work directory is now configurable in gocage.conf.yml 2024-09-22 19:30:35 +02:00
LICENSE Initial commit 2021-11-27 10:43:28 +01:00
main.go WIP on start, go fmt on * 2022-04-24 16:49:54 +02:00
README.md Update README 2024-09-22 19:35:46 +02:00
TODO.md Update TODO 2024-04-20 20:33:59 +02:00

GoCage

Jail management tool for FreeBSD, written in Go.
Support iocage jails, so they can coexist.
Gocage is meant to be a complete jail management tool with network, snapshots, jail cloning support and a web interface. This is the hypothetic future.
Gocage can handle multiple datastores, so you can have jails on HDD storage and jails on SSD storage.

From v0.33b, due to multi ZFS pool support, gocage is no longer 100% compatible with iocage.
Zfs datasets now should be specified with the ZFS pool. e.g. :

Config.Jail_zfs = 1
Config.Jail_zfs_dataset = myzfspool/poudriere
Config.Jail_zfs_mountpoint = none

Create jails

You need to specify release, and optional configuration:

gocage create jail1 -r 13.2-RELEASE -p "Config.Ip4_addr='vnet0|192.168.1.91/24',Config.Ip6=none,Config.Boot=1"

Create basejail. A basejail is a jail based on a release: system will be nullfs read-only mounted from the release directory. Main advantage is that release updates will immediately apply to jails based on this release. Another advantage is that jail system is mounted read-only, a plus from a security perspective:

gocage create -b -r 14.0-RELEASE basejail1

List jails

gocage list

Specify fields to display

Use -o to specify which fields you want to display:

gocage list -o JID,Name,Running,Config.Boot,Config.Comment  
+=====+==========+=========+=============+================+  
| JID | Name     | Running | Config.Boot | Config.Comment |  
+=====+==========+=========+=============+================+  
| 183 | test     | true    | 1           | none           |  
+-----+----------+---------+-------------+----------------+  
| 29  | srv-irc  | true    | 1           |                |  
+-----+----------+---------+-------------+----------------+  
|     | srv-web  | false   | 0           |                |  
+-----+----------+---------+-------------+----------------+  
| 22  | srv-dns1 | true    | 1           |                |  
+-----+----------+---------+-------------+----------------+  

See cmd/struct.go for field names.

Filter jails

By name

Just add name on gocage list command :

gocage list srv-bdd srv-web
+=====+=========+=================+=======================+=========+
| JID | Name    | Config.Release  | Config.Ip4_addr       | Running |
+=====+=========+=================+=======================+=========+
| 98  | srv-db  | 13.0-RELEASE-p5 | vnet0|192.168.1.56/24 | true    |
+-----+---------+-----------------+-----------------------+---------+
| 41  | srv-web | 13.0-RELEASE-p4 | vnet0|192.168.1.26/24 | true    |
+-----+---------+-----------------+-----------------------+---------+

By field value

You can filter jails with -f option, followed by key=value. Suppose you want to see only active at boot jails:

gocage list -f Config.Boot=1 -o JID,Name,Running,Config.Boot,Config.Comment
+=====+==========+=========+=============+================+
| JID | Name     | Running | Config.Boot | Config.Comment |
+=====+==========+=========+=============+================+
| 183 | test     | true    | 1           | none           |
+-----+----------+---------+-------------+----------------+
| 29  | srv-irc  | true    | 1           |                |
+-----+----------+---------+-------------+----------------+
|     | srv-db   | false   | 1           | none           |
+-----+----------+---------+-------------+----------------+
| 22  | srv-dns1 | true    | 1           |                |
+-----+----------+---------+-------------+----------------+

Now, only active at boot and running :

gocage list -f Config.Boot=1,Running=true -o JID,Name,Running,Config.Boot
+=====+==========+=========+=============+
| JID | Name     | Running | Config.Boot |
+=====+==========+=========+=============+
| 183 | test     | true    | 1           |
+-----+----------+---------+-------------+
| 29  | srv-irc  | true    | 1           |
+-----+----------+---------+-------------+
| 22  | srv-dns1 | true    | 1           |
+-----+----------+---------+-------------+

Sort jails

Use -s switch followed by sort criteria. Criteria is a field name, prefixed with + or - for sort order (increase/decrease):

gocage list -f Config.Boot=1,Running=true -o JID,Name,Running,Config.Boot -s +JID
+=====+==========+=========+=============+
| JID | Name     | Running | Config.Boot |
+=====+==========+=========+=============+
| 22  | srv-dns1 | true    | 1           |
+-----+----------+---------+-------------+
| 29  | bdd-tst  | true    | 1           |
+-----+----------+---------+-------------+
| 183 | test     | true    | 1           |
+-----+----------+---------+-------------+

You can use up to 3 criteria, delimited with comma.
As an example, you want to list boot priorities of automatically starting jails:

gocage list -o JID,Name,Config.Ip4_addr,Config.Priority,Config.Boot,Running -s -Config.Priority,-Config.Boot -f Running=true
+=====+==============+=======================+=================+=============+=========+
| JID | Name         | Config.Ip4_addr       | Config.Priority | Config.Boot | Running |
+=====+==============+=======================+=================+=============+=========+
| 1   | srv-dhcp     | vnet0|192.168.1.2/24  | 99              | 1           | true    |
+-----+--------------+-----------------------+-----------------+-------------+---------+
| 8   | srv-dns      | vnet0|192.168.1.1/24  | 80              | 1           | true    |
+-----+--------------+-----------------------+-----------------+-------------+---------+
| 7   | srv-random   | vnet0|192.168.1.12/24 | 20              | 1           | true    |
+-----+--------------+-----------------------+-----------------+-------------+---------+
| 4   | coincoin     | vnet0|192.168.1.9/24  | 20              | 0           | true    |
+-----+--------------+-----------------------+-----------------+-------------+---------+

Stop jails

gocage stop test

Update jails

To update jail patch version, use gocage update :
gocage update test

Update basejails/releases

To update basejails, you need to update the release they are based on. Specify release with -r, and the datastore storing concerned release with -d :
gocage update -d fastgocage -r 14.1-RELEASE

Upgrade jails

To upgrade jail to newer release, use gocage upgrade :
gocage upgrade -r 13.2-RELEASE test

A pre-upgrade snapshot wil be made so you can rollback if needed.

Upgrading basejail/release

Upgrading basejails currently needs to be done manually, for each jail.
The idea is to stop the jail, change the content of its fstab file to point to the new release, then start jail.
If one change the fstab while the jail is running, its system directories won't be unmounted at stop time and this will provoke stop errors.
To minimize downtime, the change could be scripted:

gocage stop jail1
sed -i .bak 's/14.0-RELEASE/14.1-RELEASE/' /iocage/jails/jail1/fstab
# Avoid race-condition by waiting for the update in fstab
until grep -q 14.1-RELEASE /iocage/jails/jail1/fstab; do sleep 0.2; done
gocage start jail1

You can now update ports.

Delete jails

gocage destroy test

Multi datastore

A datastore is a ZFS dataset mounted. It should be declared in gocage.conf.yml, specifying its ZFS mountpoint :

datastore:
  - /iocage
  - /fastiocage

In gocage commands, datastore name is the mountpoint without its "/" prefix.

List datastores

gocage datastore list 
+============+=============+============+===========+==========+============+
| Name       | Mountpoint  | ZFSDataset | Available | Used     | Referenced |
+============+=============+============+===========+==========+============+
| iocage     | /iocage     | hdd/iocage | 1.6 TB    | 414.9 GB | 27.5 KB    |
+------------+-------------+------------+-----------+----------+------------+
| fastiocage | /fastiocage | ssd/iocage | 1.5 TB    | 65.3 KB  | 34.6 KB    |
+------------+-------------+------------+-----------+----------+------------+

Filter datastores

As with jails and snapshots, you can filter by name:

gocage datastore list iocage
+============+=============+============+===========+==========+============+
| Name       | Mountpoint  | ZFSDataset | Available | Used     | Referenced |
+============+=============+============+===========+==========+============+
| iocage     | /iocage     | hdd/iocage | 1.6 TB    | 414.9 GB | 27.5 KB    |
+------------+-------------+------------+-----------+----------+------------+

Sort datastores

You can sort datastores:

gocage datastore list -s -Available
+============+=============+============+===========+==========+============+
| Name       | Mountpoint  | ZFSDataset | Available | Used     | Referenced |
+============+=============+============+===========+==========+============+
| iocage     | /iocage     | hdd/iocage | 1.6 TB    | 415.0 GB | 27.5 KB    |
+------------+-------------+------------+-----------+----------+------------+
| fastiocage | /fastiocage | ssd/iocage | 1.5 TB    | 65.3 KB  | 34.6 KB    |
+------------+-------------+------------+-----------+----------+------------+

See cmd/struct.go for field names.

Migrating jails

With multi datastore comes the need to migrate a jail between datastores.
Migration can be done with a minimal downtime, using zfs differential send/receive.
Source jail datasets are sent to the destination datastore, jail is stopped and a last differential sync is done before starting jail on new datastore.

Warning

Be aware the moment you migrate a jail to another datastore than /iocage default, you lose compatibility with iocage.
Then you need to disable iocage service, and enable gocage so the jails will start automatically at boot.
Also make sure, if you don't destroy source jail, that it won't have the "boot" property set or you will have the 2 jails up at boot.

gocage migrate -d fastiocage srv-random
Snapshot data/iocage/jails/srv-random: Done
Snapshot data/iocage/jails/srv-random/root: Done
Migrate jail config dataset to fastdata/iocage/jails/srv-random: Done
Migrate jail filesystem dataset to fastdata/iocage/jails/srv-random/root: Done

Fetch

Files can be fetched from custom repository, or from local directory with "from" option.
For example if you destroyed releases/12.3-RELEASE and still have the downloaded files in /iocage/download/12.3-RELEASE:

gocage fetch -r 12.3 -d iocage -f file:/iocage/download

TODO

gocage create from templates
gocage init
create default pool with defaults.json