diff options
32 files changed, 1376 insertions, 96 deletions
@@ -172,7 +172,7 @@ export NIX_PATH=darwin=$HOME/.nix-defexpr/darwin:darwin-config=$HOME/.nixpkgs/da cp ~/.nix-defexpr/darwin/modules/examples/simple.nix ~/.nixpkgs/darwin-configuration.nix # you can also use this to rebootstrap nix-darwin in case -# darwin-rebuild is to old to activate the system. +# darwin-rebuild is too old to activate the system. $(nix-build '<darwin>' -A system --no-out-link)/sw/bin/darwin-rebuild build $(nix-build '<darwin>' -A system --no-out-link)/sw/bin/darwin-rebuild switch diff --git a/doc/known-files/5d23e6d7015756c6f300f8cd558ec4d9234ca61deefd4f2478e91a49760b0747 b/doc/known-files/5d23e6d7015756c6f300f8cd558ec4d9234ca61deefd4f2478e91a49760b0747 new file mode 100644 index 0000000..55a2da1 --- /dev/null +++ b/doc/known-files/5d23e6d7015756c6f300f8cd558ec4d9234ca61deefd4f2478e91a49760b0747 @@ -0,0 +1,9 @@ +# Generated by https://github.com/DeterminateSystems/nix-installer. +# See `/nix/nix-installer --version` for the version details. + +build-users-group = nixbld +experimental-features = nix-command flakes repl-flake +bash-prompt-prefix = (nix:$name)\040 +max-jobs = auto +extra-nix-path = nixpkgs=flake:nixpkgs +upgrade-nix-store-path-url = https://install.determinate.systems/nix-upgrade/stable/universal diff --git a/doc/known-files/d07015be6875f134976fce84c6c7a77b512079c1c5f9594dfa65c70b7968b65f b/doc/known-files/d07015be6875f134976fce84c6c7a77b512079c1c5f9594dfa65c70b7968b65f new file mode 100644 index 0000000..7a676da --- /dev/null +++ b/doc/known-files/d07015be6875f134976fce84c6c7a77b512079c1c5f9594dfa65c70b7968b65f @@ -0,0 +1,7 @@ + +# Set up Nix only on SSH connections +# See: https://github.com/DeterminateSystems/nix-installer/pull/714 +if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ] && [ -n "${SSH_CONNECTION}" ] && [ "${SHLVL}" -eq 1 ]; then + . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' +fi +# End Nix diff --git a/doc/manual/default.nix b/doc/manual/default.nix index 5a0072a..abe126b 100644 --- a/doc/manual/default.nix +++ b/doc/manual/default.nix @@ -71,7 +71,6 @@ in rec { mkdir -p $dst cp $styles/style.css $dst - cp $styles/overrides.css $dst cp -r ${pkgs.documentation-highlighter} $dst/highlightjs substitute ${./manual.md} manual.md \ @@ -86,7 +85,6 @@ in rec { --revision ${lib.escapeShellArg revision} \ --generator "nixos-render-docs ${lib.version}" \ --stylesheet style.css \ - --stylesheet overrides.css \ --stylesheet highlightjs/mono-blue.css \ --script ./highlightjs/highlight.pack.js \ --script ./highlightjs/loader.js \ diff --git a/modules/meta.nix b/modules/meta.nix index 0adc3fb..f076161 100644 --- a/modules/meta.nix +++ b/modules/meta.nix @@ -34,7 +34,7 @@ in type = listOfMaintainers; internal = true; default = []; - example = [ lib.maintainers.all ]; + example = [ lib.maintainers.lnl7 ]; description = lib.mdDoc '' List of maintainers of each module. This option should be defined at most once per module. diff --git a/modules/module-list.nix b/modules/module-list.nix index 9e43d6c..ab7f0de 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -7,6 +7,7 @@ ./security/pam.nix ./security/pki ./security/sandbox + ./security/sudo.nix ./system ./system/base.nix ./system/checks.nix @@ -34,8 +35,10 @@ ./system/etc.nix ./system/keyboard.nix ./system/launchd.nix + ./system/nvram.nix ./system/patches.nix ./system/shells.nix + ./system/startup.nix ./system/version.nix ./time ./networking @@ -54,6 +57,7 @@ ./services/dnsmasq.nix ./services/emacs.nix ./services/eternal-terminal.nix + ./services/github-runner ./services/gitlab-runner.nix ./services/hercules-ci-agent ./services/ipfs.nix @@ -67,6 +71,7 @@ ./services/netbird.nix ./services/nix-daemon.nix ./services/nix-gc + ./services/nix-optimise ./services/ofborg ./services/postgresql ./services/privoxy @@ -78,10 +83,12 @@ ./services/synapse-bt.nix ./services/synergy ./services/tailscale.nix + ./services/trezord.nix ./services/wg-quick.nix ./services/yabai ./services/nextdns ./programs/bash + ./programs/direnv.nix ./programs/fish.nix ./programs/gnupg.nix ./programs/man.nix diff --git a/modules/nix/default.nix b/modules/nix/default.nix index ae7eb91..ef5ce6c 100644 --- a/modules/nix/default.nix +++ b/modules/nix/default.nix @@ -62,13 +62,17 @@ let if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then '' echo "Ignoring validation for cross-compilation" '' - else '' + else + let + showCommand = if isNixAtLeast "2.20pre" then "config show" else "show-config"; + in + '' echo "Validating generated nix.conf" ln -s $out ./nix.conf set -e set +o pipefail NIX_CONF_DIR=$PWD \ - ${cfg.package}/bin/nix show-config ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \ + ${cfg.package}/bin/nix ${showCommand} ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \ ${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \ |& sed -e 's/^warning:/error:/' \ | (! grep '${if cfg.checkConfig then "^error:" else "^error: unknown setting"}') @@ -672,7 +676,8 @@ in "ff08c12813680da98c4240328f828647b67a65ba7aa89c022bd8072cba862cf1" # official Nix installer as of 2.4 "f3e03d851c240c1aa7daccd144ee929f0f5971982424c868c434eb6030e961d4" # DeterminateSystems Nix installer 0.10.0 "c6080216f2a170611e339c3f46e4e1d61aaf0d8b417ad93ade8d647da1382c11" # DeterminateSystems Nix installer 0.14.0 - "97f4135d262ca22d65c9554aad795c10a4491fa61b67d9c2430f4d82bbfec9a2" # DeterminateSystems Nix installer 0.15.1+ + "97f4135d262ca22d65c9554aad795c10a4491fa61b67d9c2430f4d82bbfec9a2" # DeterminateSystems Nix installer 0.15.1 + "5d23e6d7015756c6f300f8cd558ec4d9234ca61deefd4f2478e91a49760b0747" # DeterminateSystems Nix installer 0.16.0+ ]; environment.etc."nix/registry.json".text = builtins.toJSON { diff --git a/modules/nix/linux-builder.nix b/modules/nix/linux-builder.nix index d487800..ecaf686 100644 --- a/modules/nix/linux-builder.nix +++ b/modules/nix/linux-builder.nix @@ -60,27 +60,95 @@ in ''; }; + mandatoryFeatures = mkOption { + type = types.listOf types.str; + default = []; + defaultText = literalExpression ''[]''; + example = literalExpression ''[ "big-parallel" ]''; + description = lib.mdDoc '' + A list of features mandatory for the Linux builder. The builder will + be ignored for derivations that don't require all features in + this list. All mandatory features are automatically included in + {var}`supportedFeatures`. + + This sets the corresponding `nix.buildMachines.*.mandatoryFeatures` option. + ''; + }; + maxJobs = mkOption { type = types.ints.positive; default = 1; example = 4; description = lib.mdDoc '' - This option specifies the maximum number of jobs to run on the Linux builder at once. + The number of concurrent jobs the Linux builder machine supports. The + build machine will enforce its own limits, but this allows hydra + to schedule better since there is no work-stealing between build + machines. This sets the corresponding `nix.buildMachines.*.maxJobs` option. ''; }; + protocol = mkOption { + type = types.str; + default = "ssh-ng"; + defaultText = literalExpression ''"ssh-ng"''; + example = literalExpression ''"ssh"''; + description = lib.mdDoc '' + The protocol used for communicating with the build machine. Use + `ssh-ng` if your remote builder and your local Nix version support that + improved protocol. + + Use `null` when trying to change the special localhost builder without a + protocol which is for example used by hydra. + ''; + }; + + speedFactor = mkOption { + type = types.ints.positive; + default = 1; + defaultText = literalExpression ''1''; + description = lib.mdDoc '' + The relative speed of the Linux builder. This is an arbitrary integer + that indicates the speed of this builder, relative to other + builders. Higher is faster. + + This sets the corresponding `nix.buildMachines.*.speedFactor` option. + ''; + }; + supportedFeatures = mkOption { type = types.listOf types.str; default = [ "kvm" "benchmark" "big-parallel" ]; + defaultText = literalExpression ''[ "kvm" "benchmark" "big-parallel" ]''; + example = literalExpression ''[ "kvm" "big-parallel" ]''; description = lib.mdDoc '' - This option specifies the list of features supported by the Linux builder. + A list of features supported by the Linux builder. The builder will + be ignored for derivations that require features not in this + list. This sets the corresponding `nix.buildMachines.*.supportedFeatures` option. ''; }; + systems = mkOption { + type = types.listOf types.str; + default = [ "${stdenv.hostPlatform.uname.processor}-linux" ]; + defaultText = literalExpression ''[ "''${stdenv.hostPlatform.uname.processor}-linux" ]''; + example = literalExpression '' + [ + "x86_64-linux" + "aarch64-linux" + ] + ''; + description = lib.mdDoc '' + This option specifies system types the build machine can execute derivations on. + + This sets the corresponding `nix.buildMachines.*.systems` option. + ''; + }; + + workingDirectory = mkOption { type = types.str; default = "/var/lib/darwin-builder"; @@ -139,9 +207,8 @@ in hostName = "linux-builder"; sshUser = "builder"; sshKey = "/etc/nix/builder_ed25519"; - system = "${stdenv.hostPlatform.uname.processor}-linux"; publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUpCV2N4Yi9CbGFxdDFhdU90RStGOFFVV3JVb3RpQzVxQkorVXVFV2RWQ2Igcm9vdEBuaXhvcwo="; - inherit (cfg) maxJobs supportedFeatures; + inherit (cfg) mandatoryFeatures maxJobs protocol speedFactor supportedFeatures systems; }]; nix.settings.builders-use-substitutes = true; diff --git a/modules/programs/direnv.nix b/modules/programs/direnv.nix new file mode 100644 index 0000000..648b3f9 --- /dev/null +++ b/modules/programs/direnv.nix @@ -0,0 +1,136 @@ +{ + lib, + config, + pkgs, + ... +}: let + cfg = config.programs.direnv; +in { + meta.maintainers = [ + lib.maintainers.mattpolzin or "mattpolzin" + ]; + options.programs.direnv = { + + enable = lib.mkEnableOption (lib.mdDoc '' + direnv integration. Takes care of both installation and + setting up the sourcing of the shell. Additionally enables nix-direnv + integration. + ''); + + package = lib.mkPackageOptionMD pkgs "direnv" {}; + + direnvrcExtra = lib.mkOption { + type = lib.types.lines; + default = ""; + example = '' + export FOO="foo" + echo "loaded direnv!" + ''; + description = lib.mdDoc '' + Extra lines to append to the sourced direnvrc + ''; + }; + + silent = lib.mkEnableOption (lib.mdDoc '' + the hiding of direnv logging + ''); + + loadInNixShell = + lib.mkEnableOption (lib.mdDoc '' + loading direnv in `nix-shell` `nix shell` or `nix develop` + '') + // { + default = true; + }; + + nix-direnv = { + enable = + (lib.mkEnableOption (lib.mdDoc '' + a faster, persistent implementation of use_nix and use_flake, to replace the built-in one + '')) + // { + default = true; + }; + + package = lib.mkPackageOptionMD pkgs "nix-direnv" {}; + }; + }; + + config = lib.mkIf cfg.enable { + + programs = { + zsh.interactiveShellInit = '' + if ${lib.boolToString cfg.loadInNixShell} || printenv PATH | grep -vqc '/nix/store'; then + eval "$(${lib.getExe cfg.package} hook zsh)" + fi + ''; + + #$NIX_GCROOT for "nix develop" https://github.com/NixOS/nix/blob/6db66ebfc55769edd0c6bc70fcbd76246d4d26e0/src/nix/develop.cc#L530 + #$IN_NIX_SHELL for "nix-shell" + bash.interactiveShellInit = '' + if ${lib.boolToString cfg.loadInNixShell} || [ -z "$IN_NIX_SHELL$NIX_GCROOT$(printenv PATH | grep '/nix/store')" ] ; then + eval "$(${lib.getExe cfg.package} hook bash)" + fi + ''; + + fish.interactiveShellInit = '' + if ${lib.boolToString cfg.loadInNixShell}; + or printenv PATH | grep -vqc '/nix/store'; + ${lib.getExe cfg.package} hook fish | source + end + ''; + }; + + environment = { + systemPackages = + if cfg.loadInNixShell then [cfg.package] + else [ + #direnv has a fish library which sources direnv for some reason + (cfg.package.overrideAttrs (old: { + installPhase = + (old.installPhase or "") + + '' + rm -rf $out/share/fish + ''; + })) + ]; + + variables = { + DIRENV_CONFIG = "/etc/direnv"; + DIRENV_LOG_FORMAT = lib.mkIf cfg.silent ""; + }; + + etc = { + "direnv/direnvrc".text = '' + ${lib.optionalString cfg.nix-direnv.enable '' + #Load nix-direnv + source ${cfg.nix-direnv.package}/share/nix-direnv/direnvrc + ''} + + #Load direnvrcExtra + ${cfg.direnvrcExtra} + + #Load user-configuration if present (~/.direnvrc or ~/.config/direnv/direnvrc) + direnv_config_dir_home="''${DIRENV_CONFIG_HOME:-''${XDG_CONFIG_HOME:-$HOME/.config}/direnv}" + if [[ -f $direnv_config_dir_home/direnvrc ]]; then + source "$direnv_config_dir_home/direnvrc" >&2 + elif [[ -f $HOME/.direnvrc ]]; then + source "$HOME/.direnvrc" >&2 + fi + + unset direnv_config_dir_home + ''; + + "direnv/lib/zz-user.sh".text = '' + direnv_config_dir_home="''${DIRENV_CONFIG_HOME:-''${XDG_CONFIG_HOME:-$HOME/.config}/direnv}" + + for lib in "$direnv_config_dir_home/lib/"*.sh; do + source "$lib" + done + + unset direnv_config_dir_home + ''; + }; + }; + }; +} diff --git a/modules/programs/zsh/default.nix b/modules/programs/zsh/default.nix index 615589a..cce645c 100644 --- a/modules/programs/zsh/default.nix +++ b/modules/programs/zsh/default.nix @@ -219,5 +219,9 @@ in "2af1b563e389d11b76a651b446e858116d7a20370d9120a7e9f78991f3e5f336" # DeterminateSystems installer ]; + environment.etc."zshenv".knownSha256Hashes = [ + "d07015be6875f134976fce84c6c7a77b512079c1c5f9594dfa65c70b7968b65f" # DeterminateSystems installer + ]; + }; } diff --git a/modules/security/sudo.nix b/modules/security/sudo.nix new file mode 100644 index 0000000..c0d9597 --- /dev/null +++ b/modules/security/sudo.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.security.sudo; +in +{ + meta.maintainers = [ + lib.maintainers.samasaur or "samasaur" + ]; + + options = { + security.sudo.extraConfig = mkOption { + type = types.nullOr types.lines; + default = null; + description = mdDoc '' + Extra configuration text appended to {file}`sudoers`. + ''; + }; + }; + + config = { + environment.etc = { + "sudoers.d/10-nix-darwin-extra-config" = mkIf (cfg.extraConfig != null) { + text = cfg.extraConfig; + }; + }; + }; +} diff --git a/modules/services/github-runner/default.nix b/modules/services/github-runner/default.nix new file mode 100644 index 0000000..e860eca --- /dev/null +++ b/modules/services/github-runner/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./options.nix + ./service.nix + ]; +} diff --git a/modules/services/github-runner/options.nix b/modules/services/github-runner/options.nix new file mode 100644 index 0000000..300ca32 --- /dev/null +++ b/modules/services/github-runner/options.nix @@ -0,0 +1,269 @@ +{ lib +, pkgs +, ... +}: + +with lib; +{ + options.services.github-runners = mkOption { + description = mdDoc '' + Multiple GitHub Runners. + + If `user` and `group` are set to `null`, the module will configure nix-darwin to + manage the `_github-runner` user and group. Note that multiple runner + configurations share the same user/group, which means they can access + resources from other runners. Make each runner use its own user and group if + this is not what you want. In this case, you will have to do the user and + group creation yourself. If only `user` is set, while `group` is set to + `null`, the service will infer the primary group of the `user`. + + For each GitHub runner, the system activation script creates the following + directories: + + * `/var/lib/github-runners/<name>`: + State directory to store the runner registration credentials + * `/var/log/github-runners/<name>`: + The launchd service writes the stdout and stderr streams to this + directory. + * `/var/run/github-runners/<name>`: + Working directory for workflow files. The runner only uses this + directory if `workDir` is `null` (see the `workDir` option for details). + ''; + example = { + runner1 = { + enable = true; + url = "https://github.com/owner/repo"; + name = "runner1"; + tokenFile = "/secrets/token1"; + }; + + runner2 = { + enable = true; + url = "https://github.com/owner/repo"; + name = "runner2"; + tokenFile = "/secrets/token2"; + }; + }; + default = { }; + type = types.attrsOf (types.submodule ({ name, ... }: { + options = { + enable = mkOption { + default = false; + example = true; + description = mdDoc '' + Whether to enable GitHub Actions runner. + + Note: GitHub recommends using self-hosted runners with private repositories only. Learn more here: + [About self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners). + ''; + type = types.bool; + }; + + url = mkOption { + type = types.str; + description = mdDoc '' + Repository to add the runner to. + + Changing this option triggers a new runner registration. + + IMPORTANT: If your token is org-wide (not per repository), you need to + provide a github org link, not a single repository, so do it like this + `https://github.com/nixos`, not like this + `https://github.com/nixos/nixpkgs`. + Otherwise, you are going to get a `404 NotFound` + from `POST https://api.github.com/actions/runner-registration` + in the configure script. + ''; + example = "https://github.com/nixos/nixpkgs"; + }; + + tokenFile = mkOption { + type = types.path; + description = mdDoc '' + The full path to a file which contains either + + * a fine-grained personal access token (PAT), + * a classic PAT + * or a runner registration token + + Changing this option or the `tokenFile`’s content triggers a new runner registration. + + We suggest using the fine-grained PATs. A runner registration token is valid + only for 1 hour after creation, so the next time the runner configuration changes + this will give you hard-to-debug HTTP 404 errors in the configure step. + + The file should contain exactly one line with the token without any newline. + (Use `echo -n '…token…' > …token file…` to make sure no newlines sneak in.) + + If the file contains a PAT, the service creates a new registration token + on startup as needed. + If a registration token is given, it can be used to re-register a runner of the same + name but is time-limited as noted above. + + For fine-grained PATs: + + Give it "Read and Write access to organization/repository self hosted runners", + depending on whether it is organization wide or per-repository. You might have to + experiment a little, fine-grained PATs are a `beta` Github feature and still subject + to change; nonetheless they are the best option at the moment. + + For classic PATs: + + Make sure the PAT has a scope of `admin:org` for organization-wide registrations + or a scope of `repo` for a single repository. + + For runner registration tokens: + + Nothing special needs to be done, but updating will break after one hour, + so these are not recommended. + ''; + example = "/run/secrets/github-runner/nixos.token"; + }; + + name = mkOption { + type = types.nullOr types.str; + description = mdDoc '' + Name of the runner to configure. If null, defaults to the hostname. + + Changing this option triggers a new runner registration. + ''; + example = "nixos"; + default = name; + }; + + runnerGroup = mkOption { + type = types.nullOr types.str; + description = mdDoc '' + Name of the runner group to add this runner to (defaults to the default runner group). + + Changing this option triggers a new runner registration. + ''; + default = null; + }; + + extraLabels = mkOption { + type = types.listOf types.str; + description = mdDoc '' + Extra labels in addition to the default (unless disabled through the `noDefaultLabels` option). + + Changing this option triggers a new runner registration. + ''; + example = literalExpression ''[ "nixos" ]''; + default = [ ]; + }; + + noDefaultLabels = mkOption { + type = types.bool; + description = mdDoc '' + Disables adding the default labels. Also see the `extraLabels` option. + + Changing this option triggers a new runner registration. + ''; + default = false; + }; + + replace = mkOption { + type = types.bool; + description = mdDoc '' + Replace any existing runner with the same name. + + Without this flag, registering a new runner with the same name fails. + ''; + default = false; + }; + + extraPackages = mkOption { + type = types.listOf types.package; + description = mdDoc '' + Extra packages to add to `PATH` of the service to make them available to workflows. + ''; + default = [ ]; + }; + + extraEnvironment = mkOption { + type = types.attrs; + description = mdDoc '' + Extra environment variables to set for the runner, as an attrset. + ''; + example = { + GIT_CONFIG = "/path/to/git/config"; + }; + default = { }; + }; + + serviceOverrides = mkOption { + type = types.attrs; + description = mdDoc '' + Modify the service. Can be used to, e.g., adjust the sandboxing options. + ''; + default = { }; + }; + + package = mkPackageOptionMD pkgs "github-runner" { }; + + ephemeral = mkOption { + type = types.bool; + description = mdDoc '' + If enabled, causes the following behavior: + + - Passes the `--ephemeral` flag to the runner configuration script + - De-registers and stops the runner with GitHub after it has processed one job + - Restarts the service after its successful exit + - On start, wipes the state directory and configures a new runner + + You should only enable this option if `tokenFile` points to a file which contains a + personal access token (PAT). If you're using the option with a registration token, restarting the + service will fail as soon as the registration token expired. + + Changing this option triggers a new runner registration. + ''; + default = false; + }; + + user = mkOption { + type = types.nullOr types.str; + description = mdDoc '' + User under which to run the service. + + If this option and the `group` option is set to `null`, nix-darwin creates + the `github-runner` user and group. + ''; + defaultText = literalExpression "username"; + default = null; + }; + + group = mkOption { + type = types.nullOr types.str; + description = mdDoc '' + Group under which to run the service. + + If this option and the `user` option is set to `null`, nix-darwin creates + the `github-runner` user and group. + ''; + defaultText = literalExpression "groupname"; + default = null; + }; + + workDir = mkOption { + type = with types; nullOr str; + description = mdDoc '' + Working directory, available as `$GITHUB_WORKSPACE` during workflow runs + and used as a default for [repository checkouts](https://github.com/actions/checkout). + The service cleans this directory on every service start. + + Changing this option triggers a new runner registration. + ''; + default = null; + }; + + nodeRuntimes = mkOption { + type = with types; nonEmptyListOf (enum [ "node20" ]); + default = [ "node20" ]; + description = mdDoc '' + List of Node.js runtimes the runner should support. + ''; + }; + }; + })); + }; +} diff --git a/modules/services/github-runner/service.nix b/modules/services/github-runner/service.nix new file mode 100644 index 0000000..53f2cdd --- /dev/null +++ b/modules/services/github-runner/service.nix @@ -0,0 +1,181 @@ +{ config, lib, pkgs, ... }: +with lib; +let + mkSvcName = name: "github-runner-${name}"; + mkStateDir = cfg: "/var/lib/github-runners/${cfg.name}"; + mkLogDir = cfg: "/var/log/github-runners/${cfg.name}"; + mkWorkDir = cfg: if (cfg.workDir != null) then cfg.workDir else "/var/run/github-runners/${cfg.name}"; +in +{ + config.assertions = flatten ( + flip mapAttrsToList config.services.github-runners (name: cfg: map (mkIf cfg.enable) [ + { + assertion = (cfg.user == null && cfg.group == null) || (cfg.user != null); + message = "`services.github-runners.${name}`: Either set `user` and `group` to `null` to have nix-darwin manage them or set at least `user` explicitly"; + } + { + assertion = !cfg.noDefaultLabels || (cfg.extraLabels != [ ]); + message = "`services.github-runners.${name}`: The `extraLabels` option is mandatory if `noDefaultLabels` is set"; + } + ]) + ); + + config.warnings = flatten ( + flip mapAttrsToList config.services.github-runners (name: cfg: map (mkIf cfg.enable) [ + ( + mkIf (hasPrefix builtins.storeDir cfg.tokenFile) + "`services.github-runners.${name}`: `tokenFile` contains a secret but points to the world-readable Nix store." + ) + ]) + ); + + # Create the necessary directories and make the service user/group their owner + # This has to happen *after* nix-darwin user creation and *before* any launchd service gets started. + config.system.activationScripts = mkMerge (flip mapAttrsToList config.services.github-runners (name: cfg: + let + user = config.launchd.daemons.${mkSvcName name}.serviceConfig.UserName; + group = + if config.launchd.daemons.${mkSvcName name}.serviceConfig.GroupName != null + then config.launchd.daemons.${mkSvcName name}.serviceConfig.GroupName + else ""; + in + { + launchd = mkIf cfg.enable { + text = mkBefore ('' + echo >&2 "setting up GitHub Runner '${cfg.name}'..." + + ${pkgs.coreutils}/bin/mkdir -p -m 0750 ${escapeShellArg (mkStateDir cfg)} + ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkStateDir cfg)} + + ${pkgs.coreutils}/bin/mkdir -p -m 0750 ${escapeShellArg (mkLogDir cfg)} + ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkLogDir cfg)} + '' + optionalString (cfg.workDir == null) '' + ${pkgs.coreutils}/bin/mkdir -p -m 0750 ${escapeShellArg (mkWorkDir cfg)} + ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkWorkDir cfg)} + ''); + }; + })); + + config.launchd.daemons = flip mapAttrs' config.services.github-runners (name: cfg: + let + package = cfg.package.override (old: optionalAttrs (hasAttr "nodeRuntimes" old) { inherit (cfg) nodeRuntimes; }); + stateDir = mkStateDir cfg; + logDir = mkLogDir cfg; + workDir = mkWorkDir cfg; + in + nameValuePair + (mkSvcName name) + (mkIf cfg.enable { + environment = { + HOME = stateDir; + RUNNER_ROOT = stateDir; + } // cfg.extraEnvironment; + + # Minimal package set for `actions/checkout` + path = (with pkgs; [ + bash + coreutils + git + gnutar + gzip + ]) ++ [ + config.nix.package + ] ++ cfg.extraPackages; + + script = + let + configure = pkgs.writeShellApplication { + name = "configure-github-runner-${name}"; + text = '' + export RUNNER_ROOT + + args=( + --unattended + --disableupdate + --work ${escapeShellArg workDir} + --url ${escapeShellArg cfg.url} + --labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)} + ${optionalString (cfg.name != null ) "--name ${escapeShellArg cfg.name}"} + ${optionalString cfg.replace "--replace"} + ${optionalString (cfg.runnerGroup != null) "--runnergroup ${escapeShellArg cfg.runnerGroup}"} + ${optionalString cfg.ephemeral "--ephemeral"} + ${optionalString cfg.noDefaultLabels "--no-default-labels"} + ) + # If the token file contains a PAT (i.e., it starts with "ghp_" or "github_pat_"), we have to use the --pat option, + # if it is not a PAT, we assume it contains a registration token and use the --token option + token=$(<"${cfg.tokenFile}") + if [[ "$token" =~ ^ghp_* ]] || [[ "$token" =~ ^github_pat_* ]]; then + args+=(--pat "$token") + else + args+=(--token "$token") + fi + ${package}/bin/config.sh "''${args[@]}" + ''; + }; + in + '' + echo "Configuring GitHub Actions Runner" + + # Always clean the working directory + ${pkgs.findutils}/bin/find ${escapeShellArg workDir} -mindepth 1 -delete + + # Clean the $RUNNER_ROOT if we are in ephemeral mode + if ${boolToString cfg.ephemeral}; then + echo "Cleaning $RUNNER_ROOT" + ${pkgs.findutils}/bin/find "$RUNNER_ROOT" -mindepth 1 -delete + fi + + # If the `.runner` file does not exist, we assume the runner is not configured + if [[ ! -f "$RUNNER_ROOT/.runner" ]]; then + ${getExe configure} + fi + + # Start the service + ${package}/bin/Runner.Listener run --startuptype service + ''; + + serviceConfig = mkMerge [ + { + GroupName = cfg.group; + KeepAlive = { + Crashed = false; + } // mkIf cfg.ephemeral { + SuccessfulExit = true; + }; + ProcessType = "Interactive"; + RunAtLoad = true; + StandardErrorPath = "${logDir}/launchd-stderr.log"; + StandardOutPath = "${logDir}/launchd-stdout.log"; + ThrottleInterval = 30; + UserName = if (cfg.user != null) then cfg.user else "_github-runner"; + WatchPaths = [ + "/etc/resolv.conf" + "/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist" + cfg.tokenFile + ]; + WorkingDirectory = stateDir; + } + cfg.serviceOverrides + ]; + })); + + # If any GitHub runner configuration has set both `user` and `group` set to `null`, + # manage the user and group `_github-runner` through nix-darwin. + config.users = mkIf (any (cfg: cfg.enable && cfg.user == null && cfg.group == null) (attrValues config.services.github-runners)) { + users."_github-runner" = { + createHome = false; + description = "GitHub Runner service user"; + gid = config.users.groups."_github-runner".gid; + home = "/var/lib/github-runners"; + shell = "/bin/bash"; + uid = mkDefault 533; + }; + knownUsers = [ "_github-runner" ]; + + groups."_github-runner" = { + gid = mkDefault 533; + description = "GitHub Runner service user group"; + }; + knownGroups = [ "_github-runner" ]; + }; +} diff --git a/modules/services/ipfs.nix b/modules/services/ipfs.nix index 8087ba4..6cfcc49 100644 --- a/modules/services/ipfs.nix +++ b/modules/services/ipfs.nix @@ -18,7 +18,7 @@ in }; package = mkOption { - type = types.path; + type = types.package; default = pkgs.kubo; # defaultText = "pkgs.kubo"; description = lib.mdDoc '' @@ -29,7 +29,7 @@ in logFile = mkOption { type = types.nullOr types.path; default = null; - example = "/var/tmp/lorri.log"; + example = "/var/tmp/ipfs.log"; description = lib.mdDoc '' The logfile to use for the ipfs service. Alternatively {command}`sudo launchctl debug system/org.nixos.ipfs --stderr` @@ -52,9 +52,8 @@ in }; config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.kubo ]; + environment.systemPackages = [ cfg.package ]; launchd.user.agents.ipfs = { - # command = with pkgs; "${ipfs}/bin/ipfs daemon"; serviceConfig = { ProgramArguments = [ "${cfg.package}/bin/ipfs" "daemon" ] ++ optionals (cfg.enableGarbageCollection) [ "--enable-gc" ]; diff --git a/modules/services/nix-optimise/default.nix b/modules/services/nix-optimise/default.nix new file mode 100644 index 0000000..5462bae --- /dev/null +++ b/modules/services/nix-optimise/default.nix @@ -0,0 +1,73 @@ +# Based off: +# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/misc/nix-optimise.nix +# When making changes please try to keep it in sync. +{ config, lib, ... }: + + +let + inherit (lib) + mdDoc + mkIf + mkOption + mkRemovedOptionModule + optionalString + types + ; + + cfg = config.nix.optimise; +in + +{ + imports = [ + (mkRemovedOptionModule [ "nix" "optimise" "dates" ] "Use `nix.optimise.interval` instead.") + ]; + + ###### interface + + options = { + + nix.optimise = { + + automatic = mkOption { + type = types.bool; + default = false; + description = mdDoc "Automatically run the nix store optimiser at a specific time."; + }; + + # Not in NixOS module + user = mkOption { + type = types.nullOr types.str; + default = null; + description = mdDoc "User that runs the store optimisation."; + }; + + interval = mkOption { + type = types.attrs; + default = { Hour = 3; Minute = 15; }; + description = mdDoc "The time interval at which the optimiser will run."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.automatic { + + launchd.daemons.nix-optimise = { + environment.NIX_REMOTE = optionalString config.nix.useDaemon "daemon"; + serviceConfig = { + ProgramArguments = [ + "/bin/sh" "-c" + "/bin/wait4path ${config.nix.package} && exec ${config.nix.package}/bin/nix-store --optimise" + ]; + RunAtLoad = false; + StartCalendarInterval = [ cfg.interval ]; + UserName = cfg.user; + }; + }; + + }; +} diff --git a/modules/services/trezord.nix b/modules/services/trezord.nix new file mode 100644 index 0000000..97db519 --- /dev/null +++ b/modules/services/trezord.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.trezord; +in { + # Options copied from: + # https://github.com/NixOS/nixpkgs/blob/9d6e454b857fb472fa35fc8b098fa5ac307a0d7d/nixos/modules/services/hardware/trezord.nix#L16 + options = { + services.trezord = { + enable = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Enable Trezor bridge daemon, for use with Trezor hardware wallets. + ''; + }; + + emulator.enable = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Enable Trezor emulator support. + ''; + }; + + emulator.port = mkOption { + type = types.port; + default = 21324; + description = lib.mdDoc '' + Listening port for the Trezor emulator. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + launchd.user.agents.trezord = { + serviceConfig = { + ProgramArguments = [ "${pkgs.trezord}/bin/trezord-go" ] + ++ optionals cfg.emulator.enable [ "-e" (builtins.toString cfg.emulator.port) ]; + KeepAlive = true; + RunAtLoad = true; + }; + }; + }; +} diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index 67d69be..68e01b5 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -69,6 +69,7 @@ in ${cfg.activationScripts.networking.text} ${cfg.activationScripts.keyboard.text} ${cfg.activationScripts.fonts.text} + ${cfg.activationScripts.nvram.text} ${cfg.activationScripts.postActivation.text} diff --git a/modules/system/checks.nix b/modules/system/checks.nix index 27188e3..5989dc4 100644 --- a/modules/system/checks.nix +++ b/modules/system/checks.nix @@ -191,6 +191,17 @@ let exit 2 fi ''; + + nixStoreOptimiser = '' + if test -O /nix/store; then + echo "[1;31merror: A single-user install can't run optimiser as root, aborting activation[0m" >&2 + echo "Configure the optimiser to run as the current user:" >&2 + echo >&2 + echo " nix.optimiser.user = \"$USER\";" >&2 + echo >&2 + exit 2 + fi + ''; in { @@ -230,6 +241,7 @@ in (mkIf (!config.nix.useDaemon) singleUser) nixStore (mkIf (config.nix.gc.automatic && config.nix.gc.user == null) nixGarbageCollector) + (mkIf (config.nix.optimise.automatic && config.nix.optimise.user == null) nixStoreOptimiser) (mkIf cfg.verifyNixChannels nixChannels) nixInstaller (mkIf cfg.verifyNixPath nixPath) diff --git a/modules/system/defaults-write.nix b/modules/system/defaults-write.nix index 2e56d74..7e1fc44 100644 --- a/modules/system/defaults-write.nix +++ b/modules/system/defaults-write.nix @@ -5,18 +5,8 @@ with lib; let cfg = config.system.defaults; - boolValue = x: if x then "YES" else "NO"; - - writeValue = value: - if isBool value then "-bool ${boolValue value}" else - if isInt value then "-int ${toString value}" else - if isFloat value then "-float ${strings.floatToString value}" else - if isString value then "-string '${value}'" else - if isList value then "-array ${concatStringsSep " " (map (v: writeValue v)value)}" else - throw "invalid value type"; - writeDefault = domain: key: value: - "defaults write ${domain} '${key}' ${writeValue value}"; + "defaults write ${domain} '${key}' $'${strings.escape [ "'" ] (generators.toPlist { } value)}'"; defaultsToList = domain: attrs: mapAttrsToList (writeDefault domain) (filterAttrs (n: v: v != null) attrs); diff --git a/modules/system/defaults/NSGlobalDomain.nix b/modules/system/defaults/NSGlobalDomain.nix index 4f08d4a..03a7da2 100644 --- a/modules/system/defaults/NSGlobalDomain.nix +++ b/modules/system/defaults/NSGlobalDomain.nix @@ -225,6 +225,14 @@ in { ''; }; + system.defaults.NSGlobalDomain.NSWindowShouldDragOnGesture = mkOption { + type = types.nullOr types.bool; + default = null; + description = lib.mdDoc '' + Whether to enable moving window by holding anywhere on it like on Linux. The default is false. + ''; + }; + system.defaults.NSGlobalDomain.InitialKeyRepeat = mkOption { type = types.nullOr types.int; default = null; diff --git a/modules/system/defaults/dock.nix b/modules/system/defaults/dock.nix index 7fda0da..9d54f75 100644 --- a/modules/system/defaults/dock.nix +++ b/modules/system/defaults/dock.nix @@ -123,6 +123,19 @@ in { ''; }; + system.defaults.dock.persistent-apps = mkOption { + type = types.nullOr (types.listOf (types.either types.path types.str)); + default = null; + example = [ "/Applications/Safari.app" "/System/Applications/Utilities/Terminal.app" ]; + description = lib.mdDoc '' + Persistent applications in the dock. + ''; + apply = value: + if !(isList value) + then value + else map (app: { tile-data = { file-data = { _CFURLString = app; _CFURLStringType = 0; }; }; }) value; + }; + system.defaults.dock.show-process-indicators = mkOption { type = types.nullOr types.bool; default = null; diff --git a/modules/system/nvram.nix b/modules/system/nvram.nix new file mode 100644 index 0000000..efc9c99 --- /dev/null +++ b/modules/system/nvram.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.system; + + mkNvramVariables = + lib.attrsets.mapAttrsToList + (name: value: "nvram ${lib.escapeShellArg name}=${lib.escapeShellArg value}") + cfg.nvram.variables; +in + +{ + meta.maintainers = [ + lib.maintainers.samasaur or "samasaur" + ]; + + options = { + system.nvram.variables = lib.mkOption { + type = with lib.types; attrsOf str; + default = {}; + internal = true; + example = { + "StartupMute" = "%01"; + }; + description = lib.mdDoc '' + Non-volatile RAM variables to set. Removing a key-value pair from this + list will **not** return the variable to its previous value, but will + no longer set its value on system configuration activations. + ''; + }; + }; + + config = { + system.activationScripts.nvram.text = '' + echo "setting nvram variables..." >&2 + + ${builtins.concatStringsSep "\n" mkNvramVariables} + ''; + }; +} diff --git a/modules/system/startup.nix b/modules/system/startup.nix new file mode 100644 index 0000000..ecbef46 --- /dev/null +++ b/modules/system/startup.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.system.startup; +in + +{ + meta.maintainers = [ + lib.maintainers.samasaur or "samasaur" + ]; + + options = { + system.startup.chime = lib.mkOption { + type = with lib.types; nullOr bool; + default = null; + example = false; + description = lib.mdDoc '' + Whether to enable the startup chime. + + By default, this option does not affect your system configuration in any way. + However, this means that after it has been set once, unsetting it will not + return to the old behavior. It will allow the setting to be controlled in + System Settings, though. + ''; + }; + }; + + config = { + system.nvram.variables."StartupMute" = lib.mkIf (cfg.chime != null) (if cfg.chime then "%00" else "%01"); + }; +} diff --git a/modules/users/default.nix b/modules/users/default.nix index 9648274..25cc97e 100644 --- a/modules/users/default.nix +++ b/modules/users/default.nix @@ -100,7 +100,7 @@ in ${optionalString cfg.forceRecreate '' g=$(dscl . -read '/Groups/${v.name}' PrimaryGroupID 2> /dev/null) || true g=''${g#PrimaryGroupID: } - if [ "$g" -eq ${toString v.gid} ]; then + if [[ "$g" -eq ${toString v.gid} ]]; then echo "deleting group ${v.name}..." >&2 dscl . -delete '/Groups/${v.name}' 2> /dev/null else @@ -149,7 +149,7 @@ in ${optionalString cfg.forceRecreate '' u=$(dscl . -read '/Users/${v.name}' UniqueID 2> /dev/null) || true u=''${u#UniqueID: } - if [ "$u" -eq ${toString v.uid} ]; then + if [[ "$u" -eq ${toString v.uid} ]]; then echo "deleting user ${v.name}..." >&2 dscl . -delete '/Users/${v.name}' 2> /dev/null else diff --git a/pkgs/darwin-uninstaller/default.nix b/pkgs/darwin-uninstaller/default.nix index 94c0749..3eb2c24 100644 --- a/pkgs/darwin-uninstaller/default.nix +++ b/pkgs/darwin-uninstaller/default.nix @@ -7,7 +7,7 @@ let ./configuration.nix { nixpkgs.source = pkgs.path; - nixpkgs.hostPlatform = pkgs.system; + nixpkgs.hostPlatform = pkgs.stdenv.hostPlatform.system; system.includeUninstaller = false; } ]; diff --git a/release.nix b/release.nix index ffdfc38..98a58e7 100644 --- a/release.nix +++ b/release.nix @@ -119,12 +119,14 @@ let tests.services-activate-system = makeTest ./tests/services-activate-system.nix; tests.services-activate-system-changed-label-prefix = makeTest ./tests/services-activate-system-changed-label-prefix.nix; tests.services-buildkite-agent = makeTest ./tests/services-buildkite-agent.nix; + tests.services-github-runners = makeTest ./tests/services-github-runners.nix; tests.services-lorri = makeTest ./tests/services-lorri.nix; tests.services-nix-daemon = makeTest ./tests/services-nix-daemon.nix; tests.sockets-nix-daemon = makeTest ./tests/sockets-nix-daemon.nix; tests.services-dnsmasq = makeTest ./tests/services-dnsmasq.nix; tests.services-eternal-terminal = makeTest ./tests/services-eternal-terminal.nix; tests.services-nix-gc = makeTest ./tests/services-nix-gc.nix; + tests.services-nix-optimise = makeTest ./tests/services-nix-optimise.nix; tests.services-nextdns = makeTest ./tests/services-nextdns.nix; tests.services-ofborg = makeTest ./tests/services-ofborg.nix; tests.services-offlineimap = makeTest ./tests/services-offlineimap.nix; diff --git a/tests/fixtures/system-defaults-write/activate-user.txt b/tests/fixtures/system-defaults-write/activate-user.txt new file mode 100644 index 0000000..1021ab3 --- /dev/null +++ b/tests/fixtures/system-defaults-write/activate-user.txt @@ -0,0 +1,338 @@ +defaults write -g 'AppleEnableMouseSwipeNavigateWithScrolls' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'AppleEnableSwipeNavigateWithScrolls' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'AppleFontSmoothing' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>1</integer> +</plist>' +defaults write -g 'AppleICUForce24HourTime' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'AppleKeyboardUIMode' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>3</integer> +</plist>' +defaults write -g 'ApplePressAndHoldEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'AppleScrollerPagingBehavior' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'AppleShowAllExtensions' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'AppleShowAllFiles' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'AppleShowScrollBars' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>Always</string> +</plist>' +defaults write -g 'AppleWindowTabbingMode' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>always</string> +</plist>' +defaults write -g 'InitialKeyRepeat' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>10</integer> +</plist>' +defaults write -g 'KeyRepeat' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>1</integer> +</plist>' +defaults write -g 'NSAutomaticCapitalizationEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSAutomaticDashSubstitutionEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSAutomaticPeriodSubstitutionEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSAutomaticQuoteSubstitutionEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSAutomaticSpellingCorrectionEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSAutomaticWindowAnimationsEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSDisableAutomaticTermination' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'NSDocumentSaveNewDocumentsToCloud' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSNavPanelExpandedStateForSaveMode' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'NSNavPanelExpandedStateForSaveMode2' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'NSScrollAnimationEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'NSTableViewDefaultSizeMode' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>2</integer> +</plist>' +defaults write -g 'NSTextShowsControlCharacters' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'NSUseAnimatedFocusRing' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write -g 'NSWindowResizeTime' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<real>0.010000</real> +</plist>' +defaults write -g 'NSWindowShouldDragOnGesture' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'PMPrintingExpandedStateForPrint' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'PMPrintingExpandedStateForPrint2' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'com.apple.keyboard.fnState' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'com.apple.mouse.tapBehavior' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>1</integer> +</plist>' +defaults write -g 'com.apple.springing.delay' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<real>0.000000</real> +</plist>' +defaults write -g 'com.apple.springing.enabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'com.apple.swipescrolldirection' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'com.apple.trackpad.enableSecondaryClick' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write -g 'com.apple.trackpad.trackpadCornerClickBehavior' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>1</integer> +</plist>' + +defaults write .GlobalPreferences 'com.apple.sound.beep.sound' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>/System/Library/Sounds/Funk.aiff</string> +</plist>' + +defaults write com.apple.menuextra.clock 'Show24Hour' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write com.apple.menuextra.clock 'ShowDate' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>2</integer> +</plist>' +defaults write com.apple.menuextra.clock 'ShowDayOfWeek' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.dock 'appswitcher-all-displays' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<false/> +</plist>' +defaults write com.apple.dock 'autohide-delay' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<real>0.240000</real> +</plist>' +defaults write com.apple.dock 'orientation' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>left</string> +</plist>' +defaults write com.apple.dock 'persistent-apps' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<array> + <dict> + <key>tile-data</key> + <dict> + <key>file-data</key> + <dict> + <key>_CFURLString</key> + <string>MyApp.app</string> + <key>_CFURLStringType</key> + <integer>0</integer> + </dict> + </dict> + </dict> + <dict> + <key>tile-data</key> + <dict> + <key>file-data</key> + <dict> + <key>_CFURLString</key> + <string>Cool.app</string> + <key>_CFURLStringType</key> + <integer>0</integer> + </dict> + </dict> + </dict> +</array> +</plist>' + + + +defaults write com.apple.screencapture 'location' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>/tmp</string> +</plist>' +defaults write com.apple.screensaver 'askForPassword' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.screensaver 'askForPasswordDelay' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>5</integer> +</plist>' + + + +defaults write com.apple.universalaccess 'closeViewScrollWheelToggle' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.universalaccess 'closeViewZoomFollowsFocus' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.universalaccess 'mouseDriverCursorSize' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<real>1.500000</real> +</plist>' +defaults write com.apple.universalaccess 'reduceMotion' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.universalaccess 'reduceTransparency' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.ActivityMonitor 'IconType' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>3</integer> +</plist>' +defaults write com.apple.ActivityMonitor 'OpenMainWindow' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' +defaults write com.apple.ActivityMonitor 'ShowCategory' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>103</integer> +</plist>' +defaults write com.apple.ActivityMonitor 'SortColumn' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>CPUUsage</string> +</plist>' +defaults write com.apple.ActivityMonitor 'SortDirection' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>0</integer> +</plist>' +defaults write NSGlobalDomain 'TISRomanSwitchState' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<integer>1</integer> +</plist>' +defaults write com.apple.Safari 'com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<true/> +</plist>' diff --git a/tests/fixtures/system-defaults-write/activate.txt b/tests/fixtures/system-defaults-write/activate.txt new file mode 100644 index 0000000..b22bc6d --- /dev/null +++ b/tests/fixtures/system-defaults-write/activate.txt @@ -0,0 +1,10 @@ +defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server 'NetBIOSName' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>IMAC-000000</string> +</plist>' +defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server 'ServerDescription' $'<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<string>Darwin\\\\U2019\'s iMac</string> +</plist>' diff --git a/tests/services-github-runners.nix b/tests/services-github-runners.nix new file mode 100644 index 0000000..5578750 --- /dev/null +++ b/tests/services-github-runners.nix @@ -0,0 +1,20 @@ +{ config, pkgs, ... }: +{ + services.github-runners."a-runner" = { + enable = true; + url = "https://github.com/nixos/nixpkgs"; + tokenFile = "/secret/path/to/a/github/token"; + # We need an overridable derivation but cannot use the actual github-runner package + # since it still relies on Node.js 16 which is marked as insecure. + package = pkgs.hello; + }; + + test = '' + echo >&2 "checking github-runner service in /Library/LaunchDaemons" + grep "org.nixos.github-runner-a-runner" ${config.out}/Library/LaunchDaemons/org.nixos.github-runner-a-runner.plist + grep "<string>_github-runner</string>" ${config.out}/Library/LaunchDaemons/org.nixos.github-runner-a-runner.plist + + echo >&2 "checking for user in /activate" + grep "GitHub Runner service user" ${config.out}/activate + ''; +} diff --git a/tests/services-nix-optimise.nix b/tests/services-nix-optimise.nix new file mode 100644 index 0000000..b0ecf18 --- /dev/null +++ b/tests/services-nix-optimise.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: + +let + nix = pkgs.runCommand "nix-2.2" {} "mkdir -p $out"; +in + +{ + nix.optimise.automatic = true; + nix.optimise.user = "nixuser"; + nix.package = nix; + + test = '' + echo checking nix-optimise service in /Library/LaunchDaemons >&2 + grep "<string>org.nixos.nix-optimise</string>" \ + ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist + grep "<string>/bin/wait4path ${nix} && exec ${nix}/bin/nix-store --optimise</string>" \ + ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist + grep "<key>UserName</key>" ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist + grep "<string>nixuser</string>" ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist + (! grep "<key>KeepAlive</key>" ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist) + + echo checking nix-optimise validation >&2 + (! grep "nix.optimise.user = " ${config.out}/activate-user) + ''; +} diff --git a/tests/system-defaults-write.nix b/tests/system-defaults-write.nix index e3f69fe..9840298 100644 --- a/tests/system-defaults-write.nix +++ b/tests/system-defaults-write.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { system.defaults.NSGlobalDomain.AppleShowAllFiles = true; @@ -27,6 +27,7 @@ system.defaults.NSGlobalDomain.NSUseAnimatedFocusRing = false; system.defaults.NSGlobalDomain.NSScrollAnimationEnabled = true; system.defaults.NSGlobalDomain.NSWindowResizeTime = 0.01; + system.defaults.NSGlobalDomain.NSWindowShouldDragOnGesture = true; system.defaults.NSGlobalDomain.InitialKeyRepeat = 10; system.defaults.NSGlobalDomain.KeyRepeat = 1; system.defaults.NSGlobalDomain.PMPrintingExpandedStateForPrint = true; @@ -45,11 +46,12 @@ system.defaults.dock.appswitcher-all-displays = false; system.defaults.dock.autohide-delay = 0.24; system.defaults.dock.orientation = "left"; + system.defaults.dock.persistent-apps = ["MyApp.app" "Cool.app"]; system.defaults.screencapture.location = "/tmp"; system.defaults.screensaver.askForPassword = true; system.defaults.screensaver.askForPasswordDelay = 5; system.defaults.smb.NetBIOSName = "IMAC-000000"; - system.defaults.smb.ServerDescription = ''Darwin\\\\U2019s iMac''; + system.defaults.smb.ServerDescription = ''Darwin\\\\U2019's iMac''; system.defaults.universalaccess.mouseDriverCursorSize = 1.5; system.defaults.universalaccess.reduceMotion = true; system.defaults.universalaccess.reduceTransparency = true; @@ -67,69 +69,19 @@ true; }; }; - test = '' - echo >&2 "checking defaults write in /activate" - grep "defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server 'NetBIOSName' -string 'IMAC-000000'" ${config.out}/activate - grep "defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server 'ServerDescription' -string 'Darwin.*s iMac'" ${config.out}/activate - - echo >&2 "checking defaults write in /activate-user" - grep "defaults write -g 'AppleShowAllFiles' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'AppleEnableMouseSwipeNavigateWithScrolls' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'AppleEnableSwipeNavigateWithScrolls' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'AppleFontSmoothing' -int 1" ${config.out}/activate-user - grep "defaults write -g 'AppleICUForce24HourTime' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'AppleKeyboardUIMode' -int 3" ${config.out}/activate-user - grep "defaults write -g 'ApplePressAndHoldEnabled' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'AppleShowAllExtensions' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'AppleShowScrollBars' -string 'Always'" ${config.out}/activate-user - grep "defaults write -g 'AppleScrollerPagingBehavior' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'NSAutomaticCapitalizationEnabled' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSAutomaticDashSubstitutionEnabled' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSAutomaticPeriodSubstitutionEnabled' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSAutomaticQuoteSubstitutionEnabled' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSAutomaticSpellingCorrectionEnabled' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSAutomaticWindowAnimationsEnabled' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSDisableAutomaticTermination' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'NSDocumentSaveNewDocumentsToCloud' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'AppleWindowTabbingMode' -string 'always'" ${config.out}/activate-user - grep "defaults write -g 'NSNavPanelExpandedStateForSaveMode' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'NSNavPanelExpandedStateForSaveMode2' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'NSTableViewDefaultSizeMode' -int 2" ${config.out}/activate-user - grep "defaults write -g 'NSTextShowsControlCharacters' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'NSUseAnimatedFocusRing' -bool NO" ${config.out}/activate-user - grep "defaults write -g 'NSScrollAnimationEnabled' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'NSWindowResizeTime' -float 0.01" ${config.out}/activate-user - grep "defaults write -g 'InitialKeyRepeat' -int 10" ${config.out}/activate-user - grep "defaults write -g 'KeyRepeat' -int 1" ${config.out}/activate-user - grep "defaults write -g 'PMPrintingExpandedStateForPrint' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'PMPrintingExpandedStateForPrint2' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'com.apple.keyboard.fnState' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'com.apple.mouse.tapBehavior' -int 1" ${config.out}/activate-user - grep "defaults write -g 'com.apple.trackpad.enableSecondaryClick' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'com.apple.trackpad.trackpadCornerClickBehavior' -int 1" ${config.out}/activate-user - grep "defaults write -g 'com.apple.springing.enabled' -bool YES" ${config.out}/activate-user - grep "defaults write -g 'com.apple.springing.delay' -float 0.0" ${config.out}/activate-user - grep "defaults write -g 'com.apple.swipescrolldirection' -bool YES" ${config.out}/activate-user - grep "defaults write .GlobalPreferences 'com.apple.sound.beep.sound' -string '/System/Library/Sounds/Funk.aiff'" ${config.out}/activate-user - grep "defaults write com.apple.menuextra.clock 'Show24Hour' -bool NO" ${config.out}/activate-user - grep "defaults write com.apple.menuextra.clock 'ShowDayOfWeek' -bool YES" ${config.out}/activate-user - grep "defaults write com.apple.menuextra.clock 'ShowDate' -int 2" ${config.out}/activate-user - grep "defaults write com.apple.dock 'autohide-delay' -float 0.24" ${config.out}/activate-user - grep "defaults write com.apple.dock 'appswitcher-all-displays' -bool NO" ${config.out}/activate-user - grep "defaults write com.apple.dock 'orientation' -string 'left'" ${config.out}/activate-user - grep "defaults write com.apple.screencapture 'location' -string '/tmp'" ${config.out}/activate-user - grep "defaults write com.apple.screensaver 'askForPassword' -bool YES" ${config.out}/activate-user - grep "defaults write com.apple.screensaver 'askForPasswordDelay' -int 5" ${config.out}/activate-user - grep "defaults write com.apple.universalaccess 'mouseDriverCursorSize' -float 1.5" ${config.out}/activate-user - grep "defaults write com.apple.universalaccess 'reduceMotion' -bool YES" ${config.out}/activate-user - grep "defaults write com.apple.universalaccess 'reduceTransparency' -bool YES" ${config.out}/activate-user - grep "defaults write com.apple.universalaccess 'closeViewScrollWheelToggle' -bool YES" ${config.out}/activate-user - grep "defaults write com.apple.universalaccess 'closeViewZoomFollowsFocus' -bool YES" ${config.out}/activate-user - grep "defaults write com.apple.ActivityMonitor 'ShowCategory' -int 103" ${config.out}/activate-user - grep "defaults write com.apple.ActivityMonitor 'IconType' -int 3" ${config.out}/activate-user - grep "defaults write com.apple.ActivityMonitor 'SortColumn' -string 'CPUUsage'" ${config.out}/activate-user - grep "defaults write com.apple.ActivityMonitor 'SortDirection' -int 0" ${config.out}/activate-user - grep "defaults write com.apple.ActivityMonitor 'OpenMainWindow' -bool YES" ${config.out}/activate-user - grep "defaults write NSGlobalDomain 'TISRomanSwitchState' -int 1" ${config.out}/activate-user - ''; + test = lib.strings.concatMapStringsSep "\n" (x: '' + echo >&2 "checking defaults write in /${x}" + ${pkgs.python3}/bin/python3 <<EOL +import sys +from pathlib import Path +fixture = '${./fixtures/system-defaults-write}/${x}.txt' +out = '${config.out}/${x}' +if Path(fixture).read_text() not in Path(out).read_text(): + print("Did not find content from %s in %s" % (fixture, out), file=sys.stderr) + sys.exit(1) +EOL + '') [ + "activate" + "activate-user" + ]; } |
