···11+# Overlayfs {#sec-overlayfs}
22+33+NixOS offers a convenient abstraction to create both read-only as well writable
44+overlays.
55+66+```nix
77+fileSystems = {
88+ "/writable-overlay" = {
99+ overlay = {
1010+ lowerdir = [ writableOverlayLowerdir ];
1111+ upperdir = "/.rw-writable-overlay/upper";
1212+ workdir = "/.rw-writable-overlay/work";
1313+ };
1414+ # Mount the writable overlay in the initrd.
1515+ neededForBoot = true;
1616+ };
1717+ "/readonly-overlay".overlay.lowerdir = [
1818+ writableOverlayLowerdir
1919+ writableOverlayLowerdir2
2020+ ];
2121+};
2222+```
2323+2424+If `upperdir` and `workdir` are not null, they will be created before the
2525+overlay is mounted.
2626+2727+To mount an overlay as read-only, you need to provide at least two `lowerdir`s.
+5
nixos/doc/manual/release-notes/rl-2405.section.md
···278278- The option [`services.nextcloud.config.dbport`] of the Nextcloud module was removed to match upstream.
279279 The port can be specified in [`services.nextcloud.config.dbhost`](#opt-services.nextcloud.config.dbhost).
280280281281+- A new abstraction to create both read-only as well as writable overlay file
282282+ systems was added. Available via
283283+ [fileSystems.overlay](#opt-fileSystems._name_.overlay.lowerdir). See also the
284284+ [NixOS docs](#sec-overlayfs).
285285+281286- `stdenv`: The `--replace` flag in `substitute`, `substituteInPlace`, `substituteAll`, `substituteAllStream`, and `substituteStream` is now deprecated if favor of the new `--replace-fail`, `--replace-warn` and `--replace-quiet`. The deprecated `--replace` equates to `--replace-warn`.
282287283288- A new hardening flag, `zerocallusedregs` was made available, corresponding to the gcc/clang option `-fzero-call-used-regs=used-gpr`.
···6464 example = "--max-freed $((64 * 1024**3))";
6565 type = lib.types.singleLineStr;
6666 description = lib.mdDoc ''
6767- Options given to {file}`nix-collect-garbage` when the
6868- garbage collector is run automatically.
6767+ Options given to [`nix-collect-garbage`](https://nixos.org/manual/nix/stable/command-ref/nix-collect-garbage) when the garbage collector is run automatically.
6968 '';
7069 };
7170
+144
nixos/modules/tasks/filesystems/overlayfs.nix
···11+{ config, lib, pkgs, utils, ... }:
22+33+let
44+ # The scripted initrd contains some magic to add the prefix to the
55+ # paths just in time, so we don't add it here.
66+ sysrootPrefix = fs:
77+ if config.boot.initrd.systemd.enable && (utils.fsNeededForBoot fs) then
88+ "/sysroot"
99+ else
1010+ "";
1111+1212+ # Returns a service that creates the required directories before the mount is
1313+ # created.
1414+ preMountService = _name: fs:
1515+ let
1616+ prefix = sysrootPrefix fs;
1717+1818+ escapedMountpoint = utils.escapeSystemdPath (prefix + fs.mountPoint);
1919+ mountUnit = "${escapedMountpoint}.mount";
2020+2121+ upperdir = prefix + fs.overlay.upperdir;
2222+ workdir = prefix + fs.overlay.workdir;
2323+ in
2424+ lib.mkIf (fs.overlay.upperdir != null)
2525+ {
2626+ "rw-${escapedMountpoint}" = {
2727+ requiredBy = [ mountUnit ];
2828+ before = [ mountUnit ];
2929+ unitConfig = {
3030+ DefaultDependencies = false;
3131+ RequiresMountsFor = "${upperdir} ${workdir}";
3232+ };
3333+ serviceConfig = {
3434+ Type = "oneshot";
3535+ ExecStart = "${pkgs.coreutils}/bin/mkdir -p -m 0755 ${upperdir} ${workdir}";
3636+ };
3737+ };
3838+ };
3939+4040+ overlayOpts = { config, ... }: {
4141+4242+ options.overlay = {
4343+4444+ lowerdir = lib.mkOption {
4545+ type = with lib.types; nullOr (nonEmptyListOf (either str pathInStore));
4646+ default = null;
4747+ description = lib.mdDoc ''
4848+ The list of path(s) to the lowerdir(s).
4949+5050+ To create a writable overlay, you MUST provide an upperdir and a
5151+ workdir.
5252+5353+ You can create a read-only overlay when you provide multiple (at
5454+ least 2!) lowerdirs and neither an upperdir nor a workdir.
5555+ '';
5656+ };
5757+5858+ upperdir = lib.mkOption {
5959+ type = lib.types.nullOr lib.types.str;
6060+ default = null;
6161+ description = lib.mdDoc ''
6262+ The path to the upperdir.
6363+6464+ If this is null, a read-only overlay is created using the lowerdir.
6565+6666+ If you set this to some value you MUST also set `workdir`.
6767+ '';
6868+ };
6969+7070+ workdir = lib.mkOption {
7171+ type = lib.types.nullOr lib.types.str;
7272+ default = null;
7373+ description = lib.mdDoc ''
7474+ The path to the workdir.
7575+7676+ This MUST be set if you set `upperdir`.
7777+ '';
7878+ };
7979+8080+ };
8181+8282+ config = lib.mkIf (config.overlay.lowerdir != null) {
8383+ fsType = "overlay";
8484+ device = lib.mkDefault "overlay";
8585+8686+ options =
8787+ let
8888+ prefix = sysrootPrefix config;
8989+9090+ lowerdir = map (s: prefix + s) config.overlay.lowerdir;
9191+ upperdir = prefix + config.overlay.upperdir;
9292+ workdir = prefix + config.overlay.workdir;
9393+ in
9494+ [
9595+ "lowerdir=${lib.concatStringsSep ":" lowerdir}"
9696+ ] ++ lib.optionals (config.overlay.upperdir != null) [
9797+ "upperdir=${upperdir}"
9898+ "workdir=${workdir}"
9999+ ] ++ (map (s: "x-systemd.requires-mounts-for=${s}") lowerdir);
100100+ };
101101+102102+ };
103103+in
104104+105105+{
106106+107107+ options = {
108108+109109+ # Merge the overlay options into the fileSystems option.
110110+ fileSystems = lib.mkOption {
111111+ type = lib.types.attrsOf (lib.types.submodule [ overlayOpts ]);
112112+ };
113113+114114+ };
115115+116116+ config =
117117+ let
118118+ overlayFileSystems = lib.filterAttrs (_name: fs: (fs.overlay.lowerdir != null)) config.fileSystems;
119119+ initrdFileSystems = lib.filterAttrs (_name: utils.fsNeededForBoot) overlayFileSystems;
120120+ userspaceFileSystems = lib.filterAttrs (_name: fs: (!utils.fsNeededForBoot fs)) overlayFileSystems;
121121+ in
122122+ {
123123+124124+ boot.initrd.availableKernelModules = lib.mkIf (initrdFileSystems != { }) [ "overlay" ];
125125+126126+ assertions = lib.concatLists (lib.mapAttrsToList
127127+ (_name: fs: [
128128+ {
129129+ assertion = (fs.overlay.upperdir == null) == (fs.overlay.workdir == null);
130130+ message = "You cannot define a `lowerdir` without a `workdir` and vice versa for mount point: ${fs.mountPoint}";
131131+ }
132132+ {
133133+ assertion = (fs.overlay.lowerdir != null && fs.overlay.upperdir == null) -> (lib.length fs.overlay.lowerdir) >= 2;
134134+ message = "A read-only overlay (without an `upperdir`) requires at least 2 `lowerdir`s: ${fs.mountPoint}";
135135+ }
136136+ ])
137137+ config.fileSystems);
138138+139139+ boot.initrd.systemd.services = lib.mkMerge (lib.mapAttrsToList preMountService initrdFileSystems);
140140+ systemd.services = lib.mkMerge (lib.mapAttrsToList preMountService userspaceFileSystems);
141141+142142+ };
143143+144144+}
+12-4
nixos/modules/virtualisation/qemu-vm.nix
···10661066 ''}
10671067 '';
1068106810691069- systemd.tmpfiles.rules = lib.mkIf config.boot.initrd.systemd.enable [
10701070- "f /etc/NIXOS 0644 root root -"
10711071- "d /boot 0644 root root -"
10721072- ];
10691069+ systemd.tmpfiles.settings."10-qemu-vm" = lib.mkIf config.boot.initrd.systemd.enable {
10701070+ "/etc/NIXOS".f = {
10711071+ mode = "0644";
10721072+ user = "root";
10731073+ group = "root";
10741074+ };
10751075+ "${config.boot.loader.efi.efiSysMountPoint}".d = {
10761076+ mode = "0644";
10771077+ user = "root";
10781078+ group = "root";
10791079+ };
10801080+ };
1073108110741082 # After booting, register the closure of the paths in
10751083 # `virtualisation.additionalPaths' in the Nix database in the VM. This
···11+{
22+ lib,
33+ buildNimPackage,
44+ fetchFromGitHub,
55+}:
66+buildNimPackage (final: prev: {
77+ pname = "nimlangserver";
88+ version = "1.2.0";
99+1010+ # lock.json was generated by converting
1111+ # nimble.lock into requires "<gitUrl>#revSha" in a dummy.nimble
1212+ # for all packages and then running nim_lk on said dummy package
1313+ # default nim_lk output fails because it attempts
1414+ # to use branches that will not work instead of HEAD for packages
1515+ lockFile = ./lock.json;
1616+1717+ src = fetchFromGitHub {
1818+ owner = "nim-lang";
1919+ repo = "langserver";
2020+ rev = "71b59bfa77dabf6b8b381f6e18a1d963a1a658fc";
2121+ hash = "sha256-dznegEhRHvztrNhBcUhW83RYgJpduwdGLWj/tJ//K8c=";
2222+ };
2323+2424+ doCheck = false;
2525+2626+ meta = with lib;
2727+ final.src.meta
2828+ // {
2929+ description = "The Nim language server implementation (based on nimsuggest)";
3030+ license = licenses.mit;
3131+ mainProgram = "nimlangserver";
3232+ maintainers = with maintainers; [daylinmorgan];
3333+ };
3434+})
···188188 description = "A flexible, powerful daemon for playing music";
189189 homepage = "https://www.musicpd.org/";
190190 license = licenses.gpl2Only;
191191- maintainers = with maintainers; [ astsmtl ehmry tobim ];
191191+ maintainers = with maintainers; [ astsmtl tobim ];
192192 platforms = platforms.unix;
193193 mainProgram = "mpd";
194194
+4-3
pkgs/servers/slimserver/default.nix
···2222in
2323perlPackages.buildPerlPackage rec {
2424 pname = "slimserver";
2525- version = "8.3.1";
2525+ version = "8.4.0";
26262727 src = fetchFromGitHub {
2828 owner = "Logitech";
2929 repo = "slimserver";
3030 rev = version;
3131- hash = "sha256-yMFOwh/oPiJnUsKWBGvd/GZLjkWocMAUK0r+Hx/SUPo=";
3131+ hash = "sha256-92mKchgAWRIrNOeK/zXUYRqIAk6THdtz1zQe3fg2kE0=";
3232 };
33333434 nativeBuildInputs = [ makeWrapper ];
···150150151151 meta = with lib; {
152152 homepage = "https://github.com/Logitech/slimserver";
153153+ changelog = "https://github.com/Logitech/slimserver/blob/${version}/Changelog${lib.versions.major version}.html";
153154 description = "Server for Logitech Squeezebox players. This server is also called Logitech Media Server";
154154- # the firmware is not under a free license, but not included in the default package
155155+ # the firmware is not under a free license, so we do not include firmware in the default package
155156 # https://github.com/Logitech/slimserver/blob/public/8.3/License.txt
156157 license = if enableUnfreeFirmware then licenses.unfree else licenses.gpl2Only;
157158 mainProgram = "slimserver";