From 2d2f73a9257035398e90d32dcfb7db74313d8fe6 Mon Sep 17 00:00:00 2001 From: Robert Orr Date: Mon, 25 Aug 2025 13:37:33 -0700 Subject: Generates 3 different lenghts of secrets, for future use to be written to files. Change-Id: I314d0350b03fedebeedc7eddedf409a286719486 --- flake.nix | 13 ++++++ options.nix | 38 +++++++++++++++++ secrets-lengths.md | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 options.nix create mode 100644 secrets-lengths.md diff --git a/flake.nix b/flake.nix index 2c67d17..9e73b80 100644 --- a/flake.nix +++ b/flake.nix @@ -1,4 +1,11 @@ { + description = '' + A tool to manage credentials and other secrets as mutable state within a NixOS environment, + consisting of a Rust executable, NixOS configuration, and associated documentation. + Published as part of the Small Tech Kit, ISL's public resource for small organizations + that want to host their own infrastructure, but usable independently. + ''; + inputs = { nixpkgs = { type = "github"; @@ -25,6 +32,12 @@ }; }); + nixosModules.default = { ... }: { + imports = [ + ./options.nix + ]; + }; + devShells = forAllSystems (system: let pkgs = nixpkgsFor.${system}; in { default = pkgs.mkShell { nativeBuildInputs = with pkgs; [ diff --git a/options.nix b/options.nix new file mode 100644 index 0000000..044833b --- /dev/null +++ b/options.nix @@ -0,0 +1,38 @@ + +{ pkgs, lib }: + +let + scriptRegistry = { + bigsecret = ''head -c 64 /dev/urandom | base32''; + medsecret = ''head -c 32 /dev/urandom | base32''; + smallsecret = ''head -c 16 /dev/urandom | base32''; + }; +in { + secrets.secrets = lib.mkOption { + description = '' + A set of secrets, each identified by a name (e.g. mattermost, gitlabce). + Each secret has a filename and a script to generate it. + ''; + default = { }; + type = lib.types.attrsOf (lib.types.submodule { + options = { + filename = lib.mkOption { + type = lib.types.str; + description = '' + The filename where this secret is stored, all + files at /etc/nixos/secrets + ''; + example = "mysecret.key"; + }; + script = lib.mkOption { + type = lib.types.str; + description = '' + Shell command that generates the secret. + "; + example = "head -c 32 /dev/urandom | base32"; + }; + }; + }); + }; +} + diff --git a/secrets-lengths.md b/secrets-lengths.md new file mode 100644 index 0000000..efa00ed --- /dev/null +++ b/secrets-lengths.md @@ -0,0 +1,119 @@ +# If we have a couple of applications, lets say mattermost, jenkins, opengrok for example - +# do they all require secrets of the same length and if so, we would need to create them at that length - so we would need scripts for each desired length, or have the length be a parameter. + # - Mattermost: MM_SECRET (Session/Encryption Key) - 64 chars or more + # - Mattermost: database passwords - 24 to 32 chars reccommended + # - Jenkins master key: 128 bit key, around 24 chars + # - Jenkins API tokens - 32 chars typically + # - Jenkins misc tokens - at least 32 to 64 chars + # - opengrok - between 16 and 64 chars depending on what for + + +# There are multiple ways to generate secrets, here's a by no means complete set of examples - we could even generate the long ones and cut them down. + +# Generate a random 32-byte secret and output as base32 + head -c 32 /dev/urandom | base32 + +# You can programmatically access or generate secrets: + nix eval --raw '(import {}).lib.mkSecret "mysecret"' + +# You can also store secrets outside the config with systemd: + { + systemd.services.myService.environment = { + SECRET_KEY = builtins.readFile /etc/secrets/mysecret; + }; + } +# mkpasswd + # variety of encryption methods, of different lengths + +# Many NixOS users integrate password managers to generate secrets dynamically: + pass generate my-service/secret 32 + +# Here's reusable secrets.nix template for NixOS. It generates multiple secrets for different services and can be imported into configuration.nix without exposing them in Git. + + { lib, pkgs, ... }: + + let + # Helper to generate a random base32 secret of given length + randomSecret = length: + builtins.toString (builtins.base32Encode (pkgs.lib.randomString length)); + + in { + # Example: PostgreSQL password + postgresPassword = lib.mkSecret (randomSecret 32); + + # Example: Redis password + redisPassword = lib.mkSecret (randomSecret 32); + + # Example: API token for some internal service + internalApiToken = lib.mkSecret (randomSecret 40); + + # Example: Web application secret key + webAppSecretKey = lib.mkSecret (randomSecret 64); + + # Example: SSH authorized key for automated tasks + automatedSshKey = lib.mkSecret (randomSecret 32); + + # You can add more services as needed + } +# and how to use in configuration.nix: + { config, pkgs, ... }: + + let + secrets = import ./secrets.nix { inherit pkgs lib; }; + in + { + services.postgresql = { + enable = true; + authentication = { + password = secrets.postgresPassword; + }; + }; + + services.redis.enable = true; + services.redis.password = secrets.redisPassword; + + # Example environment variable for web service + systemd.services.myWebApp.environment = { + SECRET_KEY = secrets.webAppSecretKey; + API_TOKEN = secrets.internalApiToken; + }; + } + +# ========================================================================================== + # 1. Short secrets (8–16 characters) + # • Use: Low-security tokens, simple service passwords, or internal tools with limited exposure. + # • Example Applications: + # • Temporary API keys for internal scripts + # • Simple Redis instance with limited access + # • Example: + shortToken = lib.mkSecret (builtins.toString (pkgs.lib.randomString 12)); + + # 2. Medium secrets (20–32 characters) + # • Use: Standard passwords for services, moderate security tokens, session keys. + # • Example Applications: + # • PostgreSQL or MySQL passwords + # • Redis passwords + # • Docker registry tokens + # • Example: + postgresPassword = lib.mkSecret (builtins.toString (pkgs.lib.randomString 24)); + redisPassword = lib.mkSecret (builtins.toString (pkgs.lib.randomString 32)); + + # 3. Long secrets (40–64 characters) + # • Use: Cryptographic keys, high-security API tokens, web application secrets. + # • Example Applications: + # • Web framework SECRET_KEY for session encryption (Django, Flask, etc.) + # • JWT signing keys + # • OAuth2 client secrets + # • Example: + webAppSecretKey = lib.mkSecret (builtins.toString (pkgs.lib.randomString 64)); + internalApiToken = lib.mkSecret (builtins.toString (pkgs.lib.randomString 48)); + + # 4. Very long secrets (128+ characters) + # • Use: Encryption keys, long-lived service-to-service authentication, blockchain keys. + # • Example Applications: + # • SSH private keys or passphrases + # • TLS certificates private keys + # • End-to-end encryption secrets for messaging apps + # • Example: + tlsPrivateKey = lib.mkSecret (builtins.toString (pkgs.lib.randomString 128)); + sshKeyPassphrase = lib.mkSecret (builtins.toString (pkgs.lib.randomString 256)); \ No newline at end of file -- cgit 1.4.1