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