summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorEric Merritt <ericbmerritt@gmail.com>2016-07-18 23:13:06 -0700
committerFranz Pletz <fpletz@fnordicwalking.de>2016-07-19 08:13:06 +0200
commiteb92804f914a8a40339473ebd641f0a93d8576b9 (patch)
tree591417299ee8cb66b42542676cc3ea2a102d1c56 /nixos/modules
parente2199205c7012fc9cfeaf89e85fe3bb8084b82a4 (diff)
downloadnixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.tar
nixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.tar.gz
nixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.tar.bz2
nixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.tar.lz
nixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.tar.xz
nixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.tar.zst
nixpkgs-eb92804f914a8a40339473ebd641f0a93d8576b9.zip
nixos-containers: init package (#16959)
This moves nixos-containers into its own package so that it can be
relied upon by other packages/systems. This should make development
using dynamic containers much easier.
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/virtualisation/containers.nix20
-rw-r--r--nixos/modules/virtualisation/nixos-container-completion.sh33
-rwxr-xr-xnixos/modules/virtualisation/nixos-container.pl301
3 files changed, 2 insertions, 352 deletions
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 13ecb8e25ed..b3870caece0 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -4,22 +4,6 @@ with lib;
 
 let
 
-  nixos-container = pkgs.substituteAll {
-    name = "nixos-container";
-    dir = "bin";
-    isExecutable = true;
-    src = ./nixos-container.pl;
-    perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
-    su = "${pkgs.shadow.su}/bin/su";
-    inherit (pkgs) utillinux;
-
-    postInstall = ''
-      t=$out/etc/bash_completion.d
-      mkdir -p $t
-      cp ${./nixos-container-completion.sh} $t/nixos-container
-    '';
-  };
-
   # The container's init script, a small wrapper around the regular
   # NixOS stage-2 init script.
   containerInit = pkgs.writeScript "container-init"
@@ -410,7 +394,7 @@ in
         ExecReload = pkgs.writeScript "reload-container"
           ''
             #! ${pkgs.stdenv.shell} -e
-            ${nixos-container}/bin/nixos-container run "$INSTANCE" -- \
+            ${pkgs.nixos-container}/bin/nixos-container run "$INSTANCE" -- \
               bash --login -c "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/bin/switch-to-configuration test"
           '';
 
@@ -498,6 +482,6 @@ in
 
     networking.dhcpcd.denyInterfaces = [ "ve-*" ];
 
-    environment.systemPackages = [ nixos-container ];
+    environment.systemPackages = [ pkgs.nixos-container ];
   });
 }
diff --git a/nixos/modules/virtualisation/nixos-container-completion.sh b/nixos/modules/virtualisation/nixos-container-completion.sh
deleted file mode 100644
index 0fe8ab811a1..00000000000
--- a/nixos/modules/virtualisation/nixos-container-completion.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-
-_nixos-container() {
-    local cur prev opts
-    COMPREPLY=()
-    cur="${COMP_WORDS[COMP_CWORD]}"
-    prev="${COMP_WORDS[COMP_CWORD-1]}"
-    opts="list create destroy start stop status update login root-login run show-ip show-host-key"
-    startstop_opts=$(nixos-container list)
-    update_opts="--config"
-
-    if [[ "$prev" == "nixos-container" ]]
-    then
-        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
-        return 0
-    fi
-
-    if [[ $(echo "$opts" | grep "$prev") ]]
-    then
-        if [[ "$prev" == "start" || "$prev" == "stop" ]]
-        then
-            COMPREPLY=( $(compgen -W "${startstop_opts}" -- ${cur}) )
-            return 0
-        elif [[ "$prev" == "update" ]]
-        then
-            COMPREPLY=( $(compgen -W "${update_opts}" -- ${cur}) )
-            return 0
-        fi
-    fi
-}
-
-complete -F _nixos-container nixos-container
-
diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl
deleted file mode 100755
index eda57a9751e..00000000000
--- a/nixos/modules/virtualisation/nixos-container.pl
+++ /dev/null
@@ -1,301 +0,0 @@
-#! @perl@
-
-use strict;
-use POSIX;
-use File::Path;
-use File::Slurp;
-use Fcntl ':flock';
-use Getopt::Long qw(:config gnu_getopt);
-
-my $nsenter = "@utillinux@/bin/nsenter";
-my $su = "@su@";
-
-# Ensure a consistent umask.
-umask 0022;
-
-# Parse the command line.
-
-sub showHelp {
-    print <<EOF;
-Usage: nixos-container list
-       nixos-container create <container-name> [--system-path <path>] [--config <string>] [--ensure-unique-name] [--auto-start]
-       nixos-container destroy <container-name>
-       nixos-container start <container-name>
-       nixos-container stop <container-name>
-       nixos-container status <container-name>
-       nixos-container update <container-name> [--config <string>]
-       nixos-container login <container-name>
-       nixos-container root-login <container-name>
-       nixos-container run <container-name> -- args...
-       nixos-container show-ip <container-name>
-       nixos-container show-host-key <container-name>
-EOF
-    exit 0;
-}
-
-my $systemPath;
-my $ensureUniqueName = 0;
-my $autoStart = 0;
-my $extraConfig;
-
-GetOptions(
-    "help" => sub { showHelp() },
-    "ensure-unique-name" => \$ensureUniqueName,
-    "auto-start" => \$autoStart,
-    "system-path=s" => \$systemPath,
-    "config=s" => \$extraConfig
-    ) or exit 1;
-
-my $action = $ARGV[0] or die "$0: no action specified\n";
-
-
-# Execute the selected action.
-
-mkpath("/etc/containers", 0, 0755);
-mkpath("/var/lib/containers", 0, 0700);
-
-if ($action eq "list") {
-    foreach my $confFile (glob "/etc/containers/*.conf") {
-        $confFile =~ /\/([^\/]+).conf$/ or next;
-        print "$1\n";
-    }
-    exit 0;
-}
-
-my $containerName = $ARGV[1] or die "$0: no container name specified\n";
-$containerName =~ /^[a-zA-Z0-9\-]+$/ or die "$0: invalid container name\n";
-
-sub writeNixOSConfig {
-    my ($nixosConfigFile) = @_;
-
-    my $nixosConfig = <<EOF;
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-{ boot.isContainer = true;
-  networking.hostName = mkDefault "$containerName";
-  networking.useDHCP = false;
-  $extraConfig
-}
-EOF
-
-    write_file($nixosConfigFile, $nixosConfig);
-}
-
-if ($action eq "create") {
-    # Acquire an exclusive lock to prevent races with other
-    # invocations of ‘nixos-container create’.
-    my $lockFN = "/run/lock/nixos-container";
-    open(my $lock, '>>', $lockFN) or die "$0: opening $lockFN: $!";
-    flock($lock, LOCK_EX) or die "$0: could not lock $lockFN: $!";
-
-    my $confFile = "/etc/containers/$containerName.conf";
-    my $root = "/var/lib/containers/$containerName";
-
-    # Maybe generate a unique name.
-    if ($ensureUniqueName) {
-        my $base = $containerName;
-        for (my $nr = 0; ; $nr++) {
-            $confFile = "/etc/containers/$containerName.conf";
-            $root = "/var/lib/containers/$containerName";
-            last unless -e $confFile || -e $root;
-            $containerName = "$base-$nr";
-        }
-    }
-
-    die "$0: container ‘$containerName’ already exists\n" if -e $confFile;
-
-    # Due to interface name length restrictions, container names must
-    # be restricted too.
-    die "$0: container name ‘$containerName’ is too long\n" if length $containerName > 11;
-
-    # Get an unused IP address.
-    my %usedIPs;
-    foreach my $confFile2 (glob "/etc/containers/*.conf") {
-        my $s = read_file($confFile2) or die;
-        $usedIPs{$1} = 1 if $s =~ /^HOST_ADDRESS=([0-9\.]+)$/m;
-        $usedIPs{$1} = 1 if $s =~ /^LOCAL_ADDRESS=([0-9\.]+)$/m;
-    }
-
-    my ($ipPrefix, $hostAddress, $localAddress);
-    for (my $nr = 1; $nr < 255; $nr++) {
-        $ipPrefix = "10.233.$nr";
-        $hostAddress = "$ipPrefix.1";
-        $localAddress = "$ipPrefix.2";
-        last unless $usedIPs{$hostAddress} || $usedIPs{$localAddress};
-        $ipPrefix = undef;
-    }
-
-    die "$0: out of IP addresses\n" unless defined $ipPrefix;
-
-    my @conf;
-    push @conf, "PRIVATE_NETWORK=1\n";
-    push @conf, "HOST_ADDRESS=$hostAddress\n";
-    push @conf, "LOCAL_ADDRESS=$localAddress\n";
-    push @conf, "AUTO_START=$autoStart\n";
-    write_file($confFile, \@conf);
-
-    close($lock);
-
-    print STDERR "host IP is $hostAddress, container IP is $localAddress\n";
-
-    # The per-container directory is restricted to prevent users on
-    # the host from messing with guest users who happen to have the
-    # same uid.
-    my $profileDir = "/nix/var/nix/profiles/per-container";
-    mkpath($profileDir, 0, 0700);
-    $profileDir = "$profileDir/$containerName";
-    mkpath($profileDir, 0, 0755);
-
-    # Build/set the initial configuration.
-    if (defined $systemPath) {
-        system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
-            or die "$0: failed to set initial container configuration\n";
-    } else {
-        mkpath("$root/etc/nixos", 0, 0755);
-
-        my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
-        writeNixOSConfig $nixosConfigFile;
-
-        system("nix-env", "-p", "$profileDir/system",
-               "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>",
-               "--set", "-A", "system") == 0
-            or die "$0: failed to build initial container configuration\n";
-    }
-
-    print "$containerName\n" if $ensureUniqueName;
-    exit 0;
-}
-
-my $root = "/var/lib/containers/$containerName";
-my $profileDir = "/nix/var/nix/profiles/per-container/$containerName";
-my $gcRootsDir = "/nix/var/nix/gcroots/per-container/$containerName";
-my $confFile = "/etc/containers/$containerName.conf";
-if (!-e $confFile) {
-    if ($action eq "destroy") {
-        exit 0;
-    } elsif ($action eq "status") {
-        print "gone\n";
-    }
-    die "$0: container ‘$containerName’ does not exist\n" ;
-}
-
-sub isContainerRunning {
-    my $status = `systemctl show 'container\@$containerName'`;
-    return $status =~ /ActiveState=active/;
-}
-
-sub stopContainer {
-    system("systemctl", "stop", "container\@$containerName") == 0
-        or die "$0: failed to stop container\n";
-}
-
-# Return the PID of the init process of the container.
-sub getLeader {
-    my $s = `machinectl show "$containerName" -p Leader`;
-    chomp $s;
-    $s =~ /^Leader=(\d+)$/ or die "unable to get container's main PID\n";
-    return int($1);
-}
-
-# Run a command in the container.
-sub runInContainer {
-    my @args = @_;
-    my $leader = getLeader;
-    exec($nsenter, "-t", $leader, "-m", "-u", "-i", "-n", "-p", "--", @args);
-    die "cannot run ‘nsenter’: $!\n";
-}
-
-# Remove a directory while recursively unmounting all mounted filesystems within
-# that directory and unmounting/removing that directory afterwards as well.
-#
-# NOTE: If the specified path is a mountpoint, its contents will be removed,
-#       only mountpoints underneath that path will be unmounted properly.
-sub safeRemoveTree {
-    my ($path) = @_;
-    system("find", $path, "-mindepth", "1", "-xdev",
-           "(", "-type", "d", "-exec", "mountpoint", "-q", "{}", ";", ")",
-           "-exec", "umount", "-fR", "{}", "+");
-    system("rm", "--one-file-system", "-rf", $path);
-    if (-e $path) {
-        system("umount", "-fR", $path);
-        system("rm", "--one-file-system", "-rf", $path);
-    }
-}
-
-if ($action eq "destroy") {
-    die "$0: cannot destroy declarative container (remove it from your configuration.nix instead)\n"
-        unless POSIX::access($confFile, &POSIX::W_OK);
-
-    stopContainer if isContainerRunning;
-
-    safeRemoveTree($profileDir) if -e $profileDir;
-    safeRemoveTree($gcRootsDir) if -e $gcRootsDir;
-    safeRemoveTree($root) if -e $root;
-    unlink($confFile) or die;
-}
-
-elsif ($action eq "start") {
-    system("systemctl", "start", "container\@$containerName") == 0
-        or die "$0: failed to start container\n";
-}
-
-elsif ($action eq "stop") {
-    stopContainer;
-}
-
-elsif ($action eq "status") {
-    print isContainerRunning() ? "up" : "down", "\n";
-}
-
-elsif ($action eq "update") {
-    my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
-
-    # FIXME: may want to be more careful about clobbering the existing
-    # configuration.nix.
-    writeNixOSConfig $nixosConfigFile if (defined $extraConfig && $extraConfig ne "");
-
-    system("nix-env", "-p", "$profileDir/system",
-           "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>",
-           "--set", "-A", "system") == 0
-        or die "$0: failed to build container configuration\n";
-
-    if (isContainerRunning) {
-        print STDERR "reloading container...\n";
-        system("systemctl", "reload", "container\@$containerName") == 0
-            or die "$0: failed to reload container\n";
-    }
-}
-
-elsif ($action eq "login") {
-    exec("machinectl", "login", "--", $containerName);
-}
-
-elsif ($action eq "root-login") {
-    runInContainer("@su@", "root", "-l");
-}
-
-elsif ($action eq "run") {
-    shift @ARGV; shift @ARGV;
-    # Escape command.
-    my $s = join(' ', map { s/'/'\\''/g; "'$_'" } @ARGV);
-    runInContainer("@su@", "root", "-l", "-c", "exec " . $s);
-}
-
-elsif ($action eq "show-ip") {
-    my $s = read_file($confFile) or die;
-    $s =~ /^LOCAL_ADDRESS=([0-9\.]+)$/m or die "$0: cannot get IP address\n";
-    print "$1\n";
-}
-
-elsif ($action eq "show-host-key") {
-    my $fn = "$root/etc/ssh/ssh_host_ed25519_key.pub";
-    $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub" unless -e $fn;
-    exit 1 if ! -f $fn;
-    print read_file($fn);
-}
-
-else {
-    die "$0: unknown action ‘$action’\n";
-}