{ config, pkgs, lib, ... }: with lib; let domain = "fudo.org"; hostname = "france.${domain}"; mail-hostname = hostname; host_ipv4 = "208.81.3.117"; # Use a special IP for git.fudo.org, since it needs to be SSH-able docker_ipv4 = "208.81.3.126"; all-hostnames = []; acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem"; acme-certificate = hostname: "/var/lib/acme/${hostname}/fullchain.pem"; acme-ca = "/etc/nixos/static/letsencryptauthorityx3.pem"; fudo-ca = "/etc/nixos/static/fudo_ca.pem"; minecraft-data-dir = "/srv/minecraft/data"; system-mail-directory = "/srv/mail"; in { boot.loader.grub = { enable = true; version = 2; device = "/dev/sda"; }; imports = [ ../hardware-configuration.nix ../defaults.nix ]; fudo.common = { # Sets some server-common settings. See /etc/nixos/fudo/profiles/... profile = "server"; # Sets some common site-specific settings: gateway, monitoring, etc. See /etc/nixos/fudo/sites/... site = "portage"; domain = domain; www-root = /srv/www; local-networks = [ "208.81.1.128/28" "208.81.3.112/28" "172.17.0.0/16" "127.0.0.0/8" ]; }; environment.systemPackages = with pkgs; [ docker lxd multipath-tools nix-prefetch-docker tshark ]; fudo.prometheus = { enable = true; hostname = "metrics.fudo.org"; service-discovery-dns = { node = [ "node._metrics._tcp.fudo.org" ]; postfix = [ "postfix._metrics._tcp.fudo.org" ]; dovecot = [ "dovecot._metrics._tcp.fudo.org" ]; rspamd = [ "rspamd._metrics._tcp.fudo.org" ]; }; }; fudo.grafana = { enable = true; hostname = "monitor.fudo.org"; smtp-username = "metrics"; smtp-password-file = "/srv/grafana/secure/smtp.passwd"; admin-password-file = "/srv/grafana/secure/admin.passwd"; secret-key-file = "/srv/grafana/secure/secret.key"; prometheus-host = "metrics.fudo.org"; database = { name = "grafana"; hostname = "localhost"; user = "grafana"; password-file = /srv/grafana/secure/db.passwd; }; }; # So that grafana waits for postgresql systemd.services.grafana.after = [ "postgresql.service" ]; fudo.postgresql = { enable = true; ssl-private-key = (acme-private-key hostname); ssl-certificate = (acme-certificate hostname); keytab = "/srv/postgres/secure/postgres.keytab"; # We allow connections from local networks. Auth is still required. Outside # of these networks, no access is allowed. # # TODO: that's probably too strict, allow kerberos connections from anywhere? local-networks = [ "208.81.1.128/28" "208.81.3.112/28" "192.168.11.1/24" "127.0.0.1/8" "172.17.0.0/16" ]; users = { fudo_git = { password = fileContents "/srv/git/secure/db.passwd"; databases = { fudo_git = "ALL PRIVILEGES"; }; }; gitlab_postgres = { password = fileContents "/srv/gitlab/secure/db.passwd"; databases = { gitlab = "ALL PRIVILEGES"; }; }; grafana = { password = fileContents "/srv/grafana/secure/db.passwd"; databases = { grafana = "ALL PRIVILEGES"; }; }; mattermost = { password = fileContents "/srv/mattermost/secure/db.passwd"; databases = { mattermost = "ALL PRIVILEGES"; }; }; webmail = { password = fileContents "/srv/webmail/secure/db.passwd"; databases = { webmail = "ALL PRIVILEGES"; }; }; niten = {}; }; local-users = [ "fudo_git" ]; databases = { fudo_git = ["niten"]; gitlab = ["niten"]; grafana = ["niten"]; mattermost = ["niten"]; webmail = ["niten"]; }; }; # Not all users need access to france; don't allow LDAP-user access. fudo.authentication.enable = false; # But we DO run an LDAP auth server. Should be better-named. fudo.auth = { server = { enable = true; base = "dc=fudo,dc=org"; organization = "Fudo"; rootpw-file = "/srv/ldap/secure/root.pw"; kerberos-host = "france.fudo.org"; kerberos-keytab = "/srv/ldap/secure/ldap.keytab"; sslCert = "/srv/ldap/france.fudo.org.pem"; sslKey = "/srv/ldap/secure/france.fudo.org-key.pem"; sslCACert = fudo-ca; # We're using fudo-generated certs for now, but we should move to ACME # once I can figure out how to correctly produce the ca.pem file. Until # then, the server will fail to start using these certs. See: # https://serverfault.com/a/834565 # sslCert = (acme-bare-cert hostname); # sslKey = (acme-private-key hostname); # sslCACert = acme-ca; # TODO: loop over v4 and v6 IPs. listen-uris = [ "ldap:///" "ldaps:///" # "ldap://${host_ipv4}/" # "ldaps://${host_ipv4}/" # "ldap://localhost/" # "ldaps://localhost/" # "ldap://127.0.1.1/" # "ldaps://127.0.1.1/" "ldapi:///" ]; users = import ../fudo/users.nix; groups = import ../fudo/groups.nix; system-users = import ../fudo/system-users.nix; }; # Heimdal Kerberos server kdc = { enable = true; database-path = "/var/heimdal/heimdal"; realm = "FUDO.ORG"; mkey-file = "/var/heimdal/m-key"; acl-file = "/etc/heimdal/kdc.acl"; bind-addresses = [ host_ipv4 "127.0.0.1" "127.0.1.1" ]; }; }; # TODO: not used yet fudo.acme.hostnames = all-hostnames; fudo.mail-server = import ../fudo/email.nix { inherit config; } // { enableContainer = true; debug = true; monitoring = true; hostname = mail-hostname; postfix.ssl-certificate = (acme-certificate mail-hostname); postfix.ssl-private-key = (acme-private-key mail-hostname); dovecot.ssl-certificate = (acme-certificate mail-hostname); dovecot.ssl-private-key = (acme-private-key mail-hostname); state-directory = "${system-mail-directory}/var"; mail-directory = "${system-mail-directory}/mailboxes"; dovecot.ldap-reader-dn = "cn=user_db_reader,dc=fudo,dc=org"; dovecot.ldap-reader-passwd = fileContents /srv/ldap/secure/user_db.passwd; # FIXME: use SSL once I can figure out Acme SSL cert CA for LDAP. dovecot.ldap-urls = [ "ldap://france.fudo.org" ]; clamav.enable = true; dkim.signing = true; }; fudo.webmail = { enable = true; sites = { "webmail.fudo.link" = { title = "Fudo Link Webmail"; favicon = "/etc/nixos/static/fudo.link/favicon.ico"; mail-server = mail-hostname; domain = "fudo.link"; edit-mode = "Plain"; layout-mode = "bottom"; database = { name = "webmail"; hostname = "localhost"; user = "webmail"; password-file = "/srv/webmail/secure/db.passwd"; }; }; "webmail.test.fudo.org" = { title = "Fudo Webmail"; favicon = "/etc/nixos/static/fudo.org/favicon.ico"; mail-server = mail-hostname; domain = "test.fudo.org"; edit-mode = "Plain"; database = { name = "webmail"; hostname = "localhost"; user = "webmail"; password-file = /srv/webmail/secure/db.passwd; }; }; "webmail.test.selby.ca" = { title = "Selby Webmail"; favicon = "/etc/nixos/static/selby.ca/favicon.ico"; mail-server = mail-hostname; domain = "test.selby.ca"; database = { name = "webmail"; hostname = "localhost"; user = "webmail"; password-file = /srv/webmail/secure/db.passwd; }; }; }; }; fudo.chat = { enable = true; hostname = "chat.fudo.org"; site-name = "Fudo Chat"; smtp-server = "france.fudo.org"; smtp-user = "chat"; smtp-password-file = "/srv/mattermost/secure/smtp.passwd"; database = { name = "mattermost"; hostname = "localhost"; user = "mattermost"; password-file = "/srv/mattermost/secure/db.passwd"; }; }; fudo.git = { enable = true; hostname = "git.test.fudo.org"; site-name = "Fudo Git"; user = "fudo_git"; database = { user = "fudo_git"; password-file = /srv/git/secure/db.passwd; hostname = "127.0.0.1"; name = "fudo_git"; }; repository-dir = /srv/git/repo; state-dir = /srv/git/state; }; networking = { hostName = hostname; dhcpcd.enable = false; useDHCP = false; # TODO: fix IPv6 enableIPv6 = false; # Create a bridge for VMs to use macvlans = { extif0 = { interface = "enp4s0f0"; mode = "bridge"; }; extif1 = { interface = "enp4s0f0"; mode = "bridge"; }; intif0 = { interface = "enp4s0f1"; mode = "bridge"; }; }; interfaces = { extif0 = { # result of: # echo $FQDN-extif|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/' macAddress = "02:d4:e8:3b:10:2f"; ipv4.addresses = [ { address = host_ipv4; prefixLength = 28; } ]; }; extif1 = { macAddress = "02:6d:e2:e1:ad:ca"; ipv4.addresses = [ { address = docker_ipv4; prefixLength = 28; } ]; }; intif0 = { # result of: # echo $FQDN-intif|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/' macAddress = "02:ba:ba:e9:08:21"; ipv4.addresses = [ { address = "192.168.11.1"; prefixLength = 24; } ]; }; }; }; hardware.bluetooth.enable = false; virtualisation = { docker = { enable = true; enableOnBoot = true; autoPrune = { enable = true; }; }; lxd = { enable = true; }; }; fileSystems = { "/srv/archiva" = { fsType = "btrfs"; options = ["subvol=archiva"]; label = "pool0"; }; "/srv/grafana" = { fsType = "btrfs"; options = ["subvol=grafana"]; label = "pool0"; }; "${system-mail-directory}" = { fsType = "btrfs"; options = ["subvol=mail"]; label = "pool0"; }; "/srv/gitlab" = { fsType = "btrfs"; options = ["subvol=gitlab"]; label = "pool0"; }; "/var/lib/lxd/storage-pools/pool0" = { fsType = "btrfs"; label = "pool0"; device = "/dev/disk/by-label/pool0"; }; "/var/lib/lxd/storage-pools/pool1" = { fsType = "btrfs"; label = "pool1"; device = "/dev/france-user/fudo-user"; }; }; users = { extraUsers = { archiva = { isNormalUser = false; group = "nogroup"; uid = 8001; }; fudo_git = { isNormalUser = false; uid = 8006; }; gitlab = { isNormalUser = false; uid = 8002; }; gitlab_postgres = { isNormalUser = false; group = config.fudo.postgresql.socket-group; uid = 8003; }; gitlab_redis = { isNormalUser = false; group = "redis-local"; uid = 8004; }; gitlab_www = { isNormalUser = false; group = "nogroup"; uid = 8005; }; }; extraGroups = { redis-local = { members = ["redis"]; gid = 7001; }; }; }; boot.kernel.sysctl = { # For Redis "vm.overcommit_memory" = 1; }; fudo.system = { disableTransparentHugePages = true; postHugePageServices = ["redis.service"]; }; systemd.services.redis.postStart = '' chgrp redis-local ${config.services.redis.unixSocket} ''; security.acme.certs = { "archiva.fudo.org".email = config.fudo.common.admin-email; "git.fudo.org".email = config.fudo.common.admin-email; }; services = { redis = { enable = true; bind = "127.0.0.1"; unixSocket = "/run/redis/redis.socket"; extraConfig = '' unixsocketperm 770 ''; }; nginx = { enable = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedTlsSettings = true; virtualHosts = { "archiva.fudo.org" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:8001"; extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-By $server_addr:$server_port; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; ''; }; }; "git.fudo.org" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:8002"; extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-By $server_addr:$server_port; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; ''; }; }; }; }; }; docker-containers = { archiva = { image = "xetusoss/archiva"; ports = ["127.0.0.1:8001:8080"]; # Ugly: name-to-uid lookup fails. user = toString config.users.users.archiva.uid; volumes = [ "/srv/archiva:/archiva-data" ]; environment = { # Not directly connected to the world anyway SSL_ENABLED = "false"; }; }; gitlab = { image = "gitlab/gitlab-ce:12.8.1-ce.0"; ports = [ "127.0.0.1:8002:80" "${docker_ipv4}::22" ]; # user = toString config.users.users.gitlab.uid; volumes = [ "/run/redis:/var/opt/gitlab/redis" "/srv/gitlab/builds:/var/opt/gitlab/gitlab-ci/builds" "/srv/gitlab/config:/etc/gitlab" "/srv/gitlab/logs:/var/log/gitlab" "/srv/gitlab/gitlab:/var/opt/gitlab" "${config.fudo.postgresql.socket-directory}:/run/postgresql" "${config.fudo.postgresql.socket-directory}:/var/opt/gitlab/postgresql" ]; extraDockerOptions = [ "--hostname=git.fudo.org" ]; }; }; systemd.services.docker-gitlab-config = let gitlab-config = pkgs.writeText "gitlab-config.rb" '' gitlab_rails['db_adapter'] = "postgresql" gitlab_rails['db_encoding'] = "unicode" gitlab_rails['db_database'] = "gitlab" gitlab_rails['db_username'] = "gitlab_postgres" gitlab_rails['db_password'] = "${fileContents /srv/gitlab/secure/db.passwd}" user['uid'] = "${toString config.users.users.gitlab.uid}" user['gid'] = "${toString config.users.groups.redis-local.gid}" # Provided externally redis['enable'] = false postgresql['enable'] = false web_server['uid'] = "${toString config.users.users.gitlab_www.uid}" web_server['gid'] = "${toString config.users.groups.nogroup.gid}" ''; in { # before = ["docker-gitlab.service"]; script = "cp -f ${gitlab-config} /srv/gitlab/config/gitlab.rb"; }; systemd.services.docker-gitlab.requires = ["docker-gitlab-config.service"]; ### # Minecraft ### fudo.minecraft-server = { enable = true; package = pkgs.minecraft-server_1_15_2; data-dir = minecraft-data-dir; world-name = "selbyland"; motd = "Welcome to the Selby Minecraft server."; }; }