diff --git a/config/fudo/mail-container.nix b/config/fudo/mail-container.nix index e12b9ff..c918116 100644 --- a/config/fudo/mail-container.nix +++ b/config/fudo/mail-container.nix @@ -160,22 +160,6 @@ in rec { }; }; - # users = { - # users = { - # ${container-mail-user} = { - # isSystemUser = true; - # uid = container-mail-user-id; - # group = "mailer"; - # }; - # }; - - # groups = { - # ${container-mail-group} = { - # members = ["mailer"]; - # }; - # }; - # }; - fudo.mail-server = { enable = true; hostname = cfg.hostname; diff --git a/config/fudo/mail/postfix.nix b/config/fudo/mail/postfix.nix index d05bf6d..7b96652 100644 --- a/config/fudo/mail/postfix.nix +++ b/config/fudo/mail/postfix.nix @@ -130,7 +130,7 @@ in { virtual = '' ${make-user-aliases cfg.user-aliases} - ${make-alias-users cfg.local-domains cfg.alias-users} + ${make-alias-users ([cfg.domain] ++ cfg.local-domains) cfg.alias-users} ''; sslCert = cfg.postfix.ssl-certificate; diff --git a/config/fudo/prometheus.nix b/config/fudo/prometheus.nix index 54e5b6a..7951932 100644 --- a/config/fudo/prometheus.nix +++ b/config/fudo/prometheus.nix @@ -111,6 +111,8 @@ in { webExternalUrl = "https://${cfg.hostname}"; + listenAddress = "127.0.0.1:9090"; + scrapeConfigs = [ { job_name = "docker"; diff --git a/defaults.nix b/defaults.nix index 7635608..2df8303 100644 --- a/defaults.nix +++ b/defaults.nix @@ -46,7 +46,9 @@ ipfs iptables jdk + jq kerberos + leiningen libisofs libstdcxxHook lispPackages.alexandria diff --git a/fudo/alias-users.nix b/fudo/alias-users.nix index a0bd333..bbced07 100644 --- a/fudo/alias-users.nix +++ b/fudo/alias-users.nix @@ -15,4 +15,6 @@ in { system = admin-users; asdf = ["mswaffer@gmail.com" "bouncetest@fudo.org"]; + + network-info = ["niten@fudo.org"]; } diff --git a/fudo/system-users.nix b/fudo/system-users.nix index 21830ef..4ac5c76 100644 --- a/fudo/system-users.nix +++ b/fudo/system-users.nix @@ -13,4 +13,9 @@ description = "User Database Reader"; hashed-password = "{SSHA}IVKhrB+wMOCI/CCzbJW8sNDbH67ZTMBv"; }; + + jabber = { + description = "Jabber Server"; + hashed-password = "{SSHA}KlQpe0n+NP0WcJUniHTD+JzUugzLo8Ib"; + }; } diff --git a/fudo/users.nix b/fudo/users.nix index 565f14b..b7c943e 100644 --- a/fudo/users.nix +++ b/fudo/users.nix @@ -422,4 +422,11 @@ common-name = "Kevin"; hashed-password = "{SSHA}1onx6HPMKCJvmLnRf1tiWFJ1D92DEtnl"; }; + + netinfo = { + uid = 10113; + group = "fudo"; + common-name = "Network Info Mailer"; + hashed-password = "{SSHA}UQHfW0IzjIbRU6VV+DraxvZFWt0to3oc"; + }; } diff --git a/hosts/france.nix b/hosts/france.nix index 44722a2..72f8aec 100644 --- a/hosts/france.nix +++ b/hosts/france.nix @@ -30,8 +30,16 @@ in { imports = [ ../hardware-configuration.nix - ../defaults.nix + ./france/jabber.nix + ]; + + environment.systemPackages = with pkgs; [ + docker + lxd + multipath-tools + nix-prefetch-docker + tshark ]; # services.openssh = { @@ -62,14 +70,6 @@ in { ]; }; - environment.systemPackages = with pkgs; [ - docker - lxd - multipath-tools - nix-prefetch-docker - tshark - ]; - fudo.prometheus = { enable = true; hostname = "metrics.fudo.org"; @@ -186,16 +186,9 @@ in { # 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:///" ]; @@ -369,7 +362,7 @@ in { useDHCP = false; # TODO: fix IPv6 - enableIPv6 = false; + enableIPv6 = true; # Create a bridge for VMs to use macvlans = { @@ -487,14 +480,10 @@ in { }; }; - fudo.system = { - disableTransparentHugePages = true; - postHugePageServices = ["redis.service"]; - }; - security.acme.certs = { "archiva.fudo.org".email = config.fudo.common.admin-email; "git.fudo.org".email = config.fudo.common.admin-email; + "mail.fudo.org".email = config.fudo.common.admin-email; }; services = { @@ -525,7 +514,10 @@ in { # Needed to grab a cert for the mail server. "mail.fudo.org" = { enableACME = true; - globalRedirect = "webmail.fudo.org"; + # Stopped relocating all because we need /metrics/... paths to remain unforwarded + locations."/" = { + return = "301 https://webmail.fudo.org$request_uri"; + }; }; }; }; @@ -543,6 +535,7 @@ in { environment = { # Not directly connected to the world anyway SSL_ENABLED = "false"; + PROXY_BASE_URL = "https://archiva.fudo.org/"; }; }; }; @@ -553,7 +546,7 @@ in { fudo.minecraft-server = { enable = true; - package = pkgs.minecraft-server_1_16_1; + package = pkgs.minecraft-server_1_16_2; data-dir = minecraft-data-dir; world-name = "selbyland"; motd = "Welcome to the Selby Minecraft server."; diff --git a/hosts/france/jabber.nix b/hosts/france/jabber.nix new file mode 100644 index 0000000..df4c16b --- /dev/null +++ b/hosts/france/jabber.nix @@ -0,0 +1,222 @@ +{ pkgs, lib, config, ... }: + +with lib; +let + backplane-auth = "/etc/nixos/static/backplane-auth.scm"; + + cert-basedir = "/var/lib/ejabberd/certs"; + + target-certs = ["key" "cert" "chain" "fullchain"]; + + cert-origin = hostname: filename: "/var/lib/acme/${hostname}/${filename}.pem"; + cert-target = hostname: filename: "${cert-basedir}/${hostname}-${filename}.pem"; + + move-server-certs = hostnames: + let + move-server-cert = hostname: + map (filename: '' + ensure_exists ${cert-origin hostname filename} + cp -L ${cert-origin hostname filename} ${cert-target hostname filename} + '') + target-certs; + in pkgs.writeShellScript "move-server-certs" '' + function ensure_exists() { + FILENAME=$1 + if [ ! -e $FILENAME ]; then + echo "file does not exist: $FILENAME" + exit 1 + fi + } + + if [ -d ${cert-basedir} ]; then + mkdir ${cert-basedir} + fi + + ${concatStringsSep "\n" (concatMap move-server-cert hostnames)} + + chown -R ${config.services.ejabberd.user}:${config.services.ejabberd.group} ${cert-basedir} + + exit 0 + ''; + + remove-server-certs = pkgs.writeShellScript "ejabberd-rm-combined-certs" '' + rm ${cert-basedir}/*.pem + ''; + + +in { + config = { + + security.acme.certs."fudo.im".email = "admin@fudo.org"; + security.acme.certs."backplane.fudo.org".email = "admin@fudo.org"; + + systemd.services = { + ejabberd-generate-certs = { + enable = true; + description = "Generate required SSL certs for ejabberd."; + wantedBy = [ "ejabberd.service" ]; + after = [ + "acme-backplane.fudo.org.service" + "acme-fudo.im.service" + ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${move-server-certs ["fudo.im" "backplane.fudo.org"]}"; + RemainAfterExit = true; + ExecStop = remove-server-certs; + StandardOutput = "journal"; + }; + }; + + ejabberd = { + requires = [ "ejabberd-generate-certs.service" ]; + environment = { + FUDO_HOST_PASSWD_FILE = "/srv/jabber/secret/hosts-passwd.scm"; + FUDO_SERVICE_PASSWD_FILE = "/srv/jabber/secret/services-passwd.scm"; + }; + }; + }; + + services = { + nginx = { + virtualHosts = { + "backplane.fudo.org" = { + enableACME = true; + }; + + "fudo.im" = { + enableACME = true; + }; + }; + }; + + ejabberd = { + enable = true; + + configFile = pkgs.writeText "ejabberd-config.yml" (builtins.toJSON { + loglevel = 4; + + access_rules = { + c2s = { allow = "all"; }; + announce = { allow = "admin"; }; + configure = { allow = "admin"; }; + pubsub_createnode = { allow = "local"; }; + }; + + acl = { + admin = { + user = [ + "niten@fudo.org" + ]; + }; + }; + + hosts = [ + "fudo.im" + "backplane.fudo.org" + ]; + + listen = [ + { + port = 5222; + module = "ejabberd_c2s"; + ip = "0.0.0.0"; + starttls = true; + starttls_required = true; + } + ]; + + certfiles = + concatMap (hostname: map (filename: cert-target hostname filename) target-certs) + ["fudo.im" "backplane.fudo.org"]; + + host_config = { + "fudo.im" = { + auth_method = "ldap"; + ldap_servers = ["auth.fudo.org"]; + ldap_port = 389; + ldap_rootdn = "cn=jabber,dc=fudo,dc=org"; + ldap_password = fileContents /srv/jabber/secret/ldap.passwd; + ldap_base = "ou=members,dc=fudo,dc=org"; + ldap_filter = "(objectClass=posixAccount)"; + ldap_uids = { uid = "%u"; }; + + modules = { + mod_adhoc = {}; + mod_announce = {}; + mod_avatar = {}; + mod_blocking = {}; + mod_caps = {}; + mod_carboncopy = {}; + mod_client_state = {}; + mod_configure = {}; + mod_disco = {}; + mod_fail2ban = {}; + mod_last = {}; + mod_offline = { + access_max_user_messages = 5000; + }; + mod_ping = {}; + mod_privacy = {}; + mod_private = {}; + mod_pubsub = { + access_createnode = "pubsub_createnode"; + ignore_pep_from_offline = true; + last_item_cache = false; + plugins = [ + "flat" + "pep" + ]; + }; + mod_roster = {}; + mod_stream_mgmt = {}; + mod_time = {}; + mod_vcard = { + search = false; + }; + mod_vcard_xupdate = {}; + mod_version = {}; + }; + }; + + "backplane.fudo.org" = { + auth_method = "external"; + extauth_program = "${pkgs.guile}/bin/guile -s ${backplane-auth}"; + extauth_pool_size = 3; + auth_use_cache = true; + + modules = { + mod_adhoc = {}; + mod_caps = {}; + mod_carboncopy = {}; + mod_client_state = {}; + mod_configure = {}; + mod_disco = {}; + mod_fail2ban = {}; + mod_last = {}; + mod_offline = { + access_max_user_messages = 5000; + }; + mod_ping = {}; + mod_pubsub = { + access_createnode = "pubsub_createnode"; + ignore_pep_from_offline = true; + last_item_cache = false; + plugins = [ + "flat" + "pep" + ]; + }; + mod_roster = {}; + mod_stream_mgmt = {}; + mod_time = {}; + mod_version = {}; + }; + }; + }; + }); + }; + }; + }; +} diff --git a/packages/archiva.nix b/packages/archiva.nix new file mode 100644 index 0000000..054cc8d --- /dev/null +++ b/packages/archiva.nix @@ -0,0 +1,27 @@ +{ pkgs, fetchurl, ... }: + +let + version = "2.2.5"; + url = "https://mirrors.sonic.net/apache/archiva/${version}/binaries/apache-archiva-${version}-bin.tar.gz"; + sha256 = "01119af2d9950eacbcce0b7f8db5067b166ad26c1e1701bef829105441bb6e29"; + +in pkgs.stdenv.mkDerivation { + name = "archiva-${version}"; + + src = builtins.fetchurl { + url = url; + sha256 = sha256; + }; + + phases = ["installPhase"]; + + buildInputs = with pkgs; [ stdenv procps makeWrapper ]; + + installPhase = '' + mkdir $out + tar -xzf $src + cd apache-archiva-${version} + mv {LICENSE,NOTICE,apps,bin,conf,contexts,lib,logs,temp} $out + makeWrapper $out/bin/archiva $out/bin/archivaWrapped --set PATH ${pkgs.stdenv.lib.makeBinPath [ pkgs.procps ]} + ''; +} diff --git a/packages/local.nix b/packages/local.nix index 7e72555..16637da 100644 --- a/packages/local.nix +++ b/packages/local.nix @@ -35,6 +35,18 @@ }; })); + minecraft-server_1_16_2 = let + version = "1.16.2"; + url = "https://launcher.mojang.com/v1/objects/c5f6fb23c3876461d46ec380421e42b289789530/server.jar"; + sha256 = "0fbghwrj9b2y9lkn2b17id4ghglwvyvcc8065h582ksfz0zys0i9"; + in (pkgs.minecraft-server.overrideAttrs (oldAttrs: rec { + name = "minecraft-server-${version}"; + inherit version; + src = pkgs.fetchurl { + inherit url sha256; + }; + })); + postgresql_11_gssapi = pkgs.postgresql_11.overrideAttrs (oldAttrs: rec { configureFlags = oldAttrs.configureFlags ++ [ "--with-gssapi" ]; buildInputs = oldAttrs.buildInputs ++ [ pkgs.krb5 ]; @@ -54,5 +66,10 @@ stdenv = pkgs.stdenv; fetchgit = pkgs.fetchgit; }; + + fudo-service = import ./fudo-service.nix { + fetchgit = pkgs.fetchgit; + pkgs = pkgs; + }; }; } diff --git a/static/backplane-auth.scm b/static/backplane-auth.scm new file mode 100644 index 0000000..f23ee80 --- /dev/null +++ b/static/backplane-auth.scm @@ -0,0 +1,66 @@ +(use-modules (srfi srfi-1) + (srfi srfi-13) + (ice-9 binary-ports) + (ice-9 textual-ports) + (ice-9 format) + (ice-9 regex) + (rnrs bytevectors)) + +(define *host-passwd-file* (getenv "FUDO_HOST_PASSWD_FILE")) +(when (not *host-passwd-file*) + (format (current-error-port "FUDO_HOST_PASSWD_FILE not set~%")) + (exit 1)) + +(define *service-passwd-file* (getenv "FUDO_SERVICE_PASSWD_FILE")) +(when (not *service-passwd-file*) + (format (current-error-port "FUDO_SERVICE_PASSWD_FILE not set~%")) + (exit 1)) + +(define host-regex "^host-([a-zA-Z][a-zA-Z0-9_-]+)$") +(define service-regex "^service-([a-zA-Z][a-zA-Z0-9_-]+)$") + +(define (make-verifier passwd-file) + (let ((passwds (load passwd-file))) + (lambda (username passwd) + (and (> (string-length passwd) 6) + (equal? (assoc-ref passwds username) passwd))))) + +(define (make-authenticator host-verifier service-verifier) + (lambda (username hostname password) + (cond ((string-match host-regex username) + (host-verifier (match:substring (string-match host-regex username) 1) + password)) + + ((string-match service-regex username) + (service-verifier (match:substring (string-match service-regex username) 1) + password)) + + (else #f)))) + +(define (make-handler handlers) + (lambda (request) + (let ((op (assoc-ref handlers (first request)))) + (if op + (apply op (cdr request)) + #f)))) + +(define (auth-listener handler) + (let ((in (current-input-port)) + (out (current-output-port))) + (while #t + (let ((size (bytevector-u16-ref (get-bytevector-n in 2) 0 (endianness big))) + (response (make-bytevector 4 0))) + (bytevector-u8-set! response 1 #x02) + (if (handler (string-split (get-string-n in size) #\:)) + (begin (bytevector-u8-set! response 3 #x01) + (put-bytevector out response 0 4) + (force-output out)) + (begin (bytevector-u8-set! response 3 #x00) + (put-bytevector out response 0 4) + (force-output out))))))) + +(auth-listener + (make-handler + (list (cons "auth" + (make-authenticator (make-verifier *host-passwd-file*) + (make-verifier *service-passwd-file*))))))