blob: 86be40d4ce21c6b5ded52ac94f55551d41a97b2e [file] [log] [blame]
Sergiusz Bazanski73cef112019-04-07 00:06:23 +02001{ config, pkgs, lib, ... }:
2
3with ( import ./toplevel.nix );
4let
5 fqdn = config.networking.hostName + domain;
6 node = (builtins.head (builtins.filter (n: n.fqdn == fqdn) nodes));
7 otherNodes = (builtins.filter (n: n.fqdn != fqdn) nodes);
8
9in rec {
10 imports =
11 [ # Include the results of the hardware scan.
12 ./hardware-configuration.nix
13 ];
14
15 # Use the GRUB 2 boot loader.
16 boot.loader.grub.enable = true;
17 boot.loader.grub.version = 2;
18 boot.loader.grub.device = node.diskBoot;
19
Sergiusz Bazanski4232c8b2019-04-28 17:12:54 +020020 boot.kernelParams = [ "boot.shell_on_fail" ];
21
Sergiusz Bazanski73cef112019-04-07 00:06:23 +020022 time.timeZone = "Europe/Warsaw";
23
24 # List packages installed in system profile. To search, run:
25 # $ nix search wget
26 environment.systemPackages = with pkgs; [
27 wget vim htop tcpdump
28 rxvt_unicode.terminfo
29 ];
30
31 # Some programs need SUID wrappers, can be configured further or are
32 # started in user sessions.
33 programs.mtr.enable = true;
34
35 # List services that you want to enable:
36 virtualisation.docker.enable = true;
37 virtualisation.docker.extraOptions = "--iptables=false --ip-masq=false --ip-forward=true";
38
39 # Docker 1.13 sets iptables FORWARD to DROP. Unfuck this.
40 systemd.services."docker-iptables-unfuck" = {
41 enable = true;
42 wantedBy = [ "kubernetes.target" ];
43 description = "Docker iptable Unfuck";
44 after = [ "docker.service" ];
45 requires = [ "docker.service" ];
46 path = [ pkgs.iptables ];
47 script = ''
48 iptables -P FORWARD ACCEPT
49 '';
50 serviceConfig.Type = "oneshot";
51 };
52
53 # Enable the OpenSSH daemon.
54 services.openssh.enable = true;
55 users.users.root.openssh.authorizedKeys.keys = [
56 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD4VJXAXEHEXZk2dxNwehneuJcEGkfXG/U7z4fO79vDVIENdedtXQUyLyhZJc5RTEfHhQj66FwIqzl7mzBHd9x9PuDp6QAYXrkVNMj48s6JXqZqBvF6H/weRqFMf4a2TZv+hG8D0kpvmLheCwWAVRls7Jofnp/My+yDd57GMdsbG/yFEf6WPMiOnA7hxdSJSVihCsCSw2p8PD4GhBe8CVt7xIuinhutjm9zYBjV78NT8acjDUfJh0B1ODTjs7nuW1CC4jybSe2j/OU3Yczj4AxRxBNWuFxUq+jBo9BfpbKLh+Tt7re+zBkaicM77KM/oV6943JJxgHNBBOsv9scZE7 q3k@amnesia"
57 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQb3YQoiYFZLKwvHYKbu1bMqzNeDCAszQhAe1+QI5SLDOotclyY/vFmOReZOsmyMFl71G2d7d+FbYNusUnNNjTxRYQ021tVc+RkMdLJaORRURmQfEFEKbai6QSFTwErXzuoIzyEPK0lbsQuGgqT9WaVnRzHJ2Q/4+qQbxAS34PuR5NqEkmn4G6LMo3OyJ5mwPkCj9lsqz4BcxRaMWFO3mNcwGDfSW+sqgc3E8N6LKrTpZq3ke7xacpQmcG5DU9VO+2QVPdltl9jWbs3gXjmF92YRNOuKPVfAOZBBsp8JOznfx8s9wDgs7RwPmDpjIAJEyoABqW5hlXfqRbTnfnMvuR informatic@InformaticPC"
58 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDGkMgEVwQM8yeuFUYL2TwlJIq9yUNBmHnwce46zeL2PK2CkMz7sxT/om7sp/K5XDiqeD05Nioe+Dr3drP6B8uI33S5NgxPIfaqQsRS+CBEgk6cqFlcdlKETU/DT+/WsdoO173n7mgGeafPInEuQuGDUID0Fl099kIxtqfAhdeZFMM6/szAZEZsElLJ8K6dp1Ni/jmnXCZhjivZH3AZUlnqrmtDG7FY1bgcOfDXAal45LItughGPtrdiigXe9DK2fW3+9DBZZduh5DMJTNlphAZ+nfSrbyHVKUg6WsgMSprur4KdU47q1QwzqqvEj75JcdP1jOWoZi4F6VJDte9Wb9lhD1jGgjxY9O6Gs4CH35bx15W7CN9hgNa0C8NbPJe/fZYIeMZmJ1m7O2xmnYwP8j+t7RNJWu7Pa3Em4mOEXvhBF07Zfq+Ye/4SluoRgADy5eII2x5fFo5EBhInxK0/X8wF6XZvysalVifoCh7T4Edejoi91oAxFgYAxbboXGlod0eEHIi2hla8SM9+IBHOChmgawKBYp2kzAJyAmHNBF+Pah9G4arVCj/axp/SJZDZbJQoI7UT/fJzEtvlb5RWrHXRq+y6IvjpUq4pzpDWW04+9UMqEEXRmhWOakHfEVM9rN8h3aJBflLUBBnh0Z/hVsKNh8bCRHaKtah8TrD9i+wMw== patryk.jakuszew@gmail.com"
59 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC33naG1ptCvUcRWX9cj9wXM1nW1lyQC4SvMJzWlr9aMD96O8hQ2JMkuIUgUJvorAY02QRplQ2BuoVoVkdkzwjMyi1bL3OdgcKo7Z1yByClGTTocqNJYY0lcUb6EJH8+6e6F9ydrQlSxNzL1uCaA7phZr+yPcmAmWbSfioXn98yXNkE0emHxzJv/nypJY56sDCMC2IXDRd8L2goDtPwgPEW7bWfAQdIFMJ75xOidZOTxJ8eqyXLw/kxY5UlyX66jdoYz1sE5XUHuoQl1AOG9UdlMo0aMhUvP4pX5l7r7EnA9OttKMFB3oWqkVK/R6ynZ52YNOU5BZ9V+Ppaj34W0xNu+p0mbHcCtXYCTrf/OU0hcZDbDaNTjs6Vtcm2wYw9iAKX7Tex+eOMwUwlrlcyPNRV5BTot7lGNYfauHCSIuWJKN4NhCLR/NtVNh4/94eKkPTwJsY6XqDcS7q49wPAs4DAH7BJgsbHPOqygVHrY0YYEfz3Pj0HTxJHQMCP/hQX4fXEGt0BjgoVJbXPAQtPyeg0JuxiUg+b4CgVVfQ6R060MlM1BZzhmh+FY5MJH6nJppS0aHYCvSg8Z68NUlCPKy0jpcyfuAIWQWwSGG1O010WShQG2ELsvNdg5/4HVdCGNl5mmoom6JOd72FOZyQlHDFfeQUQRn9HOeCq/c51rK99SQ== bartek@IHM"
60 ];
61
62 networking.firewall.enable = false;
63
64 # Point k8s apiserver address at ourselves, as every node runs an apiserver with this cert name.
65 networking.extraHosts = ''
66 127.0.0.1 ${k8sapi}
67 '';
68
69 security.acme.certs = {
70 host = {
71 email = acmeEmail;
72 domain = fqdn;
73 webroot = services.nginx.virtualHosts.host.root;
74 };
75 };
76
77 services.nginx = {
78 enable = true;
79 virtualHosts.host = {
80 serverName = fqdn;
81 root = "/var/www/${fqdn}";
82 };
83 };
84
85 services.etcd = {
86 enable = true;
87 name = fqdn;
88 listenClientUrls = ["https://0.0.0.0:2379"];
89 advertiseClientUrls = ["https://${fqdn}:2379"];
90 listenPeerUrls = ["https://0.0.0.0:2380"];
91 initialAdvertisePeerUrls = ["https://${fqdn}:2380"];
92 initialCluster = (map (n: "${n.fqdn}=https://${n.fqdn}:2380") nodes);
93
94 clientCertAuth = true;
95 trustedCaFile = pki.etcd.server.ca;
96 certFile = pki.etcd.server.cert;
97 keyFile = pki.etcd.server.key;
98
99 peerClientCertAuth = true;
100 peerTrustedCaFile = pki.etcdPeer.ca;
101 peerCertFile = pki.etcdPeer.cert;
102 peerKeyFile = pki.etcdPeer.key;
103
104 extraConf = {
105 PEER_CLIENT_CERT_AUTH = "true";
106 };
107 };
108
109 services.kubernetes = {
110 roles = []; # We do not use any nixpkgs predefined roles for k8s. Instead,
111 # we enable k8s components manually.
112
113 caFile = pki.kube.apiserver.ca;
114 clusterCidr = "10.10.16.0/20";
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200115
116 path = [ pkgs.e2fsprogs ]; # kubelet wants to mkfs.ext4 when mounting pvcs
117
118 addons.dns.enable = false;
119
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200120 apiserver = rec {
121 enable = true;
Sergiusz Bazanski4232c8b2019-04-28 17:12:54 +0200122 insecurePort = ports.k8sAPIServerPlain;
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200123 securePort = ports.k8sAPIServerSecure;
124 advertiseAddress = "${node.ipAddr}";
125
Sergiusz Bazanski4232c8b2019-04-28 17:12:54 +0200126 etcd = {
127 servers = (map (n: "https://${n.fqdn}:2379") nodes);
128 caFile = pki.etcd.kube.ca;
129 keyFile = pki.etcd.kube.key;
130 certFile = pki.etcd.kube.cert;
131 };
132
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200133 tlsCertFile = pki.kube.apiserver.cert;
134 tlsKeyFile = pki.kube.apiserver.key;
135
136 clientCaFile = pki.kube.apiserver.ca;
137
138 kubeletHttps = true;
139 kubeletClientCaFile = pki.kube.apiserver.ca;
140 kubeletClientCertFile = pki.kube.apiserver.cert;
141 kubeletClientKeyFile = pki.kube.apiserver.key;
142
143 serviceAccountKeyFile = pki.kube.serviceaccounts.key;
144
Sergiusz Bazanski4232c8b2019-04-28 17:12:54 +0200145 allowPrivileged = true;
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200146 serviceClusterIpRange = "10.10.12.0/24";
147 runtimeConfig = "api/all,authentication.k8s.io/v1beta1";
148 authorizationMode = ["Node" "RBAC"];
149 enableAdmissionPlugins = ["Initializers" "NamespaceLifecycle" "NodeRestriction" "LimitRanger" "ServiceAccount" "DefaultStorageClass" "ResourceQuota"];
150 extraOpts = ''
151 --apiserver-count=3 \
152 --proxy-client-cert-file=${pki.kubeFront.apiserver.cert} \
153 --proxy-client-key-file=${pki.kubeFront.apiserver.key} \
154 --requestheader-allowed-names= \
155 --requestheader-client-ca-file=${pki.kubeFront.apiserver.ca} \
156 --requestheader-extra-headers-prefix=X-Remote-Extra- \
157 --requestheader-group-headers=X-Remote-Group \
158 --requestheader-username-headers=X-Remote-User \
159 -v=5
160 '';
161 };
162
163 controllerManager = {
164 enable = true;
Sergiusz Bazanski4232c8b2019-04-28 17:12:54 +0200165 bindAddress = "0.0.0.0";
166 insecurePort = ports.k8sControllerManagerPlain;
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200167 leaderElect = true;
168 serviceAccountKeyFile = pki.kube.serviceaccounts.key;
169 rootCaFile = pki.kube.ca;
170 extraOpts = ''
171 --service-cluster-ip-range=10.10.12.0/24 \
172 --use-service-account-credentials=true \
173 --secure-port=${toString ports.k8sControllerManagerSecure}\
174 '';
175 kubeconfig = pki.kube.controllermanager.config;
176 };
177
178 scheduler = {
179 enable = true;
180 address = "0.0.0.0";
181 port = 0;
182 leaderElect = true;
183 kubeconfig = pki.kube.scheduler.config;
184 };
185
186 proxy = {
187 enable = true;
188 kubeconfig = pki.kube.proxy.config;
189 extraOpts = ''
190 --hostname-override=${fqdn}\
191 --proxy-mode=iptables
192 '';
193 };
194
195 kubelet = {
196 enable = true;
197 unschedulable = false;
Sergiusz Bazanski4232c8b2019-04-28 17:12:54 +0200198 allowPrivileged = true;
Sergiusz Bazanski73cef112019-04-07 00:06:23 +0200199 hostname = fqdn;
200 tlsCertFile = pki.kube.kubelet.cert;
201 tlsKeyFile = pki.kube.kubelet.key;
202 clientCaFile = pki.kube.kubelet.ca;
203 nodeIp = node.ipAddr;
204 networkPlugin = "cni";
205 clusterDns = "10.10.12.254";
206 kubeconfig = pki.kube.kubelet.config;
207 extraOpts = ''
208 --cni-conf-dir=/opt/cni/conf \
209 --cni-bin-dir=/opt/cni/bin
210 '';
211 };
212 };
213}