Compare commits
23 commits
master
...
release-21
Author | SHA1 | Date | |
---|---|---|---|
d93d56ab8c | |||
d14adb99f3 | |||
5eb2102aef | |||
834d863dd2 | |||
236c6ec214 | |||
e997bf4c98 | |||
7244c6715c | |||
7049cf37a9 | |||
ef6799c1ce | |||
0bdbdea2e2 | |||
ef6b316265 | |||
a8d00f5c03 | |||
47ae373e74 | |||
2e527cf33c | |||
2860d7e3bb | |||
28b9ae40c4 | |||
697cc8c68e | |||
e0bfb57d62 | |||
93ad8661c7 | |||
6ce1d64073 | |||
9437177e82 | |||
3e93c4e8b2 | |||
4daff26495 |
4
.github/workflows/github_pages.yml
vendored
4
.github/workflows/github_pages.yml
vendored
|
@ -10,8 +10,8 @@ jobs:
|
|||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v15
|
||||
- uses: actions/checkout@v3
|
||||
- uses: cachix/install-nix-action@v17
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@v10
|
||||
|
|
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
@ -11,10 +11,10 @@ jobs:
|
|||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v15
|
||||
- uses: actions/checkout@v3
|
||||
- uses: cachix/install-nix-action@v17
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
nix_path: nixpkgs=channel:nixos-21.11
|
||||
- uses: cachix/cachix-action@v10
|
||||
with:
|
||||
name: nix-community
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
released in stable NixOS. To avoid breaking users' configurations,
|
||||
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
|
||||
an issue.
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
[[sec-release-21.11]]
|
||||
== Release 21.11
|
||||
|
||||
This is the current unstable branch and the information in this
|
||||
section is therefore not final.
|
||||
The 21.11 release branch became the stable branch in November, 2021.
|
||||
|
||||
[[sec-release-21.11-highlights]]
|
||||
=== Highlights
|
||||
|
|
1
format
1
format
|
@ -24,7 +24,6 @@ find . -name '*.nix' \
|
|||
! -path ./modules/manual.nix \
|
||||
! -path ./modules/misc/news.nix \
|
||||
! -path ./modules/programs/bash.nix \
|
||||
! -path ./modules/programs/gpg.nix \
|
||||
! -path ./modules/programs/ssh.nix \
|
||||
! -path ./modules/programs/zsh.nix \
|
||||
! -path ./modules/services/gpg-agent.nix \
|
||||
|
|
|
@ -10,6 +10,23 @@ function errorEcho() {
|
|||
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() {
|
||||
if [[ -v VERBOSE ]]; then
|
||||
export VERBOSE_ARG="--verbose"
|
||||
|
@ -263,9 +280,9 @@ function doBuild() {
|
|||
setFlakeAttribute
|
||||
if [[ -v FLAKE_CONFIG_URI ]]; then
|
||||
doBuildFlake \
|
||||
"${DRY_RUN+--dry-run} \
|
||||
"${NO_OUT_LINK+--no-link} \
|
||||
"$FLAKE_CONFIG_URI.activationPackage" \
|
||||
${DRY_RUN+--dry-run} \
|
||||
${NO_OUT_LINK+--no-link} \
|
||||
|| return
|
||||
else
|
||||
doBuildAttr \
|
||||
|
@ -294,8 +311,8 @@ function doSwitch() {
|
|||
setFlakeAttribute
|
||||
if [[ -v FLAKE_CONFIG_URI ]]; then
|
||||
doBuildFlake \
|
||||
--out-link "$generation" \
|
||||
"$FLAKE_CONFIG_URI.activationPackage" \
|
||||
--out-link "$generation" \
|
||||
&& "$generation/activate" || return
|
||||
else
|
||||
doBuildAttr \
|
||||
|
@ -371,8 +388,9 @@ function doExpireGenerations() {
|
|||
}
|
||||
|
||||
function doListPackages() {
|
||||
setNixProfileCommands
|
||||
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
|
||||
nix-store -q --references "$outPath" | sed 's/[^-]*-//'
|
||||
else
|
||||
|
@ -447,6 +465,7 @@ function doShowNews() {
|
|||
|
||||
function doUninstall() {
|
||||
setVerboseAndDryRun
|
||||
setNixProfileCommands
|
||||
|
||||
echo "This will remove Home Manager from your system."
|
||||
|
||||
|
@ -464,7 +483,7 @@ function doUninstall() {
|
|||
HOME_MANAGER_CONFIG="$(mktemp --tmpdir home-manager.XXXXXXXXXX)"
|
||||
echo "{ lib, ... }: { home.file = lib.mkForce {}; }" > "$HOME_MANAGER_CONFIG"
|
||||
doSwitch
|
||||
$DRY_RUN_CMD nix-env -e home-manager-path || true
|
||||
$DRY_RUN_CMD $REMOVE_CMD home-manager-path || true
|
||||
rm "$HOME_MANAGER_CONFIG"
|
||||
$DRY_RUN_CMD rm $VERBOSE_ARG -r \
|
||||
"${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"
|
||||
|
|
|
@ -239,7 +239,7 @@ in
|
|||
}
|
||||
|
||||
function cleanOldGen() {
|
||||
if [[ ! -v oldGenPath ]] ; then
|
||||
if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then
|
||||
return
|
||||
fi
|
||||
|
||||
|
@ -260,7 +260,17 @@ in
|
|||
|
||||
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
|
||||
echo "Creating profile generation $newGenNum"
|
||||
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"
|
||||
else
|
||||
echo "No change so reusing latest profile generation $oldGenNum"
|
||||
|
|
|
@ -578,30 +578,49 @@ in
|
|||
if config.submoduleSupport.externalPackageInstall
|
||||
then
|
||||
''
|
||||
if [[ -e "$nixProfilePath"/manifest.json ]] ; then
|
||||
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
|
||||
''
|
||||
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
|
||||
|
||||
Oops, nix-env failed to install your new Home Manager profile!
|
||||
|
||||
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
|
||||
|
||||
nix-env -e {package name}
|
||||
$REMOVE_CMD_SYNTAX
|
||||
|
||||
Then try activating your Home Manager configuration again.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
unset INSTALL_CMD LIST_CMD REMOVE_CMD_SYNTAX
|
||||
''
|
||||
);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ function setupVars() {
|
|||
local profilesPath="$nixStateDir/profiles/per-user/$USER"
|
||||
local gcPath="$nixStateDir/gcroots/per-user/$USER"
|
||||
|
||||
declare -gr nixProfilePath="$profilesPath/profile"
|
||||
declare -gr genProfilePath="$profilesPath/home-manager"
|
||||
declare -gr newGenPath="@GENERATION_DIR@";
|
||||
declare -gr newGenGcPath="$gcPath/current-home"
|
||||
|
|
|
@ -8,8 +8,9 @@ let
|
|||
|
||||
isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before);
|
||||
|
||||
dagContentType = elemType:
|
||||
types.submodule ({ name, ... }: {
|
||||
dagEntryOf = elemType:
|
||||
let
|
||||
submoduleType = types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
data = mkOption { type = elemType; };
|
||||
after = mkOption { type = with types; uniq (listOf str); };
|
||||
|
@ -19,6 +20,15 @@ let
|
|||
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 {
|
||||
# A directed acyclic graph of some inner type.
|
||||
|
@ -29,21 +39,16 @@ in rec {
|
|||
# "actual" attribute name a new submodule argument is provided with
|
||||
# the name `dagName`.
|
||||
dagOf = elemType:
|
||||
let
|
||||
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);
|
||||
let attrEquivalent = types.attrsOf (dagEntryOf elemType);
|
||||
in mkOptionType rec {
|
||||
name = "dagOf";
|
||||
description = "DAG of ${elemType.description}s";
|
||||
check = isAttrs;
|
||||
merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs);
|
||||
inherit (attrEquivalent) check merge emptyValue;
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: dagOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
nestedTypes.elemType = elemType;
|
||||
};
|
||||
|
||||
# A directed acyclic graph of some inner type OR a list of that
|
||||
|
|
|
@ -15,8 +15,6 @@ in {
|
|||
"direnv"
|
||||
"enableNixDirenvIntegration"
|
||||
] [ "programs" "direnv" "nix-direnv" "enable" ])
|
||||
(mkRemovedOptionModule [ "programs" "direnv" "nix-direnv" "enableFlakes" ]
|
||||
"Flake support is now always enabled.")
|
||||
];
|
||||
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
@ -81,6 +79,7 @@ in {
|
|||
<link
|
||||
xlink:href="https://github.com/nix-community/nix-direnv">nix-direnv</link>,
|
||||
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
|
||||
package =
|
||||
pkgs.nix-direnv.override { inherit (cfg.nix-direnv) enableFlakes; };
|
||||
text = concatStringsSep "\n" (optional (cfg.stdlib != "") cfg.stdlib
|
||||
++ optional cfg.nix-direnv.enable
|
||||
"source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc");
|
||||
"source ${package}/share/nix-direnv/direnvrc");
|
||||
in mkIf (text != "") { inherit text; };
|
||||
|
||||
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
|
||||
|
|
|
@ -6,9 +6,7 @@ let
|
|||
cfg = config.programs.gpg;
|
||||
|
||||
mkKeyValue = key: value:
|
||||
if isString value
|
||||
then "${key} ${value}"
|
||||
else optionalString value key;
|
||||
if isString value then "${key} ${value}" else optionalString value key;
|
||||
|
||||
cfgText = generators.toKeyValue {
|
||||
inherit mkKeyValue;
|
||||
|
@ -21,8 +19,132 @@ let
|
|||
} cfg.scdaemonSettings;
|
||||
|
||||
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 = {
|
||||
enable = mkEnableOption "GnuPG";
|
||||
|
||||
|
@ -31,11 +153,13 @@ in
|
|||
default = pkgs.gnupg;
|
||||
defaultText = literalExpression "pkgs.gnupg";
|
||||
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 {
|
||||
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
|
||||
type =
|
||||
types.attrsOf (types.either primitiveType (types.listOf types.str));
|
||||
example = literalExpression ''
|
||||
{
|
||||
no-comments = false;
|
||||
|
@ -53,7 +177,8 @@ in
|
|||
};
|
||||
|
||||
scdaemonSettings = mkOption {
|
||||
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
|
||||
type =
|
||||
types.attrsOf (types.either primitiveType (types.listOf types.str));
|
||||
example = literalExpression ''
|
||||
{
|
||||
disable-ccid = true;
|
||||
|
@ -68,11 +193,54 @@ in
|
|||
|
||||
homedir = mkOption {
|
||||
type = types.path;
|
||||
example = literalExpression "\"\${config.xdg.dataHome}/gnupg\"";
|
||||
example = literalExpression ''"''${config.xdg.dataHome}/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.";
|
||||
};
|
||||
|
||||
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 {
|
||||
|
@ -80,7 +248,8 @@ in
|
|||
personal-cipher-preferences = mkDefault "AES256 AES192 AES";
|
||||
personal-digest-preferences = mkDefault "SHA512 SHA384 SHA256";
|
||||
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";
|
||||
s2k-digest-algo = mkDefault "SHA512";
|
||||
s2k-cipher-algo = mkDefault "AES256";
|
||||
|
@ -102,12 +271,56 @@ in
|
|||
};
|
||||
|
||||
home.packages = [ cfg.package ];
|
||||
home.sessionVariables = {
|
||||
GNUPGHOME = cfg.homedir;
|
||||
};
|
||||
home.sessionVariables = { GNUPGHOME = cfg.homedir; };
|
||||
|
||||
home.file."${cfg.homedir}/gpg.conf".text = cfgText;
|
||||
|
||||
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);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -44,14 +44,15 @@ let
|
|||
}
|
||||
''));
|
||||
|
||||
channelString = concatStringsSep cnl (flip mapAttrsToList cfg.networks (k: v:
|
||||
concatStringsSep cnl (flip mapAttrsToList v.channels (c: cv: ''
|
||||
channelString = concatStringsSep cnl (concatLists
|
||||
(flip mapAttrsToList cfg.networks (k: v:
|
||||
(flip mapAttrsToList v.channels (c: cv: ''
|
||||
{
|
||||
chatnet = "${k}";
|
||||
name = "${c}";
|
||||
autojoin = "${boolStr cv.autoJoin}";
|
||||
}
|
||||
''))));
|
||||
'')))));
|
||||
|
||||
channelType = types.submodule {
|
||||
options = {
|
||||
|
|
|
@ -530,20 +530,20 @@ let
|
|||
|
||||
uiOptions = with cfg.config.ui;
|
||||
concatStringsSep " " [
|
||||
"ncurses_set_title=${if setTitle then "true" else "false"}"
|
||||
"ncurses_status_on_top=${
|
||||
"terminal_set_title=${if setTitle then "true" else "false"}"
|
||||
"terminal_status_on_top=${
|
||||
if (statusLine == "top") then "true" else "false"
|
||||
}"
|
||||
"ncurses_assistant=${assistant}"
|
||||
"ncurses_enable_mouse=${if enableMouse then "true" else "false"}"
|
||||
"ncurses_change_colors=${if changeColors then "true" else "false"}"
|
||||
"terminal_assistant=${assistant}"
|
||||
"terminal_enable_mouse=${if enableMouse then "true" else "false"}"
|
||||
"terminal_change_colors=${if changeColors then "true" else "false"}"
|
||||
"${optionalString (wheelDownButton != null)
|
||||
"ncurses_wheel_down_button=${wheelDownButton}"}"
|
||||
"terminal_wheel_down_button=${wheelDownButton}"}"
|
||||
"${optionalString (wheelUpButton != null)
|
||||
"ncurses_wheel_up_button=${wheelUpButton}"}"
|
||||
"terminal_wheel_up_button=${wheelUpButton}"}"
|
||||
"${optionalString (shiftFunctionKeys != null)
|
||||
"ncurses_shift_function_key=${toString shiftFunctionKeys}"}"
|
||||
"ncurses_builtin_key_parser=${
|
||||
"terminal_shift_function_key=${toString shiftFunctionKeys}"}"
|
||||
"terminal_builtin_key_parser=${
|
||||
if useBuiltinKeyParser then "true" else "false"
|
||||
}"
|
||||
];
|
||||
|
|
|
@ -35,10 +35,10 @@ let
|
|||
${configStr}}
|
||||
''
|
||||
else
|
||||
mkKeyValue {
|
||||
(mkKeyValue {
|
||||
sep = " ";
|
||||
end = "";
|
||||
} name value;
|
||||
} name value) + "\n";
|
||||
|
||||
toRasi = attrs: concatStringsSep "\n" (mapAttrsToList mkRasiSection attrs);
|
||||
|
||||
|
@ -266,9 +266,9 @@ in {
|
|||
location = (getAttr cfg.location locationsMap);
|
||||
xoffset = cfg.xoffset;
|
||||
yoffset = cfg.yoffset;
|
||||
theme = themeName;
|
||||
} // 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 {
|
||||
"rofi/themes/${themeName}.rasi".text = toRasi cfg.theme;
|
||||
|
|
|
@ -170,6 +170,18 @@ in
|
|||
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
|
||||
'';
|
||||
|
||||
programs.bash.initExtra = gpgInitStr;
|
||||
programs.zsh.initExtra = gpgInitStr;
|
||||
programs.fish.interactiveShellInit = ''
|
||||
programs.bash.initExtra = mkIf cfg.enableBashIntegration gpgInitStr;
|
||||
programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgInitStr;
|
||||
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
|
||||
set -gx GPG_TTY (tty)
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -29,6 +29,10 @@ let
|
|||
|
||||
home.username = config.users.users.${name}.name;
|
||||
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;
|
||||
|
@ -130,7 +134,7 @@ in
|
|||
system.activationScripts.postActivation.text =
|
||||
concatStringsSep "\n" (mapAttrsToList (username: usercfg: ''
|
||||
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)
|
||||
"export HOME_MANAGER_BACKUP_EXT=${lib.escapeShellArg cfg.backupFileExtension}"}
|
||||
${lib.optionalString cfg.verbose "export VERBOSE=1"}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) concatStringsSep hm mkMerge mkOption types;
|
||||
inherit (lib) concatStringsSep hm mkIf mkMerge mkOption types;
|
||||
|
||||
dag = lib.hm.dag;
|
||||
|
||||
|
@ -14,10 +14,14 @@ in {
|
|||
options.tested.dag = mkOption { type = hm.types.dagOf types.str; };
|
||||
|
||||
config = {
|
||||
tested = mkMerge [
|
||||
{ dag.after = "after"; }
|
||||
{ dag.before = dag.entryBefore [ "after" ] "before"; }
|
||||
{ dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; }
|
||||
tested.dag = mkMerge [
|
||||
{ never = mkIf false "never"; }
|
||||
{ after = mkMerge [ "after" (mkIf false "neither") ]; }
|
||||
{ before = dag.entryBefore [ "after" ] (mkIf true "before"); }
|
||||
{
|
||||
between =
|
||||
mkIf true (dag.entryBetween [ "after" ] [ "before" ] "between");
|
||||
}
|
||||
];
|
||||
|
||||
home.file."result.txt".text = result;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
52
tests/modules/programs/gpg/immutable-keyfiles.nix
Normal file
52
tests/modules/programs/gpg/immutable-keyfiles.nix
Normal 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:$'
|
||||
'';
|
||||
}
|
30
tests/modules/programs/gpg/mutable-keyfiles.nix
Normal file
30
tests/modules/programs/gpg/mutable-keyfiles.nix
Normal 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$'
|
||||
'';
|
||||
}
|
|
@ -23,6 +23,8 @@ with lib;
|
|||
nmt.script = ''
|
||||
assertFileExists home-files/bar/foopg/gpg.conf
|
||||
assertFileContent home-files/bar/foopg/gpg.conf ${./override-defaults-expected.conf}
|
||||
|
||||
assertFileNotRegex activate "^unset GNUPGHOME keyId importTrust$"
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
configuration {
|
||||
location: 0;
|
||||
theme: "custom";
|
||||
xoffset: 0;
|
||||
yoffset: 0;
|
||||
}
|
||||
@theme "custom"
|
||||
|
|
Loading…
Reference in a new issue