From 71836a11cb357324e5fefe7a54f718750f839e6a Mon Sep 17 00:00:00 2001 From: Jip-Hop <2871973+Jip-Hop@users.noreply.github.com> Date: Sat, 12 Aug 2023 18:14:09 +0200 Subject: [PATCH] Add install command --- README.md | 14 +++++++++++--- jlmkr.py | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d27e0f7..f5e525b 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,16 @@ chmod +x jlmkr.py The `jlmkr.py` script (and the jails + config it creates) are now stored on the `jailmaker` dataset and will survive updates of TrueNAS SCALE. +## Install Jailmaker Dependencies + +Unfortunately since version 22.12.3 TrueNAS SCALE no longer includes systemd-nspawn. In order to use jailmaker, we need to first install systemd-nspawn using the command below. + +```shell +./jlmkr.py install +``` + +We need to do this again after each update of TrueNAS SCALE. So it is recommended to schedule this command as Post Init Script (see [Autostart Jail on Boot](#autostart-jail-on-boot)). + ## Create Jail Creating a jail is interactive. You'll be presented with questions which guide you through the process. @@ -46,7 +56,7 @@ After answering a few questions you should have your first jail up and running! ### Autostart Jail on Boot -In order to start a jail automatically after TrueNAS boots, run `/mnt/mypool/jailmaker/jlmkr.py start myjail` as Post Init Script with Type `Command` from the TrueNAS web interface. +In order to start a jail automatically after TrueNAS boots, run `/mnt/mypool/jailmaker/jlmkr.py start myjail` as Post Init Script with Type `Command` from the TrueNAS web interface. If you want to automatically install systemd-nspawn if it's not already installed (recommended to keep working after a TrueNAS SCALE update) then you may use a command such as this instead: `/mnt/mypool/jailmaker/jlmkr.py install && /mnt/mypool/jailmaker/jlmkr.py start myjail`. ## Additional Commands @@ -128,8 +138,6 @@ To make passthrough of the nvidia GPU work, you need to schedule a Pre Init comm TODO: write comparison between systemd-nspawn (without jailmaker), LXC, VMs, Docker (on the host). -## Known Issues - ### Incompatible Distros The rootfs image `jlmkr.py` downloads comes from the [Linux Containers Image server](https://images.linuxcontainers.org). These images are made for LXC. We can use them with systemd-nspawn too, although not all of them work properly. For example, the `alpine` image doesn't work well. If you stick with common systemd based distros (Debian, Ubuntu, Arch Linux...) you should be fine. diff --git a/jlmkr.py b/jlmkr.py index 7a64a1f..1d8e54d 100755 --- a/jlmkr.py +++ b/jlmkr.py @@ -4,6 +4,7 @@ import argparse import configparser import contextlib import ctypes +import glob import hashlib import os import re @@ -32,9 +33,9 @@ DISCLAIMER = f"""{YELLOW}{BOLD}USE THIS SCRIPT AT YOUR OWN RISK! IT COMES WITHOUT WARRANTY AND IS NOT SUPPORTED BY IXSYSTEMS.{NORMAL}""" DESCRIPTION = "Create persistent Linux 'jails' on TrueNAS SCALE, with full access to all files \ - via bind mounts, without modifying the host OS thanks to systemd-nspawn!" + via bind mounts, thanks to systemd-nspawn!" -VERSION = '0.0.4' +VERSION = '0.0.5' JAILS_DIR_PATH = 'jails' JAIL_CONFIG_NAME = 'config' @@ -768,6 +769,33 @@ def list_jails(): print("\nCurrently running:\n") subprocess.run(['machinectl', 'list']) +def install_jailmaker_dependencies(): + # Check if command exists in path + if shutil.which('systemd-nspawn'): + print("systemd-nspawn is already installed.") + return + + print("Installing jailmaker dependencies...") + + original_permissions = {} + + print("Temporarily enable apt and dpkg (if not already enabled) to install systemd-nspawn.") + + # Make /bin/apt* and /bin/dpkg* files executable + for file in (glob.glob('/bin/apt*') + (glob.glob('/bin/dpkg*'))): + original_permissions[file] = os.stat(file).st_mode + stat_chmod(file, 0o755) + + subprocess.run(['apt-get', 'update'], check=True) + subprocess.run(['apt-get', 'install', '-y', 'systemd-container'], check=True) + + # Restore original permissions + print("Restore permissions of apt and dpkg.") + + for file, original_permission in original_permissions.items(): + stat_chmod(file, original_permission) + + print("Done installing jailmaker dependencies.") def main(): if os.stat(__file__).st_uid != 0: @@ -791,6 +819,8 @@ def main(): subparsers.add_parser(name='list', epilog=DISCLAIMER) + subparsers.add_parser(name='install', epilog=DISCLAIMER, help="Install jailmaker dependencies") + if os.getuid() != 0: parser.print_usage() fail("Run this script as root...") @@ -816,6 +846,9 @@ def main(): elif args.subcommand == 'list': list_jails() + elif args.subcommand == 'install': + install_jailmaker_dependencies() + elif args.subcommand: parser.print_usage()