nixos: allow more things to be disabled (#429695)

This commit is contained in:
Arian van Putten
2025-08-10 19:49:52 +02:00
committed by GitHub
10 changed files with 247 additions and 182 deletions

View File

@@ -8,41 +8,47 @@
}: }:
let let
requiredPackages = corePackageNames = [
map (pkg: lib.setPrio ((pkg.meta.priority or lib.meta.defaultPriority) + 3) pkg) "acl"
[ "attr"
pkgs.acl "bashInteractive" # bash with ncurses support
pkgs.attr "bzip2"
pkgs.bashInteractive # bash with ncurses support "coreutils-full"
pkgs.bzip2 "cpio"
pkgs.coreutils-full "curl"
pkgs.cpio "diffutils"
pkgs.curl "findutils"
pkgs.diffutils "gawk"
pkgs.findutils "getent"
pkgs.gawk "getconf"
pkgs.stdenv.cc.libc "gnugrep"
pkgs.getent "gnupatch"
pkgs.getconf "gnused"
pkgs.gnugrep "gnutar"
pkgs.gnupatch "gzip"
pkgs.gnused "xz"
pkgs.gnutar "less"
pkgs.gzip "libcap"
pkgs.xz "ncurses"
pkgs.less "netcat"
pkgs.libcap "mkpasswd"
pkgs.ncurses "procps"
pkgs.netcat "su"
config.programs.ssh.package "time"
pkgs.mkpasswd "util-linux"
pkgs.procps "which"
pkgs.su "zstd"
pkgs.time ];
pkgs.util-linux corePackages =
pkgs.which (map (
pkgs.zstd n:
]; let
pkg = pkgs.${n};
in
lib.setPrio ((pkg.meta.priority or lib.meta.defaultPriority) + 3) pkg
) corePackageNames)
++ [ pkgs.stdenv.cc.libc ];
corePackagesText = "[ ${lib.concatMapStringsSep " " (n: "pkgs.${n}") corePackageNames} ]";
defaultPackageNames = [ defaultPackageNames = [
"perl" "perl"
@@ -80,6 +86,29 @@ in
''; '';
}; };
corePackages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = corePackages;
defaultText = lib.literalMD ''
these packages, with their `meta.priority` numerically increased
(thus lowering their installation priority):
${corePackagesText}
'';
example = [ ];
description = ''
Set of core packages for a normal interactive system.
Only change this if you know what you're doing!
Like with systemPackages, packages are installed to
{file}`/run/current-system/sw`. They are
automatically available to all users, and are
automatically updated every time you rebuild the system
configuration.
'';
};
defaultPackages = lib.mkOption { defaultPackages = lib.mkOption {
type = lib.types.listOf lib.types.package; type = lib.types.listOf lib.types.package;
default = defaultPackages; default = defaultPackages;
@@ -151,7 +180,7 @@ in
config = { config = {
environment.systemPackages = requiredPackages ++ config.environment.defaultPackages; environment.systemPackages = config.environment.corePackages ++ config.environment.defaultPackages;
environment.pathsToLink = [ environment.pathsToLink = [
"/bin" "/bin"

View File

@@ -23,28 +23,23 @@ let
in in
{ {
imports = [
(lib.mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
];
options = { options = {
programs.bash = { programs.bash = {
/* enable = lib.mkOption {
enable = lib.mkOption { default = true;
default = true; description = ''
description = '' Whenever to configure Bash as an interactive shell.
Whenever to configure Bash as an interactive shell. Note that this tries to make Bash the default
Note that this tries to make Bash the default {option}`users.defaultUserShell`,
{option}`users.defaultUserShell`, which in turn means that you might need to explicitly
which in turn means that you might need to explicitly set this variable if you have another shell configured
set this variable if you have another shell configured with NixOS.
with NixOS. '';
''; type = lib.types.bool;
type = lib.types.bool; };
};
*/
shellAliases = lib.mkOption { shellAliases = lib.mkOption {
default = { }; default = { };
@@ -129,121 +124,120 @@ in
}; };
config = # lib.mkIf cfg.enable config = lib.mkIf cfg.enable {
{
programs.bash = { programs.bash = {
shellAliases = builtins.mapAttrs (name: lib.mkDefault) cfge.shellAliases; shellAliases = builtins.mapAttrs (name: lib.mkDefault) cfge.shellAliases;
shellInit = '' shellInit = ''
if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
. ${config.system.build.setEnvironment} . ${config.system.build.setEnvironment}
fi
${cfge.shellInit}
'';
loginShellInit = cfge.loginShellInit;
interactiveShellInit = ''
# Check the window size after every command.
shopt -s checkwinsize
# Disable hashing (i.e. caching) of command lookups.
set +h
${cfg.promptInit}
${cfg.promptPluginInit}
${bashAliases}
${cfge.interactiveShellInit}
'';
};
environment.etc.profile.text = ''
# /etc/profile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for login shells.
# Only execute this file once per shell.
if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
__ETC_PROFILE_SOURCED=1
# Prevent this file from being sourced by interactive non-login child shells.
export __ETC_PROFILE_DONE=1
${cfg.shellInit}
${cfg.loginShellInit}
# Read system-wide modifications.
if test -f /etc/profile.local; then
. /etc/profile.local
fi fi
if [ -n "''${BASH_VERSION:-}" ]; then ${cfge.shellInit}
. /etc/bashrc
fi
''; '';
environment.etc.bashrc.text = '' loginShellInit = cfge.loginShellInit;
# /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
# Only execute this file once per shell. interactiveShellInit = ''
if [ -n "$__ETC_BASHRC_SOURCED" ] || [ -n "$NOSYSBASHRC" ]; then return; fi # Check the window size after every command.
__ETC_BASHRC_SOURCED=1 shopt -s checkwinsize
# If the profile was not loaded in a parent process, source # Disable hashing (i.e. caching) of command lookups.
# it. But otherwise don't do it because we don't want to set +h
# clobber overridden values of $PATH, etc.
if [ -z "$__ETC_PROFILE_DONE" ]; then
. /etc/profile
fi
# We are not always an interactive shell. ${cfg.promptInit}
if [ -n "$PS1" ]; then ${cfg.promptPluginInit}
${cfg.interactiveShellInit} ${bashAliases}
fi
# Read system-wide modifications. ${cfge.interactiveShellInit}
if test -f /etc/bashrc.local; then
. /etc/bashrc.local
fi
''; '';
environment.etc.bash_logout.text = ''
# /etc/bash_logout: DO NOT EDIT -- this file has been generated automatically.
# Only execute this file once per shell.
if [ -n "$__ETC_BASHLOGOUT_SOURCED" ] || [ -n "$NOSYSBASHLOGOUT" ]; then return; fi
__ETC_BASHLOGOUT_SOURCED=1
${cfg.logout}
# Read system-wide modifications.
if test -f /etc/bash_logout.local; then
. /etc/bash_logout.local
fi
'';
# Configuration for readline in bash. We use "option default"
# priority to allow user override using both .text and .source.
environment.etc.inputrc.source = lib.mkOptionDefault ./inputrc;
users.defaultUserShell = lib.mkDefault pkgs.bashInteractive;
environment.pathsToLink = lib.optionals cfg.completion.enable [
"/etc/bash_completion.d"
"/share/bash-completion"
];
environment.shells = [
"/run/current-system/sw/bin/bash"
"/run/current-system/sw/bin/sh"
"${pkgs.bashInteractive}/bin/bash"
"${pkgs.bashInteractive}/bin/sh"
];
}; };
environment.etc.profile.text = ''
# /etc/profile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for login shells.
# Only execute this file once per shell.
if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
__ETC_PROFILE_SOURCED=1
# Prevent this file from being sourced by interactive non-login child shells.
export __ETC_PROFILE_DONE=1
${cfg.shellInit}
${cfg.loginShellInit}
# Read system-wide modifications.
if test -f /etc/profile.local; then
. /etc/profile.local
fi
if [ -n "''${BASH_VERSION:-}" ]; then
. /etc/bashrc
fi
'';
environment.etc.bashrc.text = ''
# /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
# Only execute this file once per shell.
if [ -n "$__ETC_BASHRC_SOURCED" ] || [ -n "$NOSYSBASHRC" ]; then return; fi
__ETC_BASHRC_SOURCED=1
# If the profile was not loaded in a parent process, source
# it. But otherwise don't do it because we don't want to
# clobber overridden values of $PATH, etc.
if [ -z "$__ETC_PROFILE_DONE" ]; then
. /etc/profile
fi
# We are not always an interactive shell.
if [ -n "$PS1" ]; then
${cfg.interactiveShellInit}
fi
# Read system-wide modifications.
if test -f /etc/bashrc.local; then
. /etc/bashrc.local
fi
'';
environment.etc.bash_logout.text = ''
# /etc/bash_logout: DO NOT EDIT -- this file has been generated automatically.
# Only execute this file once per shell.
if [ -n "$__ETC_BASHLOGOUT_SOURCED" ] || [ -n "$NOSYSBASHLOGOUT" ]; then return; fi
__ETC_BASHLOGOUT_SOURCED=1
${cfg.logout}
# Read system-wide modifications.
if test -f /etc/bash_logout.local; then
. /etc/bash_logout.local
fi
'';
# Configuration for readline in bash. We use "option default"
# priority to allow user override using both .text and .source.
environment.etc.inputrc.source = lib.mkOptionDefault ./inputrc;
users.defaultUserShell = lib.mkDefault pkgs.bashInteractive;
environment.pathsToLink = lib.optionals cfg.completion.enable [
"/etc/bash_completion.d"
"/share/bash-completion"
];
environment.shells = [
"/run/current-system/sw/bin/bash"
"/run/current-system/sw/bin/sh"
"${pkgs.bashInteractive}/bin/bash"
"${pkgs.bashInteractive}/bin/sh"
];
};
} }

View File

@@ -1,4 +1,9 @@
{ config, lib, ... }: {
config,
lib,
pkgs,
...
}:
let let
cfg = config.programs.fuse; cfg = config.programs.fuse;
@@ -7,6 +12,10 @@ in
meta.maintainers = with lib.maintainers; [ ]; meta.maintainers = with lib.maintainers; [ ];
options.programs.fuse = { options.programs.fuse = {
enable = lib.mkEnableOption "fuse" // {
default = true;
};
mountMax = lib.mkOption { mountMax = lib.mkOption {
# In the C code it's an "int" (i.e. signed and at least 16 bit), but # In the C code it's an "int" (i.e. signed and at least 16 bit), but
# negative numbers obviously make no sense: # negative numbers obviously make no sense:
@@ -27,10 +36,30 @@ in
}; };
}; };
config = { config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.fuse
pkgs.fuse3
];
security.wrappers =
let
mkSetuidRoot = source: {
setuid = true;
owner = "root";
group = "root";
inherit source;
};
in
{
fusermount = mkSetuidRoot "${lib.getBin pkgs.fuse}/bin/fusermount";
fusermount3 = mkSetuidRoot "${lib.getBin pkgs.fuse3}/bin/fusermount3";
};
environment.etc."fuse.conf".text = '' environment.etc."fuse.conf".text = ''
${lib.optionalString (!cfg.userAllowOther) "#"}user_allow_other ${lib.optionalString (!cfg.userAllowOther) "#"}user_allow_other
mount_max = ${builtins.toString cfg.mountMax} mount_max = ${builtins.toString cfg.mountMax}
''; '';
}; };
} }

View File

@@ -335,6 +335,8 @@ in
} }
); );
environment.corePackages = [ cfg.package ];
# SSH configuration. Slight duplication of the sshd_config # SSH configuration. Slight duplication of the sshd_config
# generation in the sshd service. # generation in the sshd service.
environment.etc."ssh/ssh_config".text = '' environment.etc."ssh/ssh_config".text = ''

View File

@@ -266,8 +266,6 @@ in
in in
{ {
# These are mount related wrappers that require the +s permission. # These are mount related wrappers that require the +s permission.
fusermount = mkSetuidRoot "${lib.getBin pkgs.fuse}/bin/fusermount";
fusermount3 = mkSetuidRoot "${lib.getBin pkgs.fuse3}/bin/fusermount3";
mount = mkSetuidRoot "${lib.getBin pkgs.util-linux}/bin/mount"; mount = mkSetuidRoot "${lib.getBin pkgs.util-linux}/bin/mount";
umount = mkSetuidRoot "${lib.getBin pkgs.util-linux}/bin/umount"; umount = mkSetuidRoot "${lib.getBin pkgs.util-linux}/bin/umount";
}; };

View File

@@ -317,7 +317,7 @@ in
source ${config.system.build.earlyMountScript} source ${config.system.build.earlyMountScript}
''; '';
systemd.user = { systemd.user = lib.mkIf config.system.activatable {
services.nixos-activation = { services.nixos-activation = {
description = "Run user-specific NixOS activation"; description = "Run user-specific NixOS activation";
script = config.system.userActivationScripts.script; script = config.system.userActivationScripts.script;

View File

@@ -414,7 +414,9 @@ in
ln -s ${initrdPath} $out/initrd ln -s ${initrdPath} $out/initrd
ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out ${optionalString (config.boot.initrd.secrets != { }) ''
ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
''}
ln -s ${config.hardware.firmware}/lib/firmware $out/firmware ln -s ${config.hardware.firmware}/lib/firmware $out/firmware
''; '';

View File

@@ -1,7 +1,22 @@
{ pkgs, lib, ... }:
{ {
config = lib.mkIf (lib.meta.availableOn pkgs.stdenv.hostPlatform pkgs.kexec-tools) { config,
pkgs,
lib,
...
}:
let
cfg = config.boot.kexec;
in
{
options.boot.kexec = {
enable = lib.mkEnableOption "kexec" // {
default = lib.meta.availableOn pkgs.stdenv.hostPlatform pkgs.kexec-tools;
defaultText = lib.literalExpression ''lib.meta.availableOn pkgs.stdenv.hostPlatform pkgs.kexec-tools'';
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ pkgs.kexec-tools ]; environment.systemPackages = [ pkgs.kexec-tools ];
systemd.services.prepare-kexec = { systemd.services.prepare-kexec = {

View File

@@ -461,13 +461,7 @@ in
# Add the mount helpers to the system path so that `mount' can find them. # Add the mount helpers to the system path so that `mount' can find them.
system.fsPackages = [ pkgs.dosfstools ]; system.fsPackages = [ pkgs.dosfstools ];
environment.systemPackages = environment.systemPackages = config.system.fsPackages;
with pkgs;
[
fuse3
fuse
]
++ config.system.fsPackages;
environment.etc.fstab.text = environment.etc.fstab.text =
let let

View File

@@ -1767,17 +1767,19 @@ in
text = cfg.hostName + "\n"; text = cfg.hostName + "\n";
}; };
environment.systemPackages = [ environment.corePackages = lib.mkOptionDefault (
pkgs.host [
pkgs.hostname-debian pkgs.host
pkgs.iproute2 pkgs.hostname-debian
pkgs.iputils pkgs.iproute2
] pkgs.iputils
++ optionals config.networking.wireless.enable [ ]
pkgs.wirelesstools # FIXME: obsolete? ++ optionals config.networking.wireless.enable [
pkgs.iw pkgs.wirelesstools # FIXME: obsolete?
] pkgs.iw
++ bridgeStp; ]
++ bridgeStp
);
# Wake-on-LAN configuration is shared by the scripted and networkd backends. # Wake-on-LAN configuration is shared by the scripted and networkd backends.
systemd.network.links = pipe interfaces [ systemd.network.links = pipe interfaces [