summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt1333
-rw-r--r--LICENSE.txt674
-rw-r--r--Makefile255
-rw-r--r--VERSION.txt1
-rwxr-xr-xbin/container117
-rwxr-xr-xbin/container-shell167
-rwxr-xr-xlibexec/container/auto167
-rwxr-xr-xlibexec/container/build287
-rwxr-xr-xlibexec/container/console119
-rwxr-xr-xlibexec/container/enter129
-rwxr-xr-xlibexec/container/get287
-rwxr-xr-xlibexec/container/info221
-rwxr-xr-xlibexec/container/key176
-rwxr-xr-xlibexec/container/limit212
-rwxr-xr-xlibexec/container/list461
-rwxr-xr-xlibexec/container/log167
-rwxr-xr-xlibexec/container/move215
-rwxr-xr-xlibexec/container/rebuild152
-rwxr-xr-xlibexec/container/remove261
-rwxr-xr-xlibexec/container/restart172
-rwxr-xr-xlibexec/container/run131
-rwxr-xr-xlibexec/container/start570
-rwxr-xr-xlibexec/container/status108
-rwxr-xr-xlibexec/container/stop360
-rwxr-xr-xlibexec/container/top122
-rwxr-xr-xlibexec/container/update270
-rwxr-xr-xlibexec/container/version49
-rw-r--r--share/bash-completion/container385
-rwxr-xr-xshare/build-scripts/debconf1318
-rwxr-xr-xshare/build-scripts/debconf.d/0001-preseed-file131
-rw-r--r--share/build-scripts/debconf.d/0001-preseed-file.templates18
-rwxr-xr-xshare/build-scripts/debconf.d/0002-preseed-debconf111
-rwxr-xr-xshare/build-scripts/debconf.d/0003-debconf1371
-rw-r--r--share/build-scripts/debconf.d/0003-debconf.templates276
-rwxr-xr-xshare/build-scripts/debootstrap198
-rw-r--r--share/config/container.conf.in30
-rw-r--r--share/doc/examples/bookworm.cfg35
-rwxr-xr-xshare/doc/examples/container-images.sh113
-rw-r--r--share/doc/examples/graograman-backports.cfg70
-rw-r--r--share/doc/host-setup.old.txt230
-rw-r--r--share/doc/host-setup.txt217
-rwxr-xr-xshare/get-scripts/curl483
-rwxr-xr-xshare/get-scripts/curl.d/0001-debconf54
-rw-r--r--share/get-scripts/curl.d/0001-debconf.templates11
-rwxr-xr-xshare/hooks/post-start.chown-nvidia.sh31
-rwxr-xr-xshare/hooks/pre-build.git-pull.sh53
-rwxr-xr-xshare/hooks/pre-get.git-pull.sh53
-rwxr-xr-xshare/hooks/pre-start.unlink-console.sh32
-rw-r--r--share/keys/daniel.baumann@open-infrastructure.net_0xB62C61A10B93195F.pub14
-rw-r--r--share/keys/daniel@debian.org_0x55CF1BF986ABB9C7.pub52
-rw-r--r--share/logrotate/container13
-rw-r--r--share/man/Makefile59
-rw-r--r--share/man/compute-tools.7.rst153
-rw-r--r--share/man/container-auto.1.rst92
-rw-r--r--share/man/container-build-debconf.1.rst173
-rw-r--r--share/man/container-build-debootstrap.1.rst111
-rw-r--r--share/man/container-build.1.rst139
-rw-r--r--share/man/container-console.1.rst86
-rw-r--r--share/man/container-enter.1.rst86
-rw-r--r--share/man/container-get-curl.1.rst148
-rw-r--r--share/man/container-get.1.rst130
-rw-r--r--share/man/container-info.1.rst100
-rw-r--r--share/man/container-key.1.rst113
-rw-r--r--share/man/container-limit.1.rst121
-rw-r--r--share/man/container-list.1.rst145
-rw-r--r--share/man/container-log.1.rst101
-rw-r--r--share/man/container-move.1.rst93
-rw-r--r--share/man/container-rebuild.1.rst93
-rw-r--r--share/man/container-remove.1.rst104
-rw-r--r--share/man/container-restart.1.rst96
-rw-r--r--share/man/container-run.1.rst88
-rw-r--r--share/man/container-shell.1.rst141
-rw-r--r--share/man/container-start.1.rst93
-rw-r--r--share/man/container-status.1.rst83
-rw-r--r--share/man/container-stop.1.rst108
-rw-r--r--share/man/container-top.1.rst81
-rw-r--r--share/man/container-update.1.rst114
-rw-r--r--share/man/container-version.1.rst79
-rw-r--r--share/man/container.1.rst171
-rw-r--r--share/man/man.in19
-rw-r--r--share/needrestart/container-tools.conf6
-rw-r--r--share/procps/zz-container.conf18
-rw-r--r--share/sudo/container-shell3
-rw-r--r--share/systemd/container-auto.service18
-rw-r--r--share/systemd/container@.service16
85 files changed, 15663 insertions, 0 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
new file mode 100644
index 0000000..8dd6e3d
--- /dev/null
+++ b/CHANGELOG.txt
@@ -0,0 +1,1333 @@
+2022-12-23 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20221023.
+
+ [ Daniel Baumann ]
+ * Tightening version matches for OS detection in container info command.
+ * Adding release support for Debian 12 (bookworm).
+ * Updating distribution defaults for bookworm in container build scripts.
+ * Updating references in manpages for bookworm.
+ * Updating examples for bookworm.
+ * Adding support for non-free-firmware archive-area in debconf build script.
+ * Updating arm64 description in debconf build script.
+
+2022-10-23 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20221023.
+
+ [ Daniel Baumann ]
+ * Removing curl pre-http2 option handling.
+ * Renaming internal bootstrap function to be more generic in debconf build-script.
+ * Adding initial image support in container debconf build-scripts.
+
+2022-10-15 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20221015.
+
+ [ Daniel Baumann ]
+ * Removing machine-id from cache to fix re-using it amongst all generated containers, thanks to Sakirnth Nagarasa <sakirnth@debian.org>.
+ * Correcting a few formating errors in changelog.
+
+2022-10-02 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20221002.
+
+ [ Daniel Baumann ]
+ * Adding force and interactive options to container restart command.
+ * Updating license with newer GPL-3 version containing https instead of http links.
+ * Replacing explicit container command with variable in container main wrapper.
+ * Correcting distclean target in makefile.
+ * Also passing explicit directory output-format to mmdebstrap in build scripts.
+ * Also passing root as sandbox user to mmdebstrap in build scripts.
+
+2022-07-21 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220721.
+
+ [ Daniel Baumann ]
+ * Returning all ip addresses in cnt info command.
+ * Correcting container info command to report IP addresses of stopped container.
+ * Handling multiple IP addresses in container info command the same way for stopped containers as for started ones.
+ * Adding lazy detection in container info command for Debian 12 (booworm).
+
+2022-07-04 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220704.
+
+ [ Daniel Baumann ]
+ * Adding release related targets in Makefile.
+ * Updating links about related articles in compute-tools manpage.
+ * Reverting adding LinkLocalAddressing=no to ipv6 interfaces as its only desirable on container bridges but breaks a few other things in normal containers.
+
+2022-06-05 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220605.
+
+ * Backward incompatible changes:
+ - The container stop command is now interactive by default,
+ use 'container stop --force' / 'cnt stop -f' instead.
+
+ [ Daniel Baumann ]
+ * Correcting container status bash-completion to complete on all containers rather than only stopped ones.
+ * Using variables in directory paths in container key command.
+ * Adding default interactive mode for container stop command.
+ * Renaming force option in container stop command to kill in order to properly separate the three different stop modi (interactive, force, kill).
+ * Tracking container state in run files in /var/lib/compute-tools.
+ * Automatically restoring previous state after reboot by using last-on/last-off config options, thanks to Sakirnth Nagarasa <sakirnth@gmail.com> for the use-case and idea.
+ * Setting default for cnt.auto to last-on in debconf build scripts.
+
+2022-06-04 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220604.
+
+ [ Daniel Baumann ]
+ * Adding --name option in container-info manpage.
+ * Adding missing dhcp option in select question of the debconf build script.
+ * Adding new 'stub' network interface method in debconf build-script, thanks to Sakirnth Nagarasa <sakirnth@gmail.com> for the use-case and idea.
+ * Adding LinkLocalAddressing=no to ipv6 interfaces.
+
+2022-05-22 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220522.
+
+ [ Daniel Baumann ]
+ * Fixing copy&paste mistake in systemd-network run-files handling.
+
+2022-05-09 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220509.
+
+ [ Daniel Baumann ]
+ * Correcting wrong preseed-file handling for new links directory in container build script.
+
+2022-05-08 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220508.
+
+ [ Daniel Baumann ]
+ * Correcting off-by-one error when warning about too long veth interface names in container start commend.
+ * Adding comments about debconf hierarchy in debconf build script.
+ * Using versioned sort when sorting debconf templates.
+ * Excluding /etc/compute-tools/debconf/links from being shown in preseed file selection dialog to declutter automatization symlinks from real templates.
+ * Explicitly prefering links subdirectory over other locations withint debconf hierarchy in debconf build scripts.
+
+2022-05-05 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220505.
+
+ [ Daniel Baumann ]
+ * Adding container rebuild command.
+ * Correcting wrong shortlink for container restart command (rs instead of rt).
+ * Updating copyright notices for 2022.
+ * Showing all IP address for stopped containers in container list command.
+ * Supporting both ifupdown and systemd-networkd for the time being, depending on the existence of /etc/network/interfaces.
+ * Readding old ifupdown documentation for the time being.
+
+2022-04-30 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220430.
+
+ [ Simon Spöhel ]
+ * Updating documentation for systemd-networkd.
+
+ [ Daniel Baumann ]
+ * Actually passing through SSH_CLIENT variable to enable powerline-prompt in container enter command.
+ * Listing all IP addresses in container list command.
+
+2022-04-28 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20220428.
+
+ [ Simon Spöhel ]
+ * Using systemd-networkd to manage veth interfaces on host.
+
+2021-12-31 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211231.
+
+ [ Daniel Baumann ]
+ * Adding interactive option to container update command to ease skipping containers.
+ * Making name argument mandatory in container update command.
+
+2021-11-17 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211117.
+
+ [ Daniel Baumann ]
+ * Adding complete debconf envars in container update command.
+ * Passing fix-missing to apt upgrade in container update command.
+
+2021-11-16 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211116.
+
+ [ Daniel Baumann ]
+ * Adding comment about using grep to de-colorize apt messages in container update command.
+ * Making container update command work entirely non-interactive.
+ * Updating notifications in container update command.
+ * Refactoring notification in container update command.
+ * Adding notificiations for autoremovals in container update command.
+
+2021-11-15 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211115.
+
+ [ Daniel Baumann ]
+ * Speeding up full-upgrades in container update command by removing redundant upgrade step.
+ * Preparing update notifications handling in container update command.
+ * Adding notification handling in container update command.
+
+2021-11-13 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211113.
+
+ [ Daniel Baumann ]
+ * Replacing individual needrestart overrides by globally blacklisting container-tools service units.
+
+2021-11-03 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211103.
+
+ [ Daniel Baumann ]
+ * Adding needrestart restart scripts.
+ * Enabling automatic needrestart blacklisting for containers.
+
+2021-11-02 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20211102.
+
+ [ Daniel Baumann ]
+ * Adding 'exit' in debconf build script, thanks to Katharina.
+ * Sorting preseed-file options in debconf build script.
+ * Renaming internal config variable to more suitable debconf in debconf build script.
+ * Also removing config file stub when exiting debconf build script.
+
+2021-08-04 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210804.
+
+ [ Daniel Baumann ]
+ * Updating container update options in bash-completion.
+ * Fixing full-upgrade option in container update command.
+ * Harmonizing usage messages over all container commands with manpage references.
+ * Harmonizing parameter and usage in container build command.
+
+2021-07-27 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210727.
+
+ [ Daniel Baumann ]
+ * Adding backward incompatible changes of the previous release to changelog.
+ * Correcting synopsis in container-run manpage.
+ * Adding container update command.
+ * Also adding notifications for container get command in container main program.
+ * Suffixing keys with keyid in container keyring samples for transparency and uniqueness of the keys.
+ * Adding manpage references in usage message in main container program.
+ * Hardening quoting in container main program.
+ * Supporting /etc/compute-tools/container.conf.d.
+ * Adding boliderplate variables in post-start.chown-nvidia.sh example hook for consistency.
+
+2021-07-26 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210726.
+
+ * Backward incompatible changes:
+ - The container create command has been renamed to 'build'.
+ - The container create script using curl is now a 'get' script
+ for the new container get command.
+
+ [ Daniel Baumann ]
+ * Harmonizing formating of default values in manpages.
+ * Harmonizing formating of URL in homepage section in manpages.
+ * Correcting spelling typos in documentation files.
+ * Adding reference to manpage in 'no such container command' error message.
+ * Adding check for writable gpg directory in container key command.
+ * Updating container-image example build script for current debian releases.
+ * Renaming container create command to container build.
+ * Making previous container curl create script a container get script.
+ * Adding container get command.
+ * Creating empty keyring directory in Makefile.
+ * Adding example public keys.
+ * Updating default keyserver for container key command.
+ * Updating example key in container key manpage examples.
+ * Adding sensible default lookups for container key bash-completion.
+ * Speeding up container list command by not gathering IP addresses for output format that don't need it.
+ * Speeding up container list command by optimizing IP address gathering.
+ * Support fetching remote keys from keyserver in container key command.
+ * Support fetching local keys from keyring library in container key command.
+ * Using sig instead of sign as gpg signature extension for container images.
+
+2021-07-25 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210725.
+
+ [ Daniel Baumann ]
+ * Updating build relevant stuff to move from asciidoc to rst for manpage generation.
+ * Migrationg manpages from asciidoc to rst.
+ * Updating ssh public-key references in container-shell manpage examples.
+ * Updating references to the current Debian release in manpages for Debian 11 (bullseye).
+ * Updating build-depends listed in compute-tools manpage.
+ * Prefixing generated manpages with boiler-plate header.
+ * Injecting compute-tools version into manpage headers.
+
+2021-07-24 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210724.
+
+ [ Daniel Baumann ]
+ * Removing note about ipv4 forwarding, this is not actually required (anymore).
+ * Correcting wording in host setup documentation.
+ * Adding @FILE@ replacement variables in preseed files.
+ * Also removing lock file when force-stopping a container.
+ * Exporting IP variables to be used in host commands.
+ * Using lower-case filename for host-setup documentation.
+ * Improving section titles in host-setup documentation.
+ * Harmonizing first line in comments of non-shebang files.
+ * Using fixme rather than todo in source files.
+ * Improving comments in debootstrap script.
+
+2021-06-30 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210630.
+
+ [ Daniel Baumann ]
+ * Reverting openvswitch, not really ready yet.
+
+2021-06-29 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210629.
+
+ * Backward incompatible changes:
+ - The networking integration on the container host depended on
+ ifupdown. Now, to support KVM as an additional backend
+ alongside systemd-nspawn in compute-tools, we're switching
+ in this version exclusively to openvswitch.
+ - Moving from ifupdown to openvswitch to manage the bridges
+ requires manual re-configuration of the networking stack on
+ the host, otherwise no container will continue to have network
+ access.
+ - Configuration examples for systemd-networkd (recommended) on the
+ host to use openvswitch are documented in HOST-SETUP.txt.
+
+ [ Simon Spöhel ]
+ * Using openvswitch instead of linux bridges.
+ * Updating documentation for openvswitch.
+
+2021-06-28 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210628.
+
+ [ Daniel Baumann ]
+ * Using dpkg selection to check package availability in debconf container create script, rather than to rely on dpkg internal files.
+ * Updating unit file for systemd 246 wrt/ StandardError and StandardOutput options.
+
+ [ Katharina Drexel ]
+ * Prefering mmdebstrap to debootstrap in debconf script.
+ * Integrating mmdebstrap in debconf script.
+
+ [ Daniel Baumann ]
+ * Setting TERM in systemd container service files to improve machinectl login.
+ * Removing undesirable --verbose option when calling mmdebstrap in debconf container create script.
+ * Allowing to specify cnt.start=force in container config to ease fencing with pacemaker/corosync.
+ * Using cnt run to determine IP addresses in container list.
+ * Adding initial container info command.
+ * Handling container run command aequivalent to container enter in bash-completion.
+ * Using container-specific user-variable when logging container commands before falling back to system environment.
+
+2021-04-11 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210411.
+
+ * Backward incompatible changes:
+ - all path have been shortened in preparation for additional
+ backends alongside systemd-nspawn: The only user visible is the
+ configuration directory:
+
+ new: /etc/open-infrastructure/container
+ old: /etc/compute-tools
+
+ [ Daniel Baumann ]
+ * Moving command files from /usr/lib to /usr/libexec.
+ * Moving config files from /etc/open-infrastructure to /etc/compute-tools.
+ * Using /usr/libexec/container instead of /usr/libexec/open-infrastructure/container.
+ * Using /usr/share/compute-tools instead of /usr/share/open-infrastructure/container.
+ * Using /var/log/compute-tools instead of /var/log/open-infrastructure.
+ * Using /var/cache/container instead of /var/cache/open-infrastructure/container.
+ * Making hook to git-pull debconf files work recursively.
+ * Harmonizing initial variables in curl and debconf container create scripts for consistency.
+ * Updating copyright in bash-completion, it got re-written from scratch years ago.
+ * Adding hook support to container log command for consistency.
+ * Cosmetically improving output of test target.
+ * Adding shellcheck in test target (but not failing yet on it).
+ * Removing superfluous whitespace in changelog.
+ * Removing dpkg hack for progress-linux in debconf container create script, not needed for buster and newer anymore.
+ * Removing base-files hack for progress-linux in debconf container create script, not needed for buster and newer anymore.
+ * Removing readline hack for progress-linux in debconf container create script, not needed for buster and newer anymore.
+ * Removing sysvinit hack for progress-linux in debconf container create script, not needed for buster and newer anymore.
+ * Removing stretch support from debconf container create script.
+ * Using https for security.debian.org in container create related items.
+ * Using https instead of http in all comments.
+ * Adding support for Debian bookworm in container debconf create script.
+ * Synchronising versioning number for progress-linux releases in debconf container create script.
+ * Updating preseed examples for debconf container scripts to bullseye.
+
+2021-01-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20210101.
+
+ [ Daniel Baumann ]
+ * Adding container run command to execute programs within containers.
+ * Cleaning up and harmonizing verbose output for container remove, restart, start, and stop commands.
+ * Expanding host-setup documentation about ipv4/ipv6 dual-stack bridge configuration.
+ * Switching redirector address for progress-linux.
+ * Updating copyright notices for 2021.
+
+2020-10-30 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20201030.
+
+ [ Daniel Baumann ]
+ * Correcting wrong usages of new and old container names in container move command, thanks to Katharina Drexel <katharina.drexel@bfh.ch> for discovering it.
+ * Adding missing colon in container create commands '--script' option.
+ * Adding support for Debian 11 (bullseye) to debootstrap container create script.
+ * Adding support for Debian 11 (bullseye) to debconf container create script.
+ * Adding support for Progress Linux 6 (fuchur) to debconf container create script.
+
+ [ Katharina Drexel ]
+ * Adding overlay options to container configuration file.
+ * Adding overlay options to container create command.
+ * Adding overlay options to container start command.
+ * Adding overlay options to debconf script.
+ * Adding awk optimizations in configuration file handling.
+
+ [ Daniel Baumann ]
+ * Adding one more awk optimizations in container stop command.
+
+2020-08-30 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20200830.
+
+ [ Daniel Baumann ]
+ * Correcting permissions of pre-start.unlink-console.sh hook.
+ * Adding post-start hook to set nvidia device ownership.
+ * Harmonizing hooks.
+ * Correcting call of post hooks in container start program to make them actually work, thanks to Simon Spoehel <simon@spoehel.ch>.
+ * Using more common sign extension for detached gpg signatures in container curl create script.
+ * Updating host setup documentation.
+ * Adding IPv6 note in host setup documentation.
+ * Readding container-images.sh.
+ * Adding run comment in version command.
+
+ [ Katharina Drexel ]
+ * Fixing 'cnt remove' error when executed in directory /usr/lib/open-infrastructure/container.
+
+ [ Daniel Baumann ]
+ * Fixing one more occurence of wrong tr usage in container move command.
+
+2020-01-21 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20200121.
+
+ [ Daniel Baumann ]
+ * Fixing FTBFS with newer asciidoc versions.
+ * Adding verbose option for container start command.
+ * Updating copyright notices for 2020.
+
+2019-11-04 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20191104.
+
+ [ Daniel Baumann ]
+ * Adding default hook to unlink console prior start when bindmounting /dev (e.g. in GPU computing cases).
+ * Tightening Address lookup in container list command for systemd-networkd to not display MACAdresses instead of IPs.
+
+2019-08-11 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20190811.
+
+ [ Daniel Baumann ]
+ * Correcting whitespace error in include handling that broke debconf container create script.
+ * Cosmetically fixing internal preseed file when using the progress-linux package.
+ * Simplifying trap handling in debconf container create script.
+ * Updating interfaces example configuration in host-setup documentation.
+ * Removing stray veth links when starting containers with force.
+ * Removing stray veth links when stopping containers with force.
+
+ [ Simon Spöhel ]
+ * Fixing a bug where directories were not created for --bind-ro.
+ * Fixing a bug where only the last item in lists passed via CLI was evaluated.
+ * Fixing the debconf script to use the bind-ro string when preseeding.
+
+2019-04-13 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20190413.
+
+ [ Daniel Baumann ]
+ * Removing explicit protocol for IP adresses in container list command.
+ * Including gnupg explicitly in debconf container create command, thanks to Nik Lutz <nik@netstyle.ch>.
+ * Correcting syntax error in container bash-completion.
+ * Correcting typo when disabling IPv6 RA in debconf container create script, thanks to Simon Spöhel <simon@spoehel.ch>.
+
+ [ Nik Lutz ]
+ * Unmount bind mounts in reverse order to allow nested bind mounts.
+
+ [ Daniel Baumann ]
+ * Using trap function to unmount bind mounts etc. on exit with or without error.
+
+2019-03-19 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20190319.
+
+ * Backward incompatible changes:
+ - with the initial support for IPv6 network configuration
+ the IPv4 netmask now needs to be specified in CIDR
+ notation, e.g. '255.255.255.0' becomes '24'.
+
+ [ Daniel Baumann ]
+ * Adding initial support for IPv6 in debconf container create script.
+ * Using C.UTF-8 in container enter command as fallback locale.
+
+2019-03-04 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20190304.
+
+ [ Daniel Baumann ]
+ * Readding key command.
+ * Readding limit command.
+ * Readding curl container create script.
+ * Correcting version strings in changelog.
+ * Correcting variable name in makefile.
+
+2019-03-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20190301.
+
+ [ Daniel Baumann ]
+ * Adding a end message in container create command.
+ * Removing staging repositories in debconf create script, not used anymore.
+ * Removing Force-LoopBreak option when calling apt in container debconf create script, not needed anymore.
+ * Using apt instead of apt-get in container debconf create script.
+ * Removing progress-linux apt sources.list handling in container debconf create script by using the progress-linux package instead.
+ * Allow to select/deselect main repository in container debconf create script.
+ * Removing armel and armhf support in container debconf create script.
+ * Adding comment to debian sources.list in container debconf create script.
+ * Removing some dead code in container create scripts.
+ * Adding same internal name strings in all scripts.
+ * Adding support for using mmdebstrap in container debootstrap create script.
+ * Removing key command until its completly tested.
+ * Removing limit command until its completly tested.
+ * Removing curl container create script until its completly tested.
+ * Updating list of container commands to be logged.
+ * Updating list of container shortcut commands.
+ * Removing a few fixmes that are not needed anymore.
+ * Moving asciicast to the website.
+ * Moving container-images.sh to website.
+
+2019-02-22 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20190222.
+
+ * Backward incompatible changes:
+ - replaced Progress Linux 4 and Progress Linux 4+ support in
+ container debconf create script in favour of Progress Linux 5
+ and Progress Linux 5+ support.
+
+ - renamed upstream from container-tools to compute-tools,
+ directory names have changed. The only user visible is the
+ configuration directory:
+
+ old: /etc/container-tools
+ new: /etc/open-infrastructure/container
+
+ - harmonized field names in container debconf create script:
+
+ old: container-tools cnt-debconf/[...]
+ new: compute-tools container/[...]
+
+ See updated example files in /usr/share/doc/compute-tools/examples.
+
+ [ Daniel Baumann ]
+ * Updating year in copyright notices to 2019.
+ * Updating debian preseed example from stretch to buster.
+ * Updating progress-linux preseed example from dschinn-backports to engywuck-backports.
+ * Adding comment about enabling user namespace in procps configuration.
+ * Adding support for Debian 10 (buster) in debconf container create script.
+ * Setting default debian distribution to buster in debconf container create script.
+ * Adding support for Debian testing/bullseye in debconf container create script.
+ * Replacing Progress Linux 4 with Progress Linux 5 in debconf container create script.
+ * Setting default debian distribution to buster in debootstrap container create script.
+ * Adding verbose output when using '-n ALL' options with container commands.
+ * Updating host-setup documentation for unpriviled containers.
+ * Adding convenience symlinks for container start and stop commands.
+ * Correcting (harmless) error in https mirror handling wrt/ installing apt-transport-https.
+ * Replacing archive signing key handling for progress-linux by install the progress-linux package.
+ * Using cdn redirector as default sources.list entry.
+ * Adding st convenience symlink for status command.
+ * Adding missing convenience symlinks in bash-completion.
+ * Adding container log command.
+ * Fixing inconsistent variable usage in makefile.
+ * Updating container-images.sh example for buster.
+ * Correcting left-over from old cnt-debconf/auto field in engywuck-backports preseed example.
+ * Removing manpage symlinks in uninstall target too.
+ * Renaming container-tools to compute-tools.
+ * Using get.open-infrastructure.net as default URL to get images from in container create script.ck
+ * Harmonizing debconf values for container debconf create script.
+ * Using hostname fallback if FQDN is not set.
+
+2018-08-25 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20180825.
+
+ [ Daniel Baumann ]
+ * Dropping untested arm64 specific settings in container start command.
+ * Also allowing symlinks for containers, requires systemd 233 or newer (see #805785).
+ * Adding reference to /var/cache/container-tools to container manpage.
+ * Adding support for multiple container and host commands in debconf container create script.
+ * Removing bind mounting of /var/cache/apt/archives during creation of the container, not really usefull anymore these days.
+
+2018-05-27 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20180527.
+
+ [ Daniel Baumann ]
+ * Calling commands without exec to make multiple commands in a row work properly.
+ * Updating documentation for multiple commands in a row.
+ * Calling shell in container enter command directly, replacing container-nsenter helper program.
+ * Correcting and simplifying nsenter call in container enter command.
+ * Clarify differences between container enter and console commands in manpages.
+ * Improving comment in procps configuration.
+ * Improving comment in systemd container-auto.service description.
+ * Updating author section in manpages.
+ * Adding missing command variable in some container commands.
+ * Setting dummy SSH_CLIENT variable during container enter to enable conditional shell prompts such as powerline.
+ * Correcting typo in verbose option handling of container remove command.
+ * Adding 'ALL' as pseudo container name for container start, stop, restart, and remove commands to act on all available container respectivly.
+ * Adding check in container create command to not create any container named 'ALL'.
+
+2018-05-03 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20180503.
+
+ [ Daniel Baumann ]
+ * Removing suite reference in examples of container-create-debconf manpage.
+ * Adding -v, --verbose option to container-create command to be used e.g. when mass-creating new containers in a row.
+ * Adding quotes for consistency in bash-completion.
+ * Updating bash-completion to also complete on preseed files in the first level of subdirectories of /etc/container-tools/debconf.
+ * Updating asciicast for asciinema version 2.0.
+
+2018-02-18 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20180218.
+
+ [ Daniel Baumann ]
+ * Updating year in copyright information for 2018.
+ * Adding container remove --allow-stop option to override abort of running containers and stop them prior removal.
+ * Making pre-create.git-pull.sh hook to be aware of multiple subdirectories below /etc/container-tools/debconf for multi-site container debconf files.
+ * Making container debconf create script aware of multiple subdirectories below /etc/container-tools/debconf when showing the list of preseed files to the user.
+ * Making container debconf create script aware of multiple subdirectories below /etc/container-tools/debconf for automatically selecting an existing and matching debconf file.
+ * Always sorting preseed files starting with a capital letter first in debconf container create script, independent of systems locale.
+ * Adding support for Debian testing/buster in debconf container create script.
+
+2018-01-18 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20180118.
+
+ [ Daniel Baumann ]
+ * Adding SPDX License Identifiers.
+ * Automatically take matching preseeding files from /etc/container-tools/debconf.
+ * Automatically take default preseeding file from /etc/container-tools/debconf if available.
+ * Adding note about vsyscall boot parameter in host-setup documentation.
+ * Running host commands as last thing in debconf container create script in order to make it possible to change config files dynamically.
+ * Adding message when creating bind mount directories in container start command.
+
+2017-11-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20171101.
+
+ [ Daniel Baumann ]
+ * Removing fallback TERM in container list, not needed anymore.
+ * Adding con shortcut for container console command.
+ * Adding sh shortcut for shell format in container list command.
+ * Adding ver shortcut for container version command in bash-completion.
+ * Adding container create pre-hook that can be used to automatically git pull /etc/container-tools/debconf.
+ * Avoiding to display .cfg extension for preseed files in container debconf create script.
+ * Supporting using IP address from DNS lookup of the container name in preseed files for container debconf create script.
+ * Supporting using IP address parts of the container name in preseed files for container debconf create script.
+
+2017-10-13 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20171013.
+
+ [ Daniel Baumann ]
+ * Using linux as fallback TERM in container list command.
+ * Using iproute instead of net-tools to setup interfaces.
+ * Using iproute instead of bridge-utils to setup bridges.
+ * Removing some dead code in network-veth-extra handling.
+ * Removing ifupdown in debconf container create script earlier by excluding it from debootstrap.
+ * Removing net-tools from container-tools manpage.
+
+2017-07-26 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170726.
+
+ [ Daniel Baumann ]
+ * Fixing issues from network0 -> network1 transition in debconf container create script.
+
+2017-07-22 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170722.
+
+ * Backward incompatible changes:
+ - new default URL to download images in curl create script (files.open-infrastructure.net)
+ - new default for bridge interface (bridge0 instead of br0)
+ - new default for container interface (eno1 instead of eth0)
+ - renaming --image option to --system in curl container create script
+ - renaming curl image cache directory from /var/cache/container-tools/images to /var/cache/container-tools/system
+ - Starting to count at 1 instead of 0 in preseed files:
+
+ old: container-tools cnt-debconf/archive0/...
+ new: container-tools cnt-debconf/archive1/...
+
+ old: container-tools cnt-debconf/network0/...
+ new: container-tools cnt-debconf/network1/...
+
+ [ Daniel Baumann ]
+ * Wrapping changelog to 80 characters per line.
+ * Adding myself to copyright notice in bash-completion.
+
+ [ Simon Spöhel ]
+ * Fixing spelling typo in 'bandwidth'.
+
+ [ Daniel Baumann ]
+ * Adding interface max length check in container start command.
+ * Adding message about enabled and disabled container commands in container-shell help.
+ * Updating output of container-shell help.
+ * Also creating lz compressed container-images in example script.
+ * Correcting typo in comment in curl container create script.
+ * Updating default url to download images from in curl container create script.
+ * Adding cnt-debconf/mode preseed field to allow embedding container create script within preseed file itself without relying on a specific default create script being set on the host system, thanks to David Kunz for the idea.
+ * Using default bridge0 instead of br0 as default bridge interface.
+ * Using default eno1 instead of eth0 as default container interface.
+ * Removing unreachable fallback for veth0, always the short-hostname is used anyway.
+ * Adding knot-resolver to dschinn-backports preseed example.
+ * Making sha512 checksum optional for image downloads in curl container create script.
+ * Adding error messages in curl container create script if required decompressors are not installed.
+ * Dynamically prefer lzip over xz over gz in curl container create script, depending on if required decompressors are already installed on the host system.
+ * Reshuffeling curl options handling in curl container create script.
+ * Adjusting messages output in curl container create script.
+ * Reshuffeling checksum handling in curl container create script.
+ * Adding support for setup tarballs in curl container create script for appliance style setup of prebuilt containers.
+ * Sorting password option handling in curl container create script.
+ * Adding gzip dependency check in curl container create script for completness sake.
+ * Renaming --image option to --system in curl container create script for consistency.
+ * Adding --setup option in curl container create script to manually specify a custom setup tarball.
+ * Updating container-create-curl manpage to match current curl container create script.
+ * Updating container-images.sh example script to match current curl container create script expectations.
+ * Updating default filename for download in curl container create script.
+ * Passing container name to setup environment in curl container create script.
+ * Moving image cache from /var/cache/container-tools/images to /var/cache/container-tools/system for consistency.
+ * Adding container key command.
+ * Adding GPG signature verification for curl container create script.
+ * Adding interactive container list in curl container create script.
+ * Adding automatic compression detection for downloads in in curl container create directory.
+ * Adding architecture option to curl container create script.
+ * Making example preseed files non-interactive.
+ * Starting to count at 1 instead of 0 to be consistent with new network interface names in network and archive preseeding arrays.
+
+2017-07-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170701.
+
+ [ Daniel Baumann ]
+ * Correcting boolean typo when checking for existence of new container
+ in container move command, thanks to Simon Spöhel
+ <simon.spoehel@open-infrastructure.net>.
+ * Avoid removing top-level directories when cleaning up bind mounts in
+ container remove and stop commands.
+ * Also removing /etc/localtime before reconfiguring tzdata to workaround
+ broken tzdata preseed handling (see several bug reports in the BTS),
+ thanks to Nik Lutz <nik@netstyle.ch>.
+
+2017-06-29 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170629.
+
+ * Backward incompatible changes:
+ - container auto configuration in the [start] section to entangle
+ shared storage/automatically start at boot time support:
+
+ old: cnt.auto=true
+
+ new: cnt.auto=true
+ cnt.container-server=${FQDN}
+
+ whereas ${FQDN} needs to be replaced with the actual hostname of the
+ container server.
+
+ [ Daniel Baumann ]
+ * Removing useless whitespace in debconf script.
+ * Correcting typo in systemd parts of the Makefile's uninstall target.
+
+ [ Nik Lutz ]
+ * Implementing postup/postdown for systemd-networkd by creating systemd
+ units in /etc/systemd/system.
+
+ [ Daniel Baumann ]
+ * Dropping obsolete LTS archive definitions, thanks to Nik Lutz
+ <nik@netstyle.ch>.
+ * Using allow-hotplug instead of allow in host-setup documentation.
+ * Removing net-tools from host-setup documentation, it is a direct
+ depends of container-tools for the time being.
+ * Renaming cnt.auto to cnt.container-server in order to split
+ functionality of 'binding container to a specific host system' from
+ 'starting container at system boot'.
+ * Executing auto commands only when cnt.auto=true and
+ cnt.container-server matches the current hostname.
+ * Adding CONTAINER_COMMANDS_ENABLE variable for container-shell to add
+ support for allowing certain container commands for a specific
+ container-shell invocation only.
+ * Adding CONTAINER_COMMANDS_DISABLE variable for container-shell to add
+ support for disallowing certain container commands for a specific
+ container-shell invocation only.
+ * Documenting usage of container-shell command restrictions in
+ container-shell manpage.
+ * Using more systemd-ish status symbols in container list command.
+ * Adding new container top command.
+ * Adding new container top command manpage.
+ * Updating bash-completion for container top command.
+ * Adjusting container list outout for container top command.
+ * Harmonizing edition of container configuration file in debconf script.
+ * Allow cnt.auto=force-true to enforce startup of a locked container at
+ system startup.
+
+2017-05-22 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170522.
+
+ [ Daniel Baumann ]
+ * Correcting bind-ro option handling to actually work.
+ * Reverting "Purging packages that got removed/replaced during container
+ creation.", not needed anymore.
+
+2017-05-10 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170510.
+
+ [ Daniel Baumann ]
+ * Purging packages when autoremoving them.
+ * Purging packages that got removed/replaced during container creation.
+ * Adding missing bind-ro handling in container create command, thanks to
+ Simon Spöhel <simon.spoehel@open-infrastructure.net>.
+ * Adding sysctl config for procps to increase inotify limits in order to
+ run more than a few containers on a system.
+ * Updating list of excluded directory names in container list command.
+
+2017-04-05 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170405.
+
+ [ Daniel Baumann ]
+ * Consistently using '--force-confnew' as dpkg option when upgrading or
+ installing packages.
+
+2017-04-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170401.
+
+ [ Daniel Baumann ]
+ * Shortening file removal handling in uninstall target in makefile.
+ * Cleanup stray preseed.cfg removal.
+ * Allowing @NAME@ variable in preseed files to allow for more flexibel
+ preseed templating.
+ * Allowing multiple container commands to be executed in a row.
+ * Adding support for bind-ro nspawn option for read-only bind mounts.
+
+2017-01-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20170101.
+
+ [ Daniel Baumann ]
+ * Updating year in copyright information for 2017.
+ * Adding -f, --force option in container auto command.
+ * Adding net-tools in container-tools manpage to the list of packages to
+ install.
+ * Adding net-tools to required packages in host-setup documentation.
+ * Adding bash-completion for container auto command.
+ * Adding bash-completion for container move command.
+ * Adding bash-completion for container version command.
+ * Using generic directory instead of local directory for debconf files
+ to bash-complete container create command.
+ * Reordering bash-completion to do completion the usual way (by
+ suggesting commands first, then options and finally their arguments,
+ rather than commands and arguments only).
+
+2016-12-20 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161220.
+
+ [ Daniel Baumann ]
+ * Fixing suffix in nwdiag output in container list command.
+ * Handling unreadable container directory properly in container list
+ command.
+
+2016-12-10 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161210.
+
+ * Backward incompatible changes:
+ - container list shows now only the first IPv4 address.
+ - container rename command has been renamed to move.
+ - container list full format has been renamed to cli.
+ - container list short format has been renamed to shell.
+
+ [ Daniel Baumann ]
+ * Adding container rename to mv symlink.
+ * Renaming container rename command to move for consistency.
+ * Tidying container move interactive question.
+ * Tidying container move comments.
+ * Adding container move manpage.
+ * Harmonizing markup of email addresses in manpages.
+ * Completing usage message in container list command.
+ * Renaming internal show function in container list command for
+ consistency.
+ * Adding trailing line in full format for container list command.
+ * Sorting format code in container list command.
+ * Renaming full format in container list command to cli for consistency.
+ * Renaming short format in container list command to shell for
+ consistency.
+ * Removing half-finished multi-address handling in container list
+ command.
+ * Adding CSV export format to container list command.
+ * Adding JSON export format to container list command.
+ * Adding nwdiag export format to container list command.
+ * Adding YAML export format to container list command.
+ * Adding XML export format to container list command.
+ * Enabling pre and post hooks in container program.
+ * Enabling pre and post hooks in container commands.
+ * Enabling pre and post hooks in container create scripts.
+
+2016-12-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161201.
+
+ [ Daniel Baumann ]
+ * Adding note about configuration files in container manpage.
+ * Logging some container actions in container program to
+ /var/log/container-tools/container.log.
+ * Adding logrotate handling for /var/log/container-tools/container.log.
+ * Adding irc notification (opt-in).
+ * Calling container programm in container-shell to trigger notifications
+ too.
+
+2016-11-25 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161125.
+
+ [ Daniel Baumann ]
+ * Renaming too generic internal getopt variables to avoid possible
+ collisions in the future.
+ * Minimizing included packages by default in debconf container create
+ script.
+
+2016-11-22 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161122.
+
+ * Backward incompatible changes:
+ - renaming curl cache directory from /var/cache/container-tools/curl
+ to /var/cache/container-tools/images.
+
+ [ Daniel Baumann ]
+ * Adding runtime detection for http2 option in curl create script.
+ * Using curl with --fail option to abort in case of server/url errors.
+ * Updating contact section in manpages.
+ * Harmonizing manpage markup.
+ * Adding --clean option to curl container create script to remove
+ downloaded tarball from cache after successful container creation.
+ * Changing cache directory in curl create script from
+ /var/cache/container-tools/curl to /var/cache/container-tools/images.
+ * Using https by default in container-images.sh example script.
+ * Adding sha512 verification to curl container create script.
+ * Removing libui-dialog-perl from includes in debconf container create
+ script.
+
+2016-11-12 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161112.
+
+ * Backward incompatible changes:
+ - removes support to create Debian 8 (jessie) container in debconf
+ container create script.
+
+ [ Daniel Baumann ]
+ * Removing support for Debian 9 (jessie) in debconf container create
+ script.
+ * Adding shortcuts for container commands to bash-completion as well.
+ * Ignoring symlinks as container commands in bash-completion.
+ * Adding container version to ver symlink.
+ * Updating development section in container-tools manpage.
+ * Avoid repeating ipv4 address of the previous container in container
+ list command.
+ * Using fallback to ifupdown addresses in container list command for
+ container not using networkd yet.
+ * Fail to find container in remove command only when both the rootfs and
+ the config are gone already.
+ * Correcting syntax in usage message of container create scripts.
+ * Adding initial curl container create script.
+
+2016-11-05 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161105.
+
+ * Backward incompatible changes:
+ - container use systemd-networkd instead of ifupdown.
+
+ [ Daniel Baumann ]
+ * Readding container rename command.
+ * Readding -f|--force option in container stop command.
+ * Readding container limit command.
+ * Readding container enter command.
+ * Removing empty line at the end of the changelog file.
+ * Replacing README.txt with a copy of container-tools.7 manpage.
+ * Installing README.txt into documentation directory.
+ * Installing all generic text files as documentation.
+ * Adding mandatory inclusion of /etc/network/interfaces.d files in
+ host-setup documentation, thanks to Richard Nelson
+ <unixabg@gmail.com>.
+ * Using systemd-networkd in container instead of ifupdown.
+ * Updating container list command to use systemd-networkd config instead
+ of ifupdown.
+ * Excluding symlinks in container-shell command list.
+ * Adding container list to ls symlink.
+ * Adding container remove to rm symlink.
+
+2016-11-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20161101.
+
+ [Daniel Baumann]
+ * Changing installation of systemd support packages to workaround
+ systemd-shim failures in debootstrap.
+ * Correcting installation location for documentation in makefile.
+ * Adding note about help for individual commands in container-shell
+ program.
+ * Using sudo in container-shell.
+ * Setting LC_ALL in container-shell.
+ * Switching from ftp.debian.org as default debian mirror to
+ deb.debian.org in debconf script.
+ * Removing obsolete configuration for broadcast in interfaces of debconf
+ container create script.
+ * Removing obsolete configuration for network in interfaces of debconf
+ container create script.
+ * Removing obsolete network configurations in host-setup documentation.
+ * Switching default distribution to stretch in container create scripts.
+ * Replacing support for Progress Linux 3 (cairon) with Progress Linux 4
+ (dschinn).
+ * Automatically adding restricted archive areas for progress-linux
+ extras repositories if non-free is enabled.
+ * Updating progress-linux archive-key filenames.
+ * Removing container enter command for LTS version.
+ * Removing container limit command for LTS version.
+ * Removing -f|--force option in container stop command for LTS version.
+ * Removing container rename command for LTS version.
+ * Correcting IP address in documentation of a network configuration
+ example.
+ * Updating known limitations in README file.
+ * Updating known limitations in container-tools manpage.
+ * Improving language of preseed question in debconf script.
+ * Updating asciicast for container-tools version 20161101.
+
+2016-08-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160801.
+
+ [ Daniel Baumann ]
+ * Adding commit messages to previous changelog.
+ * Trimming usage example to basic commands only in readme file.
+ * Trimming usage example to basic commands only in container-tools
+ manpage.
+ * Adding reference to container-status command in container manpage.
+ * Updating name in container-status manpage.
+ * Dropping lxc ignore in container list command.
+ * Adding hooks directory for pre and post execution of container
+ commands.
+
+ [ Simon Spöhel ]
+ * Changing container-status command to always show full output.
+
+ [ Daniel Baumann ]
+ * Adding host system based overlay mounts.
+ * Adding error message in container start command if container is
+ locked.
+ * Adding -f, --force option to container start command to remove stray
+ lock files.
+ * Adding container-nsenter program for container enter command.
+ * Calling container-nsenter program from container enter command.
+ * Sorting container configuration file.
+ * Adding support for user namespace.
+ * Adding -v, --verbose option to container remove command.
+
+2016-07-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160701.
+
+ [ Daniel Baumann ]
+ * Showing only local containers by default in container list command.
+ * Adding container enter command.
+ * Creating non-existing source directory for bind mounts automatically
+ in container start command.
+ * Harmonizing defintions of long and short options in getopt code of
+ container commands.
+ * Adding container rename command.
+ * Updating references to bug tracking system.
+ * Updating Git URL in installation instructions.
+
+ [ Andreas Kreuzer ]
+ * Fixing bash-completion.
+ * Correcting container list manpage.
+ * Adding bash-completion for container enter command.
+ * Updating bash-completion for container list command.
+ * Updating bash-completion for format parameter in container list
+ command.
+ * Updating bash-completion for container remove command.
+
+ [ Daniel Baumann ]
+ * Using tabs instead of spaces for indentation in container
+ bash-completion.
+ * Harmonizing head comments in container bash-completion.
+ * Looking up container create scripts dynamically in container
+ bash-completion.
+ * Correcting local commands extraction in container bash-completion.
+ * Correcting bind mount directory creation in container create command
+ to work with multiple directories at once.
+ * Correcting bind mount directory removal in container remove command to
+ work with multiple directories at once.
+ * Using global path definition in container create command for
+ consistency.
+ * Using global path definition in container version command for
+ consistency.
+ * Always writing cnt.auto= default values to configuration files in
+ debconf container create script.
+ * Adding asciicast introduction.
+ * Updating depends to install in readme file.
+ * Updating depends to install in container-tools manpage.
+ * Adding section about known limitations to readme file.
+ * Adding section about known limitations to container-tools manpage.
+ * Creating machines directory in container create scripts if it's not
+ already existing.
+
+ [ Philipp Plüss ]
+ * Correcting spelling typo in HOST-SETUP.txt.
+
+ [ Simon Spöhel ]
+ * Adding container-status command.
+
+ [ Daniel Baumann ]
+ * Adding bash-completion for container status command.
+
+2016-06-15 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160615.
+
+ [ Daniel Baumann ]
+ * Adding documentation key in systemd unit files.
+ * Correcting typo in readme.
+ * Updating download links in readme.
+ * Updating download links in container-tools manpage.
+ * Correcting typo in container-tools manpage.
+ * Updating vcs links in readme.
+ * Updating vcs links in container-tools manpage.
+ * Making makefile more generic.
+ * Completing cleanup of directories in makefile uninstall target.
+ * Silencing error message in container list command if machine directory
+ is not readable.
+ * Excluding container-tools and .container-tools in /var/lib/machines as
+ special directories to allow all container-tools resources to be
+ places on shared storage.
+
+ [ Andreas Kreuzer ]
+ * Correcting limit manpage namespace.
+
+ [ Daniel Baumann ]
+ * Correcting container list command to list container without IP
+ adresses.
+ * Correcting aligning in container list command.
+ * Showing local containers in container list command only.
+ * Including apt-transport-https in default package selection of
+ progress-linux container create script.
+ * Including systemd-sysv in default package selection of progress-linux
+ container create script to prevent pulling in systemd-shim and
+ cgmanager.
+ * Switching default entries for cdn.archive.progress-linux.org to HTTPS.
+ * Using UTF-8 symbols for container status.
+
+ [ Andreas Kreuzer ]
+ * Adding bash-completion.
+
+2016-06-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160601.
+
+ * Backward incompatible changes:
+ - for consistency reasons, instead of any file only files
+ with .cfg suffix are accepted as preseed files in
+ /etc/container-tools/debconf.
+
+ [ Daniel Baumann ]
+ * Replacing http links in manpages with https.
+ * Adding bind option to bind mount directories in debconf script.
+ * Adding bind field in debconf cairon-backports example preseed file.
+ * Mounting bind mounts for the duration of the debconf script.
+ * Removing empty source directory of bind mounts in container stop
+ command.
+ * Using safety measures of rm when removing containers because of
+ (potentially) active bind mounts.
+ * Correcting cleanup of temporary debconf files in debconf script.
+ * Guessing default container script from
+ /usr/share/container-tools/scripts/default symlink (if existing).
+ * Using .cfg suffix for preseed files of debconf script for consistency.
+ * Adding auto option to set automatic start in debconf script.
+ * Adding auto field in debconf cairon-backports example preseed file.
+
+2016-05-15 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160515.
+
+ * Backward incompatible changes:
+ - container network configuration in the [start] section for
+ multi-interface support:
+
+ old: network-veth=yes
+ network-bridge=br0
+
+ new: cnt.network-bridge=veth-foo:br0
+ network-veth-extra=veth-foo:eth0
+ cnt.network-bridge=veth-bar:br1
+ network-veth-extra=veth-bar:eth1
+
+ - default container network device switched from host0 to eth0.
+ - container start in background by default.
+ - container-autostart has been renamed to container-auto.
+ - container autostart configuration in the [start] section:
+
+ old: cnt.autostart=true|FQDN
+ new: cnt.auto=true|FQDN
+
+ [ Nik Lutz ]
+ * Fixing path argument of chmod for .container-command script in the
+ debconf script.
+ * Using systemd to cleanup network interfaces after the container has
+ been stopped.
+ * Using systemctl to start containers.
+ * Swaping parsing order of NETWORK_VETH_EXTRA and NETWORK_BRIDGES.
+ * Replacing systemd-nspawn '--network-bridge=' with one config file per
+ interface in /etc/network/interfaces.d.
+ * Using eth[0-9] instead of host[0-9] in containers
+ /etc/network/interface.
+ * Removing network interface configuration in /etc/network/interfaces.d
+ after container stop.
+ * Using systemd-nspawn '--network-veth-extra=' instead of
+ '--network-veth' (prerequisite for multiple network interface support
+ h per container).
+ * Adding veth name (cnt-debconf/network[0-9]/veth) configuration option
+ to debconf script.
+
+ [ Daniel Baumann ]
+ * Adjusting output of additional IP addresses in container list command.
+ * Correcting typo in debconf jessie example preseed file.
+ * Adding veth field in debconf cairon-backports example preseed file.
+ * Removing screen session handling in container-autostart program,
+ containers start in background by default now.
+ * Reworking container-autostart program into container auto command.
+
+2016-05-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160501.
+
+ [ Daniel Baumann ]
+ * Correcting spelling error in changelog file.
+ * Excluding snapshot directories for cephfs and netapp in container list
+ command.
+ * Adding short and full list format to container list command.
+ * Adding exit alias for logout in container-shell program.
+ * Correcting Debian stretch version number in container-tools manpage.
+ * Correcting Debian stretch version number in readme file.
+ * Adding links in development section of the container-tools manpage.
+ * Adding links in development section of the readme file.
+
+2016-04-15 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160415.
+
+ * Backward incompatible changes:
+ - container stop command option -k|--kill renamed to -f|--force for
+ consistency
+
+ [ Daniel Baumann ]
+ * Removing hardcoded container reference when opening manpages in
+ container-shell help.
+ * Using logout only to exit container-shell.
+ * Adding start note about logout to container-shell.
+ * Completing output of container-shell help command.
+ * Avoid aborting container-shell help command if no manpage is
+ available.
+ * Adding container-shell about command.
+ * Adding notes about container-shell specific commands in
+ container-shell manpage.
+ * Updating container-shell start message.
+ * Overwriting existing symlinks in makefiles install target.
+ * Adding extra empty line before each command output in container-shell.
+ * Updating apt comandline in installation instructions.
+ * Dropping unused syslog.target from container-autostart.service file.
+ * Excluding lost+found directory in container list command.
+ * Creating container program shortcut symlinks in makefile instead of
+ keeping them in the sources.
+ * Creating container script shortcut symlinks in makefile instead of
+ keeping them in the sources.
+ * Adding manpage symlinks for container script shortcut symlinks.
+ * Renaming container stop command option -k, --kill to -f, --force for
+ consistency.
+ * Switching from httpredir.debian.org as default debian mirror to
+ ftp.debian.org in debconf script.
+
+2016-04-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160401.
+
+ [ Daniel Baumann ]
+ * Creating configuration directory.
+ * Adding native ARM architecture support in container start command.
+ * Adding container-shell program.
+ * Adding container-autostart program.
+ * Adding container limit command.
+ * Adding capability and drop-capability config option.
+ * Adding blockio, cpu, memory and tasks limit config options.
+ * Adding debconf script.
+ * Updating year in copyright notices in container commands.
+ * Making removal message and answer handling of container remove command
+ more userfriendly.
+ * Adding documentation about host setup.
+ * Correcting spelling in readme.
+ * Adding notes about installation to readme file.
+ * Adding notes about development to readme file.
+ * Correcting spelling in container-tools manpage.
+ * Updating comments in programs.
+ * Updating comments in commands.
+ * Updating comments in examples.
+ * Updating comments in manpages.
+ * Updating comments in scripts.
+ * Updating comments in makefile.
+ * Updating debconf title in debconf script.
+ * Correcting spelling in container program manpages.
+ * Adding notes about installation to container-tools manpage.
+ * Adding notes about development to container-tools manpage.
+ * Updating wording about Debian and Debian based containers in
+ container-create-* manpages.
+ * Updating wording about Debian and Debian based containers in jessie
+ example file.
+ * Updating container-tools description in readme file.
+ * Updating container-tools description in manpages.
+
+2016-03-01 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+
+ * Releasing version 20160301.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d652f32
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,255 @@
+# Open Infrastructure: compute-tools
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+SHELL := sh -e
+
+PROJECT = open-infrastructure
+SOFTWARE = compute-tools
+PROGRAM = container
+
+SCRIPTS = bin/* libexec/*/*
+
+VERSION := $(shell cat VERSION.txt)
+
+all: build
+
+test:
+ @echo -n "Checking for syntax errors with sh... "
+ @for SCRIPT in $(SCRIPTS); \
+ do \
+ sh -n $${SCRIPT}; \
+ echo -n "."; \
+ done
+ @echo " done."
+
+ @echo -n "Checking for bashisms... "
+ @if [ -x /usr/bin/checkbashisms ]; \
+ then \
+ for SCRIPT in $(SCRIPTS); \
+ do \
+ checkbashisms -f -x $${SCRIPT}; \
+ echo -n "."; \
+ done; \
+ else \
+ echo "Note: devscripts not installed, skipping checkbashisms."; \
+ fi
+ @echo " done."
+
+ # FIXME: fail hard on shellcheck once all issues are fixed
+ @echo -n "Checking with shellcheck... "
+ @if [ -x /usr/bin/shellcheck ]; \
+ then \
+ for SCRIPT in $(SCRIPTS); \
+ do \
+ shellcheck $${SCRIPT} || true; \
+ echo -n "."; \
+ done; \
+ else \
+ echo "Note: shellcheck not installed, skipping shellcheck."; \
+ fi
+ @echo " done."
+
+build: share/man/*.rst
+ $(MAKE) -C share/man
+
+ sed -n '/^===/,$$p' share/man/$(SOFTWARE).7.rst > README.txt
+
+install: build
+ mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/config
+ mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/debconf
+ mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/hooks
+ mkdir -p $(DESTDIR)/etc/$(SOFTWARE)/keys
+ mkdir -p $(DESTDIR)/etc/${SOFTWARE}/container.conf.d
+
+ mkdir -p $(DESTDIR)/usr/bin
+ cp -r bin/* $(DESTDIR)/usr/bin
+
+ mkdir -p $(DESTDIR)/usr/libexec
+ cp -r libexec/* $(DESTDIR)/usr/libexec
+
+ mkdir -p $(DESTDIR)/usr/share/$(SOFTWARE)
+ cp -r VERSION.txt $(DESTDIR)/usr/share/$(SOFTWARE)
+ cp -r share/config share/hooks share/keys share/build-scripts share/get-scripts $(DESTDIR)/usr/share/$(SOFTWARE)
+
+ mkdir -p $(DESTDIR)/usr/share/bash-completion/completions
+ cp -r share/bash-completion/* $(DESTDIR)/usr/share/bash-completion/completions
+
+ mkdir -p $(DESTDIR)/etc/logrotate.d
+ cp -r share/logrotate/* $(DESTDIR)/etc/logrotate.d
+
+ mkdir -p $(DESTDIR)/etc/needrestart/conf.d
+ cp -r share/needrestart/* $(DESTDIR)/etc/needrestart/conf.d
+
+ mkdir -p $(DESTDIR)/etc/sysctl.d
+ cp -r share/procps/* $(DESTDIR)/etc/sysctl.d
+
+ mkdir -p $(DESTDIR)/etc/sudoers.d
+ cp -r share/sudo/* $(DESTDIR)/etc/sudoers.d
+ chmod 0440 $(DESTDIR)/etc/sudoers.d/*
+
+ mkdir -p $(DESTDIR)/usr/share/doc/$(SOFTWARE)
+ cp -r CHANGELOG.txt LICENSE.txt README.txt share/doc/* $(DESTDIR)/usr/share/doc/$(SOFTWARE)
+
+ for SECTION in $$(seq 1 8); \
+ do \
+ if ls share/man/*.$${SECTION} > /dev/null 2>&1; \
+ then \
+ mkdir -p $(DESTDIR)/usr/share/man/man$${SECTION}; \
+ cp share/man/*.$${SECTION} $(DESTDIR)/usr/share/man/man$${SECTION}; \
+ fi; \
+ done
+
+ ln -sf container $(DESTDIR)/usr/bin/cnt
+ ln -sf container.1 $(DESTDIR)/usr/share/man/man1/cnt.1
+ ln -sf container-shell $(DESTDIR)/usr/bin/cntsh
+ ln -sf container-shell.1 $(DESTDIR)/usr/share/man/man1/cntsh.1
+ ln -sf container $(DESTDIR)/usr/share/bash-completion/completions/cnt
+
+ ln -sf debconf $(DESTDIR)/usr/share/$(SOFTWARE)/build-scripts/debian
+ ln -sf debconf.d $(DESTDIR)/usr/share/$(SOFTWARE)/build-scripts/debian.d
+ ln -sf container-build-debconf.1 $(DESTDIR)/usr/share/man/man1/container-build-debian.1
+ ln -sf debconf $(DESTDIR)/usr/share/$(SOFTWARE)/build-scripts/progress-linux
+ ln -sf debconf.d $(DESTDIR)/usr/share/$(SOFTWARE)/build-scripts/progress-linux.d
+ ln -sf container-build-debconf.1 $(DESTDIR)/usr/share/man/man1/container-build-progress-linux.1
+ ln -sf debootstrap $(DESTDIR)/usr/share/$(SOFTWARE)/build-scripts/mmdebstrap
+ ln -sf container-build-debootstrap.1 $(DESTDIR)/usr/share/man/man1/container-build-mmdebstrap.1
+
+ ln -sf build $(DESTDIR)/usr/libexec/$(PROGRAM)/b
+ ln -sf get $(DESTDIR)/usr/libexec/$(PROGRAM)/g
+ ln -sf list $(DESTDIR)/usr/libexec/$(PROGRAM)/ls
+ ln -sf move $(DESTDIR)/usr/libexec/$(PROGRAM)/mv
+ ln -sf remove $(DESTDIR)/usr/libexec/$(PROGRAM)/rm
+ ln -sf rebuild $(DESTDIR)/usr/libexec/$(PROGRAM)/rb
+ ln -sf restart $(DESTDIR)/usr/libexec/$(PROGRAM)/rs
+ ln -sf start $(DESTDIR)/usr/libexec/$(PROGRAM)/s
+ ln -sf status $(DESTDIR)/usr/libexec/$(PROGRAM)/st
+ ln -sf stop $(DESTDIR)/usr/libexec/$(PROGRAM)/t
+ ln -sf update $(DESTDIR)/usr/libexec/$(PROGRAM)/u
+
+ mkdir -p $(DESTDIR)/lib/systemd/system
+ cp -r share/systemd/* $(DESTDIR)/lib/systemd/system
+
+ mkdir -p $(DESTDIR)/var/log/$(SOFTWARE)
+
+uninstall:
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/var/log/$(SOFTWARE) || true
+
+ for FILE in share/systemd/*; \
+ do \
+ rm -f $(DESTDIR)/lib/systemd/system/$$(basename $${FILE}); \
+ done
+
+ for SECTION in $$(seq 1 8); \
+ do \
+ for FILE in share/man/*.$${SECTION}; \
+ do \
+ rm -f $(DESTDIR)/usr/share/man/man$${SECTION}/$$(basename $${FILE}); \
+ done; \
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/share/man/man$${SECTION} || true; \
+ done
+
+ rm -f $(DESTDIR)/usr/bin/cnt
+ rm -f $(DESTDIR)/usr/share/man/man1/cnt.1
+ rm -f $(DESTDIR)/usr/bin/cntsh
+ rm -f $(DESTDIR)/usr/share/man/man1/cntsh.1
+ rm -f $(DESTDIR)/usr/share/bash-completion/completions/cnt
+ rm -f $(DESTDIR)/usr/share/man/man1/container-build-debian.1
+ rm -f $(DESTDIR)/usr/share/man/man1/container-build-progress-linux.1
+ rm -f $(DESTDIR)/usr/share/man/man1/container-build-mmdebstrap.1
+
+ for FILE in share/sudo/*; \
+ do \
+ rm -f $(DESTDIR)/etc/sudoers.d/$$(basename $${FILE}); \
+ done
+
+ for FILE in share/procps/*; \
+ do \
+ rm -f $(DESTDIR)/etc/sysctl.d/$$(basename $${FILE}); \
+ done
+
+ for FILE in share/needrestart/*; \
+ do \
+ rm -f $(DESTDIR)/etc/needrestart/conf.d/$$(basename $${FILE}); \
+ done
+
+ for FILE in share/logrotate/*; \
+ do \
+ rm -f $(DESTDIR)/etc/logrotate.d/$$(basename $${FILE}); \
+ done
+
+ for FILE in share/bash-completion/*; \
+ do \
+ rm -f $(DESTDIR)/usr/share/bash-completion/completions/$$(basename $${FILE}); \
+ done
+
+ rm -rf $(DESTDIR)/usr/share/doc/$(SOFTWARE)
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/share/doc || true
+
+ rm -rf $(DESTDIR)/usr/share/$(SOFTWARE)
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/share || true
+
+ rm -rf $(DESTDIR)/usr/libexec/$(PROGRAM)
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/libexec || true
+
+ for FILE in bin/*; \
+ do \
+ rm -f $(DESTDIR)/usr/bin/$$(basename $${FILE}); \
+ done
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/usr/bin || true
+
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/config || true
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/debconf || true
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/hooks || true
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/keys || true
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE)/container.conf.d || true
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc/$(SOFTWARE) || true
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR)/etc || true
+
+ rmdir --ignore-fail-on-non-empty --parents $(DESTDIR) || true
+
+clean:
+ $(MAKE) -C share/man clean
+
+ rm -f README.txt
+
+distclean: clean
+ rm -rf $(SOFTWARE)-$(VERSION)
+
+reinstall: uninstall install
+
+release: distclean
+ git commit -a -s -S -m 'Releasing version $(VERSION).' || true
+ git tag -s -m 'Tagging version $(VERSION).' v$(VERSION) || true
+
+ mkdir -p $(SOFTWARE)-$(VERSION)
+ find . -mindepth 1 -maxdepth 1 -and -not -name ".git*" -and -not -name debian -and -not -name $(SOFTWARE)-$(VERSION) -exec cp \-a {} $(SOFTWARE)-$(VERSION) \;
+
+ for FORMAT in xz lzip; \
+ do \
+ EXTENSION=$$(echo $${FORMAT} | cut -b-2); \
+ tar --$${FORMAT} -cf ../$(SOFTWARE)-$(VERSION).tar.$${EXTENSION} $(SOFTWARE)-$(VERSION); \
+ sha512sum ../$(SOFTWARE)-$(VERSION).tar.$${EXTENSION} > ../$(SOFTWARE)-$(VERSION).tar.$${EXTENSION}.sha512; \
+ gpg --default-key 0xB62C61A10B93195F --armor -b ../$(SOFTWARE)-$(VERSION).tar.$${EXTENSION}; \
+ mv ../$(SOFTWARE)-$(VERSION).tar.$${EXTENSION}.asc ../$(SOFTWARE)-$(VERSION).tar.$${EXTENSION}.sig; \
+ done
+
+ rm -rf $(SOFTWARE)-$(VERSION)
+
+upload:
+ scp ../$(SOFTWARE)-$(VERSION).* get.open-infrastructure.net:/srv/get.open-infrastructure.net/software/$(SOFTWARE)/upstream
diff --git a/VERSION.txt b/VERSION.txt
new file mode 100644
index 0000000..7a58b9c
--- /dev/null
+++ b/VERSION.txt
@@ -0,0 +1 @@
+20221223
diff --git a/bin/container b/bin/container
new file mode 100755
index 0000000..fb52687
--- /dev/null
+++ b/bin/container
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+
+# Parameter
+PARAMETER="${1}"
+
+if [ -z "${PARAMETER}" ]
+then
+ echo "Usage: ${PROGRAM} COMMAND [OPTIONS]" >&2
+ echo "Usage: ${PROGRAM} COMMAND1,COMMAND2,... [COMMON_OPTIONS]" >&2
+ echo
+ echo "See ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+fi
+
+# Command
+COMMANDS="${1}"
+
+# Options
+shift 1
+OPTIONS="${*}"
+
+for COMMAND in $(echo "${COMMANDS}" | sed -e 's|,| |g')
+do
+ if [ ! -e "/usr/libexec/${PROGRAM}/${COMMAND}" ]
+ then
+ echo "'${COMMAND}': no such ${PROGRAM} command, see ${PROGRAM}(1)." >&2
+ exit 1
+ fi
+
+ # Pre hooks
+ for FILE in "${HOOKS}/pre-${PROGRAM}".* "${HOOKS}/${NAME}.pre-${PROGRAM}"
+ do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+ done
+
+ # Notification
+ if echo "${OPTIONS}" | grep -qs "\--no-notification"
+ then
+ OPTIONS="$(echo "${OPTIONS}" | sed -e 's|--no-notification||')"
+ else
+ case "${COMMAND}" in
+ build|b|get|g|move|mv|remove|rm|rebuild|rb|restart|rs|start|s|stop|t|update|u)
+ if [ -z "${CONTAINER_USER}" ]
+ then
+ CONTAINER_USER="${SUDO_USER:-${USER}}"
+ fi
+
+ DATE="$(date +%Y-%m-%d\ %H:%M:%S)"
+ HOST="$(hostname -f 2> /dev/null || hostname)"
+
+ # logfile
+ echo "${DATE} ${HOST} ${CONTAINER_USER} ${PROGRAM} ${COMMAND} ${OPTIONS}" >> "/var/log/${SOFTWARE}/${PROGRAM}.log"
+
+ # irc
+ if [ -e /usr/bin/irk ]
+ then
+ for FILE in "/etc/${SOFTWARE}/${PROGRAM}.conf" "/etc/${SOFTWARE}/${PROGRAM}.conf.d"/*.conf
+ do
+ if [ -e "${FILE}" ]
+ then
+ . "${FILE}"
+ fi
+ done
+
+ if [ -n "${IRK_TARGETS}" ]
+ then
+ for TARGET in ${IRK_TARGETS}
+ do
+ irk "${TARGET}" "\x0300${CONTAINER_USER}\x03@\x0312${HOST}:\x03 \x0303${PROGRAM}\x03 \x0307${COMMAND}\x03 ${OPTIONS}"
+ done
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Run
+ "/usr/libexec/${PROGRAM}/${COMMAND}" "${OPTIONS}"
+
+ # Post hooks
+ for FILE in "${HOOKS}/post-${PROGRAM}".* "${HOOKS}/${NAME}.post-${PROGRAM}"
+ do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+ done
+done
diff --git a/bin/container-shell b/bin/container-shell
new file mode 100755
index 0000000..d63c3c0
--- /dev/null
+++ b/bin/container-shell
@@ -0,0 +1,167 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+COMMAND="$(basename ${0})"
+
+LC_ALL="C.UTF-8"
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM}-shell" >&2
+ exit 1
+}
+
+Shell ()
+{
+ COMMAND="${1}"
+
+ if [ -z "${COMMAND}" ]
+ then
+ return
+ fi
+
+ shift 1
+
+ OPTIONS="${@}"
+
+ case "${COMMAND}" in
+ about)
+ man ${PROGRAM} || true
+
+ return
+ ;;
+
+ logout|exit)
+ exit 0
+ ;;
+
+ help)
+ case "${OPTIONS}" in
+ "")
+ echo
+ echo "The following ${PROGRAM} commands are available:"
+ echo
+
+ cd "/usr/libexec/${PROGRAM}"
+ find . -type f -printf " %f\n" | sort
+ cd "${OLDPWD}"
+
+ if [ -n "${CONTAINER_COMMANDS_ENABLE}" ]
+ then
+ echo
+ echo "The following container commands are enabled for the current user:"
+ echo " ${CONTAINER_COMMANDS_ENABLE}"
+ fi
+
+ if [ -n "${CONTAINER_COMMANDS_DISABLE}" ]
+ then
+ echo
+ echo "The following container commands are disabled for the current user:"
+ echo " ${CONTAINER_COMMANDS_DISABLE}"
+ fi
+
+ echo
+ echo "Use 'help COMMAND' for more information."
+
+ return
+ ;;
+
+ *)
+ man ${PROGRAM}-${1} || true
+
+ return
+ ;;
+ esac
+ ;;
+ esac
+
+ if [ ! -e "/usr/libexec/${PROGRAM}/${COMMAND}" ]
+ then
+ echo "'${COMMAND}': no such ${PROGRAM} command" >&2
+ return
+ fi
+
+ if [ -n "${CONTAINER_COMMANDS_ENABLE}" ]
+ then
+ COMMAND_ALLOWED=""
+
+ for CONTAINER_COMMAND in ${CONTAINER_COMMANDS_ENABLE}
+ do
+ case "${CONTAINER_COMMAND}" in
+ ${COMMAND}|all|about|logout|exit|help)
+ COMMAND_ALLOWED="true"
+ ;;
+ esac
+ done
+
+ case "${COMMAND_ALLOWED}" in
+ true)
+ ;;
+
+ *)
+ echo "'${COMMAND}': command not allowed for current user" >&2
+ return
+ ;;
+ esac
+ fi
+
+ if [ -n "${CONTAINER_COMMANDS_DISABLE}" ]
+ then
+ COMMAND_DISALLOWED=""
+
+ for CONTAINER_COMMAND in ${CONTAINER_COMMANDS_DISABLE}
+ do
+ case "${CONTAINER_COMMAND}" in
+ ${COMMAND}|all|about|logout|exit|help)
+ COMMAND_DISALLOWED="true"
+ ;;
+ esac
+ done
+
+ case "${COMMAND_DISALLOWED}" in
+ true)
+ echo "'${COMMAND}': command not allowed for current user" >&2
+ return
+ ;;
+ esac
+ fi
+
+ echo
+ sudo ${PROGRAM} ${COMMAND} ${OPTIONS} || true
+}
+
+trap 'echo' EXIT HUP INT QUIT TERM
+
+echo "${SOFTWARE} $(${PROGRAM} version)"
+echo "Type \"about\" or \"help\" for more information, \"logout\" to exit."
+
+while true
+do
+ echo
+ echo -n "${PROGRAM}: "
+ read CMDLINE
+
+ Shell ${CMDLINE}
+done
diff --git a/libexec/container/auto b/libexec/container/auto
new file mode 100755
index 0000000..83c5c50
--- /dev/null
+++ b/libexec/container/auto
@@ -0,0 +1,167 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="force,start,stop,"
+ GETOPT_OPTIONS="f,s,t,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -f|--force)
+ FORCE="true"
+ shift 1
+ ;;
+
+ -s|--start)
+ ACTION="start"
+ shift 1
+ ;;
+
+ -t|--stop)
+ ACTION="stop"
+ shift 1
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -f|--force -s|--start -t|--stop" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${ACTION}" ]
+then
+ Usage
+fi
+
+HOST="$(hostname -f 2> /dev/null || hostname)"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+OPTIONS=""
+
+case "${FORCE}" in
+ true)
+ OPTIONS="${OPTIONS} -f"
+ ;;
+esac
+
+for FILE in "${CONFIG}"/*.conf
+do
+ if ! grep -Eqs "^ *cnt.container-server=${HOST}" "${FILE}"
+ then
+ continue
+ fi
+
+ CONTAINER="$(basename ${FILE} .conf)"
+ CNT_AUTO="$(grep -Es "^ *cnt.auto=" ${FILE} | awk -F= '{ print $2 }')"
+
+ case "${ACTION}" in
+ start)
+ case "${CNT_AUTO}" in
+ force-true)
+ OPTIONS="${OPTIONS} -f"
+
+ cnt ${ACTION} -n ${CONTAINER} ${OPTIONS} || true
+ ;;
+
+ last-on)
+ if grep -qs start "/var/lib/${SOFTWARE}/state/${CONTAINER}.run" || \
+ [ ! -e "/var/lib/${SOFTWARE}/state/${CONTAINER}.run" ]
+ then
+ cnt start -n ${CONTAINER} ${OPTIONS} -f || true
+ fi
+ ;;
+
+ last-off)
+ if grep -qs start "/var/lib/${SOFTWARE}/state/${CONTAINER}.run"
+ then
+ cnt start -n ${CONTAINER} ${OPTIONS} -f || true
+ fi
+ ;;
+
+ true)
+ cnt ${ACTION} -n ${CONTAINER} ${OPTIONS} || true
+ ;;
+ esac
+ ;;
+
+ stop)
+ OPTIONS="${OPTIONS} -f --stateless"
+
+ cnt ${ACTION} -n ${CONTAINER} ${OPTIONS} || true
+ ;;
+ esac
+done
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/build b/libexec/container/build
new file mode 100755
index 0000000..2c29730
--- /dev/null
+++ b/libexec/container/build
@@ -0,0 +1,287 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+SCRIPTS="/usr/share/${SOFTWARE}/build-scripts"
+CONFIG_TEMPLATE="/usr/share/${SOFTWARE}/config/container.conf.in"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,cnt.auto:,cnt.container-server:,cnt.overlay:,cnt.overlay-options:,cnt.start:,bind:,bind-ro:,capability:,drop-capability:,script:,verbose,"
+ GETOPT_OPTIONS="n:,b:,c:,d:,s:,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --cnt.auto)
+ CNT_AUTO="${2}"
+ shift 2
+ ;;
+
+ --cnt.container-server)
+ CNT_CONTAINER_SERVER="${2}"
+ shift 2
+ ;;
+
+ --cnt.overlay)
+ CNT_OVERLAY="${2}"
+ shift 2
+ ;;
+
+ --cnt.overlay-options)
+ CNT_OVERLAY_OPTIONS="${2}"
+ shift 2
+ ;;
+
+ --cnt.start)
+ CNT_START="${2}"
+ shift 2
+ ;;
+
+ -b|--bind)
+ BIND="${2}"
+ shift 2
+ ;;
+
+ --bind-ro)
+ BIND_RO="${2}"
+ shift 2
+ ;;
+
+ -c|--capability)
+ CAPABILITY="${2}"
+ shift 2
+ ;;
+
+ -d|--drop-capability)
+ DROP_CAPABILITY="${2}"
+ shift 2
+ ;;
+
+ -s|--script)
+ SCRIPT="${2}"
+ shift 2
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--cnt.auto=true|false|force-true|last-on|last-off] [--cnt.container-server=true|false|FQDN] [--cnt.overlay=DIRECTORY_LOWER:DIRECTORY_UPPER:DIRECTORY_WORK:DIRECTORY_MERGED] [--cnt.overlay-options=OPTION[,OPTION]] [--cnt.start=OPTION[,OPTION]] [-b|--bind DIRECTORY:DIRECTORY[:OPTIONS]] [--bind-ro DIRECTORY:DIRECTORY[:OPTIONS]] [-c|--capability CAPABILITY[,CAPABILITY]] [-d|--drop-capability DROP_CAPABILITY[,DROP_CAPABILITY]] [-s|--script SCRIPT] [-v|--verbose] [-- SCRIPT_OPTIONS]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+case "${NAME}" in
+ ALL)
+ echo "'${NAME}': name 'ALL' is reserved to expand to all available container" >&2
+ exit 1
+ ;;
+esac
+
+if [ -e "${CONFIG}/${NAME}.conf" ]
+then
+ echo "'${NAME}': container already exists or ${CONFIG}/${NAME}.conf has not been removed" >&2
+ exit 1
+fi
+
+if [ -z "${SCRIPT}" ]
+then
+ if [ -e "${SCRIPTS}/default" ]
+ then
+ TARGET="$(basename $(readlink ${SCRIPTS}/default))"
+
+ case "${TARGET}" in
+ container_build-script)
+ TARGET="$(basename $(readlink /etc/alternatives/container_build-script))"
+ ;;
+ esac
+
+ if [ -e "${SCRIPTS}/${TARGET}" ]
+ then
+ SCRIPT="${TARGET}"
+ else
+ echo "default -> '${TARGET}': no such script" >&2
+ exit 1
+ fi
+ else
+ SCRIPT="debian"
+ fi
+else
+ if [ ! -e "${SCRIPTS}/${SCRIPT}" ]
+ then
+ echo "'${SCRIPT}': no such script" >&2
+ exit 1
+ fi
+fi
+
+case "${VERBOSE}" in
+ true)
+
+cat << EOF
+################################################################################
+Building container: ${NAME}
+################################################################################
+EOF
+
+ ;;
+esac
+
+CNT_CONTAINER_SERVER="${CNT_CONTAINER_SERVER:-$(hostname -f 2> /dev/null || hostname)}"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Creating rw bind mounts
+if [ -n "${BIND}" ]
+then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for ENTRY in ${BINDS}
+ do
+ DIRECTORY="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+
+ mkdir -p "${DIRECTORY}"
+ done
+fi
+
+# Creating ro bind mounts
+if [ -n "${BIND_RO}" ]
+then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for ENTRY in ${BINDS_RO}
+ do
+ DIRECTORY="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+
+ mkdir -p "${DIRECTORY}"
+ done
+fi
+
+# Creating overlay mounts
+if [ -n "${CNT_OVERLAY}" ]
+then
+ CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')"
+
+ for ENTRY in ${CNT_OVERLAYS}
+ do
+ DIRECTORY_LOWER="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+ DIRECTORY_UPPER="$(echo ${ENTRY} | awk -F: '{ print $2 }')"
+ DIRECTORY_WORK="$(echo ${ENTRY} | awk -F: '{ print $3 }')"
+ DIRECTORY_MERGED="$(echo ${ENTRY} | awk -F: '{ print $4 }')"
+
+ for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ do
+ mkdir -p "${DIRECTORY}"
+ done
+ done
+fi
+
+# config
+mkdir -p "${CONFIG}"
+
+sed -e "s|@CNT_AUTO@|${CNT_AUTO}|g" \
+ -e "s|@CNT_CONTAINER_SERVER@|${CNT_CONTAINER_SERVER}|g" \
+ -e "s|@CNT_NETWORK_BRIDGE@|${CNT_NETWORK_BRIDGE}|g" \
+ -e "s|@CNT_OVERLAY@|${CNT_OVERLAY}|g" \
+ -e "s|@CNT_OVERLAY_OPTIONS@|${CNT_OVERLAY_OPTIONS}|g" \
+ -e "s|@CNT_START@|${CNT_START}|g" \
+ -e "s|@NAME@|${NAME}|g" \
+ -e "s|@BIND@|${BIND}|g" \
+ -e "s|@BIND_RO@|${BIND_RO}|g" \
+ -e "s|@BOOT@|yes|g" \
+ -e "s|@CAPABILITY@|${CAPABILITY}|g" \
+ -e "s|@DIRECTORY@|${MACHINES}/${NAME}|g" \
+ -e "s|@DROP_CAPABILITY@|${DROP_CAPABILITY}|g" \
+ -e "s|@LINK_JOURNAL@|no|g" \
+ -e "s|@MACHINE@|${NAME}|g" \
+ -e "s|@NETWORK_VETH_EXTRA@|${NETWORK_VETH_EXTRA}|g" \
+ -e "s|@PRIVATE_USERS@|no|g" \
+ -e "s|@REGISTER@|yes|g" \
+"${CONFIG_TEMPLATE}" > "${CONFIG}/${NAME}.conf"
+
+# Run
+"${SCRIPTS}/${SCRIPT}" $(echo "${@}" | sed -e 's| -- | |')
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# done
+echo "'${NAME}': container built."
diff --git a/libexec/container/console b/libexec/container/console
new file mode 100755
index 0000000..be2b897
--- /dev/null
+++ b/libexec/container/console
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,"
+ GETOPT_OPTIONS="n:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+case "${STATE}" in
+ running)
+ ;;
+
+ *)
+ echo "'${NAME}': container is not started" >&2
+ exit 1
+ ;;
+esac
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+machinectl login ${NAME}
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/enter b/libexec/container/enter
new file mode 100755
index 0000000..b366ba6
--- /dev/null
+++ b/libexec/container/enter
@@ -0,0 +1,129 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,"
+ GETOPT_OPTIONS="n:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+case "${STATE}" in
+ running)
+ ;;
+
+ *)
+ echo "'${NAME}': container is not running" >&2
+ exit 1
+ ;;
+esac
+
+LEADER="$(machinectl status ${NAME} | awk '/Leader: / { print $2 }')"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+SSH_CLIENT="${SSH_CLIENT:-127.0.0.1 0 0}"
+
+# Run
+nsenter --all --target "${LEADER}" --wd="${MACHINES}/${NAME}/root" /usr/bin/script -c "LC_ALL=C.UTF-8 SSH_CLIENT=\"${SSH_CLIENT}\" /bin/bash -l" -q /dev/null
+
+case "${SSH_CLIENT}" in
+ 127.0.0.1*)
+ unset SSH_CLIENT
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/get b/libexec/container/get
new file mode 100755
index 0000000..0d0f420
--- /dev/null
+++ b/libexec/container/get
@@ -0,0 +1,287 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+SCRIPTS="/usr/share/${SOFTWARE}/get-scripts"
+CONFIG_TEMPLATE="/usr/share/${SOFTWARE}/config/container.conf.in"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,cnt.container-server:,cnt.overlay:,cnt.overlay-options:,start:,bind:,bind-ro:,capability:,drop-capability:,script:,verbose,"
+ GETOPT_OPTIONS="n:,b:,c:,d:,s:,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --cnt.auto)
+ CNT_AUTO="${2}"
+ shift 2
+ ;;
+
+ --cnt.container-server)
+ CNT_CONTAINER_SERVER="${2}"
+ shift 2
+ ;;
+
+ --cnt.overlay)
+ CNT_OVERLAY="${2}"
+ shift 2
+ ;;
+
+ --cnt.overlay-options)
+ CNT_OVERLAY_OPTIONS="${2}"
+ shift 2
+ ;;
+
+ --cnt.start)
+ CNT_START="${2}"
+ shift 2
+ ;;
+
+ -b|--bind)
+ BIND="${2}"
+ shift 2
+ ;;
+
+ --bind-ro)
+ BIND_RO="${2}"
+ shift 2
+ ;;
+
+ -c|--capability)
+ CAPABILITY="${2}"
+ shift 2
+ ;;
+
+ -d|--drop-capability)
+ DROP_CAPABILITY="${2}"
+ shift 2
+ ;;
+
+ -s|--script)
+ SCRIPT="${2}"
+ shift 2
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--cnt.container-server=true|false|FQDN] [--cnt.overlay=DIRECTORY_LOWER:DIRECTORY_UPPER:DIRECTORY_WORK:DIRECTORY_MERGED] [--cnt.overlay-options=OPTION[,OPTION]] [--cnt.start=OPTION[,OPTION]] [-b|--bind DIRECTORY:DIRECTORY[:OPTIONS]] [--bind-ro DIRECTORY:DIRECTORY[:OPTIONS]] [-c|--capability CAPABILITY[,CAPABILITY]] [-d|--drop-capability DROP_CAPABILITY[,DROP_CAPABILITY]] [-s|--script SCRIPT] [-v|--verbose] [-- SCRIPT_OPTIONS]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+case "${NAME}" in
+ ALL)
+ echo "'${NAME}': name 'ALL' is reserved to expand to all available container" >&2
+ exit 1
+ ;;
+esac
+
+if [ -e "${CONFIG}/${NAME}.conf" ]
+then
+ echo "'${NAME}': container already exists or ${CONFIG}/${NAME}.conf has not been removed" >&2
+ exit 1
+fi
+
+if [ -z "${SCRIPT}" ]
+then
+ if [ -e "${SCRIPTS}/default" ]
+ then
+ TARGET="$(basename $(readlink ${SCRIPTS}/default))"
+
+ case "${TARGET}" in
+ container_get-script)
+ TARGET="$(basename $(readlink /etc/alternatives/container_get-script))"
+ ;;
+ esac
+
+ if [ -e "${SCRIPTS}/${TARGET}" ]
+ then
+ SCRIPT="${TARGET}"
+ else
+ echo "default -> '${TARGET}': no such script" >&2
+ exit 1
+ fi
+ else
+ SCRIPT="curl"
+ fi
+else
+ if [ ! -e "${SCRIPTS}/${SCRIPT}" ]
+ then
+ echo "'${SCRIPT}': no such script" >&2
+ exit 1
+ fi
+fi
+
+case "${VERBOSE}" in
+ true)
+
+cat << EOF
+################################################################################
+Building container: ${NAME}
+################################################################################
+EOF
+
+ ;;
+esac
+
+CNT_CONTAINER_SERVER="${CNT_CONTAINER_SERVER:-$(hostname -f 2> /dev/null || hostname)}"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Creating rw bind mounts
+if [ -n "${BIND}" ]
+then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for ENTRY in ${BINDS}
+ do
+ DIRECTORY="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+
+ mkdir -p "${DIRECTORY}"
+ done
+fi
+
+# Creating ro bind mounts
+if [ -n "${BIND_RO}" ]
+then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for ENTRY in ${BINDS_RO}
+ do
+ DIRECTORY="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+
+ mkdir -p "${DIRECTORY}"
+ done
+fi
+
+# Creating overlay mounts
+if [ -n "${CNT_OVERLAY}" ]
+then
+ CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')"
+
+ for ENTRY in ${CNT_OVERLAYS}
+ do
+ DIRECTORY_LOWER="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+ DIRECTORY_UPPER="$(echo ${ENTRY} | awk -F: '{ print $2 }')"
+ DIRECTORY_WORK="$(echo ${ENTRY} | awk -F: '{ print $3 }')"
+ DIRECTORY_MERGED="$(echo ${ENTRY} | awk -F: '{ print $4 }')"
+
+ for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ do
+ mkdir -p "${DIRECTORY}"
+ done
+ done
+fi
+
+# config
+mkdir -p "${CONFIG}"
+
+sed -e "s|@CNT_AUTO@|${CNT_AUTO}|g" \
+ -e "s|@CNT_CONTAINER_SERVER@|${CNT_CONTAINER_SERVER}|g" \
+ -e "s|@CNT_NETWORK_BRIDGE@|${CNT_NETWORK_BRIDGE}|g" \
+ -e "s|@CNT_OVERLAY@|${CNT_OVERLAY}|g" \
+ -e "s|@CNT_OVERLAY_OPTIONS@|${CNT_OVERLAY_OPTIONS}|g" \
+ -e "s|@CNT_START@|${CNT_START}|g" \
+ -e "s|@NAME@|${NAME}|g" \
+ -e "s|@BIND@|${BIND}|g" \
+ -e "s|@BIND_RO@|${BIND_RO}|g" \
+ -e "s|@BOOT@|yes|g" \
+ -e "s|@CAPABILITY@|${CAPABILITY}|g" \
+ -e "s|@DIRECTORY@|${MACHINES}/${NAME}|g" \
+ -e "s|@DROP_CAPABILITY@|${DROP_CAPABILITY}|g" \
+ -e "s|@LINK_JOURNAL@|no|g" \
+ -e "s|@MACHINE@|${NAME}|g" \
+ -e "s|@NETWORK_VETH_EXTRA@|${NETWORK_VETH_EXTRA}|g" \
+ -e "s|@PRIVATE_USERS@|no|g" \
+ -e "s|@REGISTER@|yes|g" \
+"${CONFIG_TEMPLATE}" > "${CONFIG}/${NAME}.conf"
+
+# Run
+"${SCRIPTS}/${SCRIPT}" $(echo "${@}" | sed -e 's| -- | |')
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# done
+echo "'${NAME}': container created."
diff --git a/libexec/container/info b/libexec/container/info
new file mode 100755
index 0000000..b713e7a
--- /dev/null
+++ b/libexec/container/info
@@ -0,0 +1,221 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+VERSION="$(${PROGRAM} version)"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,status,os,ip,"
+ GETOPT_OPTIONS="n:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --status)
+ ACTIONS="${ACTIONS} status"
+ shift 1
+ ;;
+
+ --os)
+ ACTIONS="${ACTIONS} os"
+ shift 1
+ ;;
+
+ --ip)
+ ACTIONS="${ACTIONS} ip"
+ shift 1
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--status] [--os] [--ip]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+ACTIONS="${ACTIONS:-status os ip}"
+HOST="$(cat /etc/hostname)"
+
+# Run
+
+# Status
+STATUS="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+if [ -e "${CONFIG}/${NAME}.conf" ]
+then
+ CONTAINER_SERVER="$(awk -Fcnt.container-server= '/^cnt.container-server=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+ CONTAINER_SERVER="${CONTAINER_SERVER:-false}"
+
+ case "${CONTAINER_SERVER}" in
+ ${HOST}|true)
+ ;;
+
+ *)
+ STATUS="other"
+ ;;
+ esac
+else
+ STATUS="other"
+fi
+
+case "${STATUS}" in
+ running)
+ STATUS="started"
+ ;;
+
+ other)
+ ;;
+
+ *)
+ STATUS="stopped"
+ ;;
+esac
+
+# OS
+VERSION_BASH="$(chroot ${MACHINES}/${NAME} apt-cache policy bash | awk '/Installed: / { print $2 }')"
+
+case "${VERSION_BASH}" in
+ 4.1-*|4.1.[0-9]*)
+ OS="Debian 6 (squeeze)"
+ ;;
+
+ 4.2-*|4.2.[0-9]*)
+ OS="Debian 7 (wheezy)"
+ ;;
+
+ 4.3-*|4.3.[0-9]*)
+ OS="Debian 8 (jessie)"
+ ;;
+
+ 4.4-*|4.4.[0-9]*)
+ OS="Debian 9 (stretch)"
+ ;;
+
+ 5.0-*|5.0.[0-9]*)
+ OS="Debian 10 (buster)"
+ ;;
+
+ 5.1-*|5.1.[0-9]*)
+ OS="Debian 11 (bullseye)"
+ ;;
+
+ 5.2-*|5.2.[0-9]*)
+ OS="Debian 12 (bookworm)"
+ ;;
+
+ *)
+ OS="n/a"
+ ;;
+esac
+
+case "${STATUS}" in
+ started)
+ IP="$(cnt run -n ${NAME} -- hostname -I)"
+ ;;
+
+ *)
+ if ls "${MACHINES}/${NAME}/etc/systemd/network"/*.network > /dev/null 2>&1
+ then
+ IP="$(awk -FAddress= '/^Address/ { printf "%s ", $2 }' ${MACHINES}/${NAME}/etc/systemd/network/*.network)"
+ elif [ -e "${MACHINES}/${NAME}/etc/network/interfaces" ]
+ then
+ IP="$(awk '/address/ { printf "%s ", $2 }' ${MACHINES}/${NAME}/etc/network/interfaces)"
+ fi
+
+ IP="${IP:-n/a}"
+ ;;
+esac
+
+for ACTION in ${ACTIONS}
+do
+ case "${ACTION}" in
+ status)
+ echo "${STATUS}"
+ ;;
+
+ os)
+ echo "${OS}"
+ ;;
+
+ ip)
+ echo "${IP}"
+ ;;
+ esac
+done
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/key b/libexec/container/key
new file mode 100755
index 0000000..efd214e
--- /dev/null
+++ b/libexec/container/key
@@ -0,0 +1,176 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+KEYS="/etc/${SOFTWARE}/keys"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="add:,list,remove:,"
+ GETOPT_OPTIONS="a:,l,r:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -a|--add)
+ ADD="${2}"
+ ACTION="add"
+ shift 2
+ ;;
+
+ -l|--list)
+ ACTION="list"
+ shift 1
+ ;;
+
+ -r|--remove)
+ REMOVE="${2}"
+ ACTION="remove"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} [-a|--add KEY_FILE|KEY_ID] [-l|--list] [-r|--remove KEY|KEY_ID]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${ACTION}" ]
+then
+ Usage
+fi
+
+if [ ! -w "${KEYS}" ]
+then
+ if [ "$(id -u)" -ne 0 ]
+ then
+ echo "'${COMMAND}': need root privileges (or write permissions to '${KEYS}')" >&2
+ exit 1
+ fi
+fi
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+if [ ! -e "${KEYS}" ]
+then
+ mkdir -p "${KEYS}"
+
+ chown root:root "${KEYS}"
+ chmod 0700 "${KEYS}"
+
+cat > "${KEYS}/gnupg.conf" << EOF
+keyserver hkps://keys.openpgp.org
+keyserver-options include-revoked
+keyserver-options no-honor-keyserver-url
+
+cert-digest-algo SHA512
+default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES ZLIB ZIP Uncompressed
+personal-cipher-preferences AES256 AES192 AES
+personal-compress-preferences ZLIB ZIP Uncompressed
+personal-digest-preferences SHA512 SHA384 SHA256 SHA224
+
+no-comments
+no-emit-version
+no-greeting
+keyid-format 0xlong
+list-options show-keyring
+list-options show-uid-validity
+verify-options show-uid-validity
+with-fingerprint
+
+charset utf-8
+EOF
+
+fi
+
+case "${ACTION}" in
+ add)
+ if [ -e "${ADD}" ]
+ then
+ gpg --homedir "${KEYS}" --import "${ADD}"
+ elif [ -e "/usr/share/${SOFTWARE}/keys/${ADD}" ]
+ then
+ gpg --homedir "${KEYS}" --import "/usr/share/${SOFTWARE}/keys/${ADD}"
+ elif [ -e "/usr/share/${SOFTWARE}/keys/${ADD}.pub" ]
+ then
+ gpg --homedir "${KEYS}" --import "/usr/share/${SOFTWARE}/keys/${ADD}.pub"
+ else
+ gpg --homedir "${KEYS}" --recv "${ADD}"
+ fi
+ ;;
+
+ list)
+ gpg --homedir "${KEYS}" --list-keys
+ ;;
+
+ remove)
+ gpg --homedir "${KEYS}" --delete-keys "${REMOVE}"
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/limit b/libexec/container/limit
new file mode 100755
index 0000000..b7f6e9b
--- /dev/null
+++ b/libexec/container/limit
@@ -0,0 +1,212 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,blockio-device-weight:,blockio-read-bandwidth:,blockio-weight:,blockio-write-bandwidth:,cpu-quota:,cpu-shares:,memory-limit:,tasks-max:,"
+ GETOPT_OPTIONS="n:b:c:m:t:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -c|--cpu-quota)
+ CPU_QUOTA="${2}"
+ shift 2
+ ;;
+
+ --cpu-shares)
+ CPU_SHARES="${2}"
+ shift 2
+ ;;
+
+ -m|--memory-limit)
+ MEMORY_LIMIT="${2}"
+ shift 2
+ ;;
+
+ -t|--tasks-max)
+ TASKS_MAX="${2}"
+ shift 2
+ ;;
+
+ --blockio-device-weight)
+ BLOCK_IO_DEVICE_WEIGHT="${2}"
+ shift 2
+ ;;
+
+ --blockio-read-bandwidth)
+ BLOCK_IO_READ_BANDWIDTH="${2}"
+ shift 2
+ ;;
+
+ -b|--blockio-weight)
+ BLOCK_IO_WEIGHT="${2}"
+ shift 2
+ ;;
+
+ --blockio-write-bandwidth)
+ BLOCK_IO_WRITE_BANDWIDTH="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--blockio-device-weight \"DEVICE WEIGHT\"] [--blockio-read-bandwidth \"DEVICE BYTES\"] [-b|--blockio-weight WEIGHT] [--blockio-write-bandwidth \"DEVICE BYTES\"] [-c|--cpu-quota QUOTA] [--cpu-shares SHARES] [-m|--memory-limit BYTES] [-t|--tasks-max NUMBER]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+case "${STATE}" in
+ running)
+ ;;
+
+ *)
+ echo "'${NAME}': container is not running" >&2
+ exit 1
+ ;;
+esac
+
+if [ -n "${BLOCK_IO_DEVICE_WEIGHT}" ]
+then
+ BLOCK_IO_DEVICE_WEIGHT="BlockIODeviceWeight=${BLOCK_IO_DEVICE_WEIGHT}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${BLOCK_IO_READ_BANDWIDTH}" ]
+then
+ BLOCK_IO_READ_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_READ_BANDWIDTH}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${BLOCK_IO_WEIGHT}" ]
+then
+ BLOCK_IO_WEIGHT="BlockIOWeight=${BLOCK_IO_WEIGHT}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${BLOCK_IO_WRITE_BANDWIDTH}" ]
+then
+ BLOCK_IO_WRITE_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_WRITE_BANDWIDTH}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${CPU_QUOTA}" ]
+then
+ CPU_QUOTA="CPUQuota=${CPU_QUOTA}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${CPU_SHARES}" ]
+then
+ CPU_SHARES="CPUShares=${CPU_SHARES}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${MEMORY_LIMIT}" ]
+then
+ MEMORY_LIMIT="MemoryLimit=${MEMORY_LIMIT}"
+ SET_PROPERTY="true"
+fi
+
+if [ -n "${TASKS_MAX}" ]
+then
+ TASKS_MAX="TasksMax=${TASKS_MAX}"
+ SET_PROPERTY="true"
+fi
+
+if [ "${SET_PROPERTY}" != "true" ]
+then
+ Usage
+fi
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWIDTH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWIDTH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX}
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/list b/libexec/container/list
new file mode 100755
index 0000000..a56c1f8
--- /dev/null
+++ b/libexec/container/list
@@ -0,0 +1,461 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+VERSION="$(${PROGRAM} version)"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="all,csv-separator:,format:,host:,nwdiag-color:,nwdiag-label:,other,started,stopped,"
+ GETOPT_OPTIONS="a,f:,h:,o,s,t,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -a|--all)
+ LIST="${LIST} all"
+ shift 1
+ ;;
+
+ --csv-separator)
+ CSV_SEPARATOR="${2}"
+ shift 2
+ ;;
+
+ -f|--format)
+ FORMAT="${2}"
+ shift 2
+ ;;
+
+ -h|--host)
+ HOST="${2}"
+ shift 2
+ ;;
+
+ --nwdiag-color)
+ NWDIAG_COLOR="${2}"
+ shift 2
+ ;;
+
+ --nwdiag-label)
+ NWDIAG_LABEL="${2}"
+ shift 2
+ ;;
+
+ -o|--other)
+ LIST="${LIST} other"
+ shift 1
+ ;;
+
+ -s|--started)
+ LIST="${LIST} started"
+ shift 1
+ ;;
+
+ -t|--stopped)
+ LIST="${LIST} stopped"
+ shift 1
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} [-a|--all] [--csv-separator SEPARATOR] [--format FORMAT] [-h|--host HOSTNAME] [--nwdiag-color COLOR] [--nwdiag-label LABEL] [-o|--other] [-s|--started] [-t|--stopped]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+LIST="${LIST:-started stopped}"
+FORMAT="${FORMAT:-cli}"
+HOST="${HOST:-$(hostname -f 2> /dev/null || hostname)}"
+
+CSV_SEPARATOR="${CSV_SEPARATOR:-,}"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+List ()
+{
+ case "${FORMAT}" in
+ cli)
+ printf "%1s %-74s %-19s\n" "${STATUS}" "${BLUE}${CONTAINER}${NORMAL}" "${YELLOW}${ADDRESS}${NORMAL}"
+ ;;
+
+ csv)
+ echo "${HOST}${CSV_SEPARATOR}${CONTAINER}${CSV_SEPARATOR}${STATE}${CSV_SEPARATOR}${ADDRESS}"
+ ;;
+
+ json)
+
+cat << EOF
+ {
+ "name": "${CONTAINER}",
+ "status": "${STATE}",
+ "address": "${ADDRESS}",
+ },
+EOF
+
+ ;;
+
+ nwdiag)
+ Nwdiag_width "${CONTAINER}"
+
+ case "${STATE}" in
+ started)
+ COLOR="#73d216"
+ ;;
+
+ stopped)
+ COLOR="#cc0000"
+ ;;
+
+ other)
+ COLOR="#d3d7cf"
+ ;;
+ esac
+
+ echo " ${CONTAINER} [address = \"${ADDRESS}\", color = \"${COLOR}\", shape = \"flowchart.terminator\", width = \"${WIDTH}\"];"
+ ;;
+
+ shell|sh)
+ echo "${CONTAINER}"
+ ;;
+
+ yaml)
+
+cat << EOF
+ - name: ${CONTAINER}
+ address: ${ADDRESS}
+EOF
+
+ ;;
+
+ xml)
+
+cat << EOF
+ <container>
+ <name>${CONTAINER}</name>
+ <address>${ADDRESS}</address>
+ </container>
+EOF
+
+ ;;
+ esac
+}
+
+Nwdiag_width ()
+{
+ NAME="${1}"
+
+ CHARACTERS="$(echo "${NAME}" | wc -c)"
+
+ if [ "${CHARACTERS}" -gt 13 ]
+ then
+ # default width is 128 fitting 13 characters
+ WIDTH="$(( ${CHARACTERS} - 13 ))"
+ WIDTH="$(( ${WIDTH} * 5 ))"
+ WIDTH="$(( ${WIDTH} + 128 ))"
+ else
+ WIDTH="128"
+ fi
+}
+
+case "${FORMAT}" in
+ cli)
+ RED="$(tput setaf 1)$(tput bold)"
+ GREEN="$(tput setaf 2)$(tput bold)"
+ YELLOW="$(tput setaf 3)$(tput bold)"
+ BLUE="$(tput setaf 4)$(tput bold)"
+ WHITE="$(tput setaf 7)$(tput bold)"
+ NORMAL="$(tput sgr0)"
+
+cat << EOF
+${WHITE} ${NORMAL} Container IP Address
+--------------------------------------------------------------------------------
+EOF
+
+ ;;
+
+ csv)
+
+cat << EOF
+# compute-tools ${VERSION}
+Host${CSV_SEPARATOR}Container${CSV_SEPARATOR}Status${CSV_SEPARATOR}IPv4-Address
+EOF
+
+ ;;
+
+ json)
+
+cat << EOF
+{
+ "compute-tools": {
+ "version": "${VERSION}",
+ },
+ "host": {
+ "name": "${HOST}",
+ },
+ "container": [
+EOF
+
+ ;;
+
+ nwdiag)
+ NETWORK="$(echo ${HOST} | sed -e 's|\.|_|g')"
+
+cat << EOF
+# compute-tools ${VERSION}
+nwdiag {
+ external_connector = none;
+ network ${NETWORK} {
+EOF
+
+ if [ -n "${NWDIAG_LABEL}" ]
+ then
+ echo " label = \"${NWDIAG_LABEL}\""
+ else
+ echo " label = \"\""
+ fi
+
+ NUMBER="$(${0} --format=short | wc -l)"
+
+ if [ -n "${NWDIAG_COLOR}" ]
+ then
+ COLOR="${NWDIAG_COLOR}"
+ else
+ COLOR="#3465a4"
+ fi
+
+ Nwdiag_width "${HOST}"
+
+cat << EOF
+ # host
+ ${HOST} [color = "${COLOR}", shape = "box", numbered = "${NUMBER}", width = "${WIDTH}"];
+ # container
+EOF
+
+ ;;
+
+ yaml)
+
+cat << EOF
+---
+compute_tools:
+ version: ${VERSION}
+
+host:
+ name: ${HOST}
+
+container:
+EOF
+
+ ;;
+
+ xml)
+
+cat << EOF
+<compute-tools>
+ <version>${VERSION}</version>
+</compute-tools>
+<host>
+ <name>${HOST}</name>
+</host>
+<containers>
+EOF
+
+ ;;
+esac
+
+if ls "${MACHINES}"/* > /dev/null 2>&1
+then
+ CONTAINERS="$(cd "${MACHINES}" 2>/dev/null && find -maxdepth 1 \( -type d -or -type l \) -and -not -name 'lost+found' -printf '%P\n' | sort)"
+fi
+
+for CONTAINER in ${CONTAINERS}
+do
+ STATE="$(machinectl show ${CONTAINER} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+ if [ -e "${CONFIG}/${CONTAINER}.conf" ]
+ then
+ CONTAINER_SERVER="$(awk -Fcnt.container-server= '/^cnt.container-server=/ { print $2 }' ${CONFIG}/${CONTAINER}.conf)"
+ CONTAINER_SERVER="${CONTAINER_SERVER:-false}"
+
+ case "${CONTAINER_SERVER}" in
+ ${HOST}|true)
+ ;;
+
+ *)
+ STATE="other"
+ ;;
+ esac
+ else
+ STATE="other"
+ fi
+
+ case "${STATE}" in
+ running)
+ STATE="started"
+ STATUS="${GREEN}●${NORMAL}"
+ ;;
+
+ other)
+ STATUS="${WHITE}○${NORMAL}"
+ ;;
+
+ *)
+ STATE="stopped"
+ STATUS="${RED}●${NORMAL}"
+ ;;
+ esac
+
+ ADDRESS=""
+
+ case "${STATE}" in
+ started)
+ case "${FORMAT}" in
+ shell|sh)
+ ;;
+
+ *)
+ LEADER="$(machinectl status ${CONTAINER} | awk '/Leader: / { print $2 }')"
+ ADDRESS="$(nsenter --all --target "${LEADER}" /bin/hostname -I)"
+ ;;
+ esac
+
+ ADDRESS="${ADDRESS:-none}"
+ ;;
+
+ *)
+ if ls "${MACHINES}/${CONTAINER}/etc/systemd/network"/*.network > /dev/null 2>&1
+ then
+ ADDRESS="$(for IP in $(awk -FAddress= '/^Address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/systemd/network/*.network); do echo -n "${IP} "; done)"
+ elif [ -e "${MACHINES}/${CONTAINER}/etc/network/interfaces" ]
+ then
+ ADDRESS="$(for IP in $(awk '/address/ { print $2 }' ${MACHINES}/${CONTAINER}/etc/network/interfaces); do echo -n "${IP} "; done)"
+ fi
+
+ ADDRESS="${ADDRESS:-n/a}"
+ ;;
+ esac
+
+ if echo ${LIST} | grep -qs all
+ then
+ List
+ fi
+
+ for ITEM in other started stopped
+ do
+ if echo ${LIST} | grep -qs ${ITEM}
+ then
+ case "${STATE}" in
+ ${ITEM})
+ List
+ ;;
+ esac
+ fi
+ done
+done
+
+case "${FORMAT}" in
+ cli)
+
+cat << EOF
+--------------------------------------------------------------------------------
+EOF
+
+ ;;
+
+ json)
+
+cat << EOF
+ ],
+}
+EOF
+
+ ;;
+
+ nwdiag)
+
+cat << EOF
+ }
+}
+EOF
+
+ ;;
+
+ xml)
+
+cat << EOF
+</containers>
+EOF
+
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/log b/libexec/container/log
new file mode 100755
index 0000000..b7a000d
--- /dev/null
+++ b/libexec/container/log
@@ -0,0 +1,167 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+LOG="/var/log/${SOFTWARE}/${PROGRAM}.log"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,date:,"
+ GETOPT_OPTIONS="n:,d:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -d|--date)
+ DATE="${2}"
+ shift 2
+ ;;
+
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -u|--user)
+ USER="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} [-n|--name NAME] [-d|--date DATE|today|today-N|yesterday] [-u|--user USER]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".*
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+case "${DATE}" in
+ today-*)
+ DAYS="$(echo ${DATE} | awk -F- '{ print $2 }')"
+
+ START="$(date -d "${DAYS} day ago" '+%Y-%m-%d')"
+ END="$(date +%Y-%m-%d)"
+
+ DATE="(${START}"
+
+ while true
+ do
+ DATE="${DATE}|${START}"
+
+ if [ "${START}" = "${END}" ]
+ then
+ break
+ fi
+
+ START="$(date +%Y-%m-%d --date "${START} +1 day")"
+ done
+
+ DATE="${DATE})"
+ ;;
+
+ today)
+ DATE="$(date +%Y-%m-%d)"
+ ;;
+
+ yesterday)
+ DATE="$(date -d '1 day ago' '+%Y-%m-%d')"
+ ;;
+esac
+
+if ls "${LOG}"-*.gz > /dev/null 2>&1
+then
+ LOGS="$(ls ${LOG}-*.gz) ${LOG}"
+else
+ LOGS="${LOG}"
+fi
+
+for LOG in ${LOGS}
+do
+ case "${LOG}" in
+ *.gz)
+ GREP="zgrep"
+ ;;
+
+ *)
+ GREP="grep"
+ ;;
+ esac
+
+ case "${NAME}" in
+ "")
+ ${GREP} -E "^${DATE}" "${LOG}" || true
+ ;;
+
+ *)
+ ${GREP} -E "^${DATE}" "${LOG}" | grep " ${NAME}" || true
+ ;;
+ esac
+done
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".*
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/move b/libexec/container/move
new file mode 100755
index 0000000..fdc19e6
--- /dev/null
+++ b/libexec/container/move
@@ -0,0 +1,215 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="force,new:,old:,"
+ GETOPT_OPTIONS="f,n:,o:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -f|--force)
+ FORCE="true"
+ shift 1
+ ;;
+
+ -n|--new)
+ NEW="${2}"
+ shift 2
+ ;;
+
+ -o|--old)
+ OLD="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} [-f|--force] -n|--new NAME -o|--old NAME" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${OLD}" ] || [ -z "${NEW}" ]
+then
+ Usage
+fi
+
+if [ ! -e "${MACHINES}/${OLD}" ]
+then
+ echo "'${OLD}': no such container" >&2
+ exit 1
+fi
+
+if [ -e "${MACHINES}/${NEW}" ]
+then
+ echo "'${NEW}': container already exists" >&2
+ exit 1
+fi
+
+STATE="$(machinectl show ${OLD} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+case "${STATE}" in
+ running)
+ echo "'${OLD}': container is started" >&2
+ exit 1
+ ;;
+esac
+
+case "${FORCE}" in
+ true)
+ ;;
+
+ *)
+ if ${PROGRAM} list --other | grep -qs "^${OLD}$"
+ then
+ echo -n "'${OLD}': rename container to '${NEW}' [y|N]? "
+ read FORCE
+
+ FORCE="$(echo ${FORCE} | tr '[A-Z]' '[a-z]')"
+
+ case "${FORCE}" in
+ y|yes)
+ ;;
+
+ *)
+ exit 1
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${OLD}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+mv "${CONFIG}/${OLD}.conf" "${CONFIG}/${NEW}.conf"
+mv "${MACHINES}/${OLD}" "${MACHINES}/${NEW}"
+
+# rw bind mounts
+BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NEW}.conf)"
+
+if [ -n "${BIND}" ]
+then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for BIND in ${BINDS}
+ do
+ SOURCE_OLD="$(echo ${BIND} | awk -F: '{ print $1 }')"
+ SOURCE_NEW="$(echo ${SOURCE_OLD} | sed -e "s|${OLD}|${NEW}|g")"
+
+ if [ "${SOURCE_OLD}" != "${SOURCE_NEW}" ]
+ then
+ mv "${SOURCE_OLD}" "${SOURCE_NEW}"
+ fi
+
+ TARGET_OLD="$(echo ${BIND} | awk -F: '{ print $2 }')"
+ TARGET_NEW="$(echo ${TARGET_OLD} | sed -e "s|${OLD}|${NEW}|g")"
+
+ if [ "${TARGET_OLD}" != "${TARGET_NEW}" ]
+ then
+ mv "${MACHINES}/${NEW}/${TARGET_OLD}" "${MACHINES}/${NEW}/${TARGET_NEW}"
+ fi
+ done
+fi
+
+# ro bind mounts
+BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NEW}.conf)"
+
+if [ -n "${BIND_RO}" ]
+then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for BIND_RO in ${BINDS_RO}
+ do
+ SOURCE_OLD="$(echo ${BIND_RO} | awk -F: '{ print $1 }')"
+ SOURCE_NEW="$(echo ${SOURCE_OLD} | sed -e "s|${OLD}|${NEW}|g")"
+
+ if [ "${SOURCE_OLD}" != "${SOURCE_NEW}" ]
+ then
+ mv "${SOURCE_OLD}" "${SOURCE_NEW}"
+ fi
+
+ TARGET_OLD="$(echo ${BIND_RO} | awk -F: '{ print $2 }')"
+ TARGET_NEW="$(echo ${TARGET_OLD} | sed -e "s|${OLD}|${NEW}|g")"
+
+ if [ "${TARGET_OLD}" != "${TARGET_NEW}" ]
+ then
+ mv "${MACHINES}/${NEW}/${TARGET_OLD}" "${MACHINES}/${NEW}/${TARGET_NEW}"
+ fi
+ done
+fi
+
+# config
+sed -i -e "s|${OLD}|${NEW}|g" "${CONFIG}/${NEW}.conf"
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NEW}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/rebuild b/libexec/container/rebuild
new file mode 100755
index 0000000..e526520
--- /dev/null
+++ b/libexec/container/rebuild
@@ -0,0 +1,152 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ OPTIONS_ALL=""
+
+ GETOPT_LONGOPTIONS="name:,force,verbose,"
+ GETOPT_OPTIONS="n:,f,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -f|--force)
+ FORCE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --force"
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --verbose"
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force] [-v|--verbose]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+case "${NAME}" in
+ ALL)
+ NAMES="$(${PROGRAM} list --format shell --started)"
+
+ for NAME in ${NAMES}
+ do
+ ${PROGRAM} rebuild,start --name ${NAME} ${OPTIONS_ALL} || true
+ done
+
+ exit 0
+ ;;
+esac
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+case "${VERBOSE}" in
+ true)
+ echo -n "Rebuilding container ${NAME}..."
+ ;;
+esac
+
+${PROGRAM} stop ${OPTIONS_ALL} --name ${NAME} || true
+sleep 0.5
+${PROGRAM} remove ${OPTIONS_ALL} --name ${NAME} || true
+sleep 0.5
+${PROGRAM} build --name ${NAME} || true
+
+case "${VERBOSE}" in
+ true)
+ echo " done."
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/remove b/libexec/container/remove
new file mode 100755
index 0000000..4cb5d48
--- /dev/null
+++ b/libexec/container/remove
@@ -0,0 +1,261 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ OPTIONS_ALL=""
+
+ GETOPT_LONGOPTIONS="name:,allow-stop,force,verbose,"
+ GETOPT_OPTIONS="n:,f,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --allow-stop)
+ ALLOW_STOP="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --allow-stop"
+ ;;
+
+ -f|--force)
+ FORCE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --force"
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --verbose"
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [--allow-stop] [-f|--force] [-v|--verbose]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Rmdir ()
+{
+ DIRECTORIES="${@}"
+
+ for DIRECTORY in ${DIRECTORIES}
+ do
+ PARENT_DIRECTORY="/$(echo ${DIRECTORY} | cut -d / -f 2)"
+
+ if [ "${PARENT_DIRECTORY}" != "${DIRECTORY}" ]
+ then
+ # the directory is at least two levels down from /
+ cd "${PARENT_DIRECTORY}"
+
+ CRUFT="$(echo ${DIRECTORY} | cut -d / -f 3-)"
+ rmdir --ignore-fail-on-non-empty --parents "${CRUFT}" > /dev/null 2>&1 || true
+
+ cd "${OLDPWD}"
+ fi
+ done
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+case "${NAME}" in
+ ALL)
+ NAMES="$(${PROGRAM} list --format shell --stopped)"
+
+ for NAME in ${NAMES}
+ do
+ ${PROGRAM} remove --name ${NAME} ${OPTIONS_ALL} || true
+ done
+
+ exit 0
+ ;;
+esac
+
+if [ ! -e "${MACHINES}/${NAME}" ] && [ ! -e "${CONFIG}/${NAME}.conf" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+case "${STATE}" in
+ running)
+ case "${ALLOW_STOP}" in
+ true)
+ echo "'${NAME}': container is started, stopping it now" >&2
+ ${PROGRAM} stop -n ${NAME} -f
+ ;;
+
+ *)
+ echo "'${NAME}': container is started" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+case "${FORCE}" in
+ true)
+ ;;
+
+ *)
+ echo -n "'${NAME}': remove container '${NAME}' [y|N]? "
+ read FORCE
+
+ FORCE="$(echo ${FORCE} | tr '[A-Z]' '[a-z]')"
+
+ case "${FORCE}" in
+ y|yes)
+ ;;
+
+ *)
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+case "${VERBOSE}" in
+ true)
+ RM_OPTIONS="--verbose"
+ ;;
+
+ *)
+ RM_OPTIONS=""
+ ;;
+esac
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# data
+if [ -e "${CONFIG}/${NAME}.conf" ]
+then
+ # Removing rw bind mounts
+ BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BIND}" ]
+ then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for BIND in ${BINDS}
+ do
+ DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')"
+
+ Rmdir "${DIRECTORY}"
+ done
+ fi
+
+ # Removing ro bind mounts
+ BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BIND_RO}" ]
+ then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for BIND_RO in ${BINDS_RO}
+ do
+ DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')"
+
+ Rmdir "${DIRECTORY}"
+ done
+ fi
+fi
+
+# Run
+case "${VERBOSE}" in
+ true)
+ echo -n "Removing container ${NAME}..."
+ ;;
+esac
+
+rm --preserve-root --one-file-system -rf ${RM_OPTIONS} "${MACHINES}/${NAME}"
+rm -f ${RM_OPTIONS} "${CONFIG}/${NAME}.conf"
+
+case "${VERBOSE}" in
+ true)
+ echo " done."
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/restart b/libexec/container/restart
new file mode 100755
index 0000000..0eb753c
--- /dev/null
+++ b/libexec/container/restart
@@ -0,0 +1,172 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ OPTIONS_ALL=""
+
+ GETOPT_LONGOPTIONS="name:,force,interactive,verbose,"
+ GETOPT_OPTIONS="n:,f,i,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -f|--force)
+ FORCE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --force"
+ ;;
+
+ -i|--interactive)
+ INTERACTIVE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --interactive"
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --verbose"
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force] [-i|--interactive] [-v|--verbose]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+case "${NAME}" in
+ ALL)
+ NAMES="$(${PROGRAM} list --format shell --started)"
+
+ for NAME in ${NAMES}
+ do
+ ${PROGRAM} restart --name ${NAME} ${OPTIONS_ALL} || true
+ done
+
+ exit 0
+ ;;
+esac
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+if [ "${FORCE}" != "true" ] || [ "${INTERACTIVE}" = "true" ]
+then
+ echo -n "'${NAME}': restart container '${NAME}' [y|N]? "
+ read STOP
+
+ STOP="$(echo ${STOP} | tr '[A-Z]' '[a-z]')"
+
+ case "${STOP}" in
+ y|yes)
+ ;;
+
+ *)
+ exit 1
+ ;;
+ esac
+fi
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+case "${VERBOSE}" in
+ true)
+ echo -n "Restarting container ${NAME}..."
+ ;;
+esac
+
+machinectl reboot ${NAME}
+
+case "${VERBOSE}" in
+ true)
+ echo " done."
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/run b/libexec/container/run
new file mode 100755
index 0000000..4daeaa2
--- /dev/null
+++ b/libexec/container/run
@@ -0,0 +1,131 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2019 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,"
+ GETOPT_OPTIONS="n:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME -- COMMAND" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+STATE="$(machinectl show ${NAME} 2>&1 | awk -F= '/^State=/ { print $2 }')"
+
+case "${STATE}" in
+ running)
+ ;;
+
+ *)
+ echo "'${NAME}': container is not running" >&2
+ exit 1
+ ;;
+esac
+
+LEADER="$(machinectl status ${NAME} | awk '/Leader: / { print $2 }')"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+SSH_CLIENT="${SSH_CLIENT:-127.0.0.1 0 0}"
+
+RUN="$(echo ${@} | awk -F-- '{ print $2}')"
+
+# Run
+nsenter --all --target "${LEADER}" --wd="${MACHINES}/${NAME}/root" /usr/bin/script -c "LC_ALL=C.UTF-8 /bin/bash -l -c \"${RUN}\"" -q /dev/null
+
+case "${SSH_CLIENT}" in
+ 127.0.0.1*)
+ unset SSH_CLIENT
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/start b/libexec/container/start
new file mode 100755
index 0000000..1f22325
--- /dev/null
+++ b/libexec/container/start
@@ -0,0 +1,570 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+START="false"
+SYSTEMCTL="true"
+
+Parameters ()
+{
+ OPTIONS_ALL=""
+
+ GETOPT_LONGOPTIONS="name:,force,nspawn,start,verbose,"
+ GETOPT_OPTIONS="n:,f,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -f|--force)
+ FORCE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --force"
+ ;;
+
+ --nspawn)
+ # internal option
+ SYSTEMCTL="false"
+ shift 1
+ ;;
+
+ --start)
+ # internal option
+ START="true"
+ SYSTEMCTL="false"
+ shift 1
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --verbose"
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+# hooks
+export NAME
+
+case "${NAME}" in
+ ALL)
+ NAMES="$(${PROGRAM} list --format shell --stopped)"
+
+ for NAME in ${NAMES}
+ do
+ ${PROGRAM} start --name ${NAME} ${OPTIONS_ALL} || true
+ done
+
+ exit 0
+ ;;
+esac
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+# options
+if grep -Eqs "^ *cnt.start=" "${CONFIG}/${NAME}.conf" | grep -qs force
+then
+ FORCE="true"
+fi
+
+case "${START}" in
+ false)
+ STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+ case "${STATE}" in
+ running)
+ echo "'${NAME}': container is already started" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+if [ -e "${MACHINES}/.#${NAME}.lck" ]
+then
+ case "${FORCE}" in
+ true)
+ rm -f "${MACHINES}/.#${NAME}.lck"
+
+ VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf | awk -F: '{ print $1 }')"
+
+ for VETH in ${VETHS}
+ do
+ ip link delete ${VETH} > /dev/null 2>&1 || true
+ done
+ ;;
+
+ *)
+ echo "'${NAME}': container is locked" >&2
+ exit 1
+ ;;
+ esac
+fi
+
+HOST_ARCHITECTURE="$(dpkg --print-architecture)"
+MACHINE_ARCHITECTURE="$(chroot ${MACHINES}/${NAME} dpkg --print-architecture)"
+
+case "${HOST_ARCHITECTURE}" in
+ amd64)
+ case "${MACHINE_ARCHITECTURE}" in
+ i386)
+ SETARCH="setarch i686"
+ ;;
+
+ *)
+ SETARCH=""
+ ;;
+ esac
+ ;;
+esac
+
+if systemctl status systemd-networkd > /dev/null 2>&1
+then
+ NETWORK_SUBSYSTEM="systemd-networkd"
+else
+ NETWORK_SUBSYSTEM="ifupdown"
+fi
+
+case "${START}" in
+ start)
+ ;;
+
+ *)
+ # Pre hooks
+ for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+ do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+ done
+ ;;
+esac
+
+# config
+if [ -e "${CONFIG}/${NAME}.conf" ]
+then
+ CNT_OVERLAY="$(awk -Fcnt.overlay= '/^cnt.overlay=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+ CNT_OVERLAY_OPTIONS="$(awk -Fcnt.overlay-options= '/^cnt.overlay-options=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${CNT_OVERLAY}" ]
+ then
+ CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')"
+
+ COUNT="0"
+ for CNT_OVERLAY in ${CNT_OVERLAYS}
+ do
+ DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')"
+ DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')"
+ DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')"
+ DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')"
+
+ COUNT="$((${COUNT} + 1))"
+ CNT_OVERLAY_OPTION="$(echo ${CNT_OVERLAY_OPTIONS} | awk -F ';' "{ print \$${COUNT} }")"
+
+ for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ do
+ mkdir -p "${DIRECTORY}"
+ done
+
+ if ! findmnt -n -o SOURCE "${DIRECTORY_MERGED}" | grep -qs '^cnt.overlay-'
+ then
+ if [ -n "${CNT_OVERLAY_OPTION}" ]
+ then
+ CNT_OVERLAY_OPTION="-o ${CNT_OVERLAY_OPTION}"
+ fi
+
+ mount cnt.overlay-${NAME} -t overlay ${CNT_OVERLAY_OPTION} -olowerdir="${DIRECTORY_LOWER}",upperdir="${DIRECTORY_UPPER}",workdir="${DIRECTORY_WORK}",default_permissions "${DIRECTORY_MERGED}"
+ fi
+ done
+ fi
+
+ BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BIND}" ]
+ then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for BIND in ${BINDS}
+ do
+ DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')"
+
+ if [ ! -e "${DIRECTORY}" ]
+ then
+ echo "'${DIRECTORY}': creating non-existing directory for bind mounting"
+ mkdir -p "${DIRECTORY}"
+ fi
+ done
+
+ BIND=""
+
+ for DIRECTORIES in ${BINDS}
+ do
+ BIND="${BIND} --bind ${DIRECTORIES}"
+ done
+ fi
+
+ BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BIND_RO}" ]
+ then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for BIND_RO in ${BINDS_RO}
+ do
+ DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')"
+
+ if [ ! -e "${DIRECTORY}" ]
+ then
+ echo "'${DIRECTORY}': creating non-existing directory for bind-ro mounting"
+ mkdir -p "${DIRECTORY}"
+ fi
+ done
+
+ BIND_RO=""
+
+ for DIRECTORIES in ${BINDS_RO}
+ do
+ BIND_RO="${BIND_RO} --bind-ro ${DIRECTORIES}"
+ done
+ fi
+
+ BOOT="$(awk -Fboot= '/^boot=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)"
+
+ case "${BOOT}" in
+ yes)
+ BOOT="--boot"
+ ;;
+
+ *)
+ BOOT=""
+ ;;
+ esac
+
+ CAPABILITY="$(awk -Fcapability= '/^capability=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ case "${CAPABILITY}" in
+ "")
+ CAPABILITY=""
+ ;;
+
+ *)
+ CAPABILITY="--capability=${CAPABILITY}"
+ ;;
+ esac
+
+ DIRECTORY="$(awk -Fdirectory= '/^directory=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo ${MACHINES}/${NAMES})"
+ DIRECTORY="--directory ${DIRECTORY}"
+
+ DROP_CAPABILITY="$(awk -Fdrop-capability= '/^drop-capability=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ case "${DROP_CAPABILITY}" in
+ "")
+ DROP_CAPABILITY=""
+ ;;
+
+ *)
+ DROP_CAPABILITY="--drop-capability=${DROP_CAPABILITY}"
+ ;;
+ esac
+
+ LINK_JOURNAL="$(awk -Flink-journal= '/^link-journal=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo no)"
+
+ case "${LINK_JOURNAL}" in
+ yes)
+ LINK_JOURNAL="--link-journal=yes"
+ ;;
+
+ *)
+ LINK_JOURNAL="--link-journal=no"
+ ;;
+ esac
+
+ MACHINE="--machine=${NAME}"
+
+ NETWORK_VETH_EXTRA=""
+
+ VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ case "${VETHS}" in
+ "")
+ ;;
+
+ *)
+ for VETH in ${VETHS}
+ do
+ NETWORK_VETH_EXTRA="${NETWORK_VETH_EXTRA} --network-veth-extra=${VETH}"
+ INTERFACE="$(echo ${VETH} | awk -F: '{ print $1 }')"
+
+ if [ "$(echo ${INTERFACE} | wc -c)" -gt 16 ]
+ then
+ echo "'${INTERFACE}': name exceeds maximum of 15 characters, network might be not working."
+ fi
+ done
+ ;;
+ esac
+
+ NETWORK_BRIDGES="$(awk -Fcnt.network-bridge= '/^cnt.network-bridge=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ case "${NETWORK_BRIDGES}" in
+ "")
+ ;;
+
+ *)
+ for BRIDGE_DEFINITION in ${NETWORK_BRIDGES}
+ do
+ INTERFACE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $1 }')"
+ BRIDGE="$(echo ${BRIDGE_DEFINITION} | awk -F: '{ print $2 }')"
+
+ if [ "$(echo ${INTERFACE} | wc -c)" -gt 16 ]
+ then
+ echo "'${INTERFACE}': name exceeds maximum of 15 characters, network might be not working."
+ fi
+
+ if [ -n "${BRIDGE}" ] && [ -n "${INTERFACE}" ]
+ then
+
+ case "${NETWORK_SUBSYSTEM}" in
+ ifupdown)
+
+cat > "/etc/network/interfaces.d/${INTERFACE}" << EOF
+allow-hotplug ${INTERFACE}
+iface ${INTERFACE} inet manual
+ pre-up ip link set ${INTERFACE} up
+ post-up ip link set ${INTERFACE} master ${BRIDGE}
+ pre-down ip link set ${INTERFACE} nomaster
+ post-down ip link set ${INTERFACE} down
+EOF
+
+ ;;
+
+ systemd-networkd)
+ mkdir -p /run/systemd/network
+
+cat > "/run/systemd/network/${INTERFACE}.network" << EOF
+[Match]
+Name=${INTERFACE}
+
+[Network]
+Bridge=${BRIDGE}
+EOF
+
+ networkctl reload
+ ;;
+ esac
+ else
+ echo "Warning bridge definition '${BRIDGE_DEFINITION}' not recognized (expected <bridge>:<interface>): Ignoring"
+ fi
+ done
+ ;;
+ esac
+
+ PRIVATE_USERS="$(awk -Fprivate-users= '/^private-users=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo no)"
+
+ case "${PRIVATE_USERS}" in
+ yes)
+ PRIVATE_USERS="--private-users=yes"
+ ;;
+
+ *)
+ PRIVATE_USERS="--private-users=no"
+ ;;
+ esac
+
+ REGISTER="$(awk -Fregister= '/^register=/ { print $2 }' ${CONFIG}/${NAME}.conf || echo yes)"
+
+ case "${REGISTER}" in
+ yes)
+ REGISTER="--register=yes"
+ ;;
+
+ *)
+ REGISTER="--register=no"
+ ;;
+ esac
+
+ BLOCK_IO_DEVICE_WEIGHT="$(awk -FBlockIODeviceWeight= '/^BlockIODeviceWeight=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BLOCK_IO_DEVICE_WEIGHT}" ]
+ then
+ BLOCK_IO_DEVICE_WEIGHT="BlockIODeviceWeight=${BLOCK_IO_DEVICE_WEIGHT}"
+ SET_PROPERTY="true"
+ fi
+
+ BLOCK_IO_READ_BANDWIDTH="$(awk -FBlockIOReadBandwidth= '/^BlockIOReadBandwidth=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BLOCK_IO_READ_BANDWIDTH}" ]
+ then
+ BLOCK_IO_READ_BANDWIDTH="BlockIOReadBandwidth=${BLOCK_IO_READ_BANDWIDTH}"
+ SET_PROPERTY="true"
+ fi
+
+ BLOCK_IO_WEIGHT="$(awk -FBlockIOWeight= '/^BlockIOWeight=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BLOCK_IO_WEIGHT}" ]
+ then
+ BLOCK_IO_WEIGHT="BlockIOWeight=${BLOCK_IO_WEIGHT}"
+ SET_PROPERTY="true"
+ fi
+
+ BLOCK_IO_WRITE_BANDWIDTH="$(awk -FBlockIOWriteBandwidth=/= '/^BlockIOWriteBandwidth=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BLOCK_IO_WRITE_BANDWIDTH}" ]
+ then
+ BLOCK_IO_WRITE_BANDWIDTH="BlockIOWriteBandwidth=${BLOCK_IO_WRITE_BANDWIDTH}"
+ SET_PROPERTY="true"
+ fi
+
+ CPU_QUOTA="$(awk -FCPUQuota= '/^CPUQuota=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${CPU_QUOTA}" ]
+ then
+ CPU_QUOTA="CPUQuota=${CPU_QUOTA}"
+ SET_PROPERTY="true"
+ fi
+
+ CPU_SHARES="$(awk -FCPUShares= '/^CPUShares=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${CPU_SHARES}" ]
+ then
+ CPU_SHARES="CPUShares=${CPU_SHARES}"
+ SET_PROPERTY="true"
+ fi
+
+ MEMORY_LIMIT="$(awk -FMemoryLimit= '/^MemoryLimit=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${MEMORY_LIMIT}" ]
+ then
+ MEMORY_LIMIT="MemoryLimit=${MEMORY_LIMIT}"
+ SET_PROPERTY="true"
+ fi
+
+ TASKS_MAX="$(awk -FTasksMax= '/^TasksMax=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${TASKS_MAX}" ]
+ then
+ TASKS_MAX="TasksMax=${TASKS_MAX}"
+ SET_PROPERTY="true"
+ fi
+fi
+
+case "${SYSTEMCTL}" in
+ true)
+ systemctl start ${PROGRAM}@${NAME}.service
+
+ # Post hooks
+ for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+ do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+ done
+
+ exit 0
+ ;;
+esac
+
+case "${START}" in
+ true)
+ case "${SET_PROPERTY}" in
+ true)
+ systemctl --runtime set-property ${NAME} ${BLOCK_IO_DEVICE_WEIGHT} ${BLOCK_IO_READ_BANDWIDTH} ${BLOCK_IO_WEIGHT} ${BLOCK_IO_WRITE_BANDWIDTH} ${CPU_QUOTA} ${CPU_SHARES} ${MEMORY_LIMIT} ${TASKS_MAX}
+ ;;
+ esac
+ ;;
+
+ *)
+ # Run
+
+ case "${VERBOSE}" in
+ true)
+ echo -n "Starting container ${NAME}..."
+ ;;
+ esac
+
+ mkdir -p "/var/lib/${SOFTWARE}/state"
+ echo "start" > "/var/lib/${SOFTWARE}/state/${NAME}.run"
+
+ ${SETARCH} systemd-nspawn --keep-unit ${BIND} ${BIND_RO} ${BOOT} ${CAPABILITY} ${DIRECTORY} ${DROP_CAPABILITY} ${MACHINE} ${NETWORK_VETH_EXTRA} ${LINK_JOURNAL} ${REGISTER}
+
+ case "${VERBOSE}" in
+ true)
+ echo " done."
+ ;;
+ esac
+ ;;
+esac
diff --git a/libexec/container/status b/libexec/container/status
new file mode 100755
index 0000000..5b930a7
--- /dev/null
+++ b/libexec/container/status
@@ -0,0 +1,108 @@
+#!/bin/sh
+
+# Copyright (C) 2016 Simon Spöehel <simon.spoehel@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,"
+ GETOPT_OPTIONS="n:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+systemctl status ${PROGRAM}@${NAME}.service --full
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/stop b/libexec/container/stop
new file mode 100755
index 0000000..8ca98ce
--- /dev/null
+++ b/libexec/container/stop
@@ -0,0 +1,360 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+CLEAN="false"
+
+Parameters ()
+{
+ OPTIONS_ALL=""
+
+ GETOPT_LONGOPTIONS="name:,force,interactive,kill,clean,stateless,verbose,"
+ GETOPT_OPTIONS="n:,f,i,k,v,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -f|--force)
+ FORCE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --force"
+ ;;
+
+ -i|--interactive)
+ INTERACTIVE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --interactive"
+ ;;
+
+ -k|--kill)
+ KILL="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --kill"
+ ;;
+
+ --clean)
+ # internal option
+ CLEAN="true"
+ shift 1
+
+ OPTONS_ALL="${OPTIONS_ALL} --clean"
+ ;;
+
+ --stateless)
+ # internal option
+ STATELESS="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --stateless"
+ ;;
+
+ -v|--verbose)
+ VERBOSE="true"
+ shift 1
+
+ OPTIONS_ALL="${OPTIONS_ALL} --verbose"
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--force] [-i|--interactive] [-v|--verbose]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Rmdir ()
+{
+ DIRECTORIES="${@}"
+
+ for DIRECTORY in ${DIRECTORIES}
+ do
+ PARENT_DIRECTORY="/$(echo ${DIRECTORY} | cut -d / -f 2)"
+
+ if [ "${PARENT_DIRECTORY}" != "${DIRECTORY}" ]
+ then
+ # the directory is at least two levels down from /
+ cd "${PARENT_DIRECTORY}"
+
+ CRUFT="$(echo ${DIRECTORY} | cut -d / -f 3-)"
+ rmdir --ignore-fail-on-non-empty --parents "${CRUFT}" > /dev/null 2>&1 || true
+
+ cd "${OLDPWD}"
+ fi
+ done
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+case "${NAME}" in
+ ALL)
+ NAMES="$(${PROGRAM} list --format shell --started)"
+
+ for NAME in ${NAMES}
+ do
+ ${PROGRAM} stop --name ${NAME} ${OPTIONS_ALL} || true
+ done
+
+ exit 0
+ ;;
+esac
+
+if [ ! -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': no such container" >&2
+ exit 1
+fi
+
+if systemctl status systemd-networkd > /dev/null 2>&1
+then
+ NETWORK_SUBSYSTEM="systemd-networkd"
+else
+ NETWORK_SUBSYSTEM="ifupdown"
+fi
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+STATE="$(machinectl show ${NAME} 2>&1 | awk -FState= '/^State=/ { print $2 }')"
+
+case "${CLEAN}" in
+ true)
+ # Removing overlay mounts
+ CNT_OVERLAY="$(awk -Fcnt.overlay= '/^cnt.overlay=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${CNT_OVERLAY}" ]
+ then
+ CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')"
+
+ for CNT_OVERLAY in ${CNT_OVERLAYS}
+ do
+ DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')"
+ DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')"
+ DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')"
+ DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')"
+
+ umount -f "${DIRECTORY_MERGED}"
+
+ Rmdir "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ done
+ fi
+
+ # Removing rw bind mounts
+ BIND="$(awk -Fbind= '/^bind=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BIND}" ]
+ then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for BIND in ${BINDS}
+ do
+ DIRECTORY="$(echo ${BIND} | awk -F: '{ print $1 }')"
+
+ Rmdir "${DIRECTORY}"
+ done
+ fi
+
+ # Removing ro bind mounts
+ BIND_RO="$(awk -Fbind-ro= '/^bind-ro=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ if [ -n "${BIND_RO}" ]
+ then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for BIND_RO in ${BINDS_RO}
+ do
+ DIRECTORY="$(echo ${BIND_RO} | awk -F: '{ print $1 }')"
+
+ Rmdir "${DIRECTORY}"
+ done
+ fi
+
+ # Removing network configuration
+ VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf)"
+
+ case "${VETHS}" in
+ "")
+ ;;
+
+ *)
+ for VETH in ${VETHS}
+ do
+ INTERFACE="$(echo ${VETH} | awk -F: '{ print $1 }')"
+
+ case "${NETWORK_SUBSYSTEM}" in
+ ifupdown)
+ FILE="/etc/network/interfaces.d/${INTERFACE}"
+ ;;
+
+ systemd-networkd)
+ FILE="/run/systemd/network/${INTERFACE}.network"
+ ;;
+ esac
+
+ if [ -f "${FILE}" ]
+ then
+ rm -f "${FILE}"
+ fi
+ done
+ ;;
+ esac
+
+ exit 0
+ ;;
+
+ *)
+ ;;
+esac
+
+case "${STATE}" in
+ running)
+ ;;
+
+ *)
+ echo "'${NAME}': container is already stopped" >&2
+ exit 1
+ ;;
+esac
+
+case "${KILL}" in
+ true)
+ MODE="terminate"
+ ;;
+
+ *)
+ MODE="poweroff"
+ ;;
+esac
+
+if [ "${FORCE}" != "true" ] || [ "${INTERACTIVE}" = "true" ]
+then
+ echo -n "'${NAME}': stop container '${NAME}' [y|N]? "
+ read STOP
+
+ STOP="$(echo ${STOP} | tr '[A-Z]' '[a-z]')"
+
+ case "${STOP}" in
+ y|yes)
+ ;;
+
+ *)
+ exit 1
+ ;;
+ esac
+fi
+
+# Run
+case "${VERBOSE}" in
+ true)
+ echo -n "Stopping container ${NAME}..."
+ ;;
+esac
+
+machinectl ${MODE} ${NAME}
+
+case "${KILL}" in
+ true)
+ VETHS="$(awk -Fnetwork-veth-extra= '/^network-veth-extra=/ { print $2 }' ${CONFIG}/${NAME}.conf | awk -F: '{ print $1 }')"
+
+ for VETH in ${VETHS}
+ do
+ ip link delete ${VETH} > /dev/null 2>&1 || true
+ done
+
+ rm -f "${MACHINES}/.#${NAME}.lck"
+ ;;
+esac
+
+case "${STATELESS}" in
+ true)
+ ;;
+
+ *)
+ mkdir -p "/var/lib/${SOFTWARE}/state"
+ echo "stop" > "/var/lib/${SOFTWARE}/state/${NAME}.run"
+ ;;
+esac
+
+case "${VERBOSE}" in
+ true)
+ echo " done."
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/top b/libexec/container/top
new file mode 100755
index 0000000..268da9a
--- /dev/null
+++ b/libexec/container/top
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="delay:,"
+ GETOPT_OPTIONS="d:,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -d|--delay)
+ DELAY="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} [-d|--delay DELAY]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+DELAY="${DELAY:-1}"
+HOST="$(hostname -f 2> /dev/null || hostname)"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+Top ()
+{
+ HOME="$(tput cup 0 0)"
+ ED="$(tput ed)"
+ EL="$(tput el)"
+
+ printf '%s%s' "${HOME}" "${ED}"
+
+ while true
+ do
+ ROWS="$(tput lines)"
+ COLS="$(tput cols)"
+ CMD="${@}"
+
+ ${SHELL:=sh} -c "${CMD}" | head -n ${ROWS} | while IFS= read LINE
+ do
+ printf '%-*.*s%s\n' ${COLS} ${COLS} "${LINE}" "${EL}"
+ done
+
+ printf '%s%s' "${ED}" "${HOME}"
+ sleep ${DELAY}
+ done
+}
+
+trap 'clear' EXIT HUP INT QUIT TERM
+
+Top "${PROGRAM} list && printf '%-59s %-19s\n' \" Host: ${HOST}\" \"\$(date +%Y-%m-%d\ %H:%M:%S)\""
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/update b/libexec/container/update
new file mode 100755
index 0000000..e2d9c80
--- /dev/null
+++ b/libexec/container/update
@@ -0,0 +1,270 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="name:,full-upgrade,interactive,autoremove,purge,yes,"
+ GETOPT_OPTIONS="n:,f,i,r,p,y,"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${COMMAND} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${COMMAND}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -f|--full-upgrade)
+ FULL_UPGRADE="true"
+ shift 1
+ ;;
+
+ -i|--interactive)
+ INTERACTIVE="true"
+ shift 1
+ ;;
+
+ -r|--autoremove)
+ AUTOREMOVE="true"
+ shift 1
+ ;;
+
+ -p|--purge)
+ PURGE="--purge"
+ shift 1
+ ;;
+
+ -y|--yes)
+ YES="-y"
+ shift 1
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${COMMAND}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: ${PROGRAM} ${COMMAND} -n|--name NAME [-f|--full-upgrade] [-i|--interactive] [-r|--autoremove] [-p|--purge] [-y|--yes]" >&2
+ echo
+ echo "See ${COMMAND}(1), ${PROGRAM}(1) and ${PROJECT}(7) for more information."
+
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+Notification ()
+{
+ TYPE="${1}"
+ NUMBER="${2}"
+ PACKAGES="${3}"
+
+ if [ -z "${PACKAGES}" ]
+ then
+ return
+ fi
+
+ CONTAINER_USER="${SUDO_USER:-${USER}}"
+
+ DATE="$(date +%Y-%m-%d\ %H:%M:%S)"
+ HOST="$(hostname -f 2> /dev/null || hostname)"
+
+ # logfile
+ echo "${DATE} ${HOST} ${CONTAINER_USER} ${NAME} ${NUMBER} ${TYPE}: ${PACKAGES}" >> "/var/log/${SOFTWARE}/${PROGRAM}.log"
+
+ # irc
+ if [ -e /usr/bin/irk ]
+ then
+ for FILE in "/etc/${SOFTWARE}/${PROGRAM}.conf" "/etc/${SOFTWARE}/${PROGRAM}.conf.d"/*.conf
+ do
+ if [ -e "${FILE}" ]
+ then
+ . "${FILE}"
+ fi
+ done
+
+ if [ -n "${IRK_TARGETS}" ]
+ then
+ for TARGET in ${IRK_TARGETS}
+ do
+ irk "${TARGET}" "\x0300${CONTAINER_USER}\x03@\x0312${HOST}:\x03 \x0303${NAME}\x03 \x0307${NUMBER} ${TYPE}\x03: ${PACKAGES}"
+ done
+ fi
+ fi
+}
+
+case "${NAME}" in
+ ALL)
+ NAMES="$(container list --started --format shell)"
+ ;;
+
+ *)
+ NAMES="${NAME}"
+ ;;
+esac
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+if [ $(echo ${NAMES} | wc -w) -gt 1 ]
+then
+ NAME_LOOP="true"
+else
+ NAME_LOOP="false"
+fi
+
+# Run
+for NAME in ${NAMES}
+do
+ case "${INTERACTIVE}" in
+ true)
+ case "${NAME_LOOP}" in
+ true)
+ echo
+ ;;
+ esac
+
+ echo -n "'${NAME}': update container '${NAME}' [y|N|a]? "
+ read UPDATE
+
+ UPDATE="$(echo ${UPDATE} | tr '[A-Z]' '[a-z]')"
+
+ case "${UPDATE}" in
+ a|all)
+ INTERACTIVE="false"
+ ;;
+
+ y|yes)
+ ;;
+
+ *)
+ case "${NAME_LOOP}" in
+ true)
+ continue
+ ;;
+
+ *)
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+
+ echo "################################################################################"
+ echo "Updating ${NAME}"
+ echo "################################################################################"
+
+ container run -n ${NAME} -- "apt update"
+
+ UPDATE_NUMBER="$(container run -n ${NAME} -- "apt \-\-simulate full-upgrade" | awk '/^[0-9]* upgraded, / { print $1 }')"
+
+ case "${UPDATE_NUMBER}" in
+ 0)
+ ;;
+
+ *)
+ # usefull use of grep to de-colorize apt output
+ UPDATE_PACKAGES="$(for PACKAGE in $(container run -n ${NAME} -- "apt list \-\-upgradable 2>/dev/null | grep '\/'" | awk -F/ '{ print $1 }'); do echo -n "${PACKAGE} "; done | sed -e 's| $||'; echo)"
+
+ case "${FULL_UPGRADE}" in
+ true)
+ container run -n ${NAME} -- "DEBCONF_FRONTEND='noninteractive' DEBCONF_PRIORITY='critical' DEBCONF_NONINTERACTIVE_SEEN='true' DEBCONF_NOWARNINGS='true' apt \-o Dpkg::Options::=\-\-force-confold -f ${YES} full-upgrade"
+ ;;
+
+ *)
+ container run -n ${NAME} -- "DEBCONF_FRONTEND='noninteractive' DEBCONF_PRIORITY='critical' DEBCONF_NONINTERACTIVE_SEEN='true' DEBCONF_NOWARNINGS='true' apt \-o Dpkg::Options::=\-\-force-confold -f ${YES} upgrade"
+ ;;
+ esac
+
+ Notification "update(s)" "${UPDATE_NUMBER}" "${UPDATE_PACKAGES}"
+ ;;
+ esac
+
+ case "${AUTOREMOVE}" in
+ true)
+ REMOVE_NUMBER="$(container run -n ${NAME} -- "apt \-\-simulate autoremove" | awk '/^[0-9]* upgraded, / { print $6 }')"
+
+ case "${REMOVE_NUMBER}" in
+ 0)
+ ;;
+
+ *)
+ REMOVE_PACKAGES="$(for LINE in $(container run -n ${NAME} -- "apt \-\-simulate autoremove" | grep '^ '); do echo ${LINE}; done | sed -e 's|^ ||' -e 's| $||'; echo)"
+
+ container run -n ${NAME} -- "apt ${YES} autoremove ${PURGE}"
+
+ Notification "removal(s)" "${REMOVE_NUMBER}" "$(echo ${REMOVE_PACKAGES})"
+ ;;
+ esac
+ ;;
+ esac
+
+ echo "'${NAME}': container updated."
+done
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/libexec/container/version b/libexec/container/version
new file mode 100755
index 0000000..e580688
--- /dev/null
+++ b/libexec/container/version
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+COMMAND="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+SHARE="/usr/share/${SOFTWARE}"
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${COMMAND}".* "${HOOKS}/${NAME}.pre-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+cat "${SHARE}/VERSION.txt"
+
+# Post hooks
+for FILE in "${HOOKS}/post-${COMMAND}".* "${HOOKS}/${NAME}.post-${COMMAND}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/share/bash-completion/container b/share/bash-completion/container
new file mode 100644
index 0000000..5b57193
--- /dev/null
+++ b/share/bash-completion/container
@@ -0,0 +1,385 @@
+# Open Infrastructure: compute-tools
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+_container()
+{
+ local cur prev cmd opts
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+ if [ ${COMP_CWORD} -gt 0 ]
+ then
+ cmd="${COMP_WORDS[1]}"
+ fi
+
+ if [ "${prev}" = "--" ]
+ then
+ compopt -o bashdefault
+ COMPREPLY=( $(compgen -c -- $cur) )
+ return 0
+ fi
+
+ case "${cmd}" in
+ auto)
+ opts="-f --force -s --start -t --stop"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ build|b)
+ case "${prev}" in
+ -n|--name)
+ opts="$(cd /etc/compute-tools/debconf 2>/dev/null && ls *.cfg */*.cfg 2>/dev/null | sed -e 's|.*/||g' -e 's|.cfg$||g')"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ -s|--script)
+ opts="$(cd /usr/share/compute-tools/build-scripts && find -maxdepth 1 -not -type d -and -not -name 'default' -and -not -name 'debconf' -and -not -name '*.d' -printf '%P\n' | sort)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -c --capability -d --drop-capability -s --script -v --verbose -b --bind --bind-ro"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ console)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -s -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ enter|run)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -s -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ get|g)
+ case "${prev}" in
+ -n|--name)
+ opts="$(cd /etc/compute-tools/debconf 2>/dev/null && ls *.cfg */*.cfg 2>/dev/null | sed -e 's|.*/||g' -e 's|.cfg$||g')"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ -s|--script)
+ opts="$(cd /usr/share/compute-tools/get-scripts && find -maxdepth 1 -not -type d -and -not -name 'default' -and -not -name 'debconf' -and -not -name '*.d' -printf '%P\n' | sort)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -c --capability -d --drop-capability -s --script -v --verbose -b --bind --bind-ro"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ info)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -t -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="--status --os --ip"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ key)
+ case "${prev}" in
+ -a|--add)
+ opts="$(cd /usr/share/compute-tools/keys 2>/dev/null && ls *.pub 2>/dev/null | sed -e 's|.*/||g' -e 's|.pub$||g')"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ -r|--remove)
+ opts="$(gpg --homedir /etc/compute-tools/keys --list-keys | grep ^uid | sed -e 's|.*<||' -e 's|>||')"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-a --add -r --remove -l --list"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ limit)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -a -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name --blockio-device-weight --blockio-read-bandwidth -b --blockio-weight --blockio-write-bandwidth -c --cpu-quota --cpu-shares -m --memory-limit -t --tasks-max"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ list|ls)
+ case "${prev}" in
+ -h|--host)
+ opts="true false $(hostname -f 2> /dev/null || hostname)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ -f|--format)
+ opts="cli csv json nwdiag shell sh yaml xml"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-a --all -f --format -h --host -o --other -s --started -t --stopped"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ log)
+ case "${prev}" in
+ -d|--date)
+ opts="$(if ls /var/log/compute-tools/container.log-*.gz > /dev/null 2>&1;
+ then \
+ zcat /var/log/compute-tools/container.log-*.gz | awk '{ print $1 }' | sort -u; \
+ fi; \
+ if [ -e /var/log/compute-tools/container.log ]; \
+ then \
+ awk '{ print $1 }' /var/log/compute-tools/container.log | sort -u; \
+ fi) \
+ today yesterday"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ -n|--name)
+ opts="$(if ls /var/log/compute-tools/container.log-*.gz > /dev/null 2>&1;
+ then \
+ zgrep -E '(\-n|\-\-name) ' /var/log/compute-tools/container.log-*.gz | sed -e 's|.*-n ||' -e 's|.*--name ||' -e 's| .*$||' | sort -u; \
+ fi; \
+ if [ -e /var/log/compute-tools/container.log ]; \
+ then \
+ grep -E '(\-n|\-\-name) ' /var/log/compute-tools/container.log | sed -e 's|.*-n ||' -e 's|.*--name ||' -e 's| .*$||' | sort -u; \
+ fi)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-d --date -n --name"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ move|mv)
+ case "${prev}" in
+ -o|--old)
+ opts="$(container list -t -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-f --force -n --new -o --old"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ remove|rm)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -t -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -f --force -i --interactive -k --kill"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ rebuild|rb)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -f --force -v --verbose"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ restart|rs)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -s -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ start|s)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -t -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -v --verbose"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ status|st)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ stop|t)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -s -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -f --force"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ top)
+ opts="-d --delay"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ update|u)
+ case "${prev}" in
+ -n|--name)
+ opts="$(container list -s -f shell)"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ *)
+ opts="-n --name -f --full-upgrade -r --autoremove -p --purge --y --yes"
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+ ;;
+
+ version|ver)
+ return 0
+ ;;
+
+ *)
+ local commands=$(cd /usr/libexec/container 2>/dev/null && find * -type f -print)
+ COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+
+ compopt -o filenames
+ COMPREPLY=( $(compgen -f -- $cur) )
+ return 0
+}
+
+complete -F _container container cnt
diff --git a/share/build-scripts/debconf b/share/build-scripts/debconf
new file mode 100755
index 0000000..900242d
--- /dev/null
+++ b/share/build-scripts/debconf
@@ -0,0 +1,1318 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+VERSION="$(container version)"
+
+SCRIPT="${0}"
+export SCRIPT
+
+CACHE="/var/cache/${PROGRAM}/build-$(basename ${SCRIPT})"
+CONFIG="/etc/${SOFTWARE}/config"
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="bind:,bind-ro:,script:,name:,preseed-file:"
+ GETOPT_OPTIONS="b:,s:,n:,p:"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${SCRIPT} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${SCRIPT}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -b|--bind)
+ # ignore
+ shift 2
+ ;;
+
+ --bind-ro)
+ # ignore
+ shift 2
+ ;;
+
+ --cnt.auto)
+ # ignore
+ shift 2
+ ;;
+
+ --cnt.container-server)
+ # ignore
+ shift 2
+ ;;
+
+ -s|--script)
+ # ignore
+ shift 2
+ ;;
+
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ --preseed-file)
+ PRESEED_FILE="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${SCRIPT}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: container build -n|--name NAME -s|--script ${SCRIPT} -- [-p|--preseed-file FILE]" >&2
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': container already exists" >&2
+ exit 1
+fi
+
+if [ "$(id -u)" -ne 0 ]
+then
+ echo "'${NAME}': need root privileges" >&2
+ exit 1
+fi
+
+Mount ()
+{
+ # Mounting rw bind mounts
+ if [ -n "${BIND}" ]
+ then
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g')"
+
+ for ENTRY in ${BINDS}
+ do
+ SOURCE="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+ TARGET="$(echo ${ENTRY} | awk -F: '{ print $2 }')"
+
+ mkdir -p "${SOURCE}"
+ mkdir -p "${MACHINES}/${NAME}/${TARGET}"
+
+ mount -o bind "${SOURCE}" "${MACHINES}/${NAME}/${TARGET}"
+ done
+ fi
+
+ # Mounting ro bind mounts
+ if [ -n "${BIND_RO}" ]
+ then
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g')"
+
+ for ENTRY in ${BINDS_RO}
+ do
+ SOURCE="$(echo ${ENTRY} | awk -F: '{ print $1 }')"
+ TARGET="$(echo ${ENTRY} | awk -F: '{ print $2 }')"
+
+ mkdir -p "${SOURCE}"
+ mkdir -p "${MACHINES}/${NAME}/${TARGET}"
+
+ mount -o rbind "${SOURCE}" "${MACHINES}/${NAME}/${TARGET}"
+ done
+ fi
+
+ # Mounting overlay mounts
+ if [ -n "${CNT_OVERLAY}" ]
+ then
+ CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')"
+
+ COUNT="0"
+ for CNT_OVERLAY in ${CNT_OVERLAYS}
+ do
+ DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')"
+ DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')"
+ DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')"
+ DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')"
+
+ COUNT="$((${COUNT} + 1))"
+ CNT_OVERLAY_OPTION="$(echo ${CNT_OVERLAY_OPTIONS} | awk -F ';' "{ print \$${COUNT} }")"
+
+ for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ do
+ mkdir -p "${DIRECTORY}"
+ done
+
+ if ! findmnt -n -o SOURCE "${DIRECTORY_MERGED}" | grep -qs '^overlay-'
+ then
+ if [ -n "${CNT_OVERLAY_OPTION}" ]
+ then
+ CNT_OVERLAY_OPTION="-o ${CNT_OVERLAY_OPTION}"
+ fi
+
+ mount -t overlay overlay-${NAME} ${CNT_OVERLAY_OPTION} -olowerdir="${DIRECTORY_LOWER}",upperdir="${DIRECTORY_UPPER}",workdir="${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ fi
+ done
+ fi
+}
+
+Umount ()
+{
+ # Unmounting overlay mounts
+ if [ -n "${CNT_OVERLAY}" ]
+ then
+ CNT_OVERLAYS="$(echo ${CNT_OVERLAY} | sed -e 's|;| |g')"
+
+ for CNT_OVERLAY in ${CNT_OVERLAYS}
+ do
+ DIRECTORY_LOWER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $1 }')"
+ DIRECTORY_UPPER="$(echo ${CNT_OVERLAY} | awk -F: '{ print $2 }')"
+ DIRECTORY_WORK="$(echo ${CNT_OVERLAY} | awk -F: '{ print $3 }')"
+ DIRECTORY_MERGED="$(echo ${CNT_OVERLAY} | awk -F: '{ print $4 }')"
+
+ umount -f "${DIRECTORY_MERGED}" > /dev/null 2>&1 || true
+
+ for DIRECTORY in "${DIRECTORY_LOWER}" "${DIRECTORY_UPPER}" "${DIRECTORY_WORK}" "${DIRECTORY_MERGED}"
+ do
+ rmdir --ignore-fail-on-non-empty --parents ${DIRECTORY} > /dev/null 2>&1 || true
+ done
+ done
+
+ # empty workdir otherwise there might happen stale file handles
+ if [ -d "${DIRECTORY_WORK}" ]
+ then
+ rm --preserve-root --one-file-system -rf "${DIRECTORY_WORK}"/*
+ fi
+ fi
+
+ # Unmounting ro bind mounts
+ if [ -n "${BIND_RO}" ]
+ then
+ # unmount in reverse order to allow nested bind mounts
+ BINDS_RO="$(echo ${BIND_RO} | sed -e 's|;| |g' | awk '{ for (i=NF; i>=1; i--) printf "%s ", $i; print ""}')"
+
+ for ENTRY in ${BINDS_RO}
+ do
+ TARGET="$(echo ${ENTRY} | awk -F: '{ print $2 }')"
+
+ umount -f "${MACHINES}/${NAME}/${TARGET}" > /dev/null 2>&1 || true
+ done
+ fi
+
+ # Unmounting rw bind mounts
+ if [ -n "${BIND}" ]
+ then
+ # unmount in reverse order to allow nested bind mounts
+ BINDS="$(echo ${BIND} | sed -e 's|;| |g' | awk '{ for (i=NF; i>=1; i--) printf "%s ", $i; print ""}')"
+
+ for ENTRY in ${BINDS}
+ do
+ TARGET="$(echo ${ENTRY} | awk -F: '{ print $2 }')"
+
+ umount -f "${MACHINES}/${NAME}/${TARGET}" > /dev/null 2>&1 || true
+ done
+ fi
+
+ # Unmounting pseudo-filesystems
+ umount -f "${DIRECTORY}/dev/pts" > /dev/null 2>&1 || true
+ umount -f "${DIRECTORY}/proc" > /dev/null 2>&1 || true
+ umount -f "${DIRECTORY}/sys" > /dev/null 2>&1 || true
+}
+
+Chroot ()
+{
+ CHROOT="${1}"
+ shift
+
+ chroot "${CHROOT}" /usr/bin/env -i \
+ LC_ALL="C" PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games" TERM="${TERM}" \
+ DEBIAN_FRONTEND="${DEBCONF_FRONTEND}" DEBIAN_PRIORITY="${DEBCONF_PRIORITY}" \
+ DEBCONF_NONINTERACTIVE_SEEN="true" DEBCONF_NOWARNINGS="true" \
+ ftp_proxy="${ftp_proxy}" http_proxy="${http_proxy}" \
+ ${@}
+}
+
+Upgrade_system ()
+{
+ DIRECTORY="${1}"
+
+ # Mount pseudo-filesystems
+ mount -o bind /dev/pts "${DIRECTORY}/dev/pts"
+ mount -o bind /proc "${DIRECTORY}/proc"
+ mount -o bind /sys "${DIRECTORY}/sys"
+
+ # Disable dpkg syncing
+
+cat > "${DIRECTORY}/etc/dpkg/dpkg.cfg.d/${SOFTWARE}" << EOF
+force-unsafe-io
+EOF
+
+ # Create policy-rc.d file
+
+cat > "${DIRECTORY}/usr/sbin/policy-rc.d" << EOF
+#!/bin/sh
+echo "All runlevel operations denied by policy" >&2
+exit 101
+EOF
+
+ chmod 0755 "${DIRECTORY}/usr/sbin/policy-rc.d"
+
+ # Upgrade system
+ Chroot "${DIRECTORY}" "apt update"
+ Chroot "${DIRECTORY}" "apt --yes --option Dpkg::Options::=--force-confnew upgrade"
+ Chroot "${DIRECTORY}" "apt --yes --option Dpkg::Options::=--force-confnew dist-upgrade"
+
+ # Install systemd support packages
+ Chroot "${DIRECTORY}" "apt --yes install dbus libpam-systemd systemd-sysv"
+
+ Chroot "${DIRECTORY}" "apt clean"
+}
+
+Cleanup_system ()
+{
+ DIRECTORY="${1}"
+
+ Chroot "${DIRECTORY}" "apt --yes --purge autoremove"
+ Chroot "${DIRECTORY}" "apt clean"
+
+ # Cleanup
+ rm -f "${DIRECTORY}/etc/dpkg/dpkg.cfg.d/${SOFTWARE}"
+ rm -f "${DIRECTORY}/usr/sbin/policy-rc.d"
+
+ # Unmount pseudo-filesystems
+ umount -f "${DIRECTORY}/dev/pts" > /dev/null 2>&1 || true
+ umount -f "${DIRECTORY}/proc" > /dev/null 2>&1 || true
+ umount -f "${DIRECTORY}/sys" > /dev/null 2>&1 || true
+}
+
+Debconf ()
+{
+ # Configure local debconf
+ mkdir -p "/tmp/${SOFTWARE}"
+ DEBCONF_TMPDIR="$(mktemp -d -p "/tmp/${SOFTWARE}" -t $(basename ${0}).XXXX)"
+ export DEBCONF_TMPDIR
+
+ mkdir -p "${DEBCONF_TMPDIR}/debconf"
+
+cat > "${DEBCONF_TMPDIR}/debconf.systemrc" << EOF
+Config: configdb
+Templates: templatedb
+
+Name: config
+Driver: File
+Mode: 644
+Reject-Type: password
+Filename: ${DEBCONF_TMPDIR}/debconf/config.dat
+
+Name: passwords
+Driver: File
+Mode: 600
+Backup: false
+Required: false
+Accept-Type: password
+Filename: ${DEBCONF_TMPDIR}/debconf/passwords.dat
+
+Name: configdb
+Driver: Stack
+Stack: config, passwords
+
+Name: templatedb
+Driver: File
+Mode: 644
+Filename: ${DEBCONF_TMPDIR}/debconf/templates.dat
+EOF
+
+ DEBCONF_SYSTEMRC="${DEBCONF_TMPDIR}/debconf.systemrc"
+ export DEBCONF_SYSTEMRC
+}
+
+Bootstrap ()
+{
+ DIRECTORY="${1}"
+
+ EXCLUDE="ifupdown"
+ INCLUDE="dbus"
+
+ # apt repositories
+ INCLUDE="${INCLUDE},gnupg"
+
+ if ( echo "${MIRROR}" | grep -qs '^https' ) || \
+ ( echo "${PARENT_MIRROR}" | grep -qs '^https' )
+ then
+ INCLUDE="${INCLUDE},apt-transport-https,ca-certificates"
+ fi
+
+ case "${MODE}" in
+ progress-linux)
+ INCLUDE="${INCLUDE},progress-linux,gnupg"
+ ;;
+ esac
+
+ mkdir -p "$(dirname ${DIRECTORY})"
+
+ case "${BOOTSTRAP}" in
+ debootstrap)
+ debootstrap --verbose --arch=${ARCHITECTURE} --components=${PARENT_ARCHIVE_AREAS} \
+ --exclude=${EXCLUDE} --include=${INCLUDE} ${PARENT_DISTRIBUTION} "${DIRECTORY}" ${PARENT_MIRROR}
+ ;;
+
+ mmdebstrap)
+ mmdebstrap --arch=${ARCHITECTURE} --components=${PARENT_ARCHIVE_AREAS} \
+ --format=directory --mode=root --aptopt='APT::Sandbox::User "root"' \
+ --include=${INCLUDE} ${PARENT_DISTRIBUTION} "${DIRECTORY}" ${PARENT_MIRROR}
+ ;;
+
+ *)
+ echo "'${NAME}': ${BOOTSTRAP} - not supported" >&2
+ exit 1
+ ;;
+ esac
+}
+
+Image ()
+{
+ DIRECTORY="${1}"
+
+ FILES="${IMAGE}"
+
+ for NUMBER in $(seq 1 ${IMAGE_NUMBER})
+ do
+ eval FILES="${FILES} $`echo IMAGE${NUMBER}`"
+ done
+
+ for FILE in ${FILES}
+ do
+ case "${FILE}" in
+ *.gz)
+ TAR_OPTIONS="--gzip"
+
+ if [ ! -e /bin/gzip ]
+ then
+ echo -en "\n"
+ echo "'${NAME}': /bin/lzip - no such file." >&2
+ exit 1
+ fi
+ ;;
+
+ *.lz)
+ TAR_OPTIONS="--lzip"
+
+ if [ ! -e /usr/bin/lzip ]
+ then
+ echo -en "\n"
+ echo "'${NAME}': /usr/bin/lzip - no such file." >&2
+ exit 1
+ fi
+ ;;
+
+ *.xz)
+ TAR_OPTIONS="--xz"
+
+ if [ ! -e /usr/bin/xz ]
+ then
+ echo -en "\n"
+ echo "'${NAME}': /usr/bin/xz - no such file." >&2
+ exit 1
+ fi
+ ;;
+
+ *)
+ TAR_OPTIONS=""
+ ;;
+ esac
+
+ mkdir -p "${DIRECTORY}"
+
+ echo "Using ${FILE}"
+
+ if [ -e /usr/bin/pv ]
+ then
+ curl --fail --location --progress-bar --user-agent ${SOFTWARE}/${VERSION} --http2 ${CURL_TIME_COND} \
+ "${FILE}" -o - | \
+ pv --format '%p' --width 77 | \
+ tar -C "${DIRECTORY}" --strip 1 ${TAR_OPTIONS} -xf -
+ #pv --format '%p' --width 77 "${CACHE}/${FILE}" | tar xf - ${TAR_OPTIONS} -C "${DIRECTORY}" --strip 1
+ else
+ curl --fail --location --progress-bar --user-agent ${SOFTWARE}/${VERSION} --http2 ${CURL_TIME_COND} \
+ "${FILE}" -o - | \
+ tar -C "${DIRECTORY}" --strip 1 ${TAR_OPTIONS} -xf -
+ fi
+
+ echo " ok."
+ done
+
+ # Writing resolv.conf
+ rm -f "${DIRECTORY}/etc/resolv.conf"
+ cp /etc/resolv.conf "${DIRECTORY}/etc"
+}
+
+Configure_apt ()
+{
+ DIRECTORY="${1}"
+
+ # Configure apt
+ rm -f "${DIRECTORY}/etc/apt/sources.list"
+
+ PARENT_AREA="$(echo ${PARENT_ARCHIVE_AREAS} | sed -e 's|,| |g')"
+ PARENT_DIST="$(echo ${PARENT_DISTRIBUTION} | sed -e 's|-backports||')"
+
+cat > "${DIRECTORY}/etc/apt/sources.list.d/debian.list" << EOF
+# /etc/apt/sources.list.d/debian.list
+
+deb ${PARENT_MIRROR} ${PARENT_DIST} ${PARENT_AREA}
+EOF
+
+ case "${MODE}" in
+ progress-linux)
+
+cat > "${DIRECTORY}/progress-linux.cfg" << EOF
+progress-linux progress-linux/archives multiselect $(echo ${ARCHIVES} | sed -e 's| |, |g')
+progress-linux progress-linux/archive-areas multiselect $(echo ${ARCHIVE_AREAS} | sed -e 's|,| |g')
+EOF
+
+ Chroot "${DIRECTORY}" "debconf-set-selections progress-linux.cfg"
+ Chroot "${DIRECTORY}" "DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=criticial dpkg-reconfigure progress-linux"
+
+ rm -f "${DIRECTORY}/progress-linux.cfg"
+
+ case "${INSTALLER}" in
+ bootstrap)
+ Chroot "${DIRECTORY}" "apt update"
+ ;;
+ esac
+ ;;
+ esac
+}
+
+Deconfigure_system ()
+{
+ DIRECTORY="${1}"
+
+ # Configure fstab
+
+cat > "${DIRECTORY}/etc/fstab" << EOF
+# /etc/fstab: static file system information.
+#
+# Use 'blkid' to print the universally unique identifier for a
+# device; this may be used with UUID= as a more robust way to name devices
+# that works even if disks are added and removed. See fstab(5).
+#
+# <file system> <mount point> <type> <options> <dump> <pass>
+
+EOF
+
+ # Fix /etc/mtab
+ rm -f "${DIRECTORY}/etc/mtab"
+ ln -s /proc/self/mounts "${DIRECTORY}/etc/mtab"
+
+ # Removing machine-id
+ rm -f "${DIRECTORY}/etc/machine-id"
+
+ # Removing resolv.conf
+ rm -f "${DIRECTORY}/etc/resolv.conf"
+ cp /etc/resolv.conf "${DIRECTORY}/etc"
+
+ # Removing hosts/hostname
+ rm -f "${DIRECTORY}"/etc/hosts
+ rm -f "${DIRECTORY}"/etc/hostname
+
+ # Removing openssh-server host keys
+ rm -f "${DIRECTORY}"/etc/ssh/ssh_host_*_key
+ rm -f "${DIRECTORY}"/etc/ssh/ssh_host_*_key.pub
+}
+
+Configure_system ()
+{
+ DIRECTORY="${1}"
+
+ # Overwrite resolv.conf from cache with hosts resolv.conf
+ rm -f "${DIRECTORY}/etc/resolv.conf"
+ cp /etc/resolv.conf "${DIRECTORY}/etc"
+
+ echo "${NAME}" > "${DIRECTORY}/etc/hostname"
+
+ # Configure apt
+ rm -f "${DIRECTORY}/etc/apt/sources.list"
+
+ PARENT_AREA="$(echo ${PARENT_ARCHIVE_AREAS} | sed -e 's|,| |g')"
+ PARENT_DIST="$(echo ${PARENT_DISTRIBUTION} | sed -e 's|-backports||')"
+
+cat > "${DIRECTORY}/etc/apt/sources.list.d/debian.list" << EOF
+# /etc/apt/sources.list.d/debian.list
+
+deb ${PARENT_MIRROR} ${PARENT_DIST} ${PARENT_AREA}
+EOF
+
+ for PARENT_REPO in ${PARENT_ARCHIVES}
+ do
+ case "${PARENT_REPO}" in
+ buster-security)
+ echo "deb ${PARENT_MIRROR_SECURITY} ${PARENT_DIST}/updates ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list"
+ ;;
+
+ ${PARENT_DIST}-security)
+ echo "deb ${PARENT_MIRROR_SECURITY} ${PARENT_DIST}-security ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list"
+ ;;
+
+ ${PARENT_DIST}-updates)
+ echo "deb ${PARENT_MIRROR} ${PARENT_DIST}-updates ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list"
+ ;;
+
+ ${PARENT_DIST}-backports)
+ echo "deb ${PARENT_MIRROR} ${PARENT_DIST}-backports ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list"
+ ;;
+
+ ${PARENT_DIST}-proposed-updates)
+ echo "deb ${PARENT_MIRROR} ${PARENT_DIST}-proposed-updates ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list"
+ ;;
+
+ experimental)
+ echo "deb ${PARENT_MIRROR} experimental ${PARENT_AREA}" >> "${DIRECTORY}/etc/apt/sources.list.d/debian.list"
+ ;;
+ esac
+ done
+
+ case "${MODE}" in
+ progress-linux)
+
+cat > "${DIRECTORY}/progress-linux.cfg" << EOF
+progress-linux progress-linux/archives multiselect $(echo ${ARCHIVES} | sed -e 's| |, |g')
+progress-linux progress-linux/archive-areas multiselect $(echo ${ARCHIVE_AREAS} | sed -e 's|,| |g')
+EOF
+
+ Chroot "${DIRECTORY}" "debconf-set-selections progress-linux.cfg"
+ Chroot "${DIRECTORY}" "DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=criticial dpkg-reconfigure progress-linux"
+
+ rm -f "${DIRECTORY}/progress-linux.cfg"
+ ;;
+ esac
+
+ if [ "${APT_RECOMMENDS}" = "false" ]
+ then
+
+cat > "${DIRECTORY}/etc/apt/apt.conf.d/recommends.conf" << EOF
+APT::Install-Recommends "false";
+EOF
+
+ fi
+
+ # Add local archives configured from preseed file
+ if ls "${DEBCONF_TMPDIR}/apt"/*.list > /dev/null 2>&1
+ then
+ cp "${DEBCONF_TMPDIR}/apt"/*.list "${DIRECTORY}/etc/apt/sources.list.d"
+
+ if ls "${DEBCONF_TMPDIR}/apt"/*.key > /dev/null 2>&1
+ then
+ for KEY in "${DEBCONF_TMPDIR}/apt"/*.key
+ do
+ cp "${KEY}" "${DIRECTORY}"
+ Chroot "${DIRECTORY}" "apt-key add $(basename ${KEY})"
+ rm -f "${DIRECTORY}/$(basename ${KEY})"
+ done
+ fi
+
+ if ls "${DEBCONF_TMPDIR}/apt"/*.pref > /dev/null 2>&1
+ then
+ cp "${DEBCONF_TMPDIR}/apt"/*.pref "${DIRECTORY}/etc/apt/preferences.d"
+ fi
+ fi
+
+ Upgrade_system "${DIRECTORY}"
+
+ # Preseed system
+ if [ -n "${PRESEED_FILE}" ]
+ then
+ for FILE in ${PRESEED_FILE}
+ do
+ if [ -e /usr/bin/kdig ]
+ then
+ DIG="/usr/bin/kdig"
+ elif [ -e /usr/bin/dig ]
+ then
+ DIG="/usr/bin/dig"
+ fi
+
+ if [ -n "${DIG}" ]
+ then
+ IPV4_ADDRESS1="$(${DIG} A +short ${NAME} | tail -n1)"
+ IPV4_ADDRESS1_PART1="$(echo ${IPV4_ADDRESS1} | cut -d. -f1)"
+ IPV4_ADDRESS1_PART2="$(echo ${IPV4_ADDRESS1} | cut -d. -f2)"
+ IPV4_ADDRESS1_PART3="$(echo ${IPV4_ADDRESS1} | cut -d. -f3)"
+ IPV4_ADDRESS1_PART4="$(echo ${IPV4_ADDRESS1} | cut -d. -f4)"
+
+ IPV6_ADDRESS1="$(${DIG} AAAA +short ${NAME} | tail -n1)"
+ # FIXME: address parts
+
+ export IPV4_ADDRESS1 IPV4_ADDRESS1_PART1 IPV4_ADDRESS1_PART2 IPV4_ADDRESS1_PART3 IPV4_ADDRESS1_PART4
+ export IPV6_ADDRESS1
+ fi
+
+ sed -e "s|@FILE@|${FILE}|g" \
+ -e "s|@NAME@|${NAME}|g" \
+ -e "s|@IPV4_ADDRESS1@|${IPV4_ADDRESS1}|g" \
+ -e "s|@IPV4_ADDRESS1_PART1@|${IPV4_ADDRESS1_PART1}|g" \
+ -e "s|@IPV4_ADDRESS1_PART2@|${IPV4_ADDRESS1_PART2}|g" \
+ -e "s|@IPV4_ADDRESS1_PART3@|${IPV4_ADDRESS1_PART3}|g" \
+ -e "s|@IPV4_ADDRESS1_PART4@|${IPV4_ADDRESS1_PART4}|g" \
+ -e "s|@IPV6_ADDRESS1@|${IPV6_ADDRESS1}|g" \
+ "${FILE}" >> "${DIRECTORY}/preseed.cfg"
+ done
+
+ Chroot "${DIRECTORY}" "debconf-set-selections preseed.cfg"
+
+ rm -f "${DIRECTORY}/preseed.cfg"
+ fi
+
+ # Manual hack to workaround broken preseeding in locales package
+ if [ -n "${PRESEED_FILE}" ]
+ then
+ for FILE in ${PRESEED_FILE}
+ do
+ if grep -qs locales "${FILE}"
+ then
+ if Chroot "${DIRECTORY}" dpkg --get-selections | awk '{ print $1 }' | grep -qs '^locales$'
+ then
+ rm -f "${DIRECTORY}/etc/default/locale" "${DIRECTORY}/etc/locale.gen"
+ Chroot "${DIRECTORY}" "DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=criticial dpkg-reconfigure locales"
+
+ break
+ fi
+ fi
+ done
+ fi
+
+ # Manual hack to create conffiles when using locales-all instead of locales
+ if [ ! -e "${DIRECTORY}/etc/environment" ]
+ then
+ echo "LANG=C.UTF-8" >> "${DIRECTORY}/etc/environment"
+ fi
+
+ if [ ! -e "${DIRECTORY}/etc/default/locale" ]
+ then
+ echo "LANG=C.UTF-8" >> "${DIRECTORY}/etc/default/locale"
+ fi
+
+ # Manual hack to workaround broken preseeding in tzdata package
+ if [ -n "${PRESEED_FILE}" ]
+ then
+ for FILE in ${PRESEED_FILE}
+ do
+ if grep -qs tzdata "${FILE}"
+ then
+ rm -f "${DIRECTORY}/etc/localtime" "${DIRECTORY}/etc/timezone"
+ Chroot "${DIRECTORY}" "DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=criticial dpkg-reconfigure tzdata"
+
+ break
+ fi
+ done
+ fi
+
+ if [ -n "${PACKAGES}" ]
+ then
+ Chroot "${DIRECTORY}" "apt --option Dpkg::Options::=--force-confnew --yes install ${PACKAGES}"
+ fi
+
+ # Manual hack to regenerate ssh keys
+ if Chroot "${DIRECTORY}" dpkg --get-selections | awk '{ print $1 }' | grep -qs '^openssh-server$' && \
+ ! ls "${DIRECTORY}"/etc/ssh/ssh_host_*_key > /dev/null 2>&1
+ then
+ Chroot "${DIRECTORY}" "DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=criticial dpkg-reconfigure openssh-server"
+ fi
+
+ # container command
+ if [ -n "${CONTAINER_COMMAND}" ]
+ then
+ echo "${CONTAINER_COMMAND}" > "${DIRECTORY}/.container-command"
+
+ chmod 0755 "${DIRECTORY}/.container-command"
+ Chroot "${DIRECTORY}" "sh /.container-command"
+
+ rm -f "${DIRECTORY}/.container-command"
+ fi
+
+ for NUMBER in $(seq 1 ${CONTAINER_COMMAND_NUMBER})
+ do
+ eval COMMAND="$`echo CONTAINER_COMMAND${NUMBER}`"
+
+ echo "${COMMAND}" > "${DIRECTORY}/.container-command"
+
+ chmod 0755 "${DIRECTORY}/.container-command"
+ Chroot "${DIRECTORY}" "sh /.container-command"
+
+ rm -f "${DIRECTORY}/.container-command"
+ done
+}
+
+Configure_network ()
+{
+ DIRECTORY="${1}"
+
+ # Create /etc/resolv.conf
+ rm -f "${DIRECTORY}/etc/resolv.conf.tmp"
+
+ if [ -n "${NAMESERVER_DOMAIN}" ]
+ then
+ echo "domain ${NAMESERVER_DOMAIN}" >> "${DIRECTORY}/etc/resolv.conf.tmp"
+ fi
+
+ if [ -n "${NAMESERVER_SEARCH}" ]
+ then
+ echo "search ${NAMESERVER_SEARCH}" >> "${DIRECTORY}/etc/resolv.conf.tmp"
+ fi
+
+ if [ -n "${NAMESERVER_SERVER}" ]
+ then
+ if [ -e "${DIRECTORY}/etc/resolv.conf.tmp" ]
+ then
+ echo "" >> "${DIRECTORY}/etc/resolv.conf.tmp"
+ fi
+
+ for NAMESERVER in $(echo ${NAMESERVER_SERVER} | sed -e 's|,| |g')
+ do
+ echo "nameserver ${NAMESERVER}" >> "${DIRECTORY}/etc/resolv.conf.tmp"
+ done
+ fi
+
+ if [ -n "${NAMESERVER_OPTIONS}" ]
+ then
+ if [ -e "${DIRECTORY}/etc/resolv.conf.tmp" ]
+ then
+ echo "" >> "${DIRECTORY}/etc/resolv.conf.tmp"
+ fi
+
+ echo "options ${NAMESERVER_OPTIONS}" >> "${DIRECTORY}/etc/resolv.conf.tmp"
+ fi
+
+ if [ -e "${DIRECTORY}/etc/resolv.conf.tmp" ]
+ then
+ mv "${DIRECTORY}/etc/resolv.conf.tmp" "${DIRECTORY}/etc/resolv.conf"
+ fi
+
+ # Create /etc/hosts
+ rm -f "${DIRECTORY}/etc/hosts.tmp"
+
+ if [ -n "${NETWORK1_IPV4_ADDRESS}" ]
+ then
+
+cat >> "${DIRECTORY}/etc/hosts.tmp" << EOF
+${NETWORK1_IPV4_ADDRESS} ${NAME}
+EOF
+
+ fi
+
+ if [ -n "${NETWORK1_IPV6_ADDRESS}" ]
+ then
+
+cat >> "${DIRECTORY}/etc/hosts.tmp" << EOF
+${NETWORK1_IPV6_ADDRESS} ${NAME}
+EOF
+
+ fi
+
+ if [ -n "${NETWORK1_IPV4_ADDRESS}" ] || [ -n "${NETWORK1_IPV6_ADDRESS}" ]
+ then
+ echo >> "${DIRECTORY}/etc/hosts.tmp"
+ fi
+
+ if [ -z "${NETWORK1_IPV4_ADDRESS}" ] && [ -z "${NETWORK1_IPV6_ADDRESS}" ]
+ then
+ # localhost only
+
+cat > "${DIRECTORY}/etc/hosts.tmp" << EOF
+127.0.0.1 localhost ${NAME}
+::1 localhost ${NAME}
+EOF
+
+ else
+
+cat > "${DIRECTORY}/etc/hosts.tmp" << EOF
+127.0.0.1 localhost
+::1 localhost
+EOF
+
+ fi
+
+cat >> "${DIRECTORY}/etc/hosts.tmp" << EOF
+
+# The following lines are desirable for IPv6 capable hosts
+::1 ip6-localhost ip6-loopback
+fe00::0 ip6-localnet
+ff00::0 ip6-mcastprefix
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
+EOF
+
+ mv "${DIRECTORY}/etc/hosts.tmp" "${DIRECTORY}/etc/hosts"
+}
+
+Configure_systemd_networkd ()
+{
+ DIRECTORY="${1}"
+
+ # Enable systemd-networkd
+ chroot "${DIRECTORY}" systemctl enable systemd-networkd
+
+ for NUMBER in $(seq 1 ${NETWORK_NUMBER})
+ do
+ eval IPV4_COMMENT="$`echo NETWORK${NUMBER}_IPV4_COMMENT`"
+ eval IPV4_METHOD="$`echo NETWORK${NUMBER}_IPV4_METHOD`"
+ eval IPV4_ADDRESS="$`echo NETWORK${NUMBER}_IPV4_ADDRESS`"
+ eval IPV4_GATEWAY="$`echo NETWORK${NUMBER}_IPV4_GATEWAY`"
+ eval IPV4_NETMASK="$`echo NETWORK${NUMBER}_IPV4_NETMASK`"
+ eval IPV4_POST_UP="$`echo NETWORK${NUMBER}_IPV4_POST_UP`"
+ eval IPV4_POST_DOWN="$`echo NETWORK${NUMBER}_IPV4_POST_DOWN`"
+
+ eval IPV6_COMMENT="$`echo NETWORK${NUMBER}_IPV6_COMMENT`"
+ eval IPV6_METHOD="$`echo NETWORK${NUMBER}_IPV6_METHOD`"
+ eval IPV6_ADDRESS="$`echo NETWORK${NUMBER}_IPV6_ADDRESS`"
+ eval IPV6_GATEWAY="$`echo NETWORK${NUMBER}_IPV6_GATEWAY`"
+ eval IPV6_NETMASK="$`echo NETWORK${NUMBER}_IPV6_NETMASK`"
+ eval IPV6_POST_UP="$`echo NETWORK${NUMBER}_IPV6_POST_UP`"
+ eval IPV6_POST_DOWN="$`echo NETWORK${NUMBER}_IPV6_POST_DOWN`"
+
+ if [ "${IPV4_METHOD}" != "none" ] || [ "${IPV6_METHOD}" != "none" ]
+ then
+
+cat > "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+[Match]
+Name=eno${NUMBER}
+EOF
+
+ fi
+
+ if [ -n "${IPV4_METHOD}" ] && [ "${IPV4_METHOD}" != "none" ]
+ then
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+
+[Network]
+EOF
+
+ if [ -n "${IPV4_COMMENT}" ]
+ then
+ echo "Description=${IPV4_COMMENT}" >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network"
+ fi
+
+ case "${IPV4_METHOD}" in
+ dhcp)
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+DHCP=ipv4
+EOF
+
+ ;;
+
+ static)
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+DHCP=no
+Address=${IPV4_ADDRESS}/${IPV4_NETMASK}
+EOF
+
+ if [ -n "${IPV4_GATEWAY}" ]
+ then
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+Gateway=${IPV4_GATEWAY}
+EOF
+
+ fi
+ ;;
+
+ stub)
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+DHCP=no
+EOF
+
+ ;;
+ esac
+
+ if [ -n "${IPV4_POST_UP}" ]
+ then
+
+cat > "${DIRECTORY}/etc/systemd/system/cnt-ipv4-post-up-eno${NUMBER}.service" << EOF
+[Unit]
+Description=${SOFTWARE} IPV4_POST_UP
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -c "${IPV4_POST_UP}"
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ chroot "${DIRECTORY}" systemctl enable cnt-ipv4-post-up-eno${NUMBER}.service
+ fi
+
+ if [ -n "${IPV4_POST_DOWN}" ]
+ then
+
+cat > "${DIRECTORY}/etc/systemd/system/cnt-ipv4-post-down-eno${NUMBER}.service" << EOF
+[Unit]
+Description=${SOFTWARE} IPV4_POST_DOWN
+After=network.target
+Wants=network.target
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -c "${IPV4_POST_DOWN}"
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ chroot "${DIRECTORY}" systemctl enable cnt-ipv4-post-down-eno${NUMBER}.service
+ fi
+ fi
+
+ if [ -n "${IPV6_METHOD}" ] && [ "${IPV6_METHOD}" != "none" ]
+ then
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+
+[Network]
+EOF
+
+ if [ -n "${IPV6_COMMENT}" ]
+ then
+ echo "Description=${IPV6_COMMENT}" >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network"
+ fi
+
+ case "${IPV6_METHOD}" in
+ dhcp)
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+DHCP=ipv6
+EOF
+
+ ;;
+
+ static)
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+DHCP=no
+IPv6AcceptRA=no
+Address=${IPV6_ADDRESS}/${IPV6_NETMASK}
+EOF
+
+ if [ -n "${IPV6_GATEWAY}" ]
+ then
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+Gateway=${IPV6_GATEWAY}
+EOF
+
+ fi
+ ;;
+
+ stub)
+
+cat >> "${DIRECTORY}/etc/systemd/network/eno${NUMBER}.network" << EOF
+DHCP=no
+IPv6AcceptRA=no
+EOF
+
+ ;;
+ esac
+
+ if [ -n "${IPV6_POST_UP}" ]
+ then
+
+cat > "${DIRECTORY}/etc/systemd/system/cnt-ipv6-post-up-eno${NUMBER}.service" << EOF
+[Unit]
+Description=${SOFTWARE} IPV6_POST_UP
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -c "${IPV6_POST_UP}"
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ chroot "${DIRECTORY}" systemctl enable cnt-ipv6-post-up-eno${NUMBER}.service
+ fi
+
+ if [ -n "${IPV6_POST_DOWN}" ]
+ then
+
+cat > "${DIRECTORY}/etc/systemd/system/cnt-ipv6-post-down-eno${NUMBER}.service" << EOF
+[Unit]
+Description=${SOFTWARE} IPV6_POST_DOWN
+After=network.target
+Wants=network.target
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -c "${IPV6_POST_DOWN}"
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ chroot "${DIRECTORY}" systemctl enable cnt-ipv6-post-down-eno${NUMBER}.service
+ fi
+ fi
+
+ NUMBER="$((${NUMBER} + 1))"
+ done
+}
+
+Commands ()
+{
+ DIRECTORY="${1}"
+
+ # maximum of 15 characters, prefix is 'veth-'
+ HOSTNAME_SHORT="$(echo ${NAME} | cut -c-8)"
+ HOST_INTERFACE_NAME="$(echo ${NETWORK1_VETH:-veth-${HOSTNAME_SHORT}-0})"
+
+ sed -i -e "s|^cnt.auto=.*|cnt.auto=${CNT_AUTO}|g" \
+ -e "s|^cnt.container-server=.*|cnt.container-server=${CNT_CONTAINER_SERVER}|g" \
+ -e "s|^cnt.network-bridge=.*|cnt.network-bridge=${HOST_INTERFACE_NAME}:${NETWORK1_BRIDGE:-bridge0}|g" \
+ -e "s|^cnt.overlay=.*|cnt.overlay=${CNT_OVERLAY}|g" \
+ -e "s|^cnt.overlay-options=.*|cnt.overlay-options=${CNT_OVERLAY_OPTIONS}|g" \
+ -e "s|^bind=.*|bind=${BIND}|g" \
+ -e "s|^bind-ro=.*|bind-ro=${BIND_RO}|g" \
+ -e "s|^network-veth-extra=.*|network-veth-extra=${HOST_INTERFACE_NAME}:eno1|g" \
+ "${CONFIG}/${NAME}.conf"
+
+ if [ "${NETWORK_NUMBER}" -ge 2 ]
+ then
+ for NUMBER in $(seq 2 ${NETWORK_NUMBER})
+ do
+ eval IPV4_METHOD="$`echo NETWORK${NUMBER}_IPV4_METHOD`"
+ eval IPV6_METHOD="$`echo NETWORK${NUMBER}_IPV6_METHOD`"
+
+ if [ -z "${IPV4_METHOD}" ] && [ -z "${IPV6_METHOD}" ]
+ then
+ continue
+ fi
+
+ eval HOST_INTERFACE_NAME="$`echo NETWORK${NUMBER}_VETH`"
+
+ HOST_INTERFACE_NAME="$(echo ${HOST_INTERFACE_NAME:-veth-${HOSTNAME_SHORT}-${NUMBER}})"
+ CONTAINER_INTERFACE_NAME="eno${NUMBER}"
+
+ sed -i -e "/^register=.*/ a network-veth-extra=${HOST_INTERFACE_NAME}:${CONTAINER_INTERFACE_NAME}" "${CONFIG}/${NAME}.conf"
+
+ eval BRIDGE="$`echo NETWORK${NUMBER}_BRIDGE`"
+ sed -i -e "/^register=.*/ a cnt.network-bridge=${HOST_INTERFACE_NAME}:${BRIDGE:-bridge${NUMBER}}" "${CONFIG}/${NAME}.conf"
+ done
+ fi
+
+ # Setting root password
+ echo root:${ROOT_PASSWORD} | chroot "${DIRECTORY}" chpasswd
+
+ # Host command
+ if [ -n "${HOST_COMMAND}" ]
+ then
+ echo "${HOST_COMMAND}" > "${DIRECTORY}/.host-command"
+
+ cd "${DIRECTORY}"
+ sh "${DIRECTORY}/.host-command"
+ cd "${OLDPWD}"
+
+ rm -f "${DIRECTORY}/.host-command"
+ fi
+
+ for NUMBER in $(seq 1 ${HOST_COMMAND_NUMBER})
+ do
+ eval COMMAND="$`echo HOST_COMMAND${NUMBER}`"
+
+ echo "${COMMAND}" > "${DIRECTORY}/.host-command"
+
+ cd "${DIRECTORY}"
+ sh "${DIRECTORY}/.host-command"
+ cd "${OLDPWD}"
+
+ rm -f "${DIRECTORY}/.host-command"
+ done
+
+ # Show root password in case its automatically set
+ case "${ROOT_RANDOM_PASSWORD}" in
+ true)
+ echo "${NAME}: root password set to '${ROOT_PASSWORD}'."
+ ;;
+ esac
+}
+
+# Trap function
+trap 'Umount' EXIT HUP INT QUIT TERM
+
+umask 0022
+
+export NAME
+
+Debconf
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${SCRIPT}".* "${HOOKS}/${NAME}.pre-${SCRIPT}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run debconf parts
+for DEBCONF_SCRIPT in "/usr/share/${SOFTWARE}/build-scripts/debconf.d"/*
+do
+ if [ -x "${DEBCONF_SCRIPT}" ]
+ then
+ "${DEBCONF_SCRIPT}"
+ fi
+done
+
+# Read-in configuration from debconf
+. "${DEBCONF_TMPDIR}/debconf.default"
+
+SYSTEM="${MACHINES}/${NAME}"
+
+if [ -z "${IMAGE}" ] && [ -z "${IMAGE1}" ]
+then
+ INSTALLER="bootstrap"
+else
+ INSTALLER="image"
+fi
+
+case "${INSTALLER}" in
+ bootstrap)
+ ## Dependencies
+ if [ -x /usr/bin/mmdebstrap ]
+ then
+ BOOTSTRAP="mmdebstrap"
+ elif [ -x /usr/sbin/debootstrap ]
+ then
+ BOOTSTRAP="debootstrap"
+ else
+ echo "'${NAME}': /usr/bin/mmdebstrap or /usr/sbin/debootstrap - no such file." >&2
+ exit 1
+ fi
+
+ ## Generic parts
+ if [ ! -e "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" ]
+ then
+ Bootstrap "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}.tmp"
+ Configure_apt "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}.tmp"
+ Deconfigure_system "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}.tmp"
+
+ mv "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}.tmp" "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}"
+ fi
+
+ Upgrade_system "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" || echo "W: If upgrading the system failed, try removing the cache for your distribution in /var/cache/${PROGRAM}"
+ Cleanup_system "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}"
+
+ ## Specific parts
+ mkdir -p "${MACHINES}"
+ cp -a "${CACHE}/${DISTRIBUTION}_${ARCHITECTURE}" "${MACHINES}/${NAME}"
+ ;;
+
+ image)
+ ## Dependencies
+ if [ -x /usr/bin/curl ]
+ then
+ GET="curl"
+ elif [ -x /usr/bin/wget ]
+ then
+ GET="wget"
+ else
+ echo "'${NAME}': /usr/bin/curl or /usr/bin/wget - no such file." >&2
+ exit 1
+ fi
+
+ COMPRESSIONS=""
+
+ if [ -x /usr/bin/lzip ]
+ then
+ COMPRESSIONS="${COMPRESSIONS} lz"
+ fi
+
+ if [ -x /usr/bin/xz ]
+ then
+ COMPRESSIONS="${COMPRESSIONS} xz"
+ fi
+
+ if [ -x /bin/gzip ]
+ then
+ COMPRESSIONS="${COMPRESSIONS} gz"
+ fi
+
+ if [ -z "${COMPRESSIONS}" ]
+ then
+ echo "'${NAME}': no supported compressor available (lz, xz, gz)."
+ exit 1
+ fi
+
+ ## Parts
+ mkdir -p "${MACHINES}"
+ Image "${MACHINES}/${NAME}"
+
+ Configure_apt "${MACHINES}/${NAME}"
+ Deconfigure_system "${MACHINES}/${NAME}"
+ ;;
+esac
+
+Mount
+
+Configure_system "${MACHINES}/${NAME}"
+Configure_network "${MACHINES}/${NAME}"
+Configure_systemd_networkd "${MACHINES}/${NAME}"
+Cleanup_system "${MACHINES}/${NAME}"
+
+Commands "${MACHINES}/${NAME}"
+
+# remove debconf temporary files
+rm --preserve-root --one-file-system -rf "${DEBCONF_TMPDIR}"
+rmdir --ignore-fail-on-non-empty "/tmp/${SOFTWARE}" 2>&1 || true
+
+# Post hooks
+for FILE in "${HOOKS}/post-${SCRIPT}".* "${HOOKS}/${NAME}.post-${SCRIPT}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/share/build-scripts/debconf.d/0001-preseed-file b/share/build-scripts/debconf.d/0001-preseed-file
new file mode 100755
index 0000000..aa2c3c7
--- /dev/null
+++ b/share/build-scripts/debconf.d/0001-preseed-file
@@ -0,0 +1,131 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+CONFIG="/etc/${SOFTWARE}/config"
+DEBCONF="/etc/${SOFTWARE}/debconf"
+
+DEBCONF_NOWARNINGS="true"
+export DEBCONF_NOWARNINGS
+
+. /usr/share/debconf/confmodule
+
+# debconf template hierarchy (first match wins):
+#
+# 1. user specified a preseed file through commandline options
+# 2. /etc/compute-tools/debconf/${NAME}.cfg exists
+# 3. /etc/compute-tools/debconf/links/${NAME}.cfg exists
+# 4. /etc/compute-tools/debconf/*/${NAME}.cfg exists (only one file!)
+# 5. /etc/compute-tools/debconf/default.cfg exists
+# 6. user chooses from list of available (if any) *.cfg files
+# (recursively) found in /etc/compute-tools/debconf,
+# /etc/compute-tools/debconf/links is excluded.
+
+if [ -n "${PRESEED_FILE}" ]
+then
+ # user specified one or more preseed files through commandline option
+ db_set container/preseed-file "${PRESEED_FILE}"
+ db_fset container/preseed-file seen true
+elif [ -e "${DEBCONF}/${NAME}.cfg" ]
+then
+ # user did not specify a pressed file, but there is a matching one
+ # available on the system matching the container name
+ db_set container/preseed-file "${DEBCONF}/${NAME}.cfg"
+ db_fset container/preseed-file seen true
+elif [ -e "${DEBCONF}/links/${NAME}.cfg" ]
+then
+ # user did not specify a pressed file, but there is a matching one
+ # in /etc/${SOFTWARE}/debconf/links directory
+ db_set container/preseed-file "${DEBCONF}/links/${NAME}.cfg"
+ db_fset container/preseed-file seen true
+elif [ "$(ls ${DEBCONF}/*/${NAME}.cfg 2>/dev/null | wc -l)" -eq 1 ]
+then
+ # user did not specify a pressed file, but there is 1 (and only 1)
+ # matching in a sub-directory of /etc/${SOFTWARE}/debconf
+
+ FILE="$(ls ${DEBCONF}/*/${NAME}.cfg)"
+
+ db_set container/preseed-file "${FILE}"
+ db_fset container/preseed-file seen true
+elif [ -e "${DEBCONF}/default.cfg" ]
+then
+ # user did not specify a pressed file, but there is a default one
+ db_set container/preseed-file "${DEBCONF}/default.cfg"
+ db_fset container/preseed-file seen true
+elif ls "${DEBCONF}"/*.cfg > /dev/null 2>&1 || ls "${DEBCONF}"/*/*.cfg > /dev/null 2>&1
+then
+ # user has not specified preseed files through commandline option,
+ # showing debconf selection dialog for global preseed file.
+
+ FILES="$(cd ${DEBCONF} && find . -type f -name '*.cfg' -printf '%P\n' | grep -v '^links\/' | LC_ALL=C sort -V)"
+ PRESEED_FILES="$(for FILE in ${FILES}; do echo -n "$(echo ${FILE} | sed -e 's|.cfg$||'), "; done | sed -e 's|, $||')"
+
+ if [ -n "${PRESEED_FILES}" ]
+ then
+ db_subst container/preseed-files CHOICES "custom, exit, none, , ${PRESEED_FILES}"
+
+ db_settitle container/title
+ db_input high container/preseed-files || true
+ db_go
+
+ db_get container/preseed-files
+ PRESEED_FILE="${RET}" # select
+
+ case "${PRESEED_FILE}" in
+ custom|none)
+ ;;
+
+ exit)
+ rm -f "${CONFIG}/${NAME}.conf"
+ exit 1
+ ;;
+
+ *)
+ # user specified preseed file through debconf select
+ db_set container/preseed-file "${DEBCONF}/${PRESEED_FILE}.cfg"
+ db_fset container/preseed-file seen true
+ ;;
+ esac
+ fi
+fi
+
+case "${PRESEED_FILE}" in
+ none)
+ ;;
+
+ *)
+ # ask user for a preseed file
+ db_settitle container/title
+ db_input high container/preseed-file || true
+ db_go
+
+ db_get container/preseed-file
+ PRESEED_FILE="${RET}" # string (w/ empty)
+
+ echo "PRESEED_FILE=\"${PRESEED_FILE}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PRESEED_FILE
+ ;;
+esac
+
+db_stop
diff --git a/share/build-scripts/debconf.d/0001-preseed-file.templates b/share/build-scripts/debconf.d/0001-preseed-file.templates
new file mode 100644
index 0000000..9be825d
--- /dev/null
+++ b/share/build-scripts/debconf.d/0001-preseed-file.templates
@@ -0,0 +1,18 @@
+Template: container/title
+Type: title
+Description: compute-tools
+
+Template: container/preseed-files
+Type: select
+Default: none
+Choices: ${CHOICES}
+Description: Choose a preseed config, enter a custom one, or use no preseed file at all.
+
+Template: container/preseed-file
+Type: string
+Default:
+Description: Enter (optional) preseed file to use:
+ A preseed file can be used to automatically answer questions to this
+ container build script.
+ .
+ If you do not want to use a preseed file, leave this question empty.
diff --git a/share/build-scripts/debconf.d/0002-preseed-debconf b/share/build-scripts/debconf.d/0002-preseed-debconf
new file mode 100755
index 0000000..fcb9006
--- /dev/null
+++ b/share/build-scripts/debconf.d/0002-preseed-debconf
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+if [ -e "${DEBCONF_TMPDIR}/debconf.default" ]
+then
+ . "${DEBCONF_TMPDIR}/debconf.default"
+fi
+
+if [ -z "${PRESEED_FILE}" ]
+then
+ # user has not specified or selected any preseed files
+ exit 0
+fi
+
+# user has one or more preseed file specified through commandline option
+# or debconf selection dialog.
+PRESEED_FILES="$(echo ${PRESEED_FILE} | sed -e 's|,| |g')"
+
+DEBCONF_PRESEED_FILES=""
+
+for PRESEED_FILE in ${PRESEED_FILES}
+do
+ if [ ! -e "${PRESEED_FILE}" ]
+ then
+ # preseed file does not exist
+ echo "W: ${PRESEED_FILE}: No such file."
+
+ continue
+ fi
+
+ # add preseed file to debconf
+ DEBCONF_PRESEED_FILES="${DEBCONF_PRESEED_FILES} ${PRESEED_FILE}"
+
+ if ! grep -qs '^ *compute-tools *container/include-preseed-files' "${PRESEED_FILE}"
+ then
+ # preseed file has no includes
+ continue
+ fi
+
+ # preseed file has includes
+ INCLUDE_PRESEED_FILES="$(grep '^ *compute-tools *container/include-preseed-files' ${PRESEED_FILE} | awk '{ $1=$2=$3=""; print $0 }' | sed -e 's|,| |g')"
+
+ # only one include layer is supported, no nested/recursive includes
+ for FILE in ${INCLUDE_PRESEED_FILES}
+ do
+ if [ -e "${FILE}" ]
+ then
+ DEBCONF_PRESEED_FILES="${FILE} ${DEBCONF_PRESEED_FILES}"
+ else
+ # included preseed file does not exist
+ echo "W: ${INCLUDE_PRESEED_FILE}: No such file - included from ${PRESEED_FILE}"
+ fi
+ done
+done
+
+for DEBCONF_PRESEED_FILE in ${DEBCONF_PRESEED_FILES}
+do
+ if [ -e /usr/bin/kdig ]
+ then
+ DIG="/usr/bin/kdig"
+ elif [ -e /usr/bin/dig ]
+ then
+ DIG="/usr/bin/dig"
+ fi
+
+ if [ -n "${DIG}" ]
+ then
+ IPV4_ADDRESS1="$(${DIG} A +short ${NAME} | tail -n1)"
+ IPV4_ADDRESS1_PART1="$(echo ${IPV4_ADDRESS1} | cut -d. -f1)"
+ IPV4_ADDRESS1_PART2="$(echo ${IPV4_ADDRESS1} | cut -d. -f2)"
+ IPV4_ADDRESS1_PART3="$(echo ${IPV4_ADDRESS1} | cut -d. -f3)"
+ IPV4_ADDRESS1_PART4="$(echo ${IPV4_ADDRESS1} | cut -d. -f4)"
+
+ IPV6_ADDRESS1="$(${DIG} AAAA +short ${NAME} | tail -n1)"
+ fi
+
+ sed -e "s|@NAME@|${NAME}|g" \
+ -e "s|@IPV4_ADDRESS1@|${IPV4_ADDRESS1}|g" \
+ -e "s|@IPV4_ADDRESS1_PART1@|${IPV4_ADDRESS1_PART1}|g" \
+ -e "s|@IPV4_ADDRESS1_PART2@|${IPV4_ADDRESS1_PART2}|g" \
+ -e "s|@IPV4_ADDRESS1_PART3@|${IPV4_ADDRESS1_PART3}|g" \
+ -e "s|@IPV4_ADDRESS1_PART4@|${IPV4_ADDRESS1_PART4}|g" \
+ -e "s|@IPV6_ADDRESS1@|${IPV6_ADDRESS1}|g" \
+ "${DEBCONF_PRESEED_FILE}" > "${DIRECTORY}/preseed.cfg"
+
+ # Apply user specified preseed files
+ debconf-set-selections "${DIRECTORY}/preseed.cfg"
+
+ rm -f "${DIRECTORY}/preseed.cfg"
+done
+
+# Write expanded list of debconf preseed files
+echo "PRESEED_FILE=\"${DEBCONF_PRESEED_FILES}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
diff --git a/share/build-scripts/debconf.d/0003-debconf b/share/build-scripts/debconf.d/0003-debconf
new file mode 100755
index 0000000..e12e25e
--- /dev/null
+++ b/share/build-scripts/debconf.d/0003-debconf
@@ -0,0 +1,1371 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+DEBCONF_NOWARNINGS="true"
+export DEBCONF_NOWARNINGS
+
+. /usr/share/debconf/confmodule
+
+Mode ()
+{
+ db_get container/mode
+ MODE="${RET}" # select
+
+ if [ -z "${MODE}" ]
+ then
+ MODE="$(basename ${SCRIPT})"
+
+ case "${MODE}" in
+ debconf)
+ MODE="debian"
+ ;;
+ esac
+ fi
+
+ echo "MODE=\"${MODE}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export MODE
+}
+
+Images ()
+{
+ if db_get container/image && [ "${RET}" ]
+ then
+ db_get container/image
+ IMAGE="${RET}" # string (w/o empty)
+
+ echo "IMAGE=\"${IMAGE}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ fi
+
+ NUMBER="1"
+
+ while db_get container/image${NUMBER} && [ "${RET}" ]
+ do
+ if db_get container/image${NUMBER}
+ then
+ eval IMAGE${NUMBER}="\"${RET}\"" # string (w/o empty)
+ fi
+
+ NUMBER="$((${NUMBER} + 1))"
+ done
+
+ IMAGE_NUMBER="$((${NUMBER} - 1))"
+
+ echo "IMAGE_NUMBER=\"${IMAGE_NUMBER}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ for NUMBER in $(seq 1 ${IMAGE_NUMBER})
+ do
+ eval IMAGE="$`echo IMAGE${NUMBER}`"
+ echo "IMAGE${NUMBER}=\"${IMAGE}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ done
+}
+
+Distribution ()
+{
+ db_get container/distribution
+ DISTRIBUTION="${RET}" # select
+
+ if [ -z "${DISTRIBUTION}" ]
+ then
+ case "${MODE}" in
+ debian)
+ db_subst container/distribution CHOICES "Debian GNU/Linux 10 \"buster\", Debian GNU/Linux 11 \"bullseye\", Debian GNU/Linux 12 \"bookworm\", Debian GNU/Linux testing, Debian GNU/Linux unstable/sid"
+ db_subst container/distribution CHOICES_C "buster, bullseye, bookworm, testing, sid"
+
+ db_set container/distribution bookworm
+ db_fset container/distribution seen false
+ ;;
+
+ progress-linux)
+ db_subst container/distribution CHOICES "Progress Linux 5 (engywuck), Progress Linux 5.99 (engywuck-backports), Progress Linux 6 (fuchur), Progress Linux 6.99 (fuchur-backports), Progress Linux 7 (graograman), Progress Linux 7.99 (graograman-backports)"
+ db_subst container/distribution CHOICES_C "engywuck, engywuck-backports, fuchur, fuchur-backports, graograman, graograman-backports"
+
+ db_set container/distribution graograman-backports
+ db_fset container/distribution seen false
+ ;;
+ esac
+
+ db_settitle container/title
+ db_input high container/distribution || true
+ db_go
+
+ db_get container/distribution
+ DISTRIBUTION="${RET}" # select
+ fi
+
+ echo "DISTRIBUTION=\"${DISTRIBUTION}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export DISTRIBUTION
+}
+
+Parent_distribution ()
+{
+ db_get container/parent-distribution
+ PARENT_DISTRIBUTION="${RET}"
+
+ if [ -z "${PARENT_DISTRIBUTION}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ case "${DISTRIBUTION}" in
+ engywuck*)
+ PARENT_DISTRIBUTION="buster"
+ ;;
+
+ fuchur*)
+ PARENT_DISTRIBUTION="bullseye"
+ ;;
+
+ graograman*)
+ PARENT_DISTRIBUTION="bookworm"
+ ;;
+ esac
+ ;;
+
+ *)
+ PARENT_DISTRIBUTION="${DISTRIBUTION}"
+ ;;
+ esac
+ fi
+
+ echo "PARENT_DISTRIBUTION=\"${PARENT_DISTRIBUTION}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PARENT_DISTRIBUTION
+}
+
+Architecture ()
+{
+ case "$(dpkg --print-architecture)" in
+ amd64)
+ DEFAULT="amd64"
+ CHOICES="Automatic, 32-bit PC (i386), 64-bit PC (amd64)"
+ CHOICES_C="auto, i386, amd64"
+ ;;
+
+ arm64)
+ DEFAULT="arm64"
+ CHOICES="Automatic, RaspberryPi 3 and newer (arm64)"
+ CHOICES_C="auto, arm64"
+ ;;
+
+ i386)
+ case "$(uname -m)" in
+ x86_64)
+ DEFAULT="amd64"
+ CHOICES="Automatic, 32-bit PC (i386), 64-bit PC (amd64)"
+ CHOICES_C="auto, i386, amd64"
+ ;;
+
+ *)
+ DEFAULT="i386"
+ CHOICES=""
+ CHOICES_C=""
+ ;;
+ esac
+ ;;
+
+ *)
+ echo "E: Architecture current not yet supported."
+ exit 1
+ esac
+
+ db_get container/architecture
+ ARCHITECTURE="${RET}" # select
+
+ if [ -z "${ARCHITECTURE}" ] && [ -n "${CHOICES}" ]
+ then
+ db_subst container/architecture CHOICES ${CHOICES}
+ db_subst container/architecture CHOICES_C ${CHOICES_C}
+
+ db_set container/architecture ${DEFAULT}
+ db_fset container/distribution seen false
+
+ db_settitle container/title
+ db_input high container/architecture || true
+ db_go
+
+ db_get container/architecture
+ ARCHITECTURE="${RET}" # select
+ fi
+
+ case "${ARCHITECTURE}" in
+ auto)
+ ARCHITECTURE="${DEFAULT}"
+ ;;
+ esac
+
+ echo "ARCHITECTURE=\"${ARCHITECTURE}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export ARCHITECTURE
+}
+
+Archives ()
+{
+ db_get container/archives
+ ARCHIVES="${RET}" # multiselect
+
+ if [ -z "${ARCHIVES}" ]
+ then
+ case "${MODE}" in
+ debian)
+ case "${PARENT_DISTRIBUTION}" in
+ sid)
+ db_subst container/archives CHOICES "sid, experimental"
+
+ db_set container/archives "sid"
+ db_fset container/archives seen false
+ ;;
+
+ *)
+ db_subst container/archives CHOICES "${DISTRIBUTION}, ${DISTRIBUTION}-security, ${DISTRIBUTION}-updates, ${DISTRIBUTION}-backports, ${DISTRIBUTION}-proposed-updates"
+
+ case "${PARENT_DISTRIBUTION}" in
+ sid)
+ db_set container/archives "sid"
+ ;;
+
+ *)
+ db_set container/archives "${DISTRIBUTION}, ${DISTRIBUTION}-security, ${DISTRIBUTION}-updates"
+ ;;
+ esac
+
+ db_fset container/archives seen false
+ ;;
+ esac
+ ;;
+
+ progress-linux)
+ DIST="$(echo ${DISTRIBUTION} | sed -e 's|-backports||')"
+
+ db_subst container/archives CHOICES "${DIST}, ${DIST}-security, ${DIST}-updates, ${DIST}-extras, ${DIST}-backports, ${DIST}-backports-extras"
+
+ db_set container/archives "${DIST}, ${DIST}-security, ${DIST}-updates, ${DIST}-extras, ${DIST}-backports, ${DIST}-backports-extras"
+ db_fset container/archives seen false
+ ;;
+ esac
+
+ db_settitle container/title
+ db_input high container/archives || true
+ db_go
+
+ db_get container/archives
+ ARCHIVES="${RET}" # multiselect
+ fi
+
+ ARCHIVES="$(echo ${ARCHIVES} | sed -e 's|, | |g')"
+
+ echo "ARCHIVES=\"${ARCHIVES}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export ARCHIVES
+}
+
+Parent_archives ()
+{
+ db_get container/parent-archives
+ PARENT_ARCHIVES="${RET}" # multiselect (w/o empty)
+
+ if [ -z "${PARENT_ARCHIVES}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ db_subst container/parent-archives CHOICES "${PARENT_DISTRIBUTION}, ${PARENT_DISTRIBUTION}-security, ${PARENT_DISTRIBUTION}-updates, ${PARENT_DISTRIBUTION}-backports, ${PARENT_DISTRIBUTION}-proposed-updates"
+
+ case "${PARENT_DISTRIBUTION}" in
+ *)
+ db_set container/parent-archives "${PARENT_DISTRIBUTION}, ${PARENT_DISTRIBUTION}-security, ${PARENT_DISTRIBUTION}-updates"
+ ;;
+ esac
+
+ db_fset container/parent-archives seen false
+
+ db_settitle container/title
+ db_input high container/parent-archives || true
+ db_go
+ ;;
+
+ *)
+ db_subst container/parent-archives CHOICES "${DISTRIBUTION}, ${DISTRIBUTION}-security, ${DISTRIBUTION}-updates, ${DISTRIBUTION}-backports, ${DISTRIBUTION}-proposed-updates"
+
+ db_set container/parent-archives "${ARCHIVES}"
+ db_fset container/parent-archives seen true
+ ;;
+ esac
+
+ db_get container/parent-archives
+ PARENT_ARCHIVES="${RET}" # multiselect (w/o empty)
+
+ if [ -z "${PARENT_ARCHIVES}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ case "${PARENT_DISTRIBUTION}" in
+ *)
+ PARENT_ARCHIVES="${PARENT_DISTRIBUTION}, ${PARENT_DISTRIBUTION}-security, ${PARENT_DISTRIBUTION}-updates"
+ ;;
+ esac
+ ;;
+
+ *)
+ PARENT_ARCHIVES="${ARCHIVES}"
+ ;;
+ esac
+ fi
+ fi
+
+ PARENT_ARCHIVES="$(echo ${PARENT_ARCHIVES} | sed -e 's|, | |g')"
+
+ echo "PARENT_ARCHIVES=\"${PARENT_ARCHIVES}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PARENT_ARCHIVES
+}
+
+Mirror ()
+{
+ db_get container/mirror
+ MIRROR="${RET}"
+
+ if [ -z "${MIRROR}" ]
+ then
+ case "${MODE}" in
+ debian)
+ db_set container/mirror https://deb.debian.org/debian
+ db_fset container/mirror seen false
+ ;;
+
+ progress-linux)
+ db_set container/mirror https://deb.progress-linux.org/packages
+ db_fset container/mirror seen false
+ ;;
+ esac
+
+ db_settitle container/title
+ db_input high container/mirror || true
+ db_go
+
+ db_get container/mirror
+ MIRROR="${RET}" # string (w/o empty)
+
+ if [ -z "${MIRROR}" ]
+ then
+ case "${MODE}" in
+ debian)
+ MIRROR="https://deb.debian.org/debian"
+ ;;
+
+ progress-linux)
+ MIRROR="https://deb.progress-linux.org/packages"
+ ;;
+ esac
+ fi
+ fi
+
+ echo "MIRROR=\"${MIRROR}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export MIRROR
+}
+
+Mirror_security ()
+{
+ if ! echo "${ARCHIVES}" | grep -qs "-security"
+ then
+ return 0
+ fi
+
+ db_get container/mirror-security
+ MIRROR_SECURITY="${RET}" # string (w/o empty)
+
+ if [ -z "${MIRROR_SECURITY}" ]
+ then
+ case "${MODE}" in
+ debian)
+ db_set container/mirror-security https://security.debian.org
+ db_fset container/mirror-security seen false
+ ;;
+
+ *)
+ db_set container/mirror-security ${MIRROR}
+ db_fset container/mirror-security seen true
+ ;;
+ esac
+
+ db_settitle container/title
+ db_input high container/mirror-security || true
+ db_go
+
+ db_get container/mirror-security
+ MIRROR_SECURITY="${RET}" # string (w/o empty)
+
+ if [ -z "${MIRROR_SECURITY}" ]
+ then
+ case "${MODE}" in
+ debian)
+ MIRROR_SECURITY="https://security.debian.org"
+ ;;
+
+ *)
+ MIRROR_SECURITY="${MIRROR}"
+ ;;
+ esac
+ fi
+ fi
+
+ echo "MIRROR_SECURITY=\"${MIRROR_SECURITY}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export MIRROR_SECURITY
+}
+
+Parent_mirror ()
+{
+ db_get container/parent-mirror
+ PARENT_MIRROR="${RET}" # string (w/o empty)
+
+ if [ -z "${PARENT_MIRROR}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ db_set container/parent-mirror https://deb.debian.org/debian
+ db_fset container/parent-mirror seen false
+
+ db_settitle container/title
+ db_input high container/parent-mirror || true
+ db_go
+ ;;
+
+ *)
+ db_set container/parent-mirror ${MIRROR}
+ db_fset container/parent-mirror seen true
+ ;;
+ esac
+
+ db_get container/parent-mirror
+ PARENT_MIRROR="${RET}" # string (w/o empty)
+
+ if [ -z "${PARENT_MIRROR}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ PARENT_MIRROR="https://deb.debian.org/debian"
+ ;;
+
+ *)
+ PARENT_MIRROR="${MIRROR}"
+ ;;
+ esac
+ fi
+ fi
+
+ echo "PARENT_MIRROR=\"${PARENT_MIRROR}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PARENT_MIRROR
+}
+
+Parent_mirror_security ()
+{
+ if ! echo "${PARENT_ARCHIVES}" | grep -qs "-security"
+ then
+ return 0
+ fi
+
+ db_get container/parent-mirror-security
+ PARENT_MIRROR_SECURITY="${RET}" # string (w/o empty)
+
+ if [ -z "${PARENT_MIRROR_SECURITY}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ db_set container/parent-mirror-security https://security.debian.org
+ db_fset container/parent-mirror-security seen false
+
+ db_settitle container/title
+ db_input high container/parent-mirror-security || true
+ db_go
+ ;;
+
+ *)
+ db_set container/parent-mirror-security ${MIRROR_SECURITY}
+ db_fset container/parent-mirror-security seen true
+ ;;
+ esac
+
+ db_get container/parent-mirror-security
+ PARENT_MIRROR_SECURITY="${RET}" # string (w/o empty)
+
+ if [ -z "${PARENT_MIRROR_SECURITY}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ PARENT_MIRROR_SECURITY="https://security.debian.org"
+ ;;
+
+ *)
+ PARENT_MIRROR_SECURITY="${MIRROR_SECURITY}"
+ ;;
+ esac
+ fi
+ fi
+
+ echo "PARENT_MIRROR_SECURITY=\"${PARENT_MIRROR_SECURITY}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PARENT_MIRROR_SECURITY
+}
+
+Archive_areas ()
+{
+ db_get container/archive-areas
+ ARCHIVE_AREAS="${RET}"
+
+ case "${PARENT_DISTRIBUTION}" in
+ bookworm|testing|sid)
+ ARCHIVE_AREAS_ALL="main, contrib, non-free, non-free-firmware"
+ ;;
+
+ *)
+ ARCHIVE_AREAS_ALL="main, contrib, non-free"
+ ;;
+ esac
+
+ if [ -z "${ARCHIVE_AREAS}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ db_subst container/archive-areas CHOICES "${ARCHIVE_AREAS_ALL}"
+
+ db_set container/archive-areas "${ARCHIVE_AREAS_ALL}"
+ db_fset container/archive-areas seen false
+ ;;
+
+ *)
+ db_subst container/archive-areas CHOICES "${ARCHIVE_AREAS_ALL}"
+
+ db_set container/archive-areas "main"
+ db_fset container/archive-areas seen false
+ ;;
+ esac
+
+ db_settitle container/title
+ db_input high container/archive-areas || true
+ db_go
+
+ db_get container/archive-areas
+ ARCHIVE_AREAS="${RET}" # multiselect (w/o empty)
+
+ if [ -z "${ARCHIVE_AREAS}" ]
+ then
+ case "${MODE}" in
+ debian)
+ ARCHIVE_AREAS="main"
+ ;;
+
+ progress-linux)
+ ARCHIVE_AREAS="${ARCHIVE_AREAS_ALL}"
+ ;;
+ esac
+ fi
+ fi
+
+ ARCHIVE_AREAS="$(echo ${ARCHIVE_AREAS} | sed -e 's| ||g')"
+
+ echo "ARCHIVE_AREAS=\"${ARCHIVE_AREAS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export ARCHIVE_AREAS
+}
+
+Parent_archive_areas ()
+{
+ db_get container/parent-archive-areas
+ PARENT_ARCHIVE_AREAS="${RET}" # multiselect (w/o empty)
+
+ case "${PARENT_DISTRIBUTION}" in
+ bookworm|testing|sid)
+ PARENT_ARCHIVE_AREAS_ALL="main, contrib, non-free, non-free-firmware"
+ ;;
+
+ *)
+ PARENT_ARCHIVE_AREAS_ALL="main, contrib, non-free"
+ ;;
+ esac
+
+ if [ -z "${PARENT_ARCHIVE_AREAS}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ db_subst container/parent-archive-areas CHOICES "${PARENT_ARCHIVE_AREAS_ALL}"
+
+ db_set container/parent-archive-areas "${PARENT_ARCHIVE_AREAS_ALL}"
+ db_fset container/parent-archive-areas seen false
+
+ db_settitle container/title
+ db_input high container/parent-archive-areas || true
+ db_go
+ ;;
+
+ *)
+ db_subst container/parent-archive-areas CHOICES "${ARCHIVE_AREAS}"
+
+ db_set container/parent-archive-areas "${ARCHIVE_AREAS}"
+ db_fset container/parent-archive-areas seen true
+ ;;
+ esac
+
+ db_get container/parent-archive-areas
+ PARENT_ARCHIVE_AREAS="${RET}" # multiselect (w/o empty)
+
+ if [ -z "${PARENT_ARCHIVE_AREAS}" ]
+ then
+ case "${MODE}" in
+ progress-linux)
+ PARENT_ARCHIVE_AREAS="${PARENT_ARCHIVE_AREAS_ALL}"
+ ;;
+
+ *)
+ PARENT_ARCHIVE_AREAS="${ARCHIVE_AREAS}"
+ ;;
+ esac
+ fi
+ fi
+
+ PARENT_ARCHIVE_AREAS="$(echo ${PARENT_ARCHIVE_AREAS} | sed -e 's| ||g')"
+
+ echo "PARENT_ARCHIVE_AREAS=\"${PARENT_ARCHIVE_AREAS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PARENT_ARCHIVE_AREAS
+}
+
+Packages ()
+{
+ db_get container/packages
+ PACKAGES="${RET}" # string (w/ empty)
+
+ if [ -z "${PACKAGES}" ]
+ then
+ db_settitle container/title
+ db_input high container/packages || true
+ db_go
+
+ db_get container/packages
+ PACKAGES="${RET}" # string (w/ empty)
+ fi
+
+ echo "PACKAGES=\"${PACKAGES}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export PACKAGES
+}
+
+Local_archives ()
+{
+ NUMBER="1"
+
+ while db_get container/archive${NUMBER}/repository && [ "${RET}" ]
+ do
+ mkdir -p "${DEBCONF_TMPDIR}/apt"
+
+ REPOSITORY="${RET#deb }"
+
+ LIST="archive${NUMBER}.list"
+ if db_get container/archive${NUMBER}/list
+ then
+ LIST="$(basename ${RET} .list).list"
+ fi
+
+ COMMENT=""
+ if db_get container/archive${NUMBER}/comment
+ then
+ COMMENT="${RET}"
+
+ echo "# ${COMMENT}" > "${DEBCONF_TMPDIR}/apt/${LIST}"
+ fi
+
+ echo "deb ${REPOSITORY}" >> "${DEBCONF_TMPDIR}/apt/${LIST}"
+
+ if db_get container/archive${NUMBER}/source && [ "$RET" = true ]
+ then
+ echo "deb-src ${REPOSITORY}" >> "${DEBCONF_TMPDIR}/apt/${LIST}"
+ fi
+
+ KEY=""
+ if db_get container/archive${NUMBER}/key
+ then
+ KEY="${RET}"
+
+ wget -q "${KEY}" -O "${DEBCONF_TMPDIR}/apt/$(basename ${LIST} .list).key"
+ fi
+
+ PREFERENCES_PACKAGE=""
+ PREFERENCES_PIN=""
+ PREFERENCES_PIN_PRIORITY=""
+ if db_get container/archive${NUMBER}/preferences-package
+ then
+ PREFERENCES_PACKAGE="${RET}"
+
+ if db_get container/archive${NUMBER}/preferences-pin
+ then
+ PREFERENCES_PIN="${RET}"
+ fi
+
+ if db_get container/archive${NUMBER}/preferences-pin-priority
+ then
+ PREFERENCES_PIN_PRIORITY="${RET}"
+ fi
+
+ if [ -n "${PREFERENCES_PACKAGE}" ] || [ -n "${PREFERENCES_PIN}" ] || [ -n "${PREFERENCES_PIN_PRIORITY}" ]
+ then
+
+cat > "${DEBCONF_TMPDIR}/apt/$(basename ${LIST} .list).pref" << EOF
+Package: ${PREFERENCES_PACKAGE}
+Pin: ${PREFERENCES_PIN}
+Pin-Priority: ${PREFERENCES_PIN_PRIORITY}
+EOF
+
+ fi
+ fi
+
+ NUMBER="$((${NUMBER} + 1))"
+ done
+}
+
+Network_defaults ()
+{
+ HOSTNAME_SHORT="$(echo veth-$(echo ${NAME} | cut -c-8)-0)"
+ VETH_NAME="${HOSTNAME_SHORT}"
+
+ NETWORK1_VETH="${NETWORK1_VETH:-$VETH_NAME}"
+ NETWORK1_BRIDGE="${NETWORK1_BRIDGE:-bridge0}"
+
+ NETWORK1_IPV4_METHOD="${NETWORK1_IPV4_METHOD:-dhcp}"
+ NETWORK1_IPV4_ADDRESS="${NETWORK1_IPV4_ADDRESS:-192.168.1.2}"
+ NETWORK1_IPV4_NETMASK="${NETWORK1_IPV4_NETMASK:-24}"
+
+ NETWORK1_IPV6_METHOD="${NETWORK1_IPV6_METHOD:-none}"
+ NETWORK1_IPV6_ADDRESS="${NETWORK1_IPV6_ADDRESS:-fc00::2}"
+ NETWORK1_IPV6_NETMASK="${NETWORK1_IPV6_NETMASK:-7}"
+
+ if [ "${NETWORK1_IPV4_METHOD}" = "static" ] || [ "${NETWORK1_IPV6_METHOD}" = "static" ]
+ then
+ if [ -e /etc/resolv.conf ]
+ then
+ NAMESERVER_SERVER="${NAMESERVER_SERVER:-$(awk '/^nameserver / {$1=""; print $0}' /etc/resolv.conf)}"
+ # Workaround to get rid of newlines since debconf can not handle multiline return value in assignments
+ NAMESERVER_SERVER="$(echo ${NAMESERVER_SERVER})"
+
+ NAMESERVER_DOMAIN="${NAMESERVER_DOMAIN:-$(awk '/^domain / {$1=""; print $0}' /etc/resolv.conf)}"
+ NAMESERVER_SEARCH="${NAMESERVER_SEARCH:-$(awk '/^search / {$1=""; print $0}' /etc/resolv.conf)}"
+ NAMESERVER_OPTIONS="${NAMESERVER_OPTIONS:-$(awk '/^options / {$1=""; print $0}' /etc/resolv.conf)}"
+ fi
+ fi
+}
+
+Network ()
+{
+ db_get container/network1/bridge
+ NETWORK1_BRIDGE="${RET}" # string (w/o empty)
+
+ db_get container/network1/veth
+ NETWORK1_VETH="${RET}" # string (w/o empty)
+
+ db_get container/network1/ipv4-method
+ NETWORK1_IPV4_METHOD="${RET}" # select
+
+ db_get container/network1/ipv4-comment
+ NETWORK1_IPV4_COMMENT="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv4-address
+ NETWORK1_IPV4_ADDRESS="${RET}" # string (w/o empty)
+
+ db_get container/network1/ipv4-gateway
+ NETWORK1_IPV4_GATEWAY="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv4-netmask
+ NETWORK1_IPV4_NETMASK="${RET}" # string (w/o empty)
+
+ db_get container/network1/ipv4-post-up
+ NETWORK1_IPV4_POST_UP="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv4-post-down
+ NETWORK1_IPV4_POST_DOWN="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv6-method
+ NETWORK1_IPV6_METHOD="${RET}" # select
+
+ db_get container/network1/ipv6-comment
+ NETWORK1_IPV6_COMMENT="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv6-address
+ NETWORK1_IPV6_ADDRESS="${RET}" # string (w/o empty)
+
+ db_get container/network1/ipv6-gateway
+ NETWORK1_IPV6_GATEWAY="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv6-netmask
+ NETWORK1_IPV6_NETMASK="${RET}" # string (w/o empty)
+
+ db_get container/network1/ipv6-post-up
+ NETWORK1_IPV6_POST_UP="${RET}" # string (w/ empty)
+
+ db_get container/network1/ipv6-post-down
+ NETWORK1_IPV6_POST_DOWN="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/server
+ NAMESERVER_SERVER="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/domain
+ NAMESERVER_DOMAIN="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/search
+ NAMESERVER_SEARCH="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/options
+ NAMESERVER_OPTIONS="${RET}" # string (w/ empty)
+
+ Network_defaults
+
+ db_set container/network1/bridge "${NETWORK1_BRIDGE}"
+ db_fset container/network1/bridge seen false
+
+ db_set container/network1/veth "${NETWORK1_VETH}"
+ db_fset container/network1/veth seen false
+
+ db_set container/network1/ipv4-method "${NETWORK1_IPV4_METHOD}"
+ db_fset container/network1/ipv4-method seen false
+
+ db_set container/network1/ipv4-comment "${NETWORK1_IPV4_COMMENT}"
+ db_fset container/network1/ipv4-comment seen false
+
+ db_set container/network1/ipv4-address "${NETWORK1_IPV4_ADDRESS}"
+ db_fset container/network1/ipv4-address seen false
+
+ db_set container/network1/ipv4-gateway "${NETWORK1_IPV4_GATEWAY}"
+ db_fset container/network1/ipv4-gateway seen false
+
+ db_set container/network1/ipv4-netmask "${NETWORK1_IPV4_NETMASK}"
+ db_fset container/network1/ipv4-netmask seen false
+
+ db_set container/network1/ipv4-post-up "${NETWORK1_IPV4_POST_UP}"
+ db_fset container/network1/ipv4-post-up seen false
+
+ db_set container/network1/ipv4-post-down "${NETWORK1_IPV4_POST_DOWN}"
+ db_fset container/network1/ipv4-post-down seen false
+
+ db_set container/network1/ipv6-method "${NETWORK1_IPV6_METHOD}"
+ db_fset container/network1/ipv6-method seen false
+
+ db_set container/network1/ipv6-comment "${NETWORK1_IPV6_COMMENT}"
+ db_fset container/network1/ipv6-comment seen false
+
+ db_set container/network1/ipv6-address "${NETWORK1_IPV6_ADDRESS}"
+ db_fset container/network1/ipv6-address seen false
+
+ db_set container/network1/ipv6-gateway "${NETWORK1_IPV6_GATEWAY}"
+ db_fset container/network1/ipv6-gateway seen false
+
+ db_set container/network1/ipv6-netmask "${NETWORK1_IPV6_NETMASK}"
+ db_fset container/network1/ipv6-netmask seen false
+
+ db_set container/network1/ipv6-post-up "${NETWORK1_IPV6_POST_UP}"
+ db_fset container/network1/ipv6-post-up seen false
+
+ db_set container/network1/ipv6-post-down "${NETWORK1_IPV6_POST_DOWN}"
+ db_fset container/network1/ipv6-post-down seen false
+
+ db_set container/nameserver/server "${NAMESERVER_SERVER}"
+ db_fset container/nameserver/server seen false
+
+ db_set container/nameserver/domain "${NAMESERVER_DOMAIN}"
+ db_fset container/nameserver/domain seen false
+
+ db_set container/nameserver/search "${NAMESERVER_SEARCH}"
+ db_fset container/nameserver/search seen false
+
+ db_set container/nameserver/options "${NAMESERVER_OPTIONS}"
+ db_fset container/nameserver/options seen false
+
+ db_get container/network1/bridge
+ NETWORK1_BRIDGE="${RET}" # select
+
+ db_get container/network1/veth
+ NETWORK1_VETH="${RET}" # select
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-method || true
+ db_go
+
+ db_get container/network1/ipv4-method
+ NETWORK1_IPV4_METHOD="${RET}" # select
+
+ case "${NETWORK1_IPV4_METHOD}" in
+ none|dhcp)
+ ;;
+
+ static)
+ db_settitle container/title
+ db_input high container/network1/ipv4-comment || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-address || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-gateway || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-netmask || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-post-up || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-post-down || true
+ db_go
+ ;;
+
+ stub)
+ db_settitle container/title
+ db_input high container/network1/ipv4-comment || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-post-up || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv4-post-down || true
+ db_go
+ ;;
+ esac
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-method || true
+ db_go
+
+ db_get container/network1/ipv6-method
+ NETWORK1_IPV6_METHOD="${RET}" # select
+
+ case "${NETWORK1_IPV6_METHOD}" in
+ none|dhcp)
+ ;;
+
+ static)
+ db_settitle container/title
+ db_input high container/network1/ipv6-comment || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-address || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-gateway || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-netmask || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-post-up || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-post-down || true
+ db_go
+ ;;
+
+ stub)
+ db_settitle container/title
+ db_input high container/network1/ipv6-comment || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-post-up || true
+ db_go
+
+ db_settitle container/title
+ db_input high container/network1/ipv6-post-down || true
+ db_go
+ ;;
+ esac
+
+ if [ "${NETWORK1_IPV4_METHOD}" = "static" ] || [ "${NETWORK1_IPV6_METHOD}" = "static" ]
+ then
+ db_settitle container/title
+ db_input high container/nameserver/server || true
+ db_go
+ fi
+
+ NUMBER="1"
+
+ while ( db_get container/network${NUMBER}/ipv4-method && [ "${RET}" ] ) || ( db_get container/network${NUMBER}/ipv6-method && [ "${RET}" ] )
+ do
+ if db_get container/network${NUMBER}/bridge
+ then
+ eval NETWORK${NUMBER}_BRIDGE="\"${RET}\"" # string (w/o empty)
+ fi
+
+ if db_get container/network${NUMBER}/veth
+ then
+ eval NETWORK${NUMBER}_VETH="\"${RET}\"" # string (w/o empty)
+ fi
+
+ NUMBER="$((${NUMBER} + 1))"
+ done
+
+ NETWORK_NUMBER="$((${NUMBER} - 1))"
+
+ for NUMBER in $(seq 1 ${NETWORK_NUMBER})
+ do
+ if db_get container/network${NUMBER}/ipv4-comment
+ then
+ eval NETWORK${NUMBER}_IPV4_COMMENT="\"${RET}\"" # string (w/ empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv4-method
+ then
+ eval NETWORK${NUMBER}_IPV4_METHOD="\"${RET}\"" # select
+ fi
+
+ if db_get container/network${NUMBER}/ipv4-address
+ then
+ eval NETWORK${NUMBER}_IPV4_ADDRESS="\"${RET}\"" # string (w/o empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv4-gateway
+ then
+ eval NETWORK${NUMBER}_IPV4_GATEWAY="\"${RET}\"" # string (w/ empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv4-netmask
+ then
+ eval NETWORK${NUMBER}_IPV4_NETMASK="\"${RET}\"" # string (w/o empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv4-post-up
+ then
+ eval NETWORK${NUMBER}_IPV4_POST_UP="\"${RET}\"" # string (w/ empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv4-post-down
+ then
+ eval NETWORK${NUMBER}_IPV4_POST_DOWN="\"${RET}\"" # string (w/ empty)
+ fi
+ done
+
+ for NUMBER in $(seq 1 ${NETWORK_NUMBER})
+ do
+ if db_get container/network${NUMBER}/ipv6-comment
+ then
+ eval NETWORK${NUMBER}_IPV6_COMMENT="\"${RET}\"" # string (w/ empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv6-method
+ then
+ eval NETWORK${NUMBER}_IPV6_METHOD="\"${RET}\"" # select
+ fi
+
+ if db_get container/network${NUMBER}/ipv6-address
+ then
+ eval NETWORK${NUMBER}_IPV6_ADDRESS="\"${RET}\"" # string (w/o empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv6-gateway
+ then
+ eval NETWORK${NUMBER}_IPV6_GATEWAY="\"${RET}\"" # string (w/ empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv6-netmask
+ then
+ eval NETWORK${NUMBER}_IPV6_NETMASK="\"${RET}\"" # string (w/o empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv6-post-up
+ then
+ eval NETWORK${NUMBER}_IPV6_POST_UP="\"${RET}\"" # string (w/ empty)
+ fi
+
+ if db_get container/network${NUMBER}/ipv6-post-down
+ then
+ eval NETWORK${NUMBER}_IPV6_POST_DOWN="\"${RET}\"" # string (w/ empty)
+ fi
+ done
+
+ db_get container/nameserver/server
+ NAMESERVER_SERVER="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/domain
+ NAMESERVER_DOMAIN="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/search
+ NAMESERVER_SEARCH="${RET}" # string (w/ empty)
+
+ db_get container/nameserver/options
+ NAMESERVER_OPTIONS="${RET}" # string (w/ empty)
+
+ Network_defaults
+
+ echo "NETWORK_NUMBER=\"${NETWORK_NUMBER}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ for NUMBER in $(seq 1 ${NETWORK_NUMBER})
+ do
+ eval BRIDGE="$`echo NETWORK${NUMBER}_BRIDGE`"
+ echo "NETWORK${NUMBER}_BRIDGE=\"${BRIDGE}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval VETH="$`echo NETWORK${NUMBER}_VETH`"
+ echo "NETWORK${NUMBER}_VETH=\"${VETH}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval COMMENT="$`echo NETWORK${NUMBER}_IPV4_COMMENT`"
+ echo "NETWORK${NUMBER}_IPV4_COMMENT=\"${COMMENT}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval METHOD="$`echo NETWORK${NUMBER}_IPV4_METHOD`"
+ echo "NETWORK${NUMBER}_IPV4_METHOD=\"${METHOD}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval ADDRESS="$`echo NETWORK${NUMBER}_IPV4_ADDRESS`"
+ echo "NETWORK${NUMBER}_IPV4_ADDRESS=\"${ADDRESS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval GATEWAY="$`echo NETWORK${NUMBER}_IPV4_GATEWAY`"
+ echo "NETWORK${NUMBER}_IPV4_GATEWAY=\"${GATEWAY}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval NETMASK="$`echo NETWORK${NUMBER}_IPV4_NETMASK`"
+ echo "NETWORK${NUMBER}_IPV4_NETMASK=\"${NETMASK}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval POST_UP="$`echo NETWORK${NUMBER}_IPV4_POST_UP`"
+ echo "NETWORK${NUMBER}_IPV4_POST_UP=\"${POST_UP}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval POST_DOWN="$`echo NETWORK${NUMBER}_IPV4_POST_DOWN`"
+ echo "NETWORK${NUMBER}_IPV4_POST_DOWN=\"${POST_DOWN}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval COMMENT="$`echo NETWORK${NUMBER}_IPV6_COMMENT`"
+ echo "NETWORK${NUMBER}_IPV6_COMMENT=\"${COMMENT}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval METHOD="$`echo NETWORK${NUMBER}_IPV6_METHOD`"
+ echo "NETWORK${NUMBER}_IPV6_METHOD=\"${METHOD}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval ADDRESS="$`echo NETWORK${NUMBER}_IPV6_ADDRESS`"
+ echo "NETWORK${NUMBER}_IPV6_ADDRESS=\"${ADDRESS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval GATEWAY="$`echo NETWORK${NUMBER}_IPV6_GATEWAY`"
+ echo "NETWORK${NUMBER}_IPV6_GATEWAY=\"${GATEWAY}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval NETMASK="$`echo NETWORK${NUMBER}_IPV6_NETMASK`"
+ echo "NETWORK${NUMBER}_IPV6_NETMASK=\"${NETMASK}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval POST_UP="$`echo NETWORK${NUMBER}_IPV6_POST_UP`"
+ echo "NETWORK${NUMBER}_IPV6_POST_UP=\"${POST_UP}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ eval POST_DOWN="$`echo NETWORK${NUMBER}_IPV6_POST_DOWN`"
+ echo "NETWORK${NUMBER}_IPV6_POST_DOWN=\"${POST_DOWN}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ done
+
+ echo "NAMESERVER_SERVER=\"${NAMESERVER_SERVER}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ echo "NAMESERVER_DOMAIN=\"${NAMESERVER_DOMAIN}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ echo "NAMESERVER_SEARCH=\"${NAMESERVER_SEARCH}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ echo "NAMESERVER_OPTIONS=\"${NAMESERVER_OPTIONS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+}
+
+Root_password ()
+{
+ if db_get container/root-password
+ then
+ ROOT_PASSWORD="${RET}" # string (w/o empty)
+ fi
+
+ if [ -z "${ROOT_PASSWORD}" ]
+ then
+ # Create a random password as suggestion for the user
+ RANDOM_PASSWORD="$(dd if=/dev/urandom bs=12 count=1 2> /dev/null | base64)"
+
+ db_set container/root-password ${RANDOM_PASSWORD}
+ db_fset container/root-password seen false
+
+ db_settitle container/title
+ db_input high container/root-password || true
+ db_go
+
+ db_get container/root-password
+ ROOT_PASSWORD="${RET}"
+
+ if [ -z "${ROOT_PASSWORD}" ]
+ then
+ # User did set not set a password, falling back to random password
+ ROOT_PASSWORD="${RANDOM_PASSWORD}"
+ fi
+
+ if [ "${ROOT_PASSWORD}" = "${RANDOM_PASSWORD}" ]
+ then
+ echo "ROOT_RANDOM_PASSWORD=\"true\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ fi
+ fi
+
+ echo "ROOT_PASSWORD=\"${ROOT_PASSWORD}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+}
+
+Internal_options ()
+{
+ if db_get container/apt-recommends
+ then
+ APT_RECOMMENDS="${RET}" # boolean (w/ empty)
+ fi
+
+ echo "APT_RECOMMENDS=\"${APT_RECOMMENDS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/debconf-frontend
+ then
+ DEBCONF_FRONTEND="${RET}" # select
+ fi
+
+ DEBCONF_FRONTEND="${DEBCONF_FRONTEND:-dialog}"
+ echo "DEBCONF_FRONTEND=\"${DEBCONF_FRONTEND}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/debconf-priority
+ then
+ DEBCONF_PRIORITY="${RET}" # select
+ fi
+
+ DEBCONF_PRIORITY="${DEBCONF_PRIORITY:-high}"
+ echo "DEBCONF_PRIORITY=\"${DEBCONF_PRIORITY}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/container-command
+ then
+ CONTAINER_COMMAND="${RET}" # string (w/ empty)
+ fi
+
+ echo "CONTAINER_COMMAND=\"${CONTAINER_COMMAND}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ NUMBER="1"
+
+ while db_get container/container-command${NUMBER} && [ "${RET}" ]
+ do
+ if db_get container/container-command${NUMBER}
+ then
+ eval CONTAINER_COMMAND${NUMBER}="\"${RET}\"" # string (w/o empty)
+ fi
+
+ NUMBER="$((${NUMBER} + 1))"
+ done
+
+ CONTAINER_COMMAND_NUMBER="$((${NUMBER} - 1))"
+
+ echo "CONTAINER_COMMAND_NUMBER=\"${CONTAINER_COMMAND_NUMBER}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ for NUMBER in $(seq 1 ${CONTAINER_COMMAND_NUMBER})
+ do
+ eval COMMAND="$`echo CONTAINER_COMMAND${NUMBER}`"
+ echo "CONTAINER_COMMAND${NUMBER}=\"${COMMAND}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ done
+
+ if db_get container/host-command
+ then
+ HOST_COMMAND="${RET}" # string (w/ empty)
+ fi
+
+ echo "HOST_COMMAND=\"${HOST_COMMAND}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ NUMBER="1"
+
+ while db_get container/host-command${NUMBER} && [ "${RET}" ]
+ do
+ if db_get container/host-command${NUMBER}
+ then
+ eval HOST_COMMAND${NUMBER}="\"${RET}\"" # string (w/o empty)
+ fi
+
+ NUMBER="$((${NUMBER} + 1))"
+ done
+
+ HOST_COMMAND_NUMBER="$((${NUMBER} - 1))"
+
+ echo "HOST_COMMAND_NUMBER=\"${HOST_COMMAND_NUMBER}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ for NUMBER in $(seq 1 ${HOST_COMMAND_NUMBER})
+ do
+ eval COMMAND="$`echo HOST_COMMAND${NUMBER}`"
+ echo "HOST_COMMAND${NUMBER}=\"${COMMAND}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ done
+
+ if db_get container/auto
+ then
+ CNT_AUTO="${RET:-last-on}" # string (w/o empty)
+ fi
+
+ CNT_AUTO="${CNT_AUTO:-last-on}"
+ echo "CNT_AUTO=\"${CNT_AUTO}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/container-server
+ then
+ CNT_CONTAINER_SERVER="${RET:-FQDN}" # string (w/o empty)
+ fi
+
+ CNT_CONTAINER_SERVER="${CNT_CONTAINER_SERVER:-FQDN}"
+
+ case "${CNT_CONTAINER_SERVER}" in
+ FQDN)
+ CNT_CONTAINER_SERVER="$(hostname -f 2> /dev/null || hostname)"
+ ;;
+ esac
+
+ echo "CNT_CONTAINER_SERVER=\"${CNT_CONTAINER_SERVER}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/bind
+ then
+ BIND="${RET}" # string (w/ empty)
+ fi
+
+ echo "BIND=\"${BIND}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/bind-ro
+ then
+ BIND_RO="${RET}" # string (w/ empty)
+ fi
+
+ echo "BIND_RO=\"${BIND_RO}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/overlay
+ then
+ CNT_OVERLAY="${RET}" # string (w/ empty)
+ fi
+
+ echo "CNT_OVERLAY=\"${CNT_OVERLAY}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+
+ if db_get container/overlay-options
+ then
+ CNT_OVERLAY_OPTIONS="${RET}" # string (w/ empty)
+ fi
+
+ echo "CNT_OVERLAY_OPTIONS=\"${CNT_OVERLAY_OPTIONS}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+}
+
+Mode
+Images
+
+Distribution
+Parent_distribution
+
+Architecture
+
+Archives
+Parent_archives
+
+Mirror
+Mirror_security
+
+Parent_mirror
+Parent_mirror_security
+
+Archive_areas
+Parent_archive_areas
+
+Packages
+Local_archives
+
+Network
+Root_password
+
+Internal_options
+
+db_stop
diff --git a/share/build-scripts/debconf.d/0003-debconf.templates b/share/build-scripts/debconf.d/0003-debconf.templates
new file mode 100644
index 0000000..551033a
--- /dev/null
+++ b/share/build-scripts/debconf.d/0003-debconf.templates
@@ -0,0 +1,276 @@
+Template: container/title
+Type: title
+Description: compute-tools
+
+Template: container/mode
+Type: select
+Default:
+Choices-C: ${CHOICES_C}
+Choices: ${CHOICES}
+Description: Mode
+ Mode.
+
+Template: container/image
+Type: string
+Default:
+Description: Image
+ Image.
+
+Template: container/distribution
+Type: select
+Default:
+Choices-C: ${CHOICES_C}
+Choices: ${CHOICES}
+Description: Distribution
+ Distribution.
+
+Template: container/parent-distribution
+Type: select
+Default:
+Choices-C: ${CHOICES_C}
+Choices: ${CHOICES}
+Description: for internal use; can be preseeded
+ Parent Distribution.
+
+Template: container/architecture
+Type: select
+Default:
+Choices-C: ${CHOICES_C}
+Choices: ${CHOICES}
+Description: Architecture
+ Architecture.
+
+Template: container/archives
+Type: multiselect
+Default:
+Choices: ${CHOICES}
+Description: Archives
+ Archives.
+
+Template: container/parent-archives
+Type: multiselect
+Default:
+Choices: ${CHOICES}
+Description: Parent Archives
+ Parent Archives.
+
+Template: container/mirror
+Type: string
+Default:
+Description: Mirror
+ Mirror.
+
+Template: container/mirror-security
+Type: string
+Default:
+Description: Mirror Security
+ Mirror Security.
+
+Template: container/parent-mirror
+Type: string
+Default:
+Description: Parent Mirror
+ Parent Mirror.
+
+Template: container/parent-mirror-security
+Type: string
+Default:
+Description: Parent Mirror Security
+ Parent Mirror Security.
+
+Template: container/archive-areas
+Type: multiselect
+Default:
+Choices: ${CHOICES}
+Description: Archive Areas
+ Archive Areas.
+
+Template: container/parent-archive-areas
+Type: multiselect
+Default:
+Choices: ${CHOICES}
+Description: Parent Archive Areas
+ Parent Archive Areas.
+
+Template: container/packages
+Type: string
+Default:
+Description: Packages
+ Packages.
+
+Template: container/root-password
+Type: string
+Default:
+Description: Root password
+ Root password.
+
+Template: container/network1/bridge
+Type: string
+Default:
+Description: Bridge
+ Bridge.
+
+Template: container/network1/veth
+Type: string
+Default:
+Description: Veth name
+ Veth name.
+
+Template: container/network1/ipv4-method
+Type: select
+Choices: dhcp, static, stub, none
+Default:
+Description: Ethernet Interface Method (IPv4)?
+ What method should be used to configure the ethernet interface?
+ .
+ This defaults to dhcp and will require that you run a dhcp-server in your
+ network.
+
+Template: container/network1/ipv4-comment
+Type: string
+Default:
+Description: Ethernet Interface Comment (IPv4)?
+ What optional comment would you like to give to the ethernet interface?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv4-address
+Type: string
+Default:
+Description: Ethernet IP Address (IPv4)?
+ What should be the IP address of the current system?
+ .
+ This defaults to 192.168.1.2.
+
+Template: container/network1/ipv4-gateway
+Type: string
+Default:
+Description: Ethernet Gateway Address (IPv4)?
+ What should be the gateway address of the current system?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv4-netmask
+Type: string
+Default:
+Description: Ethernet Network Mask (IPv4)?
+ What should be the netmask of the current system?
+ .
+ Note that only the suffix is supported, e.g. '24'
+ for /24 or '16' for /16.
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv4-post-up
+Type: string
+Default:
+Description: Ethernet post-up Command (IPv4)?
+ What should be the post-up command for eno1?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv4-post-down
+Type: string
+Default:
+Description: Ethernet post-down Command (IPv4)?
+ What should be the post-down command for eno1?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv6-method
+Type: select
+Choices: dhcp, static, stub, none
+Default:
+Description: Ethernet Interface Method (IPv6)?
+ What method should be used to configure the ethernet interface?
+ .
+ This defaults to none.
+
+Template: container/network1/ipv6-comment
+Type: string
+Default:
+Description: Ethernet Interface Comment (IPv6)?
+ What optional comment would you like to give to the ethernet interface?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv6-address
+Type: string
+Default:
+Description: Ethernet IP Address (IPv6)?
+ What should be the IP address of the current system?
+ .
+ This defaults to fc00::1 (unique local unicast).
+
+Template: container/network1/ipv6-gateway
+Type: string
+Default:
+Description: Ethernet Gateway Address (IPv6)?
+ What should be the gateway address of the current system?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv6-netmask
+Type: string
+Default:
+Description: Ethernet Network Mask (IPv6)?
+ What should be the netmask of the current system?
+ .
+ Note that only the suffix is supported, e.g. '64'
+ for /64 or '48' for /48.
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv6-post-up
+Type: string
+Default:
+Description: Ethernet post-up Command (IPv6)?
+ What should be the post-up command for eno1?
+ .
+ This defaults to empty.
+
+Template: container/network1/ipv6-post-down
+Type: string
+Default:
+Description: Ethernet post-down Command (IPv6)?
+ What should be the post-down command for eno1?
+ .
+ This defaults to empty.
+
+Template: container/nameserver/server
+Type: string
+Default:
+Description: Nameserver Addresses?
+ What should be the IP addresses of the nameservers of the current system?
+ .
+ This defaults to empty. Multiple nameservers can be separated by whitespace.
+
+Template: container/nameserver/domain
+Type: string
+Default:
+Description: Nameserver Local Domain Name?
+ What should be local domain name used for name resolution?
+ .
+ See resolv.conf(5) for more information about the 'domain' option.
+ .
+ This defaults to empty.
+
+Template: container/nameserver/search
+Type: string
+Default:
+Description: Nameserver Search List?
+ What should be search list for hostname lookups?
+ .
+ See resolv.conf(5) for more information about the 'search' option.
+ .
+ This defaults to empty.
+
+Template: container/nameserver/options
+Type: string
+Default:
+Description: Nameserver Resolver Options?
+ What should be the resolver options?
+ .
+ See resolv.conf(5) for more information about the 'options' option.
+ .
+ This defaults to empty.
diff --git a/share/build-scripts/debootstrap b/share/build-scripts/debootstrap
new file mode 100755
index 0000000..5ab5db2
--- /dev/null
+++ b/share/build-scripts/debootstrap
@@ -0,0 +1,198 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+SCRIPT="$(basename ${0})"
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="bind:,bind-ro:,script:,name:,architecture:,distribution:,mirror:,password:"
+ GETOPT_OPTIONS="b:,s:,n:,a:,d:,m:,p:"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${SCRIPT} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${SCRIPT}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -b|--bind)
+ # ignore
+ shift 2
+ ;;
+
+ --bind-ro)
+ # ignore
+ shift 2
+ ;;
+
+ --cnt.auto)
+ # ignore
+ shift 2
+ ;;
+
+ --cnt.container-server)
+ # ignore
+ shift 2
+ ;;
+
+ -s|--script)
+ # ignore
+ shift 2
+ ;;
+
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -a|--architecture)
+ ARCHITECTURE="${2}"
+ shift 2
+ ;;
+
+ -d|--distribution)
+ DISTRIBUTION="${2}"
+ shift 2
+ ;;
+
+ -m|--mirror)
+ MIRROR="${2}"
+ shift 2
+ ;;
+
+ -p|--password)
+ PASSWORD="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${SCRIPT}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: container build -n|--name NAME -s|--script ${SCRIPT} -- [-a|--architecture ARCHITECTURE] [-d|--distribution DISTRIBUTION] [-m|--mirror MIRROR] [-p|--password PASSWORD}" >&2
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': container already exists" >&2
+ exit 1
+fi
+
+case "${SCRIPT}" in
+ debootstrap)
+ BOOTSTRAP="/usr/sbin/debootstrap"
+ BOOTSTRAP_OPTIONS=""
+ ;;
+
+ mmdebstrap)
+ BOOTSTRAP="/usr/bin/mmdebstrap"
+ BOOTSTRAP_OPTIONS="--format=directory --mode=root --aptopt='APT::Sandbox::User \"root\"'"
+ ;;
+esac
+
+if [ ! -x "${BOOTSTRAP}" ]
+then
+ echo "'${NAME}': ${BOOTSTRAP} - no such file." >&2
+ exit 1
+fi
+
+if [ "$(id -u)" -ne 0 ]
+then
+ echo "'${NAME}': need root privileges" >&2
+ exit 1
+fi
+
+ARCHITECTURE="${ARCHITECTURE:-$(dpkg --print-architecture)}"
+DISTRIBUTION="${DISTRIBUTION:-bookworm}"
+MIRROR="${MIRROR:-https://deb.debian.org/debian}"
+PASSWORD="${PASSWORD:-$(dd if=/dev/urandom bs=12 count=1 2> /dev/null | base64)}"
+
+INCLUDE="dbus"
+
+case "${MIRROR}" in
+ https*)
+ INCLUDE="${INCLUDE},apt-transport-https,ca-certificates"
+ ;;
+esac
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${SCRIPT}".* "${HOOKS}/${NAME}.pre-${SCRIPT}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+mkdir -p "${MACHINES}"
+${BOOTSTRAP} ${BOOTSTRAP_OPTIONS} --arch=${ARCHITECTURE} --include=${INCLUDE} ${DISTRIBUTION} ${MACHINES}/${NAME} ${MIRROR}
+
+# Cleaning apt cache
+chroot "${MACHINES}/${NAME}" apt clean
+
+# Setting hostname
+echo "${NAME}" > "${MACHINES}/${NAME}/etc/hostname"
+
+# Setting root password
+echo root:${PASSWORD} | chroot "${MACHINES}/${NAME}" chpasswd
+echo "${NAME}: root password set to '${PASSWORD}'."
+
+# Post hooks
+for FILE in "${HOOKS}/post-${SCRIPT}".* "${HOOKS}/${NAME}.post-${SCRIPT}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/share/config/container.conf.in b/share/config/container.conf.in
new file mode 100644
index 0000000..d3f9a48
--- /dev/null
+++ b/share/config/container.conf.in
@@ -0,0 +1,30 @@
+# Open Infrastructure: compute-tools
+
+[start]
+cnt.auto=@CNT_AUTO@
+cnt.container-server=@CNT_CONTAINER_SERVER@
+cnt.network-bridge=@CNT_NETWORK_BRIDGE@
+cnt.overlay=@CNT_OVERLAY@
+cnt.overlay-options=@CNT_OVERLAY_OPTIONS@
+cnt.start=@CNT_START@
+bind=@BIND@
+bind-ro=@BIND_RO@
+boot=@BOOT@
+capability=@CAPABILITY@
+directory=@DIRECTORY@
+drop-capability=@DROP_CAPABILITY@
+link-journal=@LINK_JOURNAL@
+machine=@MACHINE@
+network-veth-extra=@NETWORK_VETH_EXTRA@
+private-users=@PRIVATE_USERS@
+register=@REGISTER@
+
+[limit]
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+CPUQuota=
+CPUShares=
+MemoryLimit=
+TasksMax=
diff --git a/share/doc/examples/bookworm.cfg b/share/doc/examples/bookworm.cfg
new file mode 100644
index 0000000..1f878f4
--- /dev/null
+++ b/share/doc/examples/bookworm.cfg
@@ -0,0 +1,35 @@
+# example for automated Debian 12 (bookworm) based container building
+# using: sudo container build -s debian
+
+debconf debconf/priority select critical
+debconf debconf/frontend select Noninteractive
+
+compute-tools container/mode select debian
+
+#compute-tools container/preseed-files string
+#compute-tools container/include-preseed-files string
+
+compute-tools container/distribution select bookworm
+#compute-tools container/parent-distribution select
+
+compute-tools container/architecture select auto
+
+compute-tools container/archives multiselect bookworm-security, bookworm-updates
+#compute-tools container/parent-archives multiselect
+
+compute-tools container/mirror string https://deb.debian.org/debian
+compute-tools container/mirror-security string https://security.debian.org
+
+#compute-tools container/parent-mirror string
+#compute-tools container/parent-mirror-security string
+
+compute-tools container/archive-areas multiselect main
+#compute-tools container/parent-archive-areas multiselect
+
+compute-tools container/packages string openssh-server
+
+compute-tools container/root-password string debian
+#compute-tools container/root-password-crypted string
+
+compute-tools container/network1/bridge string bridge0
+#compute-tools container/network-mac string
diff --git a/share/doc/examples/container-images.sh b/share/doc/examples/container-images.sh
new file mode 100755
index 0000000..b711048
--- /dev/null
+++ b/share/doc/examples/container-images.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Description: example for automated Debian base system container image builds
+# Requires: debootstrap plzip xz-utils sudo
+# Usage: ./container-images.sh
+
+set -e
+
+ARCHITECTURES="amd64 i386"
+DISTRIBUTIONS="buster bullseye bookworm sid"
+MIRROR="https://deb.debian.org/debian"
+INCLUDE="dbus"
+
+KEY="0x55CF1BF986ABB9C7"
+
+COMPRESSIONS="gz lz xz"
+
+DATE="$(date +%Y%m%d)"
+
+for DISTRIBUTION in ${DISTRIBUTIONS}
+do
+ for ARCHITECTURE in ${ARCHITECTURES}
+ do
+ TITLE="Debian ${DISTRIBUTION} ${DATE}/${ARCHITECTURE}"
+ SYSTEM="debian-${DISTRIBUTION}-${DATE}_${ARCHITECTURE}"
+
+ sudo debootstrap --arch=${ARCHITECTURE} --include=${INCLUDE} ${DISTRIBUTION} ${SYSTEM} ${MIRROR}
+ sudo chroot "${SYSTEM}" apt-get clean
+
+ VERSION="$(cat ${SYSTEM}/etc/debian_version)"
+
+ case "${VERSION}" in
+ [0-9]*)
+ TITLE="Debian ${VERSION} (${DISTRIBUTION}) ${DATE}/${ARCHITECTURE}"
+ SYSTEM="debian-${VERSION}-${DATE}_${ARCHITECTURE}"
+
+ sudo mv "debian-${DISTRIBUTION}-${DATE}_${ARCHITECTURE}" "${SYSTEM}"
+ ;;
+ esac
+
+ sudo rm -f "${SYSTEM}/etc/apt/apt.conf.d/01autoremove-kernels"
+ sudo rm -f "${SYSTEM}/etc/hostname"
+ sudo rm -f "${SYSTEM}/etc/machine-id"
+ sudo rm -f "${SYSTEM}/etc/resolv.conf"
+ sudo rm -f "${SYSTEM}/var/lib/systemd/catalog/database"
+
+ for COMPRESSION in ${COMPRESSIONS}
+ do
+ case "${COMPRESSION}" in
+ gz)
+ TAR_OPTIONS="--gzip"
+ ;;
+
+ lz)
+ TAR_OPTIONS="--lzip"
+ ;;
+
+ xz)
+ TAR_OPTIONS="--xz"
+ ;;
+ esac
+
+ echo "Building ${SYSTEM}.system.tar.${COMPRESSION}"
+ sudo tar ${TAR_OPTIONS} -cf "${SYSTEM}.system.tar.${COMPRESSION}" "${SYSTEM}"
+
+ echo "Building ${SYSTEM}.system.tar.${COMPRESSION}.sha512"
+ sha512sum "${SYSTEM}.system.tar.${COMPRESSION}" > "${SYSTEM}.system.tar.${COMPRESSION}.sha512"
+
+ if [ -n "${KEY}" ]
+ then
+ echo "Building ${SYSTEM}.system.tar.${COMPRESSION}.sig"
+ gpg -a -b --default-key ${KEY} ${SYSTEM}.system.tar.${COMPRESSION}
+ mv "${SYSTEM}.system.tar.${COMPRESSION}.asc" "${SYSTEM}.system.tar.${COMPRESSION}.sig"
+ fi
+
+ echo "Building ${SYSTEM}.system.tar.${COMPRESSION} symlink"
+ ln -sf "${SYSTEM}.system.tar.${COMPRESSION}" "$(echo ${SYSTEM}.system.tar.${COMPRESSION} | sed -e "s|${DATE}|current|")"
+
+ echo "Building ${SYSTEM}.system.tar.${COMPRESSION}.sha512 copy"
+ sed -e "s|${DATE}|current|" "${SYSTEM}.system.tar.${COMPRESSION}.sha512" > "$(echo ${SYSTEM}.system.tar.${COMPRESSION}.sha512 | sed -e "s|${DATE}|current|")"
+
+ if [ -e "${SYSTEM}.system.tar.${COMPRESSION}.sig" ]
+ then
+ echo "Building ${SYSTEM}.system.tar.${COMPRESSION}.sig copy"
+ cp "${SYSTEM}.system.tar.${COMPRESSION}.sig" "$(echo ${SYSTEM}.system.tar.${COMPRESSION}.sig | sed -e "s|${DATE}|current|")"
+ fi
+ done
+
+ sudo rm -rf "${SYSTEM}"
+
+cat >> container-list.txt << EOF
+${SYSTEM}.system.tar | ${TITLE}
+EOF
+
+ done
+done
diff --git a/share/doc/examples/graograman-backports.cfg b/share/doc/examples/graograman-backports.cfg
new file mode 100644
index 0000000..d1d2640
--- /dev/null
+++ b/share/doc/examples/graograman-backports.cfg
@@ -0,0 +1,70 @@
+# example for automated Progress Linux 7.99 (graograman-backports) container building
+# using: sudo container build -s progress-linux
+
+debconf debconf/priority select critical
+debconf debconf/frontend select Noninteractive
+
+compute-tools container/mode select progress-linux
+
+#compute-tools container/preseed-files string
+#compute-tools container/include-preseed-files string
+
+compute-tools container/distribution select graograman-backports
+#compute-tools container/parent-distribution select
+
+compute-tools container/architecture select auto
+
+compute-tools container/archives multiselect graograman-security, graograman-updates, graograman-extras, graograman-backports, graograman-backports-extras
+#compute-tools container/parent-archives multiselect
+
+compute-tools container/mirror string https://deb.progress-linux.org/packages
+compute-tools container/mirror-security string https://deb.progress-linux.org/packages
+
+compute-tools container/parent-mirror string https://deb.debian.org/debian
+compute-tools container/parent-mirror-security string https://security.debian.org
+
+compute-tools container/archive-areas multiselect main, contrib, non-free, non-free-firmware
+compute-tools container/parent-archive-areas multiselect main, contrib, non-free, non-free-firmware
+
+compute-tools container/packages string knot-resolver openssh-server
+
+compute-tools container/root-password string progress
+#compute-tools container/root-password-crypted string
+
+# Network IP configuration
+compute-tools container/network1/bridge string bridge0
+compute-tools container/network1/veth string veth0
+compute-tools container/network1/ipv4-method select static
+compute-tools container/network1/ipv4-comment string Primary network interfaces
+compute-tools container/network1/ipv4-address string 192.168.0.2
+compute-tools container/network1/ipv4-gateway string 192.168.0.1
+compute-tools container/network1/ipv4-netmask string 255.255.255.0
+#compute-tools container/network1/ipv4-post-up string
+#compute-tools container/network1/ipv4-post-down string
+
+# Network DNS configuration
+compute-tools container/nameserver/server string 127.0.0.1 8.8.8.8 8.8.4.4
+compute-tools container/nameserver/domain string example.net
+compute-tools container/nameserver/search string example.net
+compute-tools container/nameserver/options string timeout:1 attempts:1
+
+# Third-Party Repositories
+#compute-tools container/archive1/repository string
+#compute-tools container/archive1/list string
+#compute-tools container/archive1/comment string
+#compute-tools container/archive1/source string
+#compute-tools container/archive1/key string
+#compute-tools container/archive1/preferences-package string
+#compute-tools container/archive1/preferences-pin string
+#compute-tools container/archive1/preferences-pin-priority
+
+# Internal Options
+#compute-tools container/apt-recommends string
+#compute-tools container/debconf-frontend string
+#compute-tools container/debconf-priority string
+#compute-tools container/container-command string
+#compute-tools container/host-command string
+compute-tools container/auto string true
+#compute-tools container/overlay string
+#compute-tools container/bind string
+#compute-tools container/bind-ro string
diff --git a/share/doc/host-setup.old.txt b/share/doc/host-setup.old.txt
new file mode 100644
index 0000000..69368d1
--- /dev/null
+++ b/share/doc/host-setup.old.txt
@@ -0,0 +1,230 @@
+compute-tools: Host Setup (with ifupdown)
+=========================================
+
+
+1. Debian Packages
+-------------------
+
+apt install bridge-utils ifenslave vlan
+
+
+2. Boot Parameters
+------------------
+
+2.1 CGroup Memory Controller (optional)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to enable the memory controller the following boot parameter needs to be used:
+
+ cgroup_enable=memory
+
+
+2.2 CGroup Swap Controller (optional)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to enable the swap controller the following boot parameter needs to be used:
+
+ swapaccount=1
+
+2.3 vsyscall (legacy)
+~~~~~~~~~~~~~~~~~~~~~
+
+In order to be able to execute binaries linked to older libc versions
+(<= wheezy) on newer linux versions (>= buster), add the following boot
+parameter (see #881813 for more information):
+
+ vsyscall=emulate
+
+
+3. Networking
+~~~~~~~~~~~~~
+
+3.1 Configure Network Bridge
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+3.1.1 Bridge: 1 Interface, standalone, DHCP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/network/interfaces << EOF
+# /etc/network/interfaces
+
+source /etc/network/interfaces.d/*
+
+auto lo
+iface lo inet loopback
+
+iface eno1 inet manual
+
+auto bridge0
+iface bridge0 inet dhcp
+ bridge_ports eno1
+ bridge_fd 0
+ bridge_maxwait 0
+ bridge_stp 0
+EOF
+
+
+3.1.2 Bridge: 1 Interface, standalone, static
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/network/interfaces << EOF
+# /etc/network/interfaces
+
+source /etc/network/interfaces.d/*
+
+auto lo
+iface lo inet loopback
+
+iface eno1 inet manual
+
+auto bridge0
+iface bridge0 inet static
+ address 10.0.0.2
+ gateway 10.0.0.1
+ netmask 24
+
+ pre-up ip link set eno1 down
+ pre-up ip link set eno1 up
+
+ bridge_ports eno1
+ bridge_fd 0
+ bridge_maxwait 0
+ bridge_stp 0
+EOF
+
+
+3.1.3 Bridge: 2 logical Interfaces, subnet, static
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/network/interfaces << EOF
+# /etc/network/interfaces
+
+source /etc/network/interfaces.d/*
+
+auto lo
+iface lo inet loopback
+
+allow-hotplug eno1
+iface eno1 inet dhcp
+
+auto bridge0
+iface bridge0 inet static
+ address 10.0.0.1
+ netmask 24
+
+ pre-up ip link add name bridge0 type bridge
+ post-down ip link delete bridge0 type bridge
+
+ bridge_fd 0
+ bridge_maxwait 0
+ bridge_stp 0
+EOF
+
+
+3.1.4 Bridge: 3 physical Interfaces, vlan, bonding, static
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/network/interfaces << EOF
+# /etc/network/interfaces
+
+source /etc/network/interfaces.d/*
+
+auto lo
+iface lo inet loopback
+
+allow-hotplug eno1
+iface eno1 inet dhcp
+
+iface eno2 inet manual
+
+iface eno3 inet manual
+
+auto bond0
+iface bond0 inet manual
+ up ip link set bond0 up
+ down ip link set bond0 down
+
+ slaves eno2 eno3
+
+ bond-mode 4
+ bond-miimon 100
+ bond-downdelay 200
+ bond-updelay 200
+ bond-lacp-rate 1
+ bond-xmit-hash-policy layer2+3
+
+iface bond0.100 inet manual
+ vlan-raw-device bond0
+
+auto bridge-100
+iface bridge-100 inet static
+ address 10.100.0.2
+ netmask 24
+
+ bridge_ports bond0.100
+ bridge_fd 0
+ bridge_maxwait 0
+ bridge_stp 0
+EOF
+
+
+4. Enabling user namespace for unprivileged containers
+------------------------------------------------------
+
+Linux supports unprivileged containers with the user namespace.
+By default the user namespace is disabled on Debian systems (see #898446).
+To enable user namespace, edit the following file for a permant change:
+
+ /etc/sysctl.d/zz-compute-tools.conf
+ sysctl -p
+
+or enable it manually with:
+
+ echo 1 > /proc/sys/kernel/unprivileged_userns_clone
+
+Note that containers need to be started with the correct
+configuration in /etc/compute-tools/container/config to run unpriviled
+(private-users option).
+
+
+5. Enabling container-shell
+---------------------------
+
+Managing privileged containers requires root privileges. In order to allow
+unprivileged users to manage privileged containers without granting them
+privileges or accounts, the container-shell can be used together with sudo
+and a container user.
+
+ sudo adduser --gecos "compute-tools,,," \
+ --home /var/lib/open-infrastructure/container-shell \
+ --shell /usr/bin/container-shell
+
+
+6. IPv4 and IPv6 dual-stack
+---------------------------
+
+Examples for /etc/network/interfaces above work for IPv6 too when using correct
+IPv6 addresses and netmasks.
+
+In order to use dual-stack, bridges must have a IPv4 address assigned
+(can be a dummy one from a privacy range or 127.0.0.0/8).
+
+Let me repeat: dual-stack only works when you assign a primary IPv6 address
+(private or public, doesn't matter) *and* add an additional IPv4 address.
+Yes, the IPv4 address can be a private address, the containers can still
+have a public IPv4 address.
+
+A complete example looks like this:
+
+auto bridge0
+iface bridge0 inet6 static
+ address 2a07:6b47:4::4:1
+ netmask 48
+
+ up ip addr add 127.4.4.1 dev $IFACE
+ down ip addr del 127.4.4.1 dev $IFACE
+
+ bridge_fd 0
+ bridge_maxwait 0
+ bridge_stp 0
+ bridge-mcquerier 1
diff --git a/share/doc/host-setup.txt b/share/doc/host-setup.txt
new file mode 100644
index 0000000..083e1aa
--- /dev/null
+++ b/share/doc/host-setup.txt
@@ -0,0 +1,217 @@
+compute-tools: Host Setup (with systemd-networkd)
+=================================================
+
+
+1. Debian Packages
+-------------------
+
+apt install systemd-networkd bridge-utils
+
+Make sure to enable networkd (sudo systemctl enable systemd-networkd)
+and convert /etc/network/interfaces (see systemd-networkd documentation).
+
+
+2. Boot Parameters
+------------------
+
+2.1 CGroup Memory Controller (optional)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to enable the memory controller the following boot parameter needs to be used:
+
+ cgroup_enable=memory
+
+
+2.2 CGroup Swap Controller (optional)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to enable the swap controller the following boot parameter needs to be used:
+
+ swapaccount=1
+
+2.3 vsyscall (legacy)
+~~~~~~~~~~~~~~~~~~~~~
+
+In order to be able to execute binaries linked to older libc versions
+(<= wheezy) on newer linux versions (>= buster), add the following boot
+parameter (see #881813 for more information):
+
+ vsyscall=emulate
+
+
+3. Networking
+~~~~~~~~~~~~~
+
+3.1 Configure Network Bridge
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+3.1.1 Bridge: 1 Interface, standalone, DHCP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/systemd/network/bridge0.netdev << EOF
+[NetDev]
+Name=bridge0
+Kind=bridge
+EOF
+
+cat > /etc/systemd/network/bridge0.network << EOF
+[Match]
+Name=bridge-0
+
+[Network]
+DHCP=yes
+EOF
+
+
+3.1.2 Bridge: 1 Interface, standalone, static
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/systemd/network/bridge0.netdev << EOF
+[NetDev]
+Name=bridge0
+Kind=bridge
+EOF
+
+cat > /etc/systemd/network/bridge0.network << EOF
+[Match]
+Name=bridge-0
+
+[Network]
+Address=10.0.0.2/24
+Gateway=10.0.0.1
+EOF
+
+
+3.1.3 Bridge: 3 physical Interfaces, vlan, bonding, static
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cat > /etc/systemd/network/eno2.network<< EOF
+[Match]
+Name=eno2
+
+[Network]
+Bond=bond0
+EOF
+
+cat > /etc/systemd/network/eno3.network<< EOF
+[Match]
+Name=eno3
+
+[Network]
+Bond=bond0
+EOF
+
+cat > /etc/systemd/network/bond0.netdev << EOF
+[NetDev]
+Name=bond0
+Kind=bond
+
+[Bond]
+Mode=802.3ad
+TransmitHashPolicy=layer3+4
+MIIMonitorSec=0.1
+UpDelaySec=0.2
+DownDelaySec=0.2
+EOF
+
+cat > /etc/systemd/network/bond0.network << EOF
+[Match]
+Name=bond0
+
+[Network]
+VLAN=100
+EOF
+
+cat > /etc/systemd/network/vlan-100.netdev << EOF
+[NetDev]
+Name=vlan-100
+Kind=vlan
+
+[VLAN]
+Id=100
+EOF
+
+cat > /etc/systemd/network/vlan-100.netdev << EOF
+[Match]
+Name=vlan-100
+
+[Network]
+Bridge=bridge-100
+EOF
+
+cat > /etc/systemd/network/bridge-100.netdev << EOF
+[NetDev]
+Name=bridge-100
+Kind=bridge
+EOF
+
+cat > /etc/systemd/network/bridge-100.network << EOF
+[Match]
+Name=bridge-100
+
+[Network]
+Address=10.100.0.2/24
+Gateway=10.100.0.1
+EOF
+
+
+4. Enabling user namespace for unprivileged containers
+------------------------------------------------------
+
+Linux supports unprivileged containers with the user namespace.
+By default the user namespace is disabled on Debian systems (see #898446).
+To enable user namespace, edit the following file for a permant change:
+
+ /etc/sysctl.d/zz-compute-tools.conf
+ sysctl -p
+
+or enable it manually with:
+
+ echo 1 > /proc/sys/kernel/unprivileged_userns_clone
+
+Note that containers need to be started with the correct
+configuration in /etc/compute-tools/container/config to run unpriviled
+(private-users option).
+
+
+5. Enabling container-shell
+---------------------------
+
+Managing privileged containers requires root privileges. In order to allow
+unprivileged users to manage privileged containers without granting them
+privileges or accounts, the container-shell can be used together with sudo
+and a container user.
+
+ sudo adduser --gecos "compute-tools,,," \
+ --home /var/lib/open-infrastructure/container-shell \
+ --shell /usr/bin/container-shell
+
+
+6. IPv4 and IPv6 dual-stack
+---------------------------
+
+Examples for /etc/network/interfaces above work for IPv6 too when using correct
+IPv6 addresses and netmasks.
+
+In order to use dual-stack, bridges must have a IPv4 address assigned
+(can be a dummy one from a privacy range or 127.0.0.0/8).
+
+Let me repeat: dual-stack only works when you assign a primary IPv6 address
+(private or public, doesn't matter) *and* add an additional IPv4 address.
+Yes, the IPv4 address can be a private address, the containers can still
+have a public IPv4 address.
+
+A complete example looks like this:
+
+auto bridge0
+iface bridge0 inet6 static
+ address 2a07:6b47:4::4:1
+ netmask 48
+
+ up ip addr add 127.4.4.1 dev $IFACE
+ down ip addr del 127.4.4.1 dev $IFACE
+
+ bridge_fd 0
+ bridge_maxwait 0
+ bridge_stp 0
+ bridge-mcquerier 1
diff --git a/share/get-scripts/curl b/share/get-scripts/curl
new file mode 100755
index 0000000..00a8d73
--- /dev/null
+++ b/share/get-scripts/curl
@@ -0,0 +1,483 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+SCRIPT="${0}"
+export SCRIPT
+
+HOOKS="/etc/${SOFTWARE}/hooks"
+KEYS="/etc/${SOFTWARE}/keys"
+MACHINES="/var/lib/machines"
+
+Parameters ()
+{
+ GETOPT_LONGOPTIONS="bind:,bind-ro:,script:,name:,architecture:,clean,password:,server:,setup:,system:,"
+ GETOPT_OPTIONS="b:,s:,n:,a:,p:"
+
+ PARAMETERS="$(getopt --longoptions ${GETOPT_LONGOPTIONS} --name=${SCRIPT} --options ${GETOPT_OPTIONS} --shell sh -- ${@})"
+
+ if [ "${?}" != "0" ]
+ then
+ echo "'${SCRIPT}': getopt exit" >&2
+ exit 1
+ fi
+
+ eval set -- "${PARAMETERS}"
+
+ while true
+ do
+ case "${1}" in
+ -b|--bind)
+ # ignore
+ shift 2
+ ;;
+
+ --bind-ro)
+ # ignore
+ shift 2
+ ;;
+
+ --cnt.auto)
+ # ignore
+ shift 2
+ ;;
+
+ --cnt.container-server)
+ # ignore
+ shift 2
+ ;;
+
+ -s|--script)
+ # ignore
+ shift 2
+ ;;
+
+ -n|--name)
+ NAME="${2}"
+ shift 2
+ ;;
+
+ -a|--architecture)
+ ARCHITECTURE="${2}"
+ shift 2
+ ;;
+
+ --clean)
+ CLEAN="true"
+ shift 1
+ ;;
+
+ -p|--password)
+ PASSWORD="${2}"
+ shift 2
+ ;;
+
+ --server)
+ SERVER="${2}"
+ shift 2
+ ;;
+
+ --setup)
+ SETUP="${2}"
+ shift 2
+ ;;
+
+ --system)
+ SYSTEM="${2}"
+ shift 2
+ ;;
+
+ --)
+ shift 1
+ break
+ ;;
+
+ *)
+ echo "'${SCRIPT}': getopt error" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+Usage ()
+{
+ echo "Usage: container get -n|--name NAME -s|--script ${SCRIPT} -- [--clean] [-p|--password PASSWORD] [--server SERVER] [--setup SETUP] [--system SYSTEM]" >&2
+ exit 1
+}
+
+Parameters "${@}"
+
+if [ -z "${NAME}" ]
+then
+ Usage
+fi
+
+if [ -e "${MACHINES}/${NAME}" ]
+then
+ echo "'${NAME}': container already exists" >&2
+ exit 1
+fi
+
+if [ ! -x /usr/bin/curl ]
+then
+ echo "'${NAME}': /usr/bin/curl - no such file." >&2
+ exit 1
+fi
+
+if [ "$(id -u)" -ne 0 ]
+then
+ echo "'${NAME}': need root privileges" >&2
+ exit 1
+fi
+
+COMPRESSIONS=""
+
+if [ -x /usr/bin/lzip ]
+then
+ COMPRESSIONS="${COMPRESSIONS} lz"
+fi
+
+if [ -x /usr/bin/xz ]
+then
+ COMPRESSIONS="${COMPRESSIONS} xz"
+fi
+
+if [ -x /bin/gzip ]
+then
+ COMPRESSIONS="${COMPRESSIONS} gz"
+fi
+
+if [ -z "${COMPRESSIONS}" ]
+then
+ echo "'${NAME}': no supported compressor available (lz, xz, gz)."
+ exit 1
+fi
+
+SERVER="${SERVER:-https://get.open-infrastructure.net/system/container/debian}"
+PASSWORD="${PASSWORD:-$(dd if=/dev/urandom bs=12 count=1 2> /dev/null | base64)}"
+CACHE="/var/cache/${PROGRAM}/get-$(basename ${SCRIPT})/$(echo ${SERVER} | sed -e 's|.*//||' -e 's|/|_|g')"
+
+VERSION="$(container version)"
+
+Debconf ()
+{
+ # Configure local debconf
+ mkdir -p "${DEBCONF_TMPDIR}/debconf"
+
+cat > "${DEBCONF_TMPDIR}/debconf.systemrc" << EOF
+Config: configdb
+Templates: templatedb
+
+Name: config
+Driver: File
+Mode: 644
+Reject-Type: password
+Filename: ${DEBCONF_TMPDIR}/debconf/config.dat
+
+Name: passwords
+Driver: File
+Mode: 600
+Backup: false
+Required: false
+Accept-Type: password
+Filename: ${DEBCONF_TMPDIR}/debconf/passwords.dat
+
+Name: configdb
+Driver: Stack
+Stack: config, passwords
+
+Name: templatedb
+Driver: File
+Mode: 644
+Filename: ${DEBCONF_TMPDIR}/debconf/templates.dat
+EOF
+
+ DEBCONF_SYSTEMRC="${DEBCONF_TMPDIR}/debconf.systemrc"
+ export DEBCONF_SYSTEMRC
+}
+
+# Pre hooks
+for FILE in "${HOOKS}/pre-${SCRIPT}".* "${HOOKS}/${NAME}.pre-${SCRIPT}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
+
+# Run
+
+# FIXME: default server via configuration file
+
+if [ -z "${SYSTEM}" ]
+then
+ # Downloading container list
+ if curl --fail --head --output /dev/null --silent "${SERVER}/container-list.txt"
+ then
+ mkdir -p "/tmp/${SOFTWARE}"
+ DEBCONF_TMPDIR="$(mktemp -d -p "/tmp/${SOFTWARE}" -t $(basename ${0}).XXXX)"
+ export DEBCONF_TMPDIR
+
+ if [ -z "${ARCHITECTURE}" ]
+ then
+ case "$(dpkg --print-architecture)" in
+ amd64)
+ GREP_PATTERN="(amd64|i386)"
+ ;;
+ esac
+ fi
+
+ GREP_PATTERN="${GREP_PATTERN:-${ARCHITECTURE}}"
+
+ echo "Downloading $(echo ${SERVER} | awk -F/ '{ print $3 }') container list"
+ curl --fail --location --progress-bar --user-agent ${SOFTWARE}/${VERSION} --http2 \
+ "${SERVER}/container-list.txt" | grep -E "${GREP_PATTERN}" > "${DEBCONF_TMPDIR}/container-list.txt"
+
+ umask 0022
+
+ Debconf
+
+ # Run debconf parts
+ for DEBCONF_SCRIPT in /usr/share/${SOFTWARE}/get-scripts/curl.d/*
+ do
+ if [ -x "${DEBCONF_SCRIPT}" ]
+ then
+ "${DEBCONF_SCRIPT}"
+ fi
+ done
+
+ # Read-in configuration from debconf
+ . "${DEBCONF_TMPDIR}/debconf.default"
+
+ # Remove debconf temporary files
+ rm --preserve-root --one-file-system -rf "${DEBCONF_TMPDIR}"
+ rmdir --ignore-fail-on-non-empty "/tmp/${SOFTWARE}" 2>&1 || true
+ fi
+fi
+
+for COMPRESSION in ${COMPRESSIONS}
+do
+ if curl --fail --head --output /dev/null --silent "${SERVER}/${SYSTEM}.${COMPRESSION}"
+ then
+ SYSTEM="${SYSTEM}.${COMPRESSION}"
+ break
+ fi
+done
+
+# Downloading container files
+mkdir -p "${CACHE}"
+
+SETUP="${SETUP:-$(echo ${SYSTEM} | sed -e 's|.system.tar.|.setup.tar.|')}"
+
+for FILE in "${SYSTEM}" "${SYSTEM}.sig" "${SYSTEM}.sha512" \
+ "${SETUP}" "${SETUP}.sig" "${SETUP}.sha512"
+do
+ if curl --fail --head --output /dev/null --silent "${SERVER}/${FILE}"
+ then
+ case "${FILE}" in
+ *.sha512)
+ if [ -e "${CACHE}/$(basename ${FILE} .sha512).sig" ]
+ then
+ continue
+ fi
+ ;;
+ esac
+
+ if [ -e "${CACHE}/${FILE}" ]
+ then
+ CURL_TIME_COND="--time-cond ${CACHE}/${FILE}"
+ else
+ CURL_TIME_COND=""
+ fi
+
+ echo "Downloading ${FILE}"
+ curl --fail --location --progress-bar --user-agent ${SOFTWARE}/${VERSION} --http2 ${CURL_TIME_COND} \
+ "${SERVER}/${FILE}" -o "${CACHE}/${FILE}"
+ fi
+done
+
+cd "${CACHE}"
+
+for FILE in "${SYSTEM}" "${SETUP}"
+do
+ if [ ! -e "${FILE}" ]
+ then
+ continue
+ fi
+
+ if [ -e "${FILE}.sig" ]
+ then
+ echo -n "Verifying ${FILE}:"
+
+ set +e
+ gpg --homedir "${KEYS}" --verify "${FILE}.sig" "${FILE}" > /dev/null 2>&1
+ GNUPG="${?}"
+ set -e
+
+ case "${GNUPG}" in
+ 0)
+ echo " gpg ok."
+ continue
+ ;;
+
+ *)
+ echo " gpg failed."
+ exit 1
+ ;;
+ esac
+ elif [ -e "${FILE}.sha512" ]
+ then
+ echo -n "Verifying ${FILE}:"
+
+ set +e
+ sha512sum --check "${FILE}.sha512" --status
+ SHA512SUM="${?}"
+ set -e
+
+ case "${SHA512SUM}" in
+ 0)
+ echo " sha512 ok."
+ ;;
+
+ *)
+ echo " sha512 failed."
+ exit 1
+ ;;
+ esac
+ fi
+done
+
+cd "${OLDPWD}"
+
+case "${SYSTEM}" in
+ *.gz)
+ TAR_OPTIONS="--gzip"
+
+ if [ ! -e /bin/gzip ]
+ then
+ echo -en "\n"
+ echo "'${NAME}': /bin/lzip - no such file." >&2
+ exit 1
+ fi
+ ;;
+
+ *.lz)
+ TAR_OPTIONS="--lzip"
+
+ if [ ! -e /usr/bin/lzip ]
+ then
+ echo -en "\n"
+ echo "'${NAME}': /usr/bin/lzip - no such file." >&2
+ exit 1
+ fi
+ ;;
+
+ *.xz)
+ TAR_OPTIONS="--xz"
+
+ if [ ! -e /usr/bin/xz ]
+ then
+ echo -en "\n"
+ echo "'${NAME}': /usr/bin/xz - no such file." >&2
+ exit 1
+ fi
+ ;;
+
+ *)
+ TAR_OPTIONS=""
+ ;;
+esac
+
+for FILE in "${SYSTEM}" "${SETUP}"
+do
+ if [ ! -e "${CACHE}/${FILE}" ]
+ then
+ continue
+ fi
+
+ case "${FILE}" in
+ *.system.tar.*)
+ DIRECTORY="${MACHINES}/${NAME}"
+ ;;
+
+ *.setup.tar.*)
+ DIRECTORY="${MACHINES}/${NAME}/setup"
+ ;;
+ esac
+
+ mkdir -p "${DIRECTORY}"
+
+ if [ -e /usr/bin/pv ]
+ then
+ echo "Unpacking ${FILE}"
+ pv --format '%p' --width 77 "${CACHE}/${FILE}" | tar xf - ${TAR_OPTIONS} -C "${DIRECTORY}" --strip 1
+ else
+ echo -n "Unpacking ${FILE}:"
+ tar xf "${CACHE}/${FILE}" ${TAR_OPTIONS} -C "${DIRECTORY}" --strip 1
+ echo " ok."
+ fi
+done
+
+if [ -x "${MACHINES}/${NAME}/setup/container" ]
+then
+ chroot "${MACHINES}/${NAME}" /usr/bin/env -i \
+ LC_ALL="C" PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games" TERM="${TERM}" \
+ DEBIAN_FRONTEND="dialog" DEBIAN_PRIORITY="low" \
+ DEBCONF_NONINTERACTIVE_SEEN="true" DEBCONF_NOWARNINGS="true" \
+ NAME="${NAME}" \
+ /setup/container
+
+ rm -rf "${MACHINES}/${NAME}/setup"
+fi
+
+# Creating machine-id
+chroot "${MACHINES}/${NAME}" systemd-machine-id-setup > /dev/null 2>&1
+
+# Setting hostname
+echo "${NAME}" > "${MACHINES}/${NAME}/etc/hostname"
+
+# Copying resolv.conf
+cp -L /etc/resolv.conf "${MACHINES}/${NAME}/etc/resolv.conf"
+
+# Setting root password
+echo root:${PASSWORD} | chroot "${MACHINES}/${NAME}" chpasswd
+echo "${NAME}: root password set to '${PASSWORD}'."
+
+# Remove cache
+case "${CLEAN}" in
+ true)
+ rm -f "${CACHE}/${SYSTEM}" "${CACHE}/${SYSTEM}.sha512"
+ rm -f "${CACHE}/${SETUP}" "${CACHE}/${SETUP}.sha512"
+ ;;
+esac
+
+# Post hooks
+for FILE in "${HOOKS}/post-${SCRIPT}".* "${HOOKS}/${NAME}.post-${SCRIPT}"
+do
+ if [ -x "${FILE}" ]
+ then
+ "${FILE}"
+ fi
+done
diff --git a/share/get-scripts/curl.d/0001-debconf b/share/get-scripts/curl.d/0001-debconf
new file mode 100755
index 0000000..5c5936e
--- /dev/null
+++ b/share/get-scripts/curl.d/0001-debconf
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+DEBCONF_NOWARNINGS="true"
+export DEBCONF_NOWARNINGS
+
+. /usr/share/debconf/confmodule
+
+System ()
+{
+ TITLE="$(echo ${SERVER} | awk -F/ '{ print $3 }')"
+
+ SYSTEMS="$(for SYSTEM in $(cat ${DEBCONF_TMPDIR}/container-list.txt | cut -d\| -f2 | sed -e 's| |#|g'); do echo -n "$(echo ${SYSTEM} | sed -e 's|#| |g'), "; done | sed -e 's|, $||')"
+ SYSTEMS_C="$(for SYSTEM_C in $(cat ${DEBCONF_TMPDIR}/container-list.txt | cut -d\| -f1); do echo -n "${SYSTEM_C}, "; done | sed -e 's|, $||')"
+
+ db_subst cnt-curl/title TITLE "${TITLE}"
+
+ db_subst cnt-curl/system CHOICES "${SYSTEMS}"
+ db_subst cnt-curl/system CHOICES_C "${SYSTEMS_C}"
+
+ db_fset cnt-curl/system seen false
+
+ db_settitle cnt-curl/title
+ db_input high cnt-curl/system || true
+ db_go
+
+ db_get cnt-curl/system
+ SYSTEM="${RET}" # select
+
+ echo "SYSTEM=\"${SYSTEM}\"" >> "${DEBCONF_TMPDIR}/debconf.default"
+ export SYSTEM
+}
+
+System
+
+db_stop
diff --git a/share/get-scripts/curl.d/0001-debconf.templates b/share/get-scripts/curl.d/0001-debconf.templates
new file mode 100644
index 0000000..c63994d
--- /dev/null
+++ b/share/get-scripts/curl.d/0001-debconf.templates
@@ -0,0 +1,11 @@
+Template: cnt-curl/title
+Type: title
+Description: ${TITLE}
+
+Template: cnt-curl/system
+Type: select
+Default:
+Choices-C: ${CHOICES_C}
+Choices: ${CHOICES}
+Description: Container list:
+ Select the system to use for downloading the container.
diff --git a/share/hooks/post-start.chown-nvidia.sh b/share/hooks/post-start.chown-nvidia.sh
new file mode 100755
index 0000000..225f13b
--- /dev/null
+++ b/share/hooks/post-start.chown-nvidia.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+CONTAINER="/var/lib/machines"
+
+if grep -qs nvidia "${CONTAINER}/${NAME}/etc/group"
+then
+ chroot "${CONTAINER}/${NAME}" chown root:nvidia "/dev/nvidia*"
+fi
diff --git a/share/hooks/pre-build.git-pull.sh b/share/hooks/pre-build.git-pull.sh
new file mode 100755
index 0000000..f1ae24b
--- /dev/null
+++ b/share/hooks/pre-build.git-pull.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+DIRECTORIES="$(for DIRECTORY in $(find /etc/${SOFTWARE}/debconf/ -type d -name ".git"); do echo $(dirname ${DIRECTORY}); done | sort -uV)"
+
+for DIRECTORY in ${DIRECTORIES}
+do
+ if [ -e "${DIRECTORY}/.git" ] && [ -e /usr/bin/git ]
+ then
+ echo "Updating ${DIRECTORY}..."
+
+ for FILE in "/etc/${SOFTWARE}/${PROGRAM}.conf" "/etc/${SOFTWARE}/${PROGRAM}.conf.d"/*.conf
+ do
+ if [ -e "${FILE}" ]
+ then
+ . "${FILE}"
+ fi
+ done
+
+ DEBCONF_ID="${DEBCONF_ID:-HEAD}"
+
+ cd "${DIRECTORY}"
+
+ git clean -dfx
+ git checkout -f ${DEBCONF_ID}
+ git pull --rebase
+ echo
+
+ cd "${OLDPWD}"
+ fi
+done
diff --git a/share/hooks/pre-get.git-pull.sh b/share/hooks/pre-get.git-pull.sh
new file mode 100755
index 0000000..f1ae24b
--- /dev/null
+++ b/share/hooks/pre-get.git-pull.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+DIRECTORIES="$(for DIRECTORY in $(find /etc/${SOFTWARE}/debconf/ -type d -name ".git"); do echo $(dirname ${DIRECTORY}); done | sort -uV)"
+
+for DIRECTORY in ${DIRECTORIES}
+do
+ if [ -e "${DIRECTORY}/.git" ] && [ -e /usr/bin/git ]
+ then
+ echo "Updating ${DIRECTORY}..."
+
+ for FILE in "/etc/${SOFTWARE}/${PROGRAM}.conf" "/etc/${SOFTWARE}/${PROGRAM}.conf.d"/*.conf
+ do
+ if [ -e "${FILE}" ]
+ then
+ . "${FILE}"
+ fi
+ done
+
+ DEBCONF_ID="${DEBCONF_ID:-HEAD}"
+
+ cd "${DIRECTORY}"
+
+ git clean -dfx
+ git checkout -f ${DEBCONF_ID}
+ git pull --rebase
+ echo
+
+ cd "${OLDPWD}"
+ fi
+done
diff --git a/share/hooks/pre-start.unlink-console.sh b/share/hooks/pre-start.unlink-console.sh
new file mode 100755
index 0000000..cebbe03
--- /dev/null
+++ b/share/hooks/pre-start.unlink-console.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROJECT="open-infrastructure"
+SOFTWARE="compute-tools"
+PROGRAM="container"
+
+CONFIG="/etc/${SOFTWARE}/config"
+
+# Run
+if grep -qs 'bind=.*/dev:/dev;' "${CONFIG}/${NAME}.conf"
+then
+ unlink /dev/console > /dev/null 2>&1 || true
+fi
diff --git a/share/keys/daniel.baumann@open-infrastructure.net_0xB62C61A10B93195F.pub b/share/keys/daniel.baumann@open-infrastructure.net_0xB62C61A10B93195F.pub
new file mode 100644
index 0000000..1e1884d
--- /dev/null
+++ b/share/keys/daniel.baumann@open-infrastructure.net_0xB62C61A10B93195F.pub
@@ -0,0 +1,14 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mDMEXAKTMBYJKwYBBAHaRw8BAQdAqmmCJDP5dgZLR8JflHZa4QF86ahh9gW7/5bd
+HUkkrsS0N0RhbmllbCBCYXVtYW5uIDxkYW5pZWwuYmF1bWFubkBvcGVuLWluZnJh
+c3RydWN0dXJlLm5ldD6IkAQTFggAOBYhBIrjR8Yn591RIGv9hLYsYaELkxlfBQJc
+ApMwAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJELYsYaELkxlf2NUBAPyZ
+GPLameJQ0qqdYhLW9fXqZgsnEEjndBJJWcCgpPolAQDfovZ1AsjVssTV9vcajOWw
+dNa6PGI/gWqoCCqsbK4GC7g4BFwCkzASCisGAQQBl1UBBQEBB0C0e0KJyQVQE8de
+THs48MotPKrefjhM0a22iziA8jWkXQMBCAeIeAQYFggAIBYhBIrjR8Yn591RIGv9
+hLYsYaELkxlfBQJcApMwAhsMAAoJELYsYaELkxlfMIwA/1JQ/fItM3rCfXb/yKIL
+5CNQ4UhrEY0YPHjhAAJAQ8bFAQDlQbUiVlqDVatOh+BIK6cPGjE+FYvuRArIuZHv
+rlmxCA==
+=Tn5F
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/share/keys/daniel@debian.org_0x55CF1BF986ABB9C7.pub b/share/keys/daniel@debian.org_0x55CF1BF986ABB9C7.pub
new file mode 100644
index 0000000..910f870
--- /dev/null
+++ b/share/keys/daniel@debian.org_0x55CF1BF986ABB9C7.pub
@@ -0,0 +1,52 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFPK4YgBEADflMdQSKGvLczvCmdYSeF3nWRE6zYG2DDoeHadp0sCs7jXgVS4
+ulWzuusV2ccAwb2hANmlPC2grEWSSQUs0PykQwgY9PzvYCVw4AGKKua3QPDMBc52
+MT43cOEhCXdcJcuMaovMVkke7YvVqwWVzM2QBXbGsqXtWMuFSFB6JhIqe4pdyyrX
+zIFIwFsU/MuS0K5Wbf4HBkw4JYgM2RUare/9awn/yKsQCQ3jeF5g9IRPz+zhagvT
+6dReJcAZCunCkktwS8Pi7mXk0O9k0C4BV+T6Dw81rsMXwVQF5SWkBCul4evnnUpT
+NUHmZYlht6WAflrd+fyGBHRMsq04GqHze0GeyAQ8DcGhBaHHku2BixSATqrnhud5
+mPL4xQQxOS4/ojBBDxVNNS7sX+2ivYLtdD1pTCQT1Xd869b8eIVCczq/+9GJnL1f
+XHIZuZrjxss1Hb+38LK5fCaKbTSpM0dkSlzHnZKx1BfOXCJp/KAfBTZwxMEh95SK
+IzcbKYzzo1vFUZHOkspW1qo3r4mq8wboAljilJjdyBSVUQKpTYel/p6NCmEmAozH
+CzSV/xiHaf2cfpQau1YEmShD73VTt2b4CVn4sGLrAQNp3S9dCAKpz6u3wXMa8vWI
+3sDq1RtXAX/YV5+VMeTH4LiMuzd3KUUnCb5O+GspBZymoCnCwd266g8eSwARAQAB
+tCdEYW5pZWwgQmF1bWFubiA8bWFpbEBkYW5pZWwtYmF1bWFubi5jaD6JAj0EEwEK
+ACcFAlPK4YgCGwMFCROq0IAFCwkIBwMFFQoJCAsFFgMCAQACHgECF4AACgkQVc8b
++YaruceN+A/+N+2A1Tt11fJ/iyP3hS+3Eaj6oE6bIQLiD9nAJeg9uLMII6lOOEkh
+7Irs+IE8MsiG7DY4wWKahtdci3Vhad71chNXnLOrMKWOk/1VFm+mjMil2oauU3fi
+6mwzb/gNyB3JLCe3oNX7TsqNAJjdPwbrVpwhJXOKKEjFitNoJMAg6m8vtNtIk2yE
+YRTU2VJG7sKaMzvHg7KxlIGsarsamFpLRx7ZnnrcA8ewsvNn6fYF8Zp8W2puScsK
+O26aHfZxrTzzBfxZ/anrPlXkFEvyVI3+qLYbDuLfPEEHQX9zh91++yKu1pYcTb/U
+KZrQIthoJ0RCdHs65uTidTtM+4/jtlUFr07LAZaQr0i8uc2HstNfqIijszvlkPOb
+lobplBB0a+saFI5CeronCzfL6uXMDe57luT6rkd+lxKC0SZ2Ai1Pon4uRbLsiAWW
+SX/DqlOaq0Zmg0vLYo64/rtw5/gbVFdBTidzEUkiX7xjxBahRLH95knPlUyaFXct
+AWERYH9brMoNl9WoPUlo4j8UrItJWXlHTw+LPCPPGNdAwchv4naozGau6xuVyVN7
+UVBXO8YMiWXXHhGQz7pX46R1OpfdoSe2nKOOJkvTL8jUCnTMl8/dFCsm2KwZMDdQ
+IvvQ19ok5QijWZyPJhEUMAb8y++p2KSwclRWHng10jQMBP+o3C8Lpt6IRgQTEQoA
+BgUCU8r6OgAKCRD4LlzASysrnmVZAKCMqPcLD1k/hgkBpZQXcYgryna01QCfV7KM
+hALFW3G/ySPEPv/THC7P2QO5Ag0EU8rhiAEQANVpq7tDaynnl+SJQYf3QX8NuV7T
+tAV/ct+Ehw2IGdv43Sv3fBYUkh16UJyBK9Qx1NP7Dljj/sGlAa3kyOiZsAGagrXU
+B55nrN3LWFJLfph0VGqsJYP9t4eu5RLRD+uathcLwHEWeINoqIb8TKTxJOvvvsvw
+VP2+QaVYKsfvn12jmrjAj1/loBjlwuPMTrwB/U2049LqbTbz+CurLwKPAuRim66r
+7wO4yeZMMlYMwnXljHO0/3WR7n6H5wO16v1QrKCYmg2rheGLeh+SUCrCzNzygP78
+gD1OqH395JQhsJQJxw2apG1dLQETWAaVBpQ+3+3aJrjhyZ4XxfyCRYntpxIhY5GA
+CcGrHkY7/EMNw1dZEMisDFaKfRxgduFjqMNTfwlGHmgnfuEvyVpeZ1zL5nzV8Wgq
+KR5xUcCB0a2UjN2UficpMIsD00R51NlxDgUGT9t+ehLWU56RX8k6O9HXnsyLF0Xo
+ahncubKPg5txU+9MI0i4Mib5pm1gGqgPGHweuUOoL21hljJIfldtbfGwApoQ7jbd
++8mOX5UAXxJDX4IVTd9HX70suhJraIpIVf2qSafJwth1ZM21PET27tGn4xmuA3vW
+sNLLRBKeeQ584n0sKPUMrS/+sRLPYlGwVO7tU1okRdP6SGndVI8xv8nOxheKXqaO
+QxYz2vFMbuWP/1CfABEBAAGJAiUEGAEKAA8FAlPK4YgCGwwFCROq0IAACgkQVc8b
++YaruceOTQ/8C6ZZme6wT6ccw42XHsv8yKFh05TPSWXR3acV1FXzncDMjIMrU097
+Y6+I8xp5y1DULziH177666SOehk3AkHSo7GUIzxLYksOx3RFskBZpQatwThr1x2S
+0YVlxMAi/juZny0rarxTrvk2YAkDC7QCaSXScrn3K03QPjnYSlv73cj2lPAurfgs
+eXL0N4xOmgbwDFnTXnuxLajA8SyuaDclIeHOp5izPQg24AzlMr0iGBZDcRyov1AH
+bkD7NqjX8vZmTEcloYZKM8m8GAx/S52rFTc0V9t+wyNq7ZHAmzu/jqgzGyAeGbnX
+mnCVW4JkrV64wFMJODAOwuJ4crZjnyHqaBAUeukpfeJj0BijskuJfj570Zq+qNHQ
+6JHiHir6kedL/Xg4onNDJyTDMWmg8cRd2vrxclUXk6AfFLb9Wp/8Lf1YmzFnLg4u
+GH3BcO4CJNBS0Z92JQD+Xdvgr7E7P3VbOSVDzJzFsilYhJgCxNkRWU5YbqBRQyG2
+4uVpTF2gu5nkjNJ+HYUWsTjgOP3Avr7KlLWJr3NfQLKhjG4AyKPGvNPgzQpUBE9O
+ADEfyz7xVsngvIcYLT3sN6/qDpFW3QWGfBBhzWGe2ekpIDNHP4lao3oRS/+LGK8j
+gHpGR2pddZzWSsAZIGqHxQEgo9ZpnfBCqub9N5ATiimma5Ot44pBkEw=
+=aSin
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/share/logrotate/container b/share/logrotate/container
new file mode 100644
index 0000000..d1783de
--- /dev/null
+++ b/share/logrotate/container
@@ -0,0 +1,13 @@
+# Open Infrastructure: compute-tools
+
+/var/log/compute-tools/container.log {
+ compress
+ create 0640 root adm
+ dateext
+ dateformat -%Y%m
+ dateyesterday
+ missingok
+ monthly
+ notifempty
+ rotate 12
+}
diff --git a/share/man/Makefile b/share/man/Makefile
new file mode 100644
index 0000000..a878dbd
--- /dev/null
+++ b/share/man/Makefile
@@ -0,0 +1,59 @@
+# Open Infrastructure: compute-tools
+
+# Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Depends: python3-docutils
+
+RST2MAN = rst2man \
+ --no-datestamp \
+ --no-generator \
+ --strict \
+ --strip-comments \
+ --tab-width=4 \
+ --verbose
+
+VERSION := $(shell cat ../../VERSION.txt)
+
+SHELL := sh -e
+
+all: build
+
+build: man
+
+rebuild: clean build
+
+man: man.in *.rst
+ @echo -n "Creating manpages... "
+
+ @for FILE in *.rst; \
+ do \
+ cp man.in $$(basename $${FILE} .rst); \
+ $(RST2MAN) $${FILE} | \
+ sed -e '/^.\\" Man page generated/d' \
+ -e '/^.\\" Generated by/d' \
+ -e "s|^\(.TH .*\) \(\"\" \"\"\) |\1 $${VERSION} compute-tools |" \
+ >> $$(basename $${FILE} .rst); \
+ echo -n "."; \
+ done
+
+ @echo " done."
+
+clean:
+ rm -f *.[0-9]
+
+.PHONY: all clean build rebuild man
diff --git a/share/man/compute-tools.7.rst b/share/man/compute-tools.7.rst
new file mode 100644
index 0000000..33e6aea
--- /dev/null
+++ b/share/man/compute-tools.7.rst
@@ -0,0 +1,153 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=============
+compute-tools
+=============
+
+--------------------------------
+Manage systemd-nspawn containers
+--------------------------------
+
+:manual section: 7
+:manual group: Open Infrastructure
+
+Description
+===========
+
+[A Linux container] is an operating-system-level virtualization environment for
+running multiple isolated Linux systems (containers) on a single Linux control
+host.
+
+ -- Wikipedia (https://en.wikipedia.org/wiki/LXC)
+
+**compute-tools** provides the system integration for managing containers using
+systemd-nspawn(1).
+
+Download
+========
+
+| Upstream Releases:
+| https://get.open-infrastructure.net/software/compute-tools/upstream
+
+| Upstream Sources:
+| https://git.open-infrastructure.net/software/compute-tools
+
+| Debian Releases:
+| https://get.open-infrastructure.net/software/compute-tools/debian
+
+| Debian Sources:
+| https://git.progress-linux.org/users/daniel/debian/packages/open-infrastructure-compute-tools
+
+Installation
+============
+
+Source
+------
+
+| $ sudo apt install git make python3-docutils dbus systemd-container
+| $ git clone https://git.open-infrastructure.net/software/compute-tools
+| $ cd compute-tools && sudo make install
+
+Debian 9 (stretch) and newer
+----------------------------
+
+| $ sudo apt install compute-tools
+
+Development
+===========
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+(https://lists.open-infrastructure.net/listinfo/software).
+
+Please base patches against the 'next' Git branch using common sense
+(https://www.kernel.org/doc/Documentation/SubmittingPatches).
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Known limitations
+=================
+
+This version of compute-tools currently do not work with systemd-networkd and
+depend on ifupdown.
+
+Using overlay, the upper directory can not be an NFS mount due to limitations in
+Linux' overlay filesystem
+(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/overlayfs.txt).
+
+Usage
+=====
+
+Build a new container:
+ sudo container build -n NAME
+
+Start a container:
+ sudo container start -n NAME
+
+Stop a container:
+ sudo container stop -n NAME
+
+Remove a container:
+ sudo container remove -n NAME
+
+List container on the system:
+ sudo container list
+
+Show container version:
+ container version
+
+See container(1) for a list of all container commands.
+
+Links
+=====
+
+| * Linux Weekly News: Kernel / Containers
+| (https://lwn.net/Kernel/Index/#Containers)
+
+| * Linux Weekly News: Security / Containers
+| (https://lwn.net/Security/Index/#Containers)
+
+| * 2016-02-24: Systemd vs. Docker
+| (https://lwn.net/Articles/676831/)
+
+| * 2015-06-10: Systemd and containers
+| (https://lwn.net/Articles/647634/)
+
+| * 2014-07-07: Control groups
+| (https://lwn.net/Articles/604609/)
+
+| * 2013-11-13: Systemd-Nspawn is Chroot on Steroids [LinuxCon Europe]
+| (https://www.youtube.com/watch?v=s7LlUs5D9p4)
+
+| * 2013-11-03: Creating containers with systemd-nspawn
+| (https://lwn.net/Articles/572957/)
+
+| * 2013-02-06: Systemd lightweight containers
+| (https://lwn.net/Articles/536033/)
+
+| * 2013-01-04: Namespaces in operation
+| (https://lwn.net/Articles/531114/)
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-auto.1.rst b/share/man/container-auto.1.rst
new file mode 100644
index 0000000..68836eb
--- /dev/null
+++ b/share/man/container-auto.1.rst
@@ -0,0 +1,92 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+==============
+container-auto
+==============
+
+-------------------------------------------------------
+Start/stop all container automatically at boot/shutdown
+-------------------------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container auto** ['OPTIONS']
+
+Description
+===========
+
+The **container auto** command starts or stops all container on the host system.
+
+Options
+=======
+
+The following **container auto** options are available:
+
+-f, --force:
+ Removing stray lock file if existing.
+
+-s, --start:
+ Start all container on the host system.
+
+-t, --stop:
+ Stop all container on the host system.
+
+Examples
+========
+
+Start all container on the host system:
+
+ sudo container auto --start
+
+Stop all container on the host system:
+
+ sudo container auto --stop
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-build-debconf.1.rst b/share/man/container-build-debconf.1.rst
new file mode 100644
index 0000000..6543140
--- /dev/null
+++ b/share/man/container-build-debconf.1.rst
@@ -0,0 +1,173 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=======================
+container-build-debconf
+=======================
+
+-----------------------------------------------------
+Build an advanced Debian based container with debconf
+-----------------------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container build -s debconf** ['OPTIONS']
+| **cnt b -s debconf** ['OPTIONS']
+
+| **container build -s debian** ['OPTIONS']
+| **cnt b -s debian** ['OPTIONS']
+
+| **container build -s progress-linux** ['OPTIONS']
+| **cnt b -s progress-linux** ['OPTIONS']
+
+Description
+===========
+
+The debconf container build script uses debconf(1) to automatically build a
+Debian based container.
+
+Scope
+-----
+
+Note that this container build script can do a few things more than just
+automatically debootstrap based on a preseed file. It also allows you to set a
+root password, configure the network, install certain packages and execute
+hooks.
+
+But: this is *not* a replacement for a configuration management system (like
+ansible, puppet, etc.). The intenion of this script is to build the initial
+container to that extend that a configuration management system can take over.
+
+As an analogy, think of debian-installer: d-i sets up your system to make it
+ready to boot and connect to the network. Everything after that is out of scope.
+Same goes for this script.
+
+Functions
+---------
+
+This script performs the following configuration on top of a Debian based
+system:
+
+ * network
+ * root password
+ * apt repositories
+ * \.\.\.
+
+Modes
+-----
+
+This container build script can be used under two different names: debian and
+progress-linux.
+
+Alternative, calling it under the debconf name is equal to the debian mode.
+
+Preseeding
+----------
+
+Hierarchy of Preseed Files:
+
+ * The debconf script can be fully preseeded. Such preseed files can include
+ one or more preseed files themselfs (currently, only one layer of includes
+ is supported, no nested or recursive includes).
+
+ * The general rule of 'the later preseed file overwrites the earlier' applies.
+ The debconf script reads the main preseed file (specified either on command
+ line or by debconf selection/input dialog) after any included preseed files
+ in there.
+
+ * That means that debconf values after the include statement in the main
+ preseed file can overwrite any values specified in the included preseed
+ files.
+
+Options
+=======
+
+The following script options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+-p, --preseed-file='FILE':
+ Specify the preseed file.
+
+Examples
+========
+
+Build a Debian based container:
+
+ sudo container build -s debian -n debian.example.net
+
+Build a Progress Linux container:
+
+ sudo container build -s progress-linux -n progress.example.net
+
+Files
+=====
+
+The following files are used:
+
+/etc/compute-tools/config:
+ Container configuration files.
+
+/usr/share/compute-tools/build-scripts:
+ Container build scripts.
+
+/usr/share/doc/compute-tools:
+ Container documentation.
+
+/var/lib/machines:
+ Container directory.
+
+/var/cache/container:
+ Container cache directory.
+
+/tmp/compute-tools:
+ Container temporary directory.
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-build-debootstrap.1.rst b/share/man/container-build-debootstrap.1.rst
new file mode 100644
index 0000000..10538c5
--- /dev/null
+++ b/share/man/container-build-debootstrap.1.rst
@@ -0,0 +1,111 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+===========================
+container-build-debootstrap
+===========================
+
+-------------------------------------------------------------------
+Build a basic Debian based container with debootstrap or mmdebstrap
+-------------------------------------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container build -s debootstrap** ['OPTIONS']
+| **cnt b -s debootstrap** ['OPTIONS']
+
+| **container build -s mmdebstrap** ['OPTIONS']
+| **cnt b -s mmdebstrap** ['OPTIONS']
+
+Description
+===========
+
+The debootstrap container build script uses debootstrap(8) or mmdebstrap(1)
+to build a Debian based container.
+
+This script builds a pure Debian system with three modificiations:
+
+ * apt cache of packages downloaded during debootstrap is cleaned
+ * hostname is set (container name) in /etc/hostname
+ * root password is set (user specified or 16 random characters)
+
+Options
+=======
+
+The following script options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+-a, --architecture='ARCHITECTURE':
+ Specify the Debian architecture, defaults to the host systems architecture.
+
+-d, --distribution='DISTRIBUTION':
+ Specify the Debian distribution, defaults to 'bookworm'.
+
+-m, --mirror='MIRROR':
+ Specify the Debian mirror, defaults to 'https://deb.debian.org/debian'.
+
+-p, --root-password='PASSWORD':
+ Specify the root password, defaults to a random 16 character password.
+
+Examples
+========
+
+Build a Debian 12 (bookworm) based container with same architecture as the host
+system using debootstrap:
+
+ sudo container build -s debootstrap -n bookworm.example.net
+
+Build a Debian 12 (bookworm) based container with different architecture as the
+host system using mmdebstrap:
+
+ sudo container build -s mmdebstrap -n bookworm-i386.example.net -- -a i386
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-build.1.rst b/share/man/container-build.1.rst
new file mode 100644
index 0000000..faa0e16
--- /dev/null
+++ b/share/man/container-build.1.rst
@@ -0,0 +1,139 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+===============
+container-build
+===============
+
+-----------------
+Build a container
+-----------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container build** ['OPTIONS']
+| **cnt b** ['OPTIONS']
+
+Description
+===========
+
+The **container build** command builds a container based on a script.
+
+Scripts
+-------
+
+The following build scripts are available:
+
+debootstrap:
+ Basic script to build Debian based container, see
+ container-build-debootstrap(1).
+
+debconf:
+ Advanced script to automatically build Debian based container, see
+ container-build-debconf(1).
+
+default:
+ Symlink (if existing) to a build script which is used if no script was
+ specified. On Debian based system this can be managed through
+ update-alternatives(1), i.e. 'sudo update-alternatives --config
+ container_build-script'.
+
+Options
+=======
+
+The following **container build** options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+-c, --capability='CAPABILITY':
+ Specify capabilities to grant, see capabilities(7).
+
+-d, --drop-capability='DROP_CAPABILITY':
+ Specify capabilities to drop, see capabilities(7).
+
+-s, --script='SCRIPT':
+ Specify container build script, defaults to 'debootstrap'.
+
+-v, --verbose:
+ Explain what is being done.
+
+-b, --bind='DIRECTORY:DIRECTORY[:OPTIONS][;DIRECTORY:DIRECTORY[:OPTIONS]]':
+ Specify container read-write bind mounts, see systemd-nspawn(1) --bind option.
+
+--bind-ro='DIRECTORY:DIRECTORY[:OPTIONS][;DIRECTORY:DIRECTORY[:OPTIONS]]':
+ Specify container read-only bind mounts, see systemd-nspawn(1) --bind-ro
+ option.
+
+--cnt-overlay='DIRECTORY_LOWER:DIRECTORY_UPPER:DIRECTORY_WORK:DIRECTORY_MERGED[;DIRECTORY_UPPER:DIRECTORY_LOWER:DIRECTORY_WORK:DIRECTORY_MERGED]':
+ Specify container overlay mounts, see Documentation/filesystems/overlayfs.txt.
+
+--cnt.overlay-options='OPTION1,OPTION2[;OPTION3,OPTION4]':
+ Specify container overlay mount options, see
+ Documentation/filesystems/overlayfs.txt.
+
+--cnt.start='OPTION1[,OPTION2,...]':
+ Specify container start options, see container-start(1).
+
+Examples
+========
+
+Build example.net container using debootstrap script:
+
+ sudo container build -n example.net -s debootstrap
+
+Build example.net container using debconf script:
+
+ sudo container build -n example.net -s debconf
+
+Build example.net container with the default build script and start it:
+
+ sudo container build,start -n example.net
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-console.1.rst b/share/man/container-console.1.rst
new file mode 100644
index 0000000..a3afd51
--- /dev/null
+++ b/share/man/container-console.1.rst
@@ -0,0 +1,86 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=================
+container-console
+=================
+
+-------------------------------
+Attach a console to a container
+-------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container console** ['OPTIONS']
+
+Description
+===========
+
+The **container console** command attaches a console to a container.
+
+While 'container enter' bypasses the login prompt and drops to a root shell, the
+'container console' command shows a full login prompt where any valid user and
+password combination can be used.
+
+Options
+=======
+
+The following **container console** options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+Examples
+========
+
+Attach console to example.net container:
+
+ sudo container console -n example.net
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-enter.1.rst b/share/man/container-enter.1.rst
new file mode 100644
index 0000000..65961f5
--- /dev/null
+++ b/share/man/container-enter.1.rst
@@ -0,0 +1,86 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+===============
+container-enter
+===============
+
+---------------------------
+Enter a container namespace
+---------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container enter** ['OPTIONS']
+
+Description
+===========
+
+The **container enter** command enters a container namespace.
+
+While 'container console' shows a full login prompt where any valid user and
+password combination can be used, the 'container enter' command bypasses this
+and drops to a root shell.
+
+Options
+=======
+
+The following **container enter** options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+Examples
+========
+
+Enter to example.net container namespace:
+
+ sudo container enter -n example.net
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-get-curl.1.rst b/share/man/container-get-curl.1.rst
new file mode 100644
index 0000000..01ae592
--- /dev/null
+++ b/share/man/container-get-curl.1.rst
@@ -0,0 +1,148 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+==================
+container-get-curl
+==================
+
+---------------------------------------------------------------------------
+Download a Debian based container by downloading a tarball over the network
+---------------------------------------------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container get -s curl** ['OPTIONS']
+
+Description
+===========
+
+The curl container download script uses curl(1) to download a tarball over the
+network to create a Debian based container.
+
+Depending on the tarball this script otherwise creates a pure Debian system
+with three modificiations:
+
+ * hostname is set (container name) in /etc/hostname
+ * systemd machine-id is generated in /etc/machine-id
+ * root password is set (user specified or 16 random characters)
+
+Container images
+----------------
+
+compute-tools will download tarballs from a server expecting that the images are
+tarballs with either gzip, lzip, xz, or no compression. See container-images.sh
+as an example on how to create your own container images.
+
+Options
+=======
+
+The following script options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+-a, --architecture='ARCHITECTURE':
+ Specify container architecture.
+
+--clean:
+ Remove container tarball after successful download.
+
+-p, --root-password='PASSWORD':
+ Specify the root password, defaults to a random 16 character password.
+
+--server='SERVER':
+ Specify the image server to download from, defaults to
+ 'https://get.open-infrastructure.net/system/container/debian'.
+
+--setup='SETUP':
+ Specify the setup image name to download, defaults to the value specified
+ through --system using the setup.tar.${COMPRESSION} suffix (where
+ ${COMPRESSION} is either lz, xz, or gz depending on compressor availability on
+ the host system).
+
+--system='SYSTEM':
+ Specify the system image name to download, defaults to
+ debian-bookworm-current_${ARCHITECTURE}.system.tar.${COMPRESSION} (where
+ ${ARCHITECTURE} is the host systems architecture and ${COMPRESSION} either
+ lz, xz, or gz depending on compressor availability on the host system).
+
+Examples
+========
+
+Download a Debian 12 (bookworm) based container with same architecture as the host
+system:
+
+ sudo container get -s curl -n bookworm.example.net
+
+Download a Debian 12 (bookworm) based container with different architecture as the
+host system:
+
+ sudo container get -s curl -n bookworm-i386.example.net -- --system debian-bookworm-current_i386.system.tar.xz
+
+Files
+=====
+
+The following files are used:
+
+/etc/compute-tools/config:
+ Container configuration files.
+
+/usr/share/compute-tools/get-scripts:
+ Container download scripts.
+
+/usr/share/doc/compute-tools:
+ Container documentation.
+
+/var/lib/machines:
+ Container directory.
+
+/var/cache/container:
+ Container cache directory.
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-get.1.rst b/share/man/container-get.1.rst
new file mode 100644
index 0000000..8ec61de
--- /dev/null
+++ b/share/man/container-get.1.rst
@@ -0,0 +1,130 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=============
+container-get
+=============
+
+--------------------
+Download a container
+--------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container get** ['OPTIONS']
+| **cnt g** ['OPTIONS']
+
+Description
+===========
+
+The **container get** command downloads a container based on a script.
+
+Scripts
+-------
+
+The following download scripts are available:
+
+curl:
+ Basic script to build Debian based container, see container-create-curl(1).
+
+default:
+ Symlink (if existing) to a download script which is used if no script was
+ specified. On Debian based system this can be managed through
+ update-alternatives(1), i.e. 'sudo update-alternatives --config
+ container_get-script'.
+
+Options
+=======
+
+The following **container get** options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+-c, --capability='CAPABILITY':
+ Specify capabilities to grant, see capabilities(7).
+
+-d, --drop-capability='DROP_CAPABILITY':
+ Specify capabilities to drop, see capabilities(7).
+
+-s, --script='SCRIPT':
+ Specify container build script, defaults to 'debootstrap'.
+
+-v, --verbose:
+ Explain what is being done.
+
+-b, --bind='DIRECTORY:DIRECTORY[:OPTIONS][;DIRECTORY:DIRECTORY[:OPTIONS]]':
+ Specify container read-write bind mounts, see systemd-nspawn(1) --bind option.
+
+--bind-ro='DIRECTORY:DIRECTORY[:OPTIONS][;DIRECTORY:DIRECTORY[:OPTIONS]]':
+ Specify container read-only bind mounts, see systemd-nspawn(1) --bind-ro
+ option.
+
+--cnt-overlay='DIRECTORY_LOWER:DIRECTORY_UPPER:DIRECTORY_WORK:DIRECTORY_MERGED[;DIRECTORY_UPPER:DIRECTORY_LOWER:DIRECTORY_WORK:DIRECTORY_MERGED]':
+ Specify container overlay mounts, see Documentation/filesystems/overlayfs.txt.
+
+--cnt.overlay-options='OPTION1,OPTION2[;OPTION3,OPTION4]':
+ Specify container overlay mount options, see
+ Documentation/filesystems/overlayfs.txt.
+
+--cnt.start='OPTION1[,OPTION2,...]':
+ Specify container start options, see container-start(1).
+
+Examples
+========
+
+Create example.net container using curl script:
+
+ sudo container get -n example.net -s curl
+
+Create example.net container with the default download script and start it:
+
+ sudo container get,start -n example.net
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-info.1.rst b/share/man/container-info.1.rst
new file mode 100644
index 0000000..99ccb55
--- /dev/null
+++ b/share/man/container-info.1.rst
@@ -0,0 +1,100 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+==============
+container-info
+==============
+
+----------------------------------------
+Show specific information of a container
+----------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container info** ['OPTIONS']
+
+Description
+===========
+
+The **container info** command shows specific information of a container.
+
+Options
+=======
+
+The following **container info** options are available, defaults to '--status
+--os --ip':
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will start all stopped container.
+
+--status:
+ Show container status (started|stopped|other).
+
+--os:
+ Show container operating system (FIXME: Debian only).
+
+--ip:
+ Show container IP address.
+
+Examples
+========
+
+Show example.net container status:
+
+ sudo container info -n example.net --status
+
+Show example.net container operating system:
+
+ sudo container info -n example.net --os
+
+Show example.net container IP address:
+
+ sudo container info -n example.net --ip
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-key.1.rst b/share/man/container-key.1.rst
new file mode 100644
index 0000000..ff2b93f
--- /dev/null
+++ b/share/man/container-key.1.rst
@@ -0,0 +1,113 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=============
+container-key
+=============
+
+---------------------------------------------
+Manage GnuPG keyring for container operations
+---------------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container key** ['OPTIONS']
+
+Description
+===========
+
+The **container key** command manages the GnuPG keyring for container
+operations.
+
+Options
+=======
+
+The following **container key** options are available:
+
+-a, --add='KEY_FILE|KEY_ID':
+ Add a key to the keyring.
+
+-l, --list':
+ List keys in the keyring.
+
+-r, --remove='KEY':
+ Remove a key from the keyring.
+
+Examples
+========
+
+Add a key to the keyring manually:
+
+ gpg --keyserver hkps://keys.openpgp.org --recv 0x55CF1BF986ABB9C7
+ gpg --armor --export 0x55CF1BF986ABB9C7 | sudo container key --add -
+
+Assisted adding of the same key:
+
+ sudo container key --add 0x55CF1BF986ABB9C7
+
+Remove a key from the keyring:
+
+ sudo container key --remove 0x55CF1BF986ABB9C7
+
+List keys in the keyring:
+
+ sudo container key --list
+
+Files
+=====
+
+The following files are used:
+
+/etc/compute-tools/keys:
+ Active container keyring.
+
+/usr/share/compute-tools/keys:
+ Inactive container keyring library.
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-limit.1.rst b/share/man/container-limit.1.rst
new file mode 100644
index 0000000..715314e
--- /dev/null
+++ b/share/man/container-limit.1.rst
@@ -0,0 +1,121 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+===============
+container-limit
+===============
+
+------------------------------
+Limit resources of a container
+------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container limit** ['OPTIONS']
+
+Description
+===========
+
+The **container limit** command limits resources available to a container at
+runtime.
+
+Options
+=======
+
+The following **container limit** options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+--blockio-device-weight='DEVICE WEIGHT':
+ Specify device specific blockio weight, see systemd.resource-control(5).
+
+--blockio-read-bandwidth='DEVICE BYTES':
+ Specify device specific blockio read bandwidth, see
+ systemd.resource-control(5).
+
+-b, --blockio-weight='WEIGHT':
+ Specify general blockio weight, see systemd.resource-control(5).
+
+--blockio-write-bandwidth='DEVICE BYTES':
+ Specify device specific blockio write bandwidth, see
+ systemd.resource-control(5).
+
+-c, --cpu-quota='QUOTA':
+ Specify CPU quota, see systemd.resource-control(5).
+
+--cpu-shares='SHARES':
+ Specify CPU shares, see systemd.resource-control(5).
+
+-m, --memory-limit='BYTES':
+ Specify memory limit, see systemd.resource-control(5).
+
+-t, --tasks-max='NUMBER':
+ Specify tasks max, see systemd.resource-control(5).
+
+Examples
+========
+
+Set blockio weight for the example.net container:
+
+ sudo container limit -n example.net --blockio-weight 100
+
+Set CPU quota for the example.net container:
+
+ sudo container limit -n example.net --cpu-quota 10%
+
+Set memory limit for the example.net container to 1GB:
+
+ sudo container limit -n example.net --memory-limit 1G
+
+Set tasks max for the example.net container to 100:
+
+ sudo container limit -n example.net --tasks-max 100
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-list.1.rst b/share/man/container-list.1.rst
new file mode 100644
index 0000000..81a394b
--- /dev/null
+++ b/share/man/container-list.1.rst
@@ -0,0 +1,145 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+==============
+container-list
+==============
+
+----------------------------
+List container on the system
+----------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container list** ['OPTIONS']
+| **cnt ls** ['OPTIONS']
+
+Description
+===========
+
+The **container list** command lists container on the system.
+
+Options
+=======
+
+The following **container list** options are available, defaults to '--started
+--stopped':
+
+-a, --all:
+ List all available container (started, stopped, and other).
+
+--csv-separator='SEPARATOR':
+ Specify custom CSV separator, defaults to ','.
+
+-f, --format='FORMAT':
+ Use format to list container. Currently available formats are 'cli' (default),
+ 'csv', 'json', 'nwdiag', 'shell', 'sh', 'yaml', or 'xml'.
+
+-h, --host='HOSTNAME':
+ List only container that are enabled for automatic start on the specified
+ hostname. Defaults to list containers of the local system only. Using 'all'
+ shows all container regardless of any automatic start configuration.
+
+--nwdiag-color='COLOR':
+ Specify custom nwdiag color for the host box, defaults to '#3465a4'.
+
+--nwdiag-label='LABEL':
+ Specify custom nwdiag label for the diagram, defaults to empty.
+
+-o, --other:
+ List only container that are not enable for automatic start on the current
+ system.
+
+-s, --started:
+ List only started container.
+
+-t, --stopped:
+ List only stopped container.
+
+Examples
+========
+
+List all started and stopped containers of the local system:
+
+ sudo container list
+
+List all started and other containers:
+
+ sudo container list -s -o
+
+Create a CSV export of all started and stopped containers:
+
+ sudo container list -f csv
+
+Create a JSON export of all started and stopped containers:
+
+ sudo container list -f json
+
+Create a nwdiag export of all started and stopped containers:
+
+ sudo container list -f nwdiag
+
+Create a SVG image via nwdiag of all started and stopped containers:
+
+ sudo container list -f nwdiag | nwdiag -T svg -o cnt-list.svg -
+
+Create a shell export of all started and stopped containers:
+
+ sudo container list -f shell
+ sudo container list -f sh
+
+Create a YAML export of all started and stopped containers:
+
+ sudo container list -f yaml
+
+Create a XML export of all started and stopped containers:
+
+ sudo container list -f xml
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-log.1.rst b/share/man/container-log.1.rst
new file mode 100644
index 0000000..5e72184
--- /dev/null
+++ b/share/man/container-log.1.rst
@@ -0,0 +1,101 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=============
+container-log
+=============
+
+------------------
+Show container log
+------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container log** ['OPTIONS']
+
+Description
+===========
+
+The **container log** command shows the container log.
+
+Options
+=======
+
+The following **container log** options are available:
+
+-d, --date:
+ Show only log entries of the specified date as 'YYYY-MM-DD' or a date range like 'today-7'.
+
+-n, --name:
+ Show only log entries for the specified container.
+
+Examples
+========
+
+Show all log entries:
+
+ sudo container log
+
+Show only log entries of today:
+
+ sudo container log -d today
+
+Show only log entries of yesterday:
+
+ sudo container log -d yesterday
+
+Show all log entries of the example.net container:
+
+ sudo container log -n example.net
+
+Show only log entries of the example.net container of the last 30 days:
+
+ sudo container log -d today-30 -n example.net
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-move.1.rst b/share/man/container-move.1.rst
new file mode 100644
index 0000000..ecbea6b
--- /dev/null
+++ b/share/man/container-move.1.rst
@@ -0,0 +1,93 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+==============
+container-move
+==============
+
+------------------
+Rename a container
+------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container move** ['OPTIONS']
+| **cnt mv** ['OPTIONS']
+
+Description
+===========
+
+The **container move** commands renames a container.
+
+Options
+=======
+
+The following **container move** options are available:
+
+-n, --new='NAME':
+ Specify new container name.
+
+-f, --force:
+ Do not prompt before moving.
+
+-o, --old:
+ Specify old container name.
+
+Examples
+========
+
+Rename example.net container to example.org:
+
+ sudo container move -n example.org -o example.net
+
+Rename example.net container to example.org without prompt:
+
+ sudo container move -n example.org -o example.net -f
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-rebuild.1.rst b/share/man/container-rebuild.1.rst
new file mode 100644
index 0000000..345ec01
--- /dev/null
+++ b/share/man/container-rebuild.1.rst
@@ -0,0 +1,93 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=================
+container-rebuild
+=================
+
+-------------------
+Restart a container
+-------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container rebuild** ['OPTIONS']
+| **cnt rb** ['OPTIONS']
+
+Description
+===========
+
+The **container rebuild** command rebuilds a container by stopping, building, starting an existing container.
+
+Options
+=======
+
+The following **container rebuild** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will rebuild all started container.
+
+-f, --force:
+ Do not fail if container is running.
+
+-v, --verbose:
+ Explain what is being done.
+
+Examples
+========
+
+Rebuild example.net container:
+
+ sudo container rebuild -n example.net
+
+Restart all container:
+
+ sudo container rebuild -n ALL
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-remove.1.rst b/share/man/container-remove.1.rst
new file mode 100644
index 0000000..00f1ad1
--- /dev/null
+++ b/share/man/container-remove.1.rst
@@ -0,0 +1,104 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+================
+container-remove
+================
+
+------------------
+Remove a container
+------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container remove** ['OPTIONS']
+| **cnt rm** ['OPTIONS']
+
+Description
+===========
+
+The **container remove** command removes a container.
+
+Options
+=======
+
+The following **container remove** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will remove all stopped container.
+
+--allow-stop:
+ Stop container prior removal.
+
+-f, --force:
+ Do not prompt before removal.
+
+-v, --verbose:
+ Explain what is being done.
+
+Examples
+========
+
+Remove example.net container from the system:
+
+ sudo container remove -n example.net
+
+Remove example.net container from the system without prompt:
+
+ sudo container remove -n example.net -f
+
+Remove a running container from the system, without prompt:
+
+ sudo container remove -n example.net -f --allow-stop
+
+Remove all container:
+
+ sudo container remove -n ALL
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-restart.1.rst b/share/man/container-restart.1.rst
new file mode 100644
index 0000000..c52353d
--- /dev/null
+++ b/share/man/container-restart.1.rst
@@ -0,0 +1,96 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=================
+container-restart
+=================
+
+-------------------
+Restart a container
+-------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container restart** ['OPTIONS']
+| **cnt rs** ['OPTIONS']
+
+Description
+===========
+
+The **container restart** command restarts a container.
+
+Options
+=======
+
+The following **container restart** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will restart all started container.
+
+-f, --force:
+ Do not prompt before every restarting.
+
+-i, --interactive:
+ Prompt before every restarting (default).
+
+-v, --verbose:
+ Explain what is being done.
+
+Examples
+========
+
+Restart example.net container:
+
+ sudo container restart -n example.net
+
+Restart all container:
+
+ sudo container restart -n ALL
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-run.1.rst b/share/man/container-run.1.rst
new file mode 100644
index 0000000..0fb923d
--- /dev/null
+++ b/share/man/container-run.1.rst
@@ -0,0 +1,88 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=============
+container-run
+=============
+
+-----------------------------------------
+Execute commands in a container namespace
+-----------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container run** ['OPTIONS'] -- 'COMMAND'\|"COMMANDS"
+| **cnt r** ['OPTIONS'] -- 'COMMAND'\|"COMMANDS"
+
+Description
+===========
+
+The **container run** command executes arbitrary commands as root in a container
+namespace.
+
+Options
+=======
+
+The following **container run** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will start all stopped container.
+
+Examples
+========
+
+Run 'hostname' in example.net container:
+
+ sudo container run -n example.net -- hostname
+
+Create and delete a file in example.net container:
+
+ sudo container run -n example.net -- 'touch /tmp/foo && rm -f /tmp/foo'
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-shell.1.rst b/share/man/container-shell.1.rst
new file mode 100644
index 0000000..b12958f
--- /dev/null
+++ b/share/man/container-shell.1.rst
@@ -0,0 +1,141 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+===============
+container-shell
+===============
+
+----------------------------------------
+Manage systemd-nspawn containers (shell)
+----------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container-shell** ['OPTIONS']
+| **cntsh** ['OPTIONS']
+
+Description
+===========
+
+compute-tools provides the system integration for managing containers using
+systemd-nspawn.
+
+Usage
+-----
+
+Although the **container-shell** can be started from a running system like any
+other program, the main intend is to use the **container-shell** via SSH. That
+way otherwise unprivileged users have possibility to manage containers without
+needing a regular shell login on the container server.
+
+For usage over SSH a unprivileged user should be created:
+
+|
+| sudo adduser --gecos "compute-tools,,," \\
+| --home /var/lib/open-infrastructure/container-shell \\
+| --shell /usr/bin/container-shell
+
+The container-shell can then be allowed for specific SSH keys via
+/var/lib/compute-tools/container-shell/.ssh/authorized_keys like so:
+
+|
+| command="/usr/bin/container-shell",no-port-forwarding,no-X11-forwarding,\\
+| no-agent-forwarding,no-pty ssh-ed25519 [...]
+
+Restricted shell
+----------------
+
+The container-shell by default grants any user that has access to it to use all available container commands.
+
+Through two corresponding environment variables users can be allowed or disallowed to use specific container commands.
+In connection with SSH this makes it possible to grant certain SSH keys (and by that, users) privileges to operate container
+servers without having to give them root access, a login shell at all and prevents them from doing things they are not trusted to do.
+
+Example (blacklisting)
+^^^^^^^^^^^^^^^^^^^^^^
+
+In order to allow all commands except for removing and stopping containers, the
+following variable can be used:
+
+|
+| command="CONTAINER_COMMANDS_DISABLE='remove stop' \\
+| /usr/bin/container-shell",no-port-forwarding,no-X11-forwarding,\\
+| no-agent-forwarding,no-pty ssh-ed25519 [...]
+
+Example (whitelisting)
+^^^^^^^^^^^^^^^^^^^^^^
+
+The other way around works too. To disallow all commands except for listing
+containers and showing the compute-tools version, the following variable can be
+used:
+
+|
+| command="CONTAINER_COMMANDS_ENABLE='list version' \\
+| /usr/bin/container-shell",no-port-forwarding,no-X11-forwarding,\\
+| no-agent-forwarding,no-pty ssh-ed25519 [...]
+
+Commands
+========
+
+All container commands are available, see container(1). Additionally, the
+following commands are specific to container-shell:
+
+about:
+ Shows introduction (manpage).
+
+help:
+ Shows available commands within the container-shell.
+
+help COMMAND:
+ Shows help (manpage) for a specific container command.
+
+logout, exit:
+ Exits container-shell.
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-start.1.rst b/share/man/container-start.1.rst
new file mode 100644
index 0000000..65d4af7
--- /dev/null
+++ b/share/man/container-start.1.rst
@@ -0,0 +1,93 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+===============
+container-start
+===============
+
+-----------------
+Start a container
+-----------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container start** ['OPTIONS']
+| **cnt s** ['OPTIONS']
+
+Description
+===========
+
+The **container start** command starts a container.
+
+Options
+=======
+
+The following **container start** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will start all stopped container.
+
+-f, --force':
+ Removing stray lock file if existing.
+
+-v, --verbose:
+ Explain what is being done.
+
+Examples
+========
+
+Start example.net container:
+
+ sudo container start -n example.net
+
+Start all container:
+
+ sudo container start -n ALL
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-status.1.rst b/share/man/container-status.1.rst
new file mode 100644
index 0000000..ad51ba7
--- /dev/null
+++ b/share/man/container-status.1.rst
@@ -0,0 +1,83 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+================
+container-status
+================
+
+---------------------
+Show container status
+---------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container status** ['OPTIONS']
+| **cnt st** ['OPTIONS']
+
+Description
+===========
+
+The **container status** command displays the status of a container.
+
+Options
+=======
+
+The following **container status** options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+Examples
+========
+
+show status of example.net container:
+
+ sudo container status -n example.net
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-stop.1.rst b/share/man/container-stop.1.rst
new file mode 100644
index 0000000..bf668be
--- /dev/null
+++ b/share/man/container-stop.1.rst
@@ -0,0 +1,108 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+==============
+container-stop
+==============
+
+----------------
+Stop a container
+----------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container stop** ['OPTIONS']
+| **cnt t** ['OPTIONS']
+
+Description
+===========
+
+The **container stop** command stops a container by running the proper shutdown
+sequence.
+
+Options
+=======
+
+The following **container stop** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will stop all started container.
+
+-f, --force:
+ Do not prompt before every stopping.
+
+-i, --interactive:
+ Prompt before every stopping (default).
+
+-k, --kill:
+ Instead of running the proper shutdown sequence, terminate all processes of the container imediatly.
+
+-v, --verbose:
+ Explain what is being done.
+
+Examples
+========
+
+Shutdown example.net container:
+
+ sudo container stop -n example.net
+
+Shutdown example.net container without prompting:
+
+ sudo container stop -n example.net -f
+
+Immediately stop example.net container:
+
+ sudo container stop -n example.net -k
+
+Stop all container:
+
+ sudo container stop -n ALL
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-top.1.rst b/share/man/container-top.1.rst
new file mode 100644
index 0000000..85b3627
--- /dev/null
+++ b/share/man/container-top.1.rst
@@ -0,0 +1,81 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=============
+container-top
+=============
+
+------------------------------------
+Dynamic list container on the system
+------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container top** ['OPTIONS']
+
+Description
+===========
+
+The **container top** command dynamically lists container on the system.
+
+Options
+=======
+
+The following **container top** options are available, defaults to '--delay 1':
+
+-d, --delay='SECONDS[.TENTHS]':
+ Specifies the delay between screen updates, defaults to '1'.
+
+Examples
+========
+
+Dynamically list containers of the local system:
+ sudo container top
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-update.1.rst b/share/man/container-update.1.rst
new file mode 100644
index 0000000..ec64f6b
--- /dev/null
+++ b/share/man/container-update.1.rst
@@ -0,0 +1,114 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+================
+container-update
+================
+
+--------------------------------------------
+Update the packages installed in a container
+--------------------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container update** ['OPTIONS']
+| **cnt u** ['OPTIONS']
+
+Description
+===========
+
+The **container update** command updates packages installed in a container.
+
+Options
+=======
+
+The following **container update** options are available:
+
+-n, --name='NAME':
+ Specify container name. Specifying 'ALL' will start all stopped container.
+
+-f, --full-upgrade:
+ Runs an additional 'apt full-upgrade' after 'apt upgrade'.
+
+-i, --interactive:
+ Prompt before every container update.
+
+-r, --autoremove:
+ Runs an additional 'apt autoremove' after 'apt upgrade'.
+
+-p, --purge:
+ Passing '--purge' to 'apt autoremove'.
+
+-y|--yes:
+ Passing 'yes' to all questions asked by the package manager.
+
+Examples
+========
+
+Update example.net container (apt update && apt upgrade):
+
+ sudo container update -n example.net
+
+Update example.net container without asking questions (apt update && apt --yes
+upgrade):
+
+ sudo container update -n example.net -y
+
+Full update of example.net container without asking questions (apt update &&
+apt --yes upgrade && apt --yes full-upgrade):
+
+ sudo container update -n example.net -f -y
+
+Full update of all container on the host, with asking questions and
+purging unused packages (apt update && apt upgrade && apt full-upgrade && apt
+autoremove):
+
+ sudo container update -n ALL -f -r -p -y
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container-version.1.rst b/share/man/container-version.1.rst
new file mode 100644
index 0000000..3f0266d
--- /dev/null
+++ b/share/man/container-version.1.rst
@@ -0,0 +1,79 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=================
+container-version
+=================
+
+----------------------
+Show container version
+----------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container version** ['OPTIONS']
+
+Description
+===========
+
+The **container version** command shows the container version number.
+
+Options
+=======
+
+The **container version** command has no options.
+
+Examples
+========
+
+Show container version:
+
+ container version
+
+See also
+========
+
+| compute-tools(7),
+| container(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/container.1.rst b/share/man/container.1.rst
new file mode 100644
index 0000000..c08cbd9
--- /dev/null
+++ b/share/man/container.1.rst
@@ -0,0 +1,171 @@
+.. Open Infrastructure: compute-tools
+
+.. Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+..
+.. SPDX-License-Identifier: GPL-3.0+
+..
+.. This program is free software: you can redistribute it and/or modify
+.. it under the terms of the GNU General Public License as published by
+.. the Free Software Foundation, either version 3 of the License, or
+.. (at your option) any later version.
+..
+.. This program is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. You should have received a copy of the GNU General Public License
+.. along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+=========
+container
+=========
+
+--------------------------------
+Manage systemd-nspawn containers
+--------------------------------
+
+:manual section: 1
+:manual group: Open Infrastructure
+
+Synopsis
+========
+
+| **container** 'COMMAND' ['OPTIONS']
+| **container** 'COMMAND1','COMMAND2',... 'COMMANDn'
+
+Description
+===========
+
+compute-tools provides the system integration for managing containers using
+systemd-nspawn.
+
+Options
+=======
+
+The following **container** common options are available:
+
+-n, --name='NAME':
+ Specify container name.
+
+Commands
+========
+
+The following **container** commands are available:
+
+build:
+ Build a new container, see container-build(1).
+
+start:
+ Start a container, see container-start(1).
+
+rebuild:
+ Rebuild a container, see container-rebuild(1).
+
+restart:
+ Restart a container, see container-restart(1).
+
+stop:
+ Stop a container, see container-stop(1).
+
+remove:
+ Remove a container, see container-remove(1).
+
+move:
+ Rename a container, see container-move(1).
+
+console:
+ Attach console to a container, see container-console(1).
+
+enter:
+ Enter a container namespace, see container-enter(1).
+
+run:
+ Execute commands in a container namespace, see container-run(1).
+
+info:
+ Show specific information of a container, see container-info(1).
+
+key:
+ Manage GnuPG keyring for container operations, see container-key(1).
+
+limit:
+ Limit resources of a container, see container-limit(1).
+
+list:
+ List container on the system, see container-list(1).
+
+log:
+ Show container log, see container-log(1).
+
+status:
+ Show container status, see container-status(1).
+
+top:
+ Dynamic list of container on the system, see container-top(1).
+
+update:
+ Update the packages installed in a container.
+
+version:
+ Show container version, see container-version(1).
+
+Files
+=====
+
+The following files are used:
+
+/etc/compute-tools/container.conf, /etc/compute-tools/container.conf.d/\*.conf:
+ Container configuration files.
+
+/usr/bin/container, /usr/bin/cnt:
+ Container program.
+
+/usr/bin/container-shell, /usr/bin/cntsh:
+ Container shell program.
+
+/usr/libexec/container:
+ Container commands.
+
+/usr/share/compute-tools/:
+ Container shared data.
+
+/usr/share/doc/compute-tools:
+ Container documentation files.
+
+/var/cache/container:
+ Container cache directory.
+
+/var/lib/machines:
+ Container root directory.
+
+/var/log/compute-tools:
+ Container log files.
+
+See also
+========
+
+| machinectl(1),
+| systemd-nspawn(1).
+
+Homepage
+========
+
+More information about compute-tools and the Open Infrastructure project can be
+found on the homepage (https://open-infrastructure.net).
+
+Contact
+=======
+
+Bug reports, feature requests, help, patches, support and everything else are
+welcome on the Open Infrastructure Software Mailing List
+<software@lists.open-infrastructure.net>.
+
+Debian specific bugs can also be reported in the Debian Bug Tracking System
+(https://bugs.debian.org).
+
+Authors
+=======
+
+compute-tools were written by Daniel Baumann
+<daniel.baumann@open-infrastructure.net> and others.
diff --git a/share/man/man.in b/share/man/man.in
new file mode 100644
index 0000000..45a5f40
--- /dev/null
+++ b/share/man/man.in
@@ -0,0 +1,19 @@
+.\" Open Infrastructure: compute-tools
+.\"
+.\" Copyright (C) 2014-2022 Daniel Baumann <daniel.baumann@open-infrastructure.net>
+.\"
+.\" SPDX-License-Identifier: GPL-3.0+
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <https://www.gnu.org/licenses/>.
+.\"
diff --git a/share/needrestart/container-tools.conf b/share/needrestart/container-tools.conf
new file mode 100644
index 0000000..cd1c76b
--- /dev/null
+++ b/share/needrestart/container-tools.conf
@@ -0,0 +1,6 @@
+# Open Infrastructure: compute-tools
+
+$nrconf{blacklist_rc} = [
+ # container-tools
+ qr(^container@(.*).service) => 0,
+];
diff --git a/share/procps/zz-container.conf b/share/procps/zz-container.conf
new file mode 100644
index 0000000..61c047d
--- /dev/null
+++ b/share/procps/zz-container.conf
@@ -0,0 +1,18 @@
+# Open Infrastructure: compute-tools
+
+# The default limits are set to low for running many containers
+# and eventually lead to errors like the following on container start:
+#
+# Failed to allocate directory watch: Too many open files
+
+# /proc/sys/fs/inotify/max_queued_events defaults to 16384
+fs.inotify.max_queued_events=1048576
+
+# /proc/sys/fs/inotify/max_user_instances defaults to 128
+fs.inotify.max_user_instances=1048576
+
+# /proc/sys/fs/inotify/max_user_watches defaults to 8192
+fs.inotify.max_user_watches=1048576
+
+# Enabling user namespace, disabled by default (#898446)
+#kernel.unprivileged_userns_clone=1
diff --git a/share/sudo/container-shell b/share/sudo/container-shell
new file mode 100644
index 0000000..c4108a6
--- /dev/null
+++ b/share/sudo/container-shell
@@ -0,0 +1,3 @@
+# Open Infrastructure: compute-tools
+
+container ALL=NOPASSWD: /usr/bin/container
diff --git a/share/systemd/container-auto.service b/share/systemd/container-auto.service
new file mode 100644
index 0000000..50f8ac6
--- /dev/null
+++ b/share/systemd/container-auto.service
@@ -0,0 +1,18 @@
+# Open Infrastructure: compute-tools
+
+[Unit]
+Description=compute-tools automatic start and stop
+Documentation=man:container-auto
+After=network.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/bin/container auto --start
+ExecStop=/usr/bin/container auto --stop
+Delegate=yes
+StandardOutput=journal
+StandardError=journal
+
+[Install]
+WantedBy=multi-user.target
diff --git a/share/systemd/container@.service b/share/systemd/container@.service
new file mode 100644
index 0000000..4bd7be5
--- /dev/null
+++ b/share/systemd/container@.service
@@ -0,0 +1,16 @@
+# Open Infrastructure: compute-tools
+
+[Unit]
+Description="Container: %i"
+Documentation=man:compute-tools
+
+[Service]
+Type=simple
+Environment=TERM=xterm-256color
+ExecStart=/usr/bin/container start --name %i --nspawn --no-notification
+ExecStartPost=/usr/bin/container start --name %i --start --no-notification
+ExecStopPost=/usr/bin/container stop -n %i --clean --no-notification
+KillMode=mixed
+
+[Install]
+WantedBy=multi-user.target