Compare commits

...

23 commits

Author SHA1 Message Date
crazymanjinn d93d56ab8c
gpg-agent: make shell integrations optional (#2927) (#2930)
In esoteric setups, automatically setting GPG_TTY to current tty is not
desired on every shell startup. This change adds configuration options
to allow user to disable that if desired.

(cherry picked from commit df6010551d)
2022-05-02 15:25:40 -04:00
Robert Helgesson d14adb99f3
i3status-rust: fix formatting
(cherry picked from commit 778af87a98)
2022-04-26 23:06:58 +02:00
Naïm Favier 5eb2102aef
gpg: create homedir with 700 permissions (#2823)
It can happen in some cases that home-manager first runs before gpg
creates its homedir, and it creates it with 755 permissions which the
user then needs to change by hand.

Do this in the module instead: before linking files, make sure the
homedir exists, and if it doesn't, create it with the right permissions.

(cherry picked from commit 399a3dfeaf)
2022-04-26 12:35:48 +02:00
Naïm Favier 834d863dd2
types: fix dagOf behaviour with mkIf
This makes definitions like

    home.activation.foo = mkIf false "bar"

work, where previously they would complain about
`home.activation.foobar.data` being used but not defined.

The crucial part is that we don't call `convertAllToDags` in
`dagOf.merge`, because we need to process `mkIf`/`mkMerge` properties
first. So we let `attrEquivalent.merge` do its job normally, but give
it a type `dagEntryOf` that does the conversion.

Ideally this shouldn't require so much boilerplate; I'd like to
implement something like

    types.changeInto dagContentType elemType dagEntryAnywhere

in Nixpkgs.

(cherry picked from commit 8db712a6a2)
2022-04-26 12:34:13 +02:00
Sam Willcocks 236c6ec214
gpg: fix handling of multiple public keys
When processing `publicKeys` entries, handle entries that contain
multiple public keys (i.e. gpg --show-key returns multiple `pub`
lines) properly, setting the trust level for each key.

PR #2897

(cherry picked from commit 620ed197f3)
2022-04-25 01:05:45 +02:00
Robert Helgesson e997bf4c98
gpg: apply nixfmt 2022-04-25 00:46:58 +02:00
dependabot[bot] 7244c6715c
ci: bump cachix/install-nix-action from 16 to 17
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 16 to 17.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v16...v17)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-13 22:11:51 +00:00
Moises Nessim 7049cf37a9
nix: add support for nix profile
PR #2833

Co-authored-by: David Arnold <dar@xoe.solutions>
Co-authored-by: Florian Franzen <Florian.Franzen@gmail.com>

(cherry picked from commit 2f58d0a3de)
2022-04-11 23:10:26 +02:00
Robert Helgesson ef6799c1ce
files: avoid cleanup if old home-files is missing
(cherry picked from commit 171702dd88)
2022-04-11 09:27:07 +02:00
Wael Nasreddine 0bdbdea2e2
nix-darwin: sudo --set-home for multiple user activation (#2857) (#2858)
Changing from `sudo -i` to `sudo -s` messes up activation when multiple
users are managed. `--set-home` should have similar behavior to `-i` in
that the activation script is run from the user's home directory.

Fixes #2856

(cherry picked from commit e1fab012e8)

Co-authored-by: toonn <toonn@toonn.io>
2022-04-01 13:31:59 -04:00
toonn ef6b316265 Run sudo with -s in the darwin module (#807)
Currently activation is run with `sudo -i` this defaults to the user's
login shell. This can lead to problems if the user's shell isn't set
properly.

By passing `-s` rather than `-i`, `sudo` runs `activate` in `SHELL`
instead. We assume that at this point in the activation `SHELL`
contains the path to a bash in the nix store. This should always be a
valid shell to run the `activate` script with.

From the `sudo` manual it seems like this cannot be fixed if `SHELL`
isn't set at this point or by passing a command to `-s` because that
command is then passed to the user's shell.

(cherry picked from commit cf62e96bf7)
2022-03-31 11:30:35 -07:00
ReplayCoding a8d00f5c03
irssi: fix syntax error when no channels are specified
(cherry picked from commit 5d4327cff4)
2022-03-13 13:40:56 +01:00
dependabot[bot] 47ae373e74
ci: bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-13 12:12:41 +00:00
Robert Helgesson 2e527cf33c
ci: run tests against Nixpkgs 21.11 2022-03-13 13:11:59 +01:00
Nicolas Berbiche 2860d7e3bb
darwin: add Nix package to activation $PATH
The fix for https://github.com/nix-community/home-manager/issues/2178
did not apply the patch to nix-darwin too.

See: https://github.com/nix-community/home-manager/issues/2178#issuecomment-1029015498
(cherry picked from commit 1fa809f783)
2022-02-04 01:12:16 +01:00
Robin Stumm 28b9ae40c4
kakoune: fix ui options (#2642)
These were renamed in v2021.08.28,
commit 7e66846172165eb1f860f26f51f7a20790b0af29.
2022-01-19 23:38:13 -05:00
Naïm Favier 697cc8c68e
gpg: allow specifying trust levels by name
(cherry picked from commit 78aa7cceff)
2021-12-19 00:59:29 +01:00
Miles Breslin e0bfb57d62
gpg: support declarative trust and public keys
PR #810

(cherry picked from commit ea1794a798)
2021-12-19 00:59:09 +01:00
Lily Foster 93ad8661c7
rofi: fix theme definition in configuration for 1.7.0+ (#2513)
Since Rofi 1.7.1 (specifically davatorium/rofi@0e70d8a), the deprecated
`theme` option in the `configuration` section no longer works. For 1.7.0
and up, `@theme "name"` is supposed to be used *after* the
`configuration` block.

(cherry picked from commit 3ec7f6fb43)
2021-12-18 08:13:37 +01:00
Nicolas Berbiche 6ce1d64073
docs: change stable from 21.05 to 21.11
(cherry picked from commit 290a188dad)
2021-12-03 18:52:38 +01:00
polykernel 9437177e82
home-manager: fix home-manager build error (#2514)
Two misplaced quotations were introduced in `doBuild` by https://github.com/nix-community/home-manager/pull/2501, which
caused the parameter expansion of DRY_RUN to include an extraneous tab. Since the flake uri is passed
later into the command, Nix assumes the whitespace sequence as the flake uri and returns that it is not
a valid flake reference.

This PR removes the misplaced quotations in `doBuild` and also places the flake uri as the first argument for
calls to `doBuildFlake` for consistency with `doBuildAttr`. Placing the uri first in the command line also guards
against possible security issues if arbitrary uris are expanded prior to the user given uri.

(cherry picked from commit 9de77227d7)
2021-12-02 23:22:52 +01:00
Jörg Thalheim 3e93c4e8b2 Revert "direnv.nix-direnv: remove enableFlakes (#2458)"
This reverts commit 1e5c8e9bff.
2021-11-30 11:10:06 +01:00
dependabot[bot] 4daff26495
ci: bump cachix/install-nix-action from 15 to 16
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 15 to 16.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v15...v16)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-26 10:05:57 +01:00
27 changed files with 470 additions and 95 deletions

View file

@ -10,8 +10,8 @@ jobs:
os: [ubuntu-latest] os: [ubuntu-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: cachix/install-nix-action@v15 - uses: cachix/install-nix-action@v17
with: with:
nix_path: nixpkgs=channel:nixos-unstable nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v10 - uses: cachix/cachix-action@v10

View file

@ -11,10 +11,10 @@ jobs:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: cachix/install-nix-action@v15 - uses: cachix/install-nix-action@v17
with: with:
nix_path: nixpkgs=channel:nixos-unstable nix_path: nixpkgs=channel:nixos-21.11
- uses: cachix/cachix-action@v10 - uses: cachix/cachix-action@v10
with: with:
name: nix-community name: nix-community

View file

@ -32,7 +32,7 @@ will write to your dconf store and cannot tell whether a configuration
that it is about to be overwritten was from a previous Home Manager that it is about to be overwritten was from a previous Home Manager
generation or from manual configuration. generation or from manual configuration.
Home Manager targets [NixOS][] unstable and NixOS version 21.05 (the Home Manager targets [NixOS][] unstable and NixOS version 21.11 (the
current stable version), it may or may not work on other Linux current stable version), it may or may not work on other Linux
distributions and NixOS versions. distributions and NixOS versions.
@ -152,7 +152,7 @@ Home Manager is developed against `nixpkgs-unstable` branch, which
often causes it to contain tweaks for changes/packages not yet often causes it to contain tweaks for changes/packages not yet
released in stable NixOS. To avoid breaking users' configurations, released in stable NixOS. To avoid breaking users' configurations,
Home Manager is released in branches corresponding to NixOS releases Home Manager is released in branches corresponding to NixOS releases
(e.g. `release-21.05`). These branches get fixes, but usually not new (e.g. `release-21.11`). These branches get fixes, but usually not new
modules. If you need a module to be backported, then feel free to open modules. If you need a module to be backported, then feel free to open
an issue. an issue.

View file

@ -1,8 +1,7 @@
[[sec-release-21.11]] [[sec-release-21.11]]
== Release 21.11 == Release 21.11
This is the current unstable branch and the information in this The 21.11 release branch became the stable branch in November, 2021.
section is therefore not final.
[[sec-release-21.11-highlights]] [[sec-release-21.11-highlights]]
=== Highlights === Highlights

1
format
View file

@ -24,7 +24,6 @@ find . -name '*.nix' \
! -path ./modules/manual.nix \ ! -path ./modules/manual.nix \
! -path ./modules/misc/news.nix \ ! -path ./modules/misc/news.nix \
! -path ./modules/programs/bash.nix \ ! -path ./modules/programs/bash.nix \
! -path ./modules/programs/gpg.nix \
! -path ./modules/programs/ssh.nix \ ! -path ./modules/programs/ssh.nix \
! -path ./modules/programs/zsh.nix \ ! -path ./modules/programs/zsh.nix \
! -path ./modules/services/gpg-agent.nix \ ! -path ./modules/services/gpg-agent.nix \

View file

@ -10,6 +10,23 @@ function errorEcho() {
echo $* >&2 echo $* >&2
} }
function removeByName() {
nix profile list \
| { grep "$1" || test $? = 1; } \
| cut -d ' ' -f 4 \
| xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG
}
function setNixProfileCommands() {
if [[ -e ~/.nix-profile/manifest.json ]] ; then
LIST_OUTPATH_CMD="nix profile list"
REMOVE_CMD="removeByName"
else
LIST_OUTPATH_CMD="nix-env -q --outpath"
REMOVE_CMD="nix-env -q"
fi
}
function setVerboseAndDryRun() { function setVerboseAndDryRun() {
if [[ -v VERBOSE ]]; then if [[ -v VERBOSE ]]; then
export VERBOSE_ARG="--verbose" export VERBOSE_ARG="--verbose"
@ -263,9 +280,9 @@ function doBuild() {
setFlakeAttribute setFlakeAttribute
if [[ -v FLAKE_CONFIG_URI ]]; then if [[ -v FLAKE_CONFIG_URI ]]; then
doBuildFlake \ doBuildFlake \
"${DRY_RUN+--dry-run} \
"${NO_OUT_LINK+--no-link} \
"$FLAKE_CONFIG_URI.activationPackage" \ "$FLAKE_CONFIG_URI.activationPackage" \
${DRY_RUN+--dry-run} \
${NO_OUT_LINK+--no-link} \
|| return || return
else else
doBuildAttr \ doBuildAttr \
@ -294,8 +311,8 @@ function doSwitch() {
setFlakeAttribute setFlakeAttribute
if [[ -v FLAKE_CONFIG_URI ]]; then if [[ -v FLAKE_CONFIG_URI ]]; then
doBuildFlake \ doBuildFlake \
--out-link "$generation" \
"$FLAKE_CONFIG_URI.activationPackage" \ "$FLAKE_CONFIG_URI.activationPackage" \
--out-link "$generation" \
&& "$generation/activate" || return && "$generation/activate" || return
else else
doBuildAttr \ doBuildAttr \
@ -371,8 +388,9 @@ function doExpireGenerations() {
} }
function doListPackages() { function doListPackages() {
setNixProfileCommands
local outPath local outPath
outPath="$(nix-env -q --out-path | grep -o '/.*home-manager-path$')" outPath="$($LIST_OUTPATH_CMD | grep -o '/.*home-manager-path$')"
if [[ -n "$outPath" ]] ; then if [[ -n "$outPath" ]] ; then
nix-store -q --references "$outPath" | sed 's/[^-]*-//' nix-store -q --references "$outPath" | sed 's/[^-]*-//'
else else
@ -447,6 +465,7 @@ function doShowNews() {
function doUninstall() { function doUninstall() {
setVerboseAndDryRun setVerboseAndDryRun
setNixProfileCommands
echo "This will remove Home Manager from your system." echo "This will remove Home Manager from your system."
@ -464,7 +483,7 @@ function doUninstall() {
HOME_MANAGER_CONFIG="$(mktemp --tmpdir home-manager.XXXXXXXXXX)" HOME_MANAGER_CONFIG="$(mktemp --tmpdir home-manager.XXXXXXXXXX)"
echo "{ lib, ... }: { home.file = lib.mkForce {}; }" > "$HOME_MANAGER_CONFIG" echo "{ lib, ... }: { home.file = lib.mkForce {}; }" > "$HOME_MANAGER_CONFIG"
doSwitch doSwitch
$DRY_RUN_CMD nix-env -e home-manager-path || true $DRY_RUN_CMD $REMOVE_CMD home-manager-path || true
rm "$HOME_MANAGER_CONFIG" rm "$HOME_MANAGER_CONFIG"
$DRY_RUN_CMD rm $VERBOSE_ARG -r \ $DRY_RUN_CMD rm $VERBOSE_ARG -r \
"${XDG_DATA_HOME:-$HOME/.local/share}/home-manager" "${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"

View file

@ -239,7 +239,7 @@ in
} }
function cleanOldGen() { function cleanOldGen() {
if [[ ! -v oldGenPath ]] ; then if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then
return return
fi fi
@ -260,7 +260,17 @@ in
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
echo "Creating profile generation $newGenNum" echo "Creating profile generation $newGenNum"
$DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath" if [[ -e "$genProfilePath"/manifest.json ]] ; then
# Remove all packages from "$genProfilePath"
# `nix profile remove '.*' --profile "$genProfilePath"` was not working, so here is a workaround:
nix profile list --profile "$genProfilePath" \
| cut -d ' ' -f 4 \
| xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG --profile "$genProfilePath"
$DRY_RUN_CMD nix profile install $VERBOSE_ARG --profile "$genProfilePath" "$newGenPath"
else
$DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath"
fi
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath" $DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
else else
echo "No change so reusing latest profile generation $oldGenNum" echo "No change so reusing latest profile generation $oldGenNum"

View file

@ -578,30 +578,49 @@ in
if config.submoduleSupport.externalPackageInstall if config.submoduleSupport.externalPackageInstall
then then
'' ''
if nix-env -q | grep '^home-manager-path$'; then if [[ -e "$nixProfilePath"/manifest.json ]] ; then
$DRY_RUN_CMD nix-env -e home-manager-path nix profile list \
| { grep 'home-manager-path$' || test $? = 1; } \
| awk -F ' ' '{ print $4 }' \
| cut -d ' ' -f 4 \
| xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG
else
if nix-env -q | grep '^home-manager-path$'; then
$DRY_RUN_CMD nix-env -e home-manager-path
fi
fi fi
'' ''
else else
'' ''
if ! $DRY_RUN_CMD nix-env -i ${cfg.path} ; then if [[ -e "$nixProfilePath"/manifest.json ]] ; then
INSTALL_CMD="nix profile install"
LIST_CMD="nix profile list"
REMOVE_CMD_SYNTAX='nix profile remove {number | store path}'
else
INSTALL_CMD="nix-env -i"
LIST_CMD="nix-env -q"
REMOVE_CMD_SYNTAX='nix-env -e {package name}'
fi
if ! $DRY_RUN_CMD $INSTALL_CMD ${cfg.path} ; then
cat <<EOF cat <<EOF
Oops, nix-env failed to install your new Home Manager profile! Oops, nix-env failed to install your new Home Manager profile!
Perhaps there is a conflict with a package that was installed using Perhaps there is a conflict with a package that was installed using
'nix-env -i'? Try running '$INSTALL_CMD'? Try running
nix-env -q $LIST_COMMAND
and if there is a conflicting package you can remove it with and if there is a conflicting package you can remove it with
nix-env -e {package name} $REMOVE_CMD_SYNTAX
Then try activating your Home Manager configuration again. Then try activating your Home Manager configuration again.
EOF EOF
exit 1 exit 1
fi fi
unset INSTALL_CMD LIST_CMD REMOVE_CMD_SYNTAX
'' ''
); );

View file

@ -5,6 +5,7 @@ function setupVars() {
local profilesPath="$nixStateDir/profiles/per-user/$USER" local profilesPath="$nixStateDir/profiles/per-user/$USER"
local gcPath="$nixStateDir/gcroots/per-user/$USER" local gcPath="$nixStateDir/gcroots/per-user/$USER"
declare -gr nixProfilePath="$profilesPath/profile"
declare -gr genProfilePath="$profilesPath/home-manager" declare -gr genProfilePath="$profilesPath/home-manager"
declare -gr newGenPath="@GENERATION_DIR@"; declare -gr newGenPath="@GENERATION_DIR@";
declare -gr newGenGcPath="$gcPath/current-home" declare -gr newGenGcPath="$gcPath/current-home"

View file

@ -8,17 +8,27 @@ let
isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before); isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before);
dagContentType = elemType: dagEntryOf = elemType:
types.submodule ({ name, ... }: { let
options = { submoduleType = types.submodule ({ name, ... }: {
data = mkOption { type = elemType; }; options = {
after = mkOption { type = with types; uniq (listOf str); }; data = mkOption { type = elemType; };
before = mkOption { type = with types; uniq (listOf str); }; after = mkOption { type = with types; uniq (listOf str); };
}; before = mkOption { type = with types; uniq (listOf str); };
config = mkIf (elemType.name == "submodule") { };
data._module.args.dagName = name; config = mkIf (elemType.name == "submodule") {
}; data._module.args.dagName = name;
}); };
});
maybeConvert = v: if isDagEntry v then v else dag.entryAnywhere v;
in mkOptionType {
name = "dagEntryOf";
description = "DAG entry of ${elemType.description}";
# leave the checking to the submodule type
merge = loc: defs:
submoduleType.merge loc
(map (def: def // { value = maybeConvert def.value; }) defs);
};
in rec { in rec {
# A directed acyclic graph of some inner type. # A directed acyclic graph of some inner type.
@ -29,21 +39,16 @@ in rec {
# "actual" attribute name a new submodule argument is provided with # "actual" attribute name a new submodule argument is provided with
# the name `dagName`. # the name `dagName`.
dagOf = elemType: dagOf = elemType:
let let attrEquivalent = types.attrsOf (dagEntryOf elemType);
convertAllToDags = let
maybeConvert = n: v: if isDagEntry v then v else dag.entryAnywhere v;
in map (def: def // { value = mapAttrs maybeConvert def.value; });
attrEquivalent = types.attrsOf (dagContentType elemType);
in mkOptionType rec { in mkOptionType rec {
name = "dagOf"; name = "dagOf";
description = "DAG of ${elemType.description}s"; description = "DAG of ${elemType.description}s";
check = isAttrs; inherit (attrEquivalent) check merge emptyValue;
merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs);
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]);
getSubModules = elemType.getSubModules; getSubModules = elemType.getSubModules;
substSubModules = m: dagOf (elemType.substSubModules m); substSubModules = m: dagOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; }; functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
}; };
# A directed acyclic graph of some inner type OR a list of that # A directed acyclic graph of some inner type OR a list of that

View file

@ -15,8 +15,6 @@ in {
"direnv" "direnv"
"enableNixDirenvIntegration" "enableNixDirenvIntegration"
] [ "programs" "direnv" "nix-direnv" "enable" ]) ] [ "programs" "direnv" "nix-direnv" "enable" ])
(mkRemovedOptionModule [ "programs" "direnv" "nix-direnv" "enableFlakes" ]
"Flake support is now always enabled.")
]; ];
meta.maintainers = [ maintainers.rycee ]; meta.maintainers = [ maintainers.rycee ];
@ -81,6 +79,7 @@ in {
<link <link
xlink:href="https://github.com/nix-community/nix-direnv">nix-direnv</link>, xlink:href="https://github.com/nix-community/nix-direnv">nix-direnv</link>,
a fast, persistent use_nix implementation for direnv''; a fast, persistent use_nix implementation for direnv'';
enableFlakes = mkEnableOption "Flake support in nix-direnv";
}; };
}; };
@ -93,9 +92,11 @@ in {
}; };
xdg.configFile."direnv/direnvrc" = let xdg.configFile."direnv/direnvrc" = let
package =
pkgs.nix-direnv.override { inherit (cfg.nix-direnv) enableFlakes; };
text = concatStringsSep "\n" (optional (cfg.stdlib != "") cfg.stdlib text = concatStringsSep "\n" (optional (cfg.stdlib != "") cfg.stdlib
++ optional cfg.nix-direnv.enable ++ optional cfg.nix-direnv.enable
"source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc"); "source ${package}/share/nix-direnv/direnvrc");
in mkIf (text != "") { inherit text; }; in mkIf (text != "") { inherit text; };
programs.bash.initExtra = mkIf cfg.enableBashIntegration ( programs.bash.initExtra = mkIf cfg.enableBashIntegration (

View file

@ -6,9 +6,7 @@ let
cfg = config.programs.gpg; cfg = config.programs.gpg;
mkKeyValue = key: value: mkKeyValue = key: value:
if isString value if isString value then "${key} ${value}" else optionalString value key;
then "${key} ${value}"
else optionalString value key;
cfgText = generators.toKeyValue { cfgText = generators.toKeyValue {
inherit mkKeyValue; inherit mkKeyValue;
@ -21,8 +19,132 @@ let
} cfg.scdaemonSettings; } cfg.scdaemonSettings;
primitiveType = types.oneOf [ types.str types.bool ]; primitiveType = types.oneOf [ types.str types.bool ];
in
{ publicKeyOpts = { config, ... }: {
options = {
text = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Text of an OpenPGP public key.
'';
};
source = mkOption {
type = types.path;
description = ''
Path of an OpenPGP public key file.
'';
};
trust = mkOption {
type = types.nullOr (types.enum [
"unknown"
1
"never"
2
"marginal"
3
"full"
4
"ultimate"
5
]);
default = null;
apply = v:
if isString v then
{
unknown = 1;
never = 2;
marginal = 3;
full = 4;
ultimate = 5;
}.${v}
else
v;
description = ''
The amount of trust you have in the key ownership and the care the
owner puts into signing other keys. The available levels are
<variablelist>
<varlistentry>
<term><literal>unknown</literal> or <literal>1</literal></term>
<listitem><para>I don't know or won't say.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>never</literal> or <literal>2</literal></term>
<listitem><para>I do NOT trust.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>marginal</literal> or <literal>3</literal></term>
<listitem><para>I trust marginally.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>full</literal> or <literal>4</literal></term>
<listitem><para>I trust fully.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>ultimate</literal> or <literal>5</literal></term>
<listitem><para>I trust ultimately.</para></listitem>
</varlistentry>
</variablelist>
</para><para>
See <link xlink:href="https://www.gnupg.org/gph/en/manual/x334.html"/>
for more.
'';
};
};
config = {
source =
mkIf (config.text != null) (pkgs.writeText "gpg-pubkey" config.text);
};
};
importTrustBashFunctions = let gpg = "${cfg.package}/bin/gpg";
in ''
function gpgKeyId() {
${gpg} --show-key --with-colons "$1" \
| grep ^pub: \
| cut -d: -f5
}
function importTrust() {
local keyIds trust
IFS='\n' read -ra keyIds <<< "$(gpgKeyId "$1")"
trust="$2"
for id in "''${keyIds[@]}" ; do
{ echo trust; echo "$trust"; (( trust == 5 )) && echo y; echo quit; } \
| ${gpg} --no-tty --command-fd 0 --edit-key "$id"
done
}
'';
keyringFiles = let
gpg = "${cfg.package}/bin/gpg";
importKey = { source, trust, ... }: ''
${gpg} --import ${source}
${optionalString (trust != null)
''importTrust "${source}" ${toString trust}''}
'';
importKeys = concatMapStringsSep "\n" importKey cfg.publicKeys;
in pkgs.runCommand "gpg-pubring" { buildInputs = [ cfg.package ]; } ''
export GNUPGHOME
GNUPGHOME=$(mktemp -d)
${importTrustBashFunctions}
${importKeys}
mkdir $out
cp $GNUPGHOME/pubring.kbx $out/pubring.kbx
if [[ -e $GNUPGHOME/trustdb.gpg ]] ; then
cp $GNUPGHOME/trustdb.gpg $out/trustdb.gpg
fi
'';
in {
options.programs.gpg = { options.programs.gpg = {
enable = mkEnableOption "GnuPG"; enable = mkEnableOption "GnuPG";
@ -31,11 +153,13 @@ in
default = pkgs.gnupg; default = pkgs.gnupg;
defaultText = literalExpression "pkgs.gnupg"; defaultText = literalExpression "pkgs.gnupg";
example = literalExpression "pkgs.gnupg23"; example = literalExpression "pkgs.gnupg23";
description = "The Gnupg package to use (also used the gpg-agent service)."; description =
"The Gnupg package to use (also used the gpg-agent service).";
}; };
settings = mkOption { settings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str)); type =
types.attrsOf (types.either primitiveType (types.listOf types.str));
example = literalExpression '' example = literalExpression ''
{ {
no-comments = false; no-comments = false;
@ -53,7 +177,8 @@ in
}; };
scdaemonSettings = mkOption { scdaemonSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str)); type =
types.attrsOf (types.either primitiveType (types.listOf types.str));
example = literalExpression '' example = literalExpression ''
{ {
disable-ccid = true; disable-ccid = true;
@ -68,11 +193,54 @@ in
homedir = mkOption { homedir = mkOption {
type = types.path; type = types.path;
example = literalExpression "\"\${config.xdg.dataHome}/gnupg\""; example = literalExpression ''"''${config.xdg.dataHome}/gnupg"'';
default = "${config.home.homeDirectory}/.gnupg"; default = "${config.home.homeDirectory}/.gnupg";
defaultText = literalExpression "\"\${config.home.homeDirectory}/.gnupg\""; defaultText =
literalExpression ''"''${config.home.homeDirectory}/.gnupg"'';
description = "Directory to store keychains and configuration."; description = "Directory to store keychains and configuration.";
}; };
mutableKeys = mkOption {
type = types.bool;
default = true;
description = ''
If set to <literal>true</literal>, you may manage your keyring as a user
using the <literal>gpg</literal> command. Upon activation, the keyring
will have managed keys added without overwriting unmanaged keys.
</para><para>
If set to <literal>false</literal>, the path
<filename>$GNUPGHOME/pubring.kbx</filename> will become an immutable
link to the Nix store, denying modifications.
'';
};
mutableTrust = mkOption {
type = types.bool;
default = true;
description = ''
If set to <literal>true</literal>, you may manage trust as a user using
the <command>gpg</command> command. Upon activation, trusted keys have
their trust set without overwriting unmanaged keys.
</para><para>
If set to <literal>false</literal>, the path
<filename>$GNUPGHOME/trustdb.gpg</filename> will be
<emphasis>overwritten</emphasis> on each activation, removing trust for
any unmanaged keys. Be careful to make a backup of your old
<filename>trustdb.gpg</filename> before switching to immutable trust!
'';
};
publicKeys = mkOption {
type = types.listOf (types.submodule publicKeyOpts);
example = literalExpression ''
[ { source = ./pubkeys.txt; } ]
'';
default = [ ];
description = ''
A list of public keys to be imported into GnuPG. Note, these key files
will be copied into the world-readable Nix store.
'';
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
@ -80,7 +248,8 @@ in
personal-cipher-preferences = mkDefault "AES256 AES192 AES"; personal-cipher-preferences = mkDefault "AES256 AES192 AES";
personal-digest-preferences = mkDefault "SHA512 SHA384 SHA256"; personal-digest-preferences = mkDefault "SHA512 SHA384 SHA256";
personal-compress-preferences = mkDefault "ZLIB BZIP2 ZIP Uncompressed"; personal-compress-preferences = mkDefault "ZLIB BZIP2 ZIP Uncompressed";
default-preference-list = mkDefault "SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed"; default-preference-list = mkDefault
"SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed";
cert-digest-algo = mkDefault "SHA512"; cert-digest-algo = mkDefault "SHA512";
s2k-digest-algo = mkDefault "SHA512"; s2k-digest-algo = mkDefault "SHA512";
s2k-cipher-algo = mkDefault "AES256"; s2k-cipher-algo = mkDefault "AES256";
@ -102,12 +271,56 @@ in
}; };
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];
home.sessionVariables = { home.sessionVariables = { GNUPGHOME = cfg.homedir; };
GNUPGHOME = cfg.homedir;
};
home.file."${cfg.homedir}/gpg.conf".text = cfgText; home.file."${cfg.homedir}/gpg.conf".text = cfgText;
home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText; home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText;
# Link keyring if keys are not mutable
home.file."${cfg.homedir}/pubring.kbx" =
mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) {
source = "${keyringFiles}/pubring.kbx";
};
home.activation = {
createGpgHomedir =
hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
$DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${escapeShellArg cfg.homedir}
'';
importGpgKeys = let
gpg = "${cfg.package}/bin/gpg";
importKey = { source, trust, ... }:
# Import mutable keys
optional cfg.mutableKeys
"$DRY_RUN_CMD ${gpg} $QUIET_ARG --import ${source}"
# Import mutable trust
++ optional (trust != null && cfg.mutableTrust)
''$DRY_RUN_CMD importTrust "${source}" ${toString trust}'';
anyTrust = any (k: k.trust != null) cfg.publicKeys;
importKeys = concatStringsSep "\n" (concatMap importKey cfg.publicKeys);
# If any key/trust should be imported then create the block. Otherwise
# leave it empty.
block = concatStringsSep "\n" (optional (importKeys != "") ''
export GNUPGHOME=${escapeShellArg cfg.homedir}
if [[ ! -v VERBOSE ]]; then
QUIET_ARG="--quiet"
else
QUIET_ARG=""
fi
${importTrustBashFunctions}
${importKeys}
unset GNUPGHOME QUIET_ARG keyId importTrust
'' ++ optional (!cfg.mutableTrust && anyTrust) ''
install -m 0700 ${keyringFiles}/trustdb.gpg "${cfg.homedir}/trustdb.gpg"'');
in mkIf (cfg.publicKeys != [ ])
(lib.hm.dag.entryAfter [ "linkGeneration" ] block);
};
}; };
} }

View file

@ -44,14 +44,15 @@ let
} }
'')); ''));
channelString = concatStringsSep cnl (flip mapAttrsToList cfg.networks (k: v: channelString = concatStringsSep cnl (concatLists
concatStringsSep cnl (flip mapAttrsToList v.channels (c: cv: '' (flip mapAttrsToList cfg.networks (k: v:
{ (flip mapAttrsToList v.channels (c: cv: ''
chatnet = "${k}"; {
name = "${c}"; chatnet = "${k}";
autojoin = "${boolStr cv.autoJoin}"; name = "${c}";
} autojoin = "${boolStr cv.autoJoin}";
'')))); }
'')))));
channelType = types.submodule { channelType = types.submodule {
options = { options = {

View file

@ -530,20 +530,20 @@ let
uiOptions = with cfg.config.ui; uiOptions = with cfg.config.ui;
concatStringsSep " " [ concatStringsSep " " [
"ncurses_set_title=${if setTitle then "true" else "false"}" "terminal_set_title=${if setTitle then "true" else "false"}"
"ncurses_status_on_top=${ "terminal_status_on_top=${
if (statusLine == "top") then "true" else "false" if (statusLine == "top") then "true" else "false"
}" }"
"ncurses_assistant=${assistant}" "terminal_assistant=${assistant}"
"ncurses_enable_mouse=${if enableMouse then "true" else "false"}" "terminal_enable_mouse=${if enableMouse then "true" else "false"}"
"ncurses_change_colors=${if changeColors then "true" else "false"}" "terminal_change_colors=${if changeColors then "true" else "false"}"
"${optionalString (wheelDownButton != null) "${optionalString (wheelDownButton != null)
"ncurses_wheel_down_button=${wheelDownButton}"}" "terminal_wheel_down_button=${wheelDownButton}"}"
"${optionalString (wheelUpButton != null) "${optionalString (wheelUpButton != null)
"ncurses_wheel_up_button=${wheelUpButton}"}" "terminal_wheel_up_button=${wheelUpButton}"}"
"${optionalString (shiftFunctionKeys != null) "${optionalString (shiftFunctionKeys != null)
"ncurses_shift_function_key=${toString shiftFunctionKeys}"}" "terminal_shift_function_key=${toString shiftFunctionKeys}"}"
"ncurses_builtin_key_parser=${ "terminal_builtin_key_parser=${
if useBuiltinKeyParser then "true" else "false" if useBuiltinKeyParser then "true" else "false"
}" }"
]; ];

View file

@ -35,10 +35,10 @@ let
${configStr}} ${configStr}}
'' ''
else else
mkKeyValue { (mkKeyValue {
sep = " "; sep = " ";
end = ""; end = "";
} name value; } name value) + "\n";
toRasi = attrs: concatStringsSep "\n" (mapAttrsToList mkRasiSection attrs); toRasi = attrs: concatStringsSep "\n" (mapAttrsToList mkRasiSection attrs);
@ -266,9 +266,9 @@ in {
location = (getAttr cfg.location locationsMap); location = (getAttr cfg.location locationsMap);
xoffset = cfg.xoffset; xoffset = cfg.xoffset;
yoffset = cfg.yoffset; yoffset = cfg.yoffset;
theme = themeName;
} // cfg.extraConfig); } // cfg.extraConfig);
}; # @theme must go after configuration but attrs are output in alphabetical order ('@' first)
} + (optionalString (themeName != null) (toRasi { "@theme" = themeName; }));
xdg.dataFile = mkIf (themePath != null) (if themePath == "custom" then { xdg.dataFile = mkIf (themePath != null) (if themePath == "custom" then {
"rofi/themes/${themeName}.rasi".text = toRasi cfg.theme; "rofi/themes/${themeName}.rasi".text = toRasi cfg.theme;

View file

@ -170,6 +170,18 @@ in
now. now.
''; '';
}; };
enableBashIntegration = mkEnableOption "Bash integration" // {
default = true;
};
enableZshIntegration = mkEnableOption "Zsh integration" // {
default = true;
};
enableFishIntegration = mkEnableOption "Fish integration" // {
default = true;
};
}; };
}; };
@ -206,9 +218,9 @@ in
fi fi
''; '';
programs.bash.initExtra = gpgInitStr; programs.bash.initExtra = mkIf cfg.enableBashIntegration gpgInitStr;
programs.zsh.initExtra = gpgInitStr; programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgInitStr;
programs.fish.interactiveShellInit = '' programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
set -gx GPG_TTY (tty) set -gx GPG_TTY (tty)
''; '';
} }

View file

@ -29,6 +29,10 @@ let
home.username = config.users.users.${name}.name; home.username = config.users.users.${name}.name;
home.homeDirectory = config.users.users.${name}.home; home.homeDirectory = config.users.users.${name}.home;
# Make activation script use same version of Nix as system as a whole.
# This avoids problems with Nix not being in PATH.
home.extraActivationPath = [ config.nix.package ];
}; };
}) })
] ++ cfg.sharedModules; ] ++ cfg.sharedModules;
@ -130,7 +134,7 @@ in
system.activationScripts.postActivation.text = system.activationScripts.postActivation.text =
concatStringsSep "\n" (mapAttrsToList (username: usercfg: '' concatStringsSep "\n" (mapAttrsToList (username: usercfg: ''
echo Activating home-manager configuration for ${username} echo Activating home-manager configuration for ${username}
sudo -u ${username} -i ${pkgs.writeShellScript "activation-${username}" '' sudo -u ${username} -s --set-home ${pkgs.writeShellScript "activation-${username}" ''
${lib.optionalString (cfg.backupFileExtension != null) ${lib.optionalString (cfg.backupFileExtension != null)
"export HOME_MANAGER_BACKUP_EXT=${lib.escapeShellArg cfg.backupFileExtension}"} "export HOME_MANAGER_BACKUP_EXT=${lib.escapeShellArg cfg.backupFileExtension}"}
${lib.optionalString cfg.verbose "export VERBOSE=1"} ${lib.optionalString cfg.verbose "export VERBOSE=1"}

View file

@ -1,7 +1,7 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
inherit (lib) concatStringsSep hm mkMerge mkOption types; inherit (lib) concatStringsSep hm mkIf mkMerge mkOption types;
dag = lib.hm.dag; dag = lib.hm.dag;
@ -14,10 +14,14 @@ in {
options.tested.dag = mkOption { type = hm.types.dagOf types.str; }; options.tested.dag = mkOption { type = hm.types.dagOf types.str; };
config = { config = {
tested = mkMerge [ tested.dag = mkMerge [
{ dag.after = "after"; } { never = mkIf false "never"; }
{ dag.before = dag.entryBefore [ "after" ] "before"; } { after = mkMerge [ "after" (mkIf false "neither") ]; }
{ dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; } { before = dag.entryBefore [ "after" ] (mkIf true "before"); }
{
between =
mkIf true (dag.entryBetween [ "after" ] [ "before" ] "between");
}
]; ];
home.file."result.txt".text = result; home.file."result.txt".text = result;

View file

@ -1 +1,5 @@
{ gpg-override-defaults = ./override-defaults.nix; } {
gpg-immutable-keyfiles = ./immutable-keyfiles.nix;
gpg-mutable-keyfiles = ./mutable-keyfiles.nix;
gpg-override-defaults = ./override-defaults.nix;
}

View file

@ -0,0 +1,52 @@
{ config, lib, pkgs, ... }:
{
programs.gpg = {
enable = true;
mutableKeys = false;
mutableTrust = false;
publicKeys = [
{
source = pkgs.fetchurl {
url =
"https://keybase.io/rycee/pgp_keys.asc?fingerprint=36cacf52d098cc0e78fb0cb13573356c25c424d4";
sha256 = "082mjy6llvrdry6i9r5gx97nw9d89blnam7bghza4ynsjk1mmx6c";
};
trust = 1; # "unknown"
}
{
source = pkgs.fetchurl {
url = "https://www.rsync.net/resources/pubkey.txt";
sha256 = "16nzqfb1kvsxjkq919hxsawx6ydvip3md3qyhdmw54qx6drnxckl";
};
trust = "never";
}
];
};
nmt.script = ''
assertFileNotRegex activate "^export GNUPGHOME='/home/hm-user/.gnupg'$"
assertFileRegex activate \
'^install -m 0700 /nix/store/[0-9a-z]*-gpg-pubring/trustdb.gpg "/home/hm-user/.gnupg/trustdb.gpg"$'
# Setup GPGHOME
export GNUPGHOME=$(mktemp -d)
cp -r $TESTED/home-files/.gnupg/* $GNUPGHOME
TRUSTDB=$(grep -o '/nix/store/[0-9a-z]*-gpg-pubring/trustdb.gpg' $TESTED/activate)
install -m 0700 $TRUSTDB $GNUPGHOME/trustdb.gpg
# Export Trust
export WORKDIR=$(mktemp -d)
${pkgs.gnupg}/bin/gpg -q --export-ownertrust > $WORKDIR/gpgtrust.txt
# Check Trust
assertFileRegex $WORKDIR/gpgtrust.txt \
'^36CACF52D098CC0E78FB0CB13573356C25C424D4:2:$'
assertFileRegex $WORKDIR/gpgtrust.txt \
'^BB847B5A69EF343CEF511B29073C282D7D6F806C:3:$'
'';
}

View file

@ -0,0 +1,30 @@
{ config, lib, pkgs, ... }:
{
programs.gpg = {
enable = true;
publicKeys = [
{
source = builtins.toFile "key1" "key1";
trust = 1;
}
{ source = builtins.toFile "key2" "key2"; }
];
};
test.stubs.gnupg = { };
nmt.script = ''
assertFileContains activate "export GNUPGHOME='/home/hm-user/.gnupg'"
assertFileContains activate "unset GNUPGHOME QUIET_ARG keyId importTrust"
assertFileRegex activate \
'^\$DRY_RUN_CMD @gnupg@/bin/gpg \$QUIET_ARG --import /nix/store/[0-9a-z]*-key1$'
assertFileRegex activate \
'^\$DRY_RUN_CMD importTrust "/nix/store/[0-9a-z]*-key1" 1$'
assertFileRegex activate \
'^\$DRY_RUN_CMD @gnupg@/bin/gpg \$QUIET_ARG --import /nix/store/[0-9a-z]*-key2$'
'';
}

View file

@ -23,6 +23,8 @@ with lib;
nmt.script = '' nmt.script = ''
assertFileExists home-files/bar/foopg/gpg.conf assertFileExists home-files/bar/foopg/gpg.conf
assertFileContent home-files/bar/foopg/gpg.conf ${./override-defaults-expected.conf} assertFileContent home-files/bar/foopg/gpg.conf ${./override-defaults-expected.conf}
assertFileNotRegex activate "^unset GNUPGHOME keyId importTrust$"
''; '';
}; };
} }

View file

@ -175,7 +175,7 @@ with lib;
[[block]] [[block]]
block = "battery" block = "battery"
'' ''
} }
''; '';
}; };

View file

@ -47,7 +47,7 @@ with lib;
block = "time" block = "time"
format = "%a %d/%m %R" format = "%a %d/%m %R"
interval = 60 interval = 60
'' ''
} }
''; '';
}; };

View file

@ -191,7 +191,7 @@ with lib;
[theme.overrides] [theme.overrides]
idle_bg = "#123456" idle_bg = "#123456"
idle_fg = "#abcdef" idle_fg = "#abcdef"
'' ''
} }
''; '';
}; };

View file

@ -1,6 +1,6 @@
configuration { configuration {
location: 0; location: 0;
theme: "custom";
xoffset: 0; xoffset: 0;
yoffset: 0; yoffset: 0;
} }
@theme "custom"

View file

@ -16,4 +16,4 @@ foreground-color: rgba ( 250, 251, 252, 100 % );
width: 512; width: 512;
} }
@import "~/.cache/wal/colors-rofi-dark" @import "~/.cache/wal/colors-rofi-dark"