Skip to content

Commit

Permalink
nixos/murmur: add option environmentFile for injecting secrets
Browse files Browse the repository at this point in the history
Secrets are injected from the environment into the rendered
configuration before each startup using envsubst.
The test now makes use of this feature for the server password.
  • Loading branch information
elseym committed Oct 7, 2020
1 parent c7f33a5 commit 533560d
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
46 changes: 41 additions & 5 deletions nixos/modules/services/networking/murmur.nix
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,34 @@ in
default = "";
description = "Extra configuration to put into murmur.ini.";
};

environmentFile = mkOption {
type = types.nullOr types.path;
default = null;
example = "/var/lib/murmur/murmurd.env";
description = ''
Environment file as defined in <citerefentry>
<refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>.
Secrets may be passed to the service without adding them to the world-readable
Nix store, by specifying placeholder variables as the option value in Nix and
setting these variables accordingly in the environment file.
<programlisting>
# snippet of murmur-related config
services.murmur.password = "$MURMURD_PASSWORD";
</programlisting>
<programlisting>
# content of the environment file
MURMURD_PASSWORD=verysecretpassword
</programlisting>
Note that this file needs to be available on the host on which
<literal>murmur</literal> is running.
'';
};
};
};

Expand All @@ -256,14 +284,22 @@ in
description = "Murmur Chat Service";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target "];
preStart = ''
${pkgs.envsubst}/bin/envsubst \
-o /run/murmur/murmurd.ini \
-i ${configFile}
'';

serviceConfig = {
# murmurd doesn't fork when logging to the console.
Type = if forking then "forking" else "simple";
PIDFile = mkIf forking "/run/murmur/murmurd.pid";
RuntimeDirectory = mkIf forking "murmur";
User = "murmur";
ExecStart = "${pkgs.murmur}/bin/murmurd -ini ${configFile}";
Type = if forking then "forking" else "simple";
PIDFile = mkIf forking "/run/murmur/murmurd.pid";
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
ExecStart = "${pkgs.murmur}/bin/murmurd -ini /run/murmur/murmurd.ini";
Restart = "always";
RuntimeDirectory = "murmur";
RuntimeDirectoryMode = "0700";
User = "murmur";
};
};
};
Expand Down
22 changes: 17 additions & 5 deletions nixos/tests/mumble.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ let
imports = [ ./common/x11.nix ];
environment.systemPackages = [ pkgs.mumble ];
};

# outside of tests, this file should obviously not come from the nix store
envFile = pkgs.writeText "nixos-test-mumble-murmurd.env" ''
MURMURD_PASSWORD=testpassword
'';

in
{
name = "mumble";
Expand All @@ -14,8 +20,10 @@ in

nodes = {
server = { config, ... }: {
services.murmur.enable = true;
services.murmur.enable = true;
services.murmur.registerName = "NixOS tests";
services.murmur.password = "$MURMURD_PASSWORD";
services.murmur.environmentFile = envFile;
networking.firewall.allowedTCPPorts = [ config.services.murmur.port ];
};

Expand All @@ -30,8 +38,8 @@ in
client1.wait_for_x()
client2.wait_for_x()
client1.execute("mumble mumble://client1\@server/test &")
client2.execute("mumble mumble://client2\@server/test &")
client1.execute("mumble mumble://client1:testpassword\@server/test &")
client2.execute("mumble mumble://client2:testpassword\@server/test &")
# cancel client audio configuration
client1.wait_for_window(r"Audio Tuning Wizard")
Expand Down Expand Up @@ -63,8 +71,12 @@ in
client2.send_chars("y")
# Find clients in logs
server.wait_until_succeeds("journalctl -eu murmur -o cat | grep -q client1")
server.wait_until_succeeds("journalctl -eu murmur -o cat | grep -q client2")
server.wait_until_succeeds(
"journalctl -eu murmur -o cat | grep -q 'client1.\+Authenticated'"
)
server.wait_until_succeeds(
"journalctl -eu murmur -o cat | grep -q 'client2.\+Authenticated'"
)
server.sleep(5) # wait to get screenshot
client1.screenshot("screen1")
Expand Down

0 comments on commit 533560d

Please sign in to comment.