summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorNikolay Amiantov <ab@fmap.me>2016-08-27 13:29:38 +0300
committerNikolay Amiantov <ab@fmap.me>2016-08-27 13:38:20 +0300
commit6efcfe03ae4ef426b77a6827243433b5296613a4 (patch)
treed71e9494714de0dd1d4c5e05aedfa2c35d58a9e7 /nixos
parent3f70fcd4c1512345a5a8a5e41da8a83839a1b16e (diff)
downloadnixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.tar
nixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.tar.gz
nixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.tar.bz2
nixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.tar.lz
nixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.tar.xz
nixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.tar.zst
nixlib-6efcfe03ae4ef426b77a6827243433b5296613a4.zip
nixos filesystems: unify early filesystems handling
A new internal config option `fileSystems.<name>.early` is added to indicate
that the filesystem needs to be loaded very early (i.e. in initrd). They are
transformed to a shell script in `system.build.earlyMountScript` with calls to
an undefined `specialMount` function, which is expected to be caller-specific.
This option is used by stage-1, stage-2 and activation script to set up and
remount those filesystems.  Options for them are updated according to systemd
defaults.
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/security/hidepid.nix19
-rw-r--r--nixos/modules/system/activation/activation-script.nix12
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh26
-rw-r--r--nixos/modules/system/boot/stage-1.nix4
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh29
-rw-r--r--nixos/modules/system/boot/stage-2.nix3
-rw-r--r--nixos/modules/tasks/filesystems.nix41
7 files changed, 75 insertions, 59 deletions
diff --git a/nixos/modules/security/hidepid.nix b/nixos/modules/security/hidepid.nix
index 8271578c55d6..4917327d617c 100644
--- a/nixos/modules/security/hidepid.nix
+++ b/nixos/modules/security/hidepid.nix
@@ -20,23 +20,6 @@ with lib;
   config = mkIf config.security.hideProcessInformation {
     users.groups.proc.gid = config.ids.gids.proc;
 
-    systemd.services.hidepid = {
-      wantedBy = [ "local-fs.target" ];
-      after = [ "systemd-remount-fs.service" ];
-      before = [ "local-fs-pre.target" "local-fs.target" "shutdown.target" ];
-      wants = [ "local-fs-pre.target" ];
-
-      serviceConfig = {
-        Type = "oneshot";
-        RemainAfterExit = true;
-        ExecStart = ''${pkgs.utillinux}/bin/mount -o remount,hidepid=2,gid=${toString config.ids.gids.proc} /proc'';
-        ExecStop = ''${pkgs.utillinux}/bin/mount -o remount,hidepid=0,gid=0 /proc'';
-      };
-
-      unitConfig = {
-        DefaultDependencies = false;
-        Conflicts = "shutdown.target";
-      };
-    };
+    fileSystems."/proc".options = [ "hidepid=2" "gid=${toString config.ids.gids.proc}" ];
   };
 }
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index 4489e34831da..1c587413121e 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -154,9 +154,15 @@ in
 
     system.activationScripts.tmpfs =
       ''
-        ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.devSize}" none /dev
-        ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.devShmSize}" none /dev/shm
-        ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.runSize}" none /run
+        specialMount() {
+          local device="$1"
+          local mountPoint="$2"
+          local options="$3"
+          local fsType="$4"
+
+          ${pkgs.utillinux}/bin/mount -t "$fsType" -o "remount,$options" "$device" "$mountPoint"
+        }
+        source ${config.system.build.earlyMountScript}
       '';
 
   };
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 65d1dcb61681..abab5f20baac 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -59,22 +59,24 @@ echo
 echo "<<< NixOS Stage 1 >>>"
 echo
 
-
-# Mount special file systems.
+# Make several required directories.
 mkdir -p /etc/udev
 touch /etc/fstab # to shut up mount
-touch /etc/mtab # to shut up mke2fs
+ln -s /proc/mounts /etc/mtab # to shut up mke2fs
 touch /etc/udev/hwdb.bin # to shut up udev
 touch /etc/initrd-release
-mkdir -p /proc
-mount -t proc proc /proc
-mkdir -p /sys
-mount -t sysfs sysfs /sys
-mount -t devtmpfs -o "size=@devSize@" devtmpfs /dev
-mkdir -p /run
-mount -t tmpfs -o "mode=0755,size=@runSize@" tmpfs /run
-mkdir /dev/pts
-mount -t devpts devpts /dev/pts
+
+# Mount special file systems.
+specialMount() {
+  local device="$1"
+  local mountPoint="$2"
+  local options="$3"
+  local fsType="$4"
+
+  mkdir -m 0755 -p "$mountPoint"
+  mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
+}
+source @earlyMountScript@
 
 # Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
 mkdir -p /tmp
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index a5c05f3dbbaf..513c121347b1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -190,7 +190,9 @@ let
 
     inherit udevRules extraUtils modulesClosure;
 
-    inherit (config.boot) resumeDevice devSize runSize;
+    inherit (config.boot) resumeDevice;
+
+    inherit (config.system.build) earlyMountScript;
 
     inherit (config.boot.initrd) checkJournalingFS
       preLVMCommands preDeviceCommands postDeviceCommands postMountCommands preFailCommands kernelModules;
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index c5a14f0766d5..7de85209a159 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -37,12 +37,16 @@ fi
 # Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a
 # stage 1, we need to do that here.
 if [ ! -e /proc/1 ]; then
-    mkdir -m 0755 -p /proc
-    mount -n -t proc proc /proc
-    mkdir -m 0755 -p /dev
-    mount -t devtmpfs devtmpfs /dev
-    mkdir -m 0755 -p /sys
-    mount -t sysfs sysfs /sys
+    specialMount() {
+        local device="$1"
+        local mountPoint="$2"
+        local options="$3"
+        local fsType="$4"
+
+        mkdir -m 0755 -p "$mountPoint"
+        mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
+    }
+    source @earlyMountScript@
 fi
 
 
@@ -87,11 +91,6 @@ done
 
 
 # More special file systems, initialise required directories.
-if ! mountpoint -q /dev/shm; then
-    mkdir -m 0755 /dev/shm
-    mount -t tmpfs -o "rw,nosuid,nodev,size=@devShmSize@" tmpfs /dev/shm
-fi
-mkdir -m 0755 -p /dev/pts
 [ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
 mkdir -m 01777 -p /tmp
 mkdir -m 0755 -p /var /var/log /var/lib /var/db
@@ -112,14 +111,6 @@ rm -f /etc/{group,passwd,shadow}.lock
 rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots
 
 
-# Create a tmpfs on /run to hold runtime state for programs such as
-# udev (if stage 1 hasn't already done so).
-if ! mountpoint -q /run; then
-    rm -rf /run
-    mkdir -m 0755 -p /run
-    mount -t tmpfs -o "mode=0755,size=@runSize@" tmpfs /run
-fi
-
 # Create a ramfs on /run/keys to hold secrets that shouldn't be
 # written to disk (generally used for NixOps, harmless elsewhere).
 if ! mountpoint -q /run/keys; then
diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix
index b67f42a017e6..7e4ec2a4a670 100644
--- a/nixos/modules/system/boot/stage-2.nix
+++ b/nixos/modules/system/boot/stage-2.nix
@@ -20,10 +20,9 @@ let
     src = ./stage-2-init.sh;
     shellDebug = "${pkgs.bashInteractive}/bin/bash";
     isExecutable = true;
-    inherit (config.boot) devShmSize runSize;
     inherit (config.nix) readOnlyStore;
     inherit (config.networking) useHostResolvConf;
-    ttyGid = config.ids.gids.tty;
+    inherit (config.system.build) earlyMountScript;
     path =
       [ pkgs.coreutils
         pkgs.utillinux
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index f146448200f9..d69284a75323 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -18,6 +18,8 @@ let
 
   prioOption = prio: optionalString (prio != null) " pri=${toString prio}";
 
+  specialFSTypes = [ "proc" "sysfs" "tmpfs" "devtmpfs" "devpts" ];
+
   fileSystemOpts = { name, config, ... }: {
 
     options = {
@@ -97,11 +99,22 @@ let
         description = "Disable running fsck on this filesystem.";
       };
 
+      early = mkOption {
+        default = false;
+        type = types.bool;
+        internal = true;
+        description = ''
+	  Mount this filesystem very early during boot. At the moment of
+	  mounting no disks are exposed, so this option is primarily for
+          special file systems.
+        '';
+      };
+
     };
 
     config = {
       mountPoint = mkDefault name;
-      device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType);
+      device = mkIf (elem config.fsType specialFSTypes) (mkDefault config.fsType);
       options = mkIf config.autoResize [ "x-nixos.autoresize" ];
 
       # -F needed to allow bare block device without partitions
@@ -110,6 +123,13 @@ let
 
   };
 
+  # Makes sequence of `specialMount device mountPoint options fsType` commands.
+  # `systemMount` should be defined in the sourcing script.
+  makeSpecialMounts = mounts:
+    pkgs.writeText "mounts.sh" (concatMapStringsSep "\n" (mount: ''
+      specialMount "${mount.device}" "${mount.mountPoint}" "${concatStringsSep "," mount.options}" "${mount.fsType}"
+    '') mounts);
+
 in
 
 {
@@ -131,8 +151,7 @@ in
           "/bigdisk".label = "bigdisk";
         }
       '';
-      type = types.loaOf types.optionSet;
-      options = [ fileSystemOpts ];
+      type = types.loaOf (types.submodule fileSystemOpts);
       description = ''
         The file systems to be mounted.  It must include an entry for
         the root directory (<literal>mountPoint = "/"</literal>).  Each
@@ -177,10 +196,14 @@ in
       { assertion = ! (fileSystems' ? "cycle");
         message = "The ‘fileSystems’ option can't be topologically sorted: mountpoint dependency path ${ls " -> " fileSystems'.cycle} loops to ${ls ", " fileSystems'.loops}";
       }
+      { assertion = all (x: !x.early || (x.label == null && !x.autoFormat && !x.autoResize)) fileSystems;
+        message = "Early filesystems don't support mounting by label, auto formatting and resizing";
+      }
     ];
 
     # Export for use in other modules
     system.build.fileSystems = fileSystems;
+    system.build.earlyMountScript = makeSpecialMounts (filter (fs: fs.early) fileSystems);
 
     boot.supportedFilesystems = map (fs: fs.fsType) fileSystems;
 
@@ -211,7 +234,7 @@ in
             + " " + (if skipCheck fs then "0" else
                      if fs.mountPoint == "/" then "1" else "2")
             + "\n"
-        ) fileSystems}
+        ) (filter (fs: !fs.early) fileSystems)}
 
         # Swap devices.
         ${flip concatMapStrings config.swapDevices (sw:
@@ -258,6 +281,16 @@ in
 
       in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems));
 
+    # Sync mount options with systemd's src/core/mount-setup.c: mount_table.
+    fileSystems = mapAttrs (n: fs: fs // { early = true; }) {
+      "/proc" = { fsType = "proc"; options = [ "nosuid" "noexec" "nodev" ]; };
+      "/sys" = { fsType = "sysfs"; options = [ "nosuid" "noexec" "nodev" ]; };
+      "/run" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=755" "size=${config.boot.runSize}" ]; };
+      "/dev" = { fsType = "devtmpfs"; options = [ "nosuid" "strictatime" "mode=755" "size=${config.boot.devSize}" ]; };
+      "/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; };
+      "/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "gid=${toString config.ids.gids.tty}" ]; };
+    };
+
   };
 
 }