3
0
Fork 0
forked from mirrors/nixpkgs
nixpkgs/nixos/modules/virtualisation/nixos-container.sh
Eelco Dolstra ba88db3cd3 Add support for imperative container management
The command nixos-container can now create containers.  For instance,
the following creates and starts a container named ‘database’:

  $ nixos-container create database

The configuration of the container is stored in
/var/lib/containers/<name>/etc/nixos/configuration.nix.  After editing
the configuration, you can make the changes take effect by doing

  $ nixos-container update database

The container can also be destroyed:

  $ nixos-container destroy database

Containers are now executed using a template unit,
‘container@.service’, so the unit in this example would be
‘container@database.service’.
2014-03-24 12:19:27 +01:00

139 lines
3.8 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! @bash@/bin/sh -e
usage() {
echo "Usage: $0 create <container-name> [--config <filename>]" >&2
echo " $0 update <container-name>" >&2
echo " $0 destroy <container-name>" >&2
echo " $0 login <container-name>" >&2
echo " $0 root-shell <container-name>" >&2
echo " $0 set-root-password <container-name> <password>" >&2
}
args="`getopt --options '' -l help -l config: -- "$@"`"
eval "set -- $args"
extraConfigFile=
while [ $# -gt 0 ]; do
case "$1" in
(--help) usage; exit 0;;
(--config) shift; extraConfigFile=$1;;
(--) shift; break;;
(*) break;;
esac
shift
done
action="$1"
if [ -z "$action" ]; then usage; exit 1; fi
shift
getContainerRoot() {
root="/var/lib/containers/$container"
if ! [ -d "$root" ]; then
echo "$0: container $container does not exist" >&2
exit 1
fi
}
container="$1"
if [ -z "$container" ]; then usage; exit 1; fi
shift
if [ $action = create ]; then
confFile="/etc/containers/$container.conf"
root="/var/lib/containers/$container"
if [ -e "$confFile" -o -e "$root/nix" ]; then
echo "$0: container $container already exists" >&2
exit 1
fi
profileDir="/nix/var/nix/profiles/per-container/$container"
mkdir -m 0755 -p "$root/etc/nixos" "$profileDir"
config="
{ config, pkgs, ... }:
with pkgs.lib;
{ boot.isContainer = true;
security.initialRootPassword = mkDefault \"!\";
networking.hostName = mkDefault \"$container\";
networking.useDHCP = false;
imports = [ <nixpkgs/nixos/modules/virtualisation/container-login.nix> $extraConfigFile ];
}"
configFile="$root/etc/nixos/configuration.nix"
echo "$config" > "$configFile"
nix-env -p "$profileDir/system" -I "nixos-config=$configFile" -f '<nixpkgs/nixos>' --set -A system
# Allocate a new /8 network in the 10.233.* range.
network="$(sed -e 's/.*_ADDRESS=10\.233\.\(.*\)\..*/\1/; t; d' /etc/containers/*.conf | sort -n | tail -n1)"
if [ -z "$network" ]; then network=0; else : $((network++)); fi
hostAddress="10.233.$network.1"
localAddress="10.233.$network.2"
echo "host IP is $hostAddress, container IP is $localAddress" >&2
cat > "$confFile" <<EOF
PRIVATE_NETWORK=1
HOST_ADDRESS=$hostAddress
LOCAL_ADDRESS=$localAddress
EOF
echo "starting container@$container.service..." >&2
systemctl start "container@$container.service"
elif [ $action = update ]; then
getContainerRoot
configFile="$root/etc/nixos/configuration.nix"
profileDir="/nix/var/nix/profiles/per-container/$container"
nix-env -p "$profileDir/system" -I "nixos-config=$configFile" -f '<nixpkgs/nixos>' --set -A system
echo "reloading container@$container.service..." >&2
systemctl reload "container@$container.service"
elif [ $action = destroy ]; then
getContainerRoot
confFile="/etc/containers/$container.conf"
if [ ! -w "$confFile" ]; then
echo "$0: cannot destroy declarative container (remove it from your configuration.nix instead)"
exit 1
fi
if systemctl show "container@$container.service" | grep -q ActiveState=active; then
echo "stopping container@$container.service..." >&2
systemctl stop "container@$container.service"
fi
rm -f "$confFile"
elif [ $action = login ]; then
getContainerRoot
exec @socat@/bin/socat "unix:$root/var/lib/login.socket" -,echo=0,raw
elif [ $action = root-shell ]; then
getContainerRoot
exec @socat@/bin/socat "unix:$root/var/lib/root-shell.socket" -
elif [ $action = set-root-password ]; then
password="$1"
if [ -z "$password" ]; then usage; exit 1; fi
# FIXME: not very secure.
getContainerRoot
(echo "passwd"; echo "$password"; echo "$password") | @socat@/bin/socat "unix:$root/var/lib/root-shell.socket" -
else
echo "$0: unknown action $action" >&2
exit 1
fi