From d429825817ad5881950eae0525c524b04bdab54f Mon Sep 17 00:00:00 2001 From: "root@procul" Date: Thu, 25 Jun 2020 22:38:50 -0500 Subject: [PATCH 1/6] Informis Checkin --- config/fudo/acme-for-hostname.nix | 44 +++--- config/fudo/dns.nix | 218 ++++++++++++++++++++++++++++++ config/fudo/mail.nix | 19 +++ config/fudo/mail/dovecot.nix | 133 +++++++++++------- config/fudo/mail/postfix.nix | 38 +++--- config/local.nix | 1 + defaults.nix | 1 + fudo/profiles/server.nix | 2 + fudo/sites/joes.nix | 27 +--- hosts/procul.nix | 218 +++++++++++++++++++++++++++--- informis/informis.land.nix | 98 ++++++++++++++ informis/users.nix | 14 ++ 12 files changed, 688 insertions(+), 125 deletions(-) create mode 100644 config/fudo/dns.nix create mode 100644 informis/informis.land.nix create mode 100644 informis/users.nix diff --git a/config/fudo/acme-for-hostname.nix b/config/fudo/acme-for-hostname.nix index 4dd5f2e..0451170 100644 --- a/config/fudo/acme-for-hostname.nix +++ b/config/fudo/acme-for-hostname.nix @@ -6,26 +6,28 @@ with lib; let cfg = config.fudo.acme; - wwwRoot = hostname: - pkgs.writeTextFile { - name = "index.html"; + # wwwRoot = hostname: + # pkgs.writeTextFile { + # name = "index.html"; - text = '' - - - ${hostname} - - -

${hostname} - - - ''; - destination = "/www"; - }; + # text = '' + # + # + # ${hostname} + # + # + #

${hostname} + # + # + # ''; + # destination = "/www"; + # }; in { options.fudo.acme = { + enable = mkEnableOption "Fetch ACME certs for supplied local hostnames."; + hostnames = mkOption { type = with types; listOf str; description = "A list of hostnames mapping to this host, for which to acquire SSL certificates."; @@ -35,9 +37,15 @@ in { "alt.hostname.com" ]; }; + + admin-address = mkOption { + type = types.str; + description = "The admin address in charge of these addresses."; + default = "admin@fudo.org"; + }; }; - config = { + config = mkIf cfg.enable { services.nginx = { enable = true; @@ -49,13 +57,13 @@ in { { enableACME = true; forceSSL = true; - root = (wwwRoot hostname) + ("/" + "www"); + # root = (wwwRoot hostname) + ("/" + "www"); }) cfg.hostnames); }; security.acme.certs = listToAttrs - (map (hostname: nameValuePair hostname { email = "admin@fudo.org"; }) + (map (hostname: nameValuePair hostname { email = cfg.admin-address; }) cfg.hostnames); }; } diff --git a/config/fudo/dns.nix b/config/fudo/dns.nix new file mode 100644 index 0000000..9de4805 --- /dev/null +++ b/config/fudo/dns.nix @@ -0,0 +1,218 @@ +{ lib, config, pkgs, ... }: + +with lib; + +let + cfg = config.fudo.dns; + + ip = import ../../lib/ip.nix { lib = lib; }; + + join-lines = concatStringsSep "\n"; + + hostOpts = { host, ...}: { + options = { + ip-addresses = mkOption { + type = with types; listOf str; + description = '' + A list of IPv4 addresses assigned to this host. + ''; + default = []; + }; + + ipv6-addresses = mkOption { + type = with types; listOf str; + description = '' + A list of IPv6 addresses assigned to this host. + ''; + default = []; + }; + + ssh-fingerprints = mkOption { + type = with types; listOf str; + description = '' + A list of DNS SSHFP records for this host. + ''; + }; + }; + }; + + srvRecordOpts = with types; { + options = { + weight = mkOption { + type = int; + description = "Weight relative to other records."; + default = 1; + }; + + priority = mkOption { + type = int; + description = "Priority to give this record."; + default = 0; + }; + + port = mkOption { + type = port; + description = "Port to use while connecting to this service."; + }; + + host = mkOption { + type = str; + description = "Host that provides this service."; + example = "my-host.my-domain.com"; + }; + }; + }; + + domainOpts = { domain, ... }: with types; { + options = { + hosts = mkOption { + type = loaOf (submodule hostOpts); + default = {}; + description = "A map of hostname to { host_attributes }."; + }; + + dnssec = mkEnableOption "Enable DNSSEC security for this zone."; + + mx = mkOption { + type = listOf str; + description = "A list of mail servers serving this domain."; + default = []; + }; + + srv-records = mkOption { + type = attrsOf (attrsOf (listOf (submodule srvRecordOpts))); + description = "Map of traffic type to srv records."; + default = {}; + example = { + tcp = { + kerberos = { + port = 88; + host = "auth-host.my-domain.com"; + }; + }; + }; + }; + + aliases = mkOption { + type = loaOf str; + default = {}; + description = "A mapping of host-alias => hostnames to add to DNS."; + example = { + "music" = "host.dom.com."; + "mail" = "hostname"; + }; + }; + + extra-dns-records = mkOption { + type = listOf str; + description = "Records to be inserted verbatim into the DNS zone."; + example = ["some-host IN CNAME base-host"]; + default = []; + }; + + dmarc-report-address = mkOption { + type = nullOr str; + description = "The email to use to recieve DMARC reports, if any."; + example = "admin-user@domain.com"; + default = null; + }; + + default-host = mkOption { + type = nullOr str; + description = "IP of the host which will act as the default server for this domain, if any."; + default = null; + }; + }; + }; + + hostARecords = host: data: + join-lines ((map (ip: "${host} IN A ${ip}") data.ip-addresses) ++ + (map (ip: "${host} IN AAAA ${ip}") data.ipv6-addresses)); + + makeSrvRecords = protocol: type: records: + join-lines (map (record: "_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${toString record.host}.") + records); + + makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types); + + cnameRecord = alias: host: "${alias} IN CNAME ${host}"; + + hostSshFpRecords = host: data: join-lines (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints); + + mxRecords = mxs: + concatStringsSep "\n" + (map (mx: "@ IN MX 10 ${mx}.") mxs); + + dmarcRecord = dmarc-email: + optionalString (dmarc-email != null) + ''_dmarc IN TXT "v=DMARC1;p=quarantine;sp=quarantine;rua=mailto:${dmarc-email};"''; + + nsRecords = ns-hosts: + join-lines ((mapAttrsToList (host: _: "@ IN NS ${host}.") ns-hosts) ++ + (mapAttrsToList (host: ip: "${host} IN A ${ip}") ns-hosts)); + +in { + + options.fudo.dns = with types; { + enable = mkEnableOption "Enable master DNS services."; + + # FIXME: This should allow for AAAA addresses too... + dns-hosts = mkOption { + type = loaOf str; + description = "Map of domain nameserver FQDNs to IP."; + example = { "ns1.domain.com" = "1.1.1.1"; }; + }; + + domains = mkOption { + type = loaOf (submodule domainOpts); + default = {}; + description = "A map of domain to domain options."; + }; + + listen-ips = mkOption { + type = listOf str; + description = "A list of IPs on which to listen for DNS queries."; + example = ["1.2.3.4"]; + }; + }; + + config = mkIf cfg.enable { + services.nsd = { + enable = true; + identity = "procul.informis.land"; + interfaces = cfg.listen-ips; + zones = mapAttrs' (dom: dom-cfg: + nameValuePair "${dom}." { + dnssec = dom-cfg.dnssec; + + data = '' + $ORIGIN ${dom}. + $TTL 12h + + @ IN SOA ns1.${dom}. hostmaster.${dom}. ( + ${toString builtins.currentTime} + 5m + 2m + 6w + 5m) + + ${optionalString (dom-cfg.default-host != null) "@ IN A ${dom-cfg.default-host}"} + + ${mxRecords dom-cfg.mx} + + $TTL 6h + + ${nsRecords cfg.dns-hosts} + + ${dmarcRecord dom-cfg.dmarc-report-address} + + ${join-lines (mapAttrsToList makeSrvProtocolRecords dom-cfg.srv-records)} + ${join-lines (mapAttrsToList hostARecords dom-cfg.hosts)} + ${join-lines (mapAttrsToList hostSshFpRecords dom-cfg.hosts)} + ${join-lines (mapAttrsToList cnameRecord dom-cfg.aliases)} + ${join-lines dom-cfg.extra-dns-records} + ''; + }) cfg.domains; + }; + }; +} diff --git a/config/fudo/mail.nix b/config/fudo/mail.nix index 7b664a8..ba350fd 100644 --- a/config/fudo/mail.nix +++ b/config/fudo/mail.nix @@ -104,6 +104,7 @@ in { user-aliases = mkOption { type = with types; loaOf(listOf str); description = "A map of real user to list of aliases."; + default = {}; example = { someuser = ["alias0" "alias1"]; }; @@ -167,4 +168,22 @@ in { ./mail/rspamd.nix ./mail/clamav.nix ]; + + config = mkIf cfg.enable { + users = { + users = { + mailuser = { + isSystemUser = true; + uid = cfg.mail-user-id; + group = "mailgroup"; + }; + }; + + groups = { + mailgroup = { + members = ["mailuser"]; + }; + }; + }; + }; } diff --git a/config/fudo/mail/dovecot.nix b/config/fudo/mail/dovecot.nix index 6c5d4fd..9d8f1cf 100644 --- a/config/fudo/mail/dovecot.nix +++ b/config/fudo/mail/dovecot.nix @@ -23,61 +23,86 @@ let ''; }; - ldap-conf = filename: uris: - pkgs.writeText filename '' - uris = ${concatStringsSep " " uris} + ldap-conf = filename: config: + let + ssl-config = if config.ca == null then '' + tls = no + tls_require_cert = try + '' else '' + tls_ca_cert_file = ${config.ca} + tls = yes + tls_require_cert = try + ''; + + in + pkgs.writeText filename '' + uris = ${concatStringsSep " " config.server-urls} ldap_version = 3 - dn = ${cfg.dovecot.ldap-reader-dn} - dnpass = ${cfg.dovecot.ldap-reader-passwd} + dn = ${config.reader-dn} + dnpass = ${config.reader-passwd} auth_bind = yes auth_bind_userdn = uid=%u,ou=members,dc=fudo,dc=org base = dc=fudo,dc=org - # tls_ca_cert_file = ${cfg.dovecot.ldap-ca} - # FIXME: turn back on when certs work - tls = no - tls_require_cert = try + ${ssl-config} ''; - dovecot-user = config.services.dovecot2.user; + ldap-passwd-entry = ldap-config: '' + passdb { + driver = ldap + args = ${ldap-conf "ldap-passdb.conf" ldap-config} + } + ''; -in { - options.fudo.mail-server.dovecot = { - ssl-private-key = mkOption { - type = types.str; - description = "Location of the server SSL private key."; - }; - - ssl-certificate = mkOption { - type = types.str; - description = "Location of the server SSL certificate."; - }; - - ldap-ca = mkOption { - type = types.str; + ldapOpts = with types; { + ca = mkOption { + type = str; description = "The path to the CA cert used to sign the LDAP server certificate."; }; - ldap-urls = mkOption { - type = with types; listOf str; - description = "The urls of LDAP servers."; + server-urls = mkOption { + type = listOf str; + description = "A list of LDAP server URLs used for authentication."; }; - ldap-reader-dn = mkOption { - type = types.str; + reader-dn = mkOption { + type = str; description = '' DN to use for reading user information. Needs access to homeDirectory, uidNumber, gidNumber, and uid, but not password attributes. ''; }; - ldap-reader-passwd = mkOption { - type = types.str; + reader-pw = mkOption { + type = str; description = '' Password for the user specified in ldap-reader-dn. ''; }; }; + dovecot-user = config.services.dovecot2.user; + +in { + options.fudo.mail-server.dovecot = with types; { + ssl-private-key = mkOption { + type = str; + description = "Location of the server SSL private key."; + }; + + ssl-certificate = mkOption { + type = str; + description = "Location of the server SSL certificate."; + }; + + ldap = mkOption { + type = nullOr (submodule ldapOpts); + default = null; + description = '' + LDAP auth server configuration. If omitted, the server will use local authentication. + ''; + }; + }; + config = mkIf cfg.enable { services.prometheus.exporters.dovecot = mkIf cfg.monitoring { @@ -93,8 +118,7 @@ in { enableImap = true; enableLmtp = true; enablePop3 = true; - enablePAM = false; - + enablePAM = cfg.dovecot.ldap == null; createMailUser = true; @@ -124,14 +148,16 @@ in { extraConfig = '' #Extra Config - # The prometheus exporter still expects an older style of metrics - mail_plugins = $mail_plugins old_stats - service old-stats { - unix_listener old-stats { - user = dovecot-exporter - group = dovecot-exporter + ${optionalString cfg.monitoring '' + # The prometheus exporter still expects an older style of metrics + mail_plugins = $mail_plugins old_stats + service old-stats { + unix_listener old-stats { + user = dovecot-exporter + group = dovecot-exporter + } } - } + ''} ${lib.optionalString cfg.debug '' mail_debug = yes @@ -170,15 +196,15 @@ in { } # Drop privs, since all mail is owned by one user - user = ${cfg.mail-user} - group = ${cfg.mail-group} + # user = ${cfg.mail-user} + # group = ${cfg.mail-group} + user = root } auth_mechanisms = login plain - passdb { - driver = ldap - args = ${ldap-conf "ldap-passdb.conf" cfg.dovecot.ldap-urls} - } + + ${optionalString (cfg.dovecot.ldap != null) + (ldap-conf cfg.dovecot.ldap)} userdb { driver = static args = uid=${toString cfg.mail-user-id} home=${cfg.mail-directory}/%u @@ -189,8 +215,18 @@ in { unix_listener auth { mode = 0660 user = "${config.services.postfix.user}" - group = ${config.services.postfix.group} + group = ${cfg.mail-group} } + + unix_listener auth-userdb { + mode = 0660 + user = "${config.services.postfix.user}" + group = ${cfg.mail-group} + } + } + + service auth-worker { + user = root } namespace inbox { @@ -236,7 +272,8 @@ in { done chown -R '${dovecot-user}:${cfg.mail-group}' '${state-directory}/imap_sieve' - chown ${cfg.mail-user}:${cfg.mail-group} ${cfg.mail-directory} + chown '${cfg.mail-user}:${cfg.mail-group}' ${cfg.mail-directory} + chmod g+w ${cfg.mail-directory} ''; }; } diff --git a/config/fudo/mail/postfix.nix b/config/fudo/mail/postfix.nix index 776c584..d05bf6d 100644 --- a/config/fudo/mail/postfix.nix +++ b/config/fudo/mail/postfix.nix @@ -6,6 +6,14 @@ let cfg = config.fudo.mail-server; + # The final newline is important + write-entries = filename: entries: + let + entries-string = (concatStringsSep "\n" entries); + in builtins.toFile filename '' + ${entries-string} + ''; + make-user-aliases = entries: concatStringsSep "\n" (mapAttrsToList (user: aliases: @@ -39,25 +47,22 @@ let /^User-Agent:/ IGNORE /^X-Enigmail:/ IGNORE ''); - blacklist-postfix-entry = sender: "${sender} REJECT"; - blacklist-postfix-file = entries: - concatStringsSep "\n" (map blacklist-postfix-entry entries); - sender-blacklist-file = builtins.toFile "reject_senders" - (blacklist-postfix-file cfg.sender-blacklist); - recipient-blacklist-file = builtins.toFile "reject_recipients" - (blacklist-postfix-file cfg.recipient-blacklist); + blacklist-postfix-file = filename: entries: + write-entries filename entries; + sender-blacklist-file = blacklist-postfix-file "reject_senders" + (map blacklist-postfix-entry cfg.sender-blacklist); + recipient-blacklist-file = blacklist-postfix-file "reject_recipients" + (map blacklist-postfix-entry cfg.recipient-blacklist); # A list of domains for which we accept mail - virtual-mailbox-map-file = builtins.toFile "virtual_mailbox_map" - (concatStringsSep "\n" - (map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain]))); + virtual-mailbox-map-file = write-entries "virtual_mailbox_map" + (map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain])); sender-login-map-file = let escapeDot = (str: replaceStrings ["."] ["\\."] str); - in builtins.toFile "sender_login_maps" - (concatStringsSep "\n" - (map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain]))); + in write-entries "sender_login_maps" + (map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain])); mapped-file = name: "hash:/var/lib/postfix/conf/${name}"; @@ -106,9 +111,8 @@ in { origin = cfg.domain; hostname = cfg.hostname; destination = ["localhost" "localhost.localdomain"]; - # destination = ["localhost" "localhost.localdomain"] ++ - # (map (domain: "localhost.${domain}") cfg.local-domains) ++ - # cfg.local-domains; + # destination = ["localhost" "localhost.localdomain" cfg.hostname] ++ + # cfg.local-domains;; enableHeaderChecks = true; enableSmtp = true; @@ -133,7 +137,7 @@ in { sslKey = cfg.postfix.ssl-private-key; config = { - virtual_mailbox_domains = builtins.toFile "domain-list" (concatStringsSep "\n" cfg.local-domains); + virtual_mailbox_domains = cfg.local-domains ++ [cfg.domain]; # virtual_mailbox_base = "${cfg.mail-directory}/"; virtual_mailbox_maps = mapped-file "virtual_mailbox_map"; diff --git a/config/local.nix b/config/local.nix index 0cc9309..31d794c 100644 --- a/config/local.nix +++ b/config/local.nix @@ -7,6 +7,7 @@ with lib; ./fudo/authentication.nix ./fudo/chat.nix ./fudo/common.nix + ./fudo/dns.nix ./fudo/git.nix ./fudo/grafana.nix ./fudo/kdc.nix diff --git a/defaults.nix b/defaults.nix index 030d694..5c4242c 100644 --- a/defaults.nix +++ b/defaults.nix @@ -54,6 +54,7 @@ lshw mkpasswd ncurses5 + nix-index nmap oidentd openldap diff --git a/fudo/profiles/server.nix b/fudo/profiles/server.nix index 1011659..7e1b7c3 100644 --- a/fudo/profiles/server.nix +++ b/fudo/profiles/server.nix @@ -51,6 +51,8 @@ in { config = mkIf (config.fudo.common.profile == "server") { environment = { systemPackages = with pkgs; [ + ldns + ldns.examples test-config reboot-if-necessary ]; diff --git a/fudo/sites/joes.nix b/fudo/sites/joes.nix index ad2d576..8f541ed 100644 --- a/fudo/sites/joes.nix +++ b/fudo/sites/joes.nix @@ -2,12 +2,7 @@ with lib; let - admin = "admin@fudo.org"; - - nameservers = [ - "1.1.1.1" - "2606:4700:4700::1111" - ]; + admin = "admin@informis.land"; hostname = config.networking.hostName; @@ -22,31 +17,23 @@ in { }; networking = { - domain = "fudo.org"; - search = ["fudo.org"]; + domain = "informis.land"; + search = ["informis.land" "fudo.org"]; firewall.enable = false; - nameservers = nameservers; defaultGateway = gateway; # defaultGateway6 = gateway6; }; fudo.node-exporter = { - enable = true; + enable = false; hostname = hostname; }; - security.acme.certs.${hostname} = { - email = "admin@fudo.org"; - # plugins = [ - # "fullchain.pem" - # "full.pem" - # "key.pem" - # "chain.pem" - # "cert.pem" - # ]; + security.acme.certs."${hostname}.informis.land" = { + email = "admin@informis.land"; }; - + services.nginx = { enable = true; recommendedGzipSettings = true; diff --git a/hosts/procul.nix b/hosts/procul.nix index ef15a4f..5237977 100644 --- a/hosts/procul.nix +++ b/hosts/procul.nix @@ -3,8 +3,10 @@ with lib; let hostname = "procul"; + domain = "informis.land"; mail-hostname = hostname; host_ipv4 = "172.86.179.18"; + host-fqdn = "${hostname}.${domain}"; all-hostnames = []; acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem"; @@ -25,37 +27,20 @@ in { ../hardware-configuration.nix ../defaults.nix + + ../informis/users.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 = "joes"; - - local-networks = [ - "172.86.179.18/29" - "208.81.1.128/28" - "208.81.3.112/28" - "172.17.0.0/16" - "127.0.0.0/8" - ]; - }; - environment.systemPackages = with pkgs; [ multipath-tools ]; - # Not all users need access to procul; don't allow LDAP-user access. - fudo.authentication.enable = false; - - # TODO: not used yet - fudo.acme.hostnames = all-hostnames; - networking = { hostName = hostname; + # provided by secure-dns-proxy + nameservers = [ "127.0.0.1" ]; + dhcpcd.enable = false; useDHCP = false; @@ -86,4 +71,193 @@ in { }; hardware.bluetooth.enable = false; + + users = { + users = { + gituser = { + isSystemUser = true; + group = "nogroup"; + }; + }; + }; + + 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 = "joes"; + + domain = domain; + + admin-email = "admin@${domain}"; + + local-networks = [ + "172.86.179.16/29" + "208.81.1.128/28" + "208.81.3.112/28" + "172.17.0.0/16" + "127.0.0.0/8" + ]; + }; + + # Not all users need access to procul; don't allow LDAP-user access. + authentication.enable = false; + + auth.kdc = { + enable = true; + database-path = "/var/heimdal/heimdal"; + realm = "INFORMIS.LAND"; + mkey-file = "/srv/heimdal/secure/m-key"; + acl-file = "/etc/heimdal/kdc.acl"; + bind-addresses = [ + host_ipv4 + "127.0.0.1" + "127.0.1.1" + ]; + }; + + secure-dns-proxy = { + enable = true; + upstream-dns = [ "https://cloudflare-dns.com/dns-query" ]; + bootstrap-dns = "1.1.1.1"; + listen-ips = [ "127.0.0.1" ]; + port = 53; + }; + + dns = { + enable = true; + + dns-hosts = { + "ns1.informis.land" = "172.86.179.18"; + "ns2.informis.land" = "172.86.179.18"; + }; + + listen-ips = [host_ipv4]; + + domains = { + "informis.land" = import ../informis/informis.land.nix { + inherit host_ipv4 config; + }; + }; + }; + + mail-server = { + enable = true; + debug = true; + + domain = domain; + hostname = "${host-fqdn}"; + monitoring = false; + mail-user = "mailuser"; + mail-user-id = 525; + mail-group = "mailgroup"; + clamav.enable = true; + dkim.signing = true; + + dovecot = { + ssl-certificate = acme-certificate "imap.${domain}"; + ssl-private-key = acme-private-key "imap.${domain}"; + }; + + postfix = { + ssl-certificate = acme-certificate "smtp.${domain}"; + ssl-private-key = acme-private-key "smtp.${domain}"; + }; + + # This should NOT include the primary domain + local-domains = [ + host-fqdn + "smtp.${domain}" + ]; + + mail-directory = "/srv/mailserver/mail"; + state-directory = "/srv/mailserver/state"; + + trusted-networks = [ + "172.86.179.16/29" + "127.0.0.0/16" + ]; + + alias-users = { + root = ["niten"]; + postmaster = ["niten"]; + hostmaster = ["niten"]; + webmaster = ["niten"]; + system = ["niten"]; + admin = ["niten"]; + dmarc-report = ["niten"]; + }; + }; + + postgresql = { + enable = true; + ssl-certificate = (acme-certificate host-fqdn); + ssl-private-key = (acme-private-key host-fqdn); + keytab = "/srv/postgres/secure/postgres.keytab"; + + local-networks = [ + "172.86.179.16/29" + "127.0.0.0/16" + ]; + + users = { + gituser = { + password = fileContents "/srv/git/secure/db.passwd"; + databases = { + git = "ALL PRIVILEGES"; + }; + }; + }; + + databases = { + git = ["niten"]; + }; + }; + + git = { + enable = true; + hostname = "git.informis.land"; + site-name = "informis git"; + user = "gituser"; + repository-dir = /srv/git/repo; + state-dir = /srv/git/state; + database = { + user = "gituser"; + password-file = /srv/git/secure/db.passwd; + hostname = "127.0.0.1"; + name = "git"; + }; + }; + + acme = { + enable = true; + + admin-address = "admin@${domain}"; + + hostnames = [ + "imap.informis.land" + "smtp.informis.land" + ]; + }; + }; + + security.acme.certs.${host-fqdn}.email = "admin@${domain}"; + + services.nginx = { + enable = true; + + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + + virtualHosts = { + "${host-fqdn}" = { + enableACME = true; + forceSSL = true; + }; + }; + }; } diff --git a/informis/informis.land.nix b/informis/informis.land.nix new file mode 100644 index 0000000..acce31d --- /dev/null +++ b/informis/informis.land.nix @@ -0,0 +1,98 @@ +{ host_ipv4, config }: + +{ + dnssec = true; + + mx = ["smtp.informis.land"]; + + hosts = { + procul = { + ip-addresses = [ "172.86.179.18" ]; + ssh-fingerprints = [ + "4 1 2a8e086d3589ce50b58c55bc35638af8da23988e" + "4 2 55a9f7c0addf08bb24c62ced954574db6e95eff38ee56d6a2cff312d20eb910e" + "1 1 d089902f60751b3d35b5329bf7b906df254d5fa7" + "1 2 8deebf42bbc40881a327f561bffd5d7bd328a4fc94d4e4ce8c502a9c6cbdfb92" + ]; + }; + }; + + default-host = "172.86.179.18"; + + srv-records = { + tcp = { + domain = [{ + host = "ns1.informis.land"; + port = 53; + }]; + ssh = [{ + host = "procul.informis.land"; + port = 22; + }]; + submission = [{ + host = "procul.informis.land"; + port = 587; + }]; + kerberos = [{ + host = "procul.informis.land"; + port = 88; + }]; + kerberos-adm = [{ + host = "procul.informis.land"; + port = 749; + }]; + imaps = [{ + host = "procul.informis.land"; + port = 993; + priority = 0; + }]; + pop3s = [{ + host = "procul.informis.land"; + port = 995; + priority = 10; + }]; + http = [{ + host = "procul.informis.land"; + port = 80; + }]; + https = [{ + host = "procul.informis.land"; + port = 443; + }]; + }; + + udp = { + domain = [{ + host = "ns1.informis.land"; + port = 53; + }]; + kerberos = [{ + host = "procul.informis.land"; + port = 88; + }]; + kerberos-master = [{ + host = "procul.informis.land"; + port = 88; + }]; + kpasswd = [{ + host = "procul.informis.land"; + port = 464; + }]; + }; + }; + + aliases = { + smtp = "procul.informis.land."; + imap = "procul.informis.land."; + gemini = "procul.informis.land."; + git = "procul.informis.land."; + }; + + extra-dns-records = [ + ''_kerberos IN TXT "INFORMIS.LAND"'' + ''@ IN TXT "v=spf1 mx ip4:${host_ipv4}/29 -all"'' + ''@ IN SPF "v=spf1 mx ip4:${host_ipv4}/29 -all"'' + ]; + + dmarc-report-address = "dmarc-report@informis.land"; +} diff --git a/informis/users.nix b/informis/users.nix new file mode 100644 index 0000000..b858c6e --- /dev/null +++ b/informis/users.nix @@ -0,0 +1,14 @@ +{ config, ... }: + +{ + config = { + users.users = { + viator = { + isNormalUser = true; + description = "Viator"; + createHome = true; + hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/"; + }; + }; + }; +} From 1998532ff7c6c628933734c71aa97889e0af7f4a Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Jul 2020 14:02:12 -0700 Subject: [PATCH 2/6] Support yubikey gpg keys --- config/fudo/slynk.nix | 32 +++++++--- defaults.nix | 20 +++++++ static/niten@fudo.org.pubkey | 109 +++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 static/niten@fudo.org.pubkey diff --git a/config/fudo/slynk.nix b/config/fudo/slynk.nix index 008e098..e8033e2 100644 --- a/config/fudo/slynk.nix +++ b/config/fudo/slynk.nix @@ -4,9 +4,15 @@ with lib; let cfg = config.fudo.slynk; - initScript = port: pkgs.writeText "slynk.lisp" '' + initScript = port: load-paths: let + load-path-string = + concatStringsSep " " (map (path: "\"${path}\"") load-paths); + in pkgs.writeText "slynk.lisp" '' (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname))) (ql:quickload :slynk) + (setf asdf:*central-registry* + (append asdf:*central-registry* + (list ${load-path-string}))) (slynk:create-server :port ${toString port} :dont-close t) (dolist (var '("LD_LIBRARY_PATH")) (format t "~S: ~S~%" var (sb-unix::posix-getenv var))) @@ -14,6 +20,18 @@ let (loop (sleep 60)) ''; + lisp-libs = with pkgs.lispPackages; [ + alexandria + asdf-package-system + asdf-system-connections + cl_plus_ssl + cl-ppcre + quicklisp + quri + uiop + usocket + ]; + in { options.fudo.slynk = { enable = mkEnableOption "Enable Slynk emacs common lisp server."; @@ -29,24 +47,24 @@ in { systemd.user.services.slynk = { description = "Slynk Common Lisp server."; - serviceConfig = { + serviceConfig = let + load-paths = (map (pkg: "${pkg}/lib/common-lisp/") lisp-libs); + in { ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init"; - ExecStart = "${pkgs.sbcl-with-libs}/bin/sbcl --load ${initScript cfg.port}"; + ExecStart = "${pkgs.sbcl-with-libs}/bin/sbcl --load ${initScript cfg.port load-paths}"; Restart = "on-failure"; PIDFile = "/run/slynk.$USERNAME.pid"; }; path = with pkgs; [ + gcc glibc # for getent file ]; environment = { - LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib:${pkgs.libuv.out}/lib"; + LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib"; }; - - ## Starts on login. But what about ports? - # wantedBy = [ "default.target" ]; }; }; } diff --git a/defaults.nix b/defaults.nix index 7d2acd1..bad3258 100644 --- a/defaults.nix +++ b/defaults.nix @@ -31,6 +31,7 @@ curl dpkg emacs + enca fail2ban file fortune @@ -81,6 +82,7 @@ vim wget yubikey-manager + yubikey-personalization ]; system.stateVersion = "19.09"; @@ -103,6 +105,8 @@ mosh.enable = true; ssh = { + startAgent = false; + extraConfig = '' GSSAPIAuthentication yes GSSAPIDelegateCredentials yes @@ -136,8 +140,21 @@ GSSAPICleanupCredentials yes ''; }; + + pcscd = { + enable = true; + }; + + udev.packages = with pkgs; [ + yubikey-personalization + ]; }; + environment.shellInit = '' + gpg-connect-agent /bye + export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) + ''; + security.pam = { enableSSHAgentAuth = true; # TODO: add yubico? @@ -173,6 +190,9 @@ group = "users"; home = "/home/niten"; hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/"; + openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDoWkjyeIfgwm0b78weToVYOQSD0RQ0qbNzpsN5NokbIFv2/980kLtnYrQEgIJ/JwMLlT3uJYacbCT5/a6Fb8oLxNpj0AF1EKaWZ3Rrlg72Sq+9SEwJwWWmZizX83sovMwUBMaUp6jWLhAhPpzBW5pfc5YWoc89wxGbELSwzgt5EgHbSJgvDnaHSp3fVaY01wfDXbL/oO160iNe7wv2HLMZu/FkWBkIjz6HmoGJJzYM89bUpHbyYG28lmCHB/8UPog5/BsjOn3/qupgf4zh6mMdMsXLvbR2jVwVjxcEMj9N5nCvc+Y3oi7Mij6VNrWbhkaAJMEzeMhWYrF3/pFQxUqG37aK3d0gw9kp5tMDLIlAPX4y1lfA87pIzoa0+Alql0CJQA1IJvp9SFG7lBmSthWQLmZvwwfoGg/ZjF6rOgsVoZ8TizpQnydWJDr6NboU9LL9Oa64OM5Rs0AU3cR2UbOF4QIcWFJ/7oDe3dOnfZ8QYqx9eXJyxoAUpDanaaTHYBiAKkeOBwQU+MVLKCcONKw9FZclf/1TpDB5b3/JeUFANjHQTv0UXA4YYU7iCx6H7XB4qwwtU9O19CGQYYfCfULX12/fRpYJw6VJaQWyyU4Bn5dk/dcB2nGI36jwbLMfhbUTIApujioAnd/GQIMakHEZ1+syPhMx9BxMkZb99B0A1Q== openpgp:0x4EC95B64" + ]; }; reaper = { isNormalUser = true; diff --git a/static/niten@fudo.org.pubkey b/static/niten@fudo.org.pubkey new file mode 100644 index 0000000..08d57bb --- /dev/null +++ b/static/niten@fudo.org.pubkey @@ -0,0 +1,109 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +qCVCWa+H/Pev226LSn2PVKK5AlBbs6uSNx/Phg== +=8Fyj +-----END PGP PUBLIC KEY BLOCK----- From 8af542c16b62df9b6ac14d47e1a451a84fcd3134 Mon Sep 17 00:00:00 2001 From: "root@procul" Date: Thu, 16 Jul 2020 15:46:14 -0500 Subject: [PATCH 3/6] Lots of commits, mostly related to cl-gemini --- config/fudo/slynk.nix | 12 +-- config/informis/cl-gemini.nix | 159 ++++++++++++++++++++++++++++++++++ config/local.nix | 2 + defaults.nix | 4 +- fudo/sites/joes.nix | 23 +++-- fudo/sites/seattle.nix | 2 + hosts/procul.nix | 12 +++ packages/cl-gemini.nix | 24 +++++ packages/local.nix | 11 +-- 9 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 config/informis/cl-gemini.nix create mode 100644 packages/cl-gemini.nix diff --git a/config/fudo/slynk.nix b/config/fudo/slynk.nix index e2ad7b8..cbfdf14 100644 --- a/config/fudo/slynk.nix +++ b/config/fudo/slynk.nix @@ -14,6 +14,12 @@ let (loop (sleep 60)) ''; + sbcl-with-ssl = pkgs.sbcl.overrideAttrs (oldAttrs: rec { + extraLibs = with pkgs; [ + openssl_1_1.dev + ]; + }); + in { options.fudo.slynk = { enable = mkEnableOption "Enable Slynk emacs common lisp server."; @@ -30,9 +36,8 @@ in { description = "Slynk Common Lisp server."; serviceConfig = { - # Type = "simple"; ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init"; - ExecStart = "${pkgs.sbcl-with-libs}/bin/sbcl --load ${initScript cfg.port}"; + ExecStart = "${pkgs.sbcl-with-ssl}/bin/sbcl --load ${initScript cfg.port}"; Restart = "on-failure"; PIDFile = "/run/slynk.$USERNAME.pid"; }; @@ -40,9 +45,6 @@ in { environment = { LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib:${pkgs.libuv.out}/lib"; }; - - ## Starts on login. But what about ports? - # wantedBy = [ "default.target" ]; }; }; } diff --git a/config/informis/cl-gemini.nix b/config/informis/cl-gemini.nix new file mode 100644 index 0000000..ccab8bc --- /dev/null +++ b/config/informis/cl-gemini.nix @@ -0,0 +1,159 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.informis.cl-gemini; + + lisp-libs = with pkgs.lispPackages; [ + alexandria + asdf-package-system + asdf-system-connections + cl_plus_ssl + cl-ppcre + quicklisp + quri + uiop + usocket + ]; + + launchServer = load-paths: ip: port: root: public-dir: key: cert: slynk-port: + let + load-path-string = + concatStringsSep " " (map (path: "\"${path}\"") load-paths); + in pkgs.writeText "launch-server.lisp" '' + (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname))) + (setf asdf:*central-registry* + (append asdf:*central-registry* + (list ${load-path-string}))) + (ql:quickload :slynk) + (ql:quickload :cl-gemini) + ${optionalString (slynk-port != null) "(slynk:create-server :port ${toString slynk-port} :dont-close t)"} + (cl-gemini:start-gemini-server "${ip}" "${key}" "${cert}" + :port ${toString port} + :document-root "${root}" + :file-cmd "${pkgs.file}/bin/file" + :log-stream *standard-output* + :threaded t + :separate-thread t) + (loop (sleep 60)) + ''; + + sbcl-with-ssl = pkgs.sbcl.overrideAttrs (oldAttrs: rec { + extraLibs = with pkgs; [ + openssl_1_1.dev + ]; + }); + +in { + options.informis.cl-gemini = with types; { + enable = mkEnableOption "Enable the cl-gemini server."; + + port = mkOption { + type = port; + description = "Port on which to serve Gemini traffic."; + default = 1965; + }; + + server-ip = mkOption { + type = str; + description = "IP on which to serve Gemini traffic."; + example = "1.2.3.4"; + }; + + document-root = mkOption { + type = path; + description = "Root at which to look for gemini files."; + example = /my/gemini/root; + }; + + user-public = mkOption { + type = str; + description = "Subdirectory of user homes to check for gemini files."; + default = "gemini-public"; + }; + + ssl-private-key = mkOption { + type = path; + description = "Path to the pem-encoded server private key."; + example = /path/to/secret/key.pem; + }; + + ssl-certificate = mkOption { + type = path; + description = "Path to the pem-encoded server public certificate."; + example = /path/to/cert.pem; + }; + + slynk-port = mkOption { + type = nullOr port; + description = "Port on which to open a slynk server, if any."; + default = null; + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = with pkgs; [ + cl-gemini + ]; + + users.users = { + cl-gemini = { + isSystemUser = true; + group = "nogroup"; + createHome = true; + home = "/var/lib/cl-gemini"; + }; + }; + + environment.etc = { + "cl-gemini/key.pem" = { + mode = "0400"; + user = "cl-gemini"; + source = cfg.ssl-private-key; + }; + + "cl-gemini/cert.pem" = { + mode = "0444"; + user = "cl-gemini"; + source = cfg.ssl-certificate; + }; + }; + + systemd.services.cl-gemini = { + description = "cl-gemini Gemini server (https://gemini.circumlunar.space/)"; + + serviceConfig = let + load-paths = (map (pkg: "${pkg}/lib/common-lisp//") + (lisp-libs ++ [pkgs.cl-gemini])); + in { + ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init"; + ExecStart = "${sbcl-with-ssl}/bin/sbcl --load ${ + launchServer + load-paths + cfg.server-ip + cfg.port + cfg.document-root + cfg.user-public + "/etc/cl-gemini/key.pem" + "/etc/cl-gemini/cert.pem" + cfg.slynk-port + }"; + Restart = "on-failure"; + PIDFile = "/run/cl-gemini.$USERNAME.uid"; + User = "cl-gemini"; + }; + + environment = { + LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib"; + }; + + path = with pkgs; [ + file + getent + ]; + + wantedBy = [ "default.target" ]; + }; + }; +} diff --git a/config/local.nix b/config/local.nix index 31d794c..a3e43b2 100644 --- a/config/local.nix +++ b/config/local.nix @@ -24,6 +24,8 @@ with lib; ./fudo/system.nix ./fudo/webmail.nix + ./informis/cl-gemini.nix + ../fudo/profiles ../fudo/sites ]; diff --git a/defaults.nix b/defaults.nix index 5c4242c..9f06d1f 100644 --- a/defaults.nix +++ b/defaults.nix @@ -55,6 +55,7 @@ mkpasswd ncurses5 nix-index + nix-prefetch-git nmap oidentd openldap @@ -81,14 +82,13 @@ yubikey-manager ]; - system.stateVersion = "19.09"; + system.stateVersion = "20.03"; system.autoUpgrade.enable = true; environment.etc.current-nixos-config.source = ./.; krb5.enable = true; - krb5.libdefaults.default_realm = "FUDO.ORG"; krb5.kerberos = pkgs.heimdalFull; console.keyMap = "dvp"; diff --git a/fudo/sites/joes.nix b/fudo/sites/joes.nix index 8f541ed..5fcb5a7 100644 --- a/fudo/sites/joes.nix +++ b/fudo/sites/joes.nix @@ -2,12 +2,14 @@ with lib; let - admin = "admin@informis.land"; - hostname = config.networking.hostName; gateway = "172.86.179.17"; + local-domain = "informis.land"; + + admin = "admin@${local-domain}"; + in { config = mkIf (config.fudo.common.site == "joes") { time.timeZone = "America/Winnipeg"; @@ -17,21 +19,30 @@ in { }; networking = { - domain = "informis.land"; - search = ["informis.land" "fudo.org"]; + domain = local-domain; + search = [ local-domain "fudo.org" ]; firewall.enable = false; defaultGateway = gateway; # defaultGateway6 = gateway6; + + hosts = { + "127.0.0.1" = [ + "${config.networking.hostName}.${local-domain}" + config.networking.hostName + ]; + }; }; + krb5.libdefaults.default_realm = "INFORMIS.LAND"; + fudo.node-exporter = { enable = false; hostname = hostname; }; - security.acme.certs."${hostname}.informis.land" = { - email = "admin@informis.land"; + security.acme.certs."${hostname}.${local-domain}" = { + email = "admin@${local-domain}"; }; services.nginx = { diff --git a/fudo/sites/seattle.nix b/fudo/sites/seattle.nix index 83788cd..8d58e61 100644 --- a/fudo/sites/seattle.nix +++ b/fudo/sites/seattle.nix @@ -22,6 +22,8 @@ in { mailto = admin; }; + krb5.libdefaults.default_realm = "FUDO.ORG"; + networking = { domain = local-domain; search = [local-domain "fudo.org"]; diff --git a/hosts/procul.nix b/hosts/procul.nix index 5237977..754d83a 100644 --- a/hosts/procul.nix +++ b/hosts/procul.nix @@ -238,8 +238,10 @@ in { admin-address = "admin@${domain}"; hostnames = [ + "informis.land" "imap.informis.land" "smtp.informis.land" + "gemini.informis.land" ]; }; }; @@ -260,4 +262,14 @@ in { }; }; }; + + informis.cl-gemini = { + enable = true; + + server-ip = host_ipv4; + document-root = /srv/gemini; + ssl-private-key = acme-private-key "informis.land"; + ssl-certificate = acme-certificate "informis.land"; + slynk-port = 4005; + }; } diff --git a/packages/cl-gemini.nix b/packages/cl-gemini.nix new file mode 100644 index 0000000..5577e17 --- /dev/null +++ b/packages/cl-gemini.nix @@ -0,0 +1,24 @@ +{ stdenv, fetchgit, pkgs }: + +let + url = "https://git.informis.land/viator/cl-gemini.git"; + version = "0.1"; + +in stdenv.mkDerivation { + name = "cl-gemini-${version}"; + + src = fetchgit { + url = "https://git.informis.land/viator/cl-gemini.git"; + rev = "a4596703a4e7ff628639ea4a2350591e4db9a32d"; + sha256 = "18zqgx200fd32kgbpfhvcnlwanzmjk3f0ggiks0n579zkhzslxs0"; + fetchSubmodules = false; + }; + + phases = ["installPhase"]; + + installPhase = '' + mkdir -p "$out/lib/common-lisp/cl-gemini" + cp "$src/cl-gemini.asd" "$out/lib/common-lisp/cl-gemini" + cp -R "$src/src" "$out/lib/common-lisp/cl-gemini" + ''; +} diff --git a/packages/local.nix b/packages/local.nix index deda25e..caba142 100644 --- a/packages/local.nix +++ b/packages/local.nix @@ -36,14 +36,15 @@ configureFlags = oldAttrs.configureFlags ++ [ "--with-gssapi" ]; buildInputs = oldAttrs.buildInputs ++ [ pkgs.krb5 ]; }); - sbcl-with-libs = pkgs.sbcl.overrideAttrs (oldAttrs: rec { - extraLibs = with pkgs; [ - openssl_1_1.dev - ]; - }); hll2380dw-cups = import ./hll2380dw-cups.nix { inherit (pkgs) stdenv fetchurl makeWrapper cups dpkg a2ps ghostscript gnugrep gnused coreutils file perl which; }; + + cl-gemini = import ./cl-gemini.nix { + pkgs = pkgs; + stdenv = pkgs.stdenv; + fetchgit = pkgs.fetchgit; + }; }; } From 115548495f0a64bc5b57832c728ccb972ab207dc Mon Sep 17 00:00:00 2001 From: "root@procul" Date: Thu, 16 Jul 2020 15:46:52 -0500 Subject: [PATCH 4/6] missed some changes --- config/informis/cl-gemini.nix | 79 +++++++++++++++++++++++++++++------ hosts/procul.nix | 16 +++++-- packages/cl-gemini.nix | 4 +- 3 files changed, 81 insertions(+), 18 deletions(-) diff --git a/config/informis/cl-gemini.nix b/config/informis/cl-gemini.nix index ccab8bc..172a92b 100644 --- a/config/informis/cl-gemini.nix +++ b/config/informis/cl-gemini.nix @@ -5,6 +5,8 @@ let cfg = config.informis.cl-gemini; lisp-libs = with pkgs.lispPackages; [ + asdf-package-system + asdf-system-connections alexandria asdf-package-system asdf-system-connections @@ -16,21 +18,17 @@ let usocket ]; - launchServer = load-paths: ip: port: root: public-dir: key: cert: slynk-port: - let - load-path-string = - concatStringsSep " " (map (path: "\"${path}\"") load-paths); - in pkgs.writeText "launch-server.lisp" '' + launchServer = ip: port: root: public-dir: key: cert: slynk-port: feeds-string: textfiles-archive: + pkgs.writeText "launch-server.lisp" '' (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname))) - (setf asdf:*central-registry* - (append asdf:*central-registry* - (list ${load-path-string}))) (ql:quickload :slynk) (ql:quickload :cl-gemini) ${optionalString (slynk-port != null) "(slynk:create-server :port ${toString slynk-port} :dont-close t)"} + ${feeds-string} (cl-gemini:start-gemini-server "${ip}" "${key}" "${cert}" :port ${toString port} :document-root "${root}" + :textfiles-root "${textfiles-archive}" :file-cmd "${pkgs.file}/bin/file" :log-stream *standard-output* :threaded t @@ -44,6 +42,36 @@ let ]; }); + feedOpts = with types; { + options = { + url = mkOption { + type = str; + description = "Base URI of the feed, i.e. the URI corresponding to the feed path."; + example = "gemini://my.server/path/to/feedfiles"; + }; + + title = mkOption { + type = str; + description = "Title of given feed."; + example = "My Fancy Feed"; + }; + + path = mkOption { + type = str; + description = "Path to Gemini files making up the feed."; + example = "/path/to/feed"; + }; + }; + }; + + register-feed = name: opts: '' + (cl-gemini:register-feed :name "${name}" :title "${opts.title}" :path "${opts.path}" :base-uri "${opts.url}")''; + + register-feeds = feeds: + concatStringsSep "\n" + (mapAttrsToList register-feed feeds); + + in { options.informis.cl-gemini = with types; { enable = mkEnableOption "Enable the cl-gemini server."; @@ -61,9 +89,9 @@ in { }; document-root = mkOption { - type = path; + type = str; description = "Root at which to look for gemini files."; - example = /my/gemini/root; + example = "/my/gemini/root"; }; user-public = mkOption { @@ -89,6 +117,25 @@ in { description = "Port on which to open a slynk server, if any."; default = null; }; + + feeds = mkOption { + type = loaOf (submodule feedOpts); + description = "Feeds to generate and make available (as eg. /feed/name.xml)."; + example = { + diary = { + title = "My Diary"; + path = "/path/to/my/gemfiles/"; + url = "gemini://my.host/blog-path/"; + }; + }; + default = {}; + }; + + textfiles-archive = mkOption { + type = str; + description = "A path containing only gemini & text files."; + example = "/path/to/textfiles/"; + }; }; config = mkIf cfg.enable { @@ -124,13 +171,11 @@ in { description = "cl-gemini Gemini server (https://gemini.circumlunar.space/)"; serviceConfig = let - load-paths = (map (pkg: "${pkg}/lib/common-lisp//") - (lisp-libs ++ [pkgs.cl-gemini])); + feed-registrations = register-feeds cfg.feeds; in { ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init"; ExecStart = "${sbcl-with-ssl}/bin/sbcl --load ${ launchServer - load-paths cfg.server-ip cfg.port cfg.document-root @@ -138,6 +183,8 @@ in { "/etc/cl-gemini/key.pem" "/etc/cl-gemini/cert.pem" cfg.slynk-port + feed-registrations + cfg.textfiles-archive }"; Restart = "on-failure"; PIDFile = "/run/cl-gemini.$USERNAME.uid"; @@ -146,9 +193,15 @@ in { environment = { LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib"; + CL_SOURCE_REGISTRY = concatStringsSep ":" + (["${config.users.users.cl-gemini.home}/quicklisp/quicklisp"] ++ + (map + (pkg: "${pkg}//") + (lisp-libs ++ [pkgs.cl-gemini]))); }; path = with pkgs; [ + gcc file getent ]; diff --git a/hosts/procul.nix b/hosts/procul.nix index 754d83a..2276e63 100644 --- a/hosts/procul.nix +++ b/hosts/procul.nix @@ -267,9 +267,19 @@ in { enable = true; server-ip = host_ipv4; - document-root = /srv/gemini; - ssl-private-key = acme-private-key "informis.land"; - ssl-certificate = acme-certificate "informis.land"; + document-root = "/srv/gemini/root"; + ssl-private-key = "/srv/gemini/private/key.pem"; + ssl-certificate = "/srv/gemini/private/cert.pem"; slynk-port = 4005; + + textfiles-archive = "/srv/gemini/textfiles"; + + feeds = { + viator = { + title = "viator's phlog"; + path = "/home/viator/gemini-public/feed/"; + url = "gemini://informis.land/user/viator/feed/"; + }; + }; }; } diff --git a/packages/cl-gemini.nix b/packages/cl-gemini.nix index 5577e17..22ef42c 100644 --- a/packages/cl-gemini.nix +++ b/packages/cl-gemini.nix @@ -9,8 +9,8 @@ in stdenv.mkDerivation { src = fetchgit { url = "https://git.informis.land/viator/cl-gemini.git"; - rev = "a4596703a4e7ff628639ea4a2350591e4db9a32d"; - sha256 = "18zqgx200fd32kgbpfhvcnlwanzmjk3f0ggiks0n579zkhzslxs0"; + rev = "3de4d1945fc91d0c9f8f65a5d4b0d3f39fbdaa80"; + sha256 = "1xzfsp5vp36a3yas5pnhj2a1dd72r72fw3l49ah19hvbapaikhsw"; fetchSubmodules = false; }; From c4f7e225220be68e7ef23e96be3139d318ea6b18 Mon Sep 17 00:00:00 2001 From: nostoromo root Date: Thu, 16 Jul 2020 14:13:32 -0700 Subject: [PATCH 5/6] no need to use sbcl-with-libs anymore --- config/fudo/slynk.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/fudo/slynk.nix b/config/fudo/slynk.nix index e8033e2..8ae12ed 100644 --- a/config/fudo/slynk.nix +++ b/config/fudo/slynk.nix @@ -51,7 +51,7 @@ in { load-paths = (map (pkg: "${pkg}/lib/common-lisp/") lisp-libs); in { ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init"; - ExecStart = "${pkgs.sbcl-with-libs}/bin/sbcl --load ${initScript cfg.port load-paths}"; + ExecStart = "${pkgs.sbcl}/bin/sbcl --load ${initScript cfg.port load-paths}"; Restart = "on-failure"; PIDFile = "/run/slynk.$USERNAME.pid"; }; From 8f3bfef11dcddb7f48406ea12cc7a66efdfdd6e9 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Jul 2020 14:41:06 -0700 Subject: [PATCH 6/6] Fixed GUI after merge --- config/fudo/common.nix | 2 ++ fudo/profiles/common-ui.nix | 61 ++++++++++++++++--------------------- fudo/profiles/default.nix | 1 + hosts/zbox.nix | 1 + 4 files changed, 31 insertions(+), 34 deletions(-) diff --git a/config/fudo/common.nix b/config/fudo/common.nix index 9cc235a..78f3fd8 100644 --- a/config/fudo/common.nix +++ b/config/fudo/common.nix @@ -52,5 +52,7 @@ with lib; description = "Email for administrator of this system."; default = "admin@fudo.org"; }; + + enable-gui = mkEnableOption "Install desktop GUI software."; }; } diff --git a/fudo/profiles/common-ui.nix b/fudo/profiles/common-ui.nix index b937ad7..60989ce 100644 --- a/fudo/profiles/common-ui.nix +++ b/fudo/profiles/common-ui.nix @@ -4,14 +4,22 @@ with lib; let profile = config.fudo.common.profile; -in mkIf ((profile == "desktop") || (profile == "laptop")) { - environment.systemPackages = with pkgs; [ + common-packages = with pkgs; [ + ffmpeg-full + libfixposix + mono + nomacs + python37Packages.youtube-dl + sqlite + system-config-printer + ]; + + gui-packages = with pkgs; [ cool-retro-term corefonts chrome-gnome-shell chromium evince - ffmpeg-full firefox gimp glxinfo @@ -23,31 +31,13 @@ in mkIf ((profile == "desktop") || (profile == "laptop")) { gtk3 gtkimageview i3lock - libfixposix - #minecraft-current - mono mplayer mpv - nomacs - openssl_1_1 pdftk - python37Packages.youtube-dl redshift rhythmbox shotwell spotify - sqlite - (steam.override { - nativeOnly = true; - extraPkgs = pkgs: [ - mono - gtk3 - gtk3-x11 - libgdiplus - zlib - ]; - withJava = true; - }) (steam.override { nativeOnly = true; extraPkgs = pkgs: [ @@ -60,15 +50,18 @@ in mkIf ((profile == "desktop") || (profile == "laptop")) { ]; withJava = true; }).run - # steam-run - # steam-run-native - system-config-printer virtmanager xorg.xev xzgv virtmanager-qt ]; + cfg = config.fudo.common; + +in mkIf ((profile == "desktop") || (profile == "laptop")) { + environment.systemPackages = + common-packages ++ (if cfg.enable-gui then gui-packages else []); + nixpkgs.config.allowBroken = true; # Splash screen @@ -82,8 +75,8 @@ in mkIf ((profile == "desktop") || (profile == "laptop")) { boot.tmpOnTmpfs = true; - services.xserver = { - # enable = true; + services.xserver = if cfg.enable-gui then { + enable = true; layout = "us"; xkbVariant = "dvp"; @@ -102,24 +95,24 @@ in mkIf ((profile == "desktop") || (profile == "laptop")) { waidPID=$! ''; }; + } else { + layout = "us"; + xkbVariant = "dvp"; + xkbOptions = "ctrl:nocaps"; }; - services.gnome3 = { + services.gnome3 = mkIf cfg.enable-gui { evolution-data-server.enable = pkgs.lib.mkForce false; gnome-user-share.enable = pkgs.lib.mkForce false; }; services.dbus.socketActivated = true; - #services.openssh.forwardX11 = true; - - #programs.ssh.forwardX11 = true; - sound.enable = true; - hardware.pulseaudio.enable = true; + hardware.pulseaudio.enable = cfg.enable-gui; - fonts = { + fonts = mkIf cfg.enable-gui { enableFontDir = true; #fontconfig.antialias = true; fontconfig.enable = true; @@ -182,4 +175,4 @@ in mkIf ((profile == "desktop") || (profile == "laptop")) { xlibs.fontxfree86type1 ]; }; -} \ No newline at end of file +} diff --git a/fudo/profiles/default.nix b/fudo/profiles/default.nix index fc70616..a4c5892 100644 --- a/fudo/profiles/default.nix +++ b/fudo/profiles/default.nix @@ -2,6 +2,7 @@ { imports = [ + ./common-ui.nix ./desktop.nix ./laptop.nix ./server.nix diff --git a/hosts/zbox.nix b/hosts/zbox.nix index a8d0790..aab9ea9 100644 --- a/hosts/zbox.nix +++ b/hosts/zbox.nix @@ -29,6 +29,7 @@ in { fudo.common = { profile = "desktop"; site = "seattle"; + enable-gui = true; }; fudo.slynk = {