0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-13 21:50:33 +03:00

Merge master into staging-next

This commit is contained in:
github-actions[bot] 2024-09-06 00:13:20 +00:00 committed by GitHub
commit 25ef10109d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
111 changed files with 1422 additions and 1244 deletions

View file

@ -34,9 +34,6 @@
Users that want to keep PulseAudio will want to set `services.pipewire.enable = false;` and `hardware.pulseaudio.enable = true;`.
There is currently no plan to fully deprecate and remove PulseAudio, however, PipeWire should generally be preferred for new installs.
- Support for mounting filesystems from block devices protected with [dm-verity](https://docs.kernel.org/admin-guide/device-mapper/verity.html)
was added through the `boot.initrd.systemd.dmVerity` option.
## New Modules {#sec-release-24.11-new-modules}
- [TaskChampion Sync-Server](https://github.com/GothenburgBitFactory/taskchampion-sync-server), a [Taskwariror 3](https://taskwarrior.org/docs/upgrade-3/) sync server, replacing Taskwarrior 2's sync server named [`taskserver`](https://github.com/GothenburgBitFactory/taskserver).
@ -412,6 +409,8 @@
- The `openlens` package got removed, suggested replacment `lens-desktop`
- The NixOS installation media no longer support the ReiserFS or JFS file systems by default.
## Other Notable Changes {#sec-release-24.11-notable-changes}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->

View file

@ -1622,7 +1622,6 @@
./system/boot/stage-2.nix
./system/boot/systemd.nix
./system/boot/systemd/coredump.nix
./system/boot/systemd/dm-verity.nix
./system/boot/systemd/initrd-secrets.nix
./system/boot/systemd/initrd.nix
./system/boot/systemd/journald.nix

View file

@ -50,7 +50,7 @@
# Include support for various filesystems and tools to create / manipulate them.
boot.supportedFilesystems =
[ "btrfs" "cifs" "f2fs" "jfs" "ntfs" "reiserfs" "vfat" "xfs" ] ++
[ "btrfs" "cifs" "f2fs" "ntfs" "vfat" "xfs" ] ++
lib.optional (lib.meta.availableOn pkgs.stdenv.hostPlatform config.boot.zfs.package) "zfs";
# Configure host id for ZFS to work

View file

@ -1,5 +1,4 @@
{ config, lib, pkgs, options, ... }:
with lib;
let
@ -8,11 +7,11 @@ let
user = if cfg.useRoot then "root" else "acme";
# Used to calculate timer accuracy for coalescing
numCerts = length (builtins.attrNames cfg.certs);
numCerts = lib.length (builtins.attrNames cfg.certs);
_24hSecs = 60 * 60 * 24;
# Used to make unique paths for each cert/account config set
mkHash = with builtins; val: substring 0 20 (hashString "sha256" val);
mkHash = with builtins; val: lib.substring 0 20 (hashString "sha256" val);
mkAccountHash = acmeServer: data: mkHash "${toString acmeServer} ${data.keyType} ${data.email}";
accountDirRoot = "/var/lib/acme/.lego/accounts/";
@ -29,7 +28,7 @@ let
else
[{ fst = head workingBaseList; snd = head needAssignmentList;}] ++
_rrCycler origBaseList (if (tail workingBaseList == []) then origBaseList else tail workingBaseList) (tail needAssignmentList);
attrsToList = mapAttrsToList (attrname: attrval: {name = attrname; value = attrval;});
attrsToList = lib.mapAttrsToList (attrname: attrval: {name = attrname; value = attrval;});
# for an AttrSet `funcsAttrs` having functions as values, apply single arguments from
# `argsList` to them in a round-robin manner.
# Returns an attribute set with the applied functions as values.
@ -57,7 +56,7 @@ let
commonServiceConfig = {
Type = "oneshot";
User = user;
Group = mkDefault "acme";
Group = lib.mkDefault "acme";
UMask = "0022";
StateDirectoryMode = "750";
ProtectSystem = "strict";
@ -136,8 +135,8 @@ let
userMigrationService = let
script = with builtins; ''
chown -R ${user} .lego/accounts
'' + (concatStringsSep "\n" (mapAttrsToList (cert: data: ''
for fixpath in ${escapeShellArg cert} .lego/${escapeShellArg cert}; do
'' + (lib.concatStringsSep "\n" (lib.mapAttrsToList (cert: data: ''
for fixpath in ${lib.escapeShellArg cert} .lego/${lib.escapeShellArg cert}; do
if [ -d "$fixpath" ]; then
chmod -R u=rwX,g=rX,o= "$fixpath"
chown -R ${user}:${data.group} "$fixpath"
@ -166,7 +165,7 @@ let
# ensure all required lock files exist, but none more
script = ''
GLOBIGNORE="${concatStringsSep ":" concurrencyLockfiles}"
GLOBIGNORE="${lib.concatStringsSep ":" concurrencyLockfiles}"
rm -f *
unset GLOBIGNORE
@ -186,7 +185,7 @@ let
useDns = data.dnsProvider != null;
useDnsOrS3 = useDns || data.s3Bucket != null;
destPath = "/var/lib/acme/${cert}";
selfsignedDeps = optionals (cfg.preliminarySelfsigned) [ "acme-selfsigned-${cert}.service" ];
selfsignedDeps = lib.optionals (cfg.preliminarySelfsigned) [ "acme-selfsigned-${cert}.service" ];
# Minica and lego have a "feature" which replaces * with _. We need
# to make this substitution to reference the output files from both programs.
@ -196,7 +195,7 @@ let
# FIXME when mkChangedOptionModule supports submodules, change to that.
# This is a workaround
extraDomains = data.extraDomainNames ++ (
optionals
lib.optionals
(data.extraDomains != "_mkMergedOptionModule")
(builtins.attrNames data.extraDomains)
);
@ -204,22 +203,22 @@ let
# Create hashes for cert data directories based on configuration
# Flags are separated to avoid collisions
hashData = with builtins; ''
${concatStringsSep " " data.extraLegoFlags} -
${concatStringsSep " " data.extraLegoRunFlags} -
${concatStringsSep " " data.extraLegoRenewFlags} -
${lib.concatStringsSep " " data.extraLegoFlags} -
${lib.concatStringsSep " " data.extraLegoRunFlags} -
${lib.concatStringsSep " " data.extraLegoRenewFlags} -
${toString acmeServer} ${toString data.dnsProvider}
${toString data.ocspMustStaple} ${data.keyType}
'';
certDir = mkHash hashData;
# TODO remove domainHash usage entirely. Waiting on go-acme/lego#1532
domainHash = mkHash "${concatStringsSep " " extraDomains} ${data.domain}";
domainHash = mkHash "${lib.concatStringsSep " " extraDomains} ${data.domain}";
accountHash = (mkAccountHash acmeServer data);
accountDir = accountDirRoot + accountHash;
protocolOpts = if useDns then (
[ "--dns" data.dnsProvider ]
++ optionals (!data.dnsPropagationCheck) [ "--dns.disable-cp" ]
++ optionals (data.dnsResolver != null) [ "--dns.resolvers" data.dnsResolver ]
++ lib.optionals (!data.dnsPropagationCheck) [ "--dns.disable-cp" ]
++ lib.optionals (data.dnsResolver != null) [ "--dns.resolvers" data.dnsResolver ]
) else if data.s3Bucket != null then [ "--http" "--http.s3-bucket" data.s3Bucket ]
else if data.listenHTTP != null then [ "--http" "--http.port" data.listenHTTP ]
else [ "--http" "--http.webroot" data.webroot ];
@ -231,22 +230,22 @@ let
"--email" data.email
"--key-type" data.keyType
] ++ protocolOpts
++ optionals (acmeServer != null) [ "--server" acmeServer ]
++ concatMap (name: [ "-d" name ]) extraDomains
++ lib.optionals (acmeServer != null) [ "--server" acmeServer ]
++ lib.concatMap (name: [ "-d" name ]) extraDomains
++ data.extraLegoFlags;
# Although --must-staple is common to both modes, it is not declared as a
# mode-agnostic argument in lego and thus must come after the mode.
runOpts = escapeShellArgs (
runOpts = lib.escapeShellArgs (
commonOpts
++ [ "run" ]
++ optionals data.ocspMustStaple [ "--must-staple" ]
++ lib.optionals data.ocspMustStaple [ "--must-staple" ]
++ data.extraLegoRunFlags
);
renewOpts = escapeShellArgs (
renewOpts = lib.escapeShellArgs (
commonOpts
++ [ "renew" "--no-random-sleep" ]
++ optionals data.ocspMustStaple [ "--must-staple" ]
++ lib.optionals data.ocspMustStaple [ "--must-staple" ]
++ data.extraLegoRenewFlags
);
@ -286,8 +285,8 @@ let
selfsignService = lockfileName: {
description = "Generate self-signed certificate for ${cert}";
after = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ] ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
requires = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ] ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
after = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ] ++ lib.optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
requires = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ] ++ lib.optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
path = with pkgs; [ minica ];
@ -315,7 +314,7 @@ let
minica \
--ca-key ca/key.pem \
--ca-cert ca/cert.pem \
--domains ${escapeShellArg (builtins.concatStringsSep "," ([ data.domain ] ++ extraDomains))}
--domains ${lib.escapeShellArg (builtins.concatStringsSep "," ([ data.domain ] ++ extraDomains))}
# Create files to match directory layout for real certificates
cd '${keyName}'
@ -334,11 +333,11 @@ let
renewService = lockfileName: {
description = "Renew ACME certificate for ${cert}";
after = [ "network.target" "network-online.target" "acme-fixperms.service" "nss-lookup.target" ] ++ selfsignedDeps ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
wants = [ "network-online.target" "acme-fixperms.service" ] ++ selfsignedDeps ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
after = [ "network.target" "network-online.target" "acme-fixperms.service" "nss-lookup.target" ] ++ selfsignedDeps ++ lib.optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
wants = [ "network-online.target" "acme-fixperms.service" ] ++ selfsignedDeps ++ lib.optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service";
# https://github.com/NixOS/nixpkgs/pull/81371#issuecomment-605526099
wantedBy = optionals (!config.boot.isContainer) [ "multi-user.target" ];
wantedBy = lib.optionals (!config.boot.isContainer) [ "multi-user.target" ];
path = with pkgs; [ lego coreutils diffutils openssl ];
@ -368,33 +367,33 @@ let
"/var/lib/acme/.lego/${cert}/${certDir}:/tmp/certificates"
];
EnvironmentFile = mkIf useDnsOrS3 data.environmentFile;
EnvironmentFile = lib.mkIf useDnsOrS3 data.environmentFile;
Environment = mkIf useDnsOrS3
(mapAttrsToList (k: v: ''"${k}=%d/${k}"'') data.credentialFiles);
Environment = lib.mkIf useDnsOrS3
(lib.mapAttrsToList (k: v: ''"${k}=%d/${k}"'') data.credentialFiles);
LoadCredential = mkIf useDnsOrS3
(mapAttrsToList (k: v: "${k}:${v}") data.credentialFiles);
LoadCredential = lib.mkIf useDnsOrS3
(lib.mapAttrsToList (k: v: "${k}:${v}") data.credentialFiles);
# Run as root (Prefixed with +)
ExecStartPost = "+" + (pkgs.writeShellScript "acme-postrun" ''
cd /var/lib/acme/${escapeShellArg cert}
cd /var/lib/acme/${lib.escapeShellArg cert}
if [ -e renewed ]; then
rm renewed
${data.postRun}
${optionalString (data.reloadServices != [])
"systemctl --no-block try-reload-or-restart ${escapeShellArgs data.reloadServices}"
${lib.optionalString (data.reloadServices != [])
"systemctl --no-block try-reload-or-restart ${lib.escapeShellArgs data.reloadServices}"
}
fi
'');
} // optionalAttrs (data.listenHTTP != null && toInt (last (splitString ":" data.listenHTTP)) < 1024) {
} // lib.optionalAttrs (data.listenHTTP != null && lib.toInt (lib.last (lib.splitString ":" data.listenHTTP)) < 1024) {
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
};
# Working directory will be /tmp
script = (if (lockfileName == null) then lib.id else wrapInFlock "${lockdir}${lockfileName}") ''
${optionalString data.enableDebugLogs "set -x"}
${lib.optionalString data.enableDebugLogs "set -x"}
set -euo pipefail
# This reimplements the expiration date check, but without querying
@ -425,7 +424,7 @@ let
[[ $expiration_days -gt ${toString data.validMinDays} ]]
}
${optionalString (data.webroot != null) ''
${lib.optionalString (data.webroot != null) ''
# Ensure the webroot exists. Fixing group is required in case configuration was changed between runs.
# Lego will fail if the webroot does not exist at all.
(
@ -461,7 +460,7 @@ let
# Produce a nice error for those doing their first nixos-rebuild with these certs
echo Failed to fetch certificates. \
This may mean your DNS records are set up incorrectly. \
${optionalString (cfg.preliminarySelfsigned) "Selfsigned certs are in place and dependant services will still start."}
${lib.optionalString (cfg.preliminarySelfsigned) "Selfsigned certs are in place and dependant services will still start."}
# Exit 10 so that users can potentially amend SuccessExitStatus to ignore this error.
# High number to avoid Systemd reserved codes.
exit 10
@ -490,7 +489,7 @@ let
};
};
certConfigs = mapAttrs certToConfig cfg.certs;
certConfigs = lib.mapAttrs certToConfig cfg.certs;
# These options can be specified within
# security.acme.defaults or security.acme.certs.<name>
@ -504,22 +503,22 @@ let
# stay constant. Though notably it wouldn't matter much, because to get
# the option information, a submodule with name `<name>` is evaluated
# without any definitions.
defaultText = if isDefaults then default else literalExpression "config.security.acme.defaults.${name}";
defaultText = if isDefaults then default else lib.literalExpression "config.security.acme.defaults.${name}";
};
in {
imports = [
(mkRenamedOptionModule [ "credentialsFile" ] [ "environmentFile" ])
(lib.mkRenamedOptionModule [ "credentialsFile" ] [ "environmentFile" ])
];
options = {
validMinDays = mkOption {
type = types.int;
validMinDays = lib.mkOption {
type = lib.types.int;
inherit (defaultAndText "validMinDays" 30) default defaultText;
description = "Minimum remaining validity before renewal in days.";
};
renewInterval = mkOption {
type = types.str;
renewInterval = lib.mkOption {
type = lib.types.str;
inherit (defaultAndText "renewInterval" "daily") default defaultText;
description = ''
Systemd calendar expression when to check for renewal. See
@ -527,12 +526,12 @@ let
'';
};
enableDebugLogs = mkEnableOption "debug logging for this certificate" // {
enableDebugLogs = lib.mkEnableOption "debug logging for this certificate" // {
inherit (defaultAndText "enableDebugLogs" true) default defaultText;
};
webroot = mkOption {
type = types.nullOr types.str;
webroot = lib.mkOption {
type = lib.types.nullOr lib.types.str;
inherit (defaultAndText "webroot" null) default defaultText;
example = "/var/lib/acme/acme-challenge";
description = ''
@ -544,8 +543,8 @@ let
'';
};
server = mkOption {
type = types.nullOr types.str;
server = lib.mkOption {
type = lib.types.nullOr lib.types.str;
inherit (defaultAndText "server" "https://acme-v02.api.letsencrypt.org/directory") default defaultText;
example = "https://acme-staging-v02.api.letsencrypt.org/directory";
description = ''
@ -556,8 +555,8 @@ let
'';
};
email = mkOption {
type = types.nullOr types.str;
email = lib.mkOption {
type = lib.types.nullOr lib.types.str;
inherit (defaultAndText "email" null) default defaultText;
description = ''
Email address for account creation and correspondence from the CA.
@ -566,14 +565,14 @@ let
'';
};
group = mkOption {
type = types.str;
group = lib.mkOption {
type = lib.types.str;
inherit (defaultAndText "group" "acme") default defaultText;
description = "Group running the ACME client.";
};
reloadServices = mkOption {
type = types.listOf types.str;
reloadServices = lib.mkOption {
type = lib.types.listOf lib.types.str;
inherit (defaultAndText "reloadServices" []) default defaultText;
description = ''
The list of systemd services to call `systemctl try-reload-or-restart`
@ -581,8 +580,8 @@ let
'';
};
postRun = mkOption {
type = types.lines;
postRun = lib.mkOption {
type = lib.types.lines;
inherit (defaultAndText "postRun" "") default defaultText;
example = "cp full.pem backup.pem";
description = ''
@ -593,8 +592,8 @@ let
'';
};
keyType = mkOption {
type = types.str;
keyType = lib.mkOption {
type = lib.types.str;
inherit (defaultAndText "keyType" "ec256") default defaultText;
description = ''
Key type to use for private keys.
@ -603,8 +602,8 @@ let
'';
};
dnsProvider = mkOption {
type = types.nullOr types.str;
dnsProvider = lib.mkOption {
type = lib.types.nullOr lib.types.str;
inherit (defaultAndText "dnsProvider" null) default defaultText;
example = "route53";
description = ''
@ -613,8 +612,8 @@ let
'';
};
dnsResolver = mkOption {
type = types.nullOr types.str;
dnsResolver = lib.mkOption {
type = lib.types.nullOr lib.types.str;
inherit (defaultAndText "dnsResolver" null) default defaultText;
example = "1.1.1.1:53";
description = ''
@ -624,8 +623,8 @@ let
'';
};
environmentFile = mkOption {
type = types.nullOr types.path;
environmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
inherit (defaultAndText "environmentFile" null) default defaultText;
description = ''
Path to an EnvironmentFile for the cert's service containing any required and
@ -636,8 +635,8 @@ let
example = "/var/src/secrets/example.org-route53-api-token";
};
credentialFiles = mkOption {
type = types.attrsOf (types.path);
credentialFiles = lib.mkOption {
type = lib.types.attrsOf (lib.types.path);
inherit (defaultAndText "credentialFiles" {}) default defaultText;
description = ''
Environment variables suffixed by "_FILE" to set for the cert's service
@ -647,15 +646,15 @@ let
This allows to securely pass credential files to lego by leveraging systemd
credentials.
'';
example = literalExpression ''
example = lib.literalExpression ''
{
"RFC2136_TSIG_SECRET_FILE" = "/run/secrets/tsig-secret-example.org";
}
'';
};
dnsPropagationCheck = mkOption {
type = types.bool;
dnsPropagationCheck = lib.mkOption {
type = lib.types.bool;
inherit (defaultAndText "dnsPropagationCheck" true) default defaultText;
description = ''
Toggles lego DNS propagation check, which is used alongside DNS-01
@ -663,8 +662,8 @@ let
'';
};
ocspMustStaple = mkOption {
type = types.bool;
ocspMustStaple = lib.mkOption {
type = lib.types.bool;
inherit (defaultAndText "ocspMustStaple" false) default defaultText;
description = ''
Turns on the OCSP Must-Staple TLS extension.
@ -675,24 +674,24 @@ let
'';
};
extraLegoFlags = mkOption {
type = types.listOf types.str;
extraLegoFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
inherit (defaultAndText "extraLegoFlags" []) default defaultText;
description = ''
Additional global flags to pass to all lego commands.
'';
};
extraLegoRenewFlags = mkOption {
type = types.listOf types.str;
extraLegoRenewFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
inherit (defaultAndText "extraLegoRenewFlags" []) default defaultText;
description = ''
Additional flags to pass to lego renew.
'';
};
extraLegoRunFlags = mkOption {
type = types.listOf types.str;
extraLegoRunFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
inherit (defaultAndText "extraLegoRunFlags" []) default defaultText;
description = ''
Additional flags to pass to lego run.
@ -704,40 +703,40 @@ let
certOpts = { name, config, ... }: {
options = {
# user option has been removed
user = mkOption {
user = lib.mkOption {
visible = false;
default = "_mkRemovedOptionModule";
};
# allowKeysForGroup option has been removed
allowKeysForGroup = mkOption {
allowKeysForGroup = lib.mkOption {
visible = false;
default = "_mkRemovedOptionModule";
};
# extraDomains was replaced with extraDomainNames
extraDomains = mkOption {
extraDomains = lib.mkOption {
visible = false;
default = "_mkMergedOptionModule";
};
directory = mkOption {
type = types.str;
directory = lib.mkOption {
type = lib.types.str;
readOnly = true;
default = "/var/lib/acme/${name}";
description = "Directory where certificate and other state is stored.";
};
domain = mkOption {
type = types.str;
domain = lib.mkOption {
type = lib.types.str;
default = name;
description = "Domain to fetch certificate for (defaults to the entry name).";
};
extraDomainNames = mkOption {
type = types.listOf types.str;
extraDomainNames = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
example = literalExpression ''
example = lib.literalExpression ''
[
"example.org"
"mydomain.org"
@ -751,8 +750,8 @@ let
# This setting must be different for each configured certificate, otherwise
# two or more renewals may fail to bind to the address. Hence, it is not in
# the inheritableOpts.
listenHTTP = mkOption {
type = types.nullOr types.str;
listenHTTP = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = ":1360";
description = ''
@ -762,8 +761,8 @@ let
'';
};
s3Bucket = mkOption {
type = types.nullOr types.str;
s3Bucket = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "acme";
description = ''
@ -771,7 +770,7 @@ let
'';
};
inheritDefaults = mkOption {
inheritDefaults = lib.mkOption {
default = true;
example = true;
description = "Whether to inherit values set in `security.acme.defaults` or not.";
@ -784,8 +783,8 @@ in {
options = {
security.acme = {
preliminarySelfsigned = mkOption {
type = types.bool;
preliminarySelfsigned = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether a preliminary self-signed certificate should be generated before
@ -797,8 +796,8 @@ in {
'';
};
acceptTerms = mkOption {
type = types.bool;
acceptTerms = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Accept the CA's terms of service. The default provider is Let's Encrypt,
@ -806,8 +805,8 @@ in {
'';
};
useRoot = mkOption {
type = types.bool;
useRoot = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to use the root user when generating certs. This is not recommended
@ -818,8 +817,8 @@ in {
'';
};
defaults = mkOption {
type = types.submodule (inheritableModule true);
defaults = lib.mkOption {
type = lib.types.submodule (inheritableModule true);
description = ''
Default values inheritable by all configured certs. You can
use this to define options shared by all your certs. These defaults
@ -828,9 +827,9 @@ in {
'';
};
certs = mkOption {
certs = lib.mkOption {
default = { };
type = with types; attrsOf (submodule [ (inheritableModule false) certOpts ]);
type = with lib.types; attrsOf (submodule [ (inheritableModule false) certOpts ]);
description = ''
Attribute set of certificates to get signed and renewed. Creates
`acme-''${cert}.{service,timer}` systemd units for
@ -838,7 +837,7 @@ in {
to those units if they rely on the certificates being present,
or trigger restarts of the service if certificates get renewed.
'';
example = literalExpression ''
example = lib.literalExpression ''
{
"example.com" = {
webroot = "/var/lib/acme/acme-challenge/";
@ -852,9 +851,9 @@ in {
}
'';
};
maxConcurrentRenewals = mkOption {
maxConcurrentRenewals = lib.mkOption {
default = 5;
type = types.int;
type = lib.types.int;
description = ''
Maximum number of concurrent certificate generation or renewal jobs. All other
jobs will queue and wait running jobs to finish. Reduces the system load of
@ -867,39 +866,39 @@ in {
};
imports = [
(mkRemovedOptionModule [ "security" "acme" "production" ] ''
(lib.mkRemovedOptionModule [ "security" "acme" "production" ] ''
Use security.acme.server to define your staging ACME server URL instead.
To use the let's encrypt staging server, use security.acme.server =
"https://acme-staging-v02.api.letsencrypt.org/directory".
'')
(mkRemovedOptionModule [ "security" "acme" "directory" ] "ACME Directory is now hardcoded to /var/lib/acme and its permissions are managed by systemd. See https://github.com/NixOS/nixpkgs/issues/53852 for more info.")
(mkRemovedOptionModule [ "security" "acme" "preDelay" ] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
(mkRemovedOptionModule [ "security" "acme" "activationDelay" ] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
(mkChangedOptionModule [ "security" "acme" "validMin" ] [ "security" "acme" "defaults" "validMinDays" ] (config: config.security.acme.validMin / (24 * 3600)))
(mkChangedOptionModule [ "security" "acme" "validMinDays" ] [ "security" "acme" "defaults" "validMinDays" ] (config: config.security.acme.validMinDays))
(mkChangedOptionModule [ "security" "acme" "renewInterval" ] [ "security" "acme" "defaults" "renewInterval" ] (config: config.security.acme.renewInterval))
(mkChangedOptionModule [ "security" "acme" "email" ] [ "security" "acme" "defaults" "email" ] (config: config.security.acme.email))
(mkChangedOptionModule [ "security" "acme" "server" ] [ "security" "acme" "defaults" "server" ] (config: config.security.acme.server))
(mkChangedOptionModule [ "security" "acme" "enableDebugLogs" ] [ "security" "acme" "defaults" "enableDebugLogs" ] (config: config.security.acme.enableDebugLogs))
(lib.mkRemovedOptionModule [ "security" "acme" "directory" ] "ACME Directory is now hardcoded to /var/lib/acme and its permissions are managed by systemd. See https://github.com/NixOS/nixpkgs/issues/53852 for more info.")
(lib.mkRemovedOptionModule [ "security" "acme" "preDelay" ] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
(lib.mkRemovedOptionModule [ "security" "acme" "activationDelay" ] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
(lib.mkChangedOptionModule [ "security" "acme" "validMin" ] [ "security" "acme" "defaults" "validMinDays" ] (config: config.security.acme.validMin / (24 * 3600)))
(lib.mkChangedOptionModule [ "security" "acme" "validMinDays" ] [ "security" "acme" "defaults" "validMinDays" ] (config: config.security.acme.validMinDays))
(lib.mkChangedOptionModule [ "security" "acme" "renewInterval" ] [ "security" "acme" "defaults" "renewInterval" ] (config: config.security.acme.renewInterval))
(lib.mkChangedOptionModule [ "security" "acme" "email" ] [ "security" "acme" "defaults" "email" ] (config: config.security.acme.email))
(lib.mkChangedOptionModule [ "security" "acme" "server" ] [ "security" "acme" "defaults" "server" ] (config: config.security.acme.server))
(lib.mkChangedOptionModule [ "security" "acme" "enableDebugLogs" ] [ "security" "acme" "defaults" "enableDebugLogs" ] (config: config.security.acme.enableDebugLogs))
];
config = mkMerge [
(mkIf (cfg.certs != { }) {
config = lib.mkMerge [
(lib.mkIf (cfg.certs != { }) {
# FIXME Most of these custom warnings and filters for security.acme.certs.* are required
# because using mkRemovedOptionModule/mkChangedOptionModule with attrsets isn't possible.
warnings = filter (w: w != "") (mapAttrsToList (cert: data: optionalString (data.extraDomains != "_mkMergedOptionModule") ''
warnings = lib.filter (w: w != "") (lib.mapAttrsToList (cert: data: lib.optionalString (data.extraDomains != "_mkMergedOptionModule") ''
The option definition `security.acme.certs.${cert}.extraDomains` has changed
to `security.acme.certs.${cert}.extraDomainNames` and is now a list of strings.
Setting a custom webroot for extra domains is not possible, instead use separate certs.
'') cfg.certs);
assertions = let
certs = attrValues cfg.certs;
certs = lib.attrValues cfg.certs;
in [
{
assertion = cfg.defaults.email != null || all (certOpts: certOpts.email != null) certs;
assertion = cfg.defaults.email != null || lib.all (certOpts: certOpts.email != null) certs;
message = ''
You must define `security.acme.certs.<name>.email` or
`security.acme.defaults.email` to register with the CA. Note that using
@ -914,7 +913,7 @@ in {
to `true`. For Let's Encrypt's ToS see https://letsencrypt.org/repository/
'';
}
] ++ (builtins.concatLists (mapAttrsToList (cert: data: [
] ++ (builtins.concatLists (lib.mapAttrsToList (cert: data: [
{
assertion = data.user == "_mkRemovedOptionModule";
message = ''
@ -936,7 +935,7 @@ in {
# referencing them as a user quite weird too. Best practice is to use
# the domain option.
{
assertion = ! hasInfix "*" cert;
assertion = ! lib.hasInfix "*" cert;
message = ''
The cert option path `security.acme.certs.${cert}.dnsProvider`
cannot contain a * character.
@ -959,7 +958,7 @@ in {
'';
})
{
assertion = all (hasSuffix "_FILE") (attrNames data.credentialFiles);
assertion = lib.all (lib.hasSuffix "_FILE") (lib.attrNames data.credentialFiles);
message = ''
Option `security.acme.certs.${cert}.credentialFiles` can only be
used for variables suffixed by "_FILE".
@ -982,27 +981,27 @@ in {
];
systemd.services = let
renewServiceFunctions = mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewService) certConfigs;
renewServiceFunctions = lib.mapAttrs' (cert: conf: lib.nameValuePair "acme-${cert}" conf.renewService) certConfigs;
renewServices = if cfg.maxConcurrentRenewals > 0
then roundRobinApplyAttrs renewServiceFunctions concurrencyLockfiles
else mapAttrs (_: f: f null) renewServiceFunctions;
selfsignServiceFunctions = mapAttrs' (cert: conf: nameValuePair "acme-selfsigned-${cert}" conf.selfsignService) certConfigs;
else lib.mapAttrs (_: f: f null) renewServiceFunctions;
selfsignServiceFunctions = lib.mapAttrs' (cert: conf: lib.nameValuePair "acme-selfsigned-${cert}" conf.selfsignService) certConfigs;
selfsignServices = if cfg.maxConcurrentRenewals > 0
then roundRobinApplyAttrs selfsignServiceFunctions concurrencyLockfiles
else mapAttrs (_: f: f null) selfsignServiceFunctions;
else lib.mapAttrs (_: f: f null) selfsignServiceFunctions;
in
{ "acme-fixperms" = userMigrationService; }
// (optionalAttrs (cfg.maxConcurrentRenewals > 0) {"acme-lockfiles" = lockfilePrepareService; })
// (lib.optionalAttrs (cfg.maxConcurrentRenewals > 0) {"acme-lockfiles" = lockfilePrepareService; })
// renewServices
// (optionalAttrs (cfg.preliminarySelfsigned) ({
// (lib.optionalAttrs (cfg.preliminarySelfsigned) ({
"acme-selfsigned-ca" = selfsignCAService;
} // selfsignServices));
systemd.timers = mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewTimer) certConfigs;
systemd.timers = lib.mapAttrs' (cert: conf: lib.nameValuePair "acme-${cert}" conf.renewTimer) certConfigs;
systemd.targets = let
# Create some targets which can be depended on to be "active" after cert renewals
finishedTargets = mapAttrs' (cert: conf: nameValuePair "acme-finished-${cert}" {
finishedTargets = lib.mapAttrs' (cert: conf: lib.nameValuePair "acme-finished-${cert}" {
wantedBy = [ "default.target" ];
requires = [ "acme-${cert}.service" ];
after = [ "acme-${cert}.service" ];
@ -1017,15 +1016,15 @@ in {
# Using a target here is fine - account creation is a one time event. Even if
# systemd clean --what=state is used to delete the account, so long as the user
# then runs one of the cert services, there won't be any issues.
accountTargets = mapAttrs' (hash: confs: let
accountTargets = lib.mapAttrs' (hash: confs: let
leader = "acme-${(builtins.head confs).cert}.service";
dependantServices = map (conf: "acme-${conf.cert}.service") (builtins.tail confs);
in nameValuePair "acme-account-${hash}" {
in lib.nameValuePair "acme-account-${hash}" {
requiredBy = dependantServices;
before = dependantServices;
requires = [ leader ];
after = [ leader ];
}) (groupBy (conf: conf.accountHash) (attrValues certConfigs));
}) (lib.groupBy (conf: conf.accountHash) (lib.attrValues certConfigs));
in finishedTargets // accountTargets;
})
];

View file

@ -137,6 +137,37 @@ in {
type = submodule { freeformType = jsonType; };
description = "IRC servers to connect to";
};
mediaProxy = {
signingKeyPath = lib.mkOption {
type = path;
default = "/var/lib/matrix-appservice-irc/media-signingkey.jwk";
description = ''
Path to the signing key file for authenticated media.
'';
};
ttlSeconds = lib.mkOption {
type = ints.positive;
default = 3600;
description = ''
Lifetime in seconds, that generated URLs stay valid.
'';
};
bindPort = lib.mkOption {
type = port;
default = 11111;
description = ''
Port that the media proxy binds to.
'';
};
publicUrl = lib.mkOption {
type = str;
example = "https://matrix.example.com/media";
description = ''
URL under which the media proxy is publicly acccessible.
'';
};
};
};
};
};
@ -144,6 +175,7 @@ in {
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.matrix-appservice-irc = {
description = "Matrix-IRC bridge";
@ -181,6 +213,9 @@ in {
sed -i "s/^hs_token:.*$/$hs_token/g" ${registrationFile}
sed -i "s/^as_token:.*$/$as_token/g" ${registrationFile}
fi
if ! [ -f "${cfg.settings.ircService.mediaProxy.signingKeyPath}"]; then
${lib.getExe pkgs.nodejs} ${pkg}/lib/generate-signing-key.js > "${cfg.settings.ircService.mediaProxy.signingKeyPath}"
fi
# Allow synapse access to the registration
if ${pkgs.getent}/bin/getent group matrix-synapse > /dev/null; then
chgrp matrix-synapse ${registrationFile}

View file

@ -188,7 +188,7 @@ or [OpenID](https://element-hq.github.io/synapse/latest/openid.html).
## Element (formerly known as Riot) Web Client {#module-services-matrix-element-web}
[Element Web](https://github.com/vector-im/riot-web/) is
[Element Web](https://github.com/element-hq/element-web) is
the reference web client for Matrix and developed by the core team at
matrix.org. Element was formerly known as Riot.im, see the
[Element introductory blog post](https://element.io/blog/welcome-to-element/)
@ -228,6 +228,6 @@ the example, this means that you should not reuse the
`myhostname.example.org` virtualHost to also serve Element,
but instead serve it on a different subdomain, like
`element.example.org` in the example. See the
[Element Important Security Notes](https://github.com/vector-im/element-web/tree/v1.10.0#important-security-notes)
[Element Important Security Notes](https://github.com/element-hq/element-web/tree/v1.10.0#important-security-notes)
for more information on this subject.
:::

View file

@ -205,11 +205,12 @@ in
boot.initrd.systemd = {
contents = {
"/etc/tmpfiles.d/resolv.conf".text =
"L /etc/resolv.conf - - - - /run/systemd/resolve/stub-resolv.conf";
"/etc/systemd/resolved.conf".text = resolvedConf;
};
tmpfiles.settings.systemd-resolved-stub."/etc/resolv.conf".L.argument =
"/run/systemd/resolve/stub-resolv.conf";
additionalUpstreamUnits = ["systemd-resolved.service"];
users.systemd-resolve = {};
groups.systemd-resolve = {};

View file

@ -1,65 +0,0 @@
{ config, lib, ... }:
let
cfg = config.boot.initrd.systemd.dmVerity;
in
{
options = {
boot.initrd.systemd.dmVerity = {
enable = lib.mkEnableOption "dm-verity" // {
description = ''
Mount verity-protected block devices in the initrd.
Enabling this option allows to use `systemd-veritysetup` and
`systemd-veritysetup-generator` in the initrd.
'';
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.enable -> config.boot.initrd.systemd.enable;
message = ''
'boot.initrd.systemd.dmVerity.enable' requires 'boot.initrd.systemd.enable' to be enabled.
'';
}
];
boot.initrd = {
availableKernelModules = [
# For documentation, see https://docs.kernel.org/admin-guide/device-mapper/dm-init.html
"dm_mod"
# For documentation, see:
# - https://docs.kernel.org/admin-guide/device-mapper/verity.html
# - https://gitlab.com/cryptsetup/cryptsetup/-/wikis/DMVerity
"dm_verity"
];
# dm-verity needs additional udev rules from LVM to work.
services.lvm.enable = true;
# The additional targets and store paths allow users to integrate verity-protected devices
# through the systemd tooling.
systemd = {
additionalUpstreamUnits = [
# https://github.com/systemd/systemd/blob/main/units/veritysetup-pre.target
"veritysetup-pre.target"
# https://github.com/systemd/systemd/blob/main/units/veritysetup.target
"veritysetup.target"
# https://github.com/systemd/systemd/blob/main/units/remote-veritysetup.target
"remote-veritysetup.target"
];
storePaths = [
# These are the two binaries mentioned in https://github.com/systemd/systemd/blob/main/src/veritysetup/meson.build; there are no others.
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-veritysetup"
"${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-veritysetup-generator"
];
};
};
};
meta.maintainers = [ lib.maintainers.msanft ];
}

View file

@ -218,7 +218,7 @@ in {
};
root = lib.mkOption {
type = lib.types.nullOr (lib.types.enum [ "fstab" "gpt-auto" ]);
type = lib.types.enum [ "fstab" "gpt-auto" ];
default = "fstab";
example = "gpt-auto";
description = ''
@ -227,9 +227,6 @@ in {
allow specifying the root file system itself this
way. Instead, the `fstab` value is used in order to interpret
the root file system specified with the `fileSystems` option.
If the root FS is mounted by other means, such as systemd generators other than
`fstab`, `gpt-auto` or a custom generator, set this to `null`.
'';
};
@ -401,9 +398,9 @@ in {
++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb"
++ lib.optional cfg.package.withEfi "efivarfs";
boot.kernelParams =
lib.optional (config.boot.initrd.systemd.root != null) "root=${config.boot.initrd.systemd.root}"
++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}"
boot.kernelParams = [
"root=${config.boot.initrd.systemd.root}"
] ++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}"
# `systemd` mounts root in initrd as read-only unless "rw" is on the kernel command line.
# For NixOS activation to succeed, we need to have root writable in initrd.
++ lib.optional (config.boot.initrd.systemd.root == "gpt-auto") "rw";

View file

@ -163,6 +163,20 @@ in
};
config = {
warnings =
let
paths = lib.filter (path:
path != null && lib.hasPrefix "/etc/tmpfiles.d/" path
) (map (path: path.target) config.boot.initrd.systemd.storePaths);
in
lib.optional (lib.length paths > 0) (lib.concatStringsSep " " [
"Files inside /etc/tmpfiles.d in the initrd need to be created with"
"boot.initrd.systemd.tmpfiles.settings."
"Creating them by hand using boot.initrd.systemd.contents or"
"boot.initrd.systemd.storePaths will lead to errors in the future."
"Found these problematic files: ${lib.concatStringsSep ", " paths}"
]);
systemd.additionalUpstreamSystemUnits = [
"systemd-tmpfiles-clean.service"
"systemd-tmpfiles-clean.timer"

View file

@ -259,7 +259,6 @@ in {
dhparams = handleTest ./dhparams.nix {};
disable-installer-tools = handleTest ./disable-installer-tools.nix {};
discourse = handleTest ./discourse.nix {};
dm-verity = runTest ./dm-verity.nix;
dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};
dnscrypt-wrapper = runTestOn ["x86_64-linux"] ./dnscrypt-wrapper;
dnsdist = import ./dnsdist.nix { inherit pkgs runTest; };
@ -571,7 +570,7 @@ in {
mate-wayland = handleTest ./mate-wayland.nix {};
matter-server = handleTest ./matter-server.nix {};
matomo = handleTest ./matomo.nix {};
matrix-appservice-irc = handleTest ./matrix/appservice-irc.nix {};
matrix-appservice-irc = runTest ./matrix/appservice-irc.nix;
matrix-conduit = handleTest ./matrix/conduit.nix {};
matrix-synapse = handleTest ./matrix/synapse.nix {};
matrix-synapse-workers = handleTest ./matrix/synapse-workers.nix {};

View file

@ -1,245 +0,0 @@
# Tests a NixOS system with a read-only root filesystem that's integrity-protected
# through DM-verity. The root filesystem is mounted read-only, and for NixOS activation
# to succeed, an overlay `tmpfs` is mounted on top of it.
# This test uses systemd-repart to create a bootable disk image, as it supplies handy
# utilities for creating verity partitions, but it can also be setup manually through
# `systemd-veritysetup`.
{ lib, pkgs, ... }:
let
imageId = "verity-root-image";
imageVersion = "1-rc1";
# Use a random, but fixed root hash placeholder to allow us specifying the "real" root hash
# after the image is first built.
roothashPlaceholder = "61fe0f0c98eff2a595dd2f63a5e481a0a25387261fa9e34c37e3a4910edf32b8";
in
{
name = "verity-root";
meta.maintainers = with lib.maintainers; [ msanft ];
nodes.machine =
{
lib,
pkgs,
config,
modulesPath,
...
}:
{
imports = [ "${modulesPath}/image/repart.nix" ];
virtualisation.directBoot.enable = false;
virtualisation.mountHostNixStore = false;
virtualisation.useEFIBoot = true;
# Disable boot loaders, as a UKI is used, which contains systemd-stub.
# TODO(raitobezarius): revisit this when #244907 lands
boot.loader.grub.enable = false;
system.image.id = imageId;
system.image.version = imageVersion;
# systemd-veritysetup-generator takes care of setting up the root filesystem.
fileSystems = lib.mkForce { };
virtualisation.fileSystems = lib.mkForce { };
# Provides 'veritysetup' to check if the verity-protected device
# has been mapped correctly.
environment.systemPackages = with pkgs; [ cryptsetup ];
boot.initrd = {
kernelModules = [ "overlay" ];
supportedFilesystems = [ "erofs" ];
systemd = {
enable = true;
dmVerity.enable = true;
root = null; # systemd-veritysetup-generator takes care of mounting /
tmpfiles.settings = {
"10-mountpoints" =
let
conf = {
mode = "0755";
user = "root";
group = "root";
};
in
{
"/run/etc/upper".d = conf;
"/run/etc/work".d = conf;
"/run/var/upper".d = conf;
"/run/var/work".d = conf;
"/run/tmp/upper".d = conf;
"/run/tmp/work".d = conf;
};
};
# We directly define the mount units here, as we need to specify dependencies very
# granularly, and systemd-fstab-generator doesn't give us that flexibility.
mounts = [
{
where = "/sysroot/etc";
what = "overlay";
type = "overlay";
options = "lowerdir=/sysroot${config.system.build.etc}/etc,upperdir=/run/etc/upper,workdir=/run/etc/work";
wantedBy = [
"initrd-fs.target"
"initrd-switch-root.target"
"default.target"
];
before = [ "initrd-fs.target" ];
after = [ "systemd-tmpfiles-setup.service" ];
unitConfig.RequiresMountsFor = "/sysroot/nix/store";
unitConfig.DefaultDependencies = false;
}
{
where = "/sysroot/var";
what = "overlay";
type = "overlay";
options = "lowerdir=/sysroot/var,upperdir=/run/var/upper,workdir=/run/var/work";
wantedBy = [
"initrd-fs.target"
"initrd-switch-root.target"
"default.target"
];
before = [ "initrd-fs.target" ];
after = [ "systemd-tmpfiles-setup.service" ];
unitConfig.RequiresMountsFor = "/sysroot/nix/store";
unitConfig.DefaultDependencies = false;
}
{
where = "/sysroot/tmp";
what = "overlay";
type = "overlay";
options = "lowerdir=/sysroot/tmp,upperdir=/run/tmp/upper,workdir=/run/tmp/work";
wantedBy = [
"initrd-fs.target"
"initrd-switch-root.target"
"default.target"
];
before = [ "initrd-fs.target" ];
after = [ "systemd-tmpfiles-setup.service" ];
unitConfig.RequiresMountsFor = "/sysroot/nix/store";
unitConfig.DefaultDependencies = false;
}
];
};
};
boot.kernelParams = [
"systemd.verity=yes"
"roothash=${roothashPlaceholder}"
];
image.repart = {
name = imageId;
# OVMF does not work with the default repart sector size of 4096
sectorSize = 512;
partitions = {
# ESP
"00-esp" = {
contents =
let
efiArch = config.nixpkgs.hostPlatform.efiArch;
in
{
"/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source = "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
"/EFI/Linux/${config.system.boot.loader.ukiFile}".source = "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
};
repartConfig = {
Type = "esp";
Format = "vfat";
# Minimize = "guess" seems to not work very well for vfat
# partitions. It's better to set a sensible default instead. The
# aarch64 kernel seems to generally be a little bigger than the
# x86_64 kernel. To stay on the safe side, leave some more slack
# for every platform other than x86_64.
SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M";
};
};
# Root Partition
"10-root" = {
storePaths = [ config.system.build.toplevel ];
repartConfig = {
Type = "root";
Format = "erofs";
Label = "root";
Verity = "data";
VerityMatchKey = "root";
Minimize = "best";
# We need to ensure that mountpoints are available.
MakeDirectories = "/bin /boot /dev /etc /home /lib /lib64 /mnt /nix /opt /proc /root /run /srv /sys /tmp /usr /var";
};
};
# Verity hashtree for the root partition
"20-root-verity" = {
repartConfig = {
Type = "root-verity";
Label = "root-verity";
Verity = "hash";
VerityMatchKey = "root";
Minimize = "best";
};
};
};
};
};
testScript =
let
# We override the build of the image by extending it with code to replace the placeholder with the real root hash.
# This way, we can build the image first and then set the root hash afterwards in a single derivation.
buildOverride = oldAttrs: {
nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.jq ];
postInstall = ''
# Replace the placeholder with the real root hash.
realRoothash=$(${pkgs.jq}/bin/jq -r "[.[] | select(.roothash != null)] | .[0].roothash" $out/repart-output.json)
sed -i "0,/${roothashPlaceholder}/ s/${roothashPlaceholder}/$realRoothash/" $out/${oldAttrs.pname}_${oldAttrs.version}.raw
'';
};
in
{ nodes, ... }:
''
import os, subprocess, tempfile
tmp_disk_image = tempfile.NamedTemporaryFile()
subprocess.run([
"${nodes.machine.virtualisation.qemu.package}/bin/qemu-img",
"create",
"-f",
"qcow2",
"-b",
"${nodes.machine.system.build.image.overrideAttrs buildOverride}/${nodes.machine.image.repart.imageFile}",
"-F",
"raw",
tmp_disk_image.name,
])
# Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
os_release = machine.succeed("cat /etc/os-release")
assert 'IMAGE_ID="${imageId}"' in os_release
assert 'IMAGE_VERSION="${imageVersion}"' in os_release
bootctl_status = machine.succeed("bootctl status")
assert "Boot Loader Specification Type #2 (.efi)" in bootctl_status
verity_status = machine.succeed("veritysetup status root")
assert "type: VERITY" in verity_status
assert "status: verified" in verity_status
commandline = machine.succeed("cat /proc/cmdline")
roothash = commandline.split("roothash=")[1].split(" ")[0]
assert roothash in verity_status
'';
}

View file

@ -1,4 +1,4 @@
import ../make-test-python.nix ({ pkgs, ... }:
{ pkgs, ... }:
let
homeserverUrl = "http://homeserver:8008";
in
@ -9,7 +9,7 @@ import ../make-test-python.nix ({ pkgs, ... }:
};
nodes = {
homeserver = { pkgs, ... }: {
homeserver = {
# We'll switch to this once the config is copied into place
specialisation.running.configuration = {
services.matrix-synapse = {
@ -46,7 +46,7 @@ import ../make-test-python.nix ({ pkgs, ... }:
};
};
ircd = { pkgs, ... }: {
ircd = {
services.ngircd = {
enable = true;
config = ''
@ -75,13 +75,16 @@ import ../make-test-python.nix ({ pkgs, ... }:
homeserver.url = homeserverUrl;
homeserver.domain = "homeserver";
ircService.servers."ircd" = {
name = "IRCd";
port = 6667;
dynamicChannels = {
enabled = true;
aliasTemplate = "#irc_$CHANNEL";
ircService = {
servers."ircd" = {
name = "IRCd";
port = 6667;
dynamicChannels = {
enabled = true;
aliasTemplate = "#irc_$CHANNEL";
};
};
mediaProxy.publicUrl = "http://localhost:11111/media";
};
};
};
@ -203,6 +206,8 @@ import ../make-test-python.nix ({ pkgs, ... }:
with subtest("start the appservice"):
appservice.wait_for_unit("matrix-appservice-irc.service")
appservice.wait_for_open_port(8009)
appservice.wait_for_file("/var/lib/matrix-appservice-irc/media-signingkey.jwk")
appservice.wait_for_open_port(11111)
with subtest("copy the registration file"):
appservice.copy_from_vm("/var/lib/matrix-appservice-irc/registration.yml")
@ -222,4 +227,4 @@ import ../make-test-python.nix ({ pkgs, ... }:
with subtest("ensure messages can be exchanged"):
client.succeed("do_test ${homeserverUrl} >&2")
'';
})
}