summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services
diff options
context:
space:
mode:
authorAlexander Sieg <alex@xanderio.de>2024-03-09 17:20:01 +0100
committerAlexander Sieg <alex@xanderio.de>2024-06-25 10:59:30 +0200
commit369cfec06d76aa8e34c394159fe4dfcb222334e2 (patch)
tree7688fd6c3431163dbe5335709a5d57b0342f05fb /nixos/modules/services
parent28106064d742529bc355b5329c1bc9c5bf8649ad (diff)
nixos/wg-access-server: init module
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/networking/wg-access-server.nix124
1 files changed, 124 insertions, 0 deletions
diff --git a/nixos/modules/services/networking/wg-access-server.nix b/nixos/modules/services/networking/wg-access-server.nix
new file mode 100644
index 000000000000..5876699924b2
--- /dev/null
+++ b/nixos/modules/services/networking/wg-access-server.nix
@@ -0,0 +1,124 @@
+{ config, pkgs, lib, ... }:
+let
+ inherit (lib) mkEnableOption mkPackageOption mkOption types;
+
+ cfg = config.services.wg-access-server;
+
+ settingsFormat = pkgs.formats.yaml { };
+ configFile = settingsFormat.generate "config.yaml" cfg.settings;
+in
+{
+
+ options.services.wg-access-server = {
+ enable = mkEnableOption "wg-access-server";
+
+ package = mkPackageOption pkgs "wg-access-server" { };
+
+ settings = mkOption {
+ type = lib.types.submodule {
+ freeformType = settingsFormat.type;
+ options = {
+ dns.enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Enable/disable the embedded DNS proxy server.
+ This is enabled by default and allows VPN clients to avoid DNS leaks by sending all DNS requests to wg-access-server itself.
+ '';
+ };
+ storage = mkOption {
+ type = types.str;
+ default = "sqlite3://db.sqlite";
+ description = "A storage backend connection string. See [storage docs](https://www.freie-netze.org/wg-access-server/3-storage/)";
+ };
+ };
+ };
+ description = "See https://www.freie-netze.org/wg-access-server/2-configuration/ for possible options";
+ };
+
+ secretsFile = mkOption {
+ type = types.path;
+ description = ''
+ yaml file containing all secrets. this needs to be in the same structure as the configuration.
+
+ This must to contain the admin password and wireguard private key.
+ As well as the secrets for your auth backend.
+
+ Example:
+ ```yaml
+ adminPassword: <admin password>
+ wireguard:
+ privateKey: <wireguard private key>
+ auth:
+ oidc:
+ clientSecret: <client secret>
+ ```
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ assertions =
+ map
+ (attrPath:
+ {
+ assertion = !lib.hasAttrByPath attrPath config.services.wg-access-server.settings;
+ message = ''
+ {option}`services.wg-access-server.settings.${lib.concatStringsSep "." attrPath}` must definded
+ in {option}`services.wg-access-server.secretsFile`.
+ '';
+ })
+ [
+ [ "adminPassword" ]
+ [ "wireguard" "privateKey" ]
+ [ "auth" "sessionStore" ]
+ [ "auth" "oidc" "clientSecret" ]
+ [ "auth" "gitlab" "clientSecret" ]
+ ];
+
+ boot.kernel.sysctl = {
+ "net.ipv4.conf.all.forwarding" = "1";
+ "net.ipv6.conf.all.forwarding" = "1";
+ };
+
+ systemd.services.wg-access-server = {
+ description = "WG access server";
+ wantedBy = [ "multi-user.target" ];
+ requires = [ "network-online.target" ];
+ after = [ "network-online.target" ];
+ script = ''
+ # merge secrets into main config
+ yq eval-all "select(fileIndex == 0) * select(fileIndex == 1)" ${configFile} $CREDENTIALS_DIRECTORY/SECRETS_FILE \
+ > "$STATE_DIRECTORY/config.yml"
+
+ ${lib.getExe cfg.package} serve --config "$STATE_DIRECTORY/config.yml"
+ '';
+
+ path = with pkgs; [
+ iptables
+ # needed by startup script
+ yq-go
+ ];
+
+ serviceConfig =
+ let
+ capabilities = [
+ "CAP_NET_ADMIN"
+ ] ++ lib.optional cfg.settings.dns.enabled "CAP_NET_BIND_SERVICE";
+ in
+ {
+ WorkingDirectory = "/var/lib/wg-access-server";
+ StateDirectory = "wg-access-server";
+
+ LoadCredential = [
+ "SECRETS_FILE:${cfg.secretsFile}"
+ ];
+
+ # Hardening
+ DynamicUser = true;
+ AmbientCapabilities = capabilities;
+ CapabilityBoundingSet = capabilities;
+ };
+ };
+ };
+}