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