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