From 5317c3f83334a29f99cdb444dcb81a93f548858a Mon Sep 17 00:00:00 2001 From: Jip-Hop <2871973+Jip-Hop@users.noreply.github.com> Date: Mon, 14 Aug 2023 15:42:20 +0200 Subject: [PATCH] Create symlink during install --- README.md | 16 ++++++++------- jlmkr.py | 59 +++++++++++++++++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 3338e8f..f20fc53 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ 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 +### 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. @@ -40,38 +40,40 @@ Unfortunately since version 22.12.3 TrueNAS SCALE no longer includes systemd-nsp 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)). +Additionally the install command will create a symlink from `/usr/bin/jlmkr` to `jlmkr.py`. Thanks this this you can now run the `jlmkr` command from anywhere (instead of having to run `./jlmkr.py` from inside the directory where you've placed it). + ## Create Jail Creating a jail is interactive. You'll be presented with questions which guide you through the process. ```shell -./jlmkr.py create myjail +jlmkr create myjail ``` 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. 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`. +In order to start a jail automatically after TrueNAS boots, run `jlmkr 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 && jlmkr start myjail`. ## Additional Commands ### Start Jail ```shell -./jlmkr.py start myjail +jlmkr start myjail ``` ### List Jails ```shell -./jlmkr.py list +jlmkr list ``` ### Remove Jail ```shell -./jlmkr.py remove myjail +jlmkr remove myjail ``` For additional commands we can use `machinectl`, `systemctl` and `journalctl` directly. The `jlmkr.py` script does not play a role here. @@ -110,7 +112,7 @@ systemd-run --machine myjail --quiet --pipe --wait --collect --service-type=exec ## Edit Jail Config -Once you've created a jail, it will exist in a directory inside the `jails` dir next to `jlmkr.py`. For example `./jails/myjail` if you've named your jail `myjail`. You may edit the jail configuration file. You'll have to stop the jail and start it again with `jlmkr.py` for these changes to take effect. +Once you've created a jail, it will exist in a directory inside the `jails` dir next to `jlmkr.py`. For example `/mnt/mypool/jailmaker/jails/myjail` if you've named your jail `myjail`. You may edit the jail configuration file. You'll have to stop the jail and start it again with `jlmkr` for these changes to take effect. ## Networking diff --git a/jlmkr.py b/jlmkr.py index df6ca18..75062e4 100755 --- a/jlmkr.py +++ b/jlmkr.py @@ -35,7 +35,7 @@ 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, thanks to systemd-nspawn!" -VERSION = '0.0.6' +VERSION = '0.0.7' JAILS_DIR_PATH = 'jails' JAIL_CONFIG_NAME = 'config' @@ -770,33 +770,44 @@ def list_jails(): print("\nCurrently running:\n") subprocess.run(['machinectl', 'list']) -def install_jailmaker_dependencies(): +def install_jailmaker(): # Check if command exists in path if shutil.which('systemd-nspawn'): print("systemd-nspawn is already installed.") - return + else: + 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("Installing jailmaker dependencies...") + target = '/usr/bin/jlmkr' - original_permissions = {} + # Check if command exists in path + if shutil.which('jlmkr'): + print("The jlmkr command is available.") + elif not os.path.lexists(target): + print(f"Creating symlink {target} to {SCRIPT_PATH}.") + os.symlink(SCRIPT_PATH, target) + else: + print(f"File {target} already exists... Maybe it's a broken symlink from a previous install attempt?") + print(f"Skipped creating new symlink {target} to {SCRIPT_PATH}.") - 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.") + print("Done installing jailmaker.") def main(): if os.stat(SCRIPT_PATH).st_uid != 0: @@ -820,7 +831,7 @@ def main(): subparsers.add_parser(name='list', epilog=DISCLAIMER) - subparsers.add_parser(name='install', epilog=DISCLAIMER, help="Install jailmaker dependencies") + subparsers.add_parser(name='install', epilog=DISCLAIMER, help="Install jailmaker dependencies and create symlink") if os.getuid() != 0: parser.print_usage() @@ -848,7 +859,7 @@ def main(): list_jails() elif args.subcommand == 'install': - install_jailmaker_dependencies() + install_jailmaker() elif args.subcommand: parser.print_usage()