Merge master into haskell-updates

This commit is contained in:
github-actions[bot] 2024-01-20 00:12:49 +00:00 committed by GitHub
commit fc9b80e7a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
372 changed files with 6182 additions and 2750 deletions

View File

@ -378,7 +378,7 @@ The staging workflow exists to batch Hydra builds of many packages together.
It works by directing commits that cause [mass rebuilds][mass-rebuild] to a separate `staging` branch that isn't directly built by Hydra.
Regularly, the `staging` branch is _manually_ merged into a `staging-next` branch to be built by Hydra using the [`nixpkgs:staging-next` jobset](https://hydra.nixos.org/jobset/nixpkgs/staging-next).
The `staging-next` branch should then only receive direct commits in order to fix Hydra builds.
Once it is verified that there are no major regressions, it is merged into `master` using [a pull requests](https://github.com/NixOS/nixpkgs/pulls?q=head%3Astaging-next).
Once it is verified that there are no major regressions, it is merged into `master` using [a pull request](https://github.com/NixOS/nixpkgs/pulls?q=head%3Astaging-next).
This is done manually in order to ensure it's a good use of Hydra's computing resources.
By keeping the `staging-next` branch separate from `staging`, this batching does not block developers from merging changes into `staging`.

View File

@ -80,6 +80,8 @@ Do _not_ use `dart run <package_name>`, as this will attempt to download depende
### Usage with nix-shell {#ssec-dart-applications-nix-shell}
#### Using dependencies from the Nix store {#ssec-dart-applications-nix-shell-deps}
As `buildDartApplication` provides dependencies instead of `pub get`, Dart needs to be explicitly told where to find them.
Run the following commands in the source directory to configure Dart appropriately.
@ -103,6 +105,9 @@ flutter.buildFlutterApplication {
pname = "firmware-updater";
version = "unstable-2023-04-30";
# To build for the Web, use the targetFlutterPlatform argument.
# targetFlutterPlatform = "web";
src = fetchFromGitHub {
owner = "canonical";
repo = "firmware-updater";
@ -117,4 +122,15 @@ flutter.buildFlutterApplication {
### Usage with nix-shell {#ssec-dart-flutter-nix-shell}
See the [Dart documentation](#ssec-dart-applications-nix-shell) for nix-shell instructions.
Flutter-specific `nix-shell` usage notes are included here. See the [Dart documentation](#ssec-dart-applications-nix-shell) for general `nix-shell` instructions.
#### Entering the shell {#ssec-dart-flutter-nix-shell-enter}
By default, dependencies for only the `targetFlutterPlatform` are available in the
build environment. This is useful for keeping closures small, but be problematic
during development. It's common, for example, to build Web apps for Linux during
development to take advantage of native features such as stateful hot reload.
To enter a shell with all the usual target platforms available, use the `multiShell` attribute.
e.g. `nix-shell '<nixpkgs>' -A fluffychat-web.multiShell`.

View File

@ -2553,6 +2553,12 @@
githubId = 52386117;
name = "Blusk";
};
bmanuel = {
name = "Benjamin Manuel";
email = "ben@benmanuel.com";
github = "bmanuel";
githubId = 3662307;
};
bmilanov = {
name = "Biser Milanov";
email = "bmilanov11+nixpkgs@gmail.com";
@ -15504,6 +15510,16 @@
githubId = 1891350;
name = "Michael Raskin";
};
ratcornu = {
email = "ratcornu@skaven.org";
github = "RatCornu";
githubId = 98173832;
name = "Balthazar Patiachvili";
matrix = "@ratcornu:skweel.skaven.org";
keys = [{
fingerprint = "1B91 F087 3D06 1319 D3D0 7F91 FA47 BDA2 6048 9ADA";
}];
};
ratsclub = {
email = "victor@freire.dev.br";
github = "ratsclub";

View File

@ -37,6 +37,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the anki-sync-server softwares.
- [Suwayomi Server](https://github.com/Suwayomi/Suwayomi-Server), a free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org). Available as [services.suwayomi-server](#opt-services.suwayomi-server.enable).
- [ping_exporter](https://github.com/czerwonk/ping_exporter), a Prometheus exporter for ICMP echo requests. Available as [services.prometheus.exporters.ping](#opt-services.prometheus.exporters.ping.enable).
- [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable).
@ -112,6 +114,13 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- `services.avahi.nssmdns` got split into `services.avahi.nssmdns4` and `services.avahi.nssmdns6` which enable the mDNS NSS switch for IPv4 and IPv6 respectively.
Since most mDNS responders only register IPv4 addresses, most users want to keep the IPv6 support disabled to avoid long timeouts.
- `multi-user.target` no longer depends on `network-online.target`.
This will potentially break services that assumed this was the case in the past.
This was changed for consistency with other distributions as well as improved boot times.
We have added a warning for services that are
`after = [ "network-online.target" ]` but do not depend on it (e.g. using `wants`).
- `networking.iproute2.enable` now does not set `environment.etc."iproute2/rt_tables".text`.
Setting `environment.etc."iproute2/{CONFIG_FILE_NAME}".text` will override the whole configuration file instead of appending it to the upstream configuration file.

View File

@ -110,6 +110,7 @@ let
withExtraAttrs = configuration: configuration // {
inherit extraArgs;
inherit (configuration._module.args) pkgs;
inherit lib;
extendModules = args: withExtraAttrs (configuration.extendModules args);
};
in

View File

@ -10,6 +10,8 @@
, systemd
, fakeroot
, util-linux
# filesystem tools
, dosfstools
, mtools
, e2fsprogs
@ -18,8 +20,13 @@
, btrfs-progs
, xfsprogs
# compression tools
, zstd
, xz
# arguments
, name
, imageFileBasename
, compression
, fileSystems
, partitions
, split
@ -52,14 +59,25 @@ let
};
fileSystemTools = builtins.concatMap (f: fileSystemToolMapping."${f}") fileSystems;
compressionPkg = {
"zstd" = zstd;
"xz" = xz;
}."${compression.algorithm}";
compressionCommand = {
"zstd" = "zstd --no-progress --threads=0 -${toString compression.level}";
"xz" = "xz --keep --verbose --threads=0 -${toString compression.level}";
}."${compression.algorithm}";
in
runCommand name
runCommand imageFileBasename
{
nativeBuildInputs = [
systemd
fakeroot
util-linux
compressionPkg
] ++ fileSystemTools;
} ''
amendedRepartDefinitions=$(${amendRepartDefinitions} ${partitions} ${definitionsDirectory})
@ -67,6 +85,7 @@ runCommand name
mkdir -p $out
cd $out
echo "Building image with systemd-repart..."
unshare --map-root-user fakeroot systemd-repart \
--dry-run=no \
--empty=create \
@ -75,6 +94,17 @@ runCommand name
--definitions="$amendedRepartDefinitions" \
--split="${lib.boolToString split}" \
--json=pretty \
image.raw \
${imageFileBasename}.raw \
| tee repart-output.json
# Compression is implemented in the same derivation as opposed to in a
# separate derivation to allow users to save disk space. Disk images are
# already very space intensive so we want to allow users to mitigate this.
if ${lib.boolToString compression.enable}; then
for f in ${imageFileBasename}*; do
echo "Compressing $f with ${compression.algorithm}..."
# Keep the original file when compressing and only delete it afterwards
${compressionCommand} $f && rm $f
done
fi
''

View File

@ -66,7 +66,53 @@ in
name = lib.mkOption {
type = lib.types.str;
description = lib.mdDoc "The name of the image.";
description = lib.mdDoc ''
Name of the image.
If this option is unset but config.system.image.id is set,
config.system.image.id is used as the default value.
'';
};
version = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = config.system.image.version;
defaultText = lib.literalExpression "config.system.image.version";
description = lib.mdDoc "Version of the image";
};
imageFileBasename = lib.mkOption {
type = lib.types.str;
readOnly = true;
description = lib.mdDoc ''
Basename of the image filename without any extension (e.g. `image_1`).
'';
};
imageFile = lib.mkOption {
type = lib.types.str;
readOnly = true;
description = lib.mdDoc ''
Filename of the image including all extensions (e.g `image_1.raw` or
`image_1.raw.zst`).
'';
};
compression = {
enable = lib.mkEnableOption (lib.mdDoc "Image compression");
algorithm = lib.mkOption {
type = lib.types.enum [ "zstd" "xz" ];
default = "zstd";
description = lib.mdDoc "Compression algorithm";
};
level = lib.mkOption {
type = lib.types.int;
description = lib.mdDoc ''
Compression level. The available range depends on the used algorithm.
'';
};
};
seed = lib.mkOption {
@ -131,6 +177,32 @@ in
config = {
image.repart =
let
version = config.image.repart.version;
versionInfix = if version != null then "_${version}" else "";
compressionSuffix = lib.optionalString cfg.compression.enable
{
"zstd" = ".zst";
"xz" = ".xz";
}."${cfg.compression.algorithm}";
in
{
name = lib.mkIf (config.system.image.id != null) (lib.mkOptionDefault config.system.image.id);
imageFileBasename = cfg.name + versionInfix;
imageFile = cfg.imageFileBasename + ".raw" + compressionSuffix;
compression = {
# Generally default to slightly faster than default compression
# levels under the assumption that most of the building will be done
# for development and release builds will be customized.
level = lib.mkOptionDefault {
"zstd" = 3;
"xz" = 3;
}."${cfg.compression.algorithm}";
};
};
system.build.image =
let
fileSystems = lib.filter
@ -160,7 +232,7 @@ in
in
pkgs.callPackage ./repart-image.nix {
systemd = cfg.package;
inherit (cfg) name split seed;
inherit (cfg) imageFileBasename compression split seed;
inherit fileSystems definitionsDirectory partitions;
};

View File

@ -28,6 +28,8 @@ let
DOCUMENTATION_URL = lib.optionalString (cfg.distroId == "nixos") "https://nixos.org/learn.html";
SUPPORT_URL = lib.optionalString (cfg.distroId == "nixos") "https://nixos.org/community.html";
BUG_REPORT_URL = lib.optionalString (cfg.distroId == "nixos") "https://github.com/NixOS/nixpkgs/issues";
IMAGE_ID = lib.optionalString (config.system.image.id != null) config.system.image.id;
IMAGE_VERSION = lib.optionalString (config.system.image.version != null) config.system.image.version;
} // lib.optionalAttrs (cfg.variant_id != null) {
VARIANT_ID = cfg.variant_id;
};
@ -110,6 +112,38 @@ in
example = "installer";
};
image = {
id = lib.mkOption {
type = types.nullOr (types.strMatching "^[a-z0-9._-]+$");
default = null;
description = lib.mdDoc ''
Image identifier.
This corresponds to the IMAGE_ID field in os-release. See the
upstream docs for more details on valid characters for this field:
https://www.freedesktop.org/software/systemd/man/latest/os-release.html#IMAGE_ID=
You would only want to set this option if you're build NixOS appliance images.
'';
};
version = lib.mkOption {
type = types.nullOr (types.strMatching "^[a-z0-9._-]+$");
default = null;
description = lib.mdDoc ''
Image version.
This corresponds to the IMAGE_VERSION field in os-release. See the
upstream docs for more details on valid characters for this field:
https://www.freedesktop.org/software/systemd/man/latest/os-release.html#IMAGE_VERSION=
You would only want to set this option if you're build NixOS appliance images.
'';
};
};
stateVersion = mkOption {
type = types.str;
# TODO Remove this and drop the default of the option so people are forced to set it.

View File

@ -1339,6 +1339,7 @@
./services/web-apps/restya-board.nix
./services/web-apps/rimgo.nix
./services/web-apps/sftpgo.nix
./services/web-apps/suwayomi-server.nix
./services/web-apps/rss-bridge.nix
./services/web-apps/selfoss.nix
./services/web-apps/shiori.nix

View File

@ -64,6 +64,7 @@ in
config = mkIf cfg.enable {
systemd = {
services.gmediarender = {
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
description = "gmediarender server daemon";

View File

@ -26,6 +26,7 @@ in
config = mkIf cfg.enable {
systemd.services.jmusicbot = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
description = "Discord music bot that's easy to set up and run yourself!";
serviceConfig = mkMerge [{

View File

@ -50,6 +50,7 @@ in
systemd.services.spotifyd = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" "sound.target" ];
description = "spotifyd, a Spotify playing daemon";
environment.SHELL = "/bin/sh";

View File

@ -50,6 +50,7 @@ in {
description = "Standalone MPD Web GUI written in C";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {

View File

@ -268,6 +268,7 @@ in {
systemd.services.buildbot-master = {
description = "Buildbot Continuous Integration Server.";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = cfg.packages ++ cfg.pythonPackages python.pkgs;
environment.PYTHONPATH = "${python.withPackages (self: cfg.pythonPackages self ++ [ package ])}/${python.sitePackages}";

View File

@ -188,6 +188,7 @@ in
nameValuePair "gitea-runner-${escapeSystemdPath name}" {
inherit (instance) enable;
description = "Gitea Actions Runner";
wants = [ "network-online.target" ];
after = [
"network-online.target"
] ++ optionals (wantsDocker) [

View File

@ -393,6 +393,7 @@ in
systemd.services.hydra-evaluator =
{ wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
wants = [ "network-online.target" ];
after = [ "hydra-init.service" "network.target" "network-online.target" ];
path = with pkgs; [ hydra-package nettools jq ];
restartTriggers = [ hydraConf ];

View File

@ -143,7 +143,7 @@ in
# ConnectionTimeout = 180
#RemoteServiceName = gds_db
RemoteServicePort = ${cfg.port}
RemoteServicePort = ${toString cfg.port}
# randomly choose port for server Event Notification
#RemoteAuxPort = 0

View File

@ -104,6 +104,7 @@ in
config = lib.mkIf cfg.enable {
systemd.services.lldap = {
description = "Lightweight LDAP server (lldap)";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {

View File

@ -294,6 +294,7 @@ in {
"man:slapd-mdb"
];
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
User = cfg.user;

View File

@ -200,6 +200,7 @@ in
};
systemd.services.geoclue = {
wants = lib.optionals cfg.enableWifi [ "network-online.target" ];
after = lib.optionals cfg.enableWifi [ "network-online.target" ];
# restart geoclue service when the configuration changes
restartTriggers = [
@ -217,6 +218,7 @@ in
# we can't be part of a system service, and the agent should
# be okay with the main service coming and going
wantedBy = [ "default.target" ];
wants = lib.optionals cfg.enableWifi [ "network-online.target" ];
after = lib.optionals cfg.enableWifi [ "network-online.target" ];
unitConfig.ConditionUser = "!@system";
serviceConfig = {

View File

@ -41,6 +41,7 @@ in
config = mkIf cfg.enable {
systemd.services.evcc = {
wants = [ "network-online.target" ];
after = [
"network-online.target"
"mosquitto.target"

View File

@ -435,6 +435,7 @@ in {
systemd.services.home-assistant = {
description = "Home Assistant";
wants = [ "network-online.target" ];
after = [
"network-online.target"

View File

@ -84,6 +84,7 @@ in {
systemd.services.journaldriver = {
description = "Stackdriver Logging journal forwarder";
script = "${pkgs.journaldriver}/bin/journaldriver";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];

View File

@ -250,6 +250,7 @@ in
path = [ config.services.postgresql.package ];
})
{
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
script = let

View File

@ -435,7 +435,7 @@ in
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
wants = sympaSubServices;
wants = sympaSubServices ++ [ "network-online.target" ];
before = sympaSubServices;
serviceConfig = sympaServiceConfig "sympa_msg";

View File

@ -1056,6 +1056,7 @@ in {
systemd.targets.matrix-synapse = lib.mkIf hasWorkers {
description = "Synapse Matrix parent target";
wants = [ "network-online.target" ];
after = [ "network-online.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
wantedBy = [ "multi-user.target" ];
};
@ -1071,6 +1072,7 @@ in {
requires = optional hasLocalPostgresDB "postgresql.service";
}
else {
wants = [ "network-online.target" ];
after = [ "network-online.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
requires = optional hasLocalPostgresDB "postgresql.service";
wantedBy = [ "multi-user.target" ];

View File

@ -41,6 +41,7 @@ in {
# See https://github.com/aws/amazon-ssm-agent/blob/mainline/packaging/linux/amazon-ssm-agent.service
systemd.services.amazon-ssm-agent = {
inherit (cfg.package.meta) description;
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];

View File

@ -154,7 +154,7 @@ in
in {
description = "BigClown Gateway";
wantedBy = [ "multi-user.target" ];
wants = mkIf config.services.mosquitto.enable [ "mosquitto.service" ];
wants = [ "network-online.target" ] ++ lib.optional config.services.mosquitto.enable "mosquitto.service";
after = [ "network-online.target" ];
preStart = ''
umask 077

View File

@ -35,6 +35,7 @@ in {
systemd.services."domoticz" = {
description = pkgDesc;
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
DynamicUser = true;

View File

@ -59,6 +59,7 @@ in
systemd.services.etesync-dav = {
description = "etesync-dav - A CalDAV and CardDAV adapter for EteSync";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.etesync-dav ];

View File

@ -357,6 +357,7 @@ in {
description = "${cfg.serverName} media Server";
# Gerbera might fail if the network interface is not available on startup
# https://github.com/gerbera/gerbera/issues/1324
wants = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${binaryCommand} --port ${toString cfg.port} ${interfaceFlag} ${configFlag} --home ${cfg.dataDir}";

View File

@ -77,6 +77,7 @@ in {
systemd.services.metabase = {
description = "Metabase server";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
environment = {
MB_PLUGINS_DIR = "${dataDir}/plugins";

View File

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
with lib;
let cfg = config.nix.sshServe;
@ -46,7 +46,7 @@ in {
description = "Nix SSH store user";
isSystemUser = true;
group = "nix-ssh";
useDefaultShell = true;
shell = pkgs.bashInteractive;
};
users.groups.nix-ssh = {};

View File

@ -297,6 +297,7 @@ in
wantedBy = [ "paperless-scheduler.service" ];
before = [ "paperless-scheduler.service" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = defaultServiceConfig // {
User = cfg.user;
Type = "oneshot";

View File

@ -84,6 +84,7 @@ in {
# upstream service file in https://git.io/JUt4Q
systemd.services.mackerel-agent = {
description = "mackerel.io agent";
wants = [ "network-online.target" ];
after = [ "network-online.target" "nss-lookup.target" ];
wantedBy = [ "multi-user.target" ];
environment = {

View File

@ -174,6 +174,7 @@ in {
systemd.services.alertmanager = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
preStart = ''
${lib.getBin pkgs.envsubst}/bin/envsubst -o "/tmp/alert-manager-substituted.yaml" \

View File

@ -30,6 +30,7 @@ in
description = "TeamViewer remote control daemon";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" "network.target" "dbus.service" ];
requires = [ "dbus.service" ];
preStart = "mkdir -pv /var/lib/teamviewer /var/log/teamviewer";

View File

@ -59,6 +59,7 @@ in {
in {
description = "Telegraf Agent";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
path = lib.optional (config.services.telegraf.extraConfig.inputs ? procstat) pkgs.procps;
serviceConfig = {

View File

@ -215,6 +215,7 @@ in
systemd.services.afsd = {
description = "AFS client";
wantedBy = [ "multi-user.target" ];
wants = lib.optional (!cfg.startDisconnected) "network-online.target";
after = singleton (if cfg.startDisconnected then "network.target" else "network-online.target");
serviceConfig = { RemainAfterExit = true; };
restartIfChanged = false;

View File

@ -154,7 +154,7 @@ in
};
securityType = mkOption {
type = types.str;
type = types.enum [ "auto" "user" "domain" "ads" ];
default = "user";
description = lib.mdDoc "Samba security type";
};

View File

@ -198,6 +198,7 @@ in
'';
in {
description = "Bitcoin daemon";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {

View File

@ -47,6 +47,7 @@ in
systemd.services.dante = {
description = "Dante SOCKS v4 and v5 compatible proxy server";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];

View File

@ -114,6 +114,7 @@ in {
systemd.services.ergo = {
description = "ergo server";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
User = cfg.user;

View File

@ -21,6 +21,7 @@ with lib;
RestartSec = 5;
};
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
};
};

View File

@ -460,6 +460,7 @@ in {
systemd.services.headscale = {
description = "headscale coordination server for Tailscale";
wants = [ "network-online.target" ];
after = ["network-online.target"];
wantedBy = ["multi-user.target"];
restartTriggers = [configFile];

View File

@ -125,7 +125,8 @@ in
systemd.services.ircd-hybrid = {
description = "IRCD Hybrid server";
after = [ "started networking" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
script = "${ircdService}/bin/control start";
};

View File

@ -27,7 +27,7 @@ with lib;
systemd.services.ivpn-service = {
description = "iVPN daemon";
wantedBy = [ "multi-user.target" ];
wants = [ "network.target" ];
wants = [ "network.target" "network-online.target" ];
after = [
"network-online.target"
"NetworkManager.service"

View File

@ -325,6 +325,9 @@ in
"network-online.target"
"time-sync.target"
];
wants = [
"network-online.target"
];
wantedBy = [
"multi-user.target"
];
@ -372,6 +375,9 @@ in
"network-online.target"
"time-sync.target"
];
wants = [
"network-online.target"
];
wantedBy = [
"multi-user.target"
];
@ -413,6 +419,7 @@ in
"https://kea.readthedocs.io/en/kea-${package.version}/arm/ddns.html"
];
wants = [ "network-online.target" ];
after = [
"network-online.target"
"time-sync.target"

View File

@ -596,6 +596,7 @@ in
systemd.services.mosquitto = {
description = "Mosquitto MQTT Broker Daemon";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
Type = "notify";

View File

@ -53,7 +53,7 @@ with lib;
systemd.services.mullvad-daemon = {
description = "Mullvad VPN daemon";
wantedBy = [ "multi-user.target" ];
wants = [ "network.target" ];
wants = [ "network.target" "network-online.target" ];
after = [
"network-online.target"
"NetworkManager.service"

View File

@ -117,6 +117,7 @@ in
boot.kernelModules = [ "nbd" ];
systemd.services.nbd-server = {
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
before = [ "multi-user.target" ];
wantedBy = [ "multi-user.target" ];

View File

@ -85,6 +85,7 @@ in
systemd.services.ocserv = {
description = "OpenConnect SSL VPN server";
documentation = [ "man:ocserv(8)" ];
wants = [ "network-online.target" ];
after = [ "dbus.service" "network-online.target" ];
wantedBy = [ "multi-user.target" ];

View File

@ -92,6 +92,7 @@ in {
systemd.services.pleroma = {
description = "Pleroma social network";
wants = [ "network-online.target" ];
after = [ "network-online.target" "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
restartTriggers = [ config.environment.etc."/pleroma/config.exs".source ];

View File

@ -208,6 +208,7 @@ in
in
rec {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
path = [ cfg.package pkgs.wireguard-tools ];

View File

@ -33,7 +33,7 @@ in {
wantedBy = [ "multi-user.target" ];
after = [ "systemd-modules-load.service" "network-online.target" ];
wants = [ "network-pre.target" ];
wants = [ "network-pre.target" "network-online.target" ];
serviceConfig = {
Type = "oneshot";

View File

@ -110,6 +110,7 @@ in
systemd.services.soju = {
description = "soju IRC bouncer";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
DynamicUser = true;

View File

@ -55,6 +55,7 @@ in {
systemd.services.strongswan-swanctl = {
description = "strongSwan IPsec IKEv1/IKEv2 daemon using swanctl";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
path = with pkgs; [ kmod iproute2 iptables util-linux ];
environment = {

View File

@ -153,6 +153,7 @@ in
description = "strongSwan IPSec Service";
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ kmod iproute2 iptables util-linux ]; # XXX Linux
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
environment = {
STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secretsFile managePlugins enabledPlugins; };

View File

@ -107,6 +107,7 @@ in
systemd.services.syncplay = {
description = "Syncplay Service";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {

View File

@ -119,6 +119,7 @@ in {
systemd.services.wasabibackend = {
description = "wasabibackend server";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
environment = {
DOTNET_PRINT_TELEMETRY_MESSAGE = "false";

View File

@ -243,6 +243,7 @@ in
systemd.services.znc = {
description = "ZNC Server";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
User = cfg.user;

View File

@ -182,6 +182,7 @@ in
systemd.services.certmgr = {
description = "certmgr";
path = mkIf (cfg.svcManager == "command") [ pkgs.bash ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
inherit preStart;

View File

@ -572,6 +572,7 @@ in
description = "OAuth2 Proxy";
path = [ cfg.package ];
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {

View File

@ -49,6 +49,7 @@ in {
config = mkIf cfg.enable {
systemd.services.cachix-agent = {
description = "Cachix Deploy Agent";
wants = [ "network-online.target" ];
after = ["network-online.target"];
path = [ config.nix.package ];
wantedBy = [ "multi-user.target" ];

View File

@ -61,6 +61,7 @@ in
config = mkIf cfg.enable {
systemd.services.cachix-watch-store-agent = {
description = "Cachix watch store Agent";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
path = [ config.nix.package ];
wantedBy = [ "multi-user.target" ];

View File

@ -94,6 +94,7 @@ in
config = lib.mkIf cfg.enable {
systemd.services.go2rtc = {
wants = [ "network-online.target" ];
after = [
"network-online.target"
];

View File

@ -974,7 +974,7 @@ in {
# This service depends on network-online.target and is sequenced after
# it because it requires access to the Internet to function properly.
bindsTo = [ "akkoma-config.service" ];
wants = [ "network-online.service" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
after = [
"akkoma-config.target"

View File

@ -94,6 +94,7 @@ in {
description = "alps is a simple and extensible webmail.";
documentation = [ "https://git.sr.ht/~migadu/alps" ];
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
serviceConfig = {

View File

@ -80,6 +80,7 @@ in {
description = "c2FmZQ-server";
documentation = [ "https://github.com/c2FmZQ/c2FmZQ/blob/main/README.md" ];
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
serviceConfig = {

View File

@ -205,6 +205,7 @@ in {
systemd.services.code-server = {
description = "Code server";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
path = cfg.extraPackages;
environment = {

View File

@ -176,6 +176,7 @@ in
systemd.targets.healthchecks = {
description = "Target for all Healthchecks services";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
};

View File

@ -267,6 +267,7 @@ in {
systemd.targets.netbox = {
description = "Target for all NetBox services";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" "redis-netbox.service" ];
};

View File

@ -159,6 +159,7 @@ in
systemd.services.openvscode-server = {
description = "OpenVSCode server";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
path = cfg.extraPackages;
environment = cfg.extraEnvironment;

View File

@ -196,6 +196,7 @@ in {
systemd.targets.peering-manager = {
description = "Target for all Peering Manager services";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" "redis-peering-manager.service" ];
};

View File

@ -0,0 +1,108 @@
# Suwayomi-Server {#module-services-suwayomi-server}
A free and open source manga reader server that runs extensions built for Tachiyomi.
## Basic usage {#module-services-suwayomi-server-basic-usage}
By default, the module will execute Suwayomi-Server backend and web UI:
```nix
{ ... }:
{
services.suwayomi-server = {
enable = true;
};
}
```
It runs in the systemd service named `suwayomi-server` in the data directory `/var/lib/suwayomi-server`.
You can change the default parameters with some other parameters:
```nix
{ ... }:
{
services.suwayomi-server = {
enable = true;
dataDir = "/var/lib/suwayomi"; # Default is "/var/lib/suwayomi-server"
openFirewall = true;
settings = {
server.port = 4567;
};
};
}
```
If you want to create a desktop icon, you can activate the system tray option:
```nix
{ ... }:
{
services.suwayomi-server = {
enable = true;
dataDir = "/var/lib/suwayomi"; # Default is "/var/lib/suwayomi-server"
openFirewall = true;
settings = {
server.port = 4567;
server.enableSystemTray = true;
};
};
}
```
## Basic authentication {#module-services-suwayomi-server-basic-auth}
You can configure a basic authentication to the web interface with:
```nix
{ ... }:
{
services.suwayomi-server = {
enable = true;
openFirewall = true;
settings = {
server.port = 4567;
server = {
basicAuthEnabled = true;
basicAuthUsername = "username";
# NOTE: this is not a real upstream option
basicAuthPasswordFile = ./path/to/the/password/file;
};
};
};
}
```
## Extra configuration {#module-services-suwayomi-server-extra-config}
Not all the configuration options are available directly in this module, but you can add the other options of suwayomi-server with:
```nix
{ ... }:
{
services.suwayomi-server = {
enable = true;
openFirewall = true;
settings = {
server = {
port = 4567;
autoDownloadNewChapters = false;
maxSourcesInParallel" = 6;
};
};
};
}
```

View File

@ -0,0 +1,260 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.suwayomi-server;
inherit (lib) mkOption mdDoc mkEnableOption mkIf types;
in
{
options = {
services.suwayomi-server = {
enable = mkEnableOption (mdDoc "Suwayomi, a free and open source manga reader server that runs extensions built for Tachiyomi.");
package = lib.mkPackageOptionMD pkgs "suwayomi-server" { };
dataDir = mkOption {
type = types.path;
default = "/var/lib/suwayomi-server";
example = "/var/data/mangas";
description = mdDoc ''
The path to the data directory in which Suwayomi-Server will download scans.
'';
};
user = mkOption {
type = types.str;
default = "suwayomi";
example = "root";
description = mdDoc ''
User account under which Suwayomi-Server runs.
'';
};
group = mkOption {
type = types.str;
default = "suwayomi";
example = "medias";
description = mdDoc ''
Group under which Suwayomi-Server runs.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Whether to open the firewall for the port in {option}`services.suwayomi-server.settings.server.port`.
'';
};
settings = mkOption {
type = types.submodule {
freeformType =
let
recursiveAttrsType = with types; attrsOf (nullOr (oneOf [
str
path
int
float
bool
(listOf str)
(recursiveAttrsType // { description = "instances of this type recursively"; })
]));
in
recursiveAttrsType;
options = {
server = {
ip = mkOption {
type = types.str;
default = "0.0.0.0";
example = "127.0.0.1";
description = mdDoc ''
The ip that Suwayomi will bind to.
'';
};
port = mkOption {
type = types.port;
default = 8080;
example = 4567;
description = mdDoc ''
The port that Suwayomi will listen to.
'';
};
basicAuthEnabled = mkEnableOption (mdDoc ''
Add basic access authentication to Suwayomi-Server.
Enabling this option is useful when hosting on a public network/the Internet
'');
basicAuthUsername = mkOption {
type = types.nullOr types.str;
default = null;
description = mdDoc ''
The username value that you have to provide when authenticating.
'';
};
# NOTE: this is not a real upstream option
basicAuthPasswordFile = mkOption {
type = types.nullOr types.path;
default = null;
example = "/var/secrets/suwayomi-server-password";
description = mdDoc ''
The password file containing the value that you have to provide when authenticating.
'';
};
downloadAsCbz = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Download chapters as `.cbz` files.
'';
};
localSourcePath = mkOption {
type = types.path;
default = cfg.dataDir;
defaultText = lib.literalExpression "suwayomi-server.dataDir";
example = "/var/data/local_mangas";
description = mdDoc ''
Path to the local source folder.
'';
};
systemTrayEnabled = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Whether to enable a system tray icon, if possible.
'';
};
};
};
};
description = mdDoc ''
Configuration to write to {file}`server.conf`.
See <https://github.com/Suwayomi/Suwayomi-Server/wiki/Configuring-Suwayomi-Server> for more information.
'';
default = { };
example = {
server.socksProxyEnabled = true;
server.socksProxyHost = "yourproxyhost.com";
server.socksProxyPort = "8080";
};
};
};
};
config = mkIf cfg.enable {
assertions = [{
assertion = with cfg.settings.server; basicAuthEnabled -> (basicAuthUsername != null && basicAuthPasswordFile != null);
message = ''
[suwayomi-server]: the username and the password file cannot be null when the basic auth is enabled
'';
}];
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.server.port ];
users.groups = mkIf (cfg.group == "suwayomi") {
suwayomi = { };
};
users.users = mkIf (cfg.user == "suwayomi") {
suwayomi = {
group = cfg.group;
# Need to set the user home because the package writes to ~/.local/Tachidesk
home = cfg.dataDir;
description = "Suwayomi Daemon user";
isSystemUser = true;
};
};
systemd.tmpfiles.settings."10-suwayomi-server" = {
"${cfg.dataDir}/.local/share/Tachidesk".d = {
mode = "0700";
inherit (cfg) user group;
};
};
systemd.services.suwayomi-server =
let
flattenConfig = prefix: config:
lib.foldl'
lib.mergeAttrs
{ }
(lib.attrValues
(lib.mapAttrs
(k: v:
if !(lib.isAttrs v)
then { "${prefix}${k}" = v; }
else flattenConfig "${prefix}${k}." v
)
config
)
);
# HOCON is a JSON superset that suwayomi-server use for configuration
toHOCON = attr:
let
attrType = builtins.typeOf attr;
in
if builtins.elem attrType [ "string" "path" "int" "float" ]
then ''"${toString attr}"''
else if attrType == "bool"
then lib.boolToString attr
else if attrType == "list"
then "[\n${lib.concatMapStringsSep ",\n" toHOCON attr}\n]"
else # attrs, lambda, null
throw ''
[suwayomi-server]: invalid config value type '${attrType}'.
'';
configFile = pkgs.writeText "server.conf" (lib.pipe cfg.settings [
(settings: lib.recursiveUpdate settings {
server.basicAuthPasswordFile = null;
server.basicAuthPassword =
if settings.server.basicAuthEnabled
then "$TACHIDESK_SERVER_BASIC_AUTH_PASSWORD"
else null;
})
(flattenConfig "")
(lib.filterAttrs (_: x: x != null))
(lib.mapAttrsToList (name: value: ''${name} = ${toHOCON value}''))
lib.concatLines
]);
in
{
description = "A free and open source manga reader server that runs extensions built for Tachiyomi.";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
script = ''
${lib.optionalString cfg.settings.server.basicAuthEnabled ''
export TACHIDESK_SERVER_BASIC_AUTH_PASSWORD="$(<${cfg.settings.server.basicAuthPasswordFile})"
''}
${lib.getExe pkgs.envsubst} -i ${configFile} -o ${cfg.dataDir}/.local/share/Tachidesk/server.conf
${lib.getExe cfg.package} -Dsuwayomi.tachidesk.config.server.rootDir=${cfg.dataDir}
'';
serviceConfig = {
User = cfg.user;
Group = cfg.group;
Type = "simple";
Restart = "on-failure";
StateDirectory = mkIf (cfg.dataDir == "/var/lib/suwayomi-server") "suwayomi-server";
};
};
};
meta = {
maintainers = with lib.maintainers; [ ratcornu ];
doc = ./suwayomi-server.md;
};
}

View File

@ -174,22 +174,22 @@ let
List of path(s) to respective language(s) which are copied from the 'languages' directory.
'';
example = literalExpression ''
[(
[
# Let's package the German language.
# For other languages try to replace language and country code in the download URL with your desired one.
# Reference https://translate.wordpress.org for available translations and
# codes.
language-de = pkgs.stdenv.mkDerivation {
(pkgs.stdenv.mkDerivation {
name = "language-de";
src = pkgs.fetchurl {
url = "https://de.wordpress.org/wordpress-''${pkgs.wordpress.version}-de_DE.tar.gz";
# Name is required to invalidate the hash when wordpress is updated
name = "wordpress-''${pkgs.wordpress.version}-language-de"
name = "wordpress-''${pkgs.wordpress.version}-language-de";
sha256 = "sha256-dlas0rXTSV4JAl8f/UyMbig57yURRYRhTMtJwF9g8h0=";
};
installPhase = "mkdir -p $out; cp -r ./wp-content/languages/* $out/";
};
)];
})
];
'';
};

View File

@ -71,6 +71,7 @@ in
systemd.services.agate = {
description = "Agate";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
script =

View File

@ -101,6 +101,7 @@ in {
];
systemd.services.mighttpd2 = {
description = "Mighttpd2 web server";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {

View File

@ -98,6 +98,7 @@ in
services.minio = {
description = "Minio Object Storage";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {

View File

@ -144,6 +144,7 @@ in {
systemd.services.traefik = {
description = "Traefik web server";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
startLimitIntervalSec = 86400;

View File

@ -15,6 +15,19 @@ import json
from typing import NamedTuple, Dict, List
from dataclasses import dataclass
# These values will be replaced with actual values during the package build
EFI_SYS_MOUNT_POINT = "@efiSysMountPoint@"
TIMEOUT = "@timeout@"
EDITOR = bool("@editor@")
CONSOLE_MODE = "@consoleMode@"
BOOTSPEC_TOOLS = "@bootspecTools@"
DISTRO_NAME = "@distroName@"
NIX = "@nix@"
SYSTEMD = "@systemd@"
CONFIGURATION_LIMIT = int("@configurationLimit@")
CAN_TOUCH_EFI_VARIABLES = "@canTouchEfiVariables@"
GRACEFUL = "@graceful@"
COPY_EXTRA_FILES = "@copyExtraFiles@"
@dataclass
class BootSpec:
@ -29,7 +42,6 @@ class BootSpec:
initrdSecrets: str | None = None
libc = ctypes.CDLL("libc.so.6")
class SystemIdentifier(NamedTuple):
@ -75,16 +87,16 @@ def generation_conf_filename(profile: str | None, generation: int, specialisatio
def write_loader_conf(profile: str | None, generation: int, specialisation: str | None) -> None:
with open("@efiSysMountPoint@/loader/loader.conf.tmp", 'w') as f:
if "@timeout@" != "":
f.write("timeout @timeout@\n")
with open(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf.tmp", 'w') as f:
if TIMEOUT != "":
f.write(f"timeout {TIMEOUT}\n")
f.write("default %s\n" % generation_conf_filename(profile, generation, specialisation))
if not @editor@:
if not EDITOR:
f.write("editor 0\n")
f.write("console-mode @consoleMode@\n")
f.write(f"console-mode {CONSOLE_MODE}\n")
f.flush()
os.fsync(f.fileno())
os.rename("@efiSysMountPoint@/loader/loader.conf.tmp", "@efiSysMountPoint@/loader/loader.conf")
os.rename(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf.tmp", f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf")
def get_bootspec(profile: str | None, generation: int) -> BootSpec:
@ -95,7 +107,7 @@ def get_bootspec(profile: str | None, generation: int) -> BootSpec:
bootspec_json = json.load(boot_json_f)
else:
boot_json_str = subprocess.check_output([
"@bootspecTools@/bin/synthesize",
f"{BOOTSPEC_TOOLS}/bin/synthesize",
"--version",
"1",
system_directory,
@ -116,7 +128,7 @@ def copy_from_file(file: str, dry_run: bool = False) -> str:
store_dir = os.path.basename(os.path.dirname(store_file_path))
efi_file_path = "/efi/nixos/%s-%s.efi" % (store_dir, suffix)
if not dry_run:
copy_if_not_exists(store_file_path, "@efiSysMountPoint@%s" % (efi_file_path))
copy_if_not_exists(store_file_path, f"{EFI_SYS_MOUNT_POINT}%s" % (efi_file_path))
return efi_file_path
def write_entry(profile: str | None, generation: int, specialisation: str | None,
@ -126,13 +138,14 @@ def write_entry(profile: str | None, generation: int, specialisation: str | None
kernel = copy_from_file(bootspec.kernel)
initrd = copy_from_file(bootspec.initrd)
title = "@distroName@{profile}{specialisation}".format(
title = "{name}{profile}{specialisation}".format(
name=DISTRO_NAME,
profile=" [" + profile + "]" if profile else "",
specialisation=" (%s)" % specialisation if specialisation else "")
try:
if bootspec.initrdSecrets is not None:
subprocess.check_call([bootspec.initrdSecrets, "@efiSysMountPoint@%s" % (initrd)])
subprocess.check_call([bootspec.initrdSecrets, f"{EFI_SYS_MOUNT_POINT}%s" % (initrd)])
except subprocess.CalledProcessError:
if current:
print("failed to create initrd secrets!", file=sys.stderr)
@ -142,7 +155,7 @@ def write_entry(profile: str | None, generation: int, specialisation: str | None
f'for "{title} - Configuration {generation}", an older generation', file=sys.stderr)
print("note: this is normal after having removed "
"or renamed a file in `boot.initrd.secrets`", file=sys.stderr)
entry_file = "@efiSysMountPoint@/loader/entries/%s" % (
entry_file = f"{EFI_SYS_MOUNT_POINT}/loader/entries/%s" % (
generation_conf_filename(profile, generation, specialisation))
tmp_path = "%s.tmp" % (entry_file)
kernel_params = "init=%s " % bootspec.init
@ -167,7 +180,7 @@ def write_entry(profile: str | None, generation: int, specialisation: str | None
def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
gen_list = subprocess.check_output([
"@nix@/bin/nix-env",
f"{NIX}/bin/nix-env",
"--list-generations",
"-p",
"/nix/var/nix/profiles/%s" % ("system-profiles/" + profile if profile else "system"),
@ -176,7 +189,7 @@ def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
gen_lines = gen_list.split('\n')
gen_lines.pop()
configurationLimit = @configurationLimit@
configurationLimit = CONFIGURATION_LIMIT
configurations = [
SystemIdentifier(
profile=profile,
@ -189,14 +202,14 @@ def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
def remove_old_entries(gens: list[SystemIdentifier]) -> None:
rex_profile = re.compile(r"^@efiSysMountPoint@/loader/entries/nixos-(.*)-generation-.*\.conf$")
rex_generation = re.compile(r"^@efiSysMountPoint@/loader/entries/nixos.*-generation-([0-9]+)(-specialisation-.*)?\.conf$")
rex_profile = re.compile(r"^" + re.escape(EFI_SYS_MOUNT_POINT) + "/loader/entries/nixos-(.*)-generation-.*\.conf$")
rex_generation = re.compile(r"^" + re.escape(EFI_SYS_MOUNT_POINT) + "/loader/entries/nixos.*-generation-([0-9]+)(-specialisation-.*)?\.conf$")
known_paths = []
for gen in gens:
bootspec = get_bootspec(gen.profile, gen.generation)
known_paths.append(copy_from_file(bootspec.kernel, True))
known_paths.append(copy_from_file(bootspec.initrd, True))
for path in glob.iglob("@efiSysMountPoint@/loader/entries/nixos*-generation-[1-9]*.conf"):
for path in glob.iglob(f"{EFI_SYS_MOUNT_POINT}/loader/entries/nixos*-generation-[1-9]*.conf"):
if rex_profile.match(path):
prof = rex_profile.sub(r"\1", path)
else:
@ -207,7 +220,7 @@ def remove_old_entries(gens: list[SystemIdentifier]) -> None:
continue
if not (prof, gen_number, None) in gens:
os.unlink(path)
for path in glob.iglob("@efiSysMountPoint@/efi/nixos/*"):
for path in glob.iglob(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/*"):
if not path in known_paths and not os.path.isdir(path):
os.unlink(path)
@ -230,7 +243,7 @@ def install_bootloader(args: argparse.Namespace) -> None:
# Since systemd version 232 a machine ID is required and it might not
# be there on newly installed systems, so let's generate one so that
# bootctl can find it and we can also pass it to write_entry() later.
cmd = ["@systemd@/bin/systemd-machine-id-setup", "--print"]
cmd = [f"{SYSTEMD}/bin/systemd-machine-id-setup", "--print"]
machine_id = subprocess.run(
cmd, text=True, check=True, stdout=subprocess.PIPE
).stdout.rstrip()
@ -242,22 +255,22 @@ def install_bootloader(args: argparse.Namespace) -> None:
# flags to pass to bootctl install/update
bootctl_flags = []
if "@canTouchEfiVariables@" != "1":
if CAN_TOUCH_EFI_VARIABLES != "1":
bootctl_flags.append("--no-variables")
if "@graceful@" == "1":
if GRACEFUL == "1":
bootctl_flags.append("--graceful")
if os.getenv("NIXOS_INSTALL_BOOTLOADER") == "1":
# bootctl uses fopen() with modes "wxe" and fails if the file exists.
if os.path.exists("@efiSysMountPoint@/loader/loader.conf"):
os.unlink("@efiSysMountPoint@/loader/loader.conf")
if os.path.exists(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf"):
os.unlink(f"{EFI_SYS_MOUNT_POINT}/loader/loader.conf")
subprocess.check_call(["@systemd@/bin/bootctl", "--esp-path=@efiSysMountPoint@"] + bootctl_flags + ["install"])
subprocess.check_call([f"{SYSTEMD}/bin/bootctl", f"--esp-path={EFI_SYS_MOUNT_POINT}"] + bootctl_flags + ["install"])
else:
# Update bootloader to latest if needed
available_out = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2]
installed_out = subprocess.check_output(["@systemd@/bin/bootctl", "--esp-path=@efiSysMountPoint@", "status"], universal_newlines=True)
available_out = subprocess.check_output([f"{SYSTEMD}/bin/bootctl", "--version"], universal_newlines=True).split()[2]
installed_out = subprocess.check_output([f"{SYSTEMD}/bin/bootctl", f"--esp-path={EFI_SYS_MOUNT_POINT}", "status"], universal_newlines=True)
# See status_binaries() in systemd bootctl.c for code which generates this
installed_match = re.search(r"^\W+File:.*/EFI/(?:BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$",
@ -276,10 +289,10 @@ def install_bootloader(args: argparse.Namespace) -> None:
if installed_version < available_version:
print("updating systemd-boot from %s to %s" % (installed_version, available_version))
subprocess.check_call(["@systemd@/bin/bootctl", "--esp-path=@efiSysMountPoint@"] + bootctl_flags + ["update"])
subprocess.check_call([f"{SYSTEMD}/bin/bootctl", f"--esp-path={EFI_SYS_MOUNT_POINT}"] + bootctl_flags + ["update"])
os.makedirs("@efiSysMountPoint@/efi/nixos", exist_ok=True)
os.makedirs("@efiSysMountPoint@/loader/entries", exist_ok=True)
os.makedirs(f"{EFI_SYS_MOUNT_POINT}/efi/nixos", exist_ok=True)
os.makedirs(f"{EFI_SYS_MOUNT_POINT}/loader/entries", exist_ok=True)
gens = get_generations()
for profile in get_profiles():
@ -302,9 +315,9 @@ def install_bootloader(args: argparse.Namespace) -> None:
else:
raise e
for root, _, files in os.walk('@efiSysMountPoint@/efi/nixos/.extra-files', topdown=False):
relative_root = root.removeprefix("@efiSysMountPoint@/efi/nixos/.extra-files").removeprefix("/")
actual_root = os.path.join("@efiSysMountPoint@", relative_root)
for root, _, files in os.walk(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/.extra-files", topdown=False):
relative_root = root.removeprefix(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/.extra-files").removeprefix("/")
actual_root = os.path.join(f"{EFI_SYS_MOUNT_POINT}", relative_root)
for file in files:
actual_file = os.path.join(actual_root, file)
@ -317,14 +330,14 @@ def install_bootloader(args: argparse.Namespace) -> None:
os.rmdir(actual_root)
os.rmdir(root)
os.makedirs("@efiSysMountPoint@/efi/nixos/.extra-files", exist_ok=True)
os.makedirs(f"{EFI_SYS_MOUNT_POINT}/efi/nixos/.extra-files", exist_ok=True)
subprocess.check_call("@copyExtraFiles@")
subprocess.check_call(COPY_EXTRA_FILES)
def main() -> None:
parser = argparse.ArgumentParser(description='Update @distroName@-related systemd-boot files')
parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default @distroName@ config to boot')
parser = argparse.ArgumentParser(description=f"Update {DISTRO_NAME}-related systemd-boot files")
parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help=f"The default {DISTRO_NAME} config to boot")
args = parser.parse_args()
try:
@ -334,9 +347,9 @@ def main() -> None:
# it can leave the system in an unbootable state, when a crash/outage
# happens shortly after an update. To decrease the likelihood of this
# event sync the efi filesystem after each update.
rc = libc.syncfs(os.open("@efiSysMountPoint@", os.O_RDONLY))
rc = libc.syncfs(os.open(f"{EFI_SYS_MOUNT_POINT}", os.O_RDONLY))
if rc != 0:
print("could not sync @efiSysMountPoint@: {}".format(os.strerror(rc)), file=sys.stderr)
print(f"could not sync {EFI_SYS_MOUNT_POINT}: {os.strerror(rc)}", file=sys.stderr)
if __name__ == '__main__':

View File

@ -81,7 +81,11 @@ in {
type = types.bool;
description = lib.mdDoc "Whether to enable the systemd-boot (formerly gummiboot) EFI boot manager";
description = lib.mdDoc ''
Whether to enable the systemd-boot (formerly gummiboot) EFI boot manager.
For more information about systemd-boot:
https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/
'';
};
editor = mkOption {

View File

@ -451,20 +451,37 @@ in
cfg.services
);
assertions = concatLists (
mapAttrsToList
(name: service:
map (message: {
assertion = false;
inherit message;
}) (concatLists [
(optional ((builtins.elem "network-interfaces.target" service.after) || (builtins.elem "network-interfaces.target" service.wants))
"Service '${name}.service' is using the deprecated target network-interfaces.target, which no longer exists. Using network.target is recommended instead."
)
])
)
cfg.services
);
assertions = let
mkOneAssert = typeStr: name: def: {
assertion = lib.elem "network-online.target" def.after -> lib.elem "network-online.target" (def.wants ++ def.requires ++ def.bindsTo);
message = "${name}.${typeStr} is ordered after 'network-online.target' but doesn't depend on it";
};
mkAsserts = typeStr: lib.mapAttrsToList (mkOneAssert typeStr);
mkMountAsserts = typeStr: map (m: mkOneAssert typeStr m.what m);
in mkMerge [
(concatLists (
mapAttrsToList
(name: service:
map (message: {
assertion = false;
inherit message;
}) (concatLists [
(optional ((builtins.elem "network-interfaces.target" service.after) || (builtins.elem "network-interfaces.target" service.wants))
"Service '${name}.service' is using the deprecated target network-interfaces.target, which no longer exists. Using network.target is recommended instead."
)
])
)
cfg.services
))
(mkAsserts "target" cfg.targets)
(mkAsserts "service" cfg.services)
(mkAsserts "socket" cfg.sockets)
(mkAsserts "timer" cfg.timers)
(mkAsserts "path" cfg.paths)
(mkMountAsserts "mount" cfg.mounts)
(mkMountAsserts "automount" cfg.automounts)
(mkAsserts "slice" cfg.slices)
];
system.build.units = cfg.units;
@ -641,7 +658,6 @@ in
systemd.services.systemd-udev-settle.restartIfChanged = false; # Causes long delays in nixos-rebuild
systemd.targets.local-fs.unitConfig.X-StopOnReconfiguration = true;
systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true;
systemd.targets.network-online.wantedBy = [ "multi-user.target" ];
systemd.services.systemd-importd.environment = proxy_env;
systemd.services.systemd-pstore.wantedBy = [ "sysinit.target" ]; # see #81138

View File

@ -71,6 +71,7 @@ in
systemd.services.fetch-ec2-metadata = {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = ["network-online.target"];
path = [ pkgs.curl ];
script = builtins.readFile ./ec2-metadata-fetcher.sh;

View File

@ -267,6 +267,7 @@ let
};
in {
wantedBy = [] ++ optional (container.autoStart) "multi-user.target";
wants = lib.optional (container.imageFile == null) "network-online.target";
after = lib.optionals (cfg.backend == "docker") [ "docker.service" "docker.socket" ]
# if imageFile is not set, the service needs the network to download the image from the registry
++ lib.optionals (container.imageFile == null) [ "network-online.target" ]

View File

@ -150,26 +150,33 @@ in
};
config = lib.mkIf cfg.enable
{
config =
let
networkConfig = ({
dns_enabled = false;
driver = "bridge";
id = "0000000000000000000000000000000000000000000000000000000000000000";
internal = false;
ipam_options = { driver = "host-local"; };
ipv6_enabled = false;
name = "podman";
network_interface = "podman0";
subnets = [{ gateway = "10.88.0.1"; subnet = "10.88.0.0/16"; }];
} // cfg.defaultNetwork.settings);
inherit (networkConfig) dns_enabled network_interface;
in
lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ]
++ lib.optional cfg.dockerCompat dockerCompat;
# https://github.com/containers/podman/blob/097cc6eb6dd8e598c0e8676d21267b4edb11e144/docs/tutorials/basic_networking.md#default-network
environment.etc."containers/networks/podman.json" = lib.mkIf (cfg.defaultNetwork.settings != { }) {
source = json.generate "podman.json" ({
dns_enabled = false;
driver = "bridge";
id = "0000000000000000000000000000000000000000000000000000000000000000";
internal = false;
ipam_options = { driver = "host-local"; };
ipv6_enabled = false;
name = "podman";
network_interface = "podman0";
subnets = [{ gateway = "10.88.0.1"; subnet = "10.88.0.0/16"; }];
} // cfg.defaultNetwork.settings);
source = json.generate "podman.json" networkConfig;
};
# containers cannot reach aardvark-dns otherwise
networking.firewall.interfaces.${network_interface}.allowedUDPPorts = lib.mkIf dns_enabled [ 53 ];
virtualisation.containers = {
enable = true; # Enable common /etc/containers configuration
containersConf.settings = {

View File

@ -134,6 +134,7 @@
testScript = ''
start_all()
peer0.systemctl("start network-online.target")
peer0.wait_for_unit("network-online.target")
peer1.wait_for_unit("3proxy.service")

View File

@ -522,6 +522,7 @@ in {
'curl --data \'{"host": "${caDomain}", "addresses": ["${nodes.acme.networking.primaryIPAddress}"]}\' http://${dnsServerIP nodes}:8055/add-a'
)
acme.systemctl("start network-online.target")
acme.wait_for_unit("network-online.target")
acme.wait_for_unit("pebble.service")

View File

@ -126,6 +126,7 @@
with subtest("Testing successful DHCP start"):
dhcpConf.wait_for_unit("adguardhome.service")
client.systemctl("start network-online.target")
client.wait_for_unit("network-online.target")
# Test IP assignment via DHCP
dhcpConf.wait_until_succeeds("ping -c 5 10.0.10.100")

View File

@ -587,6 +587,7 @@ in {
nginx-globalredirect = handleTest ./nginx-globalredirect.nix {};
nginx-http3 = handleTest ./nginx-http3.nix {};
nginx-modsecurity = handleTest ./nginx-modsecurity.nix {};
nginx-moreheaders = handleTest ./nginx-moreheaders.nix {};
nginx-njs = handleTest ./nginx-njs.nix {};
nginx-proxyprotocol = handleTest ./nginx-proxyprotocol {};
nginx-pubhtml = handleTest ./nginx-pubhtml.nix {};
@ -808,6 +809,7 @@ in {
stunnel = handleTest ./stunnel.nix {};
sudo = handleTest ./sudo.nix {};
sudo-rs = handleTest ./sudo-rs.nix {};
suwayomi-server = handleTest ./suwayomi-server.nix {};
swap-file-btrfs = handleTest ./swap-file-btrfs.nix {};
swap-partition = handleTest ./swap-partition.nix {};
swap-random-encryption = handleTest ./swap-random-encryption.nix {};

View File

@ -8,6 +8,9 @@
let
rootPartitionLabel = "root";
imageId = "nixos-appliance";
imageVersion = "1-rc1";
bootLoaderConfigPath = "/loader/entries/nixos.conf";
kernelPath = "/EFI/nixos/kernel.efi";
initrdPath = "/EFI/nixos/initrd.efi";
@ -29,6 +32,9 @@ in
# TODO(raitobezarius): revisit this when #244907 lands
boot.loader.grub.enable = false;
system.image.id = imageId;
system.image.version = imageVersion;
virtualisation.fileSystems = lib.mkForce {
"/" = {
device = "/dev/disk/by-partlabel/${rootPartitionLabel}";
@ -99,7 +105,7 @@ in
"-f",
"qcow2",
"-b",
"${nodes.machine.system.build.image}/image.raw",
"${nodes.machine.system.build.image}/${nodes.machine.image.repart.imageFile}",
"-F",
"raw",
tmp_disk_image.name,
@ -108,6 +114,10 @@ in
# Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
os_release = machine.succeed("cat /etc/os-release")
assert 'IMAGE_ID="${imageId}"' in os_release
assert 'IMAGE_VERSION="${imageVersion}"' in os_release
bootctl_status = machine.succeed("bootctl status")
assert "${bootLoaderConfigPath}" in bootctl_status
assert "${kernelPath}" in bootctl_status

View File

@ -4,7 +4,7 @@ in {
name = "ayatana-indicators";
meta = {
maintainers = with lib.maintainers; [ OPNA2608 ];
maintainers = lib.teams.lomiri.members;
};
nodes.machine = { config, ... }: {
@ -28,16 +28,34 @@ in {
enable = true;
packages = with pkgs; [
ayatana-indicator-messages
];
] ++ (with pkgs.lomiri; [
lomiri-indicator-network
]);
};
# Services needed by some indicators
# Setup needed by some indicators
services.accounts-daemon.enable = true; # messages
# Lomiri-ish setup for Lomiri indicators
# TODO move into a Lomiri module, once the package set is far enough for the DE to start
networking.networkmanager.enable = true; # lomiri-network-indicator
# TODO potentially urfkill for lomiri-network-indicator?
};
# TODO session indicator starts up in a semi-broken state, but works fine after a restart. maybe being started before graphical session is truly up & ready?
testScript = { nodes, ... }: let
runCommandPerIndicatorService = command: lib.strings.concatMapStringsSep "\n" command nodes.machine.systemd.user.targets."ayatana-indicators".wants;
runCommandOverServiceList = list: command:
lib.strings.concatMapStringsSep "\n" command list;
runCommandOverAyatanaIndicators = runCommandOverServiceList
(builtins.filter
(service: !(lib.strings.hasPrefix "lomiri" service || lib.strings.hasPrefix "telephony-service" service))
nodes.machine.systemd.user.targets."ayatana-indicators".wants);
runCommandOverAllIndicators = runCommandOverServiceList
nodes.machine.systemd.user.targets."ayatana-indicators".wants;
in ''
start_all()
machine.wait_for_x()
@ -50,7 +68,7 @@ in {
machine.sleep(10)
# Now check if all indicators were brought up successfully, and kill them for later
'' + (runCommandPerIndicatorService (service: let serviceExec = builtins.replaceStrings [ "." ] [ "-" ] service; in ''
'' + (runCommandOverAyatanaIndicators (service: let serviceExec = builtins.replaceStrings [ "." ] [ "-" ] service; in ''
machine.succeed("pgrep -f ${serviceExec}")
machine.succeed("pkill -f ${serviceExec}")
'')) + ''
@ -65,7 +83,7 @@ in {
machine.sleep(10)
# Now check if all indicator services were brought up successfully
'' + runCommandPerIndicatorService (service: ''
'' + runCommandOverAllIndicators (service: ''
machine.wait_for_unit("${service}", "${user}")
'');
})

View File

@ -120,10 +120,6 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
''
start_all()
client.wait_for_unit("network-online.target")
local_router.wait_for_unit("network-online.target")
remote_router.wait_for_unit("network-online.target")
local_router.wait_for_unit("babeld.service")
remote_router.wait_for_unit("babeld.service")

View File

@ -115,6 +115,7 @@ in
start_all()
# Wait for network and miniupnpd.
router.systemctl("start network-online.target")
router.wait_for_unit("network-online.target")
router.wait_for_unit("miniupnpd")
@ -129,6 +130,7 @@ in
tracker.succeed("chmod 644 /tmp/test.torrent")
# Start the tracker. !!! use a less crappy tracker
tracker.systemctl("start network-online.target")
tracker.wait_for_unit("network-online.target")
tracker.wait_for_unit("opentracker.service")
tracker.wait_for_open_port(6969)
@ -140,6 +142,7 @@ in
# Now we should be able to download from the client behind the NAT.
tracker.wait_for_unit("httpd")
client1.systemctl("start network-online.target")
client1.wait_for_unit("network-online.target")
client1.succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent >&2 &")
client1.wait_for_file("${download-dir}/test.tar.bz2")
@ -152,6 +155,7 @@ in
# Now download from the second client. This can only succeed if
# the first client created a NAT hole in the router.
client2.systemctl("start network-online.target")
client2.wait_for_unit("network-online.target")
client2.succeed(
"transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht >&2 &"

View File

@ -71,6 +71,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
gitrepo.wait_for_unit("multi-user.target")
with subtest("Repo is accessible via git daemon"):
bbmaster.systemctl("start network-online.target")
bbmaster.wait_for_unit("network-online.target")
bbmaster.succeed("rm -rfv /tmp/fakerepo")
bbmaster.succeed("git clone git://gitrepo/fakerepo /tmp/fakerepo")
@ -78,6 +79,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
with subtest("Master service and worker successfully connect"):
bbmaster.wait_for_unit("buildbot-master.service")
bbmaster.wait_until_succeeds("curl --fail -s --head http://bbmaster:8010")
bbworker.systemctl("start network-online.target")
bbworker.wait_for_unit("network-online.target")
bbworker.succeed("nc -z bbmaster 8010")
bbworker.succeed("nc -z bbmaster 9989")

View File

@ -56,6 +56,8 @@ import ./make-test-python.nix (
with subtest("Wait for CoreRAD and network ready"):
# Ensure networking is online and CoreRAD is ready.
router.systemctl("start network-online.target")
client.systemctl("start network-online.target")
router.wait_for_unit("network-online.target")
client.wait_for_unit("network-online.target")
router.wait_for_unit("corerad.service")

View File

@ -144,6 +144,8 @@ in {
start_all()
with subtest("Wait for network"):
web.systemctl("start network-online.target")
curl.systemctl("start network-online.target")
web.wait_for_unit("network-online.target")
curl.wait_for_unit("network-online.target")

View File

@ -55,6 +55,8 @@ import ./make-test-python.nix ({ pkgs, ...} : {
''
start_all()
client.systemctl("start network-online.target")
server.systemctl("start network-online.target")
client.wait_for_unit("network-online.target")
server.wait_for_unit("network-online.target")
server.wait_for_unit("ferm.service")

View File

@ -59,6 +59,9 @@ in {
with subtest("git daemon starts"):
server.wait_for_unit("git-daemon.service")
server.systemctl("start network-online.target")
client.systemctl("start network-online.target")
server.wait_for_unit("network-online.target")
client.wait_for_unit("network-online.target")

Some files were not shown because too many files have changed in this diff Show More