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