Browse Source

Activation script rework

Signed-off-by: Magic_RB <magic_rb@redalder.org>
master
Magic_RB 1 month ago
parent
commit
44639ca55d
Signed by: Magic_RB GPG Key ID: 08D5287CC5DDCA0E
4 changed files with 193 additions and 21 deletions
  1. +5
    -0
      lib/dag.nix
  2. +20
    -3
      modules/runit/default.nix
  3. +146
    -10
      modules/system.nix
  4. +22
    -8
      modules/users.nix

+ 5
- 0
lib/dag.nix View File

@ -0,0 +1,5 @@
{ fetchurl, lib, callPackage }:
callPackage (import (fetchurl {
url = "https://raw.githubusercontent.com/nix-community/home-manager/45abf3d38a2b51c00c347cab6950f3734e023bba/modules/lib/dag.nix";
sha256 = "sha256-NN9iKanf86D1MH9Nx8nsQj9T2+Poy9XeW9pLcZIyFHU=";
})) {}

+ 20
- 3
modules/runit/default.nix View File

@ -45,7 +45,7 @@ in
file = ./stage-2.sh;
substitutes = {
inherit (pkgs) runit findutils busybox;
inherit (cfg) serviceDir runtimeServiceDirectory;
inherit (cfg) runtimeServiceDirectory;
};
};
};
@ -61,7 +61,7 @@ in
};
};
};
serviceDir = mkOption {
serviceDirectory = mkOption {
description = "Generated service directory";
type = types.path;
readOnly = true;
@ -69,8 +69,25 @@ in
};
config = {
system.activation."runit" = nglib.dag.dagEntryAnywhere
''
export PATH=${pkgs.findutils}/bin:${pkgs.busybox}/bin
mkdir -p ${cfg.runtimeServiceDirectory}
function linkFarm() {
src="$1"
dst="$2"
find "$src" -mindepth 1 -type d -printf "%P\n" | xargs -I {} mkdir "$dst/{}"
find "$src" -mindepth 1 -type f -printf "%P\n" | xargs -I {} ln -s "$src/{}" "$dst/{}"
find "$src" -mindepth 1 -type l -printf "%P\n" | xargs -I {} cp "$src/{}" "$dst/{}"
}
linkFarm ${cfg.serviceDirectory} ${cfg.runtimeServiceDirectory}
'';
runit = {
serviceDir = pkgs.runCommandNoCCLocal "service-dir" {} ''
serviceDirectory = pkgs.runCommandNoCCLocal "service-dir" {} ''
mkdir $out
${concatStringsSep "\n" (mapAttrsToList (n: s:
let


+ 146
- 10
modules/system.nix View File

@ -1,22 +1,88 @@
{ pkgs, lib, config, ... }:
{ pkgs, lib, nglib, config, ... }:
with lib;
let
cfg = config.system;
configFinal = config;
in
{
options.system = {
createEnvSh = mkOption {
description = ''
Automatically create /bin/sh and /usr/bin/env, without the former
even some system calls will fails, most notable PostreSQL will exit
with a cryptic error.
'';
type = types.bool;
default = true;
};
build = {
toplevel = mkOption {
description = ''
The full system, built up.
'';
type = types.path;
};
ociImage = mkOption {
description = ''
OCI compatible image.
'';
type = types.submodule {
options = {
build = mkOption {
description = ''
A path to a OCI image in a gziped tarball.
'';
type = types.path;
};
stream = mkOption {
description = ''
A script which builds an OCI image and outputs what it builds
into stdout without saving to disk.
'';
type = types.path;
};
};
};
};
};
activation = mkOption {
description = ''
A set of shell script fragments that are executed when a NixNG system
configuration is activated. You can update /etc,
create accounts, and so on. For creating service related directories or file,
please user <option>init.services.<service>.ensureSomething</option>.
These fragments are isolated and can't effect each other environment.
These are run every time the system configuration is activated, which alse
please use <option>init.services.<service>.ensureSomething</option>.
These fragments are isolated and can't effect each other's environment.
These are run every time the system configuration is activated, which also
happens at boot, therefore it's important that these scripts are idempotent
and fast.
'';
type = types.attrsOf types.str;
type = with types; attrsOf (submodule {
options = {
data = mkOption {
description = ''
Script fragment which to run.
'';
type = types.str;
};
before = mkOption {
description = ''
Script before dependencies. See <literal>/lib/dag.nix</literal>.
'';
type = with types; listOf str;
};
after = mkOption {
description = ''
Script after dependencies. See <literal>/lib/dag.nix</literal>
'';
type = with types; listOf str;
};
};
});
apply = x: nglib.dag.dagTopoSort x;
default = {};
};
activationScript = mkOption {
@ -29,16 +95,86 @@ in
};
config = {
system.build = {
toplevel = pkgs.runCommandNoCC "nixng"
{ nativeBuildInputs = with pkgs; [ busybox ]; }
(with configFinal;
''
mkdir $out
ln -s ${init.script} $out/init
ln -s ${system.activationScript} $out/activation
'');
ociImage =
let
config = {
name = "nixng";
tag = "latest";
config = {
StopSignal = "SIGCONT";
Entrypoint =
[ "${configFinal.init.script}/init"
];
};
};
in
with pkgs; {
build = dockerTools.buildLayeredImage config;
stream = dockerTools.streamLayeredImage config;
};
};
system.activation.createEnvSh = mkIf cfg.createEnvSh
(nglib.dag.dagEntryAnywhere
''
# Borrowed from NixOS therefore it's licensed under the MIT license
#### Activation script snippet usrbinenv:
_localstatus=0
mkdir -m 0755 -p /usr/bin
ln -sfn ${pkgs.busybox}/bin/env /usr/bin/.env.tmp
mv /usr/bin/.env.tmp /usr/bin/env # atomically replace /usr/bin/env
# Create the required /bin/sh symlink; otherwise lots of things
# (notably the system() function) won't work.
mkdir -m 0755 -p /bin
ln -sfn "${pkgs.busybox}/bin/sh" /bin/.sh.tmp
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
'');
system.activationScript = pkgs.writeShellScript "activation"
''
${concatStringsSep "\n" (mapAttrsToList (n: v:
_status=0
trap "_status=1 _localstatus=\$?" ERR
${concatStringsSep "\n" (map (dag:
''
echo "Running activation script ${n}"
_localstatus=0
echo "Running activation script ${dag.name}"
(
${v}
) || echo "Activation script ${n} exited with code $!"
${dag.data}
)
if (( _localstatus > 0 )); then
printf "Activation script snippet '%s' failed (%s)\n" "${dag.name}" "$_localstatus"
fi
''
) cfg.activation)}
) cfg.activation.result)}
exit $_status
'';
assertions = [
{
assertion = !(cfg.activation ? "cycle" || cfg.activation ? "loops");
message = ''
`cfg.activation` has one or more cycles and/or loops.
- cycles:
${(map (x: "{ after = [ ${concatSepStrings " " x.after} ]; data = ${x.data}; name = ${x.name} }") cfg.activation.loops or []) or ""}
- loops:
${(map (x: "{ after = [ ${concatSepStrings " " x.after} ]; data = ${x.data}; name = ${x.name} }") cfg.activation.loops or [])}
'';
}
];
};
}

+ 22
- 8
modules/users.nix View File

@ -1,4 +1,4 @@
{ lib, pkgs, config, ... }:
{ nglib, lib, pkgs, config, ... }:
with lib;
let
ids = config.ids;
@ -187,13 +187,21 @@ in
) cfg.users);
system.activation."users" =
''
export PATH=${pkgs.busybox}/bin
let
createHomes =
concatMapStringsSep "\n"
({ n, v }: "mkdir -p ${v.home} && chown ${n}:${v.group} ${v.home}")
(filter ({ v, ... }: v.createHome)
(mapAttrsToList (n: v: { n = n; v = v; }) cfg.users));
in
nglib.dag.dagEntryAnywhere ''
export PATH=${pkgs.busybox}/bin
ln -sf ${cfg.passwdFile} /etc/passwd
ln -sf ${cfg.groupFile} /etc/group
${cfg.generateShadow} > /etc/shadow-generator
'';
ln -sf ${cfg.passwdFile} /etc/passwd
ln -sf ${cfg.groupFile} /etc/group
${cfg.generateShadow} > /etc/shadow-generator
${createHomes}
'';
users = {
users = mkIf cfg.createDefaultUsersGroups {
@ -204,7 +212,13 @@ in
home = "/root";
useDefaultShell = true;
};
nobody.uid = ids.uids.nobody;
nobody = {
uid = ids.uids.nobody;
group = "nogroup";
createHome = true;
home = "/var/empty";
shell = "${pkgs.busybox}/bin/nologin";
};
};
groups = mkMerge [


Loading…
Cancel
Save