Deployment and lifecycle management for Nix
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

services: add poc for injecting services into a package

+327 -1
+11 -1
flake.nix
··· 100 100 default = pkgs.callPackage ./nix/tests/e2e.nix { 101 101 flake = self; 102 102 }; 103 + services = pkgs.callPackage ./nix/tests/services.nix { 104 + flake = self; 105 + }; 103 106 }; 104 107 105 108 packages = { ··· 108 111 buildGoModule = pkgs.buildGo123Module; 109 112 inherit version; 110 113 }; 111 - server = pkgs.callPackage ./nix/packages/server.nix { inherit beamPackages elixir version; }; 114 + server = pkgs.callPackage ./nix/packages/server.nix { 115 + inherit 116 + beamPackages 117 + elixir 118 + inputs 119 + version 120 + ; 121 + }; 112 122 }; 113 123 114 124 process-compose.devServices =
+275
nix/packages/server.nix
··· 1 1 { 2 + inputs, 2 3 lib, 4 + pkgs, 3 5 callPackages, 4 6 beamPackages, 5 7 elixir, ··· 12 14 let 13 15 arch = if stdenv.isAarch64 then "arm64" else "x64"; 14 16 os = if stdenv.isDarwin then "darwin" else "linux"; 17 + pkgs' = pkgs; 18 + 19 + generateUnitFiles = 20 + { 21 + pkgs, 22 + config, 23 + }: 24 + let 25 + moduler = lib.evalModules { 26 + modules = [ 27 + { 28 + config._module.args = { 29 + inherit pkgs; 30 + }; 31 + } 32 + ( 33 + { 34 + config, 35 + lib, 36 + ... 37 + }: 38 + let 39 + utils = import "${inputs.nixpkgs}/nixos/lib/utils.nix" { 40 + inherit config lib pkgs; 41 + }; 42 + 43 + inherit (utils) systemdUtils; 44 + 45 + inherit (systemdUtils.lib) 46 + generateUnits 47 + targetToUnit 48 + serviceToUnit 49 + socketToUnit 50 + timerToUnit 51 + pathToUnit 52 + mountToUnit 53 + automountToUnit 54 + sliceToUnit 55 + ; 56 + 57 + inherit (lib) 58 + listToAttrs 59 + literalExpression 60 + mkEnableOption 61 + mkOption 62 + mkPackageOption 63 + types 64 + mapAttrs' 65 + ; 66 + 67 + cfg = config.systemd; 68 + in 69 + { 70 + options = { 71 + service-units = lib.mkOption { 72 + # TODO type this 73 + }; 74 + 75 + systemd = { 76 + package = mkPackageOption pkgs "systemd" { }; 77 + 78 + enableStrictShellChecks = mkEnableOption "" // { 79 + description = "Whether to run shellcheck on the generated scripts for systemd units."; 80 + }; 81 + 82 + units = mkOption { 83 + description = "Definition of systemd units; see {manpage}`systemd.unit(5)`."; 84 + default = { }; 85 + type = systemdUtils.types.units; 86 + }; 87 + 88 + packages = mkOption { 89 + default = [ ]; 90 + type = types.listOf types.package; 91 + example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]"; 92 + description = "Packages providing systemd units and hooks."; 93 + }; 94 + 95 + targets = mkOption { 96 + default = { }; 97 + type = systemdUtils.types.targets; 98 + description = "Definition of systemd target units; see {manpage}`systemd.target(5)`"; 99 + }; 100 + 101 + services = mkOption { 102 + default = { }; 103 + type = systemdUtils.types.services; 104 + description = "Definition of systemd service units; see {manpage}`systemd.service(5)`."; 105 + }; 106 + 107 + sockets = mkOption { 108 + default = { }; 109 + type = systemdUtils.types.sockets; 110 + description = "Definition of systemd socket units; see {manpage}`systemd.socket(5)`."; 111 + }; 112 + 113 + timers = mkOption { 114 + default = { }; 115 + type = systemdUtils.types.timers; 116 + description = "Definition of systemd timer units; see {manpage}`systemd.timer(5)`."; 117 + }; 118 + 119 + paths = mkOption { 120 + default = { }; 121 + type = systemdUtils.types.paths; 122 + description = "Definition of systemd path units; see {manpage}`systemd.path(5)`."; 123 + }; 124 + 125 + mounts = mkOption { 126 + default = [ ]; 127 + type = systemdUtils.types.mounts; 128 + description = '' 129 + Definition of systemd mount units; see {manpage}`systemd.mount(5)`. 130 + 131 + This is a list instead of an attrSet, because systemd mandates 132 + the names to be derived from the `where` attribute. 133 + ''; 134 + }; 135 + 136 + automounts = mkOption { 137 + default = [ ]; 138 + type = systemdUtils.types.automounts; 139 + description = '' 140 + Definition of systemd automount units; see {manpage}`systemd.automount(5)`. 141 + 142 + This is a list instead of an attrSet, because systemd mandates 143 + the names to be derived from the `where` attribute. 144 + ''; 145 + }; 146 + 147 + defaultUnit = mkOption { 148 + default = "multi-user.target"; 149 + type = types.str; 150 + description = '' 151 + Default unit started when the system boots; see {manpage}`systemd.special(7)`. 152 + ''; 153 + }; 154 + 155 + ctrlAltDelUnit = mkOption { 156 + default = "reboot.target"; 157 + type = types.str; 158 + example = "poweroff.target"; 159 + description = '' 160 + Target that should be started when Ctrl-Alt-Delete is pressed; 161 + see {manpage}`systemd.special(7)`. 162 + ''; 163 + }; 164 + 165 + globalEnvironment = mkOption { 166 + type = 167 + with types; 168 + attrsOf ( 169 + nullOr (oneOf [ 170 + str 171 + path 172 + package 173 + ]) 174 + ); 175 + default = { }; 176 + example = { 177 + TZ = "CET"; 178 + }; 179 + description = '' 180 + Environment variables passed to *all* systemd units. 181 + ''; 182 + }; 183 + 184 + }; 185 + }; 186 + 187 + config = { 188 + systemd = { 189 + package = pkgs.systemd; 190 + defaultUnit = "default.target"; 191 + ctrlAltDelUnit = "reboot.target"; 192 + 193 + units = 194 + let 195 + withName = cfgToUnit: cfg: lib.nameValuePair cfg.name (cfgToUnit cfg); 196 + in 197 + mapAttrs' (_: withName serviceToUnit) cfg.services 198 + // mapAttrs' (_: withName socketToUnit) cfg.sockets 199 + // mapAttrs' (_: withName targetToUnit) cfg.targets 200 + // mapAttrs' (_: withName timerToUnit) cfg.timers 201 + // listToAttrs (map (withName mountToUnit) cfg.mounts) 202 + // listToAttrs (map (withName automountToUnit) cfg.automounts); 203 + }; 204 + }; 205 + 206 + } 207 + ) 208 + ( 209 + { 210 + config, 211 + lib, 212 + pkgs, 213 + ... 214 + }: 215 + let 216 + utils = import "${inputs.nixpkgs}/nixos/lib/utils.nix" { 217 + inherit config lib pkgs; 218 + }; 219 + upstreamUnits = [ 220 + "basic.target" 221 + ]; 222 + 223 + upstreamWants = [ 224 + "multi-user.target.wants" 225 + ]; 226 + 227 + system-units = utils.systemdUtils.lib.generateUnits { 228 + type = "system"; 229 + inherit (config.systemd) units; 230 + inherit upstreamUnits upstreamWants; 231 + packages = [ ]; 232 + }; 233 + in 234 + { 235 + config = { 236 + service-units = pkgs.runCommand "service-units" { } '' 237 + cp -R ${system-units} $out 238 + chmod +w -R $out 239 + find $out -xtype l -delete 240 + find $out -type d -empty -delete 241 + for unit in ${builtins.toString upstreamUnits}; do 242 + rm $out/$unit 243 + done 244 + ''; 245 + }; 246 + } 247 + ) 248 + { 249 + systemd = config; 250 + } 251 + ]; 252 + class = "sower_services"; 253 + }; 254 + 255 + in 256 + moduler.config.service-units; 15 257 in 16 258 beamPackages.mixRelease rec { 17 259 pname = "sower"; ··· 33 275 ]; 34 276 }; 35 277 278 + sowerServices = generateUnitFiles { 279 + inherit pkgs; 280 + config = { 281 + services.test = { 282 + wantedBy = [ 283 + "default.target" 284 + "network-online.target" 285 + "multi-user.target" 286 + ]; 287 + serviceConfig = { 288 + Type = "oneshot"; 289 + ExecStart = "PLACEHOLDER_OUT/bin/sower"; 290 + }; 291 + }; 292 + 293 + sockets.test-socket = { 294 + wantedBy = [ "sockets.target" ]; 295 + }; 296 + }; 297 + }; 298 + 36 299 mixNixDeps = callPackages ./deps.nix { 37 300 inherit lib beamPackages; 38 301 overrides = _: prev: { ··· 77 340 ln -sfv ${lib.getExe tailwindcss} _build/tailwind-${os}-${arch} 78 341 79 342 mix assets.deploy --no-deps-check 343 + ''; 344 + 345 + preInstall = '' 346 + mkdir -p $out/.sower/systemd/system 347 + find ${sowerServices} -mindepth 1 -type d | while read dir; do 348 + cp --recursive $dir $out/.sower/systemd/system/ 349 + done 350 + cp --dereference ${sowerServices}/* $out/.sower/systemd/system || true 351 + find $out/.sower/systemd/ -type f | while read unit; do 352 + chmod +w $unit 353 + sed -i "s,PLACEHOLDER_OUT,$out," $unit 354 + done 80 355 ''; 81 356 82 357 # disabled because requires test deps to work
+41
nix/tests/services.nix
··· 1 + { 2 + flake, 3 + testers, 4 + }: 5 + testers.runNixOSTest { 6 + name = "sower"; 7 + 8 + nodes = { 9 + server = 10 + { lib, pkgs, ... }: 11 + { 12 + imports = [ ../nixos/module.nix ]; 13 + 14 + config = { 15 + boot.extraSystemdUnitPaths = [ 16 + "/etc/sower/system" 17 + ]; 18 + 19 + environment.etc = { 20 + "sower/system/test.service".text = '' 21 + [Unit] 22 + 23 + [Service] 24 + Type=oneshot 25 + RemainAfterExit=yes 26 + ExecStart=/run/current-system/sw/bin/true 27 + ''; 28 + 29 + # "sower/system/multi-user.target.wants/test.service".source = "/etc/sower/system/test.service"; 30 + }; 31 + }; 32 + 33 + }; 34 + }; 35 + 36 + testScript = # python 37 + '' 38 + start_all() 39 + server.wait_for_unit("test.service") 40 + ''; 41 + }