Merge remote-tracking branch 'origin/master' into systemd

Conflicts:
	modules/misc/ids.nix
	modules/services/mail/postfix.nix
	modules/services/system/nscd.nix
	modules/services/x11/desktop-managers/xfce.nix
	modules/system/boot/stage-1.nix
This commit is contained in:
Eelco Dolstra 2012-09-28 11:35:27 -04:00
commit 3ad370ae0a
15 changed files with 254 additions and 256 deletions

View File

@ -73,7 +73,7 @@ in
fprot = 52; fprot = 52;
bind = 53; bind = 53;
wwwrun = 54; wwwrun = 54;
spamd = 55; spamd = 56;
# When adding a uid, make sure it doesn't match an existing gid. # When adding a uid, make sure it doesn't match an existing gid.
@ -127,6 +127,8 @@ in
fprot = 52; fprot = 52;
wwwrun = 54; wwwrun = 54;
adm = 55; adm = 55;
spamd = 56;
networkmanager = 57;
# When adding a gid, make sure it doesn't match an existing uid. # When adding a gid, make sure it doesn't match an existing uid.

View File

@ -83,7 +83,6 @@
./services/logging/logstash.nix ./services/logging/logstash.nix
./services/logging/syslogd.nix ./services/logging/syslogd.nix
./services/mail/dovecot.nix ./services/mail/dovecot.nix
./services/mail/dovecot2.nix
./services/mail/freepops.nix ./services/mail/freepops.nix
./services/mail/mail.nix ./services/mail/mail.nix
./services/mail/postfix.nix ./services/mail/postfix.nix

View File

@ -56,8 +56,9 @@ in
'' ''
mkdir -m 0755 -p $(dirname ${soundState}) mkdir -m 0755 -p $(dirname ${soundState})
# Restore the sound state. # Try to restore the sound state.
${alsaUtils}/sbin/alsactl --ignore -f ${soundState} restore ${alsaUtils}/sbin/alsactl --ignore init || true
${alsaUtils}/sbin/alsactl --ignore -f ${soundState} restore || true
''; '';
postStop = postStop =

View File

@ -4,47 +4,46 @@ with pkgs.lib;
let let
cfg = config.services.dovecot; cfg = config.services.dovecot2;
dovecotConf = dovecotConf =
'' ''
base_dir = /var/run/dovecot/ base_dir = /var/run/dovecot2/
protocols = imap imaps pop3 pop3s protocols = imap pop3
'' ''
+ (if cfg.sslServerCert!="" then + (if cfg.sslServerCert!="" then
'' ''
ssl_cert_file = ${cfg.sslServerCert} ssl_cert = <${cfg.sslServerCert}
ssl_key_file = ${cfg.sslServerKey} ssl_key = <${cfg.sslServerKey}
ssl_ca_file = ${cfg.sslCACert} ssl_ca = <${cfg.sslCACert}
disable_plaintext_auth = yes
'' else '' '' else ''
ssl_disable = yes ssl = no
disable_plaintext_auth = no disable_plaintext_auth = no
'') '')
+ '' + ''
login_user = ${cfg.user} default_internal_user = ${cfg.user}
login_chroot = no
mail_location = maildir:/var/spool/mail/%u mail_location = ${cfg.mailLocation}
maildir_copy_with_hardlinks = yes maildir_copy_with_hardlinks = yes
auth default { auth_mechanisms = plain login
mechanisms = plain login service auth {
userdb passwd {
}
passdb pam {
}
user = root user = root
} }
auth_debug = yes userdb {
auth_verbose = yes driver = passwd
}
passdb {
driver = pam
args = dovecot2
}
pop3_uidl_format = %08Xv%08Xu pop3_uidl_format = %08Xv%08Xu
'' + cfg.extraConfig;
log_path = /var/log/dovecot.log
'';
confFile = pkgs.writeText "dovecot.conf" dovecotConf; confFile = pkgs.writeText "dovecot.conf" dovecotConf;
@ -56,23 +55,37 @@ in
options = { options = {
services.dovecot = { services.dovecot2 = {
enable = mkOption { enable = mkOption {
default = false; default = false;
description = "Whether to enable the Dovecot POP3/IMAP server."; description = "Whether to enable the Dovecot 2.x POP3/IMAP server.";
}; };
user = mkOption { user = mkOption {
default = "dovecot"; default = "dovecot2";
description = "Dovecot user name."; description = "Dovecot user name.";
}; };
group = mkOption { group = mkOption {
default = "dovecot"; default = "dovecot2";
description = "Dovecot group name."; description = "Dovecot group name.";
}; };
extraConfig = mkOption {
default = "";
example = "mail_debug = yes";
description = "Additional entries to put verbatim into Dovecot's config file.";
};
mailLocation = mkOption {
default = "maildir:/var/spool/mail/%u"; /* Same as inbox, as postfix */
example = "maildir:~/mail:INBOX=/var/spool/mail/%u";
description = ''
Location that dovecot will use for mail folders. Dovecot mail_location option.
'';
};
sslServerCert = mkOption { sslServerCert = mkOption {
default = ""; default = "";
description = "Server certificate"; description = "Server certificate";
@ -95,36 +108,44 @@ in
###### implementation ###### implementation
config = mkIf config.services.dovecot.enable { config = mkIf config.services.dovecot2.enable {
security.pam.services = [ { name = "dovecot"; } ]; security.pam.services = [ { name = "dovecot2"; } ];
users.extraUsers = singleton users.extraUsers = [
{ name = cfg.user; { name = cfg.user;
uid = config.ids.uids.dovecot; uid = config.ids.uids.dovecot2;
description = "Dovecot user"; description = "Dovecot user";
group = cfg.group; group = cfg.group;
}; }
{ name = "dovenull";
uid = config.ids.uids.dovenull2;
description = "Dovecot user for untrusted logins";
group = cfg.group;
}
];
users.extraGroups = singleton users.extraGroups = singleton
{ name = cfg.group; { name = cfg.group;
gid = config.ids.gids.dovecot; gid = config.ids.gids.dovecot2;
}; };
jobs.dovecot = jobs.dovecot2 =
{ description = "Dovecot IMAP/POP3 server"; { description = "Dovecot IMAP/POP3 server";
startOn = "started networking"; startOn = "started networking";
preStart = preStart =
'' ''
${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot /var/run/dovecot/login ${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot2 /var/run/dovecot2/login
${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} /var/run/dovecot ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} /var/run/dovecot2
''; '';
exec = "${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}"; exec = "${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}";
}; };
environment.systemPackages = [ pkgs.dovecot ];
}; };
} }

View File

@ -1,149 +0,0 @@
{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.services.dovecot2;
dovecotConf =
''
base_dir = /var/run/dovecot2/
protocols = imap pop3
''
+ (if cfg.sslServerCert!="" then
''
ssl_cert_file = ${cfg.sslServerCert}
ssl_key_file = ${cfg.sslServerKey}
ssl_ca_file = ${cfg.sslCACert}
'' else ''
ssl = no
disable_plaintext_auth = no
'')
+ ''
default_internal_user = ${cfg.user}
mail_location = ${cfg.mailLocation}
maildir_copy_with_hardlinks = yes
auth_mechanisms = plain login
service auth {
user = root
}
userdb {
driver = passwd
}
passdb {
driver = pam
args = dovecot2
}
#auth_debug = yes
#auth_verbose = yes
#debug_log_path = /tmp/dovecot2debug.log
pop3_uidl_format = %08Xv%08Xu
log_path = /var/log/dovecot2.log
'';
confFile = pkgs.writeText "dovecot.conf" dovecotConf;
in
{
###### interface
options = {
services.dovecot2 = {
enable = mkOption {
default = false;
description = "Whether to enable the Dovecot 2.x POP3/IMAP server.";
};
user = mkOption {
default = "dovecot2";
description = "Dovecot user name.";
};
group = mkOption {
default = "dovecot2";
description = "Dovecot group name.";
};
mailLocation = mkOption {
default = "maildir:/var/spool/mail/%u"; /* Same as inbox, as postfix */
example = "maildir:~/mail:INBOX=/var/spool/mail/%u";
description = ''
Location that dovecot will use for mail folders. Dovecot mail_location option.
'';
};
sslServerCert = mkOption {
default = "";
description = "Server certificate";
};
sslCACert = mkOption {
default = "";
description = "CA certificate used by the server certificate.";
};
sslServerKey = mkOption {
default = "";
description = "Server key.";
};
};
};
###### implementation
config = mkIf config.services.dovecot2.enable {
security.pam.services = [ { name = "dovecot2"; } ];
users.extraUsers = [
{ name = cfg.user;
uid = config.ids.uids.dovecot2;
description = "Dovecot user";
group = cfg.group;
}
{ name = "dovenull";
uid = config.ids.uids.dovenull2;
description = "Dovecot user for untrusted logins";
group = cfg.group;
}
];
users.extraGroups = singleton
{ name = cfg.group;
gid = config.ids.gids.dovecot2;
};
jobs.dovecot2 =
{ description = "Dovecot IMAP/POP3 server";
startOn = "started networking";
preStart =
''
${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot2 /var/run/dovecot2/login
${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} /var/run/dovecot2
'';
exec = "${pkgs.dovecot_2_0}/sbin/dovecot -F -c ${confFile}";
};
environment.systemPackages = [ pkgs.dovecot_2_0 ];
};
}

View File

@ -85,6 +85,45 @@ let
'' ''
+ cfg.extraConfig; + cfg.extraConfig;
masterCf = ''
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#submission inet n - n - - smtpd
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
pickup fifo n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr fifo n - n 300 1 qmgr
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - n - - smtp
relay unix - - n - - smtp
-o smtp_fallback_relay=
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
${cfg.extraMasterConf}
'';
aliases = aliases =
optionalString (cfg.postmasterAlias != "") '' optionalString (cfg.postmasterAlias != "") ''
postmaster: ${cfg.postmasterAlias} postmaster: ${cfg.postmasterAlias}
@ -98,6 +137,7 @@ let
aliasesFile = pkgs.writeText "postfix-aliases" aliases; aliasesFile = pkgs.writeText "postfix-aliases" aliases;
virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual; virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
mainCfFile = pkgs.writeText "postfix-main.cf" mainCf; mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
masterCfFile = pkgs.writeText "postfix-master.cf" masterCf;
in in
@ -232,7 +272,7 @@ in
extraConfig = mkOption { extraConfig = mkOption {
default = ""; default = "";
description = " description = "
Extra configuration, will be added verbatim to the configuration file. Extra lines to be added verbatim to the main.cf configuration file.
"; ";
}; };
@ -266,6 +306,12 @@ in
"; ";
}; };
extraMasterConf = mkOption {
default = "";
example = "submission inet n - n - - smtpd";
description = "Extra lines to append to the generated master.cf file.";
};
}; };
}; };
@ -342,6 +388,7 @@ in
ln -sf ${aliasesFile} /var/postfix/conf/aliases ln -sf ${aliasesFile} /var/postfix/conf/aliases
ln -sf ${virtualFile} /var/postfix/conf/virtual ln -sf ${virtualFile} /var/postfix/conf/virtual
ln -sf ${mainCfFile} /var/postfix/conf/main.cf ln -sf ${mainCfFile} /var/postfix/conf/main.cf
ln -sf ${masterCfFile} /var/postfix/conf/master.cf
${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases ${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual ${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual

View File

@ -21,6 +21,11 @@ in
description = "Whether to run the SpamAssassin daemon."; description = "Whether to run the SpamAssassin daemon.";
}; };
debug = mkOption {
default = false;
description = "Whether to run the SpamAssassin daemon in debug mode.";
};
}; };
}; };
@ -33,17 +38,23 @@ in
# Allow users to run 'spamc'. # Allow users to run 'spamc'.
environment.systemPackages = [ pkgs.spamassassin ]; environment.systemPackages = [ pkgs.spamassassin ];
users.extraUsers = singleton users.extraUsers = singleton {
{ name = "spamd"; name = "spamd";
description = "Spam Assassin Daemon"; description = "Spam Assassin Daemon";
uid = config.ids.uids.spamd; uid = config.ids.uids.spamd;
}; group = "spamd";
};
users.extraGroups = singleton {
name = "spamd";
gid = config.ids.gids.spamd;
};
jobs.spamd = { jobs.spamd = {
description = "Spam Assassin Server"; description = "Spam Assassin Server";
startOn = "started networking and filesystem"; startOn = "started networking and filesystem";
environment.TZ = config.time.timeZone; environment.TZ = config.time.timeZone;
exec = "${pkgs.spamassassin}/bin/spamd -C /etc/spamassassin/init.pre --siteconfigpath=/etc/spamassassin --username=spamd --pidfile=/var/run/spamd.pid"; exec = "${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --nouser-config --virtual-config-dir=/var/lib/spamassassin/user-%u --allow-tell --pidfile=/var/run/spamd.pid";
}; };
}; };

View File

@ -179,12 +179,7 @@ in
''; '';
}; };
services.httpd = mkIf cfg.enableWebInterface { services.httpd.extraConfig = optionalString cfg.enableWebInterface extraHttpdConfig;
extraConfig = mkThenElse {
thenPart = extraHttpdConfig;
elsePart = "";
};
};
}; };

View File

@ -33,7 +33,9 @@ let
# Helper command to manipulate both the IPv4 and IPv6 tables. # Helper command to manipulate both the IPv4 and IPv6 tables.
ip46tables() { ip46tables() {
iptables "$@" iptables "$@"
ip6tables "$@" ${optionalString config.networking.enableIPv6 ''
ip6tables "$@"
''}
} }
''; '';
@ -96,6 +98,15 @@ in
''; '';
}; };
networking.firewall.trustedInterfaces = mkOption {
type = types.list types.string;
description =
''
Traffic coming in from these interfaces will be accepted
unconditionally.
'';
};
networking.firewall.allowedTCPPorts = mkOption { networking.firewall.allowedTCPPorts = mkOption {
default = []; default = [];
example = [ 22 80 ]; example = [ 22 80 ];
@ -153,6 +164,8 @@ in
# holds). # holds).
config = mkIf cfg.enable { config = mkIf cfg.enable {
networking.firewall.trustedInterfaces = [ "lo" ];
environment.systemPackages = [ pkgs.iptables ]; environment.systemPackages = [ pkgs.iptables ];
boot.kernelModules = [ "nf_conntrack_ftp" ]; boot.kernelModules = [ "nf_conntrack_ftp" ];
@ -220,8 +233,10 @@ in
# The "nixos-fw" chain does the actual work. # The "nixos-fw" chain does the actual work.
ip46tables -N nixos-fw ip46tables -N nixos-fw
# Accept all traffic on the loopback interface. # Accept all traffic on the trusted interfaces.
ip46tables -A nixos-fw -i lo -j nixos-fw-accept ${flip concatMapStrings cfg.trustedInterfaces (iface: ''
ip46tables -A nixos-fw -i ${iface} -j nixos-fw-accept
'')}
# Accept packets from established or related connections. # Accept packets from established or related connections.
ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept

View File

@ -3,12 +3,47 @@
with pkgs.lib; with pkgs.lib;
let let
cfg = config.networking.networkmanager;
stateDir = "/var/lib/NetworkManager"; stateDirs = "/var/lib/NetworkManager /var/lib/dhclient";
in configFile = pkgs.writeText "NetworkManager.conf" ''
[main]
plugins=keyfile
{ [keyfile]
${optionalString (config.networking.hostName != "") ''
hostname=${config.networking.hostName}
''}
[logging]
level=WARN
'';
polkitConf = ''
[network-manager]
Identity=unix-group:networkmanager
Action=org.freedesktop.NetworkManager.*
ResultAny=yes
ResultInactive=no
ResultActive=yes
[modem-manager]
Identity=unix-group:networkmanager
Action=org.freedesktop.ModemManager.*
ResultAny=yes
ResultInactive=no
ResultActive=yes
'';
ipUpScript = pkgs.writeScript "01nixos-ip-up" ''
#!/bin/sh
if test "$2" = "up"; then
${pkgs.upstart}/sbin/initctl emit ip-up "IFACE=$1"
fi
'';
in {
###### interface ###### interface
@ -20,61 +55,62 @@ in
description = '' description = ''
Whether to use NetworkManager to obtain an IP adress and other Whether to use NetworkManager to obtain an IP adress and other
configuration for all network interfaces that are not manually configuration for all network interfaces that are not manually
configured. configured. If enabled, a group <literal>networkmanager</literal>
will be created. Add all users that should have permission
to change network settings to this group.
''; '';
}; };
networking.networkmanager.packages = mkOption { networking.networkmanager.packages = mkOption {
default = [ pkgs.networkmanager ]; default = [ ];
description = description = ''
'' Extra packages that provide NetworkManager plugins.
Packages providing NetworkManager plugins. '';
''; merge = mergeListOption;
apply = list: [ pkgs.networkmanager pkgs.modemmanager ] ++ list;
}; };
}; };
###### implementation ###### implementation
config = mkIf config.networking.networkmanager.enable { config = mkIf cfg.enable {
jobs.networkmanager = environment.etc = singleton {
{ startOn = "started network-interfaces"; source = ipUpScript;
stopOn = "stopping network-interfaces"; target = "NetworkManager/dispatcher.d/01nixos-ip-up";
};
script = environment.systemPackages = cfg.packages;
''
mkdir -m 755 -p /etc/NetworkManager
mkdir -m 700 -p /etc/NetworkManager/system-connections
mkdir -m 755 -p ${stateDir}
if [[ ! -f /etc/NetworkManager/NetworkManager.conf ]]; then users.extraGroups = singleton {
cat <<-EOF > /etc/NetworkManager/NetworkManager.conf name = "networkmanager";
[main] gid = config.ids.gids.networkmanager;
plugins=keyfile };
EOF
fi
exec ${pkgs.networkmanager}/sbin/NetworkManager --no-daemon jobs.networkmanager = {
''; startOn = "started network-interfaces";
}; stopOn = "stopping network-interfaces";
path = [ pkgs.networkmanager ];
preStart = ''
mkdir -m 755 -p /etc/NetworkManager
mkdir -m 700 -p /etc/NetworkManager/system-connections
mkdir -m 755 -p ${stateDirs}
'';
exec = "NetworkManager --config=${configFile} --no-daemon";
};
environment.systemPackages = config.networking.networkmanager.packages;
services.dbus.packages = config.networking.networkmanager.packages;
networking.useDHCP = false; networking.useDHCP = false;
environment.etc = [ networking.wireless.enable = true;
{
source = pkgs.writeScript "01nixos-ip-up" security.polkit.permissions = polkitConf;
''
#!/bin/sh services.dbus.packages = cfg.packages;
if test "$2" = "up"; then
${pkgs.upstart}/sbin/initctl emit ip-up "IFACE=$1" services.udev.packages = cfg.packages;
fi
'';
target = "NetworkManager/dispatcher.d/01nixos-ip-up";
}
];
}; };
} }

View File

@ -58,6 +58,8 @@ in
Type=forking Type=forking
PIDFile=/run/nscd/nscd.pid PIDFile=/run/nscd/nscd.pid
Restart=always Restart=always
ExecReload=${pkgs.glibc}/sbin/nscd --invalidate passwd
ExecReload=${pkgs.glibc}/sbin/nscd --invalidate group
ExecReload=${pkgs.glibc}/sbin/nscd --invalidate hosts ExecReload=${pkgs.glibc}/sbin/nscd --invalidate hosts
''; '';
}; };

View File

@ -7,8 +7,6 @@ let
xcfg = config.services.xserver; xcfg = config.services.xserver;
cfg = xcfg.desktopManager.xfce; cfg = xcfg.desktopManager.xfce;
isXfce48 = pkgs.xfce ? libxfce4ui;
in in
{ {
@ -45,8 +43,7 @@ in
}; };
environment.systemPackages = environment.systemPackages =
[ [ pkgs.gtk # To get GTK+'s themes.
pkgs.gtk # To get GTK+'s themes.
pkgs.hicolor_icon_theme pkgs.hicolor_icon_theme
pkgs.shared_mime_info pkgs.shared_mime_info
pkgs.which # Needed by the xfce's xinitrc script. pkgs.which # Needed by the xfce's xinitrc script.
@ -70,8 +67,6 @@ in
# "utilities-terminal" and "accessories-text-editor". # "utilities-terminal" and "accessories-text-editor".
pkgs.gnome.gnomeicontheme pkgs.gnome.gnomeicontheme
pkgs.desktop_file_utils pkgs.desktop_file_utils
]
++ optionals isXfce48 [
pkgs.xfce.libxfce4ui pkgs.xfce.libxfce4ui
pkgs.xfce.garcon pkgs.xfce.garcon
pkgs.xfce.thunar_volman pkgs.xfce.thunar_volman
@ -83,14 +78,14 @@ in
environment.pathsToLink = environment.pathsToLink =
[ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" ]; [ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" ];
environment.shellInit = optionalString isXfce48 environment.shellInit =
'' ''
export GIO_EXTRA_MODULES=${pkgs.xfce.gvfs}/lib/gio/modules export GIO_EXTRA_MODULES=${pkgs.xfce.gvfs}/lib/gio/modules
''; '';
# Enable helpful DBus services. # Enable helpful DBus services.
services.udisks = mkIf isXfce48 { enable = true; }; services.udisks.enable = true;
services.upower = mkIf (isXfce48 && config.powerManagement.enable) { enable = true; }; services.upower.enable = config.powerManagement.enable;
}; };

View File

@ -136,6 +136,10 @@ modprobe scsi_wait_scan || true
udevadm settle || true udevadm settle || true
# Load boot-time keymap before any LVM/LUKS initialization
@extraUtils@/bin/busybox loadkmap < "@busyboxKeymap@"
# XXX: Use case usb->lvm will still fail, usb->luks->lvm is covered # XXX: Use case usb->lvm will still fail, usb->luks->lvm is covered
@preLVMCommands@ @preLVMCommands@

View File

@ -280,6 +280,15 @@ let
}; };
# The binary keymap for busybox to load at boot.
busyboxKeymap = pkgs.runCommand "boottime-keymap"
{ preferLocalBuild = true; }
''
${pkgs.kbd}/bin/loadkeys -qb "${config.i18n.consoleKeyMap}" > $out ||
${pkgs.kbd}/bin/loadkeys -qbu "${config.i18n.consoleKeyMap}" > $out
'';
# The init script of boot stage 1 (loading kernel modules for # The init script of boot stage 1 (loading kernel modules for
# mounting the root FS). # mounting the root FS).
bootStage1 = pkgs.substituteAll { bootStage1 = pkgs.substituteAll {
@ -289,7 +298,7 @@ let
isExecutable = true; isExecutable = true;
inherit udevRules extraUtils modulesClosure; inherit udevRules extraUtils modulesClosure busyboxKeymap;
inherit (config.boot) resumeDevice devSize runSize; inherit (config.boot) resumeDevice devSize runSize;

View File

@ -156,6 +156,16 @@ in
description = "Names of supported filesystem types in the initial ramdisk."; description = "Names of supported filesystem types in the initial ramdisk.";
}; };
boot.ttyEmergency = mkOption {
default =
if pkgs.stdenv.isArm
then "ttyS0" # presumably an embedded platform such as a plug
else "tty1";
description = ''
The tty that will be stopped in case an emergency shell is spawned
at boot.
'';
};
}; };
@ -248,7 +258,7 @@ in
status="$(status xserver || true)" status="$(status xserver || true)"
[[ "$status" =~ start/ ]] && exit 0 [[ "$status" =~ start/ ]] && exit 0
stop tty1 || true stop ${config.boot.ttyEmergency} || true
start --no-wait emergency-shell \ start --no-wait emergency-shell \
DEVICE="$DEVICE" MOUNTPOINT="$MOUNTPOINT" DEVICE="$DEVICE" MOUNTPOINT="$MOUNTPOINT"