at 25.11-pre 4.7 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.step-ca; 9 settingsFormat = (pkgs.formats.json { }); 10in 11{ 12 meta.maintainers = [ ]; 13 14 options = { 15 services.step-ca = { 16 enable = lib.mkEnableOption "the smallstep certificate authority server"; 17 openFirewall = lib.mkEnableOption "opening the certificate authority server port"; 18 package = lib.mkOption { 19 type = lib.types.package; 20 default = pkgs.step-ca; 21 defaultText = lib.literalExpression "pkgs.step-ca"; 22 description = "Which step-ca package to use."; 23 }; 24 address = lib.mkOption { 25 type = lib.types.str; 26 example = "127.0.0.1"; 27 description = '' 28 The address (without port) the certificate authority should listen at. 29 This combined with {option}`services.step-ca.port` overrides {option}`services.step-ca.settings.address`. 30 ''; 31 }; 32 port = lib.mkOption { 33 type = lib.types.port; 34 example = 8443; 35 description = '' 36 The port the certificate authority should listen on. 37 This combined with {option}`services.step-ca.address` overrides {option}`services.step-ca.settings.address`. 38 ''; 39 }; 40 settings = lib.mkOption { 41 type = with lib.types; attrsOf anything; 42 description = '' 43 Settings that go into {file}`ca.json`. See 44 [the step-ca manual](https://smallstep.com/docs/step-ca/configuration) 45 for more information. The easiest way to 46 configure this module would be to run `step ca init` 47 to generate {file}`ca.json` and then import it using 48 `builtins.fromJSON`. 49 [This article](https://smallstep.com/docs/step-cli/basic-crypto-operations#run-an-offline-x509-certificate-authority) 50 may also be useful if you want to customize certain aspects of 51 certificate generation for your CA. 52 You need to change the database storage path to {file}`/var/lib/step-ca/db`. 53 54 ::: {.warning} 55 The {option}`services.step-ca.settings.address` option 56 will be ignored and overwritten by 57 {option}`services.step-ca.address` and 58 {option}`services.step-ca.port`. 59 ::: 60 ''; 61 }; 62 intermediatePasswordFile = lib.mkOption { 63 type = lib.types.pathWith { 64 inStore = false; 65 absolute = true; 66 }; 67 example = "/run/keys/smallstep-password"; 68 description = '' 69 Path to the file containing the password for the intermediate 70 certificate private key. 71 72 ::: {.warning} 73 Make sure to use a quoted absolute path instead of a path literal 74 to prevent it from being copied to the globally readable Nix 75 store. 76 ::: 77 ''; 78 }; 79 }; 80 }; 81 82 config = lib.mkIf config.services.step-ca.enable ( 83 let 84 configFile = settingsFormat.generate "ca.json" ( 85 cfg.settings 86 // { 87 address = cfg.address + ":" + toString cfg.port; 88 } 89 ); 90 in 91 { 92 systemd.packages = [ cfg.package ]; 93 94 # configuration file indirection is needed to support reloading 95 environment.etc."smallstep/ca.json".source = configFile; 96 97 systemd.services."step-ca" = { 98 wantedBy = [ "multi-user.target" ]; 99 restartTriggers = [ configFile ]; 100 unitConfig = { 101 ConditionFileNotEmpty = ""; # override upstream 102 }; 103 serviceConfig = { 104 User = "step-ca"; 105 Group = "step-ca"; 106 UMask = "0077"; 107 Environment = "HOME=%S/step-ca"; 108 WorkingDirectory = ""; # override upstream 109 ReadWritePaths = ""; # override upstream 110 111 # LocalCredential handles file permission problems arising from the use of DynamicUser. 112 LoadCredential = "intermediate_password:${cfg.intermediatePasswordFile}"; 113 114 ExecStart = [ 115 "" # override upstream 116 "${cfg.package}/bin/step-ca /etc/smallstep/ca.json --password-file \${CREDENTIALS_DIRECTORY}/intermediate_password" 117 ]; 118 119 # ProtectProc = "invisible"; # not supported by upstream yet 120 # ProcSubset = "pid"; # not supported by upstream yet 121 # PrivateUsers = true; # doesn't work with privileged ports therefore not supported by upstream 122 123 DynamicUser = true; 124 StateDirectory = "step-ca"; 125 }; 126 }; 127 128 users.users.step-ca = { 129 home = "/var/lib/step-ca"; 130 group = "step-ca"; 131 isSystemUser = true; 132 }; 133 134 users.groups.step-ca = { }; 135 136 networking.firewall = lib.mkIf cfg.openFirewall { 137 allowedTCPPorts = [ cfg.port ]; 138 }; 139 } 140 ); 141}