Containers: Use nsenter to execute commands in containers
Also remove ‘nixos-container set-root-password’, which is kind of pointless now.
This commit is contained in:
parent
9c7a598713
commit
6773babd5b
|
@ -18,77 +18,6 @@ with lib;
|
||||||
# Shut up warnings about not having a boot loader.
|
# Shut up warnings about not having a boot loader.
|
||||||
system.build.installBootLoader = "${pkgs.coreutils}/bin/true";
|
system.build.installBootLoader = "${pkgs.coreutils}/bin/true";
|
||||||
|
|
||||||
# Provide a root login prompt on /var/lib/root-login.socket that
|
|
||||||
# doesn't ask for a password. This socket can only be used by root
|
|
||||||
# on the host.
|
|
||||||
systemd.sockets.root-login =
|
|
||||||
{ description = "Root Login Socket";
|
|
||||||
wantedBy = [ "sockets.target" ];
|
|
||||||
socketConfig =
|
|
||||||
{ ListenStream = "/var/lib/root-login.socket";
|
|
||||||
SocketMode = "0600";
|
|
||||||
Accept = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."root-login@" =
|
|
||||||
{ description = "Root Login %i";
|
|
||||||
environment.TERM = "linux";
|
|
||||||
serviceConfig =
|
|
||||||
{ Type = "simple";
|
|
||||||
StandardInput = "socket";
|
|
||||||
ExecStart = "${pkgs.socat}/bin/socat -t0 - \"exec:${pkgs.shadow}/bin/login -f root,pty,setsid,setpgid,stderr,ctty\"";
|
|
||||||
TimeoutStopSec = 1; # FIXME
|
|
||||||
};
|
|
||||||
restartIfChanged = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Provide a daemon on /var/lib/run-command.socket that reads a
|
|
||||||
# command from stdin and executes it.
|
|
||||||
systemd.sockets.run-command =
|
|
||||||
{ description = "Run Command Socket";
|
|
||||||
wantedBy = [ "sockets.target" ];
|
|
||||||
socketConfig =
|
|
||||||
{ ListenStream = "/var/lib/run-command.socket";
|
|
||||||
SocketMode = "0600"; # only root can connect
|
|
||||||
Accept = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."run-command@" =
|
|
||||||
{ description = "Run Command %i";
|
|
||||||
environment.TERM = "linux";
|
|
||||||
serviceConfig =
|
|
||||||
{ Type = "simple";
|
|
||||||
StandardInput = "socket";
|
|
||||||
TimeoutStopSec = 1; # FIXME
|
|
||||||
};
|
|
||||||
script =
|
|
||||||
''
|
|
||||||
#! ${pkgs.stdenv.shell} -e
|
|
||||||
source /etc/bashrc
|
|
||||||
read c
|
|
||||||
eval "command=($c)"
|
|
||||||
exec "''${command[@]}"
|
|
||||||
'';
|
|
||||||
restartIfChanged = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.container-startup-done =
|
|
||||||
{ description = "Container Startup Notification";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "multi-user.target" ];
|
|
||||||
script =
|
|
||||||
''
|
|
||||||
if [ -p /var/lib/startup-done ]; then
|
|
||||||
echo done > /var/lib/startup-done
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
serviceConfig.RemainAfterExit = true;
|
|
||||||
restartIfChanged = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.systemd-remount-fs.enable = false;
|
systemd.services.systemd-remount-fs.enable = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ let
|
||||||
isExecutable = true;
|
isExecutable = true;
|
||||||
src = ./nixos-container.pl;
|
src = ./nixos-container.pl;
|
||||||
perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
|
perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
|
||||||
inherit (pkgs) socat;
|
inherit (pkgs) utillinux;
|
||||||
};
|
};
|
||||||
|
|
||||||
# The container's init script, a small wrapper around the regular
|
# The container's init script, a small wrapper around the regular
|
||||||
|
@ -254,9 +254,8 @@ in
|
||||||
ExecReload = pkgs.writeScript "reload-container"
|
ExecReload = pkgs.writeScript "reload-container"
|
||||||
''
|
''
|
||||||
#! ${pkgs.stdenv.shell} -e
|
#! ${pkgs.stdenv.shell} -e
|
||||||
SYSTEM_PATH=/nix/var/nix/profiles/system
|
${nixos-container}/bin/nixos-container run "$INSTANCE" -- \
|
||||||
echo $SYSTEM_PATH/bin/switch-to-configuration test | \
|
bash --login -c "/nix/var/nix/profiles/system/bin/switch-to-configuration test"
|
||||||
${pkgs.socat}/bin/socat unix:$root/var/lib/run-command.socket -
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
SyslogIdentifier = "container %i";
|
SyslogIdentifier = "container %i";
|
||||||
|
|
|
@ -7,7 +7,7 @@ use File::Slurp;
|
||||||
use Fcntl ':flock';
|
use Fcntl ':flock';
|
||||||
use Getopt::Long qw(:config gnu_getopt);
|
use Getopt::Long qw(:config gnu_getopt);
|
||||||
|
|
||||||
my $socat = '@socat@/bin/socat';
|
my $nsenter = "@utillinux@/bin/nsenter";
|
||||||
|
|
||||||
# Ensure a consistent umask.
|
# Ensure a consistent umask.
|
||||||
umask 0022;
|
umask 0022;
|
||||||
|
@ -25,7 +25,6 @@ Usage: nixos-container list
|
||||||
nixos-container login <container-name>
|
nixos-container login <container-name>
|
||||||
nixos-container root-login <container-name>
|
nixos-container root-login <container-name>
|
||||||
nixos-container run <container-name> -- args...
|
nixos-container run <container-name> -- args...
|
||||||
nixos-container set-root-password <container-name> <password>
|
|
||||||
nixos-container show-ip <container-name>
|
nixos-container show-ip <container-name>
|
||||||
nixos-container show-host-key <container-name>
|
nixos-container show-host-key <container-name>
|
||||||
EOF
|
EOF
|
||||||
|
@ -186,6 +185,23 @@ sub stopContainer {
|
||||||
or die "$0: failed to stop container\n";
|
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;
|
||||||
|
# FIXME: initialise the environment properly.
|
||||||
|
exec($nsenter, "-t", $leader, "-m", "-u", "-i", "-n", "-p", "--", "env", "-i", "--", @args);
|
||||||
|
die "cannot run ‘nsenter’: $!\n";
|
||||||
|
}
|
||||||
|
|
||||||
if ($action eq "destroy") {
|
if ($action eq "destroy") {
|
||||||
die "$0: cannot destroy declarative container (remove it from your configuration.nix instead)\n"
|
die "$0: cannot destroy declarative container (remove it from your configuration.nix instead)\n"
|
||||||
unless POSIX::access($confFile, &POSIX::W_OK);
|
unless POSIX::access($confFile, &POSIX::W_OK);
|
||||||
|
@ -235,28 +251,12 @@ elsif ($action eq "login") {
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif ($action eq "root-login") {
|
elsif ($action eq "root-login") {
|
||||||
exec($socat, "unix:$root/var/lib/root-login.socket", "-,echo=0,raw");
|
runInContainer("bash", "--login");
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif ($action eq "run") {
|
elsif ($action eq "run") {
|
||||||
shift @ARGV; shift @ARGV;
|
shift @ARGV; shift @ARGV;
|
||||||
my $pid = open(SOCAT, "|-", $socat, "-t0", "-", "unix:$root/var/lib/run-command.socket") or die "$0: cannot start $socat: $!\n";
|
runInContainer(@ARGV);
|
||||||
print SOCAT join(' ', map { "'$_'" } @ARGV), "\n";
|
|
||||||
flush SOCAT;
|
|
||||||
waitpid($pid, 0);
|
|
||||||
close(SOCAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
elsif ($action eq "set-root-password") {
|
|
||||||
# FIXME: don't get password from the command line.
|
|
||||||
my $password = $ARGV[2] or die "$0: no password given\n";
|
|
||||||
my $pid = open(SOCAT, "|-", $socat, "-t0", "-", "unix:$root/var/lib/run-command.socket") or die "$0: cannot start $socat: $!\n";
|
|
||||||
print SOCAT "passwd\n";
|
|
||||||
print SOCAT "$password\n";
|
|
||||||
print SOCAT "$password\n";
|
|
||||||
flush SOCAT;
|
|
||||||
waitpid($pid, 0);
|
|
||||||
close(SOCAT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif ($action eq "show-ip") {
|
elsif ($action eq "show-ip") {
|
||||||
|
|
Loading…
Reference in a new issue