nixpkgs/nixos/modules/system/boot/modprobe.nix
Eelco Dolstra 9ee30cd9b5 Add support for lightweight NixOS containers
You can now say:

  systemd.containers.foo.config =
    { services.openssh.enable = true;
      services.openssh.ports = [ 2022 ];
      users.extraUsers.root.openssh.authorizedKeys.keys = [ "ssh-dss ..." ];
    };

which defines a NixOS instance with the given configuration running
inside a lightweight container.

You can also manage the configuration of the container independently
from the host:

  systemd.containers.foo.path = "/nix/var/nix/profiles/containers/foo";

where "path" is a NixOS system profile.  It can be created/updated by
doing:

  $ nix-env --set -p /nix/var/nix/profiles/containers/foo \
      -f '<nixos>' -A system -I nixos-config=foo.nix

The container configuration (foo.nix) should define

  boot.isContainer = true;

to optimise away the building of a kernel and initrd.  This is done
automatically when using the "config" route.

On the host, a lightweight container appears as the service
"container-<name>.service".  The container is like a regular NixOS
(virtual) machine, except that it doesn't have its own kernel.  It has
its own root file system (by default /var/lib/containers/<name>), but
shares the Nix store of the host (as a read-only bind mount).  It also
has access to the network devices of the host.

Currently, if the configuration of the container changes, running
"nixos-rebuild switch" on the host will cause the container to be
rebooted.  In the future we may want to send some message to the
container so that it can activate the new container configuration
without rebooting.

Containers are not perfectly isolated yet.  In particular, the host's
/sys/fs/cgroup is mounted (writable!) in the guest.
2013-11-27 17:14:10 +01:00

114 lines
3.3 KiB
Nix

{ config, pkgs, ... }:
with pkgs.lib;
{
###### interface
options = {
system.sbin.modprobe = mkOption {
internal = true;
default = pkgs.writeTextFile {
name = "modprobe";
destination = "/sbin/modprobe";
executable = true;
text =
''
#! ${pkgs.stdenv.shell}
export MODULE_DIR=/run/current-system/kernel-modules/lib/modules
# Fall back to the kernel modules used at boot time if the
# modules in the current configuration don't match the
# running kernel.
if [ ! -d "$MODULE_DIR/$(${pkgs.coreutils}/bin/uname -r)" ]; then
MODULE_DIR=/run/booted-system/kernel-modules/lib/modules/
fi
exec ${pkgs.kmod}/sbin/modprobe "$@"
'';
};
description = ''
Wrapper around modprobe that sets the path to the modules
tree.
'';
};
boot.blacklistedKernelModules = mkOption {
type = types.listOf types.str;
default = [];
example = [ "cirrusfb" "i2c_piix4" ];
description = ''
List of names of kernel modules that should not be loaded
automatically by the hardware probing code.
'';
};
boot.extraModprobeConfig = mkOption {
default = "";
example =
''
options parport_pc io=0x378 irq=7 dma=1
'';
description = ''
Any additional configuration to be appended to the generated
<filename>modprobe.conf</filename>. This is typically used to
specify module options. See
<citerefentry><refentrytitle>modprobe.conf</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for details.
'';
type = types.lines;
};
};
###### implementation
config = mkIf (!config.boot.isContainer) {
environment.etc = singleton
{ source = pkgs.writeText "modprobe.conf"
''
${flip concatMapStrings config.boot.blacklistedKernelModules (name: ''
blacklist ${name}
'')}
${config.boot.extraModprobeConfig}
'';
target = "modprobe.d/nixos.conf";
};
environment.systemPackages = [ config.system.sbin.modprobe pkgs.kmod ];
boot.blacklistedKernelModules =
[ # This module is for debugging and generates gigantic amounts
# of log output, so it should never be loaded automatically.
"evbug"
# This module causes ALSA to occassionally select the wrong
# default sound device, and is little more than an annoyance
# on modern machines.
"snd_pcsp"
# The cirrusfb module prevents X11 from starting. FIXME:
# Ubuntu blacklists all framebuffer devices because they're
# "buggy" and cause suspend problems. Maybe we should too?
"cirrusfb"
];
system.activationScripts.modprobe =
''
# Allow the kernel to find our wrapped modprobe (which searches
# in the right location in the Nix store for kernel modules).
# We need this when the kernel (or some module) auto-loads a
# module.
echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe
'';
environment.variables.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules";
};
}