====== Créer et administrer vos jails par ZFS ======
La puissance apportée par [[https://www.freebsd.org/doc/handbook/zfs.html|ZFS]] va vous simplifier la vie dans la gestion de vos [[https://www.freebsd.org/doc/handbook/jails-build.html|jail]].
Dans cet article, une base commune est créée dont sera issues toutes les //jails// que l'on pourra par la suite distribuer pour d'autres machines.
===== Mise en place =====
Avant d'utiliser jail(8), vous devez créer un fichier de configuration: jail.conf(5).
Ce dernier est composé de deux parties.
# variables communes à toutes les jails
exec.clean;
exec.system_user = "root";
exec.jail_user = "root";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.consolelog = "/var/log/jail_${name}_console.log";
path = "/jails/${name}";
R13 {
host.hostname = r13; # Hostname
ip4 = inherit;# IP address of the jail
ip6 = inherit;# IP address of the jail
path = "/jails/RELEASE";
}
Notez que le ''path'', s'il n'est pas précisé explicitement, prendra automatiquement le nom de la //jail//.
Vous aurez probablement besoin d'une interface réseau pour faire communiquer les services des //jails// entre eux.
ifconfig lo1 create
sysrc cloned_interfaces+=lo1
De même, pour assurer un démarrage à chaque //reboot//, activer le service //jail//:
sysrc jail_enable="YES"
Et précisez les //jails// à démarrer dans la variable ''jail_list'', ou ignorez cette variable pour toute les démarrer.
==== Consoles ====
Le paramètre ''exec.consolelog'' va permettre d’enregistrer les messages de console des //jails// dans un fichier journal, pensez à programmer newsyslog(8) pour des nettoyages réguliers:
/var/log/jail_d13_console.log 600 7 1000 * JCG /var/run/jail_d13.pid
/var/log/jail_git_console.log 600 7 1000 * JCG /var/run/jail_git.pid
/var/log/jail_matrix_console.log 600 7 1000 * JCG /var/run/jail_matrix.pid
/var/log/jail_pg_console.log 600 7 1000 * JCG /var/run/jail_pg.pid
/var/log/jail_php_console.log 600 7 1000 * JCG /var/run/jail_php.pid
===== Stockage =====
Créer un [[https://www.freebsd.org/doc/handbook/zfs-term.html#zfs-term-dataset|dataset]] pour contenir toutes les //jails//, puis un [[https://www.freebsd.org/doc/handbook/zfs-term.html#zfs-term-dataset|dataset]] par //jail//.
zfs create -o mountpoint=/jails zroot/JAILS
zfs create zroot/JAILS/RELEASE
Comme vous allez multiplier les //datasets// reposant sur une même base, vous pouvez activer la ''deduplication'' afin d’économiser de l'espace disque, si vous avez assez de mémoire vive.
zfs set dedup=on zroot/JAILS
===== Base =====
Récupérer une //release// et installons une première //jail//, qui va servir de point de départ à toutes les autres.
cd /jails
fetch http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/14.2-RELEASE/base.txz
tar -C RELEASE -xf base.txz
cp /etc/resolv.conf RELEASE/etc/resolv.conf
cp /usr/local/etc/pkg/repos/*.conf RELEASE/etc/pkg
touch RELEASE/etc/rc.conf
Dans cet exemple, j'utiliserai ma propre [[ports:poudriere]].
Et réglez votre rc.conf(5) ainsi:
cron_flags="$cron_flags -J 15"
# Disable Sendmail by default
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
# Run secure syslog
syslogd_flags="-c -ss"
L’entrée pour cron(8) sert à décaler son activation par rapport à l'hôte (//jitter//), pour éviter que les scripts periodic(8) ne se lancent tous en même temps.Mettez des valeurs différentes pour chaque //jail//. Sur certaines jails, vous pouvez même le désactiver:
cron_enable="NO"
Enfin, donnez lui un nom:
hostname=nepasutiliser
==== Mail ====
Si votre //jail// doit pouvoir envoyer des mails, le plus rapide est d'activer le ''sendmail'' de la base sur ce seul service:
sendmail_enable="NO"
sendmail_submit_enable="YES"
Et d'avoir un hostname(1) complet, sur un domaine qualifié ([[https://fr.wikipedia.org/wiki/Fully_qualified_domain_name|FQDN]]).
hostname="diaspora.lapinbilly.eu"
Si vous désactivez complètement //sendmail//, les mails seront envoyés via l'hôte, si sur ce dernier est réglé pour écouter sur toutes les interfaces et non seulement ''localhost''.
sendmail_enable="YES"
sendmail_submit_enable="NO"
Attention, si vous avez autorisé cron(8), periodic(8) sera actif et vous allez remplir la base mail de ''root''.
Assurez vous soit de désactiver les scripts periodic(8) dans ''/etc/crontab'', soit d'envoyer les rapports dans un fichier:
daily_output=/var/log/daily.log
weekly_output=/var/log/weekly.log
monthly_output=/var/log/monthly.log
daily_show_success=NO
daily_show_info=NO
ou ajoutez une adresse mail générique pour cron dans ''/etc/rc.conf'':
cron_flags="$cron_flags -m patron@ailleurs.net"
==== Démarrer ====
Vous pouvez démarrer:
root@popeye:# jail -c R13
R13: created
===== Multiplier =====
A partir de ce point, vous avez préparé une base saine que vous allez pouvoir reproduire facilement.
Faites un [[https://www.freebsd.org/doc/handbook/zfs-term.html#zfs-term-snapshot|cliché]], ''test'', de la base:
zfs snap zroot/JAILS/RELEASE@test
Attention, ce cliché est dédié à la //jail// ''test'', ne prévoyez pas de l'utiliser pour autre chose, puisque qu'en cas de promotion du futur clone, il disparaîtra.
Créons une nouvelle //jail//, simplement en [[https://www.freebsd.org/doc/handbook/zfs-zfs.html|clonant ce cliché]]:
zfs clone zroot/JAILS/RELEASE@test zroot/JAILS/TEST
En fait, vous avez créer un //dataset// à partir d'un cliché.
C'est aussi simple, vous avez une ''jail'' toute prête sur ''zroot/JAILS/TEST''.
Réglons là:
hostname=TEST
TEST {
host.hostname = TEST; # Hostname
ip4.addr = "lo1|192.168.5.2"; # IP address of the jail
}
Si vous devez démarrer des //jails// en cascade, utilisez le mot clef //depend// pour lier les //jails// entre elles.
TEST2 {
host.hostname = TEST2;
depend = TEST;
}
jail -c TEST2
TEST: created
TEST2: created
De même, les jail(8) vont démarrer dans l'ordre donné par le sysrc(8) ''jail_list''.
===== Déployer =====
Il suffit de promouvoir le clone, le rendre indépendant du cliché dont il est issu:
zfs promote zroot/JAILS/TEST
Et voilà.
===== Montages =====
Vous pouvez spécifier les points de montages à créer au démarrage de la jail.
Il suffit de créer un ''fstab'' sour le nom ''fstab.'' et de le préciser dans ''jail.conf''
toto {
mount.fstab="/etc/fstab.toto"
}
C'est utile pour monter du tmpfs(5) ou du nullfs(5):
tmpfs /jails/toto/tmp tmpfs rw 0
===== Réseau =====
Si vous avez attribué une interface réseau avec IP locale sur vos jails,
en d'autre termes, vous n'avez pas utilisé ''inherit'' sur l'un des paramètres ''ip4'' ou ''ip6'',
n'oubliez pas d'écrire une règle de [[https://www.freebsd.org/doc/handbook/network-routing.html|NAT]] pour qu'elles puissent accéder à l'extérieur.
Par exemple, pour pf(4):
jailnet="192.168.0.0/24"
# ...
nat on $ext_if from $jailnet to any -> ($ext_if)
Attention avant d'autoriser l'accès à l'extérieur depuis une //jail//. La plupart du temps, hormis lors de l'installation ou la mise à jour de paquets. Vous n'en avez pas besoin.
===== DNS =====
Pensez à vérifier les valeurs de resolv.conf(5). Si vous avez suivi la procédure, ce devrait être une copie de celle de l'hôte, à moins d'utiliser un serveur DNS local comme unbound(8).\\
Pour donner accès à ce service à vos /jails/, assurez que ce dernier écoute sur des adresses autres que ''localhost''.\\
Par exemple, associez une adresse dédiée à ''unbound'' sur votre interface réseau:
cloned_interfaces="lo1"
ifconfig_lo1="inet 192.168.0.1 netmask 255.255.255.0"
ifconfig_lo1_ipv6="inet6 fd00::1 prefixlen 64"
voire ajouter d'autres alias:
ifconfig_lo1_alias0="inet 192.168.10.1 netmask 255.255.255.0"
ifconfig_lo1_ipv6_alias0="inet6 fe00::1 prefixlen 64"
ou, à la volée:
ifconfig lo1 inet 192.168.0.1 netmask 255.255.255.0 alias
ifconfig lo1 inet6 fd00::1 prefixlen 64 alias
Ensuite configurez unbound(8) pour écouter sur cette addresse:
interface: 192.168.0.1
interface: fd00::1
access-control: 192.168.0.1/24 allow
access-control: fd00::1/24 allow
ou pour tout l'interface dédiée aux //jails//:
interface: lo1
configurez alors les ''resolv.conf'' de vos //jails// pour utiliser ces adresses.
===== Services IP =====
Nombre de services //locaux// écoutent par défaut sur ''localhost'', tel que //redis// ou [[ports:web:php|php-pfm]]. Dans une //jail//, utiliser cette adresse est une très mauvaise idée car elle reste attachée à l'hôte.
Ces services devront écouter l'adresse locale ou sur une socket //unix//.
==== routage IP ====
Pour les services accessibles sur IP depuis l'extérieur que vous ne pourrez pas donner à manger à [[ports:nginx]] vous devrez utiliser des règles de redirection.
Et, de nos jours, vous devrez de plus le faire pour les adresses IPV6:
jail_git="fc00::168:13"
jail_net="192.168.0.1/24"
# ...
nat on $ext_if inet from $jail_net to any -> $ext_if:0
nat on $ext_if inet6 from $jail_git to any -> $ext_if:0
rdr pass on $ext_if proto tcp from any to ($ext_if) port 9418 -> 192.168.0.13 port 9418
rdr pass on $ext_if inet6 proto tcp from any to ($ext_if) port 9418 -> $jail_git port 9418
En //IPV6//, on demande explicitement ('':0'') la première adresse fournie par l'interface pour éviter que //pf// ne route les paquets vers un des liens locaux.
En cas de doute, préciser l'adresse:
''nat on $ext_if inet6 from $jail_git to any -> 2a01::''
===== Mettre à jour =====
Il suffit de demander à freebsd-update(8).
Consultez d'abord les versions en cours à l'aide de freebsd-version(8):
for i in $(jls name); do printf "%-10s- %s\n" $i $(freebsd-version -j ${i}) ; done
pg15 - 13.4-RELEASE-p1
php - 13.4-RELEASE-p1
synapse - 13.4-RELEASE-p1
git - 13.4-RELEASE-p1
epee - 13.4-RELEASE-p1
mariadb - 13.4-RELEASE-p1
next - 13.4-RELEASE-p1
d14 - 13.4-RELEASE-p1
==== configuration ====
freebsd-update(8) suit par défaut la configuration le fichier ''/etc/freebsd-update.conf''.
Créez en une plus adapté aux //jails// en général, en retirant tout ce qui concerne le noyau:
--- /etc/freebsd-update.conf 2018-11-02 03:58:09.000000000 +0000
+++ /usr/local/etc/jail-update.conf 2020-05-05 11:25:40.662419000 +0000
@@ -12,7 +12,7 @@
ServerName update.FreeBSD.org
# Components of the base system which should be kept updated.
-Components src world kernel
+Components world
# Example for updating the userland and the kernel source code only:
# Components src/base src/sys world
@@ -35,7 +35,7 @@
# When upgrading to a new FreeBSD release, files which match MergeChanges
# will have any local changes merged into the version from the new release.
-MergeChanges /etc/ /boot/device.hints
+MergeChanges /etc/
### Default configuration options:
@@ -66,11 +66,11 @@
# When installing a new kernel perform a backup of the old one first
# so it is possible to boot the old kernel in case of problems.
-# BackupKernel yes
+BackupKernel no
# If BackupKernel is enabled, the backup kernel is saved to this
# directory.
# BackupKernelDir /boot/kernel.old
# When backing up a kernel also back up debug symbol files?
-# BackupKernelSymbolFiles no
+BackupKernelSymbolFiles no
==== Lancer ====
Utilisez le fichier de configuration et donnez à freebsd-update(8) les bonnes informations:
* la version avec ''--currently-running ''
* le chemin de la base avec ''-b''
freebsd-update -f /usr/local/etc/jail-update.conf --currently-running 14.2-RELEASE -b /jails/majail fetch install
Notez que vous pouvez automatiser le processus en demandant directement à la //jail// quelle version elle fait tourner:
jexec jailname freebsd-version -u
RELEASE
Utilisez automatiquement cette valeur dans un script par:
freebsd-update -f /usr/local/etc/jail-update.conf --currently-running `jexec jailname freebsd-version -u` -b /jails/majail fetch install
En cas de mise à niveau, vers une version majeure plus récente, procédure est un peu plus longue.
jail -r jailname
freebsd-update -f /usr/local/etc/jail-update.conf --currently-running `jexec jailname freebsd-version -u` -b /jails/majail fetch -r 14.2-RELEASE upgrade
freebsd-update -f /usr/local/etc/jail-update.conf -b /jails/majail fetch install
jail -c jailname
freebsd-update -f /usr/local/etc/jail-update.conf -b /jails/majail fetch install
pkg -j jailname bootstrap -f
pkg -j jailname upgrade
jail -rc jailname
===== Ports ======
Utilisez des [[ports:poudriere|poudrieres]] pour installer des logiciels dans vos jails et afiner ainsi la configuration et le comportement d'une jail.\\
Par exemple, supprimer tout ce qui ressemble à une documentation, un affichage graphique ou une imprimante:
OPTIONS_UNSET=DOC DOCS NLS X11 EXAMPLES EXAMPLE XCB WAYLAND DEBUG TEST TESTS OPENGL DTRACE INFO BE_STANDARD
OPTIONS_UNSET+=CUPS MANPAGES
DEFAULT_VERSIONS+= imagemagick=6-nox11
#DEFAULT_VERSIONS+= imagemagick=7-nox11
Si vous utilisez une configuration identique à celle de l'hôte pour vos jails, il suffit de //chrooter// ''pkg'':
pkg -c /jails/example upgrade
===== En savoir plus =====
* [[https://gitlab.com/TurtleCrazy/fbsd-stable-mgmt|jeu de scripts pour mettre à jours les jails]] ;
* ''jail_update.sh'': mise à jour de la base des ''jails'' en cours de fonctionnement ;
* ''portupgrade.sh'': mise à jour des ports installés dans les ''jails'' en cours de fonctionnement et sur l'hôte.
* [[https://wiki.freebsd.org/TomMarcoen/JailNetworking|Wiki sur le réseau pour les jails]].