From 96d8478568077383dc79be5f185b62258a94183c Mon Sep 17 00:00:00 2001 From: Elias Coppens Date: Sun, 9 Mar 2025 00:39:38 +0100 Subject: [PATCH] feat(modules/nixos): init openbao module Signed-off-by: Elias Coppens --- REUSE.toml | 12 ++ default.nix | 10 ++ modules/nixos/default.nix | 1 + modules/nixos/openbao/default.nix | 248 ++++++++++++++++++++++++++ patches/nixpkgs/09-init-openbao.patch | 79 ++++++++ patches/nixpkgs/10-bump-openbao.patch | 34 ++++ 6 files changed, 384 insertions(+) create mode 100644 modules/nixos/openbao/default.nix create mode 100644 patches/nixpkgs/09-init-openbao.patch create mode 100644 patches/nixpkgs/10-bump-openbao.patch diff --git a/REUSE.toml b/REUSE.toml index 142ad9f..8b64410 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -64,3 +64,15 @@ SPDX-FileCopyrightText = "La Délégation Générale Numérique +# +# SPDX-License-Identifier: MIT + +{ + config, + lib, + pkgs, + ... +}: + +let + inherit (lib) + optionalAttrs + optional + escapeShellArgs + concatMap + mkEnableOption + mkOption + mkIf + types + literalExpression + mkPackageOption + escapeSystemdExecArgs + getExe' + genJqSecretsReplacementSnippet + ; + + cfg = config.services.openbao; + + jsonFormat = pkgs.formats.json; + + configFile = jsonFormat.generate "openbao.json" ( + cfg.extraConfig + // { + listener.tcp = + { + inherit (cfg) address; + } + // ( + if cfg.tlsCertFile == null || cfg.tlsKeyFile == null then + { tls_disable = true; } + else + { + tls_cert_file = cfg.tlsCertFile; + tls_key_file = cfg.tlsKeyFile; + } + ) + // cfg.listenerExtraConfig; + + storage.${cfg.storageBackend} = + cfg.storageConfig // (optionalAttrs (cfg.storagePath != null) { path = cfg.storagePath; }); + } + // (optionalAttrs (cfg.telemetryConfig != { }) { telemetry = cfg.telemetryConfig; }) + ); + + allConfigPaths = [ "/var/lib/openbao/config.json" ] ++ cfg.extraSettingsPaths; + configOptions = escapeShellArgs ( + concatMap (p: [ + "-config" + p + ]) allConfigPaths + ); + +in + +{ + options = { + services.openbao = { + enable = mkEnableOption "OpenBao daemon"; + + package = mkPackageOption pkgs "openbao" { }; + + address = mkOption { + type = types.str; + default = "127.0.0.1:8200"; + description = "The name of the ip interface to listen to"; + }; + + tlsCertFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/path/to/your/cert.pem"; + description = "TLS certificate file. TLS will be disabled unless this option is set"; + }; + + tlsKeyFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/path/to/your/key.pem"; + description = "TLS private key file. TLS will be disabled unless this option is set"; + }; + + listenerExtraConfig = mkOption { + inherit (jsonFormat) type; + default = { + tls_min_version = "tls12"; + }; + description = "Extra text appended to the listener section."; + }; + + storageBackend = mkOption { + type = types.enum [ + "inmem" + "file" + "consul" + "zookeeper" + "s3" + "azure" + "dynamodb" + "etcd" + "mssql" + "mysql" + "postgresql" + "swift" + "gcs" + "raft" + ]; + default = "inmem"; + description = "The name of the type of storage backend"; + }; + + storagePath = mkOption { + type = types.nullOr types.path; + default = + if cfg.storageBackend == "file" || cfg.storageBackend == "raft" then "/var/lib/vault" else null; + defaultText = literalExpression '' + if config.storageBackend == "file" || cfg.storageBackend == "raft" + then "/var/lib/vault" + else null + ''; + description = "Data directory for file backend"; + }; + + storageConfig = mkOption { + inherit (jsonFormat) type; + default = { }; + description = '' + JSON configuration to insert in the storageBackend section. + + Confidential values should not be specified here because this option's + value is written to the Nix store, which is publicly readable. + Provide credentials and such in a separate file using + [](#opt-services.vault.extraSettingsPaths). + ''; + }; + + telemetryConfig = mkOption { + type = types.lines; + default = ""; + description = "Telemetry configuration"; + }; + + extraConfig = mkOption { + inherit (jsonFormat) type; + default = ""; + description = "Extra text appended to {file}`vault.json`."; + }; + + extraSettingsPaths = mkOption { + type = types.listOf types.path; + default = [ ]; + description = '' + Configuration files to load besides the immutable one defined by the NixOS module. + This can be used to avoid putting credentials in the Nix store, which can be read by any user. + + Each path can point to a JSON- or HCL-formatted file, or a directory + to be scanned for files with `.hcl` or + `.json` extensions. + + To upload the confidential file with NixOps, use for example: + + ``` + # https://releases.nixos.org/nixops/latest/manual/manual.html#opt-deployment.keys + deployment.keys."vault.hcl" = let db = import ./db-credentials.nix; in { + text = ${"''"} + storage "postgresql" { + connection_url = "postgres://''${db.username}:''${db.password}@host.example.com/exampledb?sslmode=verify-ca" + } + ${"''"}; + user = "vault"; + }; + services.vault.extraSettingsPaths = ["/run/keys/vault.hcl"]; + services.vault.storageBackend = "postgresql"; + users.users.vault.extraGroups = ["keys"]; + ``` + ''; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.openbao ]; + + assertions = [ + { + assertion = cfg.storageBackend == "inmem" -> (cfg.storagePath == null && cfg.storageConfig == null); + message = ''The "inmem" storage expects no services.vault.storagePath nor services.vault.storageConfig''; + } + { + assertion = + (cfg.storageBackend == "file" -> (cfg.storagePath != null && cfg.storageConfig == null)) + && (cfg.storagePath != null -> (cfg.storageBackend == "file" || cfg.storageBackend == "raft")); + message = ''You must set services.vault.storagePath only when using the "file" or "raft" backend''; + } + ]; + + systemd.services.openbao = { + description = "OpenBao server daemon"; + + wantedBy = [ "multi-user.target" ]; + after = [ + "network.target" + ] ++ optional (config.services.consul.enable && cfg.storageBackend == "consul") "consul.service"; + + restartIfChanged = false; # do not restart on "nixos-rebuild switch". It would seal the storage and disrupt the clients. + preStart = genJqSecretsReplacementSnippet configFile "/var/lib/openbao/config.json"; + + startLimitIntervalSec = 60; + startLimitBurst = 3; + serviceConfig = { + DynamicUser = true; + ExecStart = escapeSystemdExecArgs [ + (lib.getExe cfg.package) + "server" + configOptions + ]; + ExecReload = "${getExe' pkgs.coreutils "kill"} -SIGHUP $MAINPID"; + StateDirectory = "openbao"; + UMask = "0700"; + # In `dev` mode vault will put its token here + PrivateDevices = true; + PrivateTmp = true; + ProtectSystem = "full"; + ProtectHome = "read-only"; + AmbientCapabilities = "cap_ipc_lock"; + NoNewPrivileges = true; + LimitCORE = 0; + KillSignal = "SIGINT"; + TimeoutStopSec = "30s"; + Restart = "on-failure"; + }; + + unitConfig.RequiresMountsFor = optional (cfg.storagePath != null) cfg.storagePath; + }; + }; + +} diff --git a/patches/nixpkgs/09-init-openbao.patch b/patches/nixpkgs/09-init-openbao.patch new file mode 100644 index 0000000..bcc1ed7 --- /dev/null +++ b/patches/nixpkgs/09-init-openbao.patch @@ -0,0 +1,79 @@ +From ad2e433d0a0089a28a0b4fee03f6a819b9a35ec9 Mon Sep 17 00:00:00 2001 +From: Brian May +Date: Sat, 14 Dec 2024 07:54:30 +1100 +Subject: [PATCH] openbao: init at 2.1.0 + +Release notes - https://github.com/openbao/openbao/releases/tag/v2.1.0 +Changelog - https://github.com/openbao/openbao/blob/main/CHANGELOG.md +--- + pkgs/by-name/op/openbao/package.nix | 60 +++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + create mode 100644 pkgs/by-name/op/openbao/package.nix + +diff --git a/pkgs/by-name/op/openbao/package.nix b/pkgs/by-name/op/openbao/package.nix +new file mode 100644 +index 00000000000000..6990e97cca5428 +--- /dev/null ++++ b/pkgs/by-name/op/openbao/package.nix +@@ -0,0 +1,60 @@ ++{ ++ lib, ++ fetchFromGitHub, ++ buildGoModule, ++ testers, ++ openbao, ++}: ++buildGoModule rec { ++ pname = "openbao"; ++ version = "2.1.0"; ++ ++ src = fetchFromGitHub { ++ owner = "openbao"; ++ repo = "openbao"; ++ rev = "v${version}"; ++ hash = "sha256-QzUNb4T9uau9bWZX6ulUDyfdInGd86iClBAG72C+7mo="; ++ }; ++ ++ vendorHash = "sha256-Lg58NbwO7vLNRCBwJujcoVcrV018FevvdrUassnAg3k="; ++ ++ proxyVendor = true; ++ ++ subPackages = [ "." ]; ++ ++ tags = [ ++ "openbao" ++ "bao" ++ ]; ++ ++ ldflags = [ ++ "-s" ++ "-w" ++ "-X github.com/openbao/openbao/version.GitCommit=${src.rev}" ++ "-X github.com/openbao/openbao/version.fullVersion=${version}" ++ ]; ++ ++ postInstall = '' ++ mv $out/bin/openbao $out/bin/bao ++ ''; ++ ++ # TODO: Enable the NixOS tests after adding OpenBao as a NixOS service in an upcoming PR and ++ # adding NixOS tests ++ # ++ # passthru.tests = { inherit (nixosTests) vault vault-postgresql vault-dev vault-agent; }; ++ ++ passthru.tests.version = testers.testVersion { ++ package = openbao; ++ command = "HOME=$(mktemp -d) bao --version"; ++ version = "v${version}"; ++ }; ++ ++ meta = with lib; { ++ homepage = "https://www.openbao.org/"; ++ description = "Open source, community-driven fork of Vault managed by the Linux Foundation"; ++ changelog = "https://github.com/openbao/openbao/blob/v${version}/CHANGELOG.md"; ++ license = licenses.mpl20; ++ mainProgram = "bao"; ++ maintainers = with maintainers; [ brianmay ]; ++ }; ++} + diff --git a/patches/nixpkgs/10-bump-openbao.patch b/patches/nixpkgs/10-bump-openbao.patch new file mode 100644 index 0000000..d55f2e2 --- /dev/null +++ b/patches/nixpkgs/10-bump-openbao.patch @@ -0,0 +1,34 @@ +From 45289b73c454b53f1910d6aa9826e85c56292fc7 Mon Sep 17 00:00:00 2001 +From: "R. Ryantm" +Date: Wed, 22 Jan 2025 01:43:17 +0000 +Subject: [PATCH] openbao: 2.1.0 -> 2.1.1 + +--- + pkgs/by-name/op/openbao/package.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/by-name/op/openbao/package.nix b/pkgs/by-name/op/openbao/package.nix +index 6990e97cca5428..d18cb99e061769 100644 +--- a/pkgs/by-name/op/openbao/package.nix ++++ b/pkgs/by-name/op/openbao/package.nix +@@ -7,16 +7,16 @@ + }: + buildGoModule rec { + pname = "openbao"; +- version = "2.1.0"; ++ version = "2.1.1"; + + src = fetchFromGitHub { + owner = "openbao"; + repo = "openbao"; + rev = "v${version}"; +- hash = "sha256-QzUNb4T9uau9bWZX6ulUDyfdInGd86iClBAG72C+7mo="; ++ hash = "sha256-viN1Yuqnyg/nrRzV2HkjVGZSWD9QIXLN6nG5N0QtwbU="; + }; + +- vendorHash = "sha256-Lg58NbwO7vLNRCBwJujcoVcrV018FevvdrUassnAg3k="; ++ vendorHash = "sha256-dSEFoD2UbY6OejSxPBDxCNKHBoHI8YNnixayIS7z3e8="; + + proxyVendor = true; + +