mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 14:54:29 +01:00
Add an option ‘boot.systemd.services’
This option makes it more convenient to define services because it automates stuff like setting $PATH, having a pre-start script, and so on.
This commit is contained in:
parent
673bf12b1d
commit
352510c208
2 changed files with 256 additions and 94 deletions
|
@ -39,6 +39,7 @@ let
|
|||
);
|
||||
|
||||
userOptions = {
|
||||
|
||||
openssh.authorizedKeys = {
|
||||
|
||||
preserveExistingKeys = mkOption {
|
||||
|
@ -77,6 +78,7 @@ let
|
|||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
mkAuthkeyScript =
|
||||
|
@ -127,19 +129,6 @@ let
|
|||
${userLoop}
|
||||
'';
|
||||
|
||||
preStart = pkgs.writeScript "openssh-pre-start"
|
||||
''
|
||||
#! ${pkgs.stdenv.shell}
|
||||
|
||||
${mkAuthkeyScript}
|
||||
|
||||
mkdir -m 0755 -p /etc/ssh
|
||||
|
||||
if ! test -f ${cfg.hostKeyPath}; then
|
||||
ssh-keygen -t ${hktn} -b ${toString hktb} -f ${cfg.hostKeyPath} -N ""
|
||||
fi
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -317,27 +306,52 @@ in
|
|||
}
|
||||
];
|
||||
|
||||
boot.systemd.units."sshd.service".text =
|
||||
''
|
||||
[Unit]
|
||||
Description=SSH daemon
|
||||
boot.systemd.services."set-ssh-keys.service" =
|
||||
{ description = "Update authorized SSH keys";
|
||||
|
||||
[Service]
|
||||
Environment=PATH=${pkgs.coreutils}/bin:${pkgs.openssh}/bin
|
||||
Environment=LD_LIBRARY_PATH=${nssModulesPath}
|
||||
Environment=LOCALE_ARCHIVE=/var/run/current-system/sw/lib/locale/locale-archive
|
||||
ExecStartPre=${preStart}
|
||||
ExecStart=\
|
||||
${pkgs.openssh}/sbin/sshd -h ${cfg.hostKeyPath} \
|
||||
-f ${pkgs.writeText "sshd_config" cfg.extraConfig}
|
||||
Restart=always
|
||||
Type=forking
|
||||
KillMode=process
|
||||
PIDFile=/run/sshd.pid
|
||||
'';
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
boot.systemd.units."sshd.service".wantedBy = [ "multi-user.target" ];
|
||||
script = mkAuthkeyScript;
|
||||
|
||||
serviceConfig =
|
||||
''
|
||||
Type=oneshot
|
||||
RemainAfterExit=true
|
||||
'';
|
||||
};
|
||||
|
||||
boot.systemd.services."sshd.service" =
|
||||
{ description = "SSH daemon";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "set-ssh-keys.service" ];
|
||||
|
||||
path = [ pkgs.openssh ];
|
||||
|
||||
environment.LD_LIBRARY_PATH = nssModulesPath;
|
||||
environment.LOCALE_ARCHIVE = "/var/run/current-system/sw/lib/locale/locale-archive";
|
||||
|
||||
preStart =
|
||||
''
|
||||
mkdir -m 0755 -p /etc/ssh
|
||||
|
||||
if ! test -f ${cfg.hostKeyPath}; then
|
||||
ssh-keygen -t ${hktn} -b ${toString hktb} -f ${cfg.hostKeyPath} -N ""
|
||||
fi
|
||||
'';
|
||||
|
||||
serviceConfig =
|
||||
''
|
||||
ExecStart=\
|
||||
${pkgs.openssh}/sbin/sshd -h ${cfg.hostKeyPath} \
|
||||
-f ${pkgs.writeText "sshd_config" cfg.extraConfig}
|
||||
Restart=always
|
||||
Type=forking
|
||||
KillMode=process
|
||||
PIDFile=/run/sshd.pid
|
||||
'';
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = cfg.ports;
|
||||
|
||||
services.openssh.extraConfig =
|
||||
|
|
|
@ -4,6 +4,102 @@ with pkgs.lib;
|
|||
|
||||
let
|
||||
|
||||
servicesOptions = {
|
||||
|
||||
description = mkOption {
|
||||
default = "";
|
||||
types = types.uniq types.string;
|
||||
description = "Description of this unit used in systemd messages and progress indicators.";
|
||||
};
|
||||
|
||||
after = mkOption {
|
||||
default = [];
|
||||
types = types.listOf types.string;
|
||||
description = ''
|
||||
If the specified units are started at the same time as
|
||||
this unit, delay this unit until they have started.
|
||||
'';
|
||||
};
|
||||
|
||||
before = mkOption {
|
||||
default = [];
|
||||
types = types.listOf types.string;
|
||||
description = ''
|
||||
If the specified units are started at the same time as
|
||||
this unit, delay them until this unit has started.
|
||||
'';
|
||||
};
|
||||
|
||||
wantedBy = mkOption {
|
||||
default = [];
|
||||
types = types.listOf types.string;
|
||||
description = "Units that want (i.e. depend on) this unit.";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
default = {};
|
||||
type = types.attrs;
|
||||
example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
|
||||
description = "Environment variables passed to the services's processes.";
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
default = [];
|
||||
apply = ps: "${makeSearchPath "bin" ps}:${makeSearchPath "sbin" ps}";
|
||||
description = ''
|
||||
Packages added to the service's <envar>PATH</envar>
|
||||
environment variable. Both the <filename>bin</filename>
|
||||
and <filename>sbin</filename> subdirectories of each
|
||||
package are added.
|
||||
'';
|
||||
};
|
||||
|
||||
serviceConfig = mkOption {
|
||||
default = "";
|
||||
type = types.string;
|
||||
description = ''
|
||||
Contents of the <literal>[Service]</literal> section of the unit.
|
||||
See <citerefentry><refentrytitle>systemd.unit</refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry> for details.
|
||||
'';
|
||||
};
|
||||
|
||||
script = mkOption {
|
||||
type = types.uniq types.string;
|
||||
default = "";
|
||||
description = "Shell commands executed as the service's main process.";
|
||||
};
|
||||
|
||||
preStart = mkOption {
|
||||
type = types.string;
|
||||
default = "";
|
||||
description = ''
|
||||
Shell commands executed before the service's main process
|
||||
is started.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
servicesConfig = { name, config, ... }: {
|
||||
|
||||
config = {
|
||||
|
||||
# Default path for systemd services. Should be quite minimal.
|
||||
path =
|
||||
[ pkgs.coreutils
|
||||
pkgs.findutils
|
||||
pkgs.gnugrep
|
||||
pkgs.gnused
|
||||
systemd
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
cfg = config.boot.systemd;
|
||||
|
||||
systemd = pkgs.systemd;
|
||||
|
@ -111,6 +207,103 @@ let
|
|||
"shutdown.target.wants"
|
||||
];
|
||||
|
||||
rescueService =
|
||||
''
|
||||
[Unit]
|
||||
Description=Rescue Shell
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
After=sysinit.target
|
||||
Before=shutdown.target
|
||||
|
||||
[Service]
|
||||
Environment=HOME=/root
|
||||
WorkingDirectory=/root
|
||||
ExecStartPre=-${pkgs.coreutils}/bin/echo 'Welcome to rescue mode. Use "systemctl default" or ^D to enter default mode.'
|
||||
#ExecStart=-/sbin/sulogin
|
||||
ExecStart=-${pkgs.bashInteractive}/bin/bash --login
|
||||
ExecStopPost=-${systemd}/bin/systemctl --fail --no-block default
|
||||
Type=idle
|
||||
StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
|
||||
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
|
||||
# terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
'';
|
||||
|
||||
gettyService =
|
||||
''
|
||||
[Unit]
|
||||
Description=Getty on %I
|
||||
Documentation=man:agetty(8)
|
||||
After=systemd-user-sessions.service plymouth-quit-wait.service
|
||||
|
||||
# If additional gettys are spawned during boot then we should make
|
||||
# sure that this is synchronized before getty.target, even though
|
||||
# getty.target didn't actually pull it in.
|
||||
Before=getty.target
|
||||
IgnoreOnIsolate=yes
|
||||
|
||||
[Service]
|
||||
Environment=TERM=linux
|
||||
ExecStart=-${pkgs.utillinux}/sbin/agetty --noclear --login-program ${pkgs.shadow}/bin/login %I 38400
|
||||
Type=idle
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
UtmpIdentifier=%I
|
||||
TTYPath=/dev/%I
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
TTYVTDisallocate=yes
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
|
||||
|
||||
# Some login implementations ignore SIGTERM, so we send SIGHUP
|
||||
# instead, to ensure that login terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
'';
|
||||
|
||||
serviceToUnit = name: def:
|
||||
{ inherit (def) wantedBy;
|
||||
|
||||
text =
|
||||
''
|
||||
[Unit]
|
||||
${optionalString (def.description != "") ''
|
||||
Description=${def.description}
|
||||
''}
|
||||
Before=${concatStringsSep " " def.before}
|
||||
After=${concatStringsSep " " def.after}
|
||||
|
||||
[Service]
|
||||
Environment=PATH=${def.path}
|
||||
${concatMapStrings (n: "Environment=${n}=\"${getAttr n def.environment}\"\n") (attrNames def.environment)}
|
||||
|
||||
${optionalString (def.preStart != "") ''
|
||||
ExecStartPre=${pkgs.writeScript "${name}-prestart.sh" ''
|
||||
#! ${pkgs.stdenv.shell} -e
|
||||
${def.preStart}
|
||||
''}
|
||||
''}
|
||||
|
||||
${optionalString (def.script != "") ''
|
||||
ExecStart=${pkgs.writeScript "${name}.sh" ''
|
||||
#! ${pkgs.stdenv.shell} -e
|
||||
${def.script}
|
||||
''}
|
||||
''}
|
||||
|
||||
${def.serviceConfig}
|
||||
'';
|
||||
};
|
||||
|
||||
nixosUnits = mapAttrsToList makeUnit cfg.units;
|
||||
|
||||
units = pkgs.runCommand "units" { preferLocalBuild = true; }
|
||||
|
@ -160,20 +353,32 @@ in
|
|||
options = {
|
||||
|
||||
boot.systemd.units = mkOption {
|
||||
description = "Definition of systemd units.";
|
||||
default = {};
|
||||
type = types.attrsOf types.optionSet;
|
||||
|
||||
options = {
|
||||
|
||||
text = mkOption {
|
||||
types = types.uniq types.string;
|
||||
description = "Text of this systemd unit.";
|
||||
};
|
||||
|
||||
wantedBy = mkOption {
|
||||
default = [];
|
||||
types = types.listOf types.string;
|
||||
description = "Units that want (i.e. depend on) this unit.";
|
||||
};
|
||||
|
||||
};
|
||||
description = "Definition of systemd units.";
|
||||
|
||||
};
|
||||
|
||||
boot.systemd.services = mkOption {
|
||||
description = "Definition of systemd services.";
|
||||
default = {};
|
||||
type = types.attrsOf types.optionSet;
|
||||
options = [ servicesOptions servicesConfig ];
|
||||
};
|
||||
|
||||
boot.systemd.defaultUnit = mkOption {
|
||||
|
@ -201,68 +406,11 @@ in
|
|||
}
|
||||
];
|
||||
|
||||
boot.systemd.units."getty@.service".text =
|
||||
''
|
||||
[Unit]
|
||||
Description=Getty on %I
|
||||
Documentation=man:agetty(8)
|
||||
After=systemd-user-sessions.service plymouth-quit-wait.service
|
||||
|
||||
# If additional gettys are spawned during boot then we should make
|
||||
# sure that this is synchronized before getty.target, even though
|
||||
# getty.target didn't actually pull it in.
|
||||
Before=getty.target
|
||||
IgnoreOnIsolate=yes
|
||||
|
||||
[Service]
|
||||
Environment=TERM=linux
|
||||
ExecStart=-${pkgs.utillinux}/sbin/agetty --noclear --login-program ${pkgs.shadow}/bin/login %I 38400
|
||||
Type=idle
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
UtmpIdentifier=%I
|
||||
TTYPath=/dev/%I
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
TTYVTDisallocate=yes
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
|
||||
|
||||
# Some login implementations ignore SIGTERM, so we send SIGHUP
|
||||
# instead, to ensure that login terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
'';
|
||||
|
||||
boot.systemd.units."rescue.service".text =
|
||||
''
|
||||
[Unit]
|
||||
Description=Rescue Shell
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
After=sysinit.target
|
||||
Before=shutdown.target
|
||||
|
||||
[Service]
|
||||
Environment=HOME=/root
|
||||
WorkingDirectory=/root
|
||||
ExecStartPre=-${pkgs.coreutils}/bin/echo 'Welcome to rescue mode. Use "systemctl default" or ^D to enter default mode.'
|
||||
#ExecStart=-/sbin/sulogin
|
||||
ExecStart=-${pkgs.bashInteractive}/bin/bash --login
|
||||
ExecStopPost=-${systemd}/bin/systemctl --fail --no-block default
|
||||
Type=idle
|
||||
StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
|
||||
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
|
||||
# terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
'';
|
||||
boot.systemd.units =
|
||||
{ "rescue.service".text = rescueService;
|
||||
"getty@.service".text = gettyService;
|
||||
}
|
||||
// mapAttrs serviceToUnit cfg.services;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue