Compare commits

...

40 Commits

Author SHA1 Message Date
home-manager-ci[bot]
233cd20d5f flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/c0b0e0fddf73fd517c3471e546c0df87a42d53f4?narHash=sha256-coBu0ONtFzlwwVBzmjacUQwj3G%2BlybcZ1oeNSQkgC0M%3D' (2025-12-28)
  → 'github:NixOS/nixpkgs/9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5?narHash=sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i%2BbwD6XxMb8A%3D' (2026-01-05)
2026-01-07 04:29:34 +00:00
Robert Helgesson
4e8b7bef66 ghostty: prevent service restarts
Stopping or restarting the service will destroy open Ghostty sessions,
potentially disrupting work. This change ensures that we leave the
existing service untouched.

Fixes #8485
2026-01-06 23:26:04 +01:00
Benedikt Rips
6e94d8157c keepassxc: point to the default upstream branch 2026-01-06 22:08:42 +01:00
Benedikt Rips
6e3931c01f keepassxc: add note about error message in the GUI 2026-01-06 22:08:42 +01:00
N4CH723HR3R
c91dbdf61a hyprland: dont recompile when disabling xwayland
xwayland can be disabled in the settings without recompiling hyprland
2026-01-06 22:07:12 +01:00
Timothy Gallion
38e187fd2f podman-linux: fix tests expected results and modules
Update the expected results to match changes in the podman generator
and fix not importing the podman stub overlay with module import
behind `mkIf` introduced in #6905.
2026-01-06 13:35:00 +01:00
Robert Helgesson
9bfca5b3a7 tree-wide: remove redundant platform checks
In the code base, there are lots of configurations locally guarded by
`stdenv.hostPlatform.is(Darwin|Linux)` despite the targeted options
already being guarded. Examples for these targeted options are:

- `systemd.user.*`: globally guarded by `systemd.user.enable`.
- `launchd.*`: globally guarded by `launchd.enable`.
- `lib.hm.darwin.assertInterval`: only effective on Darwin.

These local guards are an antipattern since they weaken the global
guards. Furthermore, they hamper readability. This series of commits
remove instances of these local guards.
2026-01-06 13:13:38 +01:00
leiserfg
bfaba198af vicinae: use simpler raycast extension in the test
This avoids npm issues.
2026-01-06 09:37:09 +01:00
Robert Helgesson
b1421bdfe5 i18n: merge changes from weblate 2026-01-06 09:32:20 +01:00
sternenseemann
4cd7ae4cd4 neovim: builtins.groupBy -> lib.groupBy
lib.groupBy is an alias for builtins.groupBy which should be
preferred, as it also has a compatibility shim in case the Nix
implementation doesn't have the builtin function.
2026-01-06 09:22:28 +01:00
Anderson Torres
e43f7c3321 treewide: remove AndersonTorres from maintainers. 2026-01-06 09:17:04 +01:00
Benedikt Rips
6841643203 yubikey-agent: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
a755d94ab0 xdg: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
33fe25dbe5 ssh-agent: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
337d3602c0 restic: remove redundant platform checks 2026-01-05 23:10:04 +01:00
Benedikt Rips
5d814af6af pueue: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
787784fb6f ollama: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
2379f704b0 nix-gc: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
a26335db1b nh: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
d016674f6a mpd: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
c2d3a75ebe home-manager-auto-expire: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
93af99ec02 gpg-agent: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
c8b68aafed git-sync: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
bca7415de4 emacs: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
d070d83048 colima: remove redundant platform checks 2026-01-05 23:10:03 +01:00
Benedikt Rips
048104c098 clipse: remove redundant platform checks 2026-01-05 23:10:02 +01:00
Benedikt Rips
af894fbbc7 borgmatic: remove redundant platform checks 2026-01-05 23:10:02 +01:00
Benedikt Rips
53084c95ce atuin: remove redundant platform checks 2026-01-05 23:08:11 +01:00
Robert Helgesson
a65c04965c gpg: update key hash in test
Fixes #8478
2026-01-05 14:29:03 +01:00
Noah765
c4eabb884b hyprpaper: update settings example
The configuration format changed in v0.8.0, which is available on nixpkgs.
2026-01-05 10:52:37 +01:00
June Stepp
156b698b75 anki: fix answerKeys of length one 2026-01-05 10:51:38 +01:00
Hoang Nguyen
9d1c71f390 gpg: add dirmngrSettings and gpgsmSettings options 2026-01-05 10:34:11 +01:00
Hoang Nguyen
47e195783e gpg: remove obsolete default values in the settings
- charset option doesn't exist. The correct option name is display-charset.
- fixed-list-mode option is always used and thus obsolete since GNUPG 2.0.10.
- use-agent is a dummy option. gpg will always requires the agent.
2026-01-05 10:34:11 +01:00
Benedikt Rips
f894bc4ffd ssh-agent: improve handling of SSH_AUTH_SOCK variable
Specifically, only preserve `$SSH_AUTH_SOCK` when it points to a
forwarded agent.
2026-01-04 20:52:35 +01:00
Benedikt Rips
73f5a5ecc9 ssh-agent: fix Nushell's check for emptiness
Previously, it would not succeed if `$env.SSH_AUTH_SOCK` is set to an
empty string.
2026-01-04 20:52:35 +01:00
Naïm Camille Favier
7d5927b63c xfconf: fix package 2026-01-04 12:26:39 +01:00
Ivan Isakov
8f7d6bacb6 launchd: Restore errexit after setting up launchd agents
At the beginning of the setup script `errexit` is disabled, but never
properly enabled again at the end. This causes potential issues/errors
in activation scripts following `setupLaunchAgents` to go unnoticed,
since the build doesn't actually fail.
2026-01-04 11:30:04 +01:00
Alex Martens
12cc14271b hyprshell: fix broken links 2026-01-04 09:32:19 +01:00
Benedikt Rips
c211298f7e tree-wide: use lib.hm.assertions.assertPlatform 2026-01-04 09:31:10 +01:00
Urocissa Caerulea.Tw
2f93d7333e Translate using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (39 of 39 strings)

Translate using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (39 of 39 strings)

Translate using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (17 of 17 strings)

Co-authored-by: Urocissa Caerulea.Tw <urocissa.tw@proton.me>
Translate-URL: https://hosted.weblate.org/projects/home-manager/cli/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/home-manager/modules/zh_Hant/
Translation: Home Manager/Home Manager CLI
Translation: Home Manager/Home Manager Modules
2025-12-04 09:16:41 +00:00
57 changed files with 1417 additions and 1388 deletions

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1766902085,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"lastModified": 1767640445,
"narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5",
"type": "github"
},
"original": {

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-07-22 10:59+0200\n"
"PO-Revision-Date: 2025-12-04 04:17+0000\n"
"PO-Revision-Date: 2025-12-04 09:16+0000\n"
"Last-Translator: \"Urocissa Caerulea.Tw\" <urocissa.tw@proton.me>\n"
"Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/"
"projects/home-manager/cli/zh_Hant/>\n"
@@ -215,7 +215,7 @@ msgstr "沒有即將過期的世代"
#: home-manager/home-manager:877
msgid "No home-manager packages seem to be installed."
msgstr "似乎沒有安裝 home-manager 軟體包。"
msgstr "似乎沒有安裝 home-manager 套件。"
#: home-manager/home-manager:962
msgid "Unknown argument %s"
@@ -223,11 +223,11 @@ msgstr "未知引數 %s"
#: home-manager/home-manager:987
msgid "This will remove Home Manager from your system."
msgstr "這將會從系統中移除 Home Manager。"
msgstr "這將會從您的系統中移除 Home Manager。"
#: home-manager/home-manager:990
msgid "This is a dry run, nothing will actually be uninstalled."
msgstr "這是試執行結果,沒有實際解除安裝任何軟體包。"
msgstr "這是模擬執行,實際上並不會解除安裝任何內容。"
#: home-manager/home-manager:994
msgid "Really uninstall Home Manager?"
@@ -235,27 +235,27 @@ msgstr "確定要解除安裝 Home Manager 嗎?"
#: home-manager/home-manager:1000
msgid "Switching to empty Home Manager configuration..."
msgstr "正在切換至空的 Home Manager 配置 ..."
msgstr "正在切換至空的 Home Manager 設定..."
#: home-manager/home-manager:1015
msgid "Yay!"
msgstr "好耶"
msgstr "太好了"
#: home-manager/home-manager:1020
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr "Home Manager 已解除安裝,但未改動您的 home.nix 配置檔案。"
msgstr "Home Manager 已解除安裝,但您的 home.nix 保持不變。"
#: home-manager/home-manager:1285
msgid "expire-generations expects one argument, got %d."
msgstr "expire-generations 須要一個引數,但獲取到了 %d 個。"
msgstr "expire-generations 預期一個引數,但到了 %d 個。"
#: home-manager/home-manager:1310
msgid "Unknown command: %s"
msgstr "未知令:%s"
msgstr "未知令:%s"
#: home-manager/install.nix:21
msgid "This derivation is not buildable, please run it using nix-shell."
msgstr "此配置檔案/變體不可構建,請在 nix-shell 執行。"
msgstr "此 derivation 無法建置,請使用 nix-shell 執行。"
#, sh-format
#~ msgid "Please set the $EDITOR environment variable"

View File

@@ -270,9 +270,7 @@ in
setupLaunchAgents
# Restore errexit
if [[ -o errexit ]]; then
set -e
fi
set -e
'';
})
];

View File

@@ -136,7 +136,7 @@ in
xdg.stateHome = mkOptionDefault defaultStateHome;
home.sessionVariables = variables;
systemd.user.sessionVariables = mkIf pkgs.stdenv.hostPlatform.isLinux variables;
systemd.user.sessionVariables = variables;
}
)

View File

@@ -135,7 +135,7 @@ in
home.activation.xfconfSettings = lib.hm.dag.entryAfter [ "installPackages" ] (
let
mkCommand = channel: property: value: ''
run ${pkgs.xfce.xfconf}/bin/xfconf-query \
run ${pkgs.xfconf}/bin/xfconf-query \
${lib.escapeShellArgs (
[
"-c"

View File

@@ -112,7 +112,7 @@ let
answer_keys: tuple[tuple[int, str], ...] = (${
lib.strings.concatMapStringsSep ", " (val: "(${toString val.ease}, '${val.key}')") cfg.answerKeys
})
}${if cfg.answerKeys != [ ] then "," else ""})
for ease, key in answer_keys:
profile_manager.set_answer_key(ease, key)

View File

@@ -11,7 +11,6 @@ let
tomlFormat = pkgs.formats.toml { };
inherit (lib) mkIf mkOption types;
inherit (pkgs.stdenv) isLinux isDarwin;
in
{
meta.maintainers = with lib.maintainers; [
@@ -221,98 +220,82 @@ in
};
}
(mkIf daemonCfg.enable (
lib.mkMerge [
(mkIf daemonCfg.enable {
assertions = [
{
assertions = [
{
assertion = lib.versionAtLeast cfg.package.version "18.2.0";
message = ''
The Atuin daemon requires at least version 18.2.0 or later.
'';
}
{
assertion = isLinux || isDarwin;
message = "The Atuin daemon can only be configured on either Linux or macOS.";
}
];
programs.atuin.settings = {
daemon = {
enabled = true;
};
};
assertion = lib.versionAtLeast cfg.package.version "18.2.0";
message = ''
The Atuin daemon requires at least version 18.2.0 or later.
'';
}
(mkIf isLinux {
programs.atuin.settings = {
daemon = {
systemd_socket = true;
};
};
{
assertion = config.systemd.user.enable || config.launchd.enable;
message = "The Atuin daemon can only be configured on systems with systemd or launchd.";
}
];
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin daemon";
Requires = [ "atuin-daemon.socket" ];
};
Install = {
Also = [ "atuin-daemon.socket" ];
WantedBy = [ "default.target" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package} daemon";
Environment = lib.optionals (daemonCfg.logLevel != null) [ "ATUIN_LOG=${daemonCfg.logLevel}" ];
Restart = "on-failure";
RestartSteps = 3;
RestartMaxDelaySec = 6;
};
};
programs.atuin.settings.daemon = {
enabled = true;
systemd_socket = config.systemd.user.enable;
socket_path = lib.mkIf (!config.systemd.user.enable) (
lib.mkDefault "${config.xdg.dataHome}/atuin/daemon.sock"
);
};
systemd.user.sockets.atuin-daemon =
let
socket_dir = if lib.versionAtLeast cfg.package.version "18.4.0" then "%t" else "%D/atuin";
in
{
Unit = {
Description = "Atuin daemon socket";
};
Install = {
WantedBy = [ "sockets.target" ];
};
Socket = {
ListenStream = "${socket_dir}/atuin.sock";
SocketMode = "0600";
RemoveOnStop = true;
};
};
})
(mkIf isDarwin {
programs.atuin.settings = {
daemon = {
socket_path = lib.mkDefault "${config.xdg.dataHome}/atuin/daemon.sock";
};
};
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin daemon";
Requires = [ "atuin-daemon.socket" ];
};
Install = {
Also = [ "atuin-daemon.socket" ];
WantedBy = [ "default.target" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package} daemon";
Environment = lib.optionals (daemonCfg.logLevel != null) [ "ATUIN_LOG=${daemonCfg.logLevel}" ];
Restart = "on-failure";
RestartSteps = 3;
RestartMaxDelaySec = 6;
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"daemon"
];
EnvironmentVariables = lib.optionalAttrs (daemonCfg.logLevel != null) {
ATUIN_LOG = daemonCfg.logLevel;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
};
systemd.user.sockets.atuin-daemon =
let
socket_dir = if lib.versionAtLeast cfg.package.version "18.4.0" then "%t" else "%D/atuin";
in
{
Unit = {
Description = "Atuin daemon socket";
};
})
]
))
Install = {
WantedBy = [ "sockets.target" ];
};
Socket = {
ListenStream = "${socket_dir}/atuin.sock";
SocketMode = "0600";
RemoveOnStop = true;
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"daemon"
];
EnvironmentVariables = lib.optionalAttrs (daemonCfg.logLevel != null) {
ATUIN_LOG = daemonCfg.logLevel;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
};
};
})
]
);
}

View File

@@ -8,7 +8,7 @@ let
cfg = config.programs.bashmount;
in
{
meta.maintainers = [ lib.maintainers.AndersonTorres ];
meta.maintainers = [ ];
options.programs.bashmount = {
enable = lib.mkEnableOption "bashmount";

View File

@@ -224,8 +224,15 @@ in
message = "Ghostty systemd integration cannot be enabled for non-linux platforms";
}
];
xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service".source =
"${cfg.package}/share/systemd/user/app-com.mitchellh.ghostty.service";
xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service.d/overrides.conf".text = ''
[Unit]
X-SwitchMethod=keep-old
'';
dbus.packages = [ cfg.package ];
})

View File

@@ -16,18 +16,13 @@ let
cfg = config.programs.gpg;
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
cfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
listsAsDuplicateKeys = true;
} cfg.settings;
scdaemonCfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
listsAsDuplicateKeys = true;
} cfg.scdaemonSettings;
toKeyValue =
settings:
lib.generators.toKeyValue {
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
listsAsDuplicateKeys = true;
} settings;
primitiveType = types.oneOf [
types.str
@@ -193,6 +188,7 @@ in
scdaemonSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
disable-ccid = true;
@@ -207,6 +203,41 @@ in
'';
};
dirmngrSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
allow-version-check = true;
keyserver = "ldaps://ldap.example.com";
}
'';
description = ''
Dirmngr configuration options. Available options are described
in
[
{manpage}`dirmngr(1)`
](https://www.gnupg.org/documentation/manuals/gnupg/Dirmngr-Options.html)
'';
};
gpgsmSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
with-key-data = true;
}
'';
description = ''
GPGSM configuration options. Available options are described
in
[
{manpage}`gpgsm(1)`
](https://www.gnupg.org/documentation/manuals/gnupg/GPGSM-Options.html)
'';
};
homedir = mkOption {
type = types.path;
example = literalExpression ''"''${config.xdg.dataHome}/gnupg"'';
@@ -267,8 +298,7 @@ in
cert-digest-algo = mkDefault "SHA512";
s2k-digest-algo = mkDefault "SHA512";
s2k-cipher-algo = mkDefault "AES256";
charset = mkDefault "utf-8";
fixed-list-mode = mkDefault true;
display-charset = mkDefault "utf-8";
no-comments = mkDefault true;
no-emit-version = mkDefault true;
keyid-format = mkDefault "0xlong";
@@ -277,11 +307,6 @@ in
with-fingerprint = mkDefault true;
require-cross-certification = mkDefault true;
no-symkey-cache = mkDefault true;
use-agent = mkDefault true;
};
programs.gpg.scdaemonSettings = {
# no defaults for scdaemon
};
home.packages = [ cfg.package ];
@@ -289,9 +314,21 @@ in
GNUPGHOME = cfg.homedir;
};
home.file."${cfg.homedir}/gpg.conf".text = cfgText;
home.file."${cfg.homedir}/gpg.conf" = mkIf (cfg.settings != { }) {
text = toKeyValue cfg.settings;
};
home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText;
home.file."${cfg.homedir}/scdaemon.conf" = mkIf (cfg.scdaemonSettings != { }) {
text = toKeyValue cfg.scdaemonSettings;
};
home.file."${cfg.homedir}/dirmngr.conf" = mkIf (cfg.dirmngrSettings != { }) {
text = toKeyValue cfg.dirmngrSettings;
};
home.file."${cfg.homedir}/gpgsm.conf" = mkIf (cfg.gpgsmSettings != { }) {
text = toKeyValue cfg.gpgsmSettings;
};
# Link keyring if keys are not mutable
home.file."${cfg.homedir}/pubring.kbx" = mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) {

View File

@@ -9,7 +9,7 @@ let
iniFormat = pkgs.formats.ini { };
in
{
meta.maintainers = with lib.maintainers; [ AndersonTorres ];
meta.maintainers = with lib.maintainers; [ ];
options.programs.havoc = {
enable = lib.mkEnableOption "Havoc terminal";

View File

@@ -62,8 +62,15 @@ in
Configuration written to
{file}`$XDG_CONFIG_HOME/keepassxc/keepassxc.ini`.
See <https://github.com/keepassxreboot/keepassxc/blob/647272e9c5542297d3fcf6502e6173c96f12a9a0/src/core/Config.cpp#L49-L223>
See <https://github.com/keepassxreboot/keepassxc/blob/develop/src/core/Config.cpp>
for the full list of options.
::: {.note}
When the settings are non-empty, the configuration file will be linked
into the Nix store and KeePassXC will report an access error for its
configuration file. This is expected and can not be fixed in a way that
aligns with Home Manager's principles. See [#8257](https://github.com/nix-community/home-manager/issues/8257) for more details.
:::
'';
};

View File

@@ -459,7 +459,7 @@ in
generatedConfigs =
let
grouped = builtins.groupBy (x: x.type) pluginsNormalized;
grouped = lib.groupBy (x: x.type) pluginsNormalized;
configsOnly = lib.foldl (acc: p: if p.config != null then acc ++ [ p.config ] else acc) [ ];
in
lib.mapAttrs (_name: vals: lib.concatStringsSep "\n" (configsOnly vals)) grouped;

View File

@@ -100,7 +100,7 @@ in
lib.optional (cfg.clean.enable && config.nix.gc.automatic)
"programs.nh.clean.enable and nix.gc.automatic (Home-Manager) are both enabled. Please use one or the other to avoid conflict.";
assertions = lib.optionals pkgs.stdenv.isDarwin [
assertions = [
(lib.hm.darwin.assertInterval "programs.nh.clean.dates" cfg.clean.dates pkgs)
];
@@ -131,30 +131,25 @@ in
];
};
systemd.user = lib.mkIf (cfg.clean.enable && pkgs.stdenv.isLinux) {
systemd.user = lib.mkIf cfg.clean.enable {
services.nh-clean = {
Unit.Description = "Nh clean (user)";
Service = {
Type = "oneshot";
ExecStart = "${lib.getExe cfg.package} clean user ${cfg.clean.extraArgs}";
};
};
timers.nh-clean = {
Unit.Description = "Run nh clean";
Timer = {
OnCalendar = cfg.clean.dates;
Persistent = true;
};
Install.WantedBy = [ "timers.target" ];
};
};
launchd.agents.nh-clean = lib.mkIf (cfg.clean.enable && pkgs.stdenv.isDarwin) {
launchd.agents.nh-clean = lib.mkIf cfg.clean.enable {
enable = true;
config = {
ProgramArguments = [
@@ -163,9 +158,7 @@ in
"user"
]
++ lib.optional (cfg.clean.extraArgs != "") cfg.clean.extraArgs;
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval cfg.clean.dates;
};
};
};

View File

@@ -66,10 +66,7 @@ in
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = pkgs.stdenv.hostPlatform.isLinux;
message = "niriswitcher is only available on Linux.";
}
(lib.hm.assertions.assertPlatform "programs.niriswitcher" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View File

@@ -32,78 +32,72 @@ in
};
};
config = lib.mkIf serviceConfig.enable (
lib.mkMerge [
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user = {
services.borgmatic = {
Unit = {
Description = "borgmatic backup";
# Prevent borgmatic from running unless the machine is
# plugged into power:
ConditionACPower = true;
};
Service = {
Type = "oneshot";
# Lower CPU and I/O priority:
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;
Restart = "no";
LogRateLimitIntervalSec = 0;
# Delay start to prevent backups running during boot:
ExecStartPre = "${pkgs.coreutils}/bin/sleep 3m";
ExecStart = ''
${pkgs.systemd}/bin/systemd-inhibit \
--who="borgmatic" \
--what="sleep:shutdown" \
--why="Prevent interrupting scheduled backup" \
${programConfig.package}/bin/borgmatic \
--stats \
--verbosity -1 \
--list \
--syslog-verbosity 1
'';
};
};
timers.borgmatic = {
Unit.Description = "Run borgmatic backup";
Timer = {
OnCalendar = serviceConfig.frequency;
Persistent = true;
RandomizedDelaySec = "10m";
};
Install.WantedBy = [ "timers.target" ];
};
config = lib.mkIf serviceConfig.enable {
systemd.user = {
services.borgmatic = {
Unit = {
Description = "borgmatic backup";
# Prevent borgmatic from running unless the machine is
# plugged into power:
ConditionACPower = true;
};
})
Service = {
Type = "oneshot";
(lib.mkIf pkgs.stdenv.isDarwin {
assertions = [
(lib.hm.darwin.assertInterval "services.borgmatic.frequency" serviceConfig.frequency pkgs)
# Lower CPU and I/O priority:
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;
Restart = "no";
LogRateLimitIntervalSec = 0;
# Delay start to prevent backups running during boot:
ExecStartPre = "${pkgs.coreutils}/bin/sleep 3m";
ExecStart = ''
${pkgs.systemd}/bin/systemd-inhibit \
--who="borgmatic" \
--what="sleep:shutdown" \
--why="Prevent interrupting scheduled backup" \
${programConfig.package}/bin/borgmatic \
--stats \
--verbosity -1 \
--list \
--syslog-verbosity 1
'';
};
};
timers.borgmatic = {
Unit.Description = "Run borgmatic backup";
Timer = {
OnCalendar = serviceConfig.frequency;
Persistent = true;
RandomizedDelaySec = "10m";
};
Install.WantedBy = [ "timers.target" ];
};
};
assertions = [
(lib.hm.darwin.assertInterval "services.borgmatic.frequency" serviceConfig.frequency pkgs)
];
launchd.agents.borgmatic = {
enable = true;
config = {
ProgramArguments = [
(lib.getExe programConfig.package)
"--stats"
"--list"
];
launchd.agents.borgmatic = {
enable = true;
config = {
ProgramArguments = [
(lib.getExe programConfig.package)
"--stats"
"--list"
];
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval serviceConfig.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stderr.log";
};
};
})
]
);
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval serviceConfig.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/borgmatic/launchd-stderr.log";
};
};
};
}

View File

@@ -156,7 +156,7 @@ in
xdg.configFile."clipse/custom_theme.json".source = jsonFormat.generate "theme" cfg.theme;
systemd.user.services.clipse = lib.mkIf (pkgs.stdenv.isLinux && (cfg.package != null)) {
systemd.user.services.clipse = lib.mkIf (cfg.package != null) {
Unit = {
Description = "Clipse listener";
PartOf = [ "graphical-session.target" ];

View File

@@ -163,7 +163,7 @@ in
};
};
config = lib.mkIf cfg.enable ({
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = (lib.count (p: p.isActive) (lib.attrValues cfg.profiles)) <= 1;
@@ -189,78 +189,74 @@ in
if activeProfile.name != "default" then "colima-${activeProfile.name}" else "colima"
);
launchd.agents = lib.mkIf pkgs.stdenv.isDarwin (
lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"start"
name
"-f"
"--activate=${if profile.isActive then "true" else "false"}"
"--save-config=false"
];
KeepAlive = true;
RunAtLoad = true;
EnvironmentVariables.PATH = lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
pkgs.darwin.DarwinTools
];
StandardOutPath = profile.logFile;
StandardErrorPath = profile.logFile;
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles)
);
launchd.agents = lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"start"
name
"-f"
"--activate=${if profile.isActive then "true" else "false"}"
"--save-config=false"
];
KeepAlive = true;
RunAtLoad = true;
EnvironmentVariables.PATH = lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
pkgs.darwin.DarwinTools
];
StandardOutPath = profile.logFile;
StandardErrorPath = profile.logFile;
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles);
systemd.user.services = lib.mkIf pkgs.stdenv.isLinux (
lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
Unit = {
Description = "Colima container runtime (${name} profile)";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
ExecStart = ''
${lib.getExe cfg.package} start ${name} \
-f \
--activate=${if profile.isActive then "true" else "false"} \
--save-config=false
'';
Restart = "always";
RestartSec = 2;
Environment = [
"PATH=${
lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
]
}"
];
StandardOutput = "append:${profile.logFile}";
StandardError = "append:${profile.logFile}";
};
Install = {
WantedBy = [ "default.target" ];
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles)
);
});
systemd.user.services = lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
Unit = {
Description = "Colima container runtime (${name} profile)";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
ExecStart = ''
${lib.getExe cfg.package} start ${name} \
-f \
--activate=${if profile.isActive then "true" else "false"} \
--save-config=false
'';
Restart = "always";
RestartSec = 2;
Environment = [
"PATH=${
lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
]
}"
];
StandardOutput = "append:${profile.logFile}";
StandardError = "append:${profile.logFile}";
};
Install = {
WantedBy = [ "default.target" ];
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles);
};
}

View File

@@ -119,127 +119,117 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{
home.sessionVariables =
let
editorBin = lib.getBin (
pkgs.writeShellScript "editor" ''exec ${lib.getBin cfg.package}/bin/emacsclient "''${@:---create-frame}"''
);
in
mkIf cfg.defaultEditor {
EDITOR = editorBin;
VISUAL = editorBin;
};
config = mkIf cfg.enable {
home.sessionVariables =
let
editorBin = lib.getBin (
pkgs.writeShellScript "editor" ''exec ${lib.getBin cfg.package}/bin/emacsclient "''${@:---create-frame}"''
);
in
mkIf cfg.defaultEditor {
EDITOR = editorBin;
VISUAL = editorBin;
};
home.packages = optional (cfg.client.enable && pkgs.stdenv.isLinux) (lib.hiPrio clientDesktopItem);
systemd.user.services.emacs = {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
After = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
PartOf = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
# Avoid killing the Emacs session, which may be full of
# unsaved buffers.
X-RestartIfChanged = false;
}
// optionalAttrs needsSocketWorkaround {
# Emacs deletes its socket when shutting down, which systemd doesn't
# handle, resulting in a server without a socket.
# See https://github.com/nix-community/home-manager/issues/2018
RefuseManualStart = true;
};
(mkIf pkgs.stdenv.isLinux {
systemd.user.services.emacs = {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
Service = {
Type = "notify";
After = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
PartOf = optional (cfg.startWithUserSession == "graphical") "graphical-session.target";
# We wrap ExecStart in a login shell so Emacs starts with the user's
# environment, most importantly $PATH and $NIX_PROFILES. It may be
# worth investigating a more targeted approach for user services to
# import the user environment.
ExecStart = ''${pkgs.runtimeShell} -l -c "${emacsBinPath}/emacs --fg-daemon${
# In case the user sets 'server-directory' or 'server-name' in
# their Emacs config, we want to specify the socket path explicitly
# so launching 'emacs.service' manually doesn't break emacsclient
# when using socket activation.
lib.optionalString cfg.socketActivation.enable "=${lib.escapeShellArg socketPath}"
} ${lib.escapeShellArgs cfg.extraOptions}"'';
# Avoid killing the Emacs session, which may be full of
# unsaved buffers.
X-RestartIfChanged = false;
}
// optionalAttrs needsSocketWorkaround {
# Emacs deletes its socket when shutting down, which systemd doesn't
# handle, resulting in a server without a socket.
# See https://github.com/nix-community/home-manager/issues/2018
RefuseManualStart = true;
};
# Emacs will exit with status 15 after having received SIGTERM, which
# is the default "KillSignal" value systemd uses to stop services.
SuccessExitStatus = 15;
Service = {
Type = "notify";
Restart = "on-failure";
}
// optionalAttrs needsSocketWorkaround {
# Use read-only directory permissions to prevent emacs from
# deleting systemd's socket file before exiting.
ExecStartPost = "${pkgs.coreutils}/bin/chmod --changes -w ${socketDir}";
ExecStopPost = "${pkgs.coreutils}/bin/chmod --changes +w ${socketDir}";
};
}
// optionalAttrs (cfg.startWithUserSession != false) {
Install = {
WantedBy = [
(if cfg.startWithUserSession == true then "default.target" else "graphical-session.target")
];
};
};
# We wrap ExecStart in a login shell so Emacs starts with the user's
# environment, most importantly $PATH and $NIX_PROFILES. It may be
# worth investigating a more targeted approach for user services to
# import the user environment.
ExecStart = ''${pkgs.runtimeShell} -l -c "${emacsBinPath}/emacs --fg-daemon${
# In case the user sets 'server-directory' or 'server-name' in
# their Emacs config, we want to specify the socket path explicitly
# so launching 'emacs.service' manually doesn't break emacsclient
# when using socket activation.
lib.optionalString cfg.socketActivation.enable "=${lib.escapeShellArg socketPath}"
} ${lib.escapeShellArgs cfg.extraOptions}"'';
systemd.user.sockets.emacs = mkIf cfg.socketActivation.enable {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
};
# Emacs will exit with status 15 after having received SIGTERM, which
# is the default "KillSignal" value systemd uses to stop services.
SuccessExitStatus = 15;
Socket = {
ListenStream = socketPath;
FileDescriptorName = "server";
SocketMode = "0600";
DirectoryMode = "0700";
# This prevents the service from immediately starting again
# after being stopped, due to the function
# `server-force-stop' present in `kill-emacs-hook', which
# calls `server-running-p', which opens the socket file.
FlushPending = true;
};
Restart = "on-failure";
}
// optionalAttrs needsSocketWorkaround {
# Use read-only directory permissions to prevent emacs from
# deleting systemd's socket file before exiting.
ExecStartPost = "${pkgs.coreutils}/bin/chmod --changes -w ${socketDir}";
ExecStopPost = "${pkgs.coreutils}/bin/chmod --changes +w ${socketDir}";
};
}
// optionalAttrs (cfg.startWithUserSession != false) {
Install = {
WantedBy = [
(if cfg.startWithUserSession == true then "default.target" else "graphical-session.target")
];
};
Install = {
WantedBy = [ "sockets.target" ];
# Adding this Requires= dependency ensures that systemd
# manages the socket file, in the case where the service is
# started when the socket is stopped.
# The socket unit is implicitly ordered before the service.
RequiredBy = [ "emacs.service" ];
};
};
launchd.agents.emacs = {
enable = true;
config = {
ProgramArguments = [
"${cfg.package}/bin/emacs"
"--fg-daemon"
]
++ cfg.extraOptions;
RunAtLoad = true;
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
home.packages = optional cfg.client.enable (lib.hiPrio clientDesktopItem);
})
(mkIf (cfg.socketActivation.enable && pkgs.stdenv.isLinux) {
systemd.user.sockets.emacs = {
Unit = {
Description = "Emacs text editor";
Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/";
};
Socket = {
ListenStream = socketPath;
FileDescriptorName = "server";
SocketMode = "0600";
DirectoryMode = "0700";
# This prevents the service from immediately starting again
# after being stopped, due to the function
# `server-force-stop' present in `kill-emacs-hook', which
# calls `server-running-p', which opens the socket file.
FlushPending = true;
};
Install = {
WantedBy = [ "sockets.target" ];
# Adding this Requires= dependency ensures that systemd
# manages the socket file, in the case where the service is
# started when the socket is stopped.
# The socket unit is implicitly ordered before the service.
RequiredBy = [ "emacs.service" ];
};
};
})
(mkIf pkgs.stdenv.isDarwin {
launchd.agents.emacs = {
enable = true;
config = {
ProgramArguments = [
"${cfg.package}/bin/emacs"
"--fg-daemon"
]
++ cfg.extraOptions;
RunAtLoad = true;
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
};
};
})
]
);
};
};
};
}

View File

@@ -15,49 +15,12 @@ let
cfg = config.services.git-sync;
mkUnit = name: repo: {
Unit.Description = "Git Sync ${name}";
Install.WantedBy = [ "default.target" ];
Service = {
Environment = [
"PATH=${
lib.makeBinPath (
with pkgs;
[
openssh
git
]
++ repo.extraPackages
)
}"
"GIT_SYNC_DIRECTORY=${lib.strings.escapeShellArg repo.path}"
"GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
"GIT_SYNC_REPOSITORY=${lib.strings.escapeShellArg repo.uri}"
"GIT_SYNC_INTERVAL=${toString repo.interval}"
];
ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
Restart = "on-abort";
};
};
mkAgent = name: repo: {
enable = true;
config = {
StartInterval = repo.interval;
ProcessType = "Background";
WorkingDirectory = "${repo.path}";
WatchPaths = [ "${repo.path}" ];
ProgramArguments = [ "${cfg.package}/bin/git-sync" ];
};
};
mkService = if pkgs.stdenv.isLinux then mkUnit else mkAgent;
services = lib.mapAttrs' (name: repo: {
name = "git-sync-${name}";
value = mkService name repo;
}) cfg.repositories;
services =
mkService:
lib.mapAttrs' (name: repo: {
name = "git-sync-${name}";
value = mkService name repo;
}) cfg.repositories;
repositoryType = types.submodule (
{ name, ... }:
@@ -141,11 +104,48 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
(mkIf pkgs.stdenv.isLinux { systemd.user.services = services; })
(mkIf pkgs.stdenv.isDarwin { launchd.agents = services; })
]
);
config = mkIf cfg.enable {
launchd.agents = services (
name: repo: {
enable = true;
config = {
StartInterval = repo.interval;
ProcessType = "Background";
WorkingDirectory = "${repo.path}";
WatchPaths = [ "${repo.path}" ];
ProgramArguments = [ "${cfg.package}/bin/git-sync" ];
};
}
);
systemd.user.services = services (
name: repo: {
Unit.Description = "Git Sync ${name}";
Install.WantedBy = [ "default.target" ];
Service = {
Environment = [
"PATH=${
lib.makeBinPath (
with pkgs;
[
openssh
git
]
++ repo.extraPackages
)
}"
"GIT_SYNC_DIRECTORY=${lib.strings.escapeShellArg repo.path}"
"GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
"GIT_SYNC_REPOSITORY=${lib.strings.escapeShellArg repo.uri}"
"GIT_SYNC_INTERVAL=${toString repo.interval}"
];
ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
Restart = "on-abort";
};
}
);
};
}

View File

@@ -344,125 +344,115 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{
# Grab the default binary name and fallback to expected value if `meta.mainProgram` not set
services.gpg-agent.pinentry.program = lib.mkOptionDefault (
cfg.pinentry.package.meta.mainProgram or "pinentry"
);
config = mkIf cfg.enable {
# Grab the default binary name and fallback to expected value if `meta.mainProgram` not set
services.gpg-agent.pinentry.program = lib.mkOptionDefault (
cfg.pinentry.package.meta.mainProgram or "pinentry"
);
home.file."${homedir}/gpg-agent.conf".text = lib.concatStringsSep "\n" (
optional cfg.enableSshSupport "enable-ssh-support"
++ optional cfg.grabKeyboardAndMouse "grab"
++ optional (!cfg.enableScDaemon) "disable-scdaemon"
++ optional cfg.noAllowExternalCache "no-allow-external-cache"
++ optional (cfg.defaultCacheTtl != null) "default-cache-ttl ${toString cfg.defaultCacheTtl}"
++ optional (
cfg.defaultCacheTtlSsh != null
) "default-cache-ttl-ssh ${toString cfg.defaultCacheTtlSsh}"
++ optional (cfg.maxCacheTtl != null) "max-cache-ttl ${toString cfg.maxCacheTtl}"
++ optional (cfg.maxCacheTtlSsh != null) "max-cache-ttl-ssh ${toString cfg.maxCacheTtlSsh}"
++ optional (
cfg.pinentry.package != null
) "pinentry-program ${lib.getExe' cfg.pinentry.package cfg.pinentry.program}"
++ [ cfg.extraConfig ]
);
home.file."${homedir}/gpg-agent.conf".text = lib.concatStringsSep "\n" (
optional cfg.enableSshSupport "enable-ssh-support"
++ optional cfg.grabKeyboardAndMouse "grab"
++ optional (!cfg.enableScDaemon) "disable-scdaemon"
++ optional cfg.noAllowExternalCache "no-allow-external-cache"
++ optional (cfg.defaultCacheTtl != null) "default-cache-ttl ${toString cfg.defaultCacheTtl}"
++ optional (
cfg.defaultCacheTtlSsh != null
) "default-cache-ttl-ssh ${toString cfg.defaultCacheTtlSsh}"
++ optional (cfg.maxCacheTtl != null) "max-cache-ttl ${toString cfg.maxCacheTtl}"
++ optional (cfg.maxCacheTtlSsh != null) "max-cache-ttl-ssh ${toString cfg.maxCacheTtlSsh}"
++ optional (
cfg.pinentry.package != null
) "pinentry-program ${lib.getExe' cfg.pinentry.package cfg.pinentry.program}"
++ [ cfg.extraConfig ]
);
home.sessionVariablesExtra = optionalString cfg.enableSshSupport ''
unset SSH_AGENT_PID
if [ -z "$SSH_CONNECTION" -o -z "$SSH_AUTH_SOCK" ] && [ "''${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
fi
'';
home.sessionVariablesExtra = optionalString cfg.enableSshSupport ''
unset SSH_AGENT_PID
if [ -z "$SSH_CONNECTION" -o -z "$SSH_AUTH_SOCK" ] && [ "''${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
fi
'';
programs = {
bash.initExtra = mkIf cfg.enableBashIntegration gpgBashInitStr;
zsh.initContent = mkIf cfg.enableZshIntegration gpgZshInitStr;
fish.interactiveShellInit = mkIf cfg.enableFishIntegration gpgFishInitStr;
nushell.extraConfig = mkIf cfg.enableNushellIntegration gpgNushellInitStr;
programs = {
bash.initExtra = mkIf cfg.enableBashIntegration gpgBashInitStr;
zsh.initContent = mkIf cfg.enableZshIntegration gpgZshInitStr;
fish.interactiveShellInit = mkIf cfg.enableFishIntegration gpgFishInitStr;
nushell.extraConfig = mkIf cfg.enableNushellIntegration gpgNushellInitStr;
};
# Trailing newlines are important
home.file."${homedir}/sshcontrol" = mkIf (cfg.sshKeys != null) {
text = lib.concatMapStrings (s: ''
${s}
'') cfg.sshKeys;
};
systemd.user = {
services.gpg-agent = {
Unit = {
Description = "GnuPG cryptographic agent and passphrase cache";
Documentation = "man:gpg-agent(1)";
Requires = "gpg-agent.socket";
After = "gpg-agent.socket";
# This is a socket-activated service:
RefuseManualStart = true;
};
}
(mkIf (cfg.sshKeys != null) {
# Trailing newlines are important
home.file."${homedir}/sshcontrol".text = lib.concatMapStrings (s: ''
${s}
'') cfg.sshKeys;
})
Service = {
ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" + optionalString cfg.verbose " --verbose";
ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent";
Environment = [ "GNUPGHOME=${homedir}" ];
};
};
(lib.mkMerge [
(mkIf pkgs.stdenv.isLinux {
systemd.user = {
services.gpg-agent = {
Unit = {
Description = "GnuPG cryptographic agent and passphrase cache";
Documentation = "man:gpg-agent(1)";
Requires = "gpg-agent.socket";
After = "gpg-agent.socket";
# This is a socket-activated service:
RefuseManualStart = true;
};
sockets = {
gpg-agent = mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache";
docs = "man:gpg-agent(1)";
stream = "S.gpg-agent";
fdName = "std";
};
Service = {
ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" + optionalString cfg.verbose " --verbose";
ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent";
Environment = [ "GNUPGHOME=${homedir}" ];
};
};
gpg-agent-ssh = mkIf cfg.enableSshSupport (mkSocket {
desc = "GnuPG cryptographic agent (ssh-agent emulation)";
docs = "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
stream = "S.gpg-agent.ssh";
fdName = "ssh";
});
sockets = {
gpg-agent = mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache";
docs = "man:gpg-agent(1)";
stream = "S.gpg-agent";
fdName = "std";
};
gpg-agent-extra = mkIf cfg.enableExtraSocket (mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache (restricted)";
docs = "man:gpg-agent(1) man:ssh(1)";
stream = "S.gpg-agent.extra";
fdName = "extra";
});
};
};
gpg-agent-ssh = mkIf cfg.enableSshSupport (mkSocket {
desc = "GnuPG cryptographic agent (ssh-agent emulation)";
docs = "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
stream = "S.gpg-agent.ssh";
fdName = "ssh";
});
gpg-agent-extra = mkIf cfg.enableExtraSocket (mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache (restricted)";
docs = "man:gpg-agent(1) man:ssh(1)";
stream = "S.gpg-agent.extra";
fdName = "extra";
});
};
};
})
(mkIf pkgs.stdenv.isDarwin {
launchd.agents.gpg-agent = {
enable = true;
config = {
ProgramArguments = [
"${gpgPkg}/bin/gpg-agent"
"--supervised"
]
++ optional cfg.verbose "--verbose";
EnvironmentVariables = {
GNUPGHOME = homedir;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = cfg.enableSshSupport;
Sockets = {
Agent = mkAgentSock "S.gpg-agent";
Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh");
Extra = mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra");
};
};
};
})
])
]
);
launchd.agents.gpg-agent = {
enable = true;
config = {
ProgramArguments = [
"${gpgPkg}/bin/gpg-agent"
"--supervised"
]
++ optional cfg.verbose "--verbose";
EnvironmentVariables = {
GNUPGHOME = homedir;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = cfg.enableSshSupport;
Sockets = {
Agent = mkAgentSock "S.gpg-agent";
Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh");
Extra = mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra");
};
};
};
};
}

View File

@@ -81,46 +81,38 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user = {
timers.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations timer";
config = lib.mkIf cfg.enable {
Install.WantedBy = [ "timers.target" ];
Timer = {
OnCalendar = cfg.frequency;
Unit = "home-manager-auto-expire.service";
Persistent = true;
};
};
services.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations";
Service.ExecStart = toString script;
};
systemd.user = {
timers.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations timer";
Install.WantedBy = [ "timers.target" ];
Timer = {
OnCalendar = cfg.frequency;
Unit = "home-manager-auto-expire.service";
Persistent = true;
};
})
};
services.home-manager-auto-expire = {
Unit.Description = "Home Manager expire generations";
Service.ExecStart = toString script;
};
};
(lib.mkIf pkgs.stdenv.isDarwin {
assertions = [
(lib.hm.darwin.assertInterval "services.home-manager.autoExpire.frequency" cfg.frequency pkgs)
];
assertions = [
(lib.hm.darwin.assertInterval "services.home-manager.autoExpire.frequency" cfg.frequency pkgs)
];
launchd.agents.home-manager-auto-expire = {
enable = true;
config = {
ProgramArguments = [ (toString script) ];
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval cfg.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stderr.log";
};
};
})
]
);
launchd.agents.home-manager-auto-expire = {
enable = true;
config = {
ProgramArguments = [ (toString script) ];
ProcessType = "Background";
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval cfg.frequency;
StandardOutPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stdout.log";
StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/home-manager-auto-expire/launchd-stderr.log";
};
};
};
}

View File

@@ -45,16 +45,18 @@ in
'';
example = lib.literalExpression ''
{
ipc = "on";
splash = false;
splash_offset = 2.0;
preload =
[ "/share/wallpapers/buttons.png" "/share/wallpapers/cat_pacman.png" ];
wallpaper = [
"DP-3,/share/wallpapers/buttons.png"
"DP-1,/share/wallpapers/cat_pacman.png"
{
monitor = "DP-3";
path = "/share/wallpapers/buttons.png";
fit_mode = "tile";
}
{
monitor = "DP-1";
path = "/share/wallpapers/cat_pacman.png";
}
];
}
'';

View File

@@ -29,7 +29,7 @@ in
default = { };
description = ''
Configuration settings for hyprshell. All the avaiblable
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/CONFIGURE.md#config-options>
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/docs/CONFIGURE.md#config-options>
'';
};
@@ -38,7 +38,7 @@ in
default = "";
description = ''
CSS file for customizing hyprshell. All the available
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/CONFIGURE.md#css>
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/docs/CONFIGURE.md#css>
'';
};

View File

@@ -182,7 +182,7 @@ in
})
];
systemd.user = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
systemd.user = {
services.mpd = {
Unit = lib.mkMerge [
{
@@ -236,7 +236,7 @@ in
};
};
launchd.agents.mpd = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
launchd.agents.mpd = {
enable = true;
config = {
ProgramArguments = [

View File

@@ -83,56 +83,51 @@ in
};
};
config = lib.mkIf cfg.automatic (
lib.mkMerge [
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user.services.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Service = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "nix-gc" "exec ${nixPackage}/bin/nix-collect-garbage ${
lib.optionalString (cfg.options != null) cfg.options
}";
};
};
systemd.user.timers.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Timer = {
OnCalendar = cfg.dates;
RandomizedDelaySec = cfg.randomizedDelaySec;
Persistent = cfg.persistent;
Unit = "nix-gc.service";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
})
config = lib.mkIf cfg.automatic {
systemd.user.services.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Service = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "nix-gc" "exec ${nixPackage}/bin/nix-collect-garbage ${
lib.optionalString (cfg.options != null) cfg.options
}";
};
};
(lib.mkIf pkgs.stdenv.isDarwin {
assertions = [
{
assertion = (lib.length cfg.dates) == 1;
message = "On Darwin, `nix.gc.dates` must contain a single element.";
}
(lib.hm.darwin.assertInterval "nix.gc.dates.*" (lib.elemAt cfg.dates 0) pkgs)
];
systemd.user.timers.nix-gc = {
Unit = {
Description = "Nix Garbage Collector";
};
Timer = {
OnCalendar = cfg.dates;
RandomizedDelaySec = cfg.randomizedDelaySec;
Persistent = cfg.persistent;
Unit = "nix-gc.service";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
launchd.agents.nix-gc = {
enable = true;
config = {
ProgramArguments = [
"${nixPackage}/bin/nix-collect-garbage"
]
++ lib.optional (cfg.options != null) cfg.options;
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval (lib.elemAt cfg.dates 0);
};
};
})
]
);
assertions = [
{
assertion = pkgs.stdenv.isDarwin -> (lib.length cfg.dates == 1);
message = "On Darwin, `nix.gc.dates` must contain a single element.";
}
(lib.hm.darwin.assertInterval "nix.gc.dates.*" (lib.elemAt cfg.dates 0) pkgs)
];
launchd.agents.nix-gc = {
enable = true;
config = {
ProgramArguments = [
"${nixPackage}/bin/nix-collect-garbage"
]
++ lib.optional (cfg.options != null) cfg.options;
StartCalendarInterval = lib.hm.darwin.mkCalendarInterval (lib.elemAt cfg.dates 0);
};
};
};
}

View File

@@ -87,7 +87,7 @@ in
};
config = mkIf cfg.enable {
systemd.user.services.ollama = mkIf pkgs.stdenv.isLinux {
systemd.user.services.ollama = {
Unit = {
Description = "Server for local large language models";
After = [ "network.target" ];
@@ -105,7 +105,7 @@ in
};
};
launchd.agents.ollama = mkIf pkgs.stdenv.isDarwin {
launchd.agents.ollama = {
enable = true;
config = {
ProgramArguments = [

View File

@@ -11,7 +11,7 @@ let
pueuedBin = "${cfg.package}/bin/pueued";
in
{
meta.maintainers = [ lib.maintainers.AndersonTorres ];
meta.maintainers = [ ];
options.services.pueue = {
enable = lib.mkEnableOption "Pueue, CLI process scheduler and manager";
@@ -35,51 +35,49 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
}
(lib.mkIf pkgs.stdenv.isLinux {
xdg.configFile."pueue/pueue.yml".source = configFile;
systemd.user = lib.mkIf (cfg.package != null) {
services.pueued = {
Unit = {
Description = "Pueue Daemon - CLI process scheduler and manager";
};
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
Service = {
Restart = "on-failure";
ExecStart = "${pueuedBin} -v -c ${configFile}";
};
xdg.configFile."pueue/pueue.yml" = lib.mkIf pkgs.stdenv.isLinux { source = configFile; };
Install.WantedBy = [ "default.target" ];
};
systemd.user = lib.mkIf (cfg.package != null) {
services.pueued = {
Unit = {
Description = "Pueue Daemon - CLI process scheduler and manager";
};
})
(lib.mkIf pkgs.stdenv.isDarwin {
# This is the default configuration file location for pueue on
# darwin (https://github.com/Nukesor/pueue/wiki/Configuration)
home.file."Library/Application Support/pueue/pueue.yml".source = configFile;
launchd.agents.pueued = lib.mkIf (cfg.package != null) {
enable = true;
config = {
ProgramArguments = [
pueuedBin
"-v"
"-c"
"${configFile}"
];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = true;
};
Service = {
Restart = "on-failure";
ExecStart = "${pueuedBin} -v -c ${configFile}";
};
})
]
);
Install.WantedBy = [ "default.target" ];
};
};
# This is the default configuration file location for pueue on
# darwin (https://github.com/Nukesor/pueue/wiki/Configuration)
home.file."Library/Application Support/pueue/pueue.yml" = lib.mkIf pkgs.stdenv.isDarwin {
source = configFile;
};
launchd.agents.pueued = lib.mkIf (cfg.package != null) {
enable = true;
config = {
ProgramArguments = [
pueuedBin
"-v"
"-c"
"${configFile}"
];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = true;
};
};
};
}

View File

@@ -62,15 +62,13 @@ let
))
];
inherit (pkgs.stdenv.hostPlatform) isLinux;
# Until we have launchd support (#7924), mark the options
# not used in the helper script as "linux exclusive"
linuxExclusive =
option:
option
// {
readOnly = pkgs.stdenv.hostPlatform.isDarwin;
readOnly = !pkgs.stdenv.hostPlatform.isLinux;
description = option.description + ''
@@ -393,219 +391,209 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
assertions = lib.mapAttrsToList (n: v: {
assertion = lib.xor (v.repository == null) (v.repositoryFile == null);
message = "services.restic.backups.${n}: exactly one of repository or repositoryFile should be set";
}) cfg.backups;
}
config = lib.mkIf cfg.enable {
assertions = lib.mapAttrsToList (n: v: {
assertion = lib.xor (v.repository == null) (v.repositoryFile == null);
message = "services.restic.backups.${n}: exactly one of repository or repositoryFile should be set";
}) cfg.backups;
(lib.mkIf isLinux {
systemd.user.services = lib.mapAttrs' (
name: backup:
let
doBackup = backup.dynamicFilesFrom != null || backup.paths != [ ];
doPrune = backup.pruneOpts != [ ];
doCheck = backup.runCheck;
serviceName = "restic-backups-${name}";
systemd.user.services = lib.mapAttrs' (
name: backup:
let
doBackup = backup.dynamicFilesFrom != null || backup.paths != [ ];
doPrune = backup.pruneOpts != [ ];
doCheck = backup.runCheck;
serviceName = "restic-backups-${name}";
extraOptions = lib.concatMap (arg: [
"-o"
arg
]) backup.extraOptions;
extraOptions = lib.concatMap (arg: [
"-o"
arg
]) backup.extraOptions;
excludeFile = pkgs.writeText "exclude-patterns" (lib.concatLines backup.exclude);
excludeFileFlag = "--exclude-file=${excludeFile}";
excludeFile = pkgs.writeText "exclude-patterns" (lib.concatLines backup.exclude);
excludeFileFlag = "--exclude-file=${excludeFile}";
filesFromTmpFile = "/run/user/$UID/${serviceName}/includes";
filesFromFlag = "--files-from=${filesFromTmpFile}";
filesFromTmpFile = "/run/user/$UID/${serviceName}/includes";
filesFromFlag = "--files-from=${filesFromTmpFile}";
inhibitCmd = lib.optionals backup.inhibitsSleep [
"${pkgs.systemd}/bin/systemd-inhibit"
"--mode='block'"
"--who='restic'"
"--what='idle'"
"--why=${lib.escapeShellArg "Scheduled backup ${name}"}"
];
inhibitCmd = lib.optionals backup.inhibitsSleep [
"${pkgs.systemd}/bin/systemd-inhibit"
"--mode='block'"
"--who='restic'"
"--what='idle'"
"--why=${lib.escapeShellArg "Scheduled backup ${name}"}"
];
mkResticCmd' =
pre: args:
lib.concatStringsSep " " (
pre ++ lib.singleton (lib.getExe backup.package) ++ extraOptions ++ lib.flatten args
);
mkResticCmd = mkResticCmd' [ ];
mkResticCmd' =
pre: args:
lib.concatStringsSep " " (
pre ++ lib.singleton (lib.getExe backup.package) ++ extraOptions ++ lib.flatten args
);
mkResticCmd = mkResticCmd' [ ];
backupCmd =
"${lib.getExe pkgs.bash} -c "
+ lib.escapeShellArg (
mkResticCmd' inhibitCmd [
"backup"
backup.extraBackupArgs
excludeFileFlag
filesFromFlag
]
);
backupCmd =
"${lib.getExe pkgs.bash} -c "
+ lib.escapeShellArg (
mkResticCmd' inhibitCmd [
"backup"
backup.extraBackupArgs
excludeFileFlag
filesFromFlag
]
);
forgetCmd = mkResticCmd [
"forget"
"--prune"
backup.pruneOpts
];
checkCmd = mkResticCmd [
"check"
backup.checkOpts
];
unlockCmd = mkResticCmd "unlock";
in
lib.nameValuePair serviceName {
Unit = {
Description = "Restic backup service";
Wants = [ "network-online.target" ];
After = [ "network-online.target" ];
};
forgetCmd = mkResticCmd [
"forget"
"--prune"
backup.pruneOpts
];
checkCmd = mkResticCmd [
"check"
backup.checkOpts
];
unlockCmd = mkResticCmd "unlock";
in
lib.nameValuePair serviceName {
Unit = {
Description = "Restic backup service";
Wants = [ "network-online.target" ];
After = [ "network-online.target" ];
};
Service = {
Type = "oneshot";
Service = {
Type = "oneshot";
X-RestartIfChanged = true;
RuntimeDirectory = serviceName;
CacheDirectory = serviceName;
CacheDirectoryMode = "0700";
PrivateTmp = true;
X-RestartIfChanged = true;
RuntimeDirectory = serviceName;
CacheDirectory = serviceName;
CacheDirectoryMode = "0700";
PrivateTmp = true;
Environment = mkEnvironment backup ++ [ "RESTIC_CACHE_DIR=%C/${serviceName}" ];
Environment = mkEnvironment backup ++ [ "RESTIC_CACHE_DIR=%C/${serviceName}" ];
ExecStart =
lib.optional doBackup backupCmd
++ lib.optionals doPrune [
unlockCmd
forgetCmd
]
++ lib.optional doCheck checkCmd;
ExecStart =
lib.optional doBackup backupCmd
++ lib.optionals doPrune [
unlockCmd
forgetCmd
]
++ lib.optional doCheck checkCmd;
ExecStartPre = lib.getExe (
pkgs.writeShellApplication {
name = "${serviceName}-exec-start-pre";
inherit runtimeInputs;
text = ''
set -x
ExecStartPre = lib.getExe (
pkgs.writeShellApplication {
name = "${serviceName}-exec-start-pre";
inherit runtimeInputs;
text = ''
set -x
${lib.optionalString (backup.backupPrepareCommand != null) ''
${pkgs.writeShellScript "backupPrepareCommand" backup.backupPrepareCommand}
''}
${lib.optionalString (backup.backupPrepareCommand != null) ''
${pkgs.writeShellScript "backupPrepareCommand" backup.backupPrepareCommand}
''}
${lib.optionalString (backup.initialize) ''
${
mkResticCmd [
"cat"
"config"
]
} 2>/dev/null || ${mkResticCmd "init"}
''}
${lib.optionalString (backup.initialize) ''
${
mkResticCmd [
"cat"
"config"
]
} 2>/dev/null || ${mkResticCmd "init"}
''}
${lib.optionalString (backup.paths != null && backup.paths != [ ]) ''
cat ${pkgs.writeText "staticPaths" (lib.concatLines backup.paths)} >> ${filesFromTmpFile}
''}
${lib.optionalString (backup.paths != null && backup.paths != [ ]) ''
cat ${pkgs.writeText "staticPaths" (lib.concatLines backup.paths)} >> ${filesFromTmpFile}
''}
${lib.optionalString (backup.dynamicFilesFrom != null) ''
${pkgs.writeShellScript "dynamicFilesFromScript" backup.dynamicFilesFrom} >> ${filesFromTmpFile}
''}
'';
}
);
ExecStopPost = lib.getExe (
pkgs.writeShellApplication {
name = "${serviceName}-exec-stop-post";
inherit runtimeInputs;
text = ''
set -x
${lib.optionalString (backup.backupCleanupCommand != null) ''
${pkgs.writeShellScript "backupCleanupCommand" backup.backupCleanupCommand}
''}
'';
}
);
${lib.optionalString (backup.dynamicFilesFrom != null) ''
${pkgs.writeShellScript "dynamicFilesFromScript" backup.dynamicFilesFrom} >> ${filesFromTmpFile}
''}
'';
}
// lib.optionalAttrs (backup.environmentFile != null) {
EnvironmentFile = backup.environmentFile;
};
}
) cfg.backups;
})
);
(lib.mkIf isLinux {
systemd.user.timers = lib.mapAttrs' (
name: backup:
lib.nameValuePair "restic-backups-${name}" {
Unit.Description = "Restic backup service";
Install.WantedBy = [ "timers.target" ];
ExecStopPost = lib.getExe (
pkgs.writeShellApplication {
name = "${serviceName}-exec-stop-post";
inherit runtimeInputs;
text = ''
set -x
Timer = backup.timerConfig;
}
) (lib.filterAttrs (_: v: v.timerConfig != null) cfg.backups);
})
{
home.packages = lib.mapAttrsToList (
name: backup:
let
serviceName = "restic-backups-${name}";
environment = mkEnvironment backup;
notPathVar = x: !(lib.hasPrefix "PATH" x);
extraOptions = lib.concatMap (arg: [
"-o"
arg
]) backup.extraOptions;
restic = lib.concatStringsSep " " (
lib.flatten [
(lib.getExe backup.package)
extraOptions
]
);
in
pkgs.writeShellApplication {
name = "restic-${name}";
excludeShellChecks = [
# https://github.com/koalaman/shellcheck/issues/1986
"SC2034"
# Allow sourcing environmentFile
"SC1091"
];
bashOptions = [
"errexit"
"nounset"
"allexport"
];
text = ''
${lib.optionalString (backup.environmentFile != null) ''
source ${backup.environmentFile}
''}
# Set same environment variables as the systemd service
${lib.pipe environment [
(lib.filter notPathVar)
lib.concatLines
]}
RESTIC_CACHE_DIR=${config.xdg.cacheHome}/${serviceName}
PATH=${
lib.pipe environment [
(lib.filter (lib.hasPrefix "PATH="))
lib.head
(lib.removePrefix "PATH=")
]
}:$PATH
exec ${restic} "$@"
'';
}
) (lib.filterAttrs (_: v: v.createWrapper) cfg.backups);
${lib.optionalString (backup.backupCleanupCommand != null) ''
${pkgs.writeShellScript "backupCleanupCommand" backup.backupCleanupCommand}
''}
'';
}
);
}
// lib.optionalAttrs (backup.environmentFile != null) {
EnvironmentFile = backup.environmentFile;
};
}
]
);
) cfg.backups;
systemd.user.timers = lib.mapAttrs' (
name: backup:
lib.nameValuePair "restic-backups-${name}" {
Unit.Description = "Restic backup service";
Install.WantedBy = [ "timers.target" ];
Timer = backup.timerConfig;
}
) (lib.filterAttrs (_: v: v.timerConfig != null) cfg.backups);
home.packages = lib.mapAttrsToList (
name: backup:
let
serviceName = "restic-backups-${name}";
environment = mkEnvironment backup;
notPathVar = x: !(lib.hasPrefix "PATH" x);
extraOptions = lib.concatMap (arg: [
"-o"
arg
]) backup.extraOptions;
restic = lib.concatStringsSep " " (
lib.flatten [
(lib.getExe backup.package)
extraOptions
]
);
in
pkgs.writeShellApplication {
name = "restic-${name}";
excludeShellChecks = [
# https://github.com/koalaman/shellcheck/issues/1986
"SC2034"
# Allow sourcing environmentFile
"SC1091"
];
bashOptions = [
"errexit"
"nounset"
"allexport"
];
text = ''
${lib.optionalString (backup.environmentFile != null) ''
source ${backup.environmentFile}
''}
# Set same environment variables as the systemd service
${lib.pipe environment [
(lib.filter notPathVar)
lib.concatLines
]}
RESTIC_CACHE_DIR=${config.xdg.cacheHome}/${serviceName}
PATH=${
lib.pipe environment [
(lib.filter (lib.hasPrefix "PATH="))
lib.head
(lib.removePrefix "PATH=")
]
}:$PATH
exec ${restic} "$@"
'';
}
) (lib.filterAttrs (_: v: v.createWrapper) cfg.backups);
};
}

View File

@@ -46,89 +46,85 @@ in
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
programs =
config = lib.mkIf cfg.enable {
programs =
let
socketPath =
if pkgs.stdenv.isDarwin then
"$(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"
else
"$XDG_RUNTIME_DIR/${cfg.socket}";
# Preserve $SSH_AUTH_SOCK only if it stems from a forwarded agent which
# is the case if both $SSH_AUTH_SOCK and $SSH_CONNECTION are set.
bashIntegration = ''
if [ -z "$SSH_AUTH_SOCK" -o -z "$SSH_CONNECTION" ]; then
export SSH_AUTH_SOCK=${socketPath}
fi
'';
fishIntegration = ''
if test -z "$SSH_AUTH_SOCK"; or test -z "$SSH_CONNECTION"
set -x SSH_AUTH_SOCK ${socketPath}
end
'';
nushellIntegration =
let
unsetOrEmpty = var: ''("${var}" not-in $env) or ($env.${var} | is-empty)'';
socketPath =
if pkgs.stdenv.isDarwin then
"$(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"
''$"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"''
else
"$XDG_RUNTIME_DIR/${cfg.socket}";
bashIntegration = ''
if [ -z "$SSH_AUTH_SOCK" ]; then
export SSH_AUTH_SOCK=${socketPath}
fi
'';
fishIntegration = ''
if test -z "$SSH_AUTH_SOCK"
set -x SSH_AUTH_SOCK ${socketPath}
end
'';
nushellIntegration =
if pkgs.stdenv.isDarwin then
''
if "SSH_AUTH_SOCK" not-in $env {
$env.SSH_AUTH_SOCK = $"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"
}
''
else
''
if "SSH_AUTH_SOCK" not-in $env {
$env.SSH_AUTH_SOCK = $"($env.XDG_RUNTIME_DIR)/${cfg.socket}"
}
'';
''$"($env.XDG_RUNTIME_DIR)/${cfg.socket}"'';
in
{
# $SSH_AUTH_SOCK has to be set early since other tools rely on it
bash.profileExtra = lib.mkIf cfg.enableBashIntegration (lib.mkOrder 900 bashIntegration);
fish.shellInit = lib.mkIf cfg.enableFishIntegration (lib.mkOrder 900 fishIntegration);
nushell.extraConfig = lib.mkIf cfg.enableNushellIntegration (lib.mkOrder 900 nushellIntegration);
zsh.envExtra = lib.mkIf cfg.enableZshIntegration (lib.mkOrder 900 bashIntegration);
};
}
''
if ${unsetOrEmpty "SSH_AUTH_SOCK"} or ${unsetOrEmpty "SSH_CONNECTION"} {
$env.SSH_AUTH_SOCK = ${socketPath}
}
'';
in
{
# $SSH_AUTH_SOCK has to be set early since other tools rely on it
bash.profileExtra = lib.mkIf cfg.enableBashIntegration (lib.mkOrder 900 bashIntegration);
fish.shellInit = lib.mkIf cfg.enableFishIntegration (lib.mkOrder 900 fishIntegration);
nushell.extraConfig = lib.mkIf cfg.enableNushellIntegration (lib.mkOrder 900 nushellIntegration);
zsh.envExtra = lib.mkIf cfg.enableZshIntegration (lib.mkOrder 900 bashIntegration);
};
(lib.mkIf pkgs.stdenv.isLinux {
systemd.user.services.ssh-agent = {
Install.WantedBy = [ "default.target" ];
Unit = {
Description = "SSH authentication agent";
Documentation = "man:ssh-agent(1)";
};
Service.ExecStart = "${lib.getExe' cfg.package "ssh-agent"} -D -a %t/${cfg.socket}${
systemd.user.services.ssh-agent = {
Install.WantedBy = [ "default.target" ];
Unit = {
Description = "SSH authentication agent";
Documentation = "man:ssh-agent(1)";
};
Service.ExecStart = "${lib.getExe' cfg.package "ssh-agent"} -D -a %t/${cfg.socket}${
lib.optionalString (
cfg.defaultMaximumIdentityLifetime != null
) " -t ${toString cfg.defaultMaximumIdentityLifetime}"
}";
};
launchd.agents.ssh-agent = {
enable = true;
config = {
ProgramArguments = [
(lib.getExe pkgs.bash)
"-c"
''${lib.getExe' cfg.package "ssh-agent"} -D -a "$(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"${
lib.optionalString (
cfg.defaultMaximumIdentityLifetime != null
) " -t ${toString cfg.defaultMaximumIdentityLifetime}"
}";
}''
];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
})
ProcessType = "Background";
RunAtLoad = true;
};
};
};
(lib.mkIf pkgs.stdenv.isDarwin {
launchd.agents.ssh-agent = {
enable = true;
config = {
ProgramArguments = [
(lib.getExe pkgs.bash)
"-c"
''${lib.getExe' cfg.package "ssh-agent"} -D -a "$(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"${
lib.optionalString (
cfg.defaultMaximumIdentityLifetime != null
) " -t ${toString cfg.defaultMaximumIdentityLifetime}"
}''
];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = true;
};
};
})
]
);
}

View File

@@ -11,7 +11,7 @@ let
in
{
meta.maintainers = [ lib.maintainers.AndersonTorres ];
meta.maintainers = [ ];
options = {
xsession.windowManager.fluxbox = {

View File

@@ -48,6 +48,11 @@ in
[ "wayland" "windowManager" "hyprland" "systemdIntegration" ] # \
[ "wayland" "windowManager" "hyprland" "systemd" "enable" ]
)
(lib.mkRenamedOptionModule # \
[ "wayland" "windowManager" "hyprland" "xwayland" "enable" ] # \
[ "wayland" "windowManager" "hyprland" "settings" "xwayland" "enable" ]
)
];
options.wayland.windowManager.hyprland = {
@@ -79,11 +84,7 @@ in
finalPackage = lib.mkOption {
type = with lib.types; nullOr package;
readOnly = true;
default =
if cfg.package != null then
cfg.package.override { enableXWayland = cfg.xwayland.enable; }
else
null;
default = if cfg.package != null then cfg.package else null;
defaultText = lib.literalMD "`wayland.windowManager.hyprland.package` with applied configuration";
description = ''
The Hyprland package after applying configuration.
@@ -162,10 +163,6 @@ in
{manpage}`systemd-xdg-autostart-generator(8)`'';
};
xwayland.enable = lib.mkEnableOption "XWayland" // {
default = true;
};
settings = lib.mkOption {
type =
with lib.types;
@@ -357,7 +354,10 @@ in
submapWarnings ++ lib.optional inconsistent warning;
home.packages = lib.mkIf (cfg.package != null) (
[ cfg.finalPackage ] ++ lib.optional cfg.xwayland.enable pkgs.xwayland
[ cfg.finalPackage ]
++ lib.optional (
(lib.hasAttrByPath [ "settings" "xwayland" "enable" ] cfg) && cfg.settings.xwayland.enable
) pkgs.xwayland
);
xdg.configFile."hypr/hyprland.conf" =

View File

@@ -19,79 +19,71 @@ in
package = lib.mkPackageOption pkgs "yubikey-agent" { };
};
config = mkIf cfg.enable (
lib.mkMerge [
{ home.packages = [ cfg.package ]; }
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
(mkIf pkgs.stdenv.isLinux {
systemd.user.services.yubikey-agent = {
Unit = {
Description = "Seamless ssh-agent for YubiKeys";
Documentation = "https://github.com/FiloSottile/yubikey-agent";
Requires = "yubikey-agent.socket";
After = "yubikey-agent.socket";
RefuseManualStart = true;
};
home.sessionVariables.SSH_AUTH_SOCK =
if pkgs.stdenv.isDarwin then
"/tmp/yubikey-agent.sock"
else
"\${XDG_RUNTIME_DIR:-/run/user/$UID}/yubikey-agent/yubikey-agent.sock";
Service = {
ExecStart = "${cfg.package}/bin/yubikey-agent -l %t/yubikey-agent/yubikey-agent.sock";
Type = "simple";
# /run/user/$UID for the socket
ReadWritePaths = [ "%t" ];
systemd.user.services.yubikey-agent = {
Unit = {
Description = "Seamless ssh-agent for YubiKeys";
Documentation = "https://github.com/FiloSottile/yubikey-agent";
Requires = "yubikey-agent.socket";
After = "yubikey-agent.socket";
RefuseManualStart = true;
};
Service = {
ExecStart = "${cfg.package}/bin/yubikey-agent -l %t/yubikey-agent/yubikey-agent.sock";
Type = "simple";
# /run/user/$UID for the socket
ReadWritePaths = [ "%t" ];
};
};
systemd.user.sockets.yubikey-agent = {
Unit = {
Description = "Unix domain socket for Yubikey SSH agent";
Documentation = "https://github.com/FiloSottile/yubikey-agent";
};
Socket = {
ListenStream = "%t/yubikey-agent/yubikey-agent.sock";
RuntimeDirectory = "yubikey-agent";
SocketMode = "0600";
DirectoryMode = "0700";
};
Install = {
WantedBy = [ "sockets.target" ];
};
};
launchd.agents.yubikey-agent = {
enable = true;
config = {
ProgramArguments = [
"${cfg.package}/bin/yubikey-agent"
"-l"
"/tmp/yubikey-agent.sock"
];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
Sockets = {
Listener = {
SockPathName = "/tmp/yubikey-agent.sock";
SockPathMode = 384; # 0600 in decimal
};
};
systemd.user.sockets.yubikey-agent = {
Unit = {
Description = "Unix domain socket for Yubikey SSH agent";
Documentation = "https://github.com/FiloSottile/yubikey-agent";
};
Socket = {
ListenStream = "%t/yubikey-agent/yubikey-agent.sock";
RuntimeDirectory = "yubikey-agent";
SocketMode = "0600";
DirectoryMode = "0700";
};
Install = {
WantedBy = [ "sockets.target" ];
};
};
home.sessionVariables = {
SSH_AUTH_SOCK = "\${XDG_RUNTIME_DIR:-/run/user/$UID}/yubikey-agent/yubikey-agent.sock";
};
})
(mkIf pkgs.stdenv.isDarwin {
launchd.agents.yubikey-agent = {
enable = true;
config = {
ProgramArguments = [
"${cfg.package}/bin/yubikey-agent"
"-l"
"/tmp/yubikey-agent.sock"
];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
Sockets = {
Listener = {
SockPathName = "/tmp/yubikey-agent.sock";
SockPathMode = 384; # 0600 in decimal
};
};
};
};
home.sessionVariables = {
SSH_AUTH_SOCK = "/tmp/yubikey-agent.sock";
};
})
]
);
};
};
};
}

View File

@@ -430,10 +430,7 @@ in
# Do not install any user services if username is root.
config = mkIf (cfg.enable && config.home.username != "root") {
assertions = [
{
assertion = pkgs.stdenv.isLinux;
message = "This module is only available on Linux.";
}
(lib.hm.assertions.assertPlatform "systemd" pkgs lib.platforms.linux)
];
xdg.configFile = mkMerge [

View File

@@ -1,5 +1,10 @@
{ lib, pkgs, ... }:
{
ghostty-example-settings = ./example-settings.nix;
ghostty-empty-settings = ./empty-settings.nix;
ghostty-example-settings = ./example-settings.nix;
ghostty-example-theme = ./example-theme.nix;
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
ghostty-systemd-service = ./systemd-service.nix;
}

View File

@@ -11,6 +11,9 @@
};
nmt.script = ''
servicePath=home-files/.config/systemd/user/app-com.mitchellh.ghostty.service
assertPathNotExists $servicePath
assertFileContent \
home-files/.config/ghostty/config \
${./example-config-expected}

View File

@@ -0,0 +1,28 @@
{ config, ... }:
{
programs.ghostty = {
enable = true;
package = config.lib.test.mkStubPackage { outPath = null; };
systemd.enable = true;
settings = {
theme = "catppuccin-mocha";
font-size = 10;
};
};
nmt.script = ''
servicePath=home-files/.config/systemd/user/app-com.mitchellh.ghostty.service
serviceOverridesPath=$servicePath.d/overrides.conf
assertFileExists $serviceOverridesPath
assertFileContent $serviceOverridesPath \
${builtins.toFile "ghostty-service-overrides" ''
[Unit]
X-SwitchMethod=keep-old
''}
assertFileContent \
home-files/.config/ghostty/config \
${./example-config-expected}
'';
}

View File

@@ -3,4 +3,5 @@
gpg-mutable-keyfiles = ./mutable-keyfiles.nix;
gpg-multiple-keys-trust = ./multiple-keys-trust.nix;
gpg-override-defaults = ./override-defaults.nix;
gpg-other-settings = ./other-settings.nix;
}

View File

@@ -12,7 +12,7 @@
{
source = realPkgs.fetchurl {
url = "https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x44CF42371ADF842E12F116EAA9D3F98FCCF5460B";
hash = "sha256-bSluCZh6ijwppigk8iF2BwWKZgq1WDbIjyYQRK772dM=";
hash = "sha256-csrFDI6QSPfNN+adOPEAupAtspYNBCybFZExvVS+vRY=";
};
trust = 1; # "unknown"
}

View File

@@ -0,0 +1,2 @@
keyserver ldaps://ldap.example.com
use-tor

View File

@@ -0,0 +1,3 @@
cipher-algo AES256
validation-model steed
with-md5-fingerprint

View File

@@ -0,0 +1,3 @@
application-priority openpgp p15 sc-hsm nks geldkarte dinsig
disable-ccid
reader-port 32769

View File

@@ -0,0 +1,32 @@
{
programs.gpg = {
enable = true;
scdaemonSettings = {
disable-ccid = true;
reader-port = "32769";
application-priority = "openpgp p15 sc-hsm nks geldkarte dinsig";
};
dirmngrSettings = {
use-tor = true;
keyserver = "ldaps://ldap.example.com";
};
gpgsmSettings = {
cipher-algo = "AES256";
with-md5-fingerprint = true;
validation-model = "steed";
};
};
nmt.script = ''
assertFileExists home-files/.gnupg/scdaemon.conf
assertFileExists home-files/.gnupg/dirmngr.conf
assertFileExists home-files/.gnupg/gpgsm.conf
assertFileContent home-files/.gnupg/scdaemon.conf ${./other-scdaemon.conf}
assertFileContent home-files/.gnupg/dirmngr.conf ${./other-dirmngr.conf}
assertFileContent home-files/.gnupg/gpgsm.conf ${./other-gpgsm.conf}
'';
}

View File

@@ -1,7 +1,6 @@
cert-digest-algo SHA512
charset utf-8
default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
fixed-list-mode
display-charset utf-8
keyid-format 0xlong
list-options show-uid-validity
@@ -16,6 +15,5 @@ s2k-digest-algo SHA512
throw-keyids
trusted-key 0xXXXXXXXXXXXXX
trusted-key 0xYYYYYYYYYYYYY
use-agent
verify-options show-uid-validity
with-fingerprint

View File

@@ -62,9 +62,9 @@
extensions = [
(config.lib.vicinae.mkRayCastExtension {
name = "gif-search";
sha256 = "sha256-G7il8T1L+P/2mXWJsb68n4BCbVKcrrtK8GnBNxzt73Q=";
rev = "4d417c2dfd86a5b2bea202d4a7b48d8eb3dbaeb1";
name = "cdnjs";
sha256 = "sha256-k3YfruMxSOMf8K65iTW84aZxiknADCcntJOAE89agYc=";
rev = "ac7c50844bf77d0cf51daa840e369d999f2add59";
})
(config.lib.vicinae.mkExtension {
name = "test-extension";
@@ -88,7 +88,7 @@
assertFileExists "home-files/.config/vicinae/settings.json"
assertFileExists "home-files/.config/systemd/user/vicinae.service"
assertFileExists "home-files/.local/share/vicinae/themes/catppuccin-mocha.toml"
assertFileExists "home-files/.local/share/vicinae/extensions/gif-search/package.json"
assertFileExists "home-files/.local/share/vicinae/extensions/cdnjs/package.json"
assertFileExists "home-files/.local/share/vicinae/extensions/test-extension/package.json"
assertFileContent "home-files/.config/systemd/user/vicinae.service" ${./service.service}
'';

View File

@@ -26,5 +26,5 @@ Type=oneshot
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
Description=Service for build my-bld
RequiresMountsFor=%t/containers
SourcePath=/nix/store/00000000000000000000000000000000-home-build-podman-my-bld/quadlets/podman-my-bld.build
RequiresMountsFor=%t/containers

View File

@@ -4,50 +4,50 @@
pkgs,
...
}:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
builds = {
"my-bld" = {
file =
let
containerFile = pkgs.writeTextFile {
name = "Containerfile";
text = ''
FROM docker.io/alpine:latest
'';
};
in
"${containerFile}";
};
services.podman = {
enable = true;
builds = {
"my-bld" = {
file =
let
containerFile = pkgs.writeTextFile {
name = "Containerfile";
text = ''
FROM docker.io/alpine:latest
'';
};
in
"${containerFile}";
};
"my-bld-2" = {
file = "https://www.github.com/././Containerfile";
extraConfig = {
Build.ImageTag = [
"locahost/somethingelse"
"localhost/anothertag"
];
"my-bld-2" = {
file = "https://www.github.com/././Containerfile";
extraConfig = {
Build.ImageTag = [
"locahost/somethingelse"
"localhost/anothertag"
];
};
};
};
};
test.asserts.assertions.expected = [
''In 'my-bld-2' config. Build.ImageTag: '[ "locahost/somethingelse" "localhost/anothertag" ]' does not contain 'homemanager/my-bld-2'.''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
buildFile=$configPath/podman-my-bld-build.service
assertFileExists $buildFile
buildFile=$(normalizeStorePaths $buildFile)
assertFileContent $buildFile ${./build-expected.service}
'';
};
test.asserts.assertions.expected = [
''In 'my-bld-2' config. Build.ImageTag: '[ "locahost/somethingelse" "localhost/anothertag" ]' does not contain 'homemanager/my-bld-2'.''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
buildFile=$configPath/podman-my-bld-build.service
assertFileExists $buildFile
buildFile=$(normalizeStorePaths $buildFile)
assertFileContent $buildFile ${./build-expected.service}
'';
}

View File

@@ -27,18 +27,18 @@ WantedBy=default.target
WantedBy=multi-user.target
[Service]
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:/home/hm-user/.nix-profile/bin:@systemd@/bin
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:@nftables@/bin:/home/hm-user/.nix-profile/bin:@systemd@/bin
Restart=on-failure
TimeoutStopSec=30
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i my-container
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i my-container
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container --cidfile=%t/%N.cid --replace --rm --cgroups=split --entrypoint /sleep.sh --network-alias test-alias-1 --network-alias test-alias-2 --read-only-tmpfs --network mynet --sdnotify=conmon -d --device /dev/null:/dev/null -v /tmp:/tmp --label io.containers.autoupdate=registry --publish 8080:80 --env VAL_A=A --env VAL_B=2 --env VAL_C=false --label nix.home-manager.managed=true --security-opt=no-new-privileges docker.io/alpine:latest
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container --replace --rm --cgroups=split --entrypoint /sleep.sh --network-alias test-alias-1 --network-alias test-alias-2 --read-only-tmpfs --network mynet --sdnotify=conmon -d --device /dev/null:/dev/null -v /tmp:/tmp --label io.containers.autoupdate=registry --publish 8080:80 --env VAL_A=A --env VAL_B=2 --env VAL_C=false --label nix.home-manager.managed=true --security-opt=no-new-privileges docker.io/alpine:latest
[Unit]
Wants=podman-user-wait-network-online.service

View File

@@ -1,61 +1,62 @@
{ config, lib, ... }:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
containers = {
"my-container" = {
description = "home-manager test";
autoStart = true;
autoUpdate = "registry";
devices = [ "/dev/null:/dev/null" ];
entrypoint = "/sleep.sh";
environment = {
"VAL_A" = "A";
"VAL_B" = 2;
"VAL_C" = false;
};
extraPodmanArgs = [ "--security-opt=no-new-privileges" ];
extraConfig = {
Container = {
ReadOnlyTmpfs = true;
NetworkAlias = "test-alias-2";
services.podman = {
enable = true;
containers = {
"my-container" = {
description = "home-manager test";
autoStart = true;
autoUpdate = "registry";
devices = [ "/dev/null:/dev/null" ];
entrypoint = "/sleep.sh";
environment = {
"VAL_A" = "A";
"VAL_B" = 2;
"VAL_C" = false;
};
Service.Restart = "on-failure";
Unit.Before = "fake.target";
extraPodmanArgs = [ "--security-opt=no-new-privileges" ];
extraConfig = {
Container = {
ReadOnlyTmpfs = true;
NetworkAlias = "test-alias-2";
};
Service.Restart = "on-failure";
Unit.Before = "fake.target";
};
image = "docker.io/alpine:latest";
# Should not generate Requires/After for network because there is no
# services.podman.networks.mynet.
network = "mynet";
networkAlias = [ "test-alias-1" ];
ports = [ "8080:80" ];
volumes = [ "/tmp:/tmp" ];
};
image = "docker.io/alpine:latest";
# Should not generate Requires/After for network because there is no
# services.podman.networks.mynet.
network = "mynet";
networkAlias = [ "test-alias-1" ];
ports = [ "8080:80" ];
volumes = [ "/tmp:/tmp" ];
};
"my-container-2" = {
image = "docker.io/alpine:latest";
extraConfig = {
Container.ContainerName = "some-other-container-name";
"my-container-2" = {
image = "docker.io/alpine:latest";
extraConfig = {
Container.ContainerName = "some-other-container-name";
};
};
};
};
test.asserts.assertions.expected = [
''In 'my-container-2' config. Container.ContainerName: 'some-other-container-name' does not match expected type: value "my-container-2" (singular enum)''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
containerFile=$configPath/podman-my-container.service
assertFileExists $containerFile
containerFile=$(normalizeStorePaths $containerFile)
assertFileContent $containerFile ${./container-expected.service}
'';
};
test.asserts.assertions.expected = [
''In 'my-container-2' config. Container.ContainerName: 'some-other-container-name' does not match expected type: value "my-container-2" (singular enum)''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
containerFile=$configPath/podman-my-container.service
assertFileExists $containerFile
containerFile=$(normalizeStorePaths $containerFile)
assertFileContent $containerFile ${./container-expected.service}
'';
}

View File

@@ -1,24 +1,24 @@
{ config, lib, ... }:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
services.podman = {
enable = true;
images = {
"my-img" = {
image = "docker.io/alpine:latest";
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
images = {
"my-img" = {
image = "docker.io/alpine:latest";
};
};
};
nmt.script = ''
configPath=home-files/.config/systemd/user
imageFile=$configPath/podman-my-img-image.service
assertFileExists $imageFile
imageFile=$(normalizeStorePaths $imageFile)
assertFileContent $imageFile ${./image-expected.service}
'';
};
nmt.script = ''
configPath=home-files/.config/systemd/user
imageFile=$configPath/podman-my-img-image.service
assertFileExists $imageFile
imageFile=$(normalizeStorePaths $imageFile)
assertFileContent $imageFile ${./image-expected.service}
'';
}

View File

@@ -26,5 +26,5 @@ Type=oneshot
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
Description=Service for build my-bld
RequiresMountsFor=%t/containers
SourcePath=/nix/store/00000000000000000000000000000000-home-container-podman-my-container-bld/quadlets/podman-my-bld.build
RequiresMountsFor=%t/containers

View File

@@ -15,24 +15,24 @@ WantedBy=default.target
WantedBy=multi-user.target
[Service]
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:/home/hm-user/.nix-profile/bin:@systemd@/bin
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:@nftables@/bin:/home/hm-user/.nix-profile/bin:@systemd@/bin
Restart=always
TimeoutStopSec=30
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i my-container-bld
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i my-container-bld
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container-bld --cidfile=%t/%N.cid --replace --rm --cgroups=split --sdnotify=conmon -d --label nix.home-manager.managed=true homemanager/my-bld
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container-bld --replace --rm --cgroups=split --sdnotify=conmon -d --label nix.home-manager.managed=true homemanager/my-bld
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
Description=Service for container my-container-bld
SourcePath=/nix/store/00000000000000000000000000000000-home-container-podman-my-container-bld/quadlets/podman-my-container-bld.container
RequiresMountsFor=%t/containers
Requires=podman-my-bld-build.service
After=podman-my-bld-build.service
RequiresMountsFor=%t/containers

View File

@@ -18,27 +18,27 @@ WantedBy=default.target
WantedBy=multi-user.target
[Service]
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:/home/hm-user/.nix-profile/bin:@systemd@/bin
Environment=PATH=/run/wrappers/bin:/run/current-system/sw/bin:@nftables@/bin:/home/hm-user/.nix-profile/bin:@systemd@/bin
Restart=always
TimeoutStopSec=30
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStop=/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i my-container
ExecStopPost=-/nix/store/00000000000000000000000000000000-podman/bin/podman rm -v -f -i my-container
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container --cidfile=%t/%N.cid --replace --rm --cgroups=split --network my-app --network externalnet --sdnotify=conmon -d -v my-app:/data --label nix.home-manager.managed=true docker.io/alpine:latest
ExecStart=/nix/store/00000000000000000000000000000000-podman/bin/podman run --name my-container --replace --rm --cgroups=split --network my-app --network externalnet --sdnotify=conmon -d -v my-app:/data --label nix.home-manager.managed=true docker.io/alpine:latest
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
Description=Service for container my-container
SourcePath=/nix/store/00000000000000000000000000000000-home-container-podman-my-container/quadlets/podman-my-container.container
RequiresMountsFor=%t/containers
Requires=podman-my-img-image.service
After=podman-my-img-image.service
RequiresMountsFor=%t/containers
Requires=podman-my-app-network.service
After=podman-my-app-network.service
Requires=podman-my-app-volume.service

View File

@@ -4,78 +4,79 @@
pkgs,
...
}:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
services.podman = {
enable = true;
builds."my-bld" = {
file =
let
containerFile = pkgs.writeTextFile {
name = "Containerfile";
text = ''
FROM docker.io/alpine:latest
'';
};
in
"${containerFile}";
};
containers = {
"my-container" = {
image = "my-img.image";
network = [
"my-app.network"
"externalnet"
];
volumes = [ "my-app.volume:/data" ];
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
builds."my-bld" = {
file =
let
containerFile = pkgs.writeTextFile {
name = "Containerfile";
text = ''
FROM docker.io/alpine:latest
'';
};
in
"${containerFile}";
};
"my-container-bld" = {
image = "my-bld.build";
containers = {
"my-container" = {
image = "my-img.image";
network = [
"my-app.network"
"externalnet"
];
volumes = [ "my-app.volume:/data" ];
};
"my-container-bld" = {
image = "my-bld.build";
};
};
images."my-img" = {
image = "docker.io/alpine:latest";
};
networks."my-app" = {
gateway = "192.168.123.1";
subnet = "192.168.123.0/24";
};
volumes."my-app" = {
device = "tmpfs";
preserve = false;
type = "tmpfs";
};
};
images."my-img" = {
image = "docker.io/alpine:latest";
};
networks."my-app" = {
gateway = "192.168.123.1";
subnet = "192.168.123.0/24";
};
volumes."my-app" = {
device = "tmpfs";
preserve = false;
type = "tmpfs";
};
nmt.script = ''
configPath=home-files/.config/systemd/user
buildFile=$configPath/podman-my-bld-build.service
containerFile=$configPath/podman-my-container.service
containerBldFile=$configPath/podman-my-container-bld.service
imageFile=$configPath/podman-my-img-image.service
networkFile=$configPath/podman-my-app-network.service
volumeFile=$configPath/podman-my-app-volume.service
assertFileExists $buildFile
assertFileExists $containerFile
assertFileExists $containerBldFile
assertFileExists $imageFile
assertFileExists $networkFile
assertFileExists $volumeFile
buildFile=$(normalizeStorePaths $buildFile)
containerFile=$(normalizeStorePaths $containerFile)
containerBldFile=$(normalizeStorePaths $containerBldFile)
imageFile=$(normalizeStorePaths $imageFile)
networkFile=$(normalizeStorePaths $networkFile)
volumeFile=$(normalizeStorePaths $volumeFile)
assertFileContent $buildFile ${./integration-build-expected.service}
assertFileContent $containerFile ${./integration-container-expected.service}
assertFileContent $containerBldFile ${./integration-container-bld-expected.service}
assertFileContent $imageFile ${./integration-image-expected.service}
assertFileContent $networkFile ${./integration-network-expected.service}
assertFileContent $volumeFile ${./integration-volume-expected.service}
'';
};
nmt.script = ''
configPath=home-files/.config/systemd/user
buildFile=$configPath/podman-my-bld-build.service
containerFile=$configPath/podman-my-container.service
containerBldFile=$configPath/podman-my-container-bld.service
imageFile=$configPath/podman-my-img-image.service
networkFile=$configPath/podman-my-app-network.service
volumeFile=$configPath/podman-my-app-volume.service
assertFileExists $buildFile
assertFileExists $containerFile
assertFileExists $containerBldFile
assertFileExists $imageFile
assertFileExists $networkFile
assertFileExists $volumeFile
buildFile=$(normalizeStorePaths $buildFile)
containerFile=$(normalizeStorePaths $containerFile)
containerBldFile=$(normalizeStorePaths $containerBldFile)
imageFile=$(normalizeStorePaths $imageFile)
networkFile=$(normalizeStorePaths $networkFile)
volumeFile=$(normalizeStorePaths $volumeFile)
assertFileContent $buildFile ${./integration-build-expected.service}
assertFileContent $containerFile ${./integration-container-expected.service}
assertFileContent $containerBldFile ${./integration-container-bld-expected.service}
assertFileContent $imageFile ${./integration-image-expected.service}
assertFileContent $networkFile ${./integration-network-expected.service}
assertFileContent $volumeFile ${./integration-volume-expected.service}
'';
}

View File

@@ -1,62 +1,62 @@
{ config, lib, ... }:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
containers."my-container-1" = {
description = "home-manager test";
autoUpdate = "registry";
autoStart = true;
image = "docker.io/alpine:latest";
entrypoint = "sleep 1000";
environment = {
"VAL_A" = "A";
"VAL_B" = 2;
"VAL_C" = false;
};
};
};
services.podman = {
enable = true;
containers."my-container-1" = {
services.podman.containers."my-container-2" = {
description = "home-manager test";
autoUpdate = "registry";
autoStart = true;
image = "docker.io/alpine:latest";
entrypoint = "sleep 1000";
environment = {
"VAL_A" = "A";
"VAL_B" = 2;
"VAL_C" = false;
"VAL_A" = "B";
"VAL_B" = 3;
"VAL_C" = true;
};
};
};
services.podman.containers."my-container-2" = {
description = "home-manager test";
autoUpdate = "registry";
autoStart = true;
image = "docker.io/alpine:latest";
entrypoint = "sleep 1000";
environment = {
"VAL_A" = "B";
"VAL_B" = 3;
"VAL_C" = true;
services.podman.networks."mynet-1" = {
subnet = "192.168.1.0/24";
gateway = "192.168.1.1";
};
services.podman.networks."mynet-2" = {
subnet = "192.168.2.0/24";
gateway = "192.168.2.1";
};
nmt.script = ''
configPath=home-files/.config/podman
containerManifest=$configPath/containers.manifest
networkManifest=$configPath/networks.manifest
assertFileExists $containerManifest
assertFileExists $networkManifest
assertFileContent $containerManifest ${builtins.toFile "containers.expected" ''
my-container-1
my-container-2
''}
assertFileContent $networkManifest ${builtins.toFile "networks.expected" ''
mynet-1
mynet-2
''}
'';
};
services.podman.networks."mynet-1" = {
subnet = "192.168.1.0/24";
gateway = "192.168.1.1";
};
services.podman.networks."mynet-2" = {
subnet = "192.168.2.0/24";
gateway = "192.168.2.1";
};
nmt.script = ''
configPath=home-files/.config/podman
containerManifest=$configPath/containers.manifest
networkManifest=$configPath/networks.manifest
assertFileExists $containerManifest
assertFileExists $networkManifest
assertFileContent $containerManifest ${builtins.toFile "containers.expected" ''
my-container-1
my-container-2
''}
assertFileContent $networkManifest ${builtins.toFile "networks.expected" ''
mynet-1
mynet-2
''}
'';
}

View File

@@ -1,52 +1,52 @@
{ config, lib, ... }:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
services.podman = {
enable = true;
networks = {
"my-net" = {
subnet = "192.168.1.0/24";
gateway = "192.168.1.1";
extraPodmanArgs = [ "--ipam-driver dhcp" ];
extraConfig = {
Network = {
NetworkName = "my-net";
Options = {
isolate = "true";
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
networks = {
"my-net" = {
subnet = "192.168.1.0/24";
gateway = "192.168.1.1";
extraPodmanArgs = [ "--ipam-driver dhcp" ];
extraConfig = {
Network = {
NetworkName = "my-net";
Options = {
isolate = "true";
};
PodmanArgs = [
"--dns=192.168.55.1"
"--log-level=debug"
];
};
PodmanArgs = [
"--dns=192.168.55.1"
"--log-level=debug"
];
};
};
};
"my-net-2" = {
subnet = "192.168.2.0/24";
gateway = "192.168.2.1";
extraConfig = {
Network = {
NetworkName = "some-other-network-name";
"my-net-2" = {
subnet = "192.168.2.0/24";
gateway = "192.168.2.1";
extraConfig = {
Network = {
NetworkName = "some-other-network-name";
};
};
};
};
};
test.asserts.assertions.expected = [
''In 'my-net-2' config. Network.NetworkName: 'some-other-network-name' does not match expected type: value "my-net-2" (singular enum)''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
networkFile=$configPath/podman-my-net-network.service
assertFileExists $networkFile
networkFile=$(normalizeStorePaths $networkFile)
assertFileContent $networkFile ${./network-expected.service}
'';
};
test.asserts.assertions.expected = [
''In 'my-net-2' config. Network.NetworkName: 'some-other-network-name' does not match expected type: value "my-net-2" (singular enum)''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
networkFile=$configPath/podman-my-net-network.service
assertFileExists $networkFile
networkFile=$(normalizeStorePaths $networkFile)
assertFileContent $networkFile ${./network-expected.service}
'';
}

View File

@@ -1,44 +1,44 @@
{ config, lib, ... }:
lib.mkIf config.test.enableLegacyIfd {
{
imports = [ ./podman-stubs.nix ];
services.podman = {
enable = true;
volumes = {
"my-vol" = {
device = "tmpfs";
extraConfig = {
Volume = {
User = 1000;
config = lib.mkIf config.test.enableLegacyIfd {
services.podman = {
enable = true;
volumes = {
"my-vol" = {
device = "tmpfs";
extraConfig = {
Volume = {
User = 1000;
};
};
extraPodmanArgs = [ "--module=/etc/nvd.conf" ];
group = 1000;
type = "tmpfs";
};
extraPodmanArgs = [ "--module=/etc/nvd.conf" ];
group = 1000;
type = "tmpfs";
};
"my-vol-2" = {
extraConfig = {
Volume = {
VolumeName = "some-other-volume-name";
"my-vol-2" = {
extraConfig = {
Volume = {
VolumeName = "some-other-volume-name";
};
};
};
};
};
test.asserts.assertions.expected = [
''In 'my-vol-2' config. Volume.VolumeName: 'some-other-volume-name' does not match expected type: value "my-vol-2" (singular enum)''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
volumeFile=$configPath/podman-my-vol-volume.service
assertFileExists $volumeFile
volumeFile=$(normalizeStorePaths $volumeFile)
assertFileContent $volumeFile ${./volume-expected.service}
'';
};
test.asserts.assertions.expected = [
''In 'my-vol-2' config. Volume.VolumeName: 'some-other-volume-name' does not match expected type: value "my-vol-2" (singular enum)''
];
nmt.script = ''
configPath=home-files/.config/systemd/user
volumeFile=$configPath/podman-my-vol-volume.service
assertFileExists $volumeFile
volumeFile=$(normalizeStorePaths $volumeFile)
assertFileContent $volumeFile ${./volume-expected.service}
'';
}