WIP: feat(systemd): switch to systemd #33

Draft
lbailly wants to merge 8 commits from lbailly/liminix:systemd into main
11 changed files with 403 additions and 65 deletions

View file

@ -25,7 +25,13 @@ let
eval = evalModules {
modules = [
{
({ lib, pkgs, ... }: {
_module.args = {
utils = import "${nixpkgs}/nixos/lib/utils.nix" {
inherit lib pkgs;
config.systemd.globalEnvironment = {};
};
};
nixpkgs = {
source = nixpkgs;
overlays = [ overlay ];
@ -33,7 +39,7 @@ let
"python-2.7.18.8"
];
};
}
})
device.module
liminix-config
];
@ -57,7 +63,7 @@ let
];
}).config.system;
in {
inherit evalModules;
inherit evalModules config;
outputs = config.system.outputs // {
default = config.system.outputs.${config.hardware.defaultOutput};

View file

@ -14,7 +14,7 @@ in
"${modulesPath}/busybox.nix"
"${modulesPath}/hostname.nix"
"${modulesPath}/kernel"
"${modulesPath}/s6"
"${modulesPath}/systemd"
"${modulesPath}/users.nix"
"${modulesPath}/outputs.nix"
"${modulesPath}/nixpkgs.nix"

View file

@ -2,7 +2,7 @@
## ============
{ lib, pkgs, config, ...}:
{ lib, pkgs, utils, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr concatStringsSep mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
@ -43,9 +43,12 @@ in {
'';
};
};
# deprecated
services = mkOption {
type = types.attrsOf type_service;
};
system.callService = mkOption {
type = types.functionTo (types.functionTo types.anything);
};
@ -129,10 +132,12 @@ in {
# By default, we enable cross-compilation support.
nixpkgs.buildPlatform = lib.mkDefault builtins.currentSystem;
defaultProfile.packages = with pkgs;
[ s6 s6-init-bin execline s6-linux-init s6-rc ];
# Set the useful PS1 prompt by default.
defaultProfile.environmentVariables.PS1 = lib.mkDefault config.defaultProfile.prompt;
defaultProfile.packages = with pkgs; [
# execline
systemd
];
boot.commandLine = [
"panic=10 oops=panic init=/bin/init loglevel=8"

View file

@ -51,7 +51,7 @@ let
in {
options = {
programs.busybox = {
applets = mkOption {
applets = mkOption {
type = types.listOf types.str;
description = "Applets required";
default = [];
@ -62,13 +62,19 @@ in {
# other strings are also used
description = "Other busybox config flags that do not map directly to applet names (often prefixed FEATURE_)";
type = types.attrsOf types.nonEmptyStr;
default = { };
example = { FEATURE_DD_IBS_OBS = "y"; };
default = { };
example = { FEATURE_DD_IBS_OBS = "y"; };
};
package = mkOption {
type = types.package;
readOnly = true;
internal = true;
};
};
};
config = {
programs.busybox = {
package = busybox;
applets = minimalApplets;
options = {
ASH_ECHO = "y";

View file

@ -186,8 +186,11 @@ in {
};
};
};
# bin = dir {
# init = symlink "${s6-init-bin}/bin/init";
# };
bin = dir {
init = symlink "${s6-init-bin}/bin/init";
init = symlink "${pkgs.systemd}/bin/init";
};
};
};

View file

@ -1,19 +0,0 @@
#!/bin/sh
### Things to do before hardware halt/reboot/poweroff.
### Ideally, it should be a single call to the service manager,
### telling it to bring all the services down.
### If your s6-linux-init-maker invocation was made with the -1
### option, messages from rc.shutdown will appear on /dev/console
### as well as be logged by the catch-all logger.
### If your s6-linux-init-maker invocation did NOT include the -1
### option, messages from rc.shutdown will only be logged by the
### catch-all logger and will NOT appear on /dev/console. In order
### to print them to /dev/console instead, you may want to
### uncomment the following line:
exec >/dev/console 2>&1
### If your services are managed by s6-rc:
exec s6-rc -v2 -bDa change

View file

@ -1,22 +0,0 @@
#!/bin/sh -e
## s6-linux-init-shutdownd never tells s6-svscan to exit, so if
## you're running s6-linux-init, it's normal that your
## .s6-svscan/finish script is not executed.
## The place where you want to hack things is /etc/rc.shutdown.final,
## which is run by the stage 4 script right before the hard reboot.
## So you can do dirty stuff [...] which should clean up the
## s6-supervise and the foreground, and give control to
## .s6-svscan/finish.
## -- Laurent Bercot on skaware mailing list,
## https://skarnet.org/lists/skaware/1913.html
exec >/dev/console 2>&1
# down, exit supervisor, wait, stay down
s6-svc -dxwD /run/service/s6-linux-init-shutdownd
# HUP, exit supervisor, wait, down
s6-svc -hxwd /run/service/s6-svscan-log
s6-svscanctl -b /run/service # abort

View file

@ -1,12 +0,0 @@
#!/bin/sh -e
### This script is called once at boot time by rc.init, and is
### also called by the runleveld service every time the user
### requests a machine state change via telinit.
### Ideally, it should just be a call to the service manager.
test "$#" -gt 0 || { echo 'runlevel: fatal: too few arguments' 1>&2 ; exit 100 ; }
### If your services are managed by s6-rc:
exec s6-rc -v2 -up change "$1"

150
modules/systemd/default.nix Normal file
View file

@ -0,0 +1,150 @@
{
pkgs,
lib,
config,
utils,
...
}:
let
inherit (lib)
mapAttrs'
nameValuePair
mkMerge
mapAttrsToList
mkOption
;
inherit (pkgs.pseudofile) dir symlink;
inherit (utils.systemdUtils.lib)
targetToUnit
serviceToUnit
;
systemd-types = import ./types.nix { inherit pkgs utils lib; busybox = config.programs.busybox.package; };
units-texts = mapAttrs' (
_: unit:
nameValuePair unit.name {
file = unit.text;
mode = "0644";
}
) config.systemd.units;
units-aliases = mkMerge (
mapAttrsToList (
_: unit:
mkMerge (
map (aka: {
${aka} = symlink "${unit.name}";
}) (unit.aliases or [ ])
)
) config.systemd.units
);
units-extraWants = mkMerge (
mapAttrsToList (
_: unit:
mkMerge (
map (unit2: {
"${unit2}.wants" = dir {
${unit.name} = symlink "../${unit.name}";
};
}) (unit.wantedBy or [ ])
)
) config.systemd.units
);
units-extraUpholds = mkMerge (
mapAttrsToList (
_: unit:
mkMerge (
map (unit2: {
"${unit2}.upholds" = dir {
${unit.name} = symlink "../${unit.name}";
};
}) (unit.upheldBy or [ ])
)
) config.systemd.units
);
units-extraRequires = mkMerge (
mapAttrsToList (
_: unit:
mkMerge (
map (unit2: {
"${unit2}.requires" = dir {
${unit.name} = symlink "../${unit.name}";
};
}) (unit.requiredBy or [ ])
)
) config.systemd.units
);
in
{
options = {
systemd = {
units = mkOption {
type = systemd-types.units;
};
services = mkOption {
type = systemd-types.services;
};
targets = mkOption {
type = systemd-types.targets;
};
};
};
config = {
systemd = {
units = mkMerge [
(mapAttrs' (_: service: nameValuePair service.name (serviceToUnit service)) config.systemd.services)
(mapAttrs' (_: target: nameValuePair target.name (targetToUnit target)) config.systemd.targets)
];
services = {
getty = {
wantedBy = [ "default.target" ];
unitConfig = {
Description = "Serial Shell";
Before = [ "default.target" ];
};
script = ''
# . /etc/profile
exec /bin/ash < /dev/ttyS0 > /dev/ttyS0 2> /dev/ttyS0
'';
};
};
targets = {
default = { };
sysinit = { };
};
};
kernel.config = {
CGROUPS = "y";
DEVTMPFS = "y";
INOTIFY_USER = "y";
SIGNALFD = "y";
TIMERFD = "y";
EPOLL = "y";
UNIX = "y";
SYSFS = "y";
PROC_FS = "y";
FHANDLE = "y";
};
boot.commandLine = [
"systemd.log_level=7"
#"systemd.crash_shell=true"
];
filesystem = dir {
etc = dir {
systemd = dir {
system = dir (mkMerge [
units-texts
units-aliases
units-extraWants
units-extraUpholds
units-extraRequires
]);
};
};
bin = dir {
init = symlink "${pkgs.systemd}/bin/init";
};
};
};
}

30
modules/systemd/types.nix Normal file
View file

@ -0,0 +1,30 @@
{
pkgs,
lib,
utils,
busybox
}:
let
inherit (utils.systemdUtils.lib) serviceConfig unitConfig;
inherit (utils.systemdUtils.unitOptions) stage2ServiceOptions;
stage2ServiceConfig = {
imports = [ serviceConfig ];
# Default path for systemd services. Should be quite minimal.
config.path = lib.mkAfter [
busybox
# pkgs.coreutils
# pkgs.gnugrep
# pkgs.gnused
pkgs.systemd
];
};
in
{
inherit (utils.systemdUtils.types) units targets;
services = lib.types.attrsOf (lib.types.submodule [
{ enableStrictShellChecks = false; }
unitConfig
stage2ServiceOptions
stage2ServiceConfig
]);
}

View file

@ -259,7 +259,12 @@ extraPkgs // {
patches = o.patches ++ [
./pkgs/qemu/arm-image-friendly-load-addr.patch
];
}); in q.override { nixosTestRunner = true; sdlSupport = false; };
}); in q.override {
vde2 = null;
nixosTestRunner = true;
sdlSupport = false;
hostCpuTargets = [ "mips-softmmu" ];
};
rsyncSmall =
let r = prev.rsync.overrideAttrs(o: {
@ -284,6 +289,192 @@ extraPkgs // {
strace = prev.strace.override { libunwind = null; };
getent =
prev.callPackage ({
lib,
stdenv,
fetchFromGitHub,
}:
stdenv.mkDerivation rec {
pname = "musl-utils";
version = "1.1.12-r7";
src = fetchFromGitHub {
owner = "boltlinux";
repo = "musl-utils";
rev = version;
hash = "sha256-q9CbOyK0Psw3YJnIT3yPRWuwr40nxLZt4RexuOHAUuw=";
};
nativeBuildInputs = [
prev.autoconf
prev.automake
];
preConfigure = ''
autoreconf -i
'';
buildPhase = ''
make -C src getent
'';
installPhase = ''
mkdir -p $out/bin/
cp src/getent $out/bin/
'';
meta = {
description = "Alpine Linux' getconf, getent and iconv implementations";
homepage = "https://github.com/boltlinux/musl-utils";
license = lib.licenses.free; # FIXME: nix-init did not find a license
maintainers = with lib.maintainers; [ ];
mainProgram = "musl-utils";
platforms = lib.platforms.all;
};
}) { };
writeShellScriptBin = name: text:
final.writeTextFile {
inherit name;
executable = true;
destination = "/bin/${name}";
text = ''
#!/bin/ash
${text}
'';
checkPhase = ''
${final.stdenv.shellDryRun} "$target"
'';
meta.mainProgram = name;
};
systemd =
let base = prev.systemd.override {
kbd = "";
coreutils = "";
bash = null;
bashInteractive = "";
withAcl = false;
withAnalyze = false;
withApparmor = false;
withAudit = false;
withBootloader = false;
withCompression = false;
withCoredump = false;
withCryptsetup = false;
withRepart = false;
withDocumentation = false;
withEfi = false;
withFido2 = false;
withHomed = false;
withHostnamed = false;
withHwdb = false;
withImportd = false;
withIptables = false;
withKmod = false;
withLibBPF = false;
withLibidn2 = false;
withLocaled = false;
withLogind = false;
withMachined = false;
withNetworkd = false;
withNss = false;
withOomd = false;
withPam = false;
withPasswordQuality = false;
withPCRE2 = false;
withPolkit = false;
withPortabled = false;
withQrencode = false;
withRemote = false;
withResolved = false;
withShellCompletions = false;
withSysusers = false;
withSysupdate = false;
withTimedated = false;
withTimesyncd = false;
withTpm2Tss = false;
withUkify = false;
withUserDb = false;
withUtmp = false;
withVmspawn = false;
withKernelInstall = false;
withLibarchive = false;
};
in base.overrideAttrs (o: {
mesonFlags = o.mesonFlags ++ [
# "--optimization=s"
"--default-library=static"
"--buildtype=minsize"
# (final.lib.mesonBool "static-libsystemd" true)
# (final.lib.mesonBool "standalone-binaries" true)
# (final.lib.mesonBool "link-udev-shared" false)
# (final.lib.mesonBool "link-executor-shared" false)
# (final.lib.mesonBool "link-systemctl-shared" false)
# (final.lib.mesonBool "link-networkd-shared" false)
# (final.lib.mesonBool "link-timesyncd-shared" false)
# (final.lib.mesonBool "link-journalctl-shared" false)
# (final.lib.mesonBool "link-boot-shared" false)
# (final.lib.mesonBool "link-portabled-shared" false)
];
postInstall = o.postInstall + ''
rm -rf $out/share
rm $out/lib/libudev.so*
rm -rf $out/lib/systemd/catalog
rm -rf $out/lib/systemd/system-generators
rm $out/lib/systemd/systemd-backlight
rm $out/lib/systemd/systemd-battery-check
rm $out/lib/systemd/systemd-hibernate-resume
rm $out/lib/systemd/systemd-makefs
rm $out/lib/systemd/systemd-nsresourced
rm $out/lib/systemd/systemd-nsresourcework
rm $out/lib/systemd/systemd-shutdown
rm $out/lib/systemd/systemd-sleep
rm $out/lib/systemd/systemd-binfmt
rm $out/lib/systemd/systemd-growfs
rm $out/lib/systemd/systemd-mountfsd
rm $out/lib/systemd/systemd-mountwork
rm $out/lib/systemd/systemd-network-generator
rm $out/lib/systemd/systemd-pstore
rm $out/lib/systemd/systemd-remount-fs
rm $out/lib/systemd/systemd-reply-password
rm $out/lib/systemd/systemd-rfkill
rm $out/lib/systemd/systemd-socket-proxyd
rm $out/lib/systemd/systemd-ssh-proxy
rm $out/lib/systemd/systemd-storagetm
rm $out/lib/systemd/systemd-volatile-root
rm $out/lib/systemd/systemd-xdg-autostart-condition
rm -rf $out/example
rm $out/bin/bootctl
rm $out/bin/systemd-nspawn
rm $out/bin/systemd-ac-power
rm $out/bin/systemd-dissect
rm $out/bin/systemd-ask-password
rm $out/bin/systemd-cgls
rm $out/bin/systemd-cgtop
rm $out/bin/systemd-creds
rm $out/bin/systemd-delta
rm $out/bin/systemd-detect-virt
rm $out/bin/systemd-escape
rm $out/bin/systemd-id128
rm $out/bin/systemd-machine-id-setup
rm $out/bin/systemd-path
rm $out/bin/systemd-run
rm $out/bin/systemd-socket-activate
rm $out/bin/systemd-stdio-bridge
rm $out/bin/systemd-sysext
rm $out/bin/systemd-tty-ask-password-agent
rm $out/bin/systemd-vpick
# rm $out/lib/libsystemd.a
# rm $out/lib/systemd/libsystemd-shared-256.so
'';
});
ubootQemuAarch64 = final.buildUBoot {
defconfig = "qemu_arm64_defconfig";
extraMeta.platforms = ["aarch64-linux"];