merged atom with upstream

This commit is contained in:
root 2020-07-16 15:09:33 -07:00
commit ac623c51c2
22 changed files with 1278 additions and 324 deletions

View File

@ -6,26 +6,28 @@ with lib;
let let
cfg = config.fudo.acme; cfg = config.fudo.acme;
wwwRoot = hostname: # wwwRoot = hostname:
pkgs.writeTextFile { # pkgs.writeTextFile {
name = "index.html"; # name = "index.html";
text = '' # text = ''
<html> # <html>
<head> # <head>
<title>${hostname}</title> # <title>${hostname}</title>
</head> # </head>
<body> # <body>
<h1>${hostname}</title> # <h1>${hostname}</title>
</body> # </body>
</html> # </html>
''; # '';
destination = "/www"; # destination = "/www";
}; # };
in { in {
options.fudo.acme = { options.fudo.acme = {
enable = mkEnableOption "Fetch ACME certs for supplied local hostnames.";
hostnames = mkOption { hostnames = mkOption {
type = with types; listOf str; type = with types; listOf str;
description = "A list of hostnames mapping to this host, for which to acquire SSL certificates."; description = "A list of hostnames mapping to this host, for which to acquire SSL certificates.";
@ -35,9 +37,15 @@ in {
"alt.hostname.com" "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 = { services.nginx = {
enable = true; enable = true;
@ -49,13 +57,13 @@ in {
{ {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
root = (wwwRoot hostname) + ("/" + "www"); # root = (wwwRoot hostname) + ("/" + "www");
}) })
cfg.hostnames); cfg.hostnames);
}; };
security.acme.certs = listToAttrs security.acme.certs = listToAttrs
(map (hostname: nameValuePair hostname { email = "admin@fudo.org"; }) (map (hostname: nameValuePair hostname { email = cfg.admin-address; })
cfg.hostnames); cfg.hostnames);
}; };
} }

View File

@ -52,5 +52,7 @@ with lib;
description = "Email for administrator of this system."; description = "Email for administrator of this system.";
default = "admin@fudo.org"; default = "admin@fudo.org";
}; };
enable-gui = mkEnableOption "Install desktop GUI software.";
}; };
} }

218
config/fudo/dns.nix Normal file
View File

@ -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;
};
};
}

View File

@ -104,6 +104,7 @@ in {
user-aliases = mkOption { user-aliases = mkOption {
type = with types; loaOf(listOf str); type = with types; loaOf(listOf str);
description = "A map of real user to list of aliases."; description = "A map of real user to list of aliases.";
default = {};
example = { example = {
someuser = ["alias0" "alias1"]; someuser = ["alias0" "alias1"];
}; };
@ -167,4 +168,22 @@ in {
./mail/rspamd.nix ./mail/rspamd.nix
./mail/clamav.nix ./mail/clamav.nix
]; ];
config = mkIf cfg.enable {
users = {
users = {
mailuser = {
isSystemUser = true;
uid = cfg.mail-user-id;
group = "mailgroup";
};
};
groups = {
mailgroup = {
members = ["mailuser"];
};
};
};
};
} }

View File

@ -23,61 +23,86 @@ let
''; '';
}; };
ldap-conf = filename: uris: ldap-conf = filename: config:
pkgs.writeText filename '' let
uris = ${concatStringsSep " " uris} 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 ldap_version = 3
dn = ${cfg.dovecot.ldap-reader-dn} dn = ${config.reader-dn}
dnpass = ${cfg.dovecot.ldap-reader-passwd} dnpass = ${config.reader-passwd}
auth_bind = yes auth_bind = yes
auth_bind_userdn = uid=%u,ou=members,dc=fudo,dc=org auth_bind_userdn = uid=%u,ou=members,dc=fudo,dc=org
base = dc=fudo,dc=org base = dc=fudo,dc=org
# tls_ca_cert_file = ${cfg.dovecot.ldap-ca} ${ssl-config}
# FIXME: turn back on when certs work
tls = no
tls_require_cert = try
''; '';
dovecot-user = config.services.dovecot2.user; ldap-passwd-entry = ldap-config: ''
passdb {
driver = ldap
args = ${ldap-conf "ldap-passdb.conf" ldap-config}
}
'';
in { ldapOpts = with types; {
options.fudo.mail-server.dovecot = { ca = mkOption {
ssl-private-key = mkOption { type = str;
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;
description = "The path to the CA cert used to sign the LDAP server certificate."; description = "The path to the CA cert used to sign the LDAP server certificate.";
}; };
ldap-urls = mkOption { server-urls = mkOption {
type = with types; listOf str; type = listOf str;
description = "The urls of LDAP servers."; description = "A list of LDAP server URLs used for authentication.";
}; };
ldap-reader-dn = mkOption { reader-dn = mkOption {
type = types.str; type = str;
description = '' description = ''
DN to use for reading user information. Needs access to homeDirectory, DN to use for reading user information. Needs access to homeDirectory,
uidNumber, gidNumber, and uid, but not password attributes. uidNumber, gidNumber, and uid, but not password attributes.
''; '';
}; };
ldap-reader-passwd = mkOption { reader-pw = mkOption {
type = types.str; type = str;
description = '' description = ''
Password for the user specified in ldap-reader-dn. 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 { config = mkIf cfg.enable {
services.prometheus.exporters.dovecot = mkIf cfg.monitoring { services.prometheus.exporters.dovecot = mkIf cfg.monitoring {
@ -93,8 +118,7 @@ in {
enableImap = true; enableImap = true;
enableLmtp = true; enableLmtp = true;
enablePop3 = true; enablePop3 = true;
enablePAM = false; enablePAM = cfg.dovecot.ldap == null;
createMailUser = true; createMailUser = true;
@ -124,14 +148,16 @@ in {
extraConfig = '' extraConfig = ''
#Extra Config #Extra Config
# The prometheus exporter still expects an older style of metrics ${optionalString cfg.monitoring ''
mail_plugins = $mail_plugins old_stats # The prometheus exporter still expects an older style of metrics
service old-stats { mail_plugins = $mail_plugins old_stats
unix_listener old-stats { service old-stats {
user = dovecot-exporter unix_listener old-stats {
group = dovecot-exporter user = dovecot-exporter
group = dovecot-exporter
}
} }
} ''}
${lib.optionalString cfg.debug '' ${lib.optionalString cfg.debug ''
mail_debug = yes mail_debug = yes
@ -170,15 +196,15 @@ in {
} }
# Drop privs, since all mail is owned by one user # Drop privs, since all mail is owned by one user
user = ${cfg.mail-user} # user = ${cfg.mail-user}
group = ${cfg.mail-group} # group = ${cfg.mail-group}
user = root
} }
auth_mechanisms = login plain auth_mechanisms = login plain
passdb {
driver = ldap ${optionalString (cfg.dovecot.ldap != null)
args = ${ldap-conf "ldap-passdb.conf" cfg.dovecot.ldap-urls} (ldap-conf cfg.dovecot.ldap)}
}
userdb { userdb {
driver = static driver = static
args = uid=${toString cfg.mail-user-id} home=${cfg.mail-directory}/%u args = uid=${toString cfg.mail-user-id} home=${cfg.mail-directory}/%u
@ -189,8 +215,18 @@ in {
unix_listener auth { unix_listener auth {
mode = 0660 mode = 0660
user = "${config.services.postfix.user}" 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 { namespace inbox {
@ -236,7 +272,8 @@ in {
done done
chown -R '${dovecot-user}:${cfg.mail-group}' '${state-directory}/imap_sieve' 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}
''; '';
}; };
} }

View File

@ -6,6 +6,14 @@ let
cfg = config.fudo.mail-server; 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: make-user-aliases = entries:
concatStringsSep "\n" concatStringsSep "\n"
(mapAttrsToList (user: aliases: (mapAttrsToList (user: aliases:
@ -39,25 +47,22 @@ let
/^User-Agent:/ IGNORE /^User-Agent:/ IGNORE
/^X-Enigmail:/ IGNORE /^X-Enigmail:/ IGNORE
''); '');
blacklist-postfix-entry = sender: "${sender} REJECT"; blacklist-postfix-entry = sender: "${sender} REJECT";
blacklist-postfix-file = entries: blacklist-postfix-file = filename: entries:
concatStringsSep "\n" (map blacklist-postfix-entry entries); write-entries filename entries;
sender-blacklist-file = builtins.toFile "reject_senders" sender-blacklist-file = blacklist-postfix-file "reject_senders"
(blacklist-postfix-file cfg.sender-blacklist); (map blacklist-postfix-entry cfg.sender-blacklist);
recipient-blacklist-file = builtins.toFile "reject_recipients" recipient-blacklist-file = blacklist-postfix-file "reject_recipients"
(blacklist-postfix-file cfg.recipient-blacklist); (map blacklist-postfix-entry cfg.recipient-blacklist);
# A list of domains for which we accept mail # A list of domains for which we accept mail
virtual-mailbox-map-file = builtins.toFile "virtual_mailbox_map" virtual-mailbox-map-file = write-entries "virtual_mailbox_map"
(concatStringsSep "\n" (map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain]));
(map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain])));
sender-login-map-file = let sender-login-map-file = let
escapeDot = (str: replaceStrings ["."] ["\\."] str); escapeDot = (str: replaceStrings ["."] ["\\."] str);
in builtins.toFile "sender_login_maps" in write-entries "sender_login_maps"
(concatStringsSep "\n" (map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain]));
(map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain])));
mapped-file = name: "hash:/var/lib/postfix/conf/${name}"; mapped-file = name: "hash:/var/lib/postfix/conf/${name}";
@ -106,9 +111,8 @@ in {
origin = cfg.domain; origin = cfg.domain;
hostname = cfg.hostname; hostname = cfg.hostname;
destination = ["localhost" "localhost.localdomain"]; destination = ["localhost" "localhost.localdomain"];
# destination = ["localhost" "localhost.localdomain"] ++ # destination = ["localhost" "localhost.localdomain" cfg.hostname] ++
# (map (domain: "localhost.${domain}") cfg.local-domains) ++ # cfg.local-domains;;
# cfg.local-domains;
enableHeaderChecks = true; enableHeaderChecks = true;
enableSmtp = true; enableSmtp = true;
@ -133,7 +137,7 @@ in {
sslKey = cfg.postfix.ssl-private-key; sslKey = cfg.postfix.ssl-private-key;
config = { 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_base = "${cfg.mail-directory}/";
virtual_mailbox_maps = mapped-file "virtual_mailbox_map"; virtual_mailbox_maps = mapped-file "virtual_mailbox_map";

View File

@ -4,9 +4,15 @@ with lib;
let let
cfg = config.fudo.slynk; 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))) (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))
(ql:quickload :slynk) (ql:quickload :slynk)
(setf asdf:*central-registry*
(append asdf:*central-registry*
(list ${load-path-string})))
(slynk:create-server :port ${toString port} :dont-close t) (slynk:create-server :port ${toString port} :dont-close t)
(dolist (var '("LD_LIBRARY_PATH")) (dolist (var '("LD_LIBRARY_PATH"))
(format t "~S: ~S~%" var (sb-unix::posix-getenv var))) (format t "~S: ~S~%" var (sb-unix::posix-getenv var)))
@ -14,6 +20,18 @@ let
(loop (sleep 60)) (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 { in {
options.fudo.slynk = { options.fudo.slynk = {
enable = mkEnableOption "Enable Slynk emacs common lisp server."; enable = mkEnableOption "Enable Slynk emacs common lisp server.";
@ -29,24 +47,24 @@ in {
systemd.user.services.slynk = { systemd.user.services.slynk = {
description = "Slynk Common Lisp server."; 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"; ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init";
ExecStart = "${pkgs.sbcl-with-libs}/bin/sbcl --load ${initScript cfg.port}"; ExecStart = "${pkgs.sbcl}/bin/sbcl --load ${initScript cfg.port load-paths}";
Restart = "on-failure"; Restart = "on-failure";
PIDFile = "/run/slynk.$USERNAME.pid"; PIDFile = "/run/slynk.$USERNAME.pid";
}; };
path = with pkgs; [ path = with pkgs; [
gcc
glibc # for getent glibc # for getent
file file
]; ];
environment = { 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" ];
}; };
}; };
} }

View File

@ -0,0 +1,212 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.informis.cl-gemini;
lisp-libs = with pkgs.lispPackages; [
asdf-package-system
asdf-system-connections
alexandria
asdf-package-system
asdf-system-connections
cl_plus_ssl
cl-ppcre
quicklisp
quri
uiop
usocket
];
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)))
(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
:separate-thread t)
(loop (sleep 60))
'';
sbcl-with-ssl = pkgs.sbcl.overrideAttrs (oldAttrs: rec {
extraLibs = with pkgs; [
openssl_1_1.dev
];
});
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.";
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 = str;
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;
};
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 {
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
feed-registrations = register-feeds cfg.feeds;
in {
ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init";
ExecStart = "${sbcl-with-ssl}/bin/sbcl --load ${
launchServer
cfg.server-ip
cfg.port
cfg.document-root
cfg.user-public
"/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";
User = "cl-gemini";
};
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
];
wantedBy = [ "default.target" ];
};
};
}

View File

@ -7,6 +7,7 @@ with lib;
./fudo/authentication.nix ./fudo/authentication.nix
./fudo/chat.nix ./fudo/chat.nix
./fudo/common.nix ./fudo/common.nix
./fudo/dns.nix
./fudo/git.nix ./fudo/git.nix
./fudo/grafana.nix ./fudo/grafana.nix
./fudo/kdc.nix ./fudo/kdc.nix
@ -23,6 +24,8 @@ with lib;
./fudo/system.nix ./fudo/system.nix
./fudo/webmail.nix ./fudo/webmail.nix
./informis/cl-gemini.nix
../fudo/profiles ../fudo/profiles
../fudo/sites ../fudo/sites
]; ];

View File

@ -31,6 +31,7 @@
curl curl
dpkg dpkg
emacs emacs
enca
fail2ban fail2ban
file file
fortune fortune
@ -56,6 +57,7 @@
mkpasswd mkpasswd
ncurses5 ncurses5
nix-index nix-index
nix-prefetch-git
nmap nmap
oidentd oidentd
openldap openldap
@ -80,6 +82,7 @@
vim vim
wget wget
yubikey-manager yubikey-manager
yubikey-personalization
]; ];
system.stateVersion = "20.03"; system.stateVersion = "20.03";
@ -89,7 +92,6 @@
environment.etc.current-nixos-config.source = ./.; environment.etc.current-nixos-config.source = ./.;
krb5.enable = true; krb5.enable = true;
krb5.libdefaults.default_realm = "FUDO.ORG";
krb5.kerberos = pkgs.heimdalFull; krb5.kerberos = pkgs.heimdalFull;
services.xserver = { services.xserver = {
@ -110,6 +112,8 @@
mosh.enable = true; mosh.enable = true;
ssh = { ssh = {
startAgent = false;
extraConfig = '' extraConfig = ''
GSSAPIAuthentication yes GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes GSSAPIDelegateCredentials yes
@ -143,8 +147,21 @@
GSSAPICleanupCredentials yes 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 = { security.pam = {
enableSSHAgentAuth = true; enableSSHAgentAuth = true;
# TODO: add yubico? # TODO: add yubico?
@ -180,6 +197,9 @@
group = "users"; group = "users";
home = "/home/niten"; home = "/home/niten";
hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/"; 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 = { reaper = {
isNormalUser = true; isNormalUser = true;

View File

@ -4,206 +4,175 @@ with lib;
let let
profile = config.fudo.common.profile; profile = config.fudo.common.profile;
in { common-packages = with pkgs; [
options.fudo.ui = { ffmpeg-full
console-only = mkOption { libfixposix
type = types.bool; mono
description = "Don't install X, only console stuff."; nomacs
default = false; python37Packages.youtube-dl
}; sqlite
system-config-printer
];
gui-packages = with pkgs; [
cool-retro-term
corefonts
chrome-gnome-shell
chromium
evince
firefox
gimp
glxinfo
gnome3.gnome-shell
gnome3.gnome-session
google-chrome
gtk2
gtk2-x11
gtk3
gtkimageview
i3lock
mplayer
mpv
pdftk
redshift
rhythmbox
shotwell
spotify
(steam.override {
nativeOnly = true;
extraPkgs = pkgs: [
mono
fmodex
gtk3
gtk3-x11
libgdiplus
zlib
];
withJava = true;
}).run
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;
services.avahi = {
enable = true;
browseDomains = [config.fudo.common.domain];
domainName = config.fudo.common.domain;
}; };
config = mkIf ((profile == "desktop") || (profile == "laptop")) { # splash screen
environment.systemPackages = with pkgs; boot.plymouth.enable = false;
[
libfixposix
python37Packages.youtube-dl
sqlite
virtmanager
xzgv
] ++ (if (config.fudo.ui.console-only) then [] else [
cool-retro-term
corefonts
chrome-gnome-shell
chromium
evince
ffmpeg-full
firefox
gimp
glxinfo
gnome3.gnome-shell
gnome3.gnome-session
google-chrome
gtk2
gtk2-x11
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: [
mono
fmodex
gtk3
gtk3-x11
libgdiplus
zlib
];
withJava = true;
}).run
# steam-run
# steam-run-native
system-config-printer
virtmanager
xorg.xev
xzgv
virtmanager-qt
]);
nixpkgs.config.allowBroken = true; boot.tmpOnTmpfs = true;
# Splash screen services.xserver = if cfg.enable-gui then {
boot.plymouth.enable = enable = true;
if (config.fudo.ui.console-only) then false else true;
services.avahi = { layout = "us";
enable = true; xkbVariant = "dvp";
browseDomains = [config.fudo.common.domain]; xkbOptions = "ctrl:nocaps";
domainName = config.fudo.common.domain;
};
boot.tmpOnTmpfs = true; desktopManager.gnome3.enable = true;
services.xserver = if (config.fudo.ui.console-only) then { displayManager.gdm.enable = true;
enable = false;
layout = "us"; displayManager.defaultSession = "gnome";
xkbVariant = "dvp";
xkbOptions = "ctrl:nocaps";
} else {
enable = true;
layout = "us"; windowManager.session = pkgs.lib.singleton {
xkbVariant = "dvp"; name = "stumpwm";
xkbOptions = "ctrl:nocaps"; start = ''
${pkgs.lispPackages.stumpwm}/bin/stumpwm &
desktopManager.gnome3.enable = true;
displayManager.gdm.enable = true;
displayManager.defaultSession = "gnome";
windowManager.session = pkgs.lib.singleton {
name = "stumpwm";
start = ''
${pkgs.lispPackages.stumpwm}/bin/stumpwm &
waidPID=$! waidPID=$!
''; '';
};
}; };
} else {
layout = "us";
xkbVariant = "dvp";
xkbOptions = "ctrl:nocaps";
};
services.gnome3 = mkIf (! config.fudo.ui.console-only) { services.gnome3 = mkIf cfg.enable-gui {
evolution-data-server.enable = pkgs.lib.mkForce false; evolution-data-server.enable = pkgs.lib.mkForce false;
gnome-user-share.enable = pkgs.lib.mkForce false; gnome-user-share.enable = pkgs.lib.mkForce false;
}; };
services.dbus.socketActivated = true; services.dbus.socketActivated = true;
#services.openssh.forwardX11 = true; sound.enable = true;
#programs.ssh.forwardX11 = true; hardware.pulseaudio.enable = true;
sound.enable = true; fonts = mkIf cfg.enable-gui {
enableFontDir = true;
#fontconfig.antialias = true;
fontconfig.enable = true;
#fontconfig.penultimate.enable = true;
#fontconfig.subpixel.lcdfilter = "default";
hardware.pulseaudio.enable = true; fonts = with pkgs; [
cantarell_fonts
fonts = mkIf (! config.fudo.ui.console-only) { dejavu_fonts
enableFontDir = true; dina-font
#fontconfig.antialias = true; dosemu_fonts
fontconfig.enable = true; fira-code
#fontconfig.penultimate.enable = true; fira-code-symbols
#fontconfig.subpixel.lcdfilter = "default"; freefont_ttf
liberation_ttf
fonts = with pkgs; [ mplus-outline-fonts
cantarell_fonts #nerdfonts
dejavu_fonts noto-fonts
dina-font noto-fonts-cjk
dosemu_fonts noto-fonts-emoji
fira-code proggyfonts
fira-code-symbols terminus_font
freefont_ttf ubuntu_font_family
liberation_ttf ucsFonts
mplus-outline-fonts unifont
#nerdfonts vistafonts
noto-fonts xlibs.fontadobe100dpi
noto-fonts-cjk xlibs.fontadobe75dpi
noto-fonts-emoji xlibs.fontadobeutopia100dpi
proggyfonts xlibs.fontadobeutopia75dpi
terminus_font xlibs.fontadobeutopiatype1
ubuntu_font_family xlibs.fontarabicmisc
ucsFonts xlibs.fontbh100dpi
unifont xlibs.fontbh75dpi
vistafonts xlibs.fontbhlucidatypewriter100dpi
xlibs.fontadobe100dpi xlibs.fontbhlucidatypewriter75dpi
xlibs.fontadobe75dpi xlibs.fontbhttf
xlibs.fontadobeutopia100dpi xlibs.fontbhtype1
xlibs.fontadobeutopia75dpi xlibs.fontbitstream100dpi
xlibs.fontadobeutopiatype1 xlibs.fontbitstream75dpi
xlibs.fontarabicmisc xlibs.fontbitstreamtype1
xlibs.fontbh100dpi xlibs.fontcronyxcyrillic
xlibs.fontbh75dpi xlibs.fontcursormisc
xlibs.fontbhlucidatypewriter100dpi xlibs.fontdaewoomisc
xlibs.fontbhlucidatypewriter75dpi xlibs.fontdecmisc
xlibs.fontbhttf xlibs.fontibmtype1
xlibs.fontbhtype1 xlibs.fontisasmisc
xlibs.fontbitstream100dpi xlibs.fontjismisc
xlibs.fontbitstream75dpi xlibs.fontmicromisc
xlibs.fontbitstreamtype1 xlibs.fontmisccyrillic
xlibs.fontcronyxcyrillic xlibs.fontmiscethiopic
xlibs.fontcursormisc xlibs.fontmiscmeltho
xlibs.fontdaewoomisc xlibs.fontmiscmisc
xlibs.fontdecmisc xlibs.fontmuttmisc
xlibs.fontibmtype1 xlibs.fontschumachermisc
xlibs.fontisasmisc xlibs.fontscreencyrillic
xlibs.fontjismisc xlibs.fontsonymisc
xlibs.fontmicromisc xlibs.fontsunmisc
xlibs.fontmisccyrillic xlibs.fontwinitzkicyrillic
xlibs.fontmiscethiopic xlibs.fontxfree86type1
xlibs.fontmiscmeltho ];
xlibs.fontmiscmisc
xlibs.fontmuttmisc
xlibs.fontschumachermisc
xlibs.fontscreencyrillic
xlibs.fontsonymisc
xlibs.fontsunmisc
xlibs.fontwinitzkicyrillic
xlibs.fontxfree86type1
];
};
}; };
} }

View File

@ -51,6 +51,8 @@ in {
config = mkIf (config.fudo.common.profile == "server") { config = mkIf (config.fudo.common.profile == "server") {
environment = { environment = {
systemPackages = with pkgs; [ systemPackages = with pkgs; [
ldns
ldns.examples
test-config test-config
reboot-if-necessary reboot-if-necessary
]; ];

View File

@ -2,17 +2,14 @@
with lib; with lib;
let let
admin = "admin@fudo.org";
nameservers = [
"1.1.1.1"
"2606:4700:4700::1111"
];
hostname = config.networking.hostName; hostname = config.networking.hostName;
gateway = "172.86.179.17"; gateway = "172.86.179.17";
local-domain = "informis.land";
admin = "admin@${local-domain}";
in { in {
config = mkIf (config.fudo.common.site == "joes") { config = mkIf (config.fudo.common.site == "joes") {
time.timeZone = "America/Winnipeg"; time.timeZone = "America/Winnipeg";
@ -22,31 +19,32 @@ in {
}; };
networking = { networking = {
domain = "fudo.org"; domain = local-domain;
search = ["fudo.org"]; search = [ local-domain "fudo.org" ];
firewall.enable = false; firewall.enable = false;
nameservers = nameservers;
defaultGateway = gateway; defaultGateway = gateway;
# defaultGateway6 = gateway6; # defaultGateway6 = gateway6;
hosts = {
"127.0.0.1" = [
"${config.networking.hostName}.${local-domain}"
config.networking.hostName
];
};
}; };
krb5.libdefaults.default_realm = "INFORMIS.LAND";
fudo.node-exporter = { fudo.node-exporter = {
enable = true; enable = false;
hostname = hostname; hostname = hostname;
}; };
security.acme.certs.${hostname} = { security.acme.certs."${hostname}.${local-domain}" = {
email = "admin@fudo.org"; email = "admin@${local-domain}";
# plugins = [
# "fullchain.pem"
# "full.pem"
# "key.pem"
# "chain.pem"
# "cert.pem"
# ];
}; };
services.nginx = { services.nginx = {
enable = true; enable = true;
recommendedGzipSettings = true; recommendedGzipSettings = true;

View File

@ -24,6 +24,8 @@ in {
mailto = admin; mailto = admin;
}; };
krb5.libdefaults.default_realm = "FUDO.ORG";
networking = { networking = {
domain = local-domain; domain = local-domain;
search = [local-domain "fudo.org"]; search = [local-domain "fudo.org"];

View File

@ -34,7 +34,7 @@ in {
}; };
fudo.laptop.use-network-manager = false; fudo.laptop.use-network-manager = false;
fudo.ui.console-only = true; fudo.common.enable-gui = false;
hardware.opengl.driSupport32Bit = true; hardware.opengl.driSupport32Bit = true;
hardware.opengl.extraPackages32 = with pkgs.pkgsi686Linux; [ libva ]; hardware.opengl.extraPackages32 = with pkgs.pkgsi686Linux; [ libva ];

View File

@ -3,8 +3,10 @@
with lib; with lib;
let let
hostname = "procul"; hostname = "procul";
domain = "informis.land";
mail-hostname = hostname; mail-hostname = hostname;
host_ipv4 = "172.86.179.18"; host_ipv4 = "172.86.179.18";
host-fqdn = "${hostname}.${domain}";
all-hostnames = []; all-hostnames = [];
acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem"; acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem";
@ -25,37 +27,20 @@ in {
../hardware-configuration.nix ../hardware-configuration.nix
../defaults.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; [ environment.systemPackages = with pkgs; [
multipath-tools 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 = { networking = {
hostName = hostname; hostName = hostname;
# provided by secure-dns-proxy
nameservers = [ "127.0.0.1" ];
dhcpcd.enable = false; dhcpcd.enable = false;
useDHCP = false; useDHCP = false;
@ -86,4 +71,215 @@ in {
}; };
hardware.bluetooth.enable = false; 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 = [
"informis.land"
"imap.informis.land"
"smtp.informis.land"
"gemini.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;
};
};
};
informis.cl-gemini = {
enable = true;
server-ip = host_ipv4;
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/";
};
};
};
} }

View File

@ -29,6 +29,7 @@ in {
fudo.common = { fudo.common = {
profile = "desktop"; profile = "desktop";
site = "seattle"; site = "seattle";
enable-gui = true;
}; };
fudo.slynk = { fudo.slynk = {

View File

@ -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";
}

14
informis/users.nix Normal file
View File

@ -0,0 +1,14 @@
{ config, ... }:
{
config = {
users.users = {
viator = {
isNormalUser = true;
description = "Viator";
createHome = true;
hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/";
};
};
};
}

24
packages/cl-gemini.nix Normal file
View File

@ -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 = "3de4d1945fc91d0c9f8f65a5d4b0d3f39fbdaa80";
sha256 = "1xzfsp5vp36a3yas5pnhj2a1dd72r72fw3l49ah19hvbapaikhsw";
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"
'';
}

View File

@ -32,14 +32,14 @@
buildInputs = oldAttrs.buildInputs ++ [ pkgs.krb5 ]; 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 { hll2380dw-cups = import ./hll2380dw-cups.nix {
inherit (pkgs) stdenv fetchurl makeWrapper cups dpkg a2ps ghostscript gnugrep gnused coreutils file perl which; 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;
};
}; };
} }

View File

@ -0,0 +1,109 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF8OOI0BEADNVhW6nBjuapgAEbzO5hNJtvEm5mcFKQ0yg0pGgFipklF8cIYY
2Ie7aiyrYMNK7dT5/twA3p8KdAlivXRosG7ak65QlchyBSmhmZPjNMSmlOAWM35A
1h/83gAkvnWcFywZFF97diFG1TSXAC+p6ZGT2rwH11ZAYghRHTqdGdLwFjeWw1lh
HUUOcz5iZcj8nXHRtoVGZFWi8FTcz9tBNsSZBVbmeHvr69p+86R4D+b32tYPlJsQ
6M73Ow+803m6qXq15apAFVhE1JcLsGjmTiWbocABX9OyV9RsojrCGBvJ2KH/ooGe
b1/38jnnHTzyvACYhR37kvQMxMj92lE03QqDezyUvQl/CQoBIwOIKRnnA/iHPnRj
OqvJq8JabLBi2252eE7nZFhA78UZ52oAE/rFQ9XwIfVs3UL3kuGNnvnxaF42zqn2
gF6UGJLYClUhhzpDxepQD8WMvnnE8Ss3aU/NcqqB+yVDPKScQB6V8Rz0Rwa9NbAT
SOgT9Lv94ilMYOHZocFdLOS6pQVGXVRDfiU7/WTB9V+zHnD+caPXO+Ed1ABzajIE
oS2surLtyHtdTTNQgd55LEeCFE/79le9zL4eC8cWoNK9sxGtbM1UGhO+QK7ku8RI
5amnIgDFFXrK9T4fT3Oh3fSL5vSgrYa6/62p5yQmPJ3B74/pi/NduYo9ZwARAQAB
tBZOaXRlbiA8bml0ZW5AZnVkby5vcmc+iQJOBBMBCAA4FiEEmbW+ZUtum3L4UbTZ
k23tiyzsAaUFAl8OOI0CGwEFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQk23t
iyzsAaV5RQ//eexUvGzY+1iT/tMxbhRm++usH7JDiSXVn5GgMi/j2D+PpJncGbgp
+QLzFIH7FOcl7+i2gjt85e1+MgyCIxwQhtinsBM8d8eNigTw/xnJZHnc1qFvMrwP
jkCIHnqOE8sWIU02Dm0tBjZi0uGMLVzbAsPX/quI0vRbP1x7pblFukexxLYbI9Z2
I+jxqc/6lXALnWouhtminpaWRmSrvM3NFvoPtOU9meIMavX53QUf1wniZnUM6bpL
roOgzYeE6uu+pTv1mZiArJeyaaBOIo+AceakEIB8ynKRZQNX+zO2DV8GzQCcGBKc
Ljw8oU/2NTG4YpzZY5ohyHvUK5UeBsJukHm2tGOwzJ223/FMPQ6XHXucaL0YMtbE
uMhWsItgTxhvui2K2K2APwSXvN7hJP4CcQUhMKLI/RsziyK8WIXJLRLBFUoyihy2
Q++oSIrQCYQ0sczGzxdjyzHoFZGgC6BD+HPoXyLN3k7ENfykUt9pp2pd/oXigEzp
ctgQBYKTdvu7pAAVlYq+ya2KmRQpqwL4hr3MCsXgpJ1MrC2ptbVeycn/+GI7AG8W
GzDt0vXs93Pc2fYRCq/lPg7i5UwOVIViTHe1xhz+firyTGoSVvzPy+UEZio+aWlk
E6qA4CctmC2k+s+hCjiAlQtSByU/jqwkgm3rVk8sLRTy9GDbteb2XZ+5Ag0EXw44
3wEQAMkxa/npGkJ/MRCwwdqOb9PojHOh7A0u+i0hQVhi1n53T1+gE3qmdPIUAzlU
XeA20qQvmDpGf0c9hE0EFoyJazV8tVIICiMqDDQ4UyJiHR1Nqa+rqgNRKlU5CBpQ
ibIgfvBnFI4Axm/LATORtxJTZGXoJm0gy3oD7+ESgnsESofMynuGvNfcH9QLIScS
TPQqB4DCStRFo/RGuglSHuQ9x0XR1hZfRvVDaVEFN7cO5K/8romlhkhLpgaLxrpg
6aHoDaqP9h9c5rwm9tc2nHdjSeteVsgCdW1LjOHUW366nkGZV5OWV92+mU6Sa6ND
fLJ4tPzqD+YvNAMpW49YhOuDRaj6yDAfZLBKEdy7bLHClcpR+b5xpgCGevXJjnx2
/znaiZnCMYDkzstUq2TZNdLEnMSpjpcJNA4yLrbMKMUTLv292vA4D9gWp+w7AIZ8
RHc4xR2ATmuSngV8cRYXxzT6bUMc+HfkSFt/bhxNykJmtDB4eeoeUkVJe+8ZQ+Ku
1JidIlJhN9++gCGrIsjXNamUXaq5eYhWI3w1lG4Rlc3CvSlvXKaP8CL5JEHhj2wL
QeXd0OMXHsNLdKl+tigf0OHkbReniJ2cc/IP01qPZ7/EHeaII2YqzN5yqrVN3RZL
7IJ41AmZvRr68APA0Y26b0OuF0xPGzxbPIuYUSgcsz822nwhABEBAAGJBHIEGAEI
ACYWIQSZtb5lS26bcvhRtNmTbe2LLOwBpQUCXw443wIbAgUJCWYBgAJACRCTbe2L
LOwBpcF0IAQZAQgAHRYhBHEyfCZCQei5p6g7uu5e6/Nf3ScNBQJfDjjfAAoJEO5e
6/Nf3ScNFBsQAITmUu3KG0a3f0NlmR/C6g6P/ybrW5TKDxrrB+vp0yayTsVWq0LO
fP5lJpVFNtz5nDfyDmjx4uBq8aC480rc5xd6t+zaQ91+Ara1JBzOQ3YWlZwngVl7
ikv5NC4ZVj8OulGSNg2Op2H4o2WhEEldbBeghdWzWUt/tshr4mQYfG0e6HdzIIL6
AurrOXlKVoCrT9ybSKi73PU0stPTTxxWDXFFgdDvSc08QSj+s3MA9L4JE6CWZGUI
qTPvvdSlWq9ZtKb6zqug0vUd16ph9EZRNs8DeLwxGFDqz9E50fYQfhX3p0srVOH0
71AUM/IPW4K1v5zKA3HLR9r/+IgZlUK+A6Z4O842QgO1enrh7zcOEF/l8oEa0ijf
rHowhP4iNa8qu2B735LB7Rh56TW3hG5eCPIBKBdmIQrYTFR+W+ze9e4oscJKxRN5
khB8T+Zz/vJqijOFenf6oIgswBBZTdk42JnRDB2ReCc0tkGko0Uk/O/s09avxXUX
AtIbPGVDZ2wnwi+m7oLounN0h7gYlTysB2VAGehuHU0udb9MJtNhuJd07gcMJwrh
PtaFdjOb+ejDQaiRs+g1CGer/r2vymoCgzkd3jOL04mG/3ZhbIjlKxutTgV+pyuQ
+7bPnOh3YBrx1UdRg5L3qduqpumHwVkJCqhpAHNU6D6kAkb7+DVuP+/LZ5YQALlJ
zrRWVYe2GMzzuT1d0yJjR/MZJa+VoS0lV/E5j4vfcLRTBKw/gaEyTzVdCfyaiRI7
PhFgW3l74sVmIGEEwp01/puc4oVtV5sE+FzOOiisWY22S+gy8ibFQArAvGIDZmZo
kxhdxU7kWbzFOqkP5gt8EaPWugL//hsYzELFxjk+CWEj8X8mbIQu0rh5QPBkLmIo
dDY+vuSd5myJNkpyQvhBxLGnZZLlBO5CqFug643fxppjC9EqOry10Qf3CFIL44aY
y2aOYxBolRzjMCLY8s+gF4yalpRUWPxJ/v5pYLkLVIqVKL5yxcp9YzZJQuR1Gxea
Tgz0nn2Nnms1vMvPj9pa2In/QLinGUNYolDln+aBkPM2xwaV+WCQVUdwS+cFIWx6
26AhFe+UgZVrGtqBkVJ1gCHk8mevFbpCh8WePQcHGd9/HiQ0/VUY6dhQ6nuR89QK
mxljXP1aNKWUhrSWvX+/+eRw5mdUO8ycfnm/rxrx1mvAoDzqHni02TbtJfqmYwqO
ps5zEMGV1C7EF2hqrhgBLVyxdvL1w1djKKFjJy9Zwyt0gY9TlM91Cpf2e0Gr1KCI
4WFH2a71ZveqMmCRcVfmJXEH+YJBeTJnAgZBl23nE1BRo/V9lQ3onv3uiOFFztH6
VGjrakScORyf41xDYaPIyaXqZ3kYnfMcqw3m4hFbuQINBF8OOP4BEACyeoL0mLan
ng8YKgdKwP7/uLRoRsTntiFB6hzNowt92niEKcOCqUXBKfG3ORQ7LAoRV6bA8SpQ
oqoiUn2MhWAfk+cP7wZLvxTxjk96JS564vppDOafNiI7mHPYr6urRNb0d7i3Q+sq
HDFH1M2rWWtYIDgYjeL8nTlwiGaYvZx8909DavhBP1TSbpFRoRl6wJzIr7Z6pl+A
Jg0AyRxVY1Fgi0c87sTf4eBmWUymbxyOY9ZdFiDP8/Ro6TIxjGqan8GP7xv28v7p
Paeqj46DoGmh3mUVq7FVbzZV4bspRLjQPSSF+wB/IpDGElleHgUF3l6R6GFMYXIJ
C6Ek3ZQ9MwRQI+5sQTVcbS8yqj639VnGeYy9NoHo6/oC3wh8U6QrxwqrQArAdsNS
yy5goa/ory7v5m3h+cxWpZBSr9JXUEA9sWuDRKMztQrMltAbsO+j8/OsVw3m+0Ud
d4wQxvu39UORELrMKSNeCgI4PH7AAs5EdIIBOxwmH5CpNiHkmfsJnumFYDCSzNXQ
sK/zA7UOAz+i7kYeAlonCYEeypJPsQs518UhsFA1qKeOUVhns/B+E03h8ktrudPA
XinhD+wC9FrbrnBRR1nNmK7yAqhpj5IrRkk4Jgcqua8NuoL8/UttKKEqRCu6KnO4
uJwO7Rpn28etMDMBvE9rwj3qjXtzGAAuFQARAQABiQI8BBgBCAAmFiEEmbW+ZUtu
m3L4UbTZk23tiyzsAaUFAl8OOP4CGwwFCQlmAYAACgkQk23tiyzsAaWHWhAAkBgs
9Xmcb0ejFBbH8U1EiTij/tXstS6YiHQ6u3HNoXLSZ9V4d21+gSiyjT42K5OnAPh7
Uzd0x0+h2E0FlaoRsrBD0z2EA7YcQpgvblBjuBzEs6InZC+aRIcnZpaejQDNQ+4T
geWBwhJItPpa33ZR7O1vLYFzLPH9DCCbtvZOCW1f72imrt4qMzWPTfPTQKZ4XGKg
p/hKOybSPAm4QxEGAf2JT+mcKdDUATuUdv75pPYHiblUoHBgezUf/xJCUYjKyUfl
DDbHwhTHr1d++c0VJHT9Zb9lCTG+A/JANBzFWKQ2otSex666g74GSTO6uzkxamhC
KKkIN5e4jhom6egs7MN4XebNgwyJ5qD2EORXOMMqCJ4IZdaQh931Kgi9OPTSZWGF
9DVevR6pBoGvBvgazIKHyjhsPz/Rlzn8qnaSYsTLnNcUT7VIU3fD1h+gsZDHCpjU
d07ovLJN+TCjnk9uisPWH2geLQBDvY2FmVX0uCqIW7kjffMogSMghSAgU1X8myT/
Z6ZHcfIPE5AhYi2i+3G50ZAqt4zRqAVlU7sT0MEQkwhAtg/G6K6nHxfLcFevG1Dn
on7WR7rQgw9ZEcIih4wTfk2dq3A2w5AcgMUryVyq7/R5mNx/Q8l+Qm9BebPQtvxq
hCKC5EM+Nmd8QHv07OIHKAeV8oeEdhhCpyCngK65Ag0EXw45HgEQAOhaSPJ4h+DC
bRvvzB5OhVg5BIPRFDSps3Omw3k2iRsgW/b/3zSQu2ditASAgn8nAwuVPe4lhpxs
JPn9roVvygvE2mPQAXUQppZndGuWDvZKr71ITAnBZaZmLNfzeyi8zBQExpSnqNYu
ECE+nMFbml9zlhahzz3DEZsQtLDOC3kSAdtImC8OdodKnd9VpjTXB8Ndsv+g7XrS
I17vC/Ycsxm78WRYGQiPPoeagYknNgzz1tSkdvJgbbyWYIcH/xQ+iDn8GyM6ff+q
6mB/jOHqYx0yxcu9tHaNXBWPFwQyP03mcK9z5jeiLsyKPpU2tZuGRoAkwTN4yFZi
sXf+kVDFSobftord3SDD2Snm0wMsiUA9fjLWV8DzukjOhrT4CWqXQIlADUgm+n1I
UbuUGZK2FZAuZm/DB+gaD9mMXqs6CxWhnxOLOlCfJ1YkOvo1uhT0sv05rrg4zlGz
QBTdxHZRs4XhAhxYUn/ugN7d06d9nxBirH15cnLGgBSkNqdppMdgGIAqR44HBBT4
xUsoJw40rD0VlyV//VOkMHlvf8l5QUA2MdBO/RRcDhhhTuILHoftcHirDC1T07X0
IZBhh8J9QtfXb99GlgnDpUlpBbLJTgGfl2T91wHacYjfqPBssx+FtRMgCm6OKgCd
38ZAgxqQcRnX6zI+EzH0HEyRlv30HQDVABEBAAGJAjwEGAEIACYWIQSZtb5lS26b
cvhRtNmTbe2LLOwBpQUCXw45HgIbIAUJCWYBgAAKCRCTbe2LLOwBpZzsEACm9HWs
TK2GrlmvecBtdg7Y/dGMIjO9XTtCQ6AzR0wYGIRXnyt4fSBzIhxgcDNyrp/TLrrd
7vp4dkIDbRW991aC/yK7eoo6MgPcpgUmdOViJCRW1mDuuXfnmZPfQmsk6kr4KEBP
2+XR66Kz+evDx15T7378WaNyQ+LGKL6lfrlRlg4YPJqnPjmQ7Zf8BN+3dI97n5SS
a6h5mHryPpZt4MiPYvT41cXax9XMpmBDJTAgscL01jSkOXPQNi/SLjd/bCktyqe2
gfKKPQXozasfGV5siGR0SC7RQefZkm0/uUZp0y3N/tZNpjLhbGkayqZS5yZMg02O
G/hEibUQF7nPlOKGTlvjnDNY9T1RBpjZxyL2OpxgaWP56pA2/fL3CpT+HduuuIzu
5zGjtFtxxbEjosR7LFA1W8sItHZpN0pER24l60ZtibdAKGPAIkdl6l1be9gopIQv
Zm/vq/PB5tPyLk4hBP26A/fC4W/jol9HI/S5VO2ziW475EjkFXTklllkVoP9J84E
JdqGSOg3kstbkPl9TlrJJ3b9rmYyIbb07HVreB/BVp3cGBxdKukSmTanspftG8Ij
Vp9CAWefbrMu82WF9qGKmO4yaAxsqU09CTB2bDrTmLpwCVxpHS1nST0M4OmiCOdy
qCVCWa+H/Pev226LSn2PVKK5AlBbs6uSNx/Phg==
=8Fyj
-----END PGP PUBLIC KEY BLOCK-----