Merge staging-next into staging

Changed files
+1538 -375
nixos
pkgs
applications
editors
video
olive-editor
by-name
as
astyle
bl
blender
ch
chhoto-url
chroma
gh
gi
gickup
gp
gpupad
in
inputplumber
li
libdwarf
ma
maa-assistant-arknights
me
mergiraf
ni
nixos-render-docs
src
nixos_render_docs
ol
olympus-unwrapped
op
opengamepadui
openimageio
pc
pl
playwright-mcp
re
redpanda-client
ro
robin-map
sa
development
beam-modules
elixir-ls
libraries
embree
libinput
python-modules
web
top-level
+34
nixos/doc/manual/default.nix
···
inherit (pkgs) buildPackages runCommand docbook_xsl_ns;
inherit (pkgs.lib)
+
evalModules
hasPrefix
removePrefix
flip
···
${testOptionsDoc.optionsJSON}/${common.outputPath}/options.json
sed -e '/@PYTHON_MACHINE_METHODS@/ {' -e 'r ${testDriverMachineDocstrings}/machine-methods.md' -e 'd' -e '}' \
-i ./development/writing-nixos-tests.section.md
+
substituteInPlace ./development/modular-services.md \
+
--replace-fail \
+
'@PORTABLE_SERVICE_OPTIONS@' \
+
${portableServiceOptions.optionsJSON}/${common.outputPath}/options.json
+
substituteInPlace ./development/modular-services.md \
+
--replace-fail \
+
'@SYSTEMD_SERVICE_OPTIONS@' \
+
${systemdServiceOptions.optionsJSON}/${common.outputPath}/options.json
'';
+
+
portableServiceOptions = buildPackages.nixosOptionsDoc {
+
inherit (evalModules { modules = [ ../../modules/system/service/portable/service.nix ]; }) options;
+
inherit revision warningsAreErrors;
+
transformOptions =
+
opt:
+
opt
+
// {
+
# Clean up declaration sites to not refer to the NixOS source tree.
+
declarations = map stripAnyPrefixes opt.declarations;
+
};
+
};
+
+
systemdServiceOptions = buildPackages.nixosOptionsDoc {
+
inherit (evalModules { modules = [ ../../modules/system/service/systemd/service.nix ]; }) options;
+
# TODO: filter out options that are not systemd-specific, maybe also change option prefix to just `service-opt-`?
+
inherit revision warningsAreErrors;
+
transformOptions =
+
opt:
+
opt
+
// {
+
# Clean up declaration sites to not refer to the NixOS source tree.
+
declarations = map stripAnyPrefixes opt.declarations;
+
};
+
};
in
rec {
+1
nixos/doc/manual/development/development.md
···
nixos-tests.chapter.md
developing-the-test-driver.chapter.md
testing-installer.chapter.md
+
modular-services.md
```
+98
nixos/doc/manual/development/modular-services.md
···
+
+
# Modular Services {#modular-services}
+
+
Status: in development. This functionality is new in NixOS 25.11, and significant changes should be expected. We'd love to hear your feedback in <https://github.com/NixOS/nixpkgs/pull/372170>
+
+
Traditionally, NixOS services were defined using sets of options *in* modules, not *as* modules. This made them non-modular, resulting in problems with composability, reuse, and portability.
+
+
A configuration management framework is an application of `evalModules` with the `class` and `specialArgs` input attribute set to particular values.
+
NixOS is such a configuration management framework, and so are [Home Manager](https://github.com/nix-community/home-manager) and [`nix-darwin`](https://github.com/lnl7/nix-darwin).
+
+
The service management component of a configuration management framework is the set of module options that connects Nix expressions with the underlying service (or process) manager.
+
For NixOS this is the module wrapping [`systemd`](https://systemd.io/), on `nix-darwin` this is the module wrapping [`launchd`](https://en.wikipedia.org/wiki/Launchd).
+
+
A *modular service* is a [module] that defines values for a core set of options declared in the service management component of a configuration management framework, including which program to run.
+
Since it's a module, it can be composed with other modules via `imports` to extend its functionality.
+
+
NixOS provides two options into which such modules can be plugged:
+
+
- `system.services.<name>`
+
- an option for user services (TBD)
+
+
Crucially, these options have the type [`attrsOf`] [`submodule`].
+
The name of the service is the attribute name corresponding to `attrsOf`.
+
<!-- ^ This is how composition is *always* provided, instead of a difficult thing (but this is reference docs, not a changelog) -->
+
The `submodule` is pre-loaded with two modules:
+
- a generic module that is intended to be portable
+
- a module with systemd-specific options, whose values or defaults derive from the generic module's option values.
+
+
So note that the default value of `system.services.<name>` is not a complete service. It requires that the user provide a value, and this is typically done by importing a module. For example:
+
+
<!-- Not using typical example syntax, because reading this is *not* optional, and should it should not be folded closed. -->
+
```nix
+
{
+
system.services.my-service-instance = {
+
imports = [ pkgs.some-application.services.some-service-module ];
+
foo.settings = {
+
# ...
+
};
+
};
+
}
+
```
+
+
## Portability {#modular-service-portability}
+
+
It is possible to write service modules that are portable. This is done by either avoiding the `systemd` option tree, or by defining process-manager-specific definitions in an optional way:
+
+
```nix
+
{ config, options, lib, ... }: {
+
_class = "service";
+
config = {
+
process.argv = [ (lib.getExe config.foo.program) ];
+
} // lib.optionalAttrs (options?systemd) {
+
# ... systemd-specific definitions ...
+
};
+
}
+
```
+
+
This way, the module can be loaded into a configuration manager that does not use systemd, and the `systemd` definitions will be ignored.
+
Similarly, other configuration managers can declare their own options for services to customize.
+
+
## Composition and Ownership {#modular-service-composition}
+
+
Compared to traditional services, modular services are inherently more composable, by virtue of being modules and receiving a user-provided name when imported.
+
However, composition can not end there, because services need to be able to interact with each other.
+
This can be achieved in two ways:
+
1. Users can link services together by providing the necessary NixOS configuration.
+
2. Services can be compositions of other services.
+
+
These aren't mutually exclusive. In fact, it is a good practice when developing services to first write them as individual services, and then compose them into a higher-level composition. Each of these services is a valid modular service, including their composition.
+
+
## Migration {#modular-service-migration}
+
+
Many services could be migrated to the modular service system, but even when the modular service system is mature, it is not necessary to migrate all services.
+
For instance, many system-wide services are a mandatory part of a desktop system, and it doesn't make sense to have multiple instances of them.
+
Moving their logic into separate Nix files may still be beneficial for the efficient evaluation of configurations that don't use those services, but that is a rather minor benefit, unless modular services potentially become the standard way to define services.
+
+
<!-- TODO example of a single-instance service -->
+
+
## Portable Service Options {#modular-service-options-portable}
+
+
```{=include=} options
+
id-prefix: service-opt-
+
list-id: service-options
+
source: @PORTABLE_SERVICE_OPTIONS@
+
```
+
+
## Systemd-specific Service Options {#modular-service-options-systemd}
+
+
```{=include=} options
+
id-prefix: systemd-service-opt-
+
list-id: systemd-service-options
+
source: @SYSTEMD_SERVICE_OPTIONS@
+
```
+
+
[module]: https://nixos.org/manual/nixpkgs/stable/index.html#module-system
+
<!-- TODO: more anchors -->
+
[`attrsOf`]: #sec-option-types-composed
+
[`submodule`]: #sec-option-types-submodule
+18
nixos/doc/manual/redirects.json
···
"book-nixos-manual": [
"index.html#book-nixos-manual"
],
+
"modular-service-composition": [
+
"index.html#modular-service-composition"
+
],
+
"modular-service-migration": [
+
"index.html#modular-service-migration"
+
],
+
"modular-service-options-portable": [
+
"index.html#modular-service-options-portable"
+
],
+
"modular-service-options-systemd": [
+
"index.html#modular-service-options-systemd"
+
],
+
"modular-service-portability": [
+
"index.html#modular-service-portability"
+
],
+
"modular-services": [
+
"index.html#modular-services"
+
],
"module-services-anubis": [
"index.html#module-services-anubis"
],
+3 -1
nixos/modules/misc/assertions.nix
···
};
};
-
# impl of assertions is in <nixpkgs/nixos/modules/system/activation/top-level.nix>
+
# impl of assertions is in
+
# - <nixpkgs/nixos/modules/system/activation/top-level.nix>
+
# - <nixpkgs/nixos/modules/system/service/portable/lib.nix>
}
+2
nixos/modules/module-list.nix
···
./system/boot/uvesafb.nix
./system/boot/zram-as-tmp.nix
./system/etc/etc-activation.nix
+
./system/service/systemd/system.nix
+
./system/service/systemd/user.nix
./tasks/auto-upgrade.nix
./tasks/bcache.nix
./tasks/cpu-freq.nix
+219 -216
nixos/modules/services/web-apps/nextcloud.nix
···
pkgs,
...
}:
-
-
with lib;
-
let
+
inherit (lib)
+
mkIf
+
mkMerge
+
;
+
cfg = config.services.nextcloud;
overridePackage = cfg.package.override {
···
nix-apps = {
enabled = cfg.extraApps != { };
linkTarget = pkgs.linkFarm "nix-apps" (
-
mapAttrsToList (name: path: { inherit name path; }) cfg.extraApps
+
lib.mapAttrsToList (name: path: { inherit name path; }) cfg.extraApps
);
writable = false;
};
···
''
mkdir $out
ln -sfv "${overridePackage}"/* "$out"
-
${concatStrings (
-
mapAttrsToList (
+
${lib.concatStrings (
+
lib.mapAttrsToList (
name: store:
-
optionalString (store.enabled && store ? linkTarget) ''
+
lib.optionalString (store.enabled && store ? linkTarget) ''
if [ -e "$out"/${name} ]; then
echo "Didn't expect ${name} already in $out!"
exit 1
···
intl
sodium
] # recommended
-
++ optional cfg.enableImagemagick imagick
+
++ lib.optional cfg.enableImagemagick imagick
# Optionally enabled depending on caching settings
-
++ optional cfg.caching.apcu apcu
-
++ optional cfg.caching.redis redis
-
++ optional cfg.caching.memcached memcached
-
++ optional (cfg.settings.log_type == "systemd") systemd
+
++ lib.optional cfg.caching.apcu apcu
+
++ lib.optional cfg.caching.redis redis
+
++ lib.optional cfg.caching.memcached memcached
+
++ lib.optional (cfg.settings.log_type == "systemd") systemd
)
++ cfg.phpExtraExtensions all; # Enabled by user
extraConfig = toKeyValue cfg.phpOptions;
};
-
toKeyValue = generators.toKeyValue {
-
mkKeyValue = generators.mkKeyValueDefault { } " = ";
+
toKeyValue = lib.generators.toKeyValue {
+
mkKeyValue = lib.generators.mkKeyValueDefault { } " = ";
};
-
phpCli = concatStringsSep " " (
+
phpCli = lib.concatStringsSep " " (
[
-
"${getExe phpPackage}"
+
"${lib.getExe phpPackage}"
]
-
++ optionals (cfg.cli.memoryLimit != null) [
+
++ lib.optionals (cfg.cli.memoryLimit != null) [
"-dmemory_limit=${cfg.cli.memoryLimit}"
]
);
···
let
s3 = c.objectstore.s3;
in
-
optionalString s3.enable ''
+
lib.optionalString s3.enable ''
'objectstore' => [
'class' => '\\OC\\Files\\ObjectStore\\S3',
'arguments' => [
'bucket' => '${s3.bucket}',
-
'verify_bucket_exists' => ${boolToString s3.verify_bucket_exists},
+
'verify_bucket_exists' => ${lib.boolToString s3.verify_bucket_exists},
'key' => '${s3.key}',
'secret' => nix_read_secret('s3_secret'),
-
${optionalString (s3.hostname != null) "'hostname' => '${s3.hostname}',"}
-
${optionalString (s3.port != null) "'port' => ${toString s3.port},"}
-
'use_ssl' => ${boolToString s3.useSsl},
-
${optionalString (s3.region != null) "'region' => '${s3.region}',"}
-
'use_path_style' => ${boolToString s3.usePathStyle},
-
${optionalString (s3.sseCKeyFile != null) "'sse_c_key' => nix_read_secret('s3_sse_c_key'),"}
+
${lib.optionalString (s3.hostname != null) "'hostname' => '${s3.hostname}',"}
+
${lib.optionalString (s3.port != null) "'port' => ${toString s3.port},"}
+
'use_ssl' => ${lib.boolToString s3.useSsl},
+
${lib.optionalString (s3.region != null) "'region' => '${s3.region}',"}
+
'use_path_style' => ${lib.boolToString s3.usePathStyle},
+
${lib.optionalString (s3.sseCKeyFile != null) "'sse_c_key' => nix_read_secret('s3_sse_c_key'),"}
],
]
'';
···
let
x = cfg.appstoreEnable;
in
-
if x == null then "false" else boolToString x;
+
if x == null then "false" else lib.boolToString x;
mkAppStoreConfig =
name:
{ enabled, writable, ... }:
-
optionalString enabled ''
-
[ 'path' => '${webroot}/${name}', 'url' => '/${name}', 'writable' => ${boolToString writable} ],
+
lib.optionalString enabled ''
+
[ 'path' => '${webroot}/${name}', 'url' => '/${name}', 'writable' => ${lib.boolToString writable} ],
'';
in
pkgs.writeText "nextcloud-config.php" ''
<?php
-
${optionalString requiresRuntimeSystemdCredentials ''
+
${lib.optionalString requiresRuntimeSystemdCredentials ''
function nix_read_secret($credential_name) {
$credentials_directory = getenv("CREDENTIALS_DIRECTORY");
if (!$credentials_directory) {
···
}
$CONFIG = [
'apps_paths' => [
-
${concatStrings (mapAttrsToList mkAppStoreConfig appStores)}
+
${lib.concatStrings (lib.mapAttrsToList mkAppStoreConfig appStores)}
],
-
${optionalString (showAppStoreSetting) "'appstoreenabled' => ${renderedAppStoreSetting},"}
-
${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
-
${optionalString (c.dbname != null) "'dbname' => '${c.dbname}',"}
-
${optionalString (c.dbhost != null) "'dbhost' => '${c.dbhost}',"}
-
${optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"}
-
${optionalString (c.dbtableprefix != null) "'dbtableprefix' => '${toString c.dbtableprefix}',"}
-
${optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_secret('dbpass'),"}
+
${lib.optionalString (showAppStoreSetting) "'appstoreenabled' => ${renderedAppStoreSetting},"}
+
${lib.optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
+
${lib.optionalString (c.dbname != null) "'dbname' => '${c.dbname}',"}
+
${lib.optionalString (c.dbhost != null) "'dbhost' => '${c.dbhost}',"}
+
${lib.optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"}
+
${lib.optionalString (
+
c.dbtableprefix != null
+
) "'dbtableprefix' => '${toString c.dbtableprefix}',"}
+
${lib.optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_secret('dbpass'),"}
'dbtype' => '${c.dbtype}',
${objectstoreConfig}
];
···
"impossible: this should never happen (decoding generated settings file %s failed)"
));
-
${optionalString (cfg.secretFile != null) ''
+
${lib.optionalString (cfg.secretFile != null) ''
$CONFIG = array_replace_recursive($CONFIG, nix_read_secret_and_decode_json_file('secret_file'));
''}
'';
···
{
imports = [
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "cron" "memoryLimit" ]
[ "services" "nextcloud" "cli" "memoryLimit" ]
)
-
(mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] ''
+
(lib.mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] ''
This option has no effect since there's no supported Nextcloud version packaged here
using OpenSSL for RC4 SSE.
'')
-
(mkRemovedOptionModule [ "services" "nextcloud" "config" "dbport" ] ''
+
(lib.mkRemovedOptionModule [ "services" "nextcloud" "config" "dbport" ] ''
Add port to services.nextcloud.config.dbhost instead.
'')
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "logLevel" ]
[ "services" "nextcloud" "settings" "loglevel" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "logType" ]
[ "services" "nextcloud" "settings" "log_type" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "config" "defaultPhoneRegion" ]
[ "services" "nextcloud" "settings" "default_phone_region" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "config" "overwriteProtocol" ]
[ "services" "nextcloud" "settings" "overwriteprotocol" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "skeletonDirectory" ]
[ "services" "nextcloud" "settings" "skeletondirectory" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "globalProfiles" ]
[ "services" "nextcloud" "settings" "profile.enabled" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "config" "extraTrustedDomains" ]
[ "services" "nextcloud" "settings" "trusted_domains" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "config" "trustedProxies" ]
[ "services" "nextcloud" "settings" "trusted_proxies" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "extraOptions" ]
[ "services" "nextcloud" "settings" ]
)
-
(mkRenamedOptionModule
+
(lib.mkRenamedOptionModule
[ "services" "nextcloud" "config" "objectstore" "s3" "autocreate" ]
[ "services" "nextcloud" "config" "objectstore" "s3" "verify_bucket_exists" ]
)
];
options.services.nextcloud = {
-
enable = mkEnableOption "nextcloud";
+
enable = lib.mkEnableOption "nextcloud";
-
hostName = mkOption {
-
type = types.str;
+
hostName = lib.mkOption {
+
type = lib.types.str;
description = "FQDN for the nextcloud instance.";
};
-
home = mkOption {
-
type = types.str;
+
home = lib.mkOption {
+
type = lib.types.str;
default = "/var/lib/nextcloud";
description = "Storage path of nextcloud.";
};
-
datadir = mkOption {
-
type = types.str;
+
datadir = lib.mkOption {
+
type = lib.types.str;
default = config.services.nextcloud.home;
-
defaultText = literalExpression "config.services.nextcloud.home";
+
defaultText = lib.literalExpression "config.services.nextcloud.home";
description = ''
Nextcloud's data storage path. Will be [](#opt-services.nextcloud.home) by default.
This folder will be populated with a config.php file and a data folder which contains the state of the instance (excluding the database).";
'';
example = "/mnt/nextcloud-file";
};
-
extraApps = mkOption {
-
type = types.attrsOf types.package;
+
extraApps = lib.mkOption {
+
type = lib.types.attrsOf lib.types.package;
default = { };
description = ''
Extra apps to install. Should be an attrSet of appid to packages generated by fetchNextcloudApp.
The appid must be identical to the "id" value in the apps appinfo/info.xml.
Using this will disable the appstore to prevent Nextcloud from updating these apps (see [](#opt-services.nextcloud.appstoreEnable)).
'';
-
example = literalExpression ''
+
example = lib.literalExpression ''
{
inherit (pkgs.nextcloud31Packages.apps) mail calendar contacts;
phonetrack = pkgs.fetchNextcloudApp {
···
}
'';
};
-
extraAppsEnable = mkOption {
-
type = types.bool;
+
extraAppsEnable = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Automatically enable the apps in [](#opt-services.nextcloud.extraApps) every time Nextcloud starts.
If set to false, apps need to be enabled in the Nextcloud web user interface or with `nextcloud-occ app:enable`.
'';
};
-
appstoreEnable = mkOption {
-
type = types.nullOr types.bool;
+
appstoreEnable = lib.mkOption {
+
type = lib.types.nullOr lib.types.bool;
default = null;
example = true;
description = ''
···
Set this to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting.
'';
};
-
https = mkOption {
-
type = types.bool;
+
https = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Use HTTPS for generated links.
···
Be aware that this also enables HTTP Strict Transport Security (HSTS) headers.
'';
};
-
package = mkOption {
-
type = types.package;
+
package = lib.mkOption {
+
type = lib.types.package;
description = "Which package to use for the Nextcloud instance.";
relatedPackages = [
"nextcloud30"
"nextcloud31"
];
};
-
phpPackage = mkPackageOption pkgs "php" {
+
phpPackage = lib.mkPackageOption pkgs "php" {
+
default = [ "php83" ];
example = "php82";
};
-
finalPackage = mkOption {
-
type = types.package;
+
finalPackage = lib.mkOption {
+
type = lib.types.package;
readOnly = true;
description = ''
Package to the finalized Nextcloud package, including all installed apps.
···
'';
};
-
maxUploadSize = mkOption {
+
maxUploadSize = lib.mkOption {
default = "512M";
-
type = types.str;
+
type = lib.types.str;
description = ''
The upload limit for files. This changes the relevant options
in php.ini and nginx if enabled.
'';
};
-
webfinger = mkOption {
-
type = types.bool;
+
webfinger = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Enable this option if you plan on using the webfinger plugin.
···
'';
};
-
phpExtraExtensions = mkOption {
-
type = with types; functionTo (listOf package);
+
phpExtraExtensions = lib.mkOption {
+
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = all: [ ];
-
defaultText = literalExpression "all: []";
+
defaultText = lib.literalExpression "all: []";
description = ''
Additional PHP extensions to use for Nextcloud.
By default, only extensions necessary for a vanilla Nextcloud installation are enabled,
but you may choose from the list of available extensions and add further ones.
This is sometimes necessary to be able to install a certain Nextcloud app that has additional requirements.
'';
-
example = literalExpression ''
+
example = lib.literalExpression ''
all: [ all.pdlib all.bz2 ]
'';
};
-
phpOptions = mkOption {
-
type =
-
with types;
-
attrsOf (oneOf [
-
str
-
int
-
]);
-
defaultText = literalExpression (
-
generators.toPretty { } (
-
defaultPHPSettings // { "openssl.cafile" = literalExpression "config.security.pki.caBundle"; }
+
phpOptions = lib.mkOption {
+
type = lib.types.attrsOf (
+
lib.types.oneOf [
+
lib.types.str
+
lib.types.int
+
]
+
);
+
defaultText = lib.literalExpression (
+
lib.generators.toPretty { } (
+
defaultPHPSettings // { "openssl.cafile" = lib.literalExpression "config.security.pki.caBundle"; }
)
);
description = ''
···
'';
};
-
poolSettings = mkOption {
-
type =
-
with types;
-
attrsOf (oneOf [
-
str
-
int
-
bool
-
]);
+
poolSettings = lib.mkOption {
+
type = lib.types.attrsOf (
+
lib.types.oneOf [
+
lib.types.str
+
lib.types.int
+
lib.types.bool
+
]
+
);
default = {
"pm" = "dynamic";
"pm.max_children" = "120";
···
'';
};
-
poolConfig = mkOption {
-
type = types.nullOr types.lines;
+
poolConfig = lib.mkOption {
+
type = lib.types.nullOr lib.types.lines;
default = null;
description = ''
Options for Nextcloud's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives.
'';
};
-
fastcgiTimeout = mkOption {
-
type = types.int;
+
fastcgiTimeout = lib.mkOption {
+
type = lib.types.int;
default = 120;
description = ''
FastCGI timeout for database connection in seconds.
···
database = {
-
createLocally = mkOption {
-
type = types.bool;
+
createLocally = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Whether to create the database and database user locally.
···
};
config = {
-
dbtype = mkOption {
-
type = types.nullOr (
-
types.enum [
+
dbtype = lib.mkOption {
+
type = lib.types.nullOr (
+
lib.types.enum [
"sqlite"
"pgsql"
"mysql"
···
default = null;
description = "Database type.";
};
-
dbname = mkOption {
-
type = types.nullOr types.str;
+
dbname = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = "nextcloud";
description = "Database name.";
};
-
dbuser = mkOption {
-
type = types.nullOr types.str;
+
dbuser = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = "nextcloud";
description = "Database user.";
};
-
dbpassFile = mkOption {
-
type = types.nullOr types.str;
+
dbpassFile = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
The full path to a file that contains the database password.
'';
};
-
dbhost = mkOption {
-
type = types.nullOr types.str;
+
dbhost = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default =
if pgsqlLocal then
"/run/postgresql"
···
defaults to the correct Unix socket instead.
'';
};
-
dbtableprefix = mkOption {
-
type = types.nullOr types.str;
+
dbtableprefix = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Table prefix in Nextcloud's database.
···
with installations that were originally provisioned with Nextcloud <20.
'';
};
-
adminuser = mkOption {
-
type = types.str;
+
adminuser = lib.mkOption {
+
type = lib.types.str;
default = "root";
description = ''
Username for the admin account. The username is only set during the
···
ID internally, it cannot be changed later!
'';
};
-
adminpassFile = mkOption {
-
type = types.str;
+
adminpassFile = lib.mkOption {
+
type = lib.types.str;
description = ''
The full path to a file that contains the admin's password. The password is
set only in the initial setup of Nextcloud by the systemd service `nextcloud-setup.service`.
···
};
objectstore = {
s3 = {
-
enable = mkEnableOption ''
+
enable = lib.mkEnableOption ''
S3 object storage as primary storage.
This mounts a bucket on an Amazon S3 object storage or compatible
···
Further details about this feature can be found in the
[upstream documentation](https://docs.nextcloud.com/server/22/admin_manual/configuration_files/primary_storage.html)
'';
-
bucket = mkOption {
-
type = types.str;
+
bucket = lib.mkOption {
+
type = lib.types.str;
example = "nextcloud";
description = ''
The name of the S3 bucket.
'';
};
-
verify_bucket_exists = mkOption {
-
type = types.bool;
+
verify_bucket_exists = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Create the objectstore bucket if it does not exist.
'';
};
-
key = mkOption {
-
type = types.str;
+
key = lib.mkOption {
+
type = lib.types.str;
example = "EJ39ITYZEUH5BGWDRUFY";
description = ''
The access key for the S3 bucket.
'';
};
-
secretFile = mkOption {
-
type = types.str;
+
secretFile = lib.mkOption {
+
type = lib.types.str;
example = "/var/nextcloud-objectstore-s3-secret";
description = ''
The full path to a file that contains the access secret.
'';
};
-
hostname = mkOption {
-
type = types.nullOr types.str;
+
hostname = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
example = "example.com";
description = ''
Required for some non-Amazon implementations.
'';
};
-
port = mkOption {
-
type = types.nullOr types.port;
+
port = lib.mkOption {
+
type = lib.types.nullOr lib.types.port;
default = null;
description = ''
Required for some non-Amazon implementations.
'';
};
-
useSsl = mkOption {
-
type = types.bool;
+
useSsl = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Use SSL for objectstore access.
'';
};
-
region = mkOption {
-
type = types.nullOr types.str;
+
region = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
example = "REGION";
description = ''
Required for some non-Amazon implementations.
'';
};
-
usePathStyle = mkOption {
-
type = types.bool;
+
usePathStyle = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Required for some non-Amazon S3 implementations.
···
`http://hostname.domain/bucket` instead.
'';
};
-
sseCKeyFile = mkOption {
-
type = types.nullOr types.path;
+
sseCKeyFile = lib.mkOption {
+
type = lib.types.nullOr lib.types.path;
default = null;
example = "/var/nextcloud-objectstore-s3-sse-c-key";
description = ''
···
};
enableImagemagick =
-
mkEnableOption ''
+
lib.mkEnableOption ''
the ImageMagick module for PHP.
This is used by the theming app and for generating previews of certain images (e.g. SVG and HEIF).
You may want to disable it for increased security. In that case, previews will still be available
···
configureRedis = lib.mkOption {
type = lib.types.bool;
default = config.services.nextcloud.notify_push.enable;
-
defaultText = literalExpression "config.services.nextcloud.notify_push.enable";
+
defaultText = lib.literalExpression "config.services.nextcloud.notify_push.enable";
description = ''
Whether to configure Nextcloud to use the recommended Redis settings for small instances.
···
};
caching = {
-
apcu = mkOption {
-
type = types.bool;
+
apcu = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = ''
Whether to load the APCu module into PHP.
'';
};
-
redis = mkOption {
-
type = types.bool;
+
redis = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Whether to load the Redis module into PHP.
···
See <https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/caching_configuration.html>
'';
};
-
memcached = mkOption {
-
type = types.bool;
+
memcached = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Whether to load the Memcached module into PHP.
···
};
};
autoUpdateApps = {
-
enable = mkOption {
-
type = types.bool;
+
enable = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Run a regular auto-update of all apps installed from the Nextcloud app store.
'';
};
-
startAt = mkOption {
-
type = with types; either str (listOf str);
+
startAt = lib.mkOption {
+
type = lib.types.either lib.types.str (lib.types.listOf lib.types.str);
default = "05:00:00";
example = "Sun 14:00:00";
description = ''
···
'';
};
};
-
occ = mkOption {
-
type = types.package;
+
occ = lib.mkOption {
+
type = lib.types.package;
default = occ;
-
defaultText = literalMD "generated script";
+
defaultText = lib.literalMD "generated script";
description = ''
The nextcloud-occ program preconfigured to target this Nextcloud instance.
'';
};
-
settings = mkOption {
-
type = types.submodule {
+
settings = lib.mkOption {
+
type = lib.types.submodule {
freeformType = jsonFormat.type;
options = {
-
loglevel = mkOption {
-
type = types.ints.between 0 4;
+
loglevel = lib.mkOption {
+
type = lib.types.ints.between 0 4;
default = 2;
description = ''
Log level value between 0 (DEBUG) and 4 (FATAL).
···
- 4 (fatal): Log only fatal errors that cause the server to stop.
'';
};
-
log_type = mkOption {
-
type = types.enum [
+
log_type = lib.mkOption {
+
type = lib.types.enum [
"errorlog"
"file"
"syslog"
···
See the [nextcloud documentation](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/logging_configuration.html) for details.
'';
};
-
skeletondirectory = mkOption {
+
skeletondirectory = lib.mkOption {
default = "";
-
type = types.str;
+
type = lib.types.str;
description = ''
The directory where the skeleton files are located. These files will be
copied to the data directory of new users. Leave empty to not copy any
skeleton files.
'';
};
-
trusted_domains = mkOption {
-
type = types.listOf types.str;
+
trusted_domains = lib.mkOption {
+
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Trusted domains, from which the nextcloud installation will be
···
`services.nextcloud.hostname` here.
'';
};
-
trusted_proxies = mkOption {
-
type = types.listOf types.str;
+
trusted_proxies = lib.mkOption {
+
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Trusted proxies, to provide if the nextcloud installation is being
proxied to secure against e.g. spoofing.
'';
};
-
overwriteprotocol = mkOption {
-
type = types.enum [
+
overwriteprotocol = lib.mkOption {
+
type = lib.types.enum [
""
"http"
"https"
···
Nextcloud may be served via HTTPS.
'';
};
-
default_phone_region = mkOption {
+
default_phone_region = lib.mkOption {
default = "";
-
type = types.str;
+
type = lib.types.str;
example = "DE";
description = ''
An [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html)
···
the `+49` prefix can be omitted for phone numbers.
'';
};
-
"profile.enabled" = mkEnableOption "global profiles" // {
+
"profile.enabled" = lib.mkEnableOption "global profiles" // {
description = ''
Makes user-profiles globally available under `nextcloud.tld/u/user.name`.
Even though it's enabled by default in Nextcloud, it must be explicitly enabled
···
description = ''
Extra options which should be appended to Nextcloud's config.php file.
'';
-
example = literalExpression ''
+
example = lib.literalExpression ''
{
redis = {
host = "/run/redis/redis.sock";
···
'';
};
-
secretFile = mkOption {
-
type = types.nullOr types.str;
+
secretFile = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Secret options which will be appended to Nextcloud's config.php file (written as JSON, in the same
···
};
nginx = {
-
recommendedHttpHeaders = mkOption {
-
type = types.bool;
+
recommendedHttpHeaders = lib.mkOption {
+
type = lib.types.bool;
default = true;
description = "Enable additional recommended HTTP response headers";
};
-
hstsMaxAge = mkOption {
-
type = types.ints.positive;
+
hstsMaxAge = lib.mkOption {
+
type = lib.types.ints.positive;
default = 15552000;
description = ''
Value for the `max-age` directive of the HTTP
···
directive and header.
'';
};
-
enableFastcgiRequestBuffering = mkOption {
-
type = types.bool;
+
enableFastcgiRequestBuffering = lib.mkOption {
+
type = lib.types.bool;
default = false;
description = ''
Whether to buffer requests against fastcgi requests. This is a workaround
···
};
};
-
cli.memoryLimit = mkOption {
-
type = types.nullOr types.str;
+
cli.memoryLimit = lib.mkOption {
+
type = lib.types.nullOr lib.types.str;
default = null;
example = "1G";
description = ''
···
'';
in
-
(optional (cfg.poolConfig != null) ''
+
(lib.optional (cfg.poolConfig != null) ''
Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release.
Please migrate your configuration to config.services.nextcloud.poolSettings.
'')
-
++ (optional (cfg.config.dbtableprefix != null) ''
+
++ (lib.optional (cfg.config.dbtableprefix != null) ''
Using `services.nextcloud.config.dbtableprefix` is deprecated. Fresh installations with this
option set are not allowed anymore since v20.
If you have an existing installation with a custom table prefix, make sure it is
set correctly in `config.php` and remove the option from your NixOS config.
'')
-
++ (optional (versionOlder overridePackage.version "26") (upgradeWarning 25 "23.05"))
-
++ (optional (versionOlder overridePackage.version "27") (upgradeWarning 26 "23.11"))
-
++ (optional (versionOlder overridePackage.version "28") (upgradeWarning 27 "24.05"))
-
++ (optional (versionOlder overridePackage.version "29") (upgradeWarning 28 "24.11"))
-
++ (optional (versionOlder overridePackage.version "30") (upgradeWarning 29 "24.11"))
-
++ (optional (versionOlder overridePackage.version "31") (upgradeWarning 30 "25.05"));
+
++ (lib.optional (lib.versionOlder overridePackage.version "26") (upgradeWarning 25 "23.05"))
+
++ (lib.optional (lib.versionOlder overridePackage.version "27") (upgradeWarning 26 "23.11"))
+
++ (lib.optional (lib.versionOlder overridePackage.version "28") (upgradeWarning 27 "24.05"))
+
++ (lib.optional (lib.versionOlder overridePackage.version "29") (upgradeWarning 28 "24.11"))
+
++ (lib.optional (lib.versionOlder overridePackage.version "30") (upgradeWarning 29 "24.11"))
+
++ (lib.optional (lib.versionOlder overridePackage.version "31") (upgradeWarning 30 "25.05"));
services.nextcloud.package =
with pkgs;
-
mkDefault (
+
lib.mkDefault (
if pkgs ? nextcloud then
throw ''
The `pkgs.nextcloud`-attribute has been removed. If it's supposed to be the default
···
nextcloud31
);
-
services.nextcloud.phpPackage = pkgs.php83;
-
services.nextcloud.phpOptions = mkMerge [
-
(mapAttrs (const mkOptionDefault) defaultPHPSettings)
+
(lib.mapAttrs (lib.const lib.mkOptionDefault) defaultPHPSettings)
upload_max_filesize = cfg.maxUploadSize;
post_max_size = cfg.maxUploadSize;
···
arg = "ADMINPASS";
value = ''"$(<"$CREDENTIALS_DIRECTORY/adminpass")"'';
};
-
installFlags = concatStringsSep " \\\n " (
-
mapAttrsToList (k: v: "${k} ${toString v}") {
+
installFlags = lib.concatStringsSep " \\\n " (
+
lib.mapAttrsToList (k: v: "${k} ${toString v}") {
"--database" = ''"${c.dbtype}"'';
# The following attributes are optional depending on the type of
# database. Those that evaluate to null on the left hand side
···
${lib.getExe occ} maintenance:install \
${installFlags}
'';
-
occSetTrustedDomainsCmd = concatStringsSep "\n" (
-
imap0 (i: v: ''
+
occSetTrustedDomainsCmd = lib.concatStringsSep "\n" (
+
lib.imap0 (i: v: ''
${lib.getExe occ} config:system:set trusted_domains \
${toString i} --value="${toString v}"
'') (lib.unique ([ cfg.hostName ] ++ cfg.settings.trusted_domains))
···
wantedBy = [ "multi-user.target" ];
wants = [ "nextcloud-update-db.service" ];
before = [ "phpfpm-nextcloud.service" ];
-
after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.target";
-
requires = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.target";
+
after = lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.target";
+
requires = lib.optional mysqlLocal "mysql.service" ++ lib.optional pgsqlLocal "postgresql.target";
path = [ occ ];
restartTriggers = [ overrideConfig ];
script = ''
-
${optionalString (c.dbpassFile != null) ''
+
${lib.optionalString (c.dbpassFile != null) ''
if [ -z "$(<"$CREDENTIALS_DIRECTORY/dbpass")" ]; then
echo "dbpassFile ${c.dbpassFile} is empty!"
exit 1
···
exit 1
fi
-
${concatMapStrings
+
${lib.concatMapStrings
(name: ''
if [ -d "${cfg.home}"/${name} ]; then
echo "Cleaning up ${name}; these are now bundled in the webroot store-path!"
···
${lib.getExe occ} config:system:delete trusted_domains
-
${optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) ''
+
${lib.optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) ''
# Try to enable apps
-
${lib.getExe occ} app:enable ${concatStringsSep " " (attrNames cfg.extraApps)}
+
${lib.getExe occ} app:enable ${lib.concatStringsSep " " (lib.attrNames cfg.extraApps)}
''}
${occSetTrustedDomainsCmd}
···
PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin";
};
settings =
-
mapAttrs (name: mkDefault) {
+
lib.mapAttrs (name: lib.mkDefault) {
"listen.owner" = config.services.nginx.user;
"listen.group" = config.services.nginx.group;
···
services.nextcloud = {
caching.redis = lib.mkIf cfg.configureRedis true;
settings = mkMerge [
-
({
+
{
datadirectory = lib.mkDefault "${datadir}/data";
trusted_domains = [ cfg.hostName ];
"upgrade.disable-web" = true;
# NixOS already provides its own integrity check and the nix store is read-only, therefore Nextcloud does not need to do its own integrity checks.
"integrity.check.disabled" = true;
-
})
+
}
(lib.mkIf cfg.configureRedis {
"memcache.distributed" = ''\OC\Memcache\Redis'';
"memcache.locking" = ''\OC\Memcache\Redis'';
···
];
};
-
services.nginx.enable = mkDefault true;
+
services.nginx.enable = lib.mkDefault true;
services.nginx.virtualHosts.${cfg.hostName} = {
root = webroot;
···
};
extraConfig = ''
index index.php index.html /index.php$request_uri;
-
${optionalString (cfg.nginx.recommendedHttpHeaders) ''
+
${lib.optionalString (cfg.nginx.recommendedHttpHeaders) ''
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag "noindex, nofollow";
···
add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
''}
-
${optionalString (cfg.https) ''
+
${lib.optionalString (cfg.https) ''
add_header Strict-Transport-Security "max-age=${toString cfg.nginx.hstsMaxAge}; includeSubDomains" always;
''}
client_max_body_size ${cfg.maxUploadSize};
···
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
-
${optionalString cfg.webfinger ''
+
${lib.optionalString cfg.webfinger ''
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
''}
···
]);
meta.doc = ./nextcloud.md;
-
meta.maintainers = teams.nextcloud.members;
+
meta.maintainers = lib.teams.nextcloud.members;
+28
nixos/modules/system/service/README.md
···
+
+
# Modular Services
+
+
This directory defines a modular service infrastructure for NixOS.
+
See the [Modular Services chapter] in the manual [[source]](../../doc/manual/development/modular-services.md).
+
+
[Modular Services chapter]: https://nixos.org/manual/nixos/unstable/#modular-services
+
+
# Design decision log
+
+
- `system.services.<name>`. Alternatives considered
+
- `systemServices`: similar to does not allow importing a composition of services into `system`. Not sure if that's a good idea in the first place, but I've kept the possibility open.
+
- `services.abstract`: used in https://github.com/NixOS/nixpkgs/pull/267111, but too weird. Service modules should fit naturally into the configuration system.
+
Also "abstract" is wrong, because it has submodules - in other words, evalModules results, concrete services - not abstract at all.
+
- `services.modular`: only slightly better than `services.abstract`, but still weird
+
+
- No `daemon.*` options. https://github.com/NixOS/nixpkgs/pull/267111/files#r1723206521
+
+
- For now, do not add an `enable` option, because it's ambiguous. Does it disable at the Nix level (not generate anything) or at the systemd level (generate a service that is disabled)?
+
+
- Move all process options into a `process` option tree. Putting this at the root is messy, because we also have sub-services at that level. Those are rather distinct. Grouping them "by kind" should raise fewer questions.
+
+
- `modules/system/service/systemd/system.nix` has `system` twice. Not great, but
+
- they have different meanings
+
1. These are system-provided modules, provided by the configuration manager
+
2. `systemd/system` configures SystemD _system units_.
+
- This reserves `modules/service` for actual service modules, at least until those are lifted out of NixOS, potentially
+
+33
nixos/modules/system/service/portable/lib.nix
···
+
{ lib, ... }:
+
let
+
inherit (lib) concatLists mapAttrsToList showOption;
+
in
+
rec {
+
flattenMapServicesConfigToList =
+
f: loc: config:
+
f loc config
+
++ concatLists (
+
mapAttrsToList (
+
k: v:
+
flattenMapServicesConfigToList f (
+
loc
+
++ [
+
"services"
+
k
+
]
+
) v
+
) config.services
+
);
+
+
getWarnings = flattenMapServicesConfigToList (
+
loc: config: map (msg: "in ${showOption loc}: ${msg}") config.warnings
+
);
+
+
getAssertions = flattenMapServicesConfigToList (
+
loc: config:
+
map (ass: {
+
message = "in ${showOption loc}: ${ass.message}";
+
assertion = ass.assertion;
+
}) config.assertions
+
);
+
}
+48
nixos/modules/system/service/portable/service.nix
···
+
{
+
lib,
+
config,
+
options,
+
...
+
}:
+
let
+
inherit (lib) mkOption types;
+
pathOrStr = types.coercedTo types.path (x: "${x}") types.str;
+
in
+
{
+
# https://nixos.org/manual/nixos/unstable/#modular-services
+
_class = "service";
+
imports = [
+
../../../misc/assertions.nix
+
];
+
options = {
+
services = mkOption {
+
type = types.attrsOf (
+
types.submoduleWith {
+
modules = [
+
./service.nix
+
];
+
}
+
);
+
description = ''
+
A collection of [modular services](https://nixos.org/manual/nixos/unstable/#modular-services) that are configured in one go.
+
+
You could consider the sub-service relationship to be an ownership relation.
+
It **does not** automatically create any other relationship between services (e.g. systemd slices), unless perhaps such a behavior is explicitly defined and enabled in another option.
+
'';
+
default = { };
+
visible = "shallow";
+
};
+
process = {
+
argv = lib.mkOption {
+
type = types.listOf pathOrStr;
+
example = lib.literalExpression ''[ (lib.getExe config.package) "--nobackground" ]'';
+
description = ''
+
Command filename and arguments for starting this service.
+
This is a raw command-line that should not contain any shell escaping.
+
If expansion of environmental variables is required then use
+
a shell script or `importas` from `pkgs.execline`.
+
'';
+
};
+
};
+
};
+
}
+183
nixos/modules/system/service/portable/test.nix
···
+
# Run:
+
# nix-instantiate --eval nixos/modules/system/service/portable/test.nix
+
let
+
lib = import ../../../../../lib;
+
+
inherit (lib) mkOption types;
+
+
portable-lib = import ./lib.nix { inherit lib; };
+
+
dummyPkg =
+
name:
+
derivation {
+
system = "dummy";
+
name = name;
+
builder = "/bin/false";
+
};
+
+
exampleConfig = {
+
_file = "${__curPos.file}:${toString __curPos.line}";
+
services = {
+
service1 = {
+
process = {
+
argv = [
+
"/usr/bin/echo" # *giggles*
+
"hello"
+
];
+
};
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for that reason";
+
}
+
];
+
warnings = [
+
"The `foo' service is deprecated and will go away soon!"
+
];
+
};
+
service2 = {
+
process = {
+
# No meta.mainProgram, because it's supposedly an executable script _file_,
+
# not a directory with a bin directory containing the main program.
+
argv = [
+
(dummyPkg "cowsay.sh")
+
"world"
+
];
+
};
+
};
+
service3 = {
+
process = {
+
argv = [ "/bin/false" ];
+
};
+
services.exclacow = {
+
process = {
+
argv = [
+
(lib.getExe (
+
dummyPkg "cowsay-ng"
+
// {
+
meta.mainProgram = "cowsay";
+
}
+
))
+
"!"
+
];
+
};
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for such reason";
+
}
+
];
+
warnings = [
+
"The `bar' service is deprecated and will go away soon!"
+
];
+
};
+
};
+
};
+
};
+
+
exampleEval = lib.evalModules {
+
modules = [
+
{
+
options.services = mkOption {
+
type = types.attrsOf (
+
types.submoduleWith {
+
class = "service";
+
modules = [
+
./service.nix
+
];
+
}
+
);
+
};
+
}
+
exampleConfig
+
];
+
};
+
+
test =
+
assert
+
exampleEval.config == {
+
services = {
+
service1 = {
+
process = {
+
argv = [
+
"/usr/bin/echo"
+
"hello"
+
];
+
};
+
services = { };
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for that reason";
+
}
+
];
+
warnings = [
+
"The `foo' service is deprecated and will go away soon!"
+
];
+
};
+
service2 = {
+
process = {
+
argv = [
+
"${dummyPkg "cowsay.sh"}"
+
"world"
+
];
+
};
+
services = { };
+
assertions = [ ];
+
warnings = [ ];
+
};
+
service3 = {
+
process = {
+
argv = [ "/bin/false" ];
+
};
+
services.exclacow = {
+
process = {
+
argv = [
+
"${dummyPkg "cowsay-ng"}/bin/cowsay"
+
"!"
+
];
+
};
+
services = { };
+
assertions = [
+
{
+
assertion = false;
+
message = "you can't enable this for such reason";
+
}
+
];
+
warnings = [ "The `bar' service is deprecated and will go away soon!" ];
+
};
+
assertions = [ ];
+
warnings = [ ];
+
};
+
};
+
};
+
+
assert
+
portable-lib.getWarnings [ "service1" ] exampleEval.config.services.service1 == [
+
"in service1: The `foo' service is deprecated and will go away soon!"
+
];
+
+
assert
+
portable-lib.getAssertions [ "service1" ] exampleEval.config.services.service1 == [
+
{
+
message = "in service1: you can't enable this for that reason";
+
assertion = false;
+
}
+
];
+
+
assert
+
portable-lib.getWarnings [ "service3" ] exampleEval.config.services.service3 == [
+
"in service3.services.exclacow: The `bar' service is deprecated and will go away soon!"
+
];
+
assert
+
portable-lib.getAssertions [ "service3" ] exampleEval.config.services.service3 == [
+
{
+
message = "in service3.services.exclacow: you can't enable this for such reason";
+
assertion = false;
+
}
+
];
+
+
"ok";
+
+
in
+
test
+121
nixos/modules/system/service/systemd/service.nix
···
+
{
+
lib,
+
config,
+
systemdPackage,
+
...
+
}:
+
let
+
inherit (lib)
+
concatMapStringsSep
+
isDerivation
+
isInt
+
isFloat
+
isPath
+
isString
+
mkOption
+
replaceStrings
+
types
+
;
+
inherit (builtins) toJSON;
+
+
# Local copy of systemd exec argument escaping function.
+
# TODO: This could perhaps be deduplicated, but it is unclear where it should go.
+
# Preferably, we don't create a hard dependency on NixOS here, so that this
+
# module can be reused in a non-NixOS context, such as mutaable services
+
# in /run/systemd/system.
+
+
# Quotes an argument for use in Exec* service lines.
+
# systemd accepts "-quoted strings with escape sequences, toJSON produces
+
# a subset of these.
+
# Additionally we escape % to disallow expansion of % specifiers. Any lone ;
+
# in the input will be turned it ";" and thus lose its special meaning.
+
# Every $ is escaped to $$, this makes it unnecessary to disable environment
+
# substitution for the directive.
+
escapeSystemdExecArg =
+
arg:
+
let
+
s =
+
if isPath arg then
+
"${arg}"
+
else if isString arg then
+
arg
+
else if isInt arg || isFloat arg || isDerivation arg then
+
toString arg
+
else
+
throw "escapeSystemdExecArg only allows strings, paths, numbers and derivations";
+
in
+
replaceStrings [ "%" "$" ] [ "%%" "$$" ] (toJSON s);
+
+
# Quotes a list of arguments into a single string for use in a Exec*
+
# line.
+
escapeSystemdExecArgs = concatMapStringsSep " " escapeSystemdExecArg;
+
+
in
+
{
+
imports = [
+
../portable/service.nix
+
(lib.mkAliasOptionModule [ "systemd" "service" ] [ "systemd" "services" "" ])
+
(lib.mkAliasOptionModule [ "systemd" "socket" ] [ "systemd" "sockets" "" ])
+
];
+
options = {
+
systemd.services = mkOption {
+
description = ''
+
This module configures systemd services, with the notable difference that their unit names will be prefixed with the abstract service name.
+
+
This option's value is not suitable for reading, but you can define a module here that interacts with just the unit configuration in the host system configuration.
+
+
Note that this option contains _deferred_ modules.
+
This means that the module has not been combined with the system configuration yet, no values can be read from this option.
+
What you can do instead is define a module that reads from the module arguments (such as `config`) that are available when the module is merged into the system configuration.
+
'';
+
type = types.lazyAttrsOf (
+
types.deferredModuleWith {
+
staticModules = [
+
# TODO: Add modules for the purpose of generating documentation?
+
];
+
}
+
);
+
default = { };
+
};
+
systemd.sockets = mkOption {
+
description = ''
+
Declares systemd socket units. Names will be prefixed by the service name / path.
+
+
See {option}`systemd.services`.
+
'';
+
type = types.lazyAttrsOf types.deferredModule;
+
default = { };
+
};
+
+
# Also import systemd logic into sub-services
+
# extends the portable `services` option
+
services = mkOption {
+
type = types.attrsOf (
+
types.submoduleWith {
+
class = "service";
+
modules = [
+
./service.nix
+
];
+
specialArgs = {
+
inherit systemdPackage;
+
};
+
}
+
);
+
};
+
};
+
config = {
+
# Note that this is the systemd.services option above, not the system one.
+
systemd.services."" = {
+
# TODO description;
+
wantedBy = lib.mkDefault [ "multi-user.target" ];
+
serviceConfig = {
+
Type = lib.mkDefault "simple";
+
Restart = lib.mkDefault "always";
+
RestartSec = lib.mkDefault "5";
+
ExecStart = [
+
(escapeSystemdExecArgs config.process.argv)
+
];
+
};
+
};
+
};
+
}
+90
nixos/modules/system/service/systemd/system.nix
···
+
{
+
lib,
+
config,
+
options,
+
pkgs,
+
...
+
}:
+
+
let
+
inherit (lib)
+
concatMapAttrs
+
mkOption
+
types
+
concatLists
+
mapAttrsToList
+
;
+
+
portable-lib = import ../portable/lib.nix { inherit lib; };
+
+
dash =
+
before: after:
+
if after == "" then
+
before
+
else if before == "" then
+
after
+
else
+
"${before}-${after}";
+
+
makeUnits =
+
unitType: prefix: service:
+
concatMapAttrs (unitName: unitModule: {
+
"${dash prefix unitName}" =
+
{ ... }:
+
{
+
imports = [ unitModule ];
+
};
+
}) service.systemd.${unitType}
+
// concatMapAttrs (
+
subServiceName: subService: makeUnits unitType (dash prefix subServiceName) subService
+
) service.services;
+
in
+
{
+
# First half of the magic: mix systemd logic into the otherwise abstract services
+
options = {
+
system.services = mkOption {
+
description = ''
+
A collection of NixOS [modular services](https://nixos.org/manual/nixos/unstable/#modular-services) that are configured as systemd services.
+
'';
+
type = types.attrsOf (
+
types.submoduleWith {
+
class = "service";
+
modules = [
+
./service.nix
+
];
+
specialArgs = {
+
# perhaps: features."systemd" = { };
+
inherit pkgs;
+
systemdPackage = config.systemd.package;
+
};
+
}
+
);
+
default = { };
+
visible = "shallow";
+
};
+
};
+
+
# Second half of the magic: siphon units that were defined in isolation to the system
+
config = {
+
+
assertions = concatLists (
+
mapAttrsToList (
+
name: cfg: portable-lib.getAssertions (options.system.services.loc ++ [ name ]) cfg
+
) config.system.services
+
);
+
+
warnings = concatLists (
+
mapAttrsToList (
+
name: cfg: portable-lib.getWarnings (options.system.services.loc ++ [ name ]) cfg
+
) config.system.services
+
);
+
+
systemd.services = concatMapAttrs (
+
serviceName: topLevelService: makeUnits "services" serviceName topLevelService
+
) config.system.services;
+
+
systemd.sockets = concatMapAttrs (
+
serviceName: topLevelService: makeUnits "sockets" serviceName topLevelService
+
) config.system.services;
+
};
+
}
+92
nixos/modules/system/service/systemd/test.nix
···
+
# Run:
+
# nix-build -A nixosTests.modularService
+
+
{
+
evalSystem,
+
runCommand,
+
hello,
+
...
+
}:
+
+
let
+
machine = evalSystem (
+
{ lib, ... }:
+
let
+
hello' = lib.getExe hello;
+
in
+
{
+
+
# Test input
+
+
system.services.foo = {
+
process = {
+
argv = [
+
hello'
+
"--greeting"
+
"hoi"
+
];
+
};
+
};
+
system.services.bar = {
+
process = {
+
argv = [
+
hello'
+
"--greeting"
+
"hoi"
+
];
+
};
+
systemd.service = {
+
serviceConfig.X-Bar = "lol crossbar whatever";
+
};
+
services.db = {
+
process = {
+
argv = [
+
hello'
+
"--greeting"
+
"Hi, I'm a database, would you believe it"
+
];
+
};
+
systemd.service = {
+
serviceConfig.RestartSec = "42";
+
};
+
};
+
};
+
+
# irrelevant stuff
+
system.stateVersion = "25.05";
+
fileSystems."/".device = "/test/dummy";
+
boot.loader.grub.enable = false;
+
}
+
);
+
+
inherit (machine.config.system.build) toplevel;
+
in
+
runCommand "test-modular-service-systemd-units"
+
{
+
passthru = {
+
inherit
+
machine
+
toplevel
+
;
+
};
+
}
+
''
+
echo ${toplevel}/etc/systemd/system/foo.service:
+
cat -n ${toplevel}/etc/systemd/system/foo.service
+
(
+
set -x
+
grep -F 'ExecStart="${hello}/bin/hello" "--greeting" "hoi"' ${toplevel}/etc/systemd/system/foo.service >/dev/null
+
+
grep -F 'ExecStart="${hello}/bin/hello" "--greeting" "hoi"' ${toplevel}/etc/systemd/system/bar.service >/dev/null
+
grep -F 'X-Bar=lol crossbar whatever' ${toplevel}/etc/systemd/system/bar.service >/dev/null
+
+
grep 'ExecStart="${hello}/bin/hello" "--greeting" ".*database.*"' ${toplevel}/etc/systemd/system/bar-db.service >/dev/null
+
grep -F 'RestartSec=42' ${toplevel}/etc/systemd/system/bar-db.service >/dev/null
+
+
[[ ! -e ${toplevel}/etc/systemd/system/foo.socket ]]
+
[[ ! -e ${toplevel}/etc/systemd/system/bar.socket ]]
+
[[ ! -e ${toplevel}/etc/systemd/system/bar-db.socket ]]
+
)
+
echo 🐬👍
+
touch $out
+
''
+3
nixos/modules/system/service/systemd/user.nix
···
+
# TBD, analogous to system.nix but for user units
+
{
+
}
+14
nixos/tests/all-tests.nix
···
featureFlags.minimalModules = { };
};
evalMinimalConfig = module: nixosLib.evalModules { modules = [ module ]; };
+
evalSystem =
+
module:
+
import ../lib/eval-config.nix {
+
system = null;
+
modules = [
+
../modules/misc/nixpkgs/read-only.nix
+
{ nixpkgs.pkgs = pkgs; }
+
module
+
];
+
};
inherit
(rec {
···
gerrit = runTest ./gerrit.nix;
geth = runTest ./geth.nix;
ghostunnel = runTest ./ghostunnel.nix;
+
ghostunnel-modular = runTest ./ghostunnel-modular.nix;
gitdaemon = runTest ./gitdaemon.nix;
gitea = handleTest ./gitea.nix { giteaPackage = pkgs.gitea; };
github-runner = runTest ./github-runner.nix;
···
mjolnir = runTest ./matrix/mjolnir.nix;
mobilizon = runTest ./mobilizon.nix;
mod_perl = runTest ./mod_perl.nix;
+
modularService = pkgs.callPackage ../modules/system/service/systemd/test.nix {
+
inherit evalSystem;
+
};
molly-brown = runTest ./molly-brown.nix;
mollysocket = runTest ./mollysocket.nix;
monado = runTest ./monado.nix;
+120
nixos/tests/ghostunnel-modular.nix
···
+
{ hostPkgs, lib, ... }:
+
{
+
_class = "nixosTest";
+
name = "ghostunnel";
+
nodes = {
+
backend =
+
{ pkgs, ... }:
+
{
+
services.nginx.enable = true;
+
services.nginx.virtualHosts."backend".root = pkgs.runCommand "webroot" { } ''
+
mkdir $out
+
echo hi >$out/hi.txt
+
'';
+
networking.firewall.allowedTCPPorts = [ 80 ];
+
};
+
service =
+
{ pkgs, ... }:
+
{
+
system.services."ghostunnel-plain-old" = {
+
imports = [ pkgs.ghostunnel.services.default ];
+
ghostunnel = {
+
listen = "0.0.0.0:443";
+
cert = "/root/service-cert.pem";
+
key = "/root/service-key.pem";
+
disableAuthentication = true;
+
target = "backend:80";
+
unsafeTarget = true;
+
};
+
};
+
system.services."ghostunnel-client-cert" = {
+
imports = [ pkgs.ghostunnel.services.default ];
+
ghostunnel = {
+
listen = "0.0.0.0:1443";
+
cert = "/root/service-cert.pem";
+
key = "/root/service-key.pem";
+
cacert = "/root/ca.pem";
+
target = "backend:80";
+
allowCN = [ "client" ];
+
unsafeTarget = true;
+
};
+
};
+
networking.firewall.allowedTCPPorts = [
+
443
+
1443
+
];
+
};
+
client =
+
{ pkgs, ... }:
+
{
+
environment.systemPackages = [
+
pkgs.curl
+
];
+
};
+
};
+
+
testScript = ''
+
+
# prepare certificates
+
+
def cmd(command):
+
print(f"+{command}")
+
r = os.system(command)
+
if r != 0:
+
raise Exception(f"Command {command} failed with exit code {r}")
+
+
# Create CA
+
cmd("${hostPkgs.openssl}/bin/openssl genrsa -out ca-key.pem 4096")
+
cmd("${hostPkgs.openssl}/bin/openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -subj '/C=NL/ST=Zuid-Holland/L=The Hague/O=Stevige Balken en Planken B.V./OU=OpSec/CN=Certificate Authority' -out ca.pem")
+
+
# Create service
+
cmd("${hostPkgs.openssl}/bin/openssl genrsa -out service-key.pem 4096")
+
cmd("${hostPkgs.openssl}/bin/openssl req -subj '/CN=service' -sha256 -new -key service-key.pem -out service.csr")
+
cmd("echo subjectAltName = DNS:service,IP:127.0.0.1 >> extfile.cnf")
+
cmd("echo extendedKeyUsage = serverAuth >> extfile.cnf")
+
cmd("${hostPkgs.openssl}/bin/openssl x509 -req -days 365 -sha256 -in service.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out service-cert.pem -extfile extfile.cnf")
+
+
# Create client
+
cmd("${hostPkgs.openssl}/bin/openssl genrsa -out client-key.pem 4096")
+
cmd("${hostPkgs.openssl}/bin/openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr")
+
cmd("echo extendedKeyUsage = clientAuth > extfile-client.cnf")
+
cmd("${hostPkgs.openssl}/bin/openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile extfile-client.cnf")
+
+
cmd("ls -al")
+
+
start_all()
+
+
# Configuration
+
service.copy_from_host("ca.pem", "/root/ca.pem")
+
service.copy_from_host("service-cert.pem", "/root/service-cert.pem")
+
service.copy_from_host("service-key.pem", "/root/service-key.pem")
+
client.copy_from_host("ca.pem", "/root/ca.pem")
+
client.copy_from_host("service-cert.pem", "/root/service-cert.pem")
+
client.copy_from_host("client-cert.pem", "/root/client-cert.pem")
+
client.copy_from_host("client-key.pem", "/root/client-key.pem")
+
+
backend.wait_for_unit("nginx.service")
+
service.wait_for_unit("multi-user.target")
+
service.wait_for_unit("multi-user.target")
+
client.wait_for_unit("multi-user.target")
+
+
# Check assumptions before the real test
+
client.succeed("bash -c 'diff <(curl -v --no-progress-meter http://backend/hi.txt) <(echo hi)'")
+
+
# Plain old simple TLS can connect, ignoring cert
+
client.succeed("bash -c 'diff <(curl -v --no-progress-meter --insecure https://service/hi.txt) <(echo hi)'")
+
+
# Plain old simple TLS provides correct signature with its cert
+
client.succeed("bash -c 'diff <(curl -v --no-progress-meter --cacert /root/ca.pem https://service/hi.txt) <(echo hi)'")
+
+
# Client can authenticate with certificate
+
client.succeed("bash -c 'diff <(curl -v --no-progress-meter --cert /root/client-cert.pem --key /root/client-key.pem --cacert /root/ca.pem https://service:1443/hi.txt) <(echo hi)'")
+
+
# Client must authenticate with certificate
+
client.fail("bash -c 'diff <(curl -v --no-progress-meter --cacert /root/ca.pem https://service:1443/hi.txt) <(echo hi)'")
+
'';
+
+
meta.maintainers = with lib.maintainers; [
+
roberth
+
];
+
}
+13
pkgs/applications/editors/vim/plugins/generated.nix
···
meta.hydraPlatforms = [ ];
+
opencode-nvim = buildVimPlugin {
+
pname = "opencode.nvim";
+
version = "2025-07-24";
+
src = fetchFromGitHub {
+
owner = "NickvanDyke";
+
repo = "opencode.nvim";
+
rev = "db3aa9ca3b738600c81e29646a3356477dabaa87";
+
sha256 = "1yhspgja3zdnsf8r3ahci14cndk3bzxvq0w9jqggd7ya103nq6kz";
+
};
+
meta.homepage = "https://github.com/NickvanDyke/opencode.nvim/";
+
meta.hydraPlatforms = [ ];
+
};
+
openingh-nvim = buildVimPlugin {
pname = "openingh.nvim";
version = "2025-05-01";
+1
pkgs/applications/editors/vim/plugins/vim-plugin-names
···
https://github.com/rmehri01/onenord.nvim/,main,
https://github.com/tyru/open-browser-github.vim/,,
https://github.com/tyru/open-browser.vim/,,
+
https://github.com/NickvanDyke/opencode.nvim/,HEAD,
https://github.com/Almo7aya/openingh.nvim/,,
https://github.com/salkin-mada/openscad.nvim/,HEAD,
https://github.com/chipsenkbeil/org-roam.nvim/,HEAD,
+3
pkgs/applications/video/olive-editor/default.nix
···
hash = "sha256-I2/JPmUBDb0bw7qbSZcAkYHB2q2Uo7En7ZurMwWhg/M=";
}
);
+
+
# robin-map headers require c++17
+
cmakeFlags = (old.cmakeFlags or [ ]) ++ [ (lib.cmakeFeature "CMAKE_CXX_STANDARD" "17") ];
});
in
+2 -2
pkgs/by-name/as/astyle/package.nix
···
stdenv.mkDerivation rec {
pname = "astyle";
-
version = "3.6.9";
+
version = "3.6.10";
src = fetchurl {
url = "mirror://sourceforge/${pname}/${pname}-${version}.tar.bz2";
-
hash = "sha256-tkRZdlTfW0AIe+SkZyPGUED3zlnzNp8bj2kPnBDKurw=";
+
hash = "sha256-HW7onAhKk93MKNGgVs2o0cNX0xjvjihEVtnwvSzrS20=";
};
nativeBuildInputs = [ cmake ];
+2 -2
pkgs/by-name/bl/blender/package.nix
···
opencolorio,
openexr,
openimagedenoise,
-
openimageio_2,
+
openimageio,
openjpeg,
openpgl,
opensubdiv,
···
(manifold.override { tbb_2021 = tbb; })
opencolorio
openexr
-
openimageio_2
+
openimageio
openjpeg
(openpgl.override { inherit tbb; })
(opensubdiv.override { inherit cudaSupport; })
+3 -3
pkgs/by-name/ch/chhoto-url/package.nix
···
rustPlatform.buildRustPackage (finalAttrs: {
pname = "chhoto-url";
-
version = "6.2.10";
+
version = "6.2.11";
src = fetchFromGitHub {
owner = "SinTan1729";
repo = "chhoto-url";
tag = finalAttrs.version;
-
hash = "sha256-56tbSOoYRtmRzKqRDe951JXOlPymRGtEyGSZ0dWXOcw=";
+
hash = "sha256-3VQmTQ6ZlDTRL3nx/sQxWLKgW8ee0Ts+C1CiWkiX2/g=";
};
sourceRoot = "${finalAttrs.src.name}/actix";
···
--replace-fail "./resources/" "${placeholder "out"}/share/chhoto-url/resources/"
'';
-
cargoHash = "sha256-z5BFo6X3Lpb/PJPMQ+3m1RozvXeHLaY81PABAE7gTTA=";
+
cargoHash = "sha256-QIqLzk/vAOrW0ain0Oq9tnqzCSyK4yDOYsjmil3xPc4=";
postInstall = ''
mkdir -p $out/share/chhoto-url
+2 -2
pkgs/by-name/ch/chroma/package.nix
···
buildGoModule rec {
pname = "chroma";
-
version = "2.15.0";
+
version = "2.19.0";
# To update:
# nix-prefetch-git --rev v${version} https://github.com/alecthomas/chroma.git > src.json
···
inherit (srcInfo) sha256;
};
-
vendorHash = "sha256:14jg809xz647yv6sc8rnnksg2bpnn75panj8a2kdk2v87yrpq2zr";
+
vendorHash = "sha256-Gqldcp68Rn4wkfQptbmKUjkwLSb+qaFboJNfmWVkrPU=";
modRoot = "./cmd/chroma";
+5 -5
pkgs/by-name/ch/chroma/src.json
···
{
"url": "https://github.com/alecthomas/chroma.git",
-
"rev": "009385f9487ee14c8a54e49aaf4331fea0830310",
-
"date": "2024-12-30T09:27:18+11:00",
-
"path": "/nix/store/rr2cj4bmlfw803diwyfpbrpai35gifaw-chroma",
-
"sha256": "088w3aixwfk8s04iyb2mjn3kx5dl3gb9q14jzawabcdy2ar7iijn",
-
"hash": "sha256-VsZ4shK+saW4+pIEnNYbtJU+h5VVLB8J0Gg63qMaHCE=",
+
"rev": "adeac8f5dbfb6806a51bcf07eefd89fc8a0aee6a",
+
"date": "2025-07-01T09:59:45+10:00",
+
"path": "/nix/store/063ldbczafhxq02g5n28bxr1xnl6fwgd-chroma",
+
"sha256": "1r50gqbizi7l1l07syx9wgfyx1k8gzspmsbpk42jnwgw3h9dcw42",
+
"hash": "sha256-gnDWEhz8cSsFmXfpevV/aIbu3eOpe30ADfTEHxd+oOQ=",
"fetchLFS": false,
"fetchSubmodules": false,
"deepClone": false,
+2 -2
pkgs/by-name/gh/gh-f/package.nix
···
in
stdenvNoCC.mkDerivation rec {
pname = "gh-f";
-
version = "1.3.0";
+
version = "1.4.0";
src = fetchFromGitHub {
owner = "gennaro-tedesco";
repo = "gh-f";
rev = "v${version}";
-
hash = "sha256-CW6iAI5IomJoMuPBFq/3owhZJbcruKtOqoxzsh+FNVw=";
+
hash = "sha256-JlMJ5RplEtQ8ApN3x1Sl0Lkutb5kLpuMJrF96oKZC9k=";
};
nativeBuildInputs = [
+6
pkgs/by-name/gh/ghostunnel/package.nix
···
fetchFromGitHub,
lib,
nixosTests,
+
ghostunnel,
apple-sdk_12,
darwinMinVersionHook,
}:
···
passthru.tests = {
nixos = nixosTests.ghostunnel;
podman = nixosTests.podman-tls-ghostunnel;
+
};
+
+
passthru.services.default = {
+
imports = [ ./service.nix ];
+
ghostunnel.package = ghostunnel; # FIXME: finalAttrs.finalPackage
};
meta = {
+241
pkgs/by-name/gh/ghostunnel/service.nix
···
+
{
+
lib,
+
config,
+
options,
+
pkgs,
+
...
+
}:
+
let
+
inherit (lib)
+
concatStringsSep
+
getExe
+
mkDefault
+
mkIf
+
mkOption
+
optional
+
types
+
;
+
cfg = config.ghostunnel;
+
+
in
+
{
+
# https://nixos.org/manual/nixos/unstable/#modular-services
+
_class = "service";
+
options = {
+
ghostunnel = {
+
package = mkOption {
+
description = "Package to use for ghostunnel";
+
type = types.package;
+
};
+
+
listen = mkOption {
+
description = ''
+
Address and port to listen on (can be HOST:PORT, unix:PATH).
+
'';
+
type = types.str;
+
};
+
+
target = mkOption {
+
description = ''
+
Address to forward connections to (can be HOST:PORT or unix:PATH).
+
'';
+
type = types.str;
+
};
+
+
keystore = mkOption {
+
description = ''
+
Path to keystore (combined PEM with cert/key, or PKCS12 keystore).
+
+
NB: storepass is not supported because it would expose credentials via `/proc/*/cmdline`.
+
+
Specify this or `cert` and `key`.
+
'';
+
type = types.nullOr types.str;
+
default = null;
+
};
+
+
cert = mkOption {
+
description = ''
+
Path to certificate (PEM with certificate chain).
+
+
Not required if `keystore` is set.
+
'';
+
type = types.nullOr types.str;
+
default = null;
+
};
+
+
key = mkOption {
+
description = ''
+
Path to certificate private key (PEM with private key).
+
+
Not required if `keystore` is set.
+
'';
+
type = types.nullOr types.str;
+
default = null;
+
};
+
+
cacert = mkOption {
+
description = ''
+
Path to CA bundle file (PEM/X509). Uses system trust store if `null`.
+
'';
+
type = types.nullOr types.str;
+
};
+
+
disableAuthentication = mkOption {
+
description = ''
+
Disable client authentication, no client certificate will be required.
+
'';
+
type = types.bool;
+
default = false;
+
};
+
+
allowAll = mkOption {
+
description = ''
+
If true, allow all clients, do not check client cert subject.
+
'';
+
type = types.bool;
+
default = false;
+
};
+
+
allowCN = mkOption {
+
description = ''
+
Allow client if common name appears in the list.
+
'';
+
type = types.listOf types.str;
+
default = [ ];
+
};
+
+
allowOU = mkOption {
+
description = ''
+
Allow client if organizational unit name appears in the list.
+
'';
+
type = types.listOf types.str;
+
default = [ ];
+
};
+
+
allowDNS = mkOption {
+
description = ''
+
Allow client if DNS subject alternative name appears in the list.
+
'';
+
type = types.listOf types.str;
+
default = [ ];
+
};
+
+
allowURI = mkOption {
+
description = ''
+
Allow client if URI subject alternative name appears in the list.
+
'';
+
type = types.listOf types.str;
+
default = [ ];
+
};
+
+
extraArguments = mkOption {
+
description = "Extra arguments to pass to `ghostunnel server`";
+
type = types.listOf types.str;
+
default = [ ];
+
};
+
+
unsafeTarget = mkOption {
+
description = ''
+
If set, does not limit target to localhost, 127.0.0.1, [::1], or UNIX sockets.
+
+
This is meant to protect against accidental unencrypted traffic on
+
untrusted networks.
+
'';
+
type = types.bool;
+
default = false;
+
};
+
};
+
};
+
+
config = {
+
assertions = [
+
{
+
message = ''
+
At least one access control flag is required.
+
Set at least one of:
+
- ${options.ghostunnel.disableAuthentication}
+
- ${options.ghostunnel.allowAll}
+
- ${options.ghostunnel.allowCN}
+
- ${options.ghostunnel.allowOU}
+
- ${options.ghostunnel.allowDNS}
+
- ${options.ghostunnel.allowURI}
+
'';
+
assertion =
+
cfg.disableAuthentication
+
|| cfg.allowAll
+
|| cfg.allowCN != [ ]
+
|| cfg.allowOU != [ ]
+
|| cfg.allowDNS != [ ]
+
|| cfg.allowURI != [ ];
+
}
+
];
+
+
ghostunnel = {
+
# Clients should not be authenticated with the public root certificates
+
# (afaict, it doesn't make sense), so we only provide that default when
+
# client cert auth is disabled.
+
cacert = mkIf cfg.disableAuthentication (mkDefault null);
+
};
+
+
# TODO assertions
+
+
process = {
+
argv =
+
# Use a shell if credentials need to be pulled from the environment.
+
optional
+
(builtins.any (v: v != null) [
+
cfg.keystore
+
cfg.cert
+
cfg.key
+
cfg.cacert
+
])
+
(
+
pkgs.writeScript "load-credentials" ''
+
#!${pkgs.runtimeShell}
+
exec $@ ${
+
concatStringsSep " " (
+
optional (cfg.keystore != null) "--keystore=$CREDENTIALS_DIRECTORY/keystore"
+
++ optional (cfg.cert != null) "--cert=$CREDENTIALS_DIRECTORY/cert"
+
++ optional (cfg.key != null) "--key=$CREDENTIALS_DIRECTORY/key"
+
++ optional (cfg.cacert != null) "--cacert=$CREDENTIALS_DIRECTORY/cacert"
+
)
+
}
+
''
+
)
+
++ [
+
(getExe cfg.package)
+
"server"
+
"--listen"
+
cfg.listen
+
"--target"
+
cfg.target
+
]
+
++ optional cfg.allowAll "--allow-all"
+
++ map (v: "--allow-cn=${v}") cfg.allowCN
+
++ map (v: "--allow-ou=${v}") cfg.allowOU
+
++ map (v: "--allow-dns=${v}") cfg.allowDNS
+
++ map (v: "--allow-uri=${v}") cfg.allowURI
+
++ optional cfg.disableAuthentication "--disable-authentication"
+
++ optional cfg.unsafeTarget "--unsafe-target"
+
++ cfg.extraArguments;
+
};
+
+
# refine the service
+
systemd.service = {
+
after = [ "network.target" ];
+
wants = [ "network.target" ];
+
wantedBy = [ "multi-user.target" ];
+
serviceConfig = {
+
Restart = "always";
+
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+
DynamicUser = true;
+
LoadCredential =
+
optional (cfg.keystore != null) "keystore:${cfg.keystore}"
+
++ optional (cfg.cert != null) "cert:${cfg.cert}"
+
++ optional (cfg.key != null) "key:${cfg.key}"
+
++ optional (cfg.cacert != null) "cacert:${cfg.cacert}";
+
};
+
};
+
};
+
}
+3 -3
pkgs/by-name/gi/gickup/package.nix
···
buildGoModule rec {
pname = "gickup";
-
version = "0.10.38";
+
version = "0.10.39";
src = fetchFromGitHub {
owner = "cooperspencer";
repo = "gickup";
tag = "v${version}";
-
hash = "sha256-vthr4nkwuhvGXxH2P0uHeuQpjQFNTpGFHF+eXG2jiqk=";
+
hash = "sha256-Aalt/oiNzV2a8Ix/ruL4r3q0W1EY1UTe9IVPWNL+lLA=";
};
-
vendorHash = "sha256-RtuEpvux+8oJ829WEvz5OPfnYvFCdNo/9GCXhjXurRM=";
+
vendorHash = "sha256-Xtreh7nHovBYh0PnFYn2VuYGN8GQSmy6EPnZnHSdt/o=";
ldflags = [ "-X main.version=${version}" ];
+2 -2
pkgs/by-name/gp/gpupad/package.nix
···
glslang,
imath,
ktx-tools,
-
openimageio_2,
+
openimageio,
qt6Packages,
spdlog,
spirv-cross,
···
glslang
imath # needed for openimageio
ktx-tools
-
openimageio_2
+
openimageio
qt6Packages.qtbase
qt6Packages.qtdeclarative
qt6Packages.qtmultimedia
+3 -3
pkgs/by-name/in/inputplumber/package.nix
···
rustPlatform.buildRustPackage rec {
pname = "inputplumber";
-
version = "0.60.2";
+
version = "0.60.7";
src = fetchFromGitHub {
owner = "ShadowBlip";
repo = "InputPlumber";
tag = "v${version}";
-
hash = "sha256-zcy9scs7oRRLKm/FL6BfO64IstWY4HmTRxG/jJG0jLw=";
+
hash = "sha256-3o5Y6fbshC3oTerf8M+yuo01BbQAilkT7TdrlwO6YBs=";
};
useFetchCargoVendor = true;
-
cargoHash = "sha256-fw7pM6HSy/8fNTYu7MqKiTl/2jdyDOLDBNhd0rpzb6M=";
+
cargoHash = "sha256-Tk3NCcturMHIs9hdGqwC87kqnhg/PvriCNSkYcq9+aM=";
nativeBuildInputs = [
pkg-config
+2 -2
pkgs/by-name/li/libdwarf/package.nix
···
stdenv.mkDerivation (finalAttrs: {
pname = "libdwarf";
-
version = "2.0.0";
+
version = "2.1.0";
src = fetchFromGitHub {
owner = "davea42";
repo = "libdwarf-code";
tag = "v${finalAttrs.version}";
-
hash = "sha256-SsFg+7zGBEGxDSzfiIP5bxdttlBkhEiEQWaU12hINas=";
+
hash = "sha256-Q+ke5vRSBFZirCIBu8M88LzBQW851kjkW4vUgE89ejQ=";
};
nativeBuildInputs = [
+4 -4
pkgs/by-name/ma/maa-assistant-arknights/pin.json
···
{
"stable": {
-
"version": "5.18.3",
-
"hash": "sha256-we4mWtMemszIpTehk74hbqjisX1vTk94tLdGGNiz4c8="
+
"version": "5.20.0",
+
"hash": "sha256-XqzCxzmNJHG+aYBJoeAAryFx3XctrGBk6QqoonCbrWU="
},
"beta": {
-
"version": "5.18.3",
-
"hash": "sha256-we4mWtMemszIpTehk74hbqjisX1vTk94tLdGGNiz4c8="
+
"version": "5.20.0",
+
"hash": "sha256-XqzCxzmNJHG+aYBJoeAAryFx3XctrGBk6QqoonCbrWU="
}
}
+3 -3
pkgs/by-name/me/mergiraf/package.nix
···
rustPlatform.buildRustPackage (finalAttrs: {
pname = "mergiraf";
-
version = "0.12.1";
+
version = "0.13.0";
src = fetchFromGitea {
domain = "codeberg.org";
owner = "mergiraf";
repo = "mergiraf";
tag = "v${finalAttrs.version}";
-
hash = "sha256-09C5A9ToH3zzUlUcLDd/5wOOkWs4jmjaqI9HpzGebUU=";
+
hash = "sha256-MPmpS4iLur05jkSUrGl6NCtzRO/8Pch9pRNuT6psNRo=";
};
useFetchCargoVendor = true;
-
cargoHash = "sha256-TFGFHK35pary9nGG3XB474Bv2B8YW2X06NvInBLmcIA=";
+
cargoHash = "sha256-nT9HsG9eRBf4mRr7fqmRSQVI+yz+yr7wKCSQHG5JtD4=";
nativeCheckInputs = [ git ];
+1 -1
pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/redirects.py
···
- The first element of an identifier's redirects list must denote its current location.
"""
xref_targets = {}
-
ignored_identifier_patterns = ("opt-", "auto-generated-", "function-library-")
+
ignored_identifier_patterns = ("opt-", "auto-generated-", "function-library-", "service-opt-", "systemd-service-opt")
for id, target in initial_xref_targets.items():
# filter out automatically generated identifiers from module options and library documentation
if id.startswith(ignored_identifier_patterns):
+4 -4
pkgs/by-name/ol/olympus-unwrapped/package.nix
···
phome = "$out/lib/olympus";
# The following variables are to be updated by the update script.
-
version = "25.07.12.01";
-
buildId = "4934"; # IMPORTANT: This line is matched with regex in update.sh.
-
rev = "17634d29b91b737580c878ba96f73bd077fbfba0";
+
version = "25.07.23.01";
+
buildId = "4972"; # IMPORTANT: This line is matched with regex in update.sh.
+
rev = "2d4876fa93063df39ba8e2d6c97b57223f7b3b4f";
in
buildDotnetModule {
pname = "olympus-unwrapped";
···
owner = "EverestAPI";
repo = "Olympus";
fetchSubmodules = true; # Required. See upstream's README.
-
hash = "sha256-Z6OWO6WCHhmmGI8dF23yiLNBy11Mutu941jY/0pxIkQ=";
+
hash = "sha256-30Lir9erklCPIEsreIWwjrSkuZtr5mJpqxXAMXawYyk=";
};
nativeBuildInputs = [
+2 -2
pkgs/by-name/op/opengamepadui/package.nix
···
stdenv.mkDerivation (finalAttrs: {
pname = "opengamepadui";
-
version = "0.40.3";
+
version = "0.40.4";
buildType = if withDebug then "debug" else "release";
···
owner = "ShadowBlip";
repo = "OpenGamepadUI";
tag = "v${finalAttrs.version}";
-
hash = "sha256-ggCVNWh36q/clYMzObhhxU39qacWSb6urgXOI9yfQeo=";
+
hash = "sha256-o6n3b4dh3IHaRk2Zi7rt3gzKTZWt6s9L9WcG0WoCQ3U=";
};
cargoDeps = rustPlatform.fetchCargoVendor {
-15
pkgs/by-name/op/openimageio/2.nix
···
-
{ fetchFromGitHub, openimageio }:
-
-
let
-
version = "2.5.17.0";
-
in
-
openimageio.overrideAttrs {
-
inherit version;
-
-
src = fetchFromGitHub {
-
owner = "AcademySoftwareFoundation";
-
repo = "OpenImageIO";
-
tag = "v${version}";
-
hash = "sha256-d5LqRcqWj6E9jJYY/Pa5e7/MeuQGMjUo/hMCYRKsKeU=";
-
};
-
}
+4 -13
pkgs/by-name/pc/pcsx2/package.nix
···
libwebp,
llvmPackages,
lz4,
-
makeWrapper,
pkg-config,
qt6,
shaderc,
···
pcsx2_patches = fetchFromGitHub {
owner = "PCSX2";
repo = "pcsx2_patches";
-
rev = "6448ff90bbf2fddb4498dcfdae0e6d3ec8c23479";
-
hash = "sha256-ZXAZekllZHYjfU1q1QrbEdRlRAUAB6VOXLeAfn1GqW0=";
+
rev = "9b193aa0a61f5e93d3bd4124b111e8f296ef9fa8";
+
hash = "sha256-1hhdjFxJCNfeO/FIAnjRHESfiyzkErYddZqpRxzG7VQ=";
};
inherit (qt6)
···
in
llvmPackages.stdenv.mkDerivation (finalAttrs: {
pname = "pcsx2";
-
version = "2.3.424";
+
version = "2.4.0";
src = fetchFromGitHub {
pname = "pcsx2-source";
owner = "PCSX2";
repo = "pcsx2";
tag = "v${finalAttrs.version}";
-
hash = "sha256-EdFkSsat6O/1tXtJVHOPviseSaixd5LB1TNtfqhqR1E=";
+
hash = "sha256-R+BdywkZKxR/+Z+o1512O3A1mg9A6s7i+JZjFyUbJVs=";
};
patches = [
···
preFixup = ''
qtWrapperArgs+=("''${gappsWrapperArgs[@]}")
-
'';
-
-
# https://github.com/PCSX2/pcsx2/pull/10200
-
# Can't avoid the double wrapping, the binary wrapper from qtWrapperArgs doesn't support --run
-
postFixup = ''
-
source "${makeWrapper}/nix-support/setup-hook"
-
wrapProgram $out/bin/pcsx2-qt \
-
--run 'if [[ -z $I_WANT_A_BROKEN_WAYLAND_UI ]]; then export QT_QPA_PLATFORM=xcb; fi'
'';
passthru = {
+8 -4
pkgs/by-name/pc/pcsx2/update.sh
···
#!/usr/bin/env nix-shell
-
#!nix-shell -i bash -p bash nix-update common-updater-scripts coreutils
+
#!nix-shell -i bash -p bash nix-update common-updater-scripts coreutils jq
set -ex
-
latestRev=`git ls-remote -b https://github.com/PCSX2/pcsx2_patches main | cut -f1`
+
latestPatchesRev=`git ls-remote -b https://github.com/PCSX2/pcsx2_patches main | cut -f1`
update-source-version pcsx2 \
--ignore-same-version \
-
--rev=$latestRev \
+
--rev=$latestPatchesRev \
--source-key=pcsx2_patches
-
nix-update --version=unstable pcsx2
+
+
latestVersion="`curl "https://api.github.com/repos/PCSX2/pcsx2/releases/latest" \
+
| jq -r ".tag_name[1:]"`"
+
+
nix-update pcsx2 --version=$latestVersion
+3 -3
pkgs/by-name/pl/playwright-mcp/package.nix
···
buildNpmPackage rec {
pname = "playwright-mcp";
-
version = "0.0.29";
+
version = "0.0.31";
src = fetchFromGitHub {
owner = "Microsoft";
repo = "playwright-mcp";
tag = "v${version}";
-
hash = "sha256-owSoE3+jSg09dFpM5wv7FJovzsX5ZMp/9IIQhkmSZt0=";
+
hash = "sha256-Hw4OUZCHoquX6Ixv7GlsHcKxqOdJEQYfuDPzqYkVNAk=";
};
-
npmDepsHash = "sha256-jweIBhlVci8CFBIYlFp0opc1ilWMcHt0is4qgTiYNcQ=";
+
npmDepsHash = "sha256-70/t/mgSBwMv9C3VusbjIMMyy3e3npxQLXqKbdL9xa4=";
postInstall = ''
rm -r $out/lib/node_modules/@playwright/mcp/node_modules/playwright
+3 -3
pkgs/by-name/re/redpanda-client/package.nix
···
stdenv,
}:
let
-
version = "25.1.7";
+
version = "25.1.9";
src = fetchFromGitHub {
owner = "redpanda-data";
repo = "redpanda";
rev = "v${version}";
-
sha256 = "sha256-GRWLEzf0YfSk96oDCuthMNmu0C1KJCk10Uz7eApS4mk=";
+
sha256 = "sha256-X7pBbR2XCyHB4V0Z/PjZ10o/heXswyhzVj1yp+jvUEM=";
};
in
buildGoModule rec {
···
inherit doCheck src version;
modRoot = "./src/go/rpk";
runVend = false;
-
vendorHash = "sha256-DevAHiNcxSbgNwr2Jm7yXhNWflXvqWZOlaYHj+xY0Tw=";
+
vendorHash = "sha256-I/jUlOYUXOSmAD2r8lBlnEBYlxf+V6gSICgnMXosP+4=";
ldflags = [
''-X "github.com/redpanda-data/redpanda/src/go/rpk/pkg/cli/cmd/version.version=${version}"''
+2 -2
pkgs/by-name/ro/robin-map/package.nix
···
stdenv.mkDerivation rec {
pname = "robin-map";
-
version = "1.3.0";
+
version = "1.4.0";
src = fetchFromGitHub {
owner = "Tessil";
repo = "robin-map";
tag = "v${version}";
-
hash = "sha256-dspOWp/8oNR0p5XRnqO7WtPcCx54/y8m1cDho4UBYyc=";
+
hash = "sha256-Hkgxiq2i0TuqMK/bI5OMOn3LkmSE40NimDjK1FBZpsA=";
};
nativeBuildInputs = [
+2 -2
pkgs/by-name/sa/saga/package.nix
···
stdenv.mkDerivation rec {
pname = "saga";
-
version = "9.9.0";
+
version = "9.9.1";
src = fetchurl {
url = "mirror://sourceforge/saga-gis/saga-${version}.tar.gz";
-
hash = "sha256-xS9h8QGm6PH8rx0qXmvolDpH9fy8ma7HlBVbQo5pX4Q=";
+
hash = "sha256-InypyVCk08tsByKaIBRFWldwRz1AkNCgFD3DL4OG84w=";
};
sourceRoot = "saga-${version}/saga-gis";
+6 -2
pkgs/development/beam-modules/elixir-ls/launch.sh.patch
···
diff --git c/scripts/launch.sh w/scripts/launch.sh
-
index 21afbb1e..6b61f0b4 100755
+
index 21afbb1e..8bc5c382 100755
--- c/scripts/launch.sh
+++ w/scripts/launch.sh
@@ -1,125 +1,4 @@
···
# In case that people want to tweak the path, which Elixir to use, or
# whatever prior to launching the language server or the debug adapter, we
-
@@ -138,29 +17,18 @@ fi
+
@@ -138,29 +17,22 @@ fi
# script so we can correctly configure the Erlang library path to
# include the local .ez files, and then do what we were asked to do.
···
+# ensure elixir stdlib can be found
+ELX_STDLIB_PATH=${ELX_STDLIB_PATH:-@elixir@/lib/elixir}
+export ELX_STDLIB_PATH
+
+
+
+# ensure our elixir is in the path
+
+PATH="@elixir@/bin:$PATH"
+
+export PATH
+
+source "$SCRIPTPATH/exec.bash"
+2 -2
pkgs/development/libraries/embree/2.x.nix
···
ispc,
tbb_2020,
glfw,
-
openimageio_2,
+
openimageio,
libjpeg,
libpng,
libpthreadstubs,
···
# tbb_2021 is not backward compatible
tbb_2020
glfw
-
openimageio_2
+
openimageio
libjpeg
libpng
libX11
+4
pkgs/development/libraries/libinput/default.nix
···
maintainers = with maintainers; [ codyopel ];
teams = [ teams.freedesktop ];
changelog = "https://gitlab.freedesktop.org/libinput/libinput/-/releases/${version}";
+
badPlatforms = [
+
# Mandatory shared library.
+
lib.systems.inspect.platformPatterns.isStatic
+
];
};
}
+30 -6
pkgs/development/python-modules/imageio/default.nix
···
buildPythonPackage,
fetchFromGitHub,
isPyPy,
-
replaceVars,
# build-system
setuptools,
···
# tests
pytestCheckHook,
+
gitMinimal,
fsspec,
}:
+
let
+
test_images = fetchFromGitHub {
+
owner = "imageio";
+
repo = "test_images";
+
rev = "f676c96b1af7e04bb1eed1e4551e058eb2f14acd";
+
leaveDotGit = true;
+
hash = "sha256-Kh8DowuhcCT5C04bE5yJa2C+efilLxP0AM31XjnHRf4=";
+
};
+
libgl = "${libGL.out}/lib/libGL${stdenv.hostPlatform.extensions.sharedLibrary}";
+
in
+
buildPythonPackage rec {
pname = "imageio";
version = "2.37.0";
···
hash = "sha256-/nxJxZrTYX7F2grafIWwx9SyfR47ZXyaUwPHMEOdKkI=";
};
-
patches = lib.optionals (!stdenv.hostPlatform.isDarwin) [
-
(replaceVars ./libgl-path.patch {
-
libgl = "${libGL.out}/lib/libGL${stdenv.hostPlatform.extensions.sharedLibrary}";
-
})
-
];
+
postPatch = lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
+
substituteInPlace tests/test_core.py \
+
--replace-fail 'ctypes.util.find_library("GL")' '"${libgl}"'
+
'';
build-system = [ setuptools ];
···
nativeCheckInputs = [
fsspec
+
gitMinimal
psutil
pytestCheckHook
]
++ fsspec.optional-dependencies.github
++ lib.flatten (builtins.attrValues optional-dependencies);
+
pytestFlags = [ "--test-images=file://${test_images}" ];
+
+
# These should have had `needs_internet` mark applied but don't so far.
+
# See https://github.com/imageio/imageio/pull/1142
+
disabledTests = [
+
"test_read_stream"
+
"test_uri_reading"
+
"test_trim_filter"
+
];
+
disabledTestMarks = [ "needs_internet" ];
+
+
# These tests require the old and vulnerable freeimage binaries; skip.
+
disabledTestPaths = [ "tests/test_freeimage.py" ];
preCheck = ''
export IMAGEIO_USERDIR=$(mktemp -d)
-13
pkgs/development/python-modules/imageio/libgl-path.patch
···
-
diff --git a/tests/test_core.py b/tests/test_core.py
-
index 2cdbb3a..032974c 100644
-
--- a/tests/test_core.py
-
+++ b/tests/test_core.py
-
@@ -129,7 +129,7 @@ def test_findlib2():
-
open(os.path.join(fi_dir, "notalib.test.so"), "wb")
-
-
# Loading libs
-
- gllib = ctypes.util.find_library("GL")
-
+ gllib = "@libgl@"
-
core.load_lib([gllib], [])
-
# Fail
-
raises(ValueError, core.load_lib, [], []) # Nothing given
+5 -13
pkgs/development/python-modules/materialx/default.nix
···
libX11,
libXt,
libGL,
-
openimageio_2,
+
openimageio,
imath,
python,
apple-sdk_14,
···
buildPythonPackage rec {
pname = "materialx";
-
version = "1.38.10";
+
version = "1.39.3";
-
# nixpkgs-update: no auto update
-
# Updates are disabled due to API breakage in 1.39+ that breaks almost all
-
# consumers.
src = fetchFromGitHub {
owner = "AcademySoftwareFoundation";
repo = "MaterialX";
rev = "v${version}";
-
hash = "sha256-/kMHmW2dptZNtjuhE5s+jvPRIdtY+FRiVtMU+tiBgQo=";
+
hash = "sha256-ceVYD/dyb3SEEENoJZxjn94DGmUj6IYSNLjsJvmPM84=";
};
format = "other";
···
];
buildInputs = [
-
openimageio_2
+
openimageio
imath
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
···
cmakeFlags = [
(lib.cmakeBool "MATERIALX_BUILD_OIIO" true)
+
(lib.cmakeBool "MATERIALX_BUILD_SHARED_LIBS" true)
(lib.cmakeBool "MATERIALX_BUILD_PYTHON" true)
(lib.cmakeBool "MATERIALX_BUILD_GEN_MSL" (
stdenv.hostPlatform.isLinux || stdenv.hostPlatform.isDarwin
···
# required for cmake to find the bindings, when included in other projects
ln -s $out/python $target_dir
'';
-
-
# Update to 1.39 has major API changes and downstream software
-
# needs to adapt, first. So, do not include in mass updates. For reference, see
-
# https://github.com/NixOS/nixpkgs/pull/326466#issuecomment-2293029160
-
# and https://github.com/NixOS/nixpkgs/issues/380230
-
passthru.skipBulkUpdate = true;
meta = {
changelog = "https://github.com/AcademySoftwareFoundation/MaterialX/blob/${src.rev}/CHANGELOG.md";
+2 -2
pkgs/development/python-modules/playwright/default.nix
···
buildPythonPackage rec {
pname = "playwright";
# run ./pkgs/development/python-modules/playwright/update.sh to update
-
version = "1.53.0";
+
version = "1.54.0";
pyproject = true;
disabled = pythonOlder "3.9";
···
owner = "microsoft";
repo = "playwright-python";
tag = "v${version}";
-
hash = "sha256-jFS2Luq/9mRsXZ65H3VLw+sTBplVNVy/yZYrpF5Hc0M=";
+
hash = "sha256-xyuofDL0hWL8Gn4sYNLKte8q/4bMo+3aSbYaf5iWiBk=";
};
patches = [
+17 -1
pkgs/development/python-modules/playwright/update.sh
···
temp_dir=$(mktemp -d)
trap 'rm -rf "$temp_dir"' EXIT
+
# Update playwright-mcp package
+
mcp_version=$(curl ${GITHUB_TOKEN:+" -u \":$GITHUB_TOKEN\""} -s https://api.github.com/repos/microsoft/playwright-mcp/releases/latest | jq -r '.tag_name | sub("^v"; "")')
+
update-source-version playwright-mcp "$mcp_version"
+
+
# Update npmDepsHash for playwright-mcp
+
pushd "$temp_dir" >/dev/null
+
curl -fsSL -o package-lock.json "https://raw.githubusercontent.com/microsoft/playwright-mcp/v${mcp_version}/package-lock.json"
+
mcp_npm_hash=$(prefetch-npm-deps package-lock.json)
+
rm -f package-lock.json
+
popd >/dev/null
+
+
mcp_package_file="$root/../../../by-name/pl/playwright-mcp/package.nix"
+
sed -E 's#\bnpmDepsHash = ".*?"#npmDepsHash = "'"$mcp_npm_hash"'"#' -i "$mcp_package_file"
# update binaries of browsers, used by playwright.
···
fi
else
if [ "$name" = "ffmpeg" ] || [ "$name" = "chromium-headless-shell" ]; then
+
suffix="linux"
+
elif [ "$name" = "chromium" ]; then
+
stripRoot="true"
suffix="linux"
elif [ "$name" = "firefox" ]; then
stripRoot="true"
···
)
' > "$playwright_dir/browsers.json"
-
# We currently use Chromium from nixpkgs, so we don't need to download it here
+
update_browser "chromium" "linux"
update_browser "chromium-headless-shell" "linux"
update_browser "firefox" "linux"
update_browser "webkit" "linux"
+8 -8
pkgs/development/web/playwright/browsers.json
···
"comment": "This file is kept up to date via update.sh",
"browsers": {
"chromium": {
-
"revision": "1179",
-
"browserVersion": "138.0.7204.23"
+
"revision": "1181",
+
"browserVersion": "139.0.7258.5"
},
"chromium-headless-shell": {
-
"revision": "1179",
-
"browserVersion": "138.0.7204.23"
+
"revision": "1181",
+
"browserVersion": "139.0.7258.5"
},
"firefox": {
-
"revision": "1488",
-
"browserVersion": "139.0"
+
"revision": "1489",
+
"browserVersion": "140.0.2"
},
"webkit": {
-
"revision": "2182",
+
"revision": "2191",
"revisionOverrides": {
"debian11-x64": "2105",
"debian11-arm64": "2105",
···
"ubuntu20.04-x64": "2092",
"ubuntu20.04-arm64": "2092"
},
-
"browserVersion": "18.5"
+
"browserVersion": "26.0"
},
"ffmpeg": {
"revision": "1011",
+4 -4
pkgs/development/web/playwright/chromium-headless-shell.nix
···
stripRoot = false;
hash =
{
-
x86_64-linux = "sha256-C545VC0RxFYfKf8XArfVoI2yzrGyfR7vxjryJHfcfBQ=";
-
aarch64-linux = "sha256-i+HVf/6Qz2nCLLzPxbRYVFjDDOhd5ETYuHje5YsmsAo=";
+
x86_64-linux = "sha256-AYh2urKZdjXCELimYaFihWp0FbDLf4uRrKLJZVxug5M=";
+
aarch64-linux = "sha256-diBiy0z51BxGK0PcfQOf1aryUcZesKu/UHBSZUjqwMk=";
}
.${system} or throwSystem;
};
···
stripRoot = false;
hash =
{
-
x86_64-darwin = "sha256-2pe1LS3WXRG/V2k/BNN1MmOOdGoA0WCFhUpZW8TUhic=";
-
aarch64-darwin = "sha256-U07QnHFPQXyO3VGWfZvcP8cJEmVJAJ7imj+6DQlN9vQ=";
+
x86_64-darwin = "sha256-vIJuDjkasUYlMW0aCOyztyrlh5kvcwNR9GBaoa/yh/M=";
+
aarch64-darwin = "sha256-6Q6nz0H2749srdMF/puk/gnG1gQBEnWe9cQO3owL2OU=";
}
.${system} or throwSystem;
};
+4 -4
pkgs/development/web/playwright/chromium.nix
···
url = "https://playwright.azureedge.net/builds/chromium/${revision}/chromium-${suffix}.zip";
hash =
{
-
x86_64-linux = "sha256-7oQQCAIt1VJiMNFEJO40K8oENK/L0BICXm2D/3fZ8bA=";
-
aarch64-linux = "sha256-1OmByLX2jNHXAzWdXF8Od7S7pj/jl4wwvOQcsZc5R7o=";
+
x86_64-linux = "sha256-R7nMCVpUqgRwtB0syhfIK81maiTVWr8lYBLp4bR8VBg=";
+
aarch64-linux = "sha256-4fc4X7QwBigktmEeseuqIyEeV70Dy3eO/femXrftMd0=";
}
.${system} or throwSystem;
};
···
stripRoot = false;
hash =
{
-
x86_64-darwin = "sha256-KOoCbygsZZzGNKD8ICcGg0iM2h0HVgXq0I4JMPaUJR8=";
-
aarch64-darwin = "sha256-2naFzKWmo6el+AqljzILO+hUq/E2g81Dt1fwq79EYO8=";
+
x86_64-darwin = "sha256-0u1AStbUTX+qgUmg2DvL59B4b265WywDaBV+MdSuaNE=";
+
aarch64-darwin = "sha256-4pg4wmNTF8mw+APmdpvYlFxb9zc6OUh11oW5gCRKETY=";
}
.${system} or throwSystem;
};
+4 -4
pkgs/development/web/playwright/driver.nix
···
}
.${system} or throwSystem;
-
version = "1.53.1";
+
version = "1.54.1";
src = fetchFromGitHub {
owner = "Microsoft";
repo = "playwright";
rev = "v${version}";
-
hash = "sha256-N5BS8zpoQGUf5gly0fyutaK76CAhbwOGAUofGnfkmnM=";
+
hash = "sha256-xwyREgelHLkpbUXOZTppKK7L6dE4jx0d/lbDWSKGzTY=";
};
babel-bundle = buildNpmPackage {
···
pname = "utils-bundle-core";
inherit version src;
sourceRoot = "${src.name}/packages/playwright-core/bundles/utils";
-
npmDepsHash = "sha256-3hdOmvs/IGAgW7vhldms9Q9/ZQfbjbc+xP+JEtGJ7g8=";
+
npmDepsHash = "sha256-gEm2oTxj4QIiGnIOPffOLh3BYSngpGToF89ObnDYBqs=";
dontNpmBuild = true;
installPhase = ''
cp -r . "$out"
···
inherit version src;
sourceRoot = "${src.name}"; # update.sh depends on sourceRoot presence
-
npmDepsHash = "sha256-a1s1l8PG0ViVqYOksB2dkID/AHczMjLNQJW88+yB0B0=";
+
npmDepsHash = "sha256-4bsX8Q8V3CBpIsyqMYTzfERQQPY5zlPf7CoqR6UkUHU=";
nativeBuildInputs = [
cacert
+4 -4
pkgs/development/web/playwright/firefox.nix
···
}.zip";
hash =
{
-
x86_64-linux = "sha256-L9bIldFCqZ/jnNKkJk6nS0HNaJefzTMQIJ6VLUE9ugc=";
-
aarch64-linux = "sha256-iuiS59f8j3K+grBU7ZtZPfU4r2Dp7s0JJHf2n/4r30U=";
+
x86_64-linux = "sha256-j7gOuXMyftNQencgfpk8Y4ED2LuT7TAa30IPyzmir48=";
+
aarch64-linux = "sha256-deIUGKBrp56TsDr61cbNbRRSRcVpSoa6pdmMk4oB/Eg=";
}
.${system} or throwSystem;
};
···
stripRoot = false;
hash =
{
-
x86_64-darwin = "sha256-K0eW1kC1tckJu0crD89hDhK8PHyQUB0YUYN9DdX0HKw=";
-
aarch64-darwin = "sha256-n1Uy59r6wxmung8QKvw3JeyF3ec/avCVp9fI+bck/iA=";
+
x86_64-darwin = "sha256-ljgFoyqCg9kma2cDFodNjbkAeEylIzVdWkS1vU/9Rbg=";
+
aarch64-darwin = "sha256-W2J5APPWEkmoDgBEox6/ygg2xyWpOHZESXFG0tZbj1M=";
}
.${system} or throwSystem;
};
+9 -5
pkgs/development/web/playwright/webkit.nix
···
hash = "sha256-X4fbYTMS+kHfZRbeGzSdBW5jQKw8UN44FEyFRUtw0qo=";
})
];
-
postPatch = "";
+
postPatch = ''
+
# Fix multiple definition errors by using C++17 instead of C++11
+
substituteInPlace CMakeLists.txt \
+
--replace "set(CMAKE_CXX_STANDARD 11)" "set(CMAKE_CXX_STANDARD 17)"
+
'';
postInstall = "";
cmakeFlags = [
···
stripRoot = false;
hash =
{
-
x86_64-linux = "sha256-lwH783B3/laqw0IdGBnVzvySRoF0AwZsSolaqUKmsM4=";
-
aarch64-linux = "sha256-qtvP0bc5rcZcz6SqigfdrjhTWEmvT4k11I1GW1Eoj/Q=";
+
x86_64-linux = "sha256-OSVHFGdcQrzmhLPdXF61tKmip/6/D+uaQgSBBQiOIZI=";
+
aarch64-linux = "sha256-b8XwVMCwSbujyqgkJKIPAVNX83Qmmsthprr2x9XSb10=";
}
.${system} or throwSystem;
};
···
stripRoot = false;
hash =
{
-
x86_64-darwin = "sha256-p1+Pk+Zhf2OPEmEWCEd0tA7CdoMcOgYp69SnQXufFJ0=";
-
aarch64-darwin = "sha256-tEfKvJuGe4htZLSOn94eKeBtWXYkjl73iJSY4BWJMKo=";
+
x86_64-darwin = "sha256-shjhozJS2VbBjpjJVlM9hwBzGWwgva1qhfEUhY8t9Bk=";
+
aarch64-darwin = "sha256-ZRl86L/OOTNPWfZDl6JQfuXL41kI/Wir99/JIbf7T7M=";
}
.${system} or throwSystem;
};
+6 -6
pkgs/top-level/aliases.nix
···
gcj6 = throw "gcj6 has been removed from Nixpkgs, as it is unmaintained and obsolete"; # Added 2024-09-13
gcolor2 = throw "'gcolor2' has been removed due to lack of maintenance upstream and depending on gtk2. Consider using 'gcolor3' or 'eyedropper' instead"; # Added 2024-09-15
gdome2 = throw "'gdome2' has been removed from nixpkgs, as it is umaintained and obsolete"; # Added 2024-12-29
-
geocode-glib = "throw 'geocode-glib' has been removed, as it was unused and used outdated libraries"; # Added 2025-04-16
+
geocode-glib = throw "throw 'geocode-glib' has been removed, as it was unused and used outdated libraries"; # Added 2025-04-16
geos_3_11 = throw "geos_3_11 has been removed from nixpgks. Please use a more recent 'geos' instead.";
gfbgraph = throw "'gfbgraph' has been removed as it was archived upstream and unused in nixpkgs"; # Added 2025-04-20
gfortran48 = throw "'gfortran48' has been removed from nixpkgs"; # Added 2024-09-10
···
gsignond = throw "'gsignond' and its plugins have been removed due to lack of maintenance upstream"; # added 2025-04-17
gsignondPlugins = throw "'gsignondPlugins' have been removed alongside 'gsignond' due to lack of maintenance upstream and depending on libsoup_2"; # added 2025-04-17
gtetrinet = throw "'gtetrinet' has been removed because it depends on GNOME 2 libraries"; # Added 2024-06-27
-
gtk-engine-bluecurve = "'gtk-engine-bluecurve' has been removed as it has been archived upstream."; # Added 2024-12-04
+
gtk-engine-bluecurve = throw "'gtk-engine-bluecurve' has been removed as it has been archived upstream."; # Added 2024-12-04
gtk2fontsel = throw "'gtk2fontsel' has been removed due to lack of maintenance upstream. GTK now has a built-in font chooser so it's no longer needed for newer apps"; # Added 2024-10-19
gtkcord4 = dissent; # Added 2024-03-10
gtkextra = throw "'gtkextra' has been removed due to lack of maintenance upstream."; # Added 2025-06-10
···
schildichat-desktop = schildichat-web;
schildichat-desktop-wayland = schildichat-web;
scitoken-cpp = scitokens-cpp; # Added 2024-02-12
-
scry = "'scry' has been removed as it was archived upstream. Use 'crystalline' instead"; # Added 2025-02-12
+
scry = throw "'scry' has been removed as it was archived upstream. Use 'crystalline' instead"; # Added 2025-02-12
semeru-bin-16 = throw "Semeru 16 has been removed as it has reached its end of life"; # Added 2024-08-01
semeru-jre-bin-16 = throw "Semeru 16 has been removed as it has reached its end of life"; # Added 2024-08-01
sensu = throw "sensu has been removed as the upstream project is deprecated. Consider using `sensu-go`"; # Added 2024-10-28
···
timelens = throw "'timelens' has been removed due to lack of upstream maintenance"; # Added 2025-01-25
tix = tclPackages.tix; # Added 2024-10-02
tkcvs = tkrev; # Added 2022-03-07
-
tkgate = "'tkgate' has been removed as it is unmaintained"; # Added 2025-05-17
+
tkgate = throw "'tkgate' has been removed as it is unmaintained"; # Added 2025-05-17
tkimg = tclPackages.tkimg; # Added 2024-10-02
-
todiff = "'todiff' was removed due to lack of known users"; # Added 2025-01-25
+
todiff = throw "'todiff' was removed due to lack of known users"; # Added 2025-01-25
toil = throw "toil was removed as it was broken and requires obsolete versions of libraries"; # Added 2024-09-22
tokodon = plasma5Packages.tokodon;
tokyo-night-gtk = tokyonight-gtk-theme; # Added 2024-01-28
···
ubootBeagleboneBlack = throw "'ubootBeagleboneBlack' has been renamed to/replaced by 'ubootAmx335xEVM'"; # Converted to throw 2024-10-17
ubuntu_font_family = ubuntu-classic; # Added 2024-02-19
uclibc = uclibc-ng; # Added 2022-06-16
-
unicap = "'unicap' has been removed because it is unmaintained"; # Added 2025-05-17
+
unicap = throw "'unicap' has been removed because it is unmaintained"; # Added 2025-05-17
unicorn-emu = throw "'unicorn-emu' has been renamed to/replaced by 'unicorn'"; # Converted to throw 2024-10-17
uniffi-bindgen = throw "uniffi-bindgen has been removed since upstream no longer provides a standalone package for the CLI";
unifi-poller = unpoller; # Added 2022-11-24
-2
pkgs/top-level/all-packages.nix
···
inherit (darwin) DarwinTools;
-
openimageio_2 = callPackage ../by-name/op/openimageio/2.nix { };
-
open-music-kontrollers = lib.recurseIntoAttrs {
eteroj = callPackage ../applications/audio/open-music-kontrollers/eteroj.nix { };
jit = callPackage ../applications/audio/open-music-kontrollers/jit.nix { };