Skip to content

Commit

Permalink
services/yggdrasil: init
Browse files Browse the repository at this point in the history
  • Loading branch information
Rubikoid committed Jul 10, 2024
1 parent cf297a8 commit 744a7f5
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
./services/trezord.nix
./services/wg-quick.nix
./services/yabai
./services/yggdrasil.nix
./services/nextdns
./programs/bash
./programs/direnv.nix
Expand Down
117 changes: 117 additions & 0 deletions modules/services/yggdrasil.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.yggdrasil;

settingsProvided = cfg.settings != { };
configFileProvided = cfg.configFile != null;

format = pkgs.formats.json { };
in
{
options = with types; {
services.yggdrasil = {
enable = mkEnableOption ("the yggdrasil system service");

settings = mkOption {
type = format.type;
default = { };
example = {
Peers = [
"tcp://aa.bb.cc.dd:eeeee"
"tcp://[aaaa:bbbb:cccc:dddd::eeee]:fffff"
];
Listen = [
"tcp://0.0.0.0:xxxxx"
];
};
description = ''
Configuration for yggdrasil, as a Nix attribute set.
Warning: this is stored in the WORLD-READABLE Nix store!
Therefore, it is not appropriate for private keys. If you
wish to specify the keys, use {option}`configFile`.
If no keys are specified then ephemeral keys are generated
and the Yggdrasil interface will have a random IPv6 address
each time the service is started. This is the default.
If both {option}`configFile` and {option}`settings`
are supplied, they will be combined, with values from
{option}`configFile` taking precedence.
You can use the command `nix-shell -p yggdrasil --run "yggdrasil -genconf"`
to generate default configuration values with documentation.
'';
};

configFile = mkOption {
type = nullOr path;
default = null;
example = "/run/keys/yggdrasil.conf";
description = lib.mdDoc ''
A file which contains JSON or HJSON configuration for yggdrasil. See
the {option}`settings` option for more information.
Note: This file must not be larger than 1 MB because it is passed to
the yggdrasil process via systemd‘s LoadCredential mechanism. For
details, see <https://systemd.io/CREDENTIALS/> and `man 5
systemd.exec`.
'';
};

package = mkPackageOption pkgs "yggdrasil" { };

extraArgs = mkOption {
type = listOf str;
default = [ ];
example = [ "-loglevel" "info" ];
description = lib.mdDoc "Extra command line arguments.";
};
};
};

config = mkIf cfg.enable (
let
yggdrasilConf = "/run/yggdrasil/yggdrasil.conf";
binYggdrasil = "${cfg.package}/bin/yggdrasil";
binHjson = "${pkgs.hjson-go}/bin/hjson-cli";
in
{
environment.systemPackages = [ cfg.package ];

# have to write it in that way to not interfere with brew's (or idk github?) ygg.plist
launchd.daemons.ygg =
{
script = ''
set -euo pipefail
mkdir -p $(dirname ${yggdrasilConf})
# prepare config file
${(if settingsProvided || configFileProvided then
"echo "
+ (lib.optionalString settingsProvided
"'${builtins.toJSON cfg.settings}'")
+ (lib.optionalString configFileProvided
"$(${binHjson} -c ${cfg.configFile})")
+ " | ${pkgs.jq}/bin/jq -s add | ${binYggdrasil} -normaliseconf -useconf"
else
"${binYggdrasil} -genconf") + " > ${yggdrasilConf}"}
# start yggdrasil
${binYggdrasil} -useconffile ${yggdrasilConf} ${lib.strings.escapeShellArgs cfg.extraArgs}
'';

serviceConfig = {
ProcessType = "Interactive";
StandardOutPath = "/tmp/yggdrasil.stdout.log";
StandardErrorPath = "/tmp/yggdrasil.stderr.log";
KeepAlive = true;
RunAtLoad = true;
};
};
}
);
}

0 comments on commit 744a7f5

Please sign in to comment.