at 23.11-pre 6.7 kB view raw
1{ config, lib, options, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.etcd; 7 opt = options.services.etcd; 8 9in { 10 11 options.services.etcd = { 12 enable = mkOption { 13 description = lib.mdDoc "Whether to enable etcd."; 14 default = false; 15 type = types.bool; 16 }; 17 18 name = mkOption { 19 description = lib.mdDoc "Etcd unique node name."; 20 default = config.networking.hostName; 21 defaultText = literalExpression "config.networking.hostName"; 22 type = types.str; 23 }; 24 25 advertiseClientUrls = mkOption { 26 description = lib.mdDoc "Etcd list of this member's client URLs to advertise to the rest of the cluster."; 27 default = cfg.listenClientUrls; 28 defaultText = literalExpression "config.${opt.listenClientUrls}"; 29 type = types.listOf types.str; 30 }; 31 32 listenClientUrls = mkOption { 33 description = lib.mdDoc "Etcd list of URLs to listen on for client traffic."; 34 default = ["http://127.0.0.1:2379"]; 35 type = types.listOf types.str; 36 }; 37 38 listenPeerUrls = mkOption { 39 description = lib.mdDoc "Etcd list of URLs to listen on for peer traffic."; 40 default = ["http://127.0.0.1:2380"]; 41 type = types.listOf types.str; 42 }; 43 44 initialAdvertisePeerUrls = mkOption { 45 description = lib.mdDoc "Etcd list of this member's peer URLs to advertise to rest of the cluster."; 46 default = cfg.listenPeerUrls; 47 defaultText = literalExpression "config.${opt.listenPeerUrls}"; 48 type = types.listOf types.str; 49 }; 50 51 initialCluster = mkOption { 52 description = lib.mdDoc "Etcd initial cluster configuration for bootstrapping."; 53 default = ["${cfg.name}=http://127.0.0.1:2380"]; 54 defaultText = literalExpression ''["''${config.${opt.name}}=http://127.0.0.1:2380"]''; 55 type = types.listOf types.str; 56 }; 57 58 initialClusterState = mkOption { 59 description = lib.mdDoc "Etcd initial cluster configuration for bootstrapping."; 60 default = "new"; 61 type = types.enum ["new" "existing"]; 62 }; 63 64 initialClusterToken = mkOption { 65 description = lib.mdDoc "Etcd initial cluster token for etcd cluster during bootstrap."; 66 default = "etcd-cluster"; 67 type = types.str; 68 }; 69 70 discovery = mkOption { 71 description = lib.mdDoc "Etcd discovery url"; 72 default = ""; 73 type = types.str; 74 }; 75 76 clientCertAuth = mkOption { 77 description = lib.mdDoc "Whether to use certs for client authentication"; 78 default = false; 79 type = types.bool; 80 }; 81 82 trustedCaFile = mkOption { 83 description = lib.mdDoc "Certificate authority file to use for clients"; 84 default = null; 85 type = types.nullOr types.path; 86 }; 87 88 certFile = mkOption { 89 description = lib.mdDoc "Cert file to use for clients"; 90 default = null; 91 type = types.nullOr types.path; 92 }; 93 94 keyFile = mkOption { 95 description = lib.mdDoc "Key file to use for clients"; 96 default = null; 97 type = types.nullOr types.path; 98 }; 99 100 peerCertFile = mkOption { 101 description = lib.mdDoc "Cert file to use for peer to peer communication"; 102 default = cfg.certFile; 103 defaultText = literalExpression "config.${opt.certFile}"; 104 type = types.nullOr types.path; 105 }; 106 107 peerKeyFile = mkOption { 108 description = lib.mdDoc "Key file to use for peer to peer communication"; 109 default = cfg.keyFile; 110 defaultText = literalExpression "config.${opt.keyFile}"; 111 type = types.nullOr types.path; 112 }; 113 114 peerTrustedCaFile = mkOption { 115 description = lib.mdDoc "Certificate authority file to use for peer to peer communication"; 116 default = cfg.trustedCaFile; 117 defaultText = literalExpression "config.${opt.trustedCaFile}"; 118 type = types.nullOr types.path; 119 }; 120 121 peerClientCertAuth = mkOption { 122 description = lib.mdDoc "Whether to check all incoming peer requests from the cluster for valid client certificates signed by the supplied CA"; 123 default = false; 124 type = types.bool; 125 }; 126 127 extraConf = mkOption { 128 description = lib.mdDoc '' 129 Etcd extra configuration. See 130 <https://github.com/coreos/etcd/blob/master/Documentation/op-guide/configuration.md#configuration-flags> 131 ''; 132 type = types.attrsOf types.str; 133 default = {}; 134 example = literalExpression '' 135 { 136 "CORS" = "*"; 137 "NAME" = "default-name"; 138 "MAX_RESULT_BUFFER" = "1024"; 139 "MAX_CLUSTER_SIZE" = "9"; 140 "MAX_RETRY_ATTEMPTS" = "3"; 141 } 142 ''; 143 }; 144 145 dataDir = mkOption { 146 type = types.path; 147 default = "/var/lib/etcd"; 148 description = lib.mdDoc "Etcd data directory."; 149 }; 150 }; 151 152 config = mkIf cfg.enable { 153 systemd.tmpfiles.rules = [ 154 "d '${cfg.dataDir}' 0700 etcd - - -" 155 ]; 156 157 systemd.services.etcd = { 158 description = "etcd key-value store"; 159 wantedBy = [ "multi-user.target" ]; 160 after = [ "network.target" ]; 161 162 environment = (filterAttrs (n: v: v != null) { 163 ETCD_NAME = cfg.name; 164 ETCD_DISCOVERY = cfg.discovery; 165 ETCD_DATA_DIR = cfg.dataDir; 166 ETCD_ADVERTISE_CLIENT_URLS = concatStringsSep "," cfg.advertiseClientUrls; 167 ETCD_LISTEN_CLIENT_URLS = concatStringsSep "," cfg.listenClientUrls; 168 ETCD_LISTEN_PEER_URLS = concatStringsSep "," cfg.listenPeerUrls; 169 ETCD_INITIAL_ADVERTISE_PEER_URLS = concatStringsSep "," cfg.initialAdvertisePeerUrls; 170 ETCD_PEER_CLIENT_CERT_AUTH = toString cfg.peerClientCertAuth; 171 ETCD_PEER_TRUSTED_CA_FILE = cfg.peerTrustedCaFile; 172 ETCD_PEER_CERT_FILE = cfg.peerCertFile; 173 ETCD_PEER_KEY_FILE = cfg.peerKeyFile; 174 ETCD_CLIENT_CERT_AUTH = toString cfg.clientCertAuth; 175 ETCD_TRUSTED_CA_FILE = cfg.trustedCaFile; 176 ETCD_CERT_FILE = cfg.certFile; 177 ETCD_KEY_FILE = cfg.keyFile; 178 }) // (optionalAttrs (cfg.discovery == ""){ 179 ETCD_INITIAL_CLUSTER = concatStringsSep "," cfg.initialCluster; 180 ETCD_INITIAL_CLUSTER_STATE = cfg.initialClusterState; 181 ETCD_INITIAL_CLUSTER_TOKEN = cfg.initialClusterToken; 182 }) // (mapAttrs' (n: v: nameValuePair "ETCD_${n}" v) cfg.extraConf); 183 184 unitConfig = { 185 Documentation = "https://github.com/coreos/etcd"; 186 }; 187 188 serviceConfig = { 189 Type = "notify"; 190 ExecStart = "${pkgs.etcd}/bin/etcd"; 191 User = "etcd"; 192 LimitNOFILE = 40000; 193 }; 194 }; 195 196 environment.systemPackages = [ pkgs.etcd ]; 197 198 users.users.etcd = { 199 isSystemUser = true; 200 group = "etcd"; 201 description = "Etcd daemon user"; 202 home = cfg.dataDir; 203 }; 204 users.groups.etcd = {}; 205 }; 206}