aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--default.nix2
-rw-r--r--modules/home-environment.nix1
-rw-r--r--modules/misc/news.nix46
-rw-r--r--modules/modules.nix10
-rw-r--r--modules/programs/home-manager.nix2
-rw-r--r--modules/systemd-activate.sh (renamed from modules/systemd-activate.nix)44
-rw-r--r--modules/systemd.nix26
-rw-r--r--nixos/default.nix57
8 files changed, 161 insertions, 27 deletions
diff --git a/default.nix b/default.nix
index 2988bbbf0d8..9ae18232316 100644
--- a/default.nix
+++ b/default.nix
@@ -9,4 +9,6 @@ rec {
install = import ./home-manager/install.nix {
inherit home-manager pkgs;
};
+
+ nixos = import ./nixos;
}
diff --git a/modules/home-environment.nix b/modules/home-environment.nix
index 197e9dc57f3..6c98343d792 100644
--- a/modules/home-environment.nix
+++ b/modules/home-environment.nix
@@ -291,6 +291,7 @@ in
# script's "check" and the "write" phases.
home.activation.writeBoundary = dag.entryAnywhere "";
+ # Install packages to the user environment.
home.activation.installPackages = dag.entryAfter ["writeBoundary"] ''
$DRY_RUN_CMD nix-env -i ${cfg.path}
'';
diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index 47efef6a146..0fffe2ea8c9 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -568,6 +568,52 @@ in
GTK configurations.
'';
}
+
+ {
+ time = "2018-02-06T20:23:34+00:00";
+ message = ''
+ It is now possible to use Home Manager as a NixOS module.
+ This allows you to prepare user environments from the system
+ configuration file, which often is more convenient than
+ using the 'home-manager' tool. It also opens up additional
+ possibilities, for example, to automatically configure user
+ environments in NixOS declarative containers or on systems
+ deployed through NixOps.
+
+ This feature should be considered experimental for now and
+ some critial limitations apply. For example, it is currently
+ not possible to use 'nixos-rebuild build-vm' when using the
+ Home Manager NixOS module. That said, it should be
+ reasonably robust and stable for simpler use cases.
+
+ To make Home Manager available in your NixOS system
+ configuration you can add
+
+ imports = [
+ "''${builtins.fetchTarball https://github.com/rycee/home-manager/archive/master.tar.gz}/nixos"
+ ];
+
+ to your 'configuration.nix' file. This will introduce a new
+ NixOS option called 'home-manager.users' whose type is an
+ attribute set mapping user names to Home Manager
+ configurations.
+
+ For example, a NixOS configuration may include the lines
+
+ users.users.eve.isNormalUser = true;
+ home-manager.users.eve = {
+ home.packages = [ pkgs.atool pkgs.httpie ];
+ programs.bash.enable = true;
+ };
+
+ and after a 'nixos-rebuild switch' the user eve's
+ environment should include a basic Bash configuration and
+ the packages atool and httpie.
+
+ More detailed documentation on the intricacies of this new
+ feature is slowly forthcoming.
+ '';
+ }
];
};
}
diff --git a/modules/modules.nix b/modules/modules.nix
index c179c732536..7e9e6dae7e4 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -3,6 +3,9 @@
# Whether to enable module type checking.
, check ? true
+
+ # Whether these modules are inside a NixOS submodule.
+, nixosSubmodule ? false
}:
with lib;
@@ -75,10 +78,17 @@ let
];
pkgsModule = {
+ options.nixosSubmodule = mkOption {
+ type = types.bool;
+ internal = true;
+ readOnly = true;
+ };
+
config._module.args.baseModules = modules;
config._module.args.pkgs = lib.mkDefault pkgs;
config._module.check = check;
config.lib = import ./lib { inherit lib; };
+ config.nixosSubmodule = nixosSubmodule;
config.nixpkgs.system = mkDefault pkgs.system;
};
diff --git a/modules/programs/home-manager.nix b/modules/programs/home-manager.nix
index 306b14a2198..e9d48117da0 100644
--- a/modules/programs/home-manager.nix
+++ b/modules/programs/home-manager.nix
@@ -32,7 +32,7 @@ in
};
};
- config = mkIf cfg.enable {
+ config = mkIf (cfg.enable && !config.nixosSubmodule) {
home.packages = [
(import ../../home-manager {
inherit pkgs;
diff --git a/modules/systemd-activate.nix b/modules/systemd-activate.sh
index 5e3b5773df7..1c464693cfc 100644
--- a/modules/systemd-activate.nix
+++ b/modules/systemd-activate.sh
@@ -1,14 +1,14 @@
-systemctlPath:
-''
+#!/usr/bin/env bash
+
function isStartable() {
local service="$1"
- [[ $(${systemctlPath} --user show -p RefuseManualStart "$service") == *=no ]]
+ [[ $(systemctl --user show -p RefuseManualStart "$service") == *=no ]]
}
function isStoppable() {
if [[ -v oldGenPath ]] ; then
local service="$1"
- [[ $(${systemctlPath} --user show -p RefuseManualStop "$service") == *=no ]]
+ [[ $(systemctl --user show -p RefuseManualStop "$service") == *=no ]]
fi
}
@@ -53,19 +53,19 @@ function systemdPostReload() {
--old-line-format='-%L' \
--unchanged-line-format=' %L' \
"$oldServiceFiles" "$newServiceFiles" \
- > $servicesDiffFile || true
+ > "$servicesDiffFile" || true
- local -a maybeRestart=( $(grep '^ ' $servicesDiffFile | cut -c2-) )
- local -a maybeStop=( $(grep '^-' $servicesDiffFile | cut -c2-) )
- local -a maybeStart=( $(grep '^+' $servicesDiffFile | cut -c2-) )
+ local -a maybeRestart=( $(grep '^ ' "$servicesDiffFile" | cut -c2-) )
+ local -a maybeStop=( $(grep '^-' "$servicesDiffFile" | cut -c2-) )
+ local -a maybeStart=( $(grep '^+' "$servicesDiffFile" | cut -c2-) )
local -a toRestart=( )
local -a toStop=( )
local -a toStart=( )
- for f in ''${maybeRestart[@]} ; do
+ for f in "${maybeRestart[@]}" ; do
if isStoppable "$f" \
&& isStartable "$f" \
- && ${systemctlPath} --quiet --user is-active "$f" \
+ && systemctl --quiet --user is-active "$f" \
&& ! cmp --quiet \
"$oldUserServicePath/$f" \
"$newUserServicePath/$f" ; then
@@ -73,32 +73,32 @@ function systemdPostReload() {
fi
done
- for f in ''${maybeStop[@]} ; do
+ for f in "${maybeStop[@]}" ; do
if isStoppable "$f" ; then
toStop+=("$f")
fi
done
- for f in ''${maybeStart[@]} ; do
+ for f in "${maybeStart[@]}" ; do
if isStartable "$f" ; then
toStart+=("$f")
fi
done
- rm -r $workDir
+ rm -r "$workDir"
local sugg=""
- if [[ -n "''${toRestart[@]}" ]] ; then
- sugg="''${sugg}systemctl --user restart ''${toRestart[@]}\n"
+ if [[ -n "${toRestart[@]}" ]] ; then
+ sugg="${sugg}systemctl --user restart ${toRestart[@]}\n"
fi
- if [[ -n "''${toStop[@]}" ]] ; then
- sugg="''${sugg}systemctl --user stop ''${toStop[@]}\n"
+ if [[ -n "${toStop[@]}" ]] ; then
+ sugg="${sugg}systemctl --user stop ${toStop[@]}\n"
fi
- if [[ -n "''${toStart[@]}" ]] ; then
- sugg="''${sugg}systemctl --user start ''${toStart[@]}\n"
+ if [[ -n "${toStart[@]}" ]] ; then
+ sugg="${sugg}systemctl --user start ${toStart[@]}\n"
fi
if [[ -n "$sugg" ]] ; then
@@ -107,6 +107,8 @@ function systemdPostReload() {
fi
}
-$DRY_RUN_CMD ${systemctlPath} --user daemon-reload
+oldGenPath="$1"
+newGenPath="$2"
+
+$DRY_RUN_CMD systemctl --user daemon-reload
systemdPostReload
-''
diff --git a/modules/systemd.nix b/modules/systemd.nix
index 3ee5ccc8ef9..9eaba7c22b1 100644
--- a/modules/systemd.nix
+++ b/modules/systemd.nix
@@ -145,14 +145,30 @@ in
(buildServices "timer" cfg.timers)
);
+ # Run systemd service reload if user is logged in. If we're
+ # running this from the NixOS module then XDG_RUNTIME_DIR is not
+ # set and systemd commands will fail. We'll therefore have to
+ # set it ourselves in that case.
home.activation.reloadSystemD = dag.entryAfter ["linkGeneration"] (
- if cfg.startServices then
+ let
+ autoReloadCmd = ''
+ ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \
+ "''${oldGenPath=}" "$newGenPath" "${servicesStartTimeoutMs}"
+ '';
+
+ legacyReloadCmd = ''
+ bash ${./systemd-activate.sh} "''${oldGenPath=}" "$newGenPath"
+ '';
+ in
''
- PATH=${dirOf cfg.systemctlPath} \
- ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \
- "''${oldGenPath=}" "$newGenPath" "${servicesStartTimeoutMs}"
+ if who | grep -q '^${config.home.username} '; then
+ XDG_RUNTIME_DIR=''${XDG_RUNTIME_DIR:-/run/user/$(id -u)} \
+ PATH=${dirOf cfg.systemctlPath}:$PATH \
+ ${if cfg.startServices then autoReloadCmd else legacyReloadCmd}
+ else
+ echo "User ${config.home.username} not logged in. Skipping."
+ fi
''
- else import ./systemd-activate.nix cfg.systemctlPath
);
})
];
diff --git a/nixos/default.nix b/nixos/default.nix
new file mode 100644
index 00000000000..d72d8a19557
--- /dev/null
+++ b/nixos/default.nix
@@ -0,0 +1,57 @@
+{ config, lib, pkgs, utils, ... }:
+
+with lib;
+
+let
+
+ cfg = config.home-manager;
+
+ hmModule = types.submodule ({name, ...}: {
+ imports = import ../modules/modules.nix {
+ inherit lib pkgs;
+ nixosSubmodule = true;
+ };
+
+ config = {
+ home.username = config.users.users.${name}.name;
+ home.homeDirectory = config.users.users.${name}.home;
+ };
+ });
+
+in
+
+{
+ options = {
+ home-manager.users = mkOption {
+ type = types.attrsOf hmModule;
+ default = {};
+ description = ''
+ Per-user Home Manager configuration.
+ '';
+ };
+ };
+
+ config = mkIf (cfg.users != {}) {
+ systemd.services = mapAttrs' (username: usercfg:
+ nameValuePair ("home-manager-${utils.escapeSystemdPath username}") {
+ description = "Home Manager environment for ${username}";
+ wantedBy = [ "multi-user.target" ];
+
+ serviceConfig = {
+ User = username;
+ Type = "oneshot";
+ RemainAfterExit = "yes";
+ SyslogIdentifier = "hm-activate-${username}";
+
+ # The activation script is run by a login shell to make sure
+ # that the user is given a sane Nix environment.
+ ExecStart = pkgs.writeScript "activate-${username}" ''
+ #! ${pkgs.stdenv.shell} -el
+ echo Activating home-manager configuration for ${username}
+ exec ${usercfg.home.activationPackage}/activate
+ '';
+ };
+ }
+ ) cfg.users;
+ };
+}