Move profiles from ./profile-config to ./profile
This commit is contained in:
parent
79b05be7d3
commit
566643e195
|
@ -8,6 +8,7 @@
|
|||
./groups.nix
|
||||
./hosts.nix
|
||||
./networks.nix
|
||||
./profile.nix
|
||||
./sites.nix
|
||||
./users.nix
|
||||
./wireless-networks.nix
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
hardware.bluetooth.enable = false;
|
||||
|
||||
network = {
|
||||
networking = {
|
||||
macvlans = {
|
||||
intif0 = {
|
||||
interface = "enp4s0f1";
|
||||
|
|
|
@ -10,10 +10,17 @@ let
|
|||
host-fqdn = "${hostname}.${domain-name}";
|
||||
mail-hostname = "mail.fudo.org";
|
||||
|
||||
france-secrets = config.fudo.secrets.host-secrets.france;
|
||||
secrets = config.fudo.secrets.host-secrets.france;
|
||||
secret-files = config.fudo.secrets.files;
|
||||
|
||||
acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem";
|
||||
acme-certificate = hostname: "/var/lib/acme/${hostname}/fullchain.pem";
|
||||
letsencrypt-full-chain = name: chain: pkgs.stdenv.mkDerivation {
|
||||
name = "${name}-letsencrypt-full-chain.pem";
|
||||
phases = "installPhase";
|
||||
installPhase = ''
|
||||
cat ${chain} > $out
|
||||
cat ${pkgs.letsencrypt-ca}/ca.pem >> $out
|
||||
'';
|
||||
};
|
||||
|
||||
in {
|
||||
imports = let
|
||||
|
@ -28,9 +35,66 @@ in {
|
|||
in nix-files ./france;
|
||||
|
||||
config = {
|
||||
security.acme.email = "admin@fudo.org";
|
||||
|
||||
fudo = {
|
||||
hosts.france.external-interfaces = [ "extif0" ];
|
||||
|
||||
acme.host-domains.france."france.fudo.org" = {
|
||||
email = "admin@fudo.org";
|
||||
local-copies = {
|
||||
postgres = {
|
||||
user = config.services.postgresql.user;
|
||||
};
|
||||
openldap = {
|
||||
user = config.services.openldap.user;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
secrets.host-secrets.${hostname} = let
|
||||
ldap-user = config.services.openldap.user;
|
||||
ldap-group = config.services.openldap.group;
|
||||
in {
|
||||
ldap-ssl-certificate = {
|
||||
source-file = cfg.ssl-certificate;
|
||||
target-file = "/run/openldap/ssl-certificate.pem";
|
||||
user = ldap-user;
|
||||
group = ldap-group;
|
||||
permissions = "0444";
|
||||
};
|
||||
ldap-ssl-private-key = {
|
||||
source-file = cfg.ssl-private-key;
|
||||
target-file = "/run/openldap/ssl-private-key.pem";
|
||||
user = ldap-user;
|
||||
group = ldap-group;
|
||||
};
|
||||
ldap-ssl-ca-certificate = {
|
||||
source-file = cfg.ssl-ca-certificate;
|
||||
target-file = "/run/openldap/ssl-ca-certificate.pem";
|
||||
user = ldap-user;
|
||||
group = ldap-group;
|
||||
permissions = "0444";
|
||||
};
|
||||
ldap-keytab = {
|
||||
source-file = secret-files.service-keytabs.france.ldap;
|
||||
target-file = "/run/openldap/ldap.keytab";
|
||||
user = ldap-user;
|
||||
group = ldap-group;
|
||||
};
|
||||
ldap-root-passwd = {
|
||||
source-file = passwd.random-passwd-file;
|
||||
target-file = "/run/openldap/root.passwd";
|
||||
user = ldap-user;
|
||||
group = ldap-group;
|
||||
};
|
||||
postgres-keytab = {
|
||||
source-file = secret-files.service-keytabs.france.postgres;
|
||||
target-file = "/run/postgres/postgres.keytab";
|
||||
user = config.services.postgresql.user;
|
||||
};
|
||||
};
|
||||
|
||||
client.dns = {
|
||||
enable = true;
|
||||
ipv4 = true;
|
||||
|
@ -40,16 +104,53 @@ in {
|
|||
};
|
||||
|
||||
france = {
|
||||
ldap = let
|
||||
cert-copy = config.fudo.acme.host-domains.france."france.fudo.org".local-copies.openldap;
|
||||
chain = "${letsencrypt-full-chain "openldap-france" cert-copy.chain}";
|
||||
in {
|
||||
ssl-certificate = cert-copy.certificate;
|
||||
ssl-private-key = cert-copy.private-key;
|
||||
ssl-ca-certificate = chain;
|
||||
keytab = secrets.ldap-keytab.target-file;
|
||||
root-password-file = secrets.ldap-root-passwd.target-file;
|
||||
};
|
||||
|
||||
kdc = {
|
||||
state-directory = "/state/kerberos";
|
||||
master-key-file = "";
|
||||
listen-ips = [ primary-ip "127.0.0.1" "127.0.1.1" "::1" ];
|
||||
};
|
||||
|
||||
jabber = {
|
||||
ldap-servers = [ "france.fudo.org" ];
|
||||
listen-ips = [ primary-ip ];
|
||||
};
|
||||
|
||||
backplane = {
|
||||
host-passwd-files = let
|
||||
hosts = attrNames config.fudo.hosts;
|
||||
in mapAttrs (hostname: hostOpts: hostOpts.backplane-password-file)
|
||||
config.fudo.hosts;
|
||||
service-passwd-files = genAttrs [ "dns" ]
|
||||
(service-name:
|
||||
lib.fudo.passwd.stablerandom-passwd-file
|
||||
"${service-name}-service-backplane-passwd"
|
||||
"${service-name}-service-backplane-passwd-${config.instance.build-seed}");
|
||||
};
|
||||
|
||||
backplane-server = {
|
||||
listen-ips = [ primary-ip ];
|
||||
};
|
||||
|
||||
mail = {
|
||||
mail-directory = "/state/mail-server/mail";
|
||||
state-directory = "/state/mail-server/var";
|
||||
mail-directory = "/srv/mail/mailboxes";
|
||||
state-directory = "/srv/mail/var";
|
||||
ldap-server-urls = [
|
||||
"ldap://france.fudo.org"
|
||||
];
|
||||
};
|
||||
|
||||
webmail = {
|
||||
# TODO: this is not using the database!
|
||||
mail-server = mail-hostname;
|
||||
database.hostname = "localhost";
|
||||
};
|
||||
|
@ -58,6 +159,15 @@ in {
|
|||
repository-directory = "/state/gitea/repo";
|
||||
state-directory = "/state/gitea/state";
|
||||
ssh.listen-ip = git-server-ip;
|
||||
database-host = "localhost";
|
||||
};
|
||||
|
||||
postgresql = let
|
||||
cert-copy = config.fudo.acme.host-domains.france."france.fudo.org".local-copies.postgres;
|
||||
in {
|
||||
keytab = secrets.postgres-keytab.target-file;
|
||||
ssl-certificate = cert-copy.certificate;
|
||||
ssl-private-key = cert-copy.private-key;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -71,6 +181,9 @@ in {
|
|||
};
|
||||
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
|
||||
interfaces = {
|
||||
intif0 = {
|
||||
ipv4.addresses = [{
|
||||
address = "192.168.11.1";
|
||||
|
@ -90,12 +203,13 @@ in {
|
|||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
nginx = {
|
||||
enable = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisations = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedProxySettings = true;
|
||||
|
||||
|
|
|
@ -7,83 +7,79 @@ let
|
|||
site-name = config.instance.local-site;
|
||||
fqdn = "${hostname}.${domain-name}";
|
||||
|
||||
secrets = config.fudo.secrets.host-secrets.france;
|
||||
|
||||
# same as genAttr, but takes back attrsets and merges them
|
||||
concatGenAttrs = lst: f:
|
||||
foldr (a0: a1: a0 // a1) {} (map f lst);
|
||||
|
||||
passwd = import ../../../lib/passwd.nix { inherit lib; };
|
||||
|
||||
secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||
|
||||
cfg = config.fudo.france;
|
||||
|
||||
in {
|
||||
options.france = with types; {
|
||||
options.fudo.france = with types; {
|
||||
ldap = {
|
||||
ssl-certificate = mkOption {
|
||||
type = path;
|
||||
type = str;
|
||||
description = "SSL certificate to use for the LDAP server.";
|
||||
};
|
||||
ssl-private-key = mkOption {
|
||||
type = path;
|
||||
type = str;
|
||||
description = "SSL private key to use for the LDAP server.";
|
||||
};
|
||||
ssl-ca-certificate = mkOption {
|
||||
type = path;
|
||||
type = str;
|
||||
description = "SSL certificate authority to use for the LDAP server.";
|
||||
};
|
||||
keytab = mkOption {
|
||||
type = str;
|
||||
description = "Path to the LDAP service keytab.";
|
||||
};
|
||||
root-password-file = mkOption {
|
||||
type = str;
|
||||
description = "Path to the file containing the LDAP root password.";
|
||||
};
|
||||
};
|
||||
|
||||
kdc = {
|
||||
state-directory = mkOption {
|
||||
type = str;
|
||||
description = "Path at which to store kerberos state.";
|
||||
default = "/state/kerberos";
|
||||
};
|
||||
|
||||
master-key-file = mkOption {
|
||||
type = str;
|
||||
description = "Heimdal database master key file.";
|
||||
};
|
||||
|
||||
listen-ips = mkOption {
|
||||
type = listOf str;
|
||||
description = "IP addresses on which to listen for connections.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
fudo = {
|
||||
secrets.host-secrets.${hostname} = {
|
||||
ldap-ssl-certificate = {
|
||||
source-file = cfg.ssl-certificate;
|
||||
target-file = "/var/run/ldap/ssl-certificate.pem";
|
||||
user = config.services.openldap.user;
|
||||
group = config.services.openldap.group;
|
||||
permissions = "0444";
|
||||
};
|
||||
ldap-ssl-private-key = {
|
||||
source-file = cfg.ssl-private-key;
|
||||
target-file = "/var/run/ldap/ssl-private-key.pem";
|
||||
user = config.services.openldap.user;
|
||||
group = config.services.openldap.group;
|
||||
permissions = "0400";
|
||||
};
|
||||
ldap-ssl-ca-certificate = {
|
||||
source-file = cfg.ssl-ca-certificate;
|
||||
target-file = "/var/run/ldap/ssl-ca-certificate.pem";
|
||||
user = config.services.openldap.user;
|
||||
group = config.services.openldap.group;
|
||||
permissions = "0400";
|
||||
};
|
||||
secrets.host-secrets.${hostname}.kdc-master-key = {
|
||||
source-file = cfg.kdc.master-key-file;
|
||||
target-file = "/run/kerberos/kdc/master.key";
|
||||
user = config.fudo.auth.kdc.user;
|
||||
};
|
||||
|
||||
auth = {
|
||||
ldap = {
|
||||
ldap-server = {
|
||||
enable = true;
|
||||
base = "dc=fudo,dc=org";
|
||||
organization = "Fudo";
|
||||
rootpw-file = secrets.ldap-root-passwd;
|
||||
rootpw-file = cfg.ldap.root-password-file;
|
||||
kerberos-host = fqdn;
|
||||
kerberos-keytab = secrets.ldap-keytab;
|
||||
|
||||
sslCert =
|
||||
secrets.ldap-ssl-certificate.target-file;
|
||||
sslKey =
|
||||
secrets.ldap-ssl-private-key.target-file;
|
||||
sslCACert =
|
||||
secrets.ldap-ssl-ca-certificate.target-file;
|
||||
kerberos-keytab = cfg.ldap.keytab;
|
||||
ssl-certificate = cfg.ldap.ssl-certificate;
|
||||
ssl-private-key = cfg.ldap.ssl-private-key;
|
||||
ssl-ca-certificate = cfg.ldap.ssl-ca-certificate;
|
||||
|
||||
listen-uris = [ "ldap:///" "ldaps:///" "ldapi:///" ];
|
||||
|
||||
|
@ -95,9 +91,9 @@ in {
|
|||
# TODO: let build hosts create keys?
|
||||
kdc = {
|
||||
enable = true;
|
||||
realm = config.domains.${domain-name}.gssapi-realm;
|
||||
state-directory = cfg.state-directory;
|
||||
master-key-file = cfg.master-key-file;
|
||||
realm = config.fudo.domains.${domain-name}.gssapi-realm;
|
||||
state-directory = cfg.kdc.state-directory;
|
||||
master-key-file = secrets.kdc-master-key.target-file;
|
||||
acl = let
|
||||
admin-entries = concatGenAttrs
|
||||
config.instance.local-admins
|
||||
|
@ -109,7 +105,7 @@ in {
|
|||
"host/*.fudo.org" = { perms = [ "add" ]; };
|
||||
"pam_migrate/*.fudo.org" = { perms = [ "add" "change-password" ]; };
|
||||
} // admin-entries;
|
||||
bind-addresses = [ primary-ip "127.0.0.1" "127.0.1.1" "::1" ];
|
||||
bind-addresses = cfg.kdc.listen-ips;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
hostname = config.instance.hostname;
|
||||
timestamp = config.instance.build-timestamp;
|
||||
domain = config.instance.local-domain;
|
||||
|
||||
powerdns-user = "backplane-powerdns";
|
||||
backplane-dns-user = "backplane-dns";
|
||||
|
||||
generate-role-passwd = role:
|
||||
lib.fudo.passwd.stablerandom-password-file
|
||||
"backplane-${role}-password"
|
||||
"${hostname}-${domain}-${role}-password-${config.instance.build-timestamp}";
|
||||
|
||||
powerdns-password = generate-role-passwd "powerdns-db";
|
||||
|
||||
backplane-dns-xmpp-password = generate-role-passwd "backplane-dns-xmpp";
|
||||
|
||||
backplane-dns-db-password = generate-role-passwd "backplane-dns-db";
|
||||
|
||||
secrets = config.fudo.secrets.host-secrets.france;
|
||||
|
||||
cfg = config.fudo.france.backplane-server;
|
||||
|
||||
in {
|
||||
options.fudo.france.backplane-server = with types; {
|
||||
listen-ips = mkOption {
|
||||
type = listOf str;
|
||||
description = "List of IPs on which to listen for incoming backplane connections.";
|
||||
};
|
||||
|
||||
listen-ipv6s = mkOption {
|
||||
type = listOf str;
|
||||
description = "List of IPv6s on which to listen for incoming backplane connections.";
|
||||
default = [];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
users = {
|
||||
users = {
|
||||
${powerdns-user} = {
|
||||
isSystemUser = true;
|
||||
};
|
||||
${backplane-dns-user} = {
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
|
||||
groups = {
|
||||
${powerdns-user} = {
|
||||
members = [ powerdns-user ];
|
||||
};
|
||||
${backplane-dns-user} = {
|
||||
members = [ backplane-dns-user ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fudo = {
|
||||
secrets.host-secrets.france = {
|
||||
powerdns-password = {
|
||||
source-file = powerdns-password;
|
||||
target-file = "/run/backplane/dns/powerdns/db.passwd";
|
||||
user = config.fudo.backplane.dns.database.user;
|
||||
};
|
||||
|
||||
backplane-dns-db-password = {
|
||||
source-file = backplane-dns-db-password;
|
||||
target-file = "/run/backplane/dns/db.passwd";
|
||||
user = config.fudo.backplane.dns.backplane.user;
|
||||
};
|
||||
|
||||
backplane-dns-xmpp-password = {
|
||||
source-file = backplane-dns-db-password;
|
||||
target-file = "/run/backplane/dns/xmpp.passwd";
|
||||
user = config.fudo.backplane.dns.backplane.user;
|
||||
};
|
||||
};
|
||||
|
||||
postgresql = {
|
||||
enable = true;
|
||||
required-services = [ "fudo-passwords.target" ];
|
||||
|
||||
users = {
|
||||
${powerdns-user} = {
|
||||
password-file = secrets.powerdns-password.target-file;
|
||||
databases = {
|
||||
backplane_dns = {
|
||||
access = "CONNECT";
|
||||
entity-access = {
|
||||
"ALL TABLES IN SCHEMA public" = "SELECT,INSERT,UPDATE,DELETE";
|
||||
"ALL SEQUENCES IN SCHEMA public" = "SELECT,UPDATE";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
${backplane-dns-user} = {
|
||||
password-file = secrets.backplane-dns-db-password;
|
||||
databases = {
|
||||
backplane_dns = {
|
||||
access = "CONNECT";
|
||||
entity-access = {
|
||||
"ALL TABLES IN SCHEMA public" = "SELECT,INSERT,UPDATE,DELETE";
|
||||
"ALL SEQUENCES IN SCHEMA public" = "SELECT,UPDATE";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
databases = {
|
||||
backplane_dns = {
|
||||
users = ["niten"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
backplane.dns = {
|
||||
enable = true;
|
||||
listen-v4-addresses = cfg.listen-ips;
|
||||
listen-v6-addresses = cfg.listen-ipv6s;
|
||||
user = backplane-dns-user;
|
||||
group = backplane-dns-user;
|
||||
database = {
|
||||
username = powerdns-user;
|
||||
database = "backplane_dns";
|
||||
# Uses an IP to avoid cyclical dependency...
|
||||
host = "127.0.0.1";
|
||||
password-file = secrets.powerdns-password.target-file;
|
||||
};
|
||||
backplane = {
|
||||
host = "backplane.fudo.org";
|
||||
role = "service-dns";
|
||||
password-file = secrets.backplane-dns-xmpp-password.target-file;
|
||||
database = {
|
||||
username = backplane-dns-user;
|
||||
database = backplane-dns-user;
|
||||
host = "127.0.0.1";
|
||||
password-file = secrets.backplane-dns-db-password.target-file;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -7,14 +7,16 @@ let
|
|||
|
||||
secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||
|
||||
cfg = config.fudo.france.git;
|
||||
|
||||
sshOpts = { ... }: {
|
||||
options = {
|
||||
options = with types; {
|
||||
listen-ip = mkOption {
|
||||
type = str;
|
||||
description = "IP address on which to listen for SSH connections.";
|
||||
};
|
||||
listen-port = mkOption {
|
||||
type = str;
|
||||
type = port;
|
||||
description = "Port on which to listen for SSH connections.";
|
||||
default = 22;
|
||||
};
|
||||
|
@ -23,7 +25,7 @@ let
|
|||
|
||||
|
||||
in {
|
||||
options.france.git = with types; {
|
||||
options.fudo.france.git = with types; {
|
||||
repository-directory = mkOption {
|
||||
type = str;
|
||||
description = "Path to store git repositories.";
|
||||
|
@ -43,6 +45,14 @@ in {
|
|||
};
|
||||
|
||||
config.fudo = {
|
||||
secrets.host-secrets.${hostname}.git-database-password = {
|
||||
source-file = lib.fudo.passwd.stablerandom-passwd-file
|
||||
"gitea-database-passwd"
|
||||
"${hostname}-gitea-database-passwd-${config.instance.build-seed}";
|
||||
target-file = "/var/gitea/database.passwd";
|
||||
user = config.services.gitea.user;
|
||||
};
|
||||
|
||||
postgresql = {
|
||||
databases.fudo_git.users =
|
||||
config.instance.local_admins;
|
||||
|
|
|
@ -5,23 +5,107 @@ let
|
|||
hostname = config.instance.hostname;
|
||||
secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||
|
||||
cfg = config.fudo.france;
|
||||
|
||||
generate-auth-file = name: files: let
|
||||
make-entry = name: passwd-file:
|
||||
''("${name}" . "${readFile passwd-file}")'';
|
||||
entries = mapAttrsToList make-entry files;
|
||||
content = concatStringsSep "\n" entries;
|
||||
in writeText "${name}-backplane-auth.scm" "'(${content})'";
|
||||
|
||||
host-auth-file = generate-auth-file "host" cfg.host-passwd-files;
|
||||
service-auth-file = generate-auth-filre "service" cfg.service-passwd-files;
|
||||
|
||||
ldap-password-file =
|
||||
lib.fudo.passwd.random-passwd-file "ejabberd-ldap-auth-user";
|
||||
|
||||
ldap-hashed-password =
|
||||
hash-ldap-passwd "ejabberd-ldap-hashed-passwd" ldap-password-file;
|
||||
|
||||
in {
|
||||
options.fudo.france = with types; {
|
||||
jabber = {
|
||||
ldap-user = mkOption {
|
||||
type = str;
|
||||
description = "System user as which to authenticate to LDAP.";
|
||||
default = "ejabberd";
|
||||
};
|
||||
|
||||
ldap-servers = mkOption {
|
||||
type = listOf str;
|
||||
description = "LDAP servers to use for user authentication.";
|
||||
};
|
||||
|
||||
listen-ips = mkOption {
|
||||
type = listOf str;
|
||||
description = "IPs on which to listen for incoming connections.";
|
||||
};
|
||||
};
|
||||
|
||||
backplane = {
|
||||
host-passwd-files = mkOption {
|
||||
type = attrsOf str;
|
||||
description = "Map of hostname to password file, for backplane host authentication.";
|
||||
default = {};
|
||||
};
|
||||
|
||||
service-passwd-files = mkOption {
|
||||
type = attrsOf str;
|
||||
description = "Map of service to password file, for backplane service authentication.";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
fudo = {
|
||||
system-users.${cfg.jabber.ldap-user} = {
|
||||
description = "ejabberd authentication user.";
|
||||
hashed-password = ldap-hashed-password;
|
||||
};
|
||||
|
||||
secrets.host-secrets.${hostname} = let
|
||||
user = config.services.ejabberd.user;
|
||||
in {
|
||||
host-auth = {
|
||||
source-file = host-auth-file;
|
||||
target-file = "/run/backplane/host-auth-file.scm";
|
||||
user = user;
|
||||
};
|
||||
service-auth = {
|
||||
source-file = service-auth-file;
|
||||
target-file = "/run/backplane/service-auth-file.scm";
|
||||
user = user;
|
||||
};
|
||||
ldap-password = {
|
||||
source-file = ldap-password-file;
|
||||
target-file = "/run/ejabberd/ldap.passwd";
|
||||
user = user;
|
||||
};
|
||||
};
|
||||
|
||||
jabber = {
|
||||
enable = true;
|
||||
|
||||
listen-ips = cfg.jabber.listen-ips;
|
||||
|
||||
environment = {
|
||||
FUDO_HOST_PASSWD_FILE = secrets.host-auth.target-file;
|
||||
FUDO_SERVICE_PASSWD_FILE = secrets.service-auth.target-file;
|
||||
};
|
||||
|
||||
secret-files = {
|
||||
LDAP_PASSWORD = secrets.jabber-ldap-password.target-file;
|
||||
LDAP_PASSWORD = secrets.ldap-password.target-file;
|
||||
};
|
||||
|
||||
sites = {
|
||||
"fudo.im" = {
|
||||
site-config = {
|
||||
auth_method = "ldap";
|
||||
ldap_servers = [ "auth.fudo.org" ];
|
||||
ldap_servers = cfg.jabber.ldap-servers;
|
||||
ldap_port = 389;
|
||||
ldap_rootdn = "cn=jabber,dc=fudo,dc=org";
|
||||
ldap_rootdn = "cn=${cfg.jabber.ldap-user},dc=fudo,dc=org";
|
||||
ldap_password = ''"LDAP_PASSWD"'';
|
||||
ldap_base = "ou=members,dc=fudo,dc=org";
|
||||
ldap_filter = "(objectClass=posixAccount)";
|
||||
|
@ -69,7 +153,7 @@ in {
|
|||
"backplane.fudo.org" = {
|
||||
site-config = {
|
||||
auth_method = "external";
|
||||
extauth_program = "${pkgs.guile}/bin/guile -s ${backplane-auth}";
|
||||
extauth_program = "${pkgs.guile}/bin/guile -s ${pkgs.backplane-auth}/backplane-auth.scm";
|
||||
extauth_pool_size = 3;
|
||||
auth_use_cache = true;
|
||||
|
||||
|
@ -100,7 +184,6 @@ in {
|
|||
mod_time = {};
|
||||
mod_version = {};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ let
|
|||
|
||||
mail-reader-dn = "mail-auth-reader";
|
||||
in {
|
||||
options.france.mail = with types; {
|
||||
options.fudo.france.mail = with types; {
|
||||
mail-directory = mkOption {
|
||||
type = str;
|
||||
description = "Directory to contain user maildirs.";
|
||||
|
@ -39,16 +39,19 @@ in {
|
|||
enableContainer = true;
|
||||
monitoring = true;
|
||||
|
||||
hostname = "mail.${domain-name}";
|
||||
domain = domain-name;
|
||||
mail-hostname = "mail.${domain-name}";
|
||||
|
||||
state-directory = cfg.state-directory;
|
||||
mail-directory = cfg.mail-directory;
|
||||
|
||||
dovecot.ldap = {
|
||||
reader-dn = "cn=mail-reader-dn,${config.fudo.auth.ldap.base}";
|
||||
dovecot = {
|
||||
ldap = {
|
||||
reader-dn = "cn=${mail-reader-dn},${config.fudo.auth.ldap.base}";
|
||||
reader-password-file = secrets.mail-reader-passwd.target-file;
|
||||
server-urls = cfg.ldap-server-urls;
|
||||
};
|
||||
};
|
||||
|
||||
state-directory = cfg.state-directory;
|
||||
mail-directory = cfg.mail-directory;
|
||||
|
||||
clamav.enable = true;
|
||||
dkim.signing = true;
|
||||
|
|
|
@ -5,14 +5,28 @@ let
|
|||
hostname = config.instance.hostname;
|
||||
secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||
in {
|
||||
options.fudo.france.postgresql = with types; {
|
||||
ssl-certificate = mkOption {
|
||||
type = str;
|
||||
description = "SSL certificate to use for the LDAP server.";
|
||||
};
|
||||
ssl-private-key = mkOption {
|
||||
type = str;
|
||||
description = "SSL private key to use for the LDAP server.";
|
||||
};
|
||||
keytab = mkOption {
|
||||
type = path;
|
||||
description = "Postgres service keytab.";
|
||||
};
|
||||
};
|
||||
|
||||
config.fudo.postgresql = {
|
||||
enable = true;
|
||||
|
||||
local-networks = config.instance.local-networks;
|
||||
admin-users = config.instance.admin-users;
|
||||
|
||||
ssl-private-key = secrets.postgres-ssl-key;
|
||||
ssl-certificate = secrets.postgres-ssl-certificate;
|
||||
keytab = secrets.postgres-keytab.target-file;
|
||||
ssl-private-key = cfg.ssl-private-key;
|
||||
ssl-certificate = cfg.ssl-certificate;
|
||||
keytab = cfg.keytab;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ let
|
|||
db-passwd = pkgs.lib.fudo.passwd.random-passwd-file "webmail" 40;
|
||||
|
||||
in {
|
||||
options.france.webmail = with types; {
|
||||
options.fudo.france.webmail = with types; {
|
||||
mail-server = mkOption {
|
||||
type = str;
|
||||
description = "Mail server to use for webmail.";
|
||||
|
|
|
@ -22,6 +22,8 @@ let
|
|||
|
||||
secrets = config.fudo.secrets.host-secrets.procul;
|
||||
|
||||
passwd = pkgs.lib.fudo.passwd;
|
||||
|
||||
in {
|
||||
networking = {
|
||||
dhcpcd.enable = false;
|
||||
|
@ -85,75 +87,17 @@ in {
|
|||
fudo = {
|
||||
hosts.procul.external-interfaces = [ "extif0" ];
|
||||
|
||||
jabber = {
|
||||
enable = true;
|
||||
|
||||
secret-files = {
|
||||
SECRET = secrets.jabber-ldap-password.traget-file;
|
||||
};
|
||||
|
||||
sites."informis.land" = {
|
||||
site-config = {
|
||||
auth_method = "ldap";
|
||||
ldap_servers = [ "auth.fudo.org" ];
|
||||
ldap_port = 636;
|
||||
ldap_rootdn = "cn=jabber,dc=fudo,dc=org";
|
||||
ldap_password = ''"LDAP_PASSWD"'';
|
||||
ldap_base = "ou=members,dc=fudo,dc=org";
|
||||
ldap_filter = "(objectClass=posixAccount)";
|
||||
ldap_uids = { uid = "%u"; };
|
||||
|
||||
modules = {
|
||||
mod_adhoc = {};
|
||||
mod_announce = {};
|
||||
mod_avatar = {};
|
||||
mod_blocking = {};
|
||||
mod_caps = {};
|
||||
mod_carboncopy = {};
|
||||
mod_client_state = {};
|
||||
mod_configure = {};
|
||||
mod_disco = {};
|
||||
mod_fail2ban = {};
|
||||
mod_last = {};
|
||||
mod_offline = {
|
||||
access_max_user_messages = 5000;
|
||||
};
|
||||
mod_ping = {};
|
||||
mod_privacy = {};
|
||||
mod_private = {};
|
||||
mod_pubsub = {
|
||||
access_createnode = "pubsub_createnode";
|
||||
ignore_pep_from_offline = true;
|
||||
last_item_cache = false;
|
||||
plugins = [
|
||||
"flat"
|
||||
"pep"
|
||||
];
|
||||
};
|
||||
mod_roster = {};
|
||||
mod_stream_mgmt = {};
|
||||
mod_time = {};
|
||||
mod_vcard = {
|
||||
search = false;
|
||||
};
|
||||
mod_vcard_xupdate = {};
|
||||
mod_version = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
secrets.host-secrets.procul = let
|
||||
secrets = config.fudo.secrets.files;
|
||||
files = config.fudo.secrets.files;
|
||||
in {
|
||||
postgres-keytab = {
|
||||
source-file = secrets.service-keytabs.procul.postgres;
|
||||
source-file = files.service-keytabs.procul.postgres;
|
||||
target-file = "/srv/postgres/secure/postgres.keytab";
|
||||
user = "root";
|
||||
};
|
||||
|
||||
gitea-database-password = {
|
||||
source-file = secrets.service-passwords.procul.gitea-database;
|
||||
source-file = files.service-passwords.procul.gitea-database;
|
||||
target-file = "/srv/gitea/secure/database.passwd";
|
||||
user = config.fudo.git.user;
|
||||
};
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
syslib = pkgs.callPackage ../lib/hosts.nix {};
|
||||
|
||||
in {
|
||||
config.fudo.hosts = syslib.base-host-config ./hosts;
|
||||
config.fudo.hosts = let
|
||||
build-seed = config.instance.build-seed;
|
||||
base-config = syslib.base-host-config ./hosts;
|
||||
in mapAttrs (hostname: base-config:
|
||||
base-config // {
|
||||
backplane-password-file =
|
||||
pkgs.lib.fudo.passwd.stablerandom-passwd-file
|
||||
"${hostname}-host-backplane-passwd"
|
||||
"${hostname}-host-backplane-passwd-${build-seed}";
|
||||
}) base-config;
|
||||
}
|
||||
|
|
|
@ -1,140 +1,4 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
hostname = config.instance.hostname;
|
||||
enable-gui = config.fudo.hosts.${hostname}.enable-gui;
|
||||
|
||||
in {
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
boot.plymouth.enable = false;
|
||||
|
||||
boot.tmpOnTmpfs = true;
|
||||
|
||||
environment = mkIf enable-gui {
|
||||
systemPackages = [
|
||||
#libva
|
||||
];
|
||||
};
|
||||
|
||||
# We're deploying via nixops, this is just annoying
|
||||
system = { autoUpgrade.enable = false; };
|
||||
|
||||
services = {
|
||||
xserver = mkIf enable-gui {
|
||||
enable = true;
|
||||
|
||||
desktopManager.gnome.enable = true;
|
||||
|
||||
displayManager.gdm = {
|
||||
enable = true;
|
||||
wayland = false;
|
||||
};
|
||||
|
||||
windowManager.stumpwm.enable = true;
|
||||
|
||||
# windowManager.session = pkgs.lib.singleton {
|
||||
# name = "stumpwm";
|
||||
# start = ''
|
||||
# ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
|
||||
# waidPID=$!
|
||||
# '';
|
||||
# };
|
||||
};
|
||||
|
||||
trezord.enable = true;
|
||||
};
|
||||
|
||||
hardware = {
|
||||
bluetooth.enable = true;
|
||||
|
||||
opengl = mkIf enable-gui {
|
||||
enable = true;
|
||||
driSupport = true;
|
||||
driSupport32Bit = true;
|
||||
};
|
||||
};
|
||||
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio = {
|
||||
enable = true;
|
||||
support32Bit = config.hardware.pulseaudio.enable;
|
||||
};
|
||||
|
||||
console.font =
|
||||
lib.mkDefault "${pkgs.terminus_font}/share/consolefonts/ter-g18n.psf.gz";
|
||||
|
||||
services.gnome = mkIf enable-gui {
|
||||
evolution-data-server.enable = mkForce false;
|
||||
gnome-user-share.enable = mkForce false;
|
||||
};
|
||||
|
||||
services.flatpak.enable = enable-gui;
|
||||
|
||||
# programs.steam.enable = enable-gui;
|
||||
|
||||
fonts = mkIf enable-gui {
|
||||
fontDir.enable = true;
|
||||
fontconfig.enable = true;
|
||||
#fontconfig.antialias = true;
|
||||
#fontconfig.penultimate.enable = true;
|
||||
#fontconfig.subpixel.lcdfilter = "default";
|
||||
|
||||
fonts = with pkgs; [
|
||||
cantarell_fonts
|
||||
dejavu_fonts
|
||||
dina-font
|
||||
dosemu_fonts
|
||||
fira-code
|
||||
fira-code-symbols
|
||||
freefont_ttf
|
||||
liberation_ttf
|
||||
mplus-outline-fonts
|
||||
nerdfonts
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
noto-fonts-emoji
|
||||
proggyfonts
|
||||
terminus_font
|
||||
ubuntu_font_family
|
||||
ucsFonts
|
||||
ultimate-oldschool-pc-font-pack
|
||||
unifont
|
||||
xorg.fontadobe100dpi
|
||||
xorg.fontadobe75dpi
|
||||
xorg.fontadobeutopia100dpi
|
||||
xorg.fontadobeutopia75dpi
|
||||
xorg.fontadobeutopiatype1
|
||||
xorg.fontarabicmisc
|
||||
xorg.fontbh100dpi
|
||||
xorg.fontbh75dpi
|
||||
xorg.fontbhlucidatypewriter100dpi
|
||||
xorg.fontbhlucidatypewriter75dpi
|
||||
xorg.fontbhttf
|
||||
xorg.fontbhtype1
|
||||
xorg.fontbitstream100dpi
|
||||
xorg.fontbitstream75dpi
|
||||
xorg.fontbitstreamtype1
|
||||
xorg.fontcronyxcyrillic
|
||||
xorg.fontcursormisc
|
||||
xorg.fontdaewoomisc
|
||||
xorg.fontdecmisc
|
||||
xorg.fontibmtype1
|
||||
xorg.fontisasmisc
|
||||
xorg.fontjismisc
|
||||
xorg.fontmicromisc
|
||||
xorg.fontmisccyrillic
|
||||
xorg.fontmiscethiopic
|
||||
xorg.fontmiscmeltho
|
||||
xorg.fontmiscmisc
|
||||
xorg.fontmuttmisc
|
||||
xorg.fontschumachermisc
|
||||
xorg.fontscreencyrillic
|
||||
xorg.fontsonymisc
|
||||
xorg.fontsunmisc
|
||||
xorg.fontwinitzkicyrillic
|
||||
xorg.fontxfree86type1
|
||||
];
|
||||
};
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,142 +1,5 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
# Available to all users on the system. Keep it minimal.
|
||||
global-packages = with pkgs; [
|
||||
bind
|
||||
cryptsetup
|
||||
git
|
||||
heimdal
|
||||
openssh_gssapi
|
||||
tldr
|
||||
vim
|
||||
wget
|
||||
];
|
||||
|
||||
in {
|
||||
environment = {
|
||||
etc.nixos-live.source = ../../.;
|
||||
|
||||
systemPackages = global-packages;
|
||||
|
||||
# shellInit = ''
|
||||
# ${pkgs.gnupg}/bin/gpg-connect-agent /bye
|
||||
# export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
|
||||
# '';
|
||||
};
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
};
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
security.acme.acceptTerms = true;
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
krb5 = {
|
||||
enable = true;
|
||||
|
||||
appdefaults = {
|
||||
forwardable = true;
|
||||
proxiable = true;
|
||||
encrypt = true;
|
||||
forward = true;
|
||||
};
|
||||
|
||||
libdefaults = {
|
||||
allow_weak_crypto = true;
|
||||
dns_lookup_kdc = true;
|
||||
dns_lookup_realm = true;
|
||||
forwardable = true;
|
||||
proxiable = true;
|
||||
};
|
||||
|
||||
kerberos = pkgs.heimdalFull;
|
||||
};
|
||||
|
||||
services = {
|
||||
openssh = {
|
||||
enable = true;
|
||||
startWhenNeeded = true;
|
||||
useDns = true;
|
||||
permitRootLogin = "prohibit-password";
|
||||
extraConfig = ''
|
||||
GSSAPIAuthentication yes
|
||||
GSSAPICleanupCredentials yes
|
||||
GSSAPIKeyExchange yes
|
||||
GSSAPIStoreCredentialsOnRekey yes
|
||||
'';
|
||||
};
|
||||
|
||||
fail2ban =
|
||||
let domain-name = config.fudo.hosts.${config.instance.hostname}.domain;
|
||||
in {
|
||||
enable = config.networking.firewall.enable;
|
||||
bantime-increment.enable = true;
|
||||
ignoreIP = config.fudo.domains.${domain-name}.local-networks;
|
||||
};
|
||||
|
||||
xserver = {
|
||||
layout = "us";
|
||||
xkbVariant = "dvp";
|
||||
xkbOptions = "ctrl:nocaps";
|
||||
};
|
||||
|
||||
# pcscd.enable = true;
|
||||
# udev.packages = with pkgs; [ yubikey-personalization ];
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
# Allow mosh connections if the firewall is enabled
|
||||
allowedUDPPortRanges = [{
|
||||
from = 60000;
|
||||
to = 60100;
|
||||
}];
|
||||
};
|
||||
|
||||
console.useXkbConfig = true;
|
||||
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
programs = {
|
||||
mosh.enable = true;
|
||||
|
||||
bash.enableCompletion = true;
|
||||
|
||||
fish.enable = true;
|
||||
|
||||
gnupg.agent = {
|
||||
enable = true;
|
||||
# enableSSHSupport = true;
|
||||
# pinentryFlavor = if cfg.enable-gui then "gnome3" else "curses";
|
||||
};
|
||||
|
||||
ssh = {
|
||||
startAgent = true;
|
||||
|
||||
package = pkgs.openssh_gssapi;
|
||||
|
||||
extraConfig = ''
|
||||
GSSAPIAuthentication yes
|
||||
GSSAPIDelegateCredentials yes
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
security.pam = {
|
||||
enableSSHAgentAuth = true;
|
||||
|
||||
services = {
|
||||
sshd = {
|
||||
makeHomeDir = true;
|
||||
sshAgentAuth = true;
|
||||
# This isn't supposed to ask for a code unless ~/.google_authenticator exists...but it does
|
||||
# googleAuthenticator.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib; {
|
||||
imports = [ ./common-ui.nix ];
|
||||
|
||||
config = { networking = { networkmanager.enable = mkForce false; }; };
|
||||
}
|
||||
|
|
|
@ -2,31 +2,4 @@
|
|||
|
||||
with lib;
|
||||
{
|
||||
imports = [ ./common-ui.nix ];
|
||||
|
||||
options.fudo.profile.laptop = {
|
||||
use-network-manager =
|
||||
mkEnableOption "Use NetworkManager instead of wpa_supplicant.";
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
environment.systemPackages = with pkgs; [ acpi upower wpa_supplicant ];
|
||||
|
||||
networking = if (config.fudo.profile.laptop.use-network-manager) then {
|
||||
networkmanager.enable = true;
|
||||
} else {
|
||||
networkmanager.enable = false;
|
||||
wireless = {
|
||||
enable = true;
|
||||
userControlled = {
|
||||
enable = true;
|
||||
group = "wheel";
|
||||
};
|
||||
networks = mapAttrs (network: networkOpts: {
|
||||
psk = networkOpts.key;
|
||||
}) config.fudo.wireless-networks;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,75 +1,5 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
serverPackages = with pkgs; [ emacs-nox reboot-if-necessary test-config ];
|
||||
|
||||
reboot-if-necessary = pkgs.writeShellScriptBin "reboot-if-necessary" ''
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "FAILED: no sync file provided."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WALL=${pkgs.utillinux}/bin/wall
|
||||
|
||||
if [ -f $1 ]; then
|
||||
$WALL "$1 exists, rebooting system"
|
||||
${pkgs.systemd}/bin/reboot
|
||||
else
|
||||
$WALL "$1 does not exist, switching config."
|
||||
nixos-rebuild switch
|
||||
fi
|
||||
|
||||
exit 0
|
||||
'';
|
||||
|
||||
test-config = pkgs.writeShellScriptBin "fudo-test-config" ''
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "usage: $0 [timeout]"
|
||||
exit 1
|
||||
elif [ $# -eq 1 ]; then
|
||||
TIMEOUT=$1
|
||||
else
|
||||
TIMEOUT=15m
|
||||
fi
|
||||
|
||||
SYNCFILE=$TMP/sync-$(date +"%Y%m%d-%H%M%N")
|
||||
touch $SYNCFILE
|
||||
${pkgs.utillinux}/bin/wall "Launching config. System will restart in $TIMEOUT if $SYNCFILE still exists."
|
||||
systemd-run --on-active=$TIMEOUT ${reboot-if-necessary} $SYNCFILE
|
||||
nixos-rebuild test
|
||||
|
||||
exit 0
|
||||
'';
|
||||
|
||||
in {
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
config = {
|
||||
environment = { systemPackages = serverPackages; };
|
||||
|
||||
system.autoUpgrade.enable = false;
|
||||
|
||||
networking.networkmanager.enable = mkForce false;
|
||||
|
||||
services = { xserver.enable = false; };
|
||||
|
||||
sound.enable = false;
|
||||
hardware.pulseaudio.enable = false;
|
||||
|
||||
powerManagement =
|
||||
if config.fudo.hosts.${config.instance.hostname}.keep-cool then {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "ondemand";
|
||||
} else {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
hibernate.enable = false;
|
||||
hybrid-sleep.enable = false;
|
||||
};
|
||||
};
|
||||
{
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
hostname = config.instance.hostname;
|
||||
enable-gui = config.fudo.hosts.${hostname}.enable-gui;
|
||||
|
||||
in {
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
boot = {
|
||||
plymouth.enable = false;
|
||||
tmpOnTmpfs = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
xserver = mkIf enable-gui {
|
||||
enable = true;
|
||||
|
||||
desktopManager.gnome.enable = true;
|
||||
|
||||
displayManager.gdm = {
|
||||
enable = true;
|
||||
wayland = false;
|
||||
autoSuspend = false;
|
||||
};
|
||||
|
||||
windowManager.stumpwm.enable = true;
|
||||
|
||||
# windowManager.session = pkgs.lib.singleton {
|
||||
# name = "stumpwm";
|
||||
# start = ''
|
||||
# ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
|
||||
# waidPID=$!
|
||||
# '';
|
||||
# };
|
||||
};
|
||||
|
||||
trezord.enable = true;
|
||||
};
|
||||
|
||||
hardware = {
|
||||
bluetooth.enable = true;
|
||||
|
||||
opengl = mkIf enable-gui {
|
||||
enable = true;
|
||||
driSupport = true;
|
||||
driSupport32Bit = true;
|
||||
};
|
||||
};
|
||||
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio = {
|
||||
enable = true;
|
||||
support32Bit = config.hardware.pulseaudio.enable;
|
||||
};
|
||||
|
||||
# console.font =
|
||||
# lib.mkDefault "${pkgs.terminus_font}/share/consolefonts/ter-g18n.psf.gz";
|
||||
|
||||
services.gnome = mkIf enable-gui {
|
||||
evolution-data-server.enable = mkForce false;
|
||||
gnome-user-share.enable = mkForce false;
|
||||
};
|
||||
|
||||
services.flatpak.enable = enable-gui;
|
||||
|
||||
fonts = mkIf enable-gui {
|
||||
fontDir.enable = true;
|
||||
fontconfig.enable = true;
|
||||
#fontconfig.antialias = true;
|
||||
#fontconfig.penultimate.enable = true;
|
||||
#fontconfig.subpixel.lcdfilter = "default";
|
||||
|
||||
fonts = with pkgs; [
|
||||
cantarell_fonts
|
||||
dejavu_fonts
|
||||
dina-font
|
||||
dosemu_fonts
|
||||
fira-code
|
||||
fira-code-symbols
|
||||
freefont_ttf
|
||||
liberation_ttf
|
||||
mplus-outline-fonts
|
||||
nerdfonts
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
noto-fonts-emoji
|
||||
proggyfonts
|
||||
terminus_font
|
||||
ubuntu_font_family
|
||||
ucsFonts
|
||||
ultimate-oldschool-pc-font-pack
|
||||
unifont
|
||||
xorg.fontadobe100dpi
|
||||
xorg.fontadobe75dpi
|
||||
xorg.fontadobeutopia100dpi
|
||||
xorg.fontadobeutopia75dpi
|
||||
xorg.fontadobeutopiatype1
|
||||
xorg.fontarabicmisc
|
||||
xorg.fontbh100dpi
|
||||
xorg.fontbh75dpi
|
||||
xorg.fontbhlucidatypewriter100dpi
|
||||
xorg.fontbhlucidatypewriter75dpi
|
||||
xorg.fontbhttf
|
||||
xorg.fontbhtype1
|
||||
xorg.fontbitstream100dpi
|
||||
xorg.fontbitstream75dpi
|
||||
xorg.fontbitstreamtype1
|
||||
xorg.fontcronyxcyrillic
|
||||
xorg.fontcursormisc
|
||||
xorg.fontdaewoomisc
|
||||
xorg.fontdecmisc
|
||||
xorg.fontibmtype1
|
||||
xorg.fontisasmisc
|
||||
xorg.fontjismisc
|
||||
xorg.fontmicromisc
|
||||
xorg.fontmisccyrillic
|
||||
xorg.fontmiscethiopic
|
||||
xorg.fontmiscmeltho
|
||||
xorg.fontmiscmisc
|
||||
xorg.fontmuttmisc
|
||||
xorg.fontschumachermisc
|
||||
xorg.fontscreencyrillic
|
||||
xorg.fontsonymisc
|
||||
xorg.fontsunmisc
|
||||
xorg.fontwinitzkicyrillic
|
||||
xorg.fontxfree86type1
|
||||
];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
# Available to all users on the system. Keep it minimal.
|
||||
global-packages = with pkgs; [
|
||||
bind
|
||||
cryptsetup
|
||||
git
|
||||
heimdal
|
||||
openssh_gssapi
|
||||
tldr
|
||||
vim
|
||||
wget
|
||||
];
|
||||
|
||||
in {
|
||||
environment = {
|
||||
etc.nixos-live.source = ../../.;
|
||||
|
||||
systemPackages = global-packages;
|
||||
|
||||
# shellInit = ''
|
||||
# ${pkgs.gnupg}/bin/gpg-connect-agent /bye
|
||||
# export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
|
||||
# '';
|
||||
};
|
||||
|
||||
system.autoUpgrade.enable = false;
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
};
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
security.acme.acceptTerms = true;
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
krb5 = {
|
||||
enable = true;
|
||||
|
||||
appdefaults = {
|
||||
forwardable = true;
|
||||
proxiable = true;
|
||||
encrypt = true;
|
||||
forward = true;
|
||||
};
|
||||
|
||||
libdefaults = {
|
||||
allow_weak_crypto = true;
|
||||
dns_lookup_kdc = true;
|
||||
dns_lookup_realm = true;
|
||||
forwardable = true;
|
||||
proxiable = true;
|
||||
};
|
||||
|
||||
kerberos = pkgs.heimdalFull;
|
||||
};
|
||||
|
||||
services = {
|
||||
openssh = {
|
||||
enable = true;
|
||||
startWhenNeeded = true;
|
||||
useDns = true;
|
||||
permitRootLogin = "prohibit-password";
|
||||
extraConfig = ''
|
||||
GSSAPIAuthentication yes
|
||||
GSSAPICleanupCredentials yes
|
||||
GSSAPIKeyExchange yes
|
||||
GSSAPIStoreCredentialsOnRekey yes
|
||||
'';
|
||||
};
|
||||
|
||||
fail2ban = let
|
||||
domain-name = config.fudo.hosts.${config.instance.hostname}.domain;
|
||||
in {
|
||||
enable = config.networking.firewall.enable;
|
||||
bantime-increment.enable = true;
|
||||
ignoreIP = config.instance.local-networks;
|
||||
};
|
||||
|
||||
xserver = {
|
||||
layout = "us";
|
||||
xkbVariant = "dvp";
|
||||
xkbOptions = "ctrl:nocaps";
|
||||
};
|
||||
|
||||
# pcscd.enable = true;
|
||||
# udev.packages = with pkgs; [ yubikey-personalization ];
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
# Allow mosh connections if the firewall is enabled
|
||||
allowedUDPPortRanges = [{
|
||||
from = 60000;
|
||||
to = 60100;
|
||||
}];
|
||||
};
|
||||
|
||||
console.useXkbConfig = true;
|
||||
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
programs = {
|
||||
mosh.enable = true;
|
||||
|
||||
bash.enableCompletion = true;
|
||||
|
||||
fish.enable = true;
|
||||
|
||||
gnupg.agent = {
|
||||
enable = true;
|
||||
# enableSSHSupport = true;
|
||||
# pinentryFlavor = if cfg.enable-gui then "gnome3" else "curses";
|
||||
};
|
||||
|
||||
ssh = {
|
||||
startAgent = true;
|
||||
|
||||
package = pkgs.openssh_gssapi;
|
||||
|
||||
extraConfig = ''
|
||||
GSSAPIAuthentication yes
|
||||
GSSAPIDelegateCredentials yes
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
security.pam = {
|
||||
enableSSHAgentAuth = true;
|
||||
|
||||
services = {
|
||||
sshd = {
|
||||
makeHomeDir = true;
|
||||
sshAgentAuth = true;
|
||||
# This isn't supposed to ask for a code unless ~/.google_authenticator exists...but it does
|
||||
# googleAuthenticator.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
imports = [ ./common-ui.nix ];
|
||||
|
||||
config = {
|
||||
networking.networkmanager.enable = mkForce false;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
imports = [ ./common-ui.nix ];
|
||||
|
||||
options.fudo.profile.laptop = {
|
||||
use-network-manager =
|
||||
mkEnableOption "Use NetworkManager instead of wpa_supplicant.";
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
environment.systemPackages = with pkgs; [ acpi upower wpa_supplicant ];
|
||||
|
||||
networking = if (config.fudo.profile.laptop.use-network-manager) then {
|
||||
networkmanager.enable = true;
|
||||
} else {
|
||||
networkmanager.enable = false;
|
||||
wireless = {
|
||||
enable = true;
|
||||
userControlled = {
|
||||
enable = true;
|
||||
group = "wheel";
|
||||
};
|
||||
networks = mapAttrs (network: networkOpts: {
|
||||
psk = networkOpts.key;
|
||||
}) config.fudo.wireless-networks;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
reboot-if-necessary = pkgs.writeShellScriptBin "reboot-if-necessary" ''
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "FAILED: no sync file provided."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WALL=${pkgs.utillinux}/bin/wall
|
||||
|
||||
if [ -f $1 ]; then
|
||||
$WALL "$1 exists, rebooting system"
|
||||
${pkgs.systemd}/bin/reboot
|
||||
else
|
||||
$WALL "$1 does not exist, switching config."
|
||||
nixos-rebuild switch
|
||||
fi
|
||||
|
||||
exit 0
|
||||
'';
|
||||
|
||||
test-config = pkgs.writeShellScriptBin "fudo-test-config" ''
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "usage: $0 [timeout]"
|
||||
exit 1
|
||||
elif [ $# -eq 1 ]; then
|
||||
TIMEOUT=$1
|
||||
else
|
||||
TIMEOUT=15m
|
||||
fi
|
||||
|
||||
SYNCFILE=$TMP/sync-$(date +"%Y%m%d-%H%M%N")
|
||||
touch $SYNCFILE
|
||||
${pkgs.utillinux}/bin/wall "Launching config. System will restart in $TIMEOUT if $SYNCFILE still exists."
|
||||
systemd-run --on-active=$TIMEOUT ${reboot-if-necessary} $SYNCFILE
|
||||
nixos-rebuild test
|
||||
|
||||
exit 0
|
||||
'';
|
||||
|
||||
in {
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
config = {
|
||||
environment = {
|
||||
serverPackages = with pkgs;
|
||||
[ emacs-nox reboot-if-necessary test-config ];
|
||||
};
|
||||
|
||||
networking.networkmanager.enable = mkForce false;
|
||||
|
||||
services.xserver.enable = false;
|
||||
|
||||
sound.enable = false;
|
||||
hardware.pulseaudio.enable = false;
|
||||
|
||||
powerManagement =
|
||||
if config.fudo.hosts.${config.instance.hostname}.keep-cool then {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "ondemand";
|
||||
} else {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
hibernate.enable = false;
|
||||
hybrid-sleep.enable = false;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -38,29 +38,31 @@ in {
|
|||
options = [ "comment=systemd.automount" ];
|
||||
};
|
||||
|
||||
# NOTE: these are pointing directly to nostromo so the krb lookup works
|
||||
"/net/documents" = {
|
||||
device = "sea-store.sea.fudo.org:/export/documents";
|
||||
device = "nostromo.sea.fudo.org:/export/documents";
|
||||
fsType = "nfs4";
|
||||
options = [ "comment=systemd.automount" "sec=krb5p" ];
|
||||
options = [ "comment=systemd.automount" "sec=krb5p" "proto=tcp" ];
|
||||
};
|
||||
"/net/downloads" = {
|
||||
device = "sea-store.sea.fudo.org:/export/downloads";
|
||||
device = "nostromo.sea.fudo.org:/export/downloads";
|
||||
fsType = "nfs4";
|
||||
options = [ "comment=systemd.automount" "sec=krb5i" ];
|
||||
options = [ "comment=systemd.automount" "sec=krb5i" "proto=tcp" ];
|
||||
};
|
||||
"/net/projects" = {
|
||||
device = "sea-store.sea.fudo.org:/export/projects";
|
||||
device = "nostromo.sea.fudo.org:/export/projects";
|
||||
fsType = "nfs4";
|
||||
options = [ "comment=systemd.automount" "sec=krb5p" ];
|
||||
options = [ "comment=systemd.automount" "sec=krb5p" "proto=tcp" ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
"d /net/documents - root sea-documents - -"
|
||||
"d /net/downloads - root sea-downloads - -"
|
||||
"d /net/projects - root sea-projects - -"
|
||||
];
|
||||
## This fails if the filesystems already exist
|
||||
# tmpfiles.rules = [
|
||||
# "d /net/documents - root sea-documents - -"
|
||||
# "d /net/downloads - root sea-downloads - -"
|
||||
# "d /net/projects - root sea-projects - -"
|
||||
# ];
|
||||
|
||||
# mounts = [
|
||||
# {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
{
|
||||
replicator = {
|
||||
description = "Database Replicator";
|
||||
hashed-password = "{SHA}HpiRMyxLR+0ZFHz/COvG9lcNYyQ=";
|
||||
};
|
||||
|
||||
auth_reader = {
|
||||
description = "System Authenticator";
|
||||
hashed-password = "{MD5}N36/kQ64mev1HARddvVk7Q==";
|
||||
};
|
||||
|
||||
user_db_reader = {
|
||||
description = "User Database Reader";
|
||||
hashed-password = "{SSHA}IVKhrB+wMOCI/CCzbJW8sNDbH67ZTMBv";
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{ hostname, site, domain, profile, build-timestamp, ... }:
|
||||
{ lib, pkgs, hostname, site, domain, profile, build-timestamp, ... }:
|
||||
|
||||
let
|
||||
# Get info on this host so we know what to load
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ lib, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with pkgs.lib;
|
||||
let
|
||||
join-lines = concatStringsSep "\n";
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
{ lib, ... }:
|
||||
|
||||
let
|
||||
ip = import ./ip.nix { inherit lib; };
|
||||
dns = import ./dns.nix { inherit lib; };
|
||||
passwd = import ./passwd.nix { inherit lib; };
|
||||
in
|
||||
# NOTE: OBSOLETE! See overlay.nix
|
||||
|
||||
{
|
||||
lib.overlays = [
|
||||
(final: prev:
|
||||
prev.lib // {
|
||||
fudo = {
|
||||
inherit ip dns passwd;
|
||||
fudo = let
|
||||
lib = prev.lib;
|
||||
in {
|
||||
ip = import ./ip.nix { inherit lib; };
|
||||
dns = import ./dns.nix { inherit lib; };
|
||||
passwd = import ./passwd.nix { inherit lib; };
|
||||
lisp = import ./lisp.nix { inherit lib; };
|
||||
};
|
||||
})
|
||||
];
|
||||
|
|
|
@ -30,7 +30,9 @@ let
|
|||
# };
|
||||
# };
|
||||
|
||||
domainOpts = { domain, ... }: {
|
||||
domainOpts = { name, ... }: let
|
||||
domain = name;
|
||||
in {
|
||||
options = with types; {
|
||||
email = mkOption {
|
||||
type = str;
|
||||
|
@ -45,8 +47,12 @@ let
|
|||
};
|
||||
|
||||
local-copies = let
|
||||
localCopyOpts = { copy, ... }: {
|
||||
options = with types; {
|
||||
localCopyOpts = { name, ... }: let
|
||||
copy = name;
|
||||
in {
|
||||
options = with types; let
|
||||
target-path = "/var/run/${domain}/${copy}";
|
||||
in {
|
||||
user = mkOption {
|
||||
type = str;
|
||||
description = "User to which this copy belongs.";
|
||||
|
@ -58,17 +64,35 @@ let
|
|||
default = null;
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = str;
|
||||
description = "Path at which to store the local copy.";
|
||||
default = "/var/run/${domain}/${copy}";
|
||||
};
|
||||
|
||||
service = mkOption {
|
||||
type = str;
|
||||
description = "systemd job to copy certs.";
|
||||
default = "fudo-${domain}-${copy}-certs.service";
|
||||
};
|
||||
|
||||
certificate = mkOption {
|
||||
type = str;
|
||||
description = "Full path to the local copy certificate.";
|
||||
default = "${target-path}/cert.pem";
|
||||
};
|
||||
|
||||
full-certificate = mkOption {
|
||||
type = str;
|
||||
description = "Full path to the local copy certificate.";
|
||||
default = "${target-path}/fullchain.pem";
|
||||
};
|
||||
|
||||
chain = mkOption {
|
||||
type = str;
|
||||
description = "Full path to the local copy certificate.";
|
||||
default = "${target-path}/chain.pem";
|
||||
};
|
||||
|
||||
private-key = mkOption {
|
||||
type = str;
|
||||
description = "Full path to the local copy certificate.";
|
||||
default = "${target-path}/key.pem";
|
||||
};
|
||||
};
|
||||
};
|
||||
in mkOption {
|
||||
|
@ -92,7 +116,7 @@ let
|
|||
cfg.host-domains.${hostname} else {};
|
||||
|
||||
optionalStringOr = str: default:
|
||||
if cond then str else default;
|
||||
if (str != null) then str else default;
|
||||
|
||||
in {
|
||||
options.fudo.acme = with types; {
|
||||
|
@ -113,26 +137,41 @@ in {
|
|||
tmpfiles.rules = let
|
||||
copies = concatMapAttrs (domain: domainOpts:
|
||||
domainOpts.local-copies) localDomains;
|
||||
perms = copyOpts: if (copyOpts.group != null) then "0550" else "0500";
|
||||
copy-paths = mapAttrsToList (copy: copyOpts:
|
||||
"D '${path}' 0550 ${copyOpts.user} ${optionalStringOr copyOpts.group "-"} - -")
|
||||
copies;
|
||||
in copy-paths;
|
||||
let
|
||||
dir-entry = copyOpts: file: "D '${dirOf file}' ${perms copyOpts} ${copyOpts.user} ${optionalStringOr copyOpts.group "-"} - -";
|
||||
in map (dir-entry copyOpts) [
|
||||
copyOpts.certificate
|
||||
copyOpts.full-certificate
|
||||
copyOpts.chain
|
||||
copyOpts.private-key
|
||||
]) copies;
|
||||
in unique copy-paths;
|
||||
|
||||
# TODO: Make this a Fudo service?
|
||||
services = concatMapAttrs (domain: domainOpts:
|
||||
mapAttrs' (copy: copyOpts: let
|
||||
key-perms = copyOpts: if (copyOpts.group != null) then "0440" else "0400";
|
||||
source = config.security.acme.certs.${domain}.directory;
|
||||
target = copyOpts.path;
|
||||
install-certs = pkgs.writeShellScript "fudo-install-${domain}-${site}-certs.sh" ''
|
||||
for cert in cert chain fullchain full key; do
|
||||
cp ${source}/$cert.pem ${target}/$cert.pem
|
||||
chmod 0440 ${source}/$cert.pem
|
||||
done
|
||||
install-certs = pkgs.writeShellScript "fudo-install-${domain}-${copy}-certs.sh" ''
|
||||
cp cert.pem ${copyOpts.certificate}
|
||||
chmod 0444 ${copyOpts.certificate}
|
||||
|
||||
cp full.pem ${copyOpts.full-certificate}
|
||||
chmod 0444 ${copyOpts.full-certificate}
|
||||
|
||||
cp chain.pem ${copyOpts.chain}
|
||||
chmod 0444 ${copyOpts.chain}
|
||||
|
||||
cp key.pem ${copyOpts.private-key}
|
||||
chmod ${key-perms copyOpts} ${copyOpts.private-key}
|
||||
'';
|
||||
remove-certs = pkgs.writeShellScript "fudo-remove-${domain}-${site}-certs.sh" ''
|
||||
for cert in cert chain fullchain full key; do
|
||||
rm -rf ${target}/$cert.pem
|
||||
done
|
||||
remove-certs = pkgs.writeShellScript "fudo-remove-${domain}-${copy}-certs.sh" ''
|
||||
rm -f ${copyOpts.private-key}
|
||||
rm -f ${copyOpts.chainy}
|
||||
rm -f ${copyOpts.full-certificate}
|
||||
rm -f ${copyOpts.certificate}
|
||||
'';
|
||||
in nameValuePair
|
||||
(rm-service-ext copyOpts.service) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{ ... }:
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
imports = [
|
||||
./dns.nix
|
||||
|
|
|
@ -1,63 +1,10 @@
|
|||
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.fudo.backplane.dns;
|
||||
|
||||
lisp-pkgs = with pkgs.localLispPackages; [
|
||||
arrows
|
||||
backplane-dns
|
||||
backplane-server
|
||||
cl-sasl
|
||||
cl-xmpp
|
||||
ip-utils
|
||||
|
||||
alexandria
|
||||
babel
|
||||
bordeaux-threads
|
||||
cffi
|
||||
cl-base64
|
||||
cl-json
|
||||
cl-postgres
|
||||
cl-ppcre
|
||||
cl-unicode
|
||||
cl_plus_ssl
|
||||
closer-mop
|
||||
closure-common
|
||||
cxml
|
||||
flexi-streams
|
||||
global-vars
|
||||
introspect-environment
|
||||
ironclad
|
||||
iterate
|
||||
lisp-namespace
|
||||
md5
|
||||
nibbles
|
||||
postmodern
|
||||
puri
|
||||
s-sql
|
||||
split-sequence
|
||||
trivia
|
||||
trivia_dot_balland2006
|
||||
trivia_dot_level0
|
||||
trivia_dot_level1
|
||||
trivia_dot_level2
|
||||
trivia_dot_trivial
|
||||
trivial-cltl2
|
||||
trivial-features
|
||||
trivial-garbage
|
||||
trivial-gray-streams
|
||||
type-i
|
||||
uax-15
|
||||
usocket
|
||||
];
|
||||
|
||||
backup-directory = "/var/lib/fudo/backplane/dns";
|
||||
|
||||
powerdns-home = "/var/lib/powerdns";
|
||||
|
||||
powerdns-conf-dir = "${powerdns-home}/conf.d";
|
||||
powerdns-conf-dir = "${cfg.powerdns-home}/conf.d";
|
||||
|
||||
backplaneOpts = { ... }: {
|
||||
options = {
|
||||
|
@ -117,53 +64,59 @@ let
|
|||
};
|
||||
|
||||
in {
|
||||
options.fudo.backplane.dns = {
|
||||
options.fudo.backplane.dns = with types; {
|
||||
enable = mkEnableOption "Enable backplane dynamic DNS server.";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
type = port;
|
||||
description = "Port on which to serve authoritative DNS requests.";
|
||||
default = 53;
|
||||
};
|
||||
|
||||
listen-v4-addresses = mkOption {
|
||||
type = with types; listOf str;
|
||||
type = listOf str;
|
||||
description = "IPv4 addresses on which to listen for dns requests.";
|
||||
default = [ "0.0.0.0" ];
|
||||
};
|
||||
|
||||
listen-v6-addresses = mkOption {
|
||||
type = with types; listOf str;
|
||||
type = listOf str;
|
||||
description = "IPv6 addresses on which to listen for dns requests.";
|
||||
example = [ "[abcd::1]" ];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
required-services = mkOption {
|
||||
type = with types; listOf str;
|
||||
type = listOf str;
|
||||
description =
|
||||
"A list of services required before the DNS server can start.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
type = str;
|
||||
description = "User as which to run DNS backplane listener service.";
|
||||
default = "backplane-dns";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
type = str;
|
||||
description = "Group as which to run DNS backplane listener service.";
|
||||
default = "backplane-dns";
|
||||
};
|
||||
|
||||
database = mkOption {
|
||||
type = with types; submodule databaseOpts;
|
||||
type = submodule databaseOpts;
|
||||
description = "Database settings for the DNS server.";
|
||||
};
|
||||
|
||||
powerdns-home = mkOption {
|
||||
type = str;
|
||||
description = "Directory at which to store powerdns configuration and state.";
|
||||
default = "/run/backplane-dns/powerdns";
|
||||
};
|
||||
|
||||
backplane = mkOption {
|
||||
type = with types; submodule backplaneOpts;
|
||||
type = submodule backplaneOpts;
|
||||
description = "Backplane Jabber settings for the DNS server.";
|
||||
};
|
||||
};
|
||||
|
@ -177,7 +130,11 @@ in {
|
|||
createHome = true;
|
||||
home = "/var/home/${cfg.user}";
|
||||
};
|
||||
backplane-powerdns = { isSystemUser = true; };
|
||||
backplane-powerdns = {
|
||||
isSystemUser = true;
|
||||
home = cfg.powerdns-home;
|
||||
createHome = true;
|
||||
};
|
||||
};
|
||||
|
||||
groups = {
|
||||
|
@ -186,65 +143,17 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
targets = {
|
||||
backplane-dns = {
|
||||
description = "Fudo DNS backplane services.";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
|
||||
backplane-powerdns = let
|
||||
configDir = pkgs.writeTextDir "pdns.conf" ''
|
||||
local-address=${lib.concatStringsSep ", " cfg.listen-v4-addresses}
|
||||
local-ipv6=${lib.concatStringsSep ", " cfg.listen-v6-addresses}
|
||||
local-port=${toString cfg.port}
|
||||
launch=
|
||||
include-dir=${powerdns-conf-dir}/
|
||||
'';
|
||||
|
||||
psql-user = config.services.postgresql.superUser;
|
||||
|
||||
in {
|
||||
unitConfig.Documentation = "man:pdns_server(1) man:pdns_control(1)";
|
||||
description = "Backplane PowerDNS name server";
|
||||
requires = [
|
||||
"postgresql.service"
|
||||
"backplane-dns-config-generator.service"
|
||||
"backplane-dns.target"
|
||||
];
|
||||
after = [ "network.target" "postgresql.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = with pkgs; [ postgresql ];
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10";
|
||||
StartLimitInterval = "0";
|
||||
PrivateDevices = true;
|
||||
# CapabilityBoundingSet="CAP_CHOWN CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT";
|
||||
# NoNewPrivileges=true;
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${powerdns-home}";
|
||||
ExecStart =
|
||||
"${pkgs.powerdns}/bin/pdns_server --setuid=backplane-powerdns --setgid=backplane-powerdns --chroot=${powerdns-home} --socket-dir=/ --daemon=no --guardian=no --disable-syslog --write-pid=no --config-dir=${configDir}";
|
||||
ProtectSystem = "full";
|
||||
# ProtectHome=true;
|
||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
};
|
||||
};
|
||||
|
||||
backplane-dns-config-generator = {
|
||||
fudo.system.services = {
|
||||
backplane-powerdns-config-generator = {
|
||||
description =
|
||||
"Generate postgres configuration for backplane DNS server.";
|
||||
requiredBy = [ "backplane-powerdns.service" ];
|
||||
requires = cfg.required-services;
|
||||
serviceConfig.Type = "oneshot";
|
||||
type = "oneshot";
|
||||
restartIfChanged = true;
|
||||
partOf = [ "backplane-dns.target" ];
|
||||
|
||||
readWritePaths = [ powerdns-conf-dir ];
|
||||
|
||||
preStart = ''
|
||||
mkdir -p ${powerdns-conf-dir}
|
||||
chown backplane-powerdns:backplane-powerdns ${powerdns-conf-dir}
|
||||
|
@ -277,30 +186,42 @@ in {
|
|||
echo "gpgsql-dnssec=yes" >> $TMPCONF
|
||||
|
||||
mv $TMPCONF ${powerdns-conf-dir}/pdns.local.gpgsql.conf
|
||||
|
||||
rm -rf $TMPDIR
|
||||
|
||||
exit 0
|
||||
'';
|
||||
};
|
||||
|
||||
backplane-powerdns = let
|
||||
pdns-config-dir = pkgs.writeTextDir "pdns.conf" ''
|
||||
local-address=${lib.concatStringsSep ", " cfg.listen-v4-addresses}
|
||||
local-ipv6=${lib.concatStringsSep ", " cfg.listen-v6-addresses}
|
||||
local-port=${toString cfg.port}
|
||||
launch=
|
||||
include-dir=${powerdns-conf-dir}/
|
||||
'';
|
||||
in {
|
||||
description = "Backplane PowerDNS name server";
|
||||
requires = [
|
||||
"postgresql.service"
|
||||
"backplane-powerdns-config-generator.service"
|
||||
];
|
||||
after = [ "network.target" ];
|
||||
path = with pkgs; [ powerdns postgresql ];
|
||||
execStart = "pdns_server --setuid=backplane-powerdns --setgid=backplane-powerdns --chroot=${cfg.powerdns-home} --socket-dir=/ --daemon=no --guardian=no --disable-syslog --write-pid=no --config-dir=${pdns-config-dir}";
|
||||
};
|
||||
|
||||
backplane-dns = {
|
||||
description = "Fudo DNS Backplane Server";
|
||||
restartIfChanged = true;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
"${pkgs.backplane-dns-server}/bin/launch-backplane-dns.sh";
|
||||
Restart = "on-failure";
|
||||
PIDFile = "/run/backplane-dns.$USERNAME.pid";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StandardOutput = "journal";
|
||||
};
|
||||
|
||||
path = with pkgs; [ backplane-dns-server ];
|
||||
execStart = "launch-backplane-dns.sh";
|
||||
pidFile = "/run/backplane-dns.$USERNAME.pid";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
partOf = [ "backplane-dns.target" ];
|
||||
requires = [ "postgresql.service" ];
|
||||
environment = {
|
||||
# LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib";
|
||||
|
||||
FUDO_DNS_BACKPLANE_XMPP_HOSTNAME = cfg.backplane.host;
|
||||
FUDO_DNS_BACKPLANE_XMPP_USERNAME = cfg.backplane.role;
|
||||
FUDO_DNS_BACKPLANE_XMPP_PASSWORD_FILE = cfg.backplane.password-file;
|
||||
|
@ -311,15 +232,18 @@ in {
|
|||
FUDO_DNS_BACKPLANE_DATABASE_PASSWORD_FILE =
|
||||
cfg.backplane.database.password-file;
|
||||
|
||||
# CL_SOURCE_REGISTRY = "${pkgs.localLispPackages.backplane-dns}//";
|
||||
|
||||
CL_SOURCE_REGISTRY =
|
||||
lib.concatStringsSep ":" (map (pkg: "${pkg}//") lisp-pkgs);
|
||||
pkgs.lib.fudo.lisp.lisp-source-registry pkgs.backplane-dns-server;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
requires = cfg.required-services;
|
||||
partOf = [ "backplane-dns.target" ];
|
||||
systemd = {
|
||||
targets = {
|
||||
backplane-dns = {
|
||||
description = "Fudo DNS backplane services.";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requries = cfg.required-services ++ [ "postgresql.service" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -108,7 +108,7 @@ in {
|
|||
enable = true;
|
||||
appName = cfg.site-name;
|
||||
database = {
|
||||
createDatabase = true;
|
||||
createDatabase = false;
|
||||
host = cfg.database.hostname;
|
||||
name = cfg.database.name;
|
||||
user = cfg.database.user;
|
||||
|
|
|
@ -34,8 +34,9 @@ in {
|
|||
systemd = {
|
||||
# Ensure the mountpoints exist
|
||||
tmpfiles.rules = let
|
||||
mpPerms = mpOpts: if mpOpts.world-readable then "755" else "750";
|
||||
mountpointToPath = mp: mpOpts:
|
||||
"d '${mp}' 750 root ${optionalOrDefault mpOpts.group "-"} - -";
|
||||
"d '${mp}' ${mpPerms mpOpts} root ${optionalOrDefault mpOpts.group "-"} - -";
|
||||
filesystemsToMountpointLists = mapAttrsToList
|
||||
(fs: fsOpts: fsOpts.mountpoints);
|
||||
mountpointListsToPaths = concatMap
|
||||
|
|
|
@ -6,6 +6,10 @@ let
|
|||
|
||||
host = import ../types/host.nix { inherit lib; };
|
||||
|
||||
hostname = config.instance.hostname;
|
||||
|
||||
host-secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||
|
||||
in {
|
||||
options.fudo.hosts = with types;
|
||||
mkOption {
|
||||
|
@ -73,6 +77,8 @@ in {
|
|||
config.environment.systemPackages;
|
||||
sorted-unique = sort lessThan (unique packages);
|
||||
in concatStringsSep "\n" sorted-unique;
|
||||
|
||||
build-timestamp.text = toString config.instance.build-timestamp;
|
||||
};
|
||||
|
||||
systemPackages = with pkgs;
|
||||
|
@ -103,10 +109,6 @@ in {
|
|||
(keypair: keypair.private-key)
|
||||
(try-attr hostname files.build-keypairs);
|
||||
|
||||
backplane-passwd-source = try-attr hostname files.backplane-passwords;
|
||||
|
||||
backplane-passwd-target = "/var/run/backplane/passwd";
|
||||
|
||||
in {
|
||||
secrets.host-secrets.${hostname} = {
|
||||
host-keytab = mkIf (keytab-file != null) {
|
||||
|
@ -121,15 +123,15 @@ in {
|
|||
user = "root";
|
||||
};
|
||||
|
||||
backplane-passwd = mkIf (backplane-passwd-source != null) {
|
||||
source-file = backplane-passwd-source;
|
||||
target-file = backplane-passwd-target;
|
||||
backplane-passwd = {
|
||||
source-file = host-cfg.backplane-password-file;
|
||||
target-file = "/run/backplane/client/passwd";
|
||||
user = config.fudo.client.dns.user;
|
||||
};
|
||||
};
|
||||
|
||||
client.dns.password-file = mkIf (backplane-passwd-source != null)
|
||||
backplane-passwd-target;
|
||||
client.dns.password-file =
|
||||
host-secrets.backplane-passwd.target-file;
|
||||
};
|
||||
|
||||
programs.adb.enable = host-cfg.android-dev;
|
||||
|
|
|
@ -23,16 +23,16 @@ let
|
|||
foldr (a: b: a // b) {} (mapAttrs f attrs);
|
||||
|
||||
concatMapAttrsToList = f: attr:
|
||||
attrValues (concatMapAttrs f attr);
|
||||
concatMap (i: i) (attrValues (mapAttrs f attr));
|
||||
|
||||
host-domains = config.fudo.acme.host-domains.${hostname};
|
||||
|
||||
siteCerts = site: let
|
||||
certPath = host-domains.${site}.local-copies.ejabberd.path;
|
||||
cert-copy = host-domains.${site}.local-copies.ejabberd;
|
||||
in [
|
||||
"${certPath}/fullchain.pem"
|
||||
"${certPath}/privkey.pem"
|
||||
"${certPath}/chain.pem"
|
||||
cert-copy.certificate
|
||||
cert-copy.private-key
|
||||
cert-copy.chain
|
||||
];
|
||||
|
||||
siteCertService = site:
|
||||
|
@ -60,13 +60,13 @@ let
|
|||
|
||||
hosts = attrNames cfg.sites;
|
||||
|
||||
listen = [{
|
||||
listen = map (ip: {
|
||||
port = cfg.port;
|
||||
module = "ejabberd_c2s";
|
||||
ip = cfg.listen-ip;
|
||||
ip = ip;
|
||||
starttls = true;
|
||||
starttls_required = true;
|
||||
}];
|
||||
}) cfg.listen-ips;
|
||||
|
||||
certfiles = concatMapAttrsToList
|
||||
(site: siteOpts:
|
||||
|
@ -94,7 +94,6 @@ let
|
|||
swapper = concatStringsSep " | " secret-swappers;
|
||||
in pkgs.writeShellScript "ejabberd-generate-config.sh" ''
|
||||
cat ${template} | ${swapper} > ${target}
|
||||
chown ${cfg.user}:${cfg.group} ${target}
|
||||
'';
|
||||
|
||||
cfg = config.fudo.jabber;
|
||||
|
@ -103,6 +102,11 @@ in {
|
|||
options.fudo.jabber = with types; {
|
||||
enable = mkEnableOption "Enable ejabberd server.";
|
||||
|
||||
listen-ips = mkOption {
|
||||
type = listOf str;
|
||||
description = "IPs on which to listen for Jabber connections.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to listen for Jabber connections.";
|
||||
|
@ -122,7 +126,7 @@ in {
|
|||
};
|
||||
|
||||
admins = mkOption {
|
||||
type = str;
|
||||
type = listOf str;
|
||||
description = "List of admin users for the server.";
|
||||
default = [];
|
||||
};
|
||||
|
@ -141,7 +145,23 @@ in {
|
|||
config-file = mkOption {
|
||||
type = str;
|
||||
description = "Location at which to generate the configuration file.";
|
||||
default = "/var/run/ejabberd/ejabberd.yaml";
|
||||
default = "/run/ejabberd/ejabberd.yaml";
|
||||
};
|
||||
|
||||
log-level = mkOption {
|
||||
type = int;
|
||||
description = ''
|
||||
Log level at which to run the server.
|
||||
|
||||
See: https://docs.ejabberd.im/admin/guide/troubleshooting/
|
||||
'';
|
||||
default = 3;
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = attrsOf str;
|
||||
description = "Environment variables to set for the ejabberd daemon.";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -156,7 +176,8 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
fudo.acme.host-domains.${hostname} = mapAttrs (site: siteCfg:
|
||||
fudo = {
|
||||
acme.host-domains.${hostname} = mapAttrs (site: siteCfg:
|
||||
mkIf siteCfg.enableACME {
|
||||
local-copies.ejabberd = {
|
||||
user = cfg.user;
|
||||
|
@ -164,18 +185,41 @@ in {
|
|||
};
|
||||
}) cfg.sites;
|
||||
|
||||
system = let
|
||||
config-dir = dirOf cfg.config-file;
|
||||
in {
|
||||
ensure-directories.${config-dir} = {
|
||||
user = cfg.user;
|
||||
perms = "0700";
|
||||
};
|
||||
|
||||
services.ejabberd-config-generator = let
|
||||
config-generator =
|
||||
enter-secrets config-file-template cfg.secret-files cfg.config-file;
|
||||
in {
|
||||
script = "${config-generator}";
|
||||
readWritePaths = [ config-dir ];
|
||||
workingDirectory = config-dir;
|
||||
user = cfg.user;
|
||||
description = "Generate ejabberd config file with necessary passwords.";
|
||||
postStart = ''
|
||||
chown ${cfg.user} ${cfg.config-file}
|
||||
chmod 0400 ${cfg.config-file}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
"D '${dirOf cfg.config-file}' 0550 ${cfg.user} ${cfg.group} - -"
|
||||
];
|
||||
|
||||
services.ejabberd = let
|
||||
config-generator = enter-secrets config-file-template cfg.secret-files cfg.config-file;
|
||||
in {
|
||||
services = {
|
||||
ejabberd = {
|
||||
wants = map (site: siteCertService site) (attrNames cfg.sites);
|
||||
environment = cfg.secret-files;
|
||||
serviceConfig = {
|
||||
ExecStartPre = mkAfter "${config-generator}";
|
||||
requires = [ "ejabberd-config-generator.service" ];
|
||||
environment = cfg.environment;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -205,6 +205,7 @@ in {
|
|||
|
||||
ssl-ca-certificate = mkOption {
|
||||
type = with types; nullOr str;
|
||||
|
||||
description = ''
|
||||
The path to the SSL CA cert used to sign the certificate.
|
||||
'';
|
||||
|
@ -220,9 +221,8 @@ in {
|
|||
|
||||
base = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
The base dn of the LDAP server (eg. "dc=fudo,dc=org").
|
||||
'';
|
||||
description = "The base dn of the LDAP server.";
|
||||
example = "dc=fudo,dc=org";
|
||||
};
|
||||
|
||||
rootpw-file = mkOption {
|
||||
|
@ -239,7 +239,6 @@ in {
|
|||
A list of URIs on which the ldap server should listen.
|
||||
'';
|
||||
example = [ "ldap://auth.fudo.org" "ldaps://auth.fudo.org" ];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
users = mkOption {
|
||||
|
@ -295,12 +294,11 @@ in {
|
|||
etc = {
|
||||
"openldap/sasl2/slapd.conf" = {
|
||||
mode = "0400";
|
||||
user = "openldap";
|
||||
group = "openldap";
|
||||
# FIXME: take arguments!
|
||||
user = config.services.openldap.user;
|
||||
group = config.services.openldap.group;
|
||||
text = ''
|
||||
mech_list: gssapi external
|
||||
keytab: /etc/ldap/ldap.keytab
|
||||
keytab: ${cfg.kerberos-keytab}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
@ -343,72 +341,126 @@ in {
|
|||
rootdn = "cn=admin,${cfg.base}";
|
||||
rootpwFile = "${cfg.rootpw-file}";
|
||||
urlList = cfg.listen-uris;
|
||||
database = "mdb";
|
||||
|
||||
extraConfig = ''
|
||||
settings = let
|
||||
makeAccessLine = i: attrs: perm-map: let
|
||||
perm-strings = mapAttrs (dn: perm: "by ${dn} ${perm}") perm-map;
|
||||
perm-string = concatStringsSep " " perm-strings;
|
||||
in "${i}to ${attrs} ${perm-string}";
|
||||
|
||||
TLSCertificateFile ${cfg.ssl-certificate}
|
||||
TLSCertificateKeyFile ${cfg.ssl-private-key}
|
||||
${optionalString (cfg.ssl-ca-certificate != null)
|
||||
"TLSCACertificateFile ${cfg.ssl-ca-certificate}"}
|
||||
makeAccess = access-map: let
|
||||
pairs = mapAttrsToList (target: perm-map: [target perm-map]) access-map;
|
||||
in imap0 (i: pair: makeAccessLine i pair[0] pair[1]) pairs;
|
||||
|
||||
authz-regexp "^uid=auth/([^.]+)\.fudo\.org,cn=fudo\.org,cn=gssapi,cn=auth$" "cn=$1,ou=hosts,dc=fudo,dc=org"
|
||||
authz-regexp "^uid=[^,/]+/root,cn=fudo\.org,cn=gssapi,cn=auth$" "cn=admin,dc=fudo,dc=org"
|
||||
authz-regexp "^uid=([^,/]+),cn=fudo\.org,cn=gssapi,cn=auth$" "uid=$1,ou=members,dc=fudo,dc=org"
|
||||
authz-regexp "^uid=host/([^,/]+),cn=fudo\.org,cn=gssapi,cn=auth$" "cn=$1,ou=hosts,dc=fudo,dc=org"
|
||||
authz-regexp "^gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth$" "cn=admin,dc=fudo,dc=org"
|
||||
|
||||
'';
|
||||
|
||||
extraDatabaseConfig = ''
|
||||
# access to dn=base=""
|
||||
# by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
|
||||
# by * read
|
||||
|
||||
access to attrs=userPassword,shadowLastChange
|
||||
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
|
||||
by group.exact="cn=admin,ou=members,${cfg.base}" write
|
||||
by dn.exact="cn=auth_reader,${cfg.base}" read
|
||||
by dn.exact="cn=replicator,${cfg.base}" read
|
||||
by self write
|
||||
by * auth
|
||||
|
||||
access to dn.exact="cn=admin,ou=groups,${cfg.base}"
|
||||
by dn.exact="cn=admin,${cfg.base}" write
|
||||
by users read
|
||||
by * none
|
||||
|
||||
access to dn.subtree="ou=groups,${cfg.base}" attrs=memberUid
|
||||
by dn.regex="cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" write
|
||||
by group.exact="cn=admin,ou=groups,${cfg.base}" write
|
||||
by users read
|
||||
by * none
|
||||
|
||||
access to dn.subtree="ou=members,${cfg.base}" attrs=cn,sn,homeDirectory,loginShell,gecos,description,homeDirectory,uidNumber,gidNumber
|
||||
by group.exact="cn=admin,ou=groups,${cfg.base}" write
|
||||
by dn.exact="cn=user_db_reader,${cfg.base}" read
|
||||
by users read
|
||||
by * none
|
||||
|
||||
access to dn.exact="cn=admin,ou=groups,${cfg.base}"
|
||||
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
|
||||
by users read
|
||||
by * none
|
||||
|
||||
access to dn.subtree="ou=groups,${cfg.base}" attrs=memberUid
|
||||
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
|
||||
by dn.regex="cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" write
|
||||
by group.exact="cn=admin,ou=groups,${cfg.base}" write
|
||||
by users read
|
||||
by * none
|
||||
|
||||
access to *
|
||||
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
|
||||
by users read
|
||||
by * none
|
||||
|
||||
|
||||
index objectClass,uid eq
|
||||
'';
|
||||
in {
|
||||
attrs = {
|
||||
cn = "config";
|
||||
objectClass = "olcGlobal";
|
||||
olcPidFile = "/run/slapd/slapd.pid";
|
||||
olcTLSCertificateFile = cfg.ssl-certificate;
|
||||
olcTLSCertificateKeyFile = cfg.ssl-private-key;
|
||||
olcTLSCACertificateFile = cfg.ssl-ca-certificate;
|
||||
olcSaslSecProps = "noplain,noanonymous";
|
||||
olcAuthzRegexp = let
|
||||
authz-regex-entry = i: { regex, target}:
|
||||
"{${i}}\"${rx}\" \"${target}\"";
|
||||
in imap0 authz-regex-entry [
|
||||
{
|
||||
regex = "^uid=auth/([^.]+).fudo.org,cn=fudo.org,cn=gssapi,cn=auth$";
|
||||
target = "cn=$1,ou=hosts,dc=fudo,dc=org";
|
||||
}
|
||||
{
|
||||
regex = "^uid=[^,/]+/root,cn=fudo.org,cn=gssapi,cn=auth$";
|
||||
target = "cn=admin,dc=fudo,dc=org";
|
||||
}
|
||||
{
|
||||
regex = "^uid=([^,/]+),cn=fudo.org,cn=gssapi,cn=auth$";
|
||||
target = "uid=$1,ou=members,dc=fudo,dc=org";
|
||||
}
|
||||
{
|
||||
regex = "^uid=host/([^,/]+),cn=fudo.org,cn=gssapi,cn=auth$";
|
||||
target = "cn=$1,ou=hosts,dc=fudo,dc=org";
|
||||
}
|
||||
{
|
||||
regex = "^gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth$";
|
||||
target = "cn=admin,dc=fudo,dc=org";
|
||||
}
|
||||
];
|
||||
};
|
||||
children = {
|
||||
"olcDatabase{-1}frontend" = {
|
||||
attrs = {
|
||||
objectClass = [ "olcDatabaseConfig" "olcFrontendConfig" ];
|
||||
olcDatabase = "{-1}frontend";
|
||||
olcAccess = makeAccess {
|
||||
"*" = {
|
||||
"dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"dn.exact=cn=admin,dc=fudo,dc=org" = "manage";
|
||||
"*" = "none";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
"olcDatabase{0}config" = {
|
||||
attrs = {
|
||||
objectClass = [ "olcDatabaseConfig" ];
|
||||
olcDatabase = "{0}config";
|
||||
olcAccess = [ "by * none" ];
|
||||
};
|
||||
};
|
||||
"olcDatabase{1}mdb" = {
|
||||
attrs = {
|
||||
objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
|
||||
olcDatabase = "{1}mdb";
|
||||
olcSuffix = cfg.base;
|
||||
# olcRootDN = "cn=admin,${cfg.base}";
|
||||
# olcRootPW = FIXME; # NOTE: this should be hashed...
|
||||
olcDbDirectory = cfg.database-directory;
|
||||
olcDbIndex = [ "objectClass eq" "uid eq" ];
|
||||
olcAccess = makeAccess {
|
||||
"attrs=userPassword,shadowLastChange" = {
|
||||
"dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"group/groupOfNames/member.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"dn.exact=cn=auth_reader,${cfg.base}" = "read";
|
||||
"dn.exact=cn=replicator,${cfg.base}" = "read";
|
||||
"self" = "write";
|
||||
"*" = "auth";
|
||||
};
|
||||
"dn.base=cn=admin,ou=groups,${cfg.base}" = {
|
||||
"dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"dn.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"users" = "read";
|
||||
"*" = "none";
|
||||
};
|
||||
"dn.subtree=ou=groups,${cfg.base} attrs=memberUid" = {
|
||||
"dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"dn.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"dn.regex=cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" = "write";
|
||||
"group/groupOfNames/member.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"users" = "read";
|
||||
"*" = "none";
|
||||
};
|
||||
"dn.subtree=ou=members,${cfg.base} attrs=cn,sn,homeDirectory,loginShell,gecos,description,homeDirectory,uidNumber,gidNumber" = {
|
||||
"dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"dn.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"group/groupOfNames/member.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"dn.exact=cn=user_db_reader,${cfg.base}" = "read";
|
||||
"users" = "read";
|
||||
"*" = "none";
|
||||
};
|
||||
"*" = {
|
||||
"dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"dn.exact=cn=admin,ou=groups,${cfg.base}" = "write";
|
||||
"group/groupOfNames/member.exact=cn=admin,ou=groups,${cfg.base}" = "read";
|
||||
"users" = "read";
|
||||
"*" = "none";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
declarativeContents = ''
|
||||
dn: ${cfg.base}
|
||||
|
|
|
@ -1,66 +1,31 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
hostname = config.instance.hostname;
|
||||
cfg = config.fudo.mail-server;
|
||||
container-maildir = "/var/lib/mail";
|
||||
container-statedir = "/var/lib/mail-state";
|
||||
container-shared = "container/mail-server";
|
||||
container-postfix-cert = "${container-shared}/postfix/cert.pem";
|
||||
container-postfix-key = "${container-shared}/postfix/key.pem";
|
||||
container-dovecot-cert = "${container-shared}/dovecot/cert.pem";
|
||||
container-dovecot-key = "${container-shared}/dovecot/key.pem";
|
||||
container-fudo-ca-cert = "${container-shared}/fudo-ca.pem";
|
||||
|
||||
# Don't bother with group-id, nixos doesn't seem to use it anyway
|
||||
container-mail-user = "mailer";
|
||||
container-mail-user-id = 542;
|
||||
container-mail-group = "mailer";
|
||||
fudo-cfg = config.fudo.common;
|
||||
|
||||
in rec {
|
||||
options.fudo.mail-server.container = {
|
||||
ldap-url = mkOption {
|
||||
type = types.str;
|
||||
description = "URL of the LDAP server to use for authentication.";
|
||||
example = "ldaps://auth.fudo.org/";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enableContainer && !cfg.enable) {
|
||||
|
||||
# Disable postfix on thi host--it'll be run in the container instead
|
||||
config = mkIf (cfg.enableContainer) {
|
||||
# Disable postfix on this host--it'll be run in the container instead
|
||||
services.postfix.enable = false;
|
||||
|
||||
# Copy data intended for the container to a path in /etc which can be
|
||||
# bind-mounted.
|
||||
environment.etc = {
|
||||
"${container-postfix-cert}" = {
|
||||
mode = "0444";
|
||||
source = cfg.postfix.ssl-certificate;
|
||||
fudo.acme.host-domains.${hostname}.${cfg.mail-hostname} = {
|
||||
local-copies = {
|
||||
postfix = {
|
||||
user = "root";
|
||||
};
|
||||
dovecot-cert = {
|
||||
user = "root";
|
||||
};
|
||||
|
||||
"${container-postfix-key}" = {
|
||||
mode = "0400";
|
||||
source = cfg.postfix.ssl-private-key;
|
||||
};
|
||||
|
||||
"${container-dovecot-cert}" = {
|
||||
mode = "0444";
|
||||
source = cfg.dovecot.ssl-certificate;
|
||||
};
|
||||
|
||||
"${container-dovecot-key}" = {
|
||||
mode = "0400";
|
||||
source = cfg.dovecot.ssl-private-key;
|
||||
};
|
||||
|
||||
"${container-fudo-ca-cert}" = {
|
||||
mode = "0444";
|
||||
source = "/etc/nixos/static/fudo_ca.pem";
|
||||
};
|
||||
};
|
||||
|
||||
security.acme.certs.${cfg.hostname}.email = fudo-cfg.admin-email;
|
||||
|
||||
services.nginx = mkIf cfg.monitoring {
|
||||
enable = true;
|
||||
|
@ -71,14 +36,15 @@ in rec {
|
|||
proxy_set_header Host $host;
|
||||
'';
|
||||
trusted-network-string =
|
||||
optionalString ((length fudo-cfg.local-networks) > 0)
|
||||
optionalString ((length config.instance.local-networks) > 0)
|
||||
(concatStringsSep "\n"
|
||||
(map (network: "allow ${network};") fudo-cfg.local-networks)) + ''
|
||||
(map (network: "allow ${network};")
|
||||
config.instance.local-networks)) + ''
|
||||
|
||||
deny all;'';
|
||||
|
||||
in {
|
||||
"${cfg.hostname}" = {
|
||||
"${cfg.mail-hostname}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
|
@ -119,7 +85,9 @@ in rec {
|
|||
|
||||
autoStart = true;
|
||||
|
||||
bindMounts = {
|
||||
bindMounts = let
|
||||
cert-copies = config.fudo.acme.host-domains.${hostname}.${cfg.mail-hostname}.local-copies;
|
||||
in {
|
||||
"${container-maildir}" = {
|
||||
hostPath = cfg.mail-directory;
|
||||
isReadOnly = false;
|
||||
|
@ -134,29 +102,73 @@ in rec {
|
|||
hostPath = "/etc/${container-shared}";
|
||||
isReadOnly = true;
|
||||
};
|
||||
|
||||
"/run/mail/certs/postfix/cert.pem" = {
|
||||
hostPath = cert-copies.postfix.certificate;
|
||||
isReadOnly = true;
|
||||
};
|
||||
|
||||
"/run/mail/certs/postfix/key.pem" = {
|
||||
hostPath = cert-copies.postfix.private-key;
|
||||
isReadOnly = true;
|
||||
};
|
||||
|
||||
"/run/mail/certs/dovecot/cert.pem" = {
|
||||
hostPath = cert-copies.dovecot.certificate;
|
||||
isReadOnly = true;
|
||||
};
|
||||
|
||||
"/run/mail/certs/dovecot/key.pem" = {
|
||||
hostPath = cert-copies.dovecot.private-key;
|
||||
isReadOnly = true;
|
||||
};
|
||||
};
|
||||
|
||||
imports = let
|
||||
initialize-host = import ../../initialize-host.nix;
|
||||
build-timestamp = config.instance.build-timestamp;
|
||||
site = config.instance.site;
|
||||
domain = config.instance.domain;
|
||||
profile = "container";
|
||||
in [
|
||||
(initialize-host {
|
||||
inherit
|
||||
lib
|
||||
pkgs
|
||||
build-timestamp
|
||||
site
|
||||
domain
|
||||
profile;
|
||||
hostname = "mail-container";
|
||||
})
|
||||
];
|
||||
|
||||
config = { config, pkgs, ... }: {
|
||||
|
||||
environment.systemPackages = with pkgs; [ nmap ];
|
||||
|
||||
imports = [ ./mail.nix ];
|
||||
|
||||
environment = {
|
||||
etc = {
|
||||
"postfix-certs/key.pem" = {
|
||||
source = "/etc/${container-postfix-key}";
|
||||
environment.etc = {
|
||||
"mail-server/postfix/cert.pem" = {
|
||||
source = "/run/mail/certs/postfix/cert.pem";
|
||||
user = config.services.postfix.user;
|
||||
mode = "0444";
|
||||
};
|
||||
"mail-server/postfix/key.pem" = {
|
||||
source = "/run/mail/certs/postfix/key.pem";
|
||||
user = config.services.postfix.user;
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
"dovecot-certs/key.pem" = {
|
||||
source = "/etc/${container-dovecot-key}";
|
||||
user = config.services.dovecot2.user;
|
||||
"mail-server/dovecot/cert.pem" = {
|
||||
source = "/run/mail/certs/dovecot/cert.pem";
|
||||
user = config.services.dovecot.user;
|
||||
mode = "0444";
|
||||
};
|
||||
"mail-server/dovecot/key.pem" = {
|
||||
source = "/run/mail/certs/dovecot/key.pem";
|
||||
user = config.services.dovecot.user;
|
||||
mode = "0400";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imports = [ ./mail.nix ];
|
||||
|
||||
fudo.mail-server = {
|
||||
enable = true;
|
||||
|
@ -169,14 +181,15 @@ in rec {
|
|||
state-directory = container-statedir;
|
||||
mail-directory = container-maildir;
|
||||
|
||||
postfix.ssl-certificate = "/etc/${container-postfix-cert}";
|
||||
postfix.ssl-private-key = "/etc/postfix-certs/key.pem";
|
||||
postfix = {
|
||||
ssl-certificate = "/etc/mail-server/postfix/cert.pem";
|
||||
ssl-private-key = "/etc/mail-server/postfix/key.pem";
|
||||
};
|
||||
|
||||
dovecot = {
|
||||
ssl-certificate = "/etc/${container-dovecot-cert}";
|
||||
ssl-private-key = "/etc/dovecot-certs/key.pem";
|
||||
ssl-certificate = "/etc/mail-server/dovecot/cert.pem";
|
||||
ssl-private-key = "/etc/mail-server/dovecot/key.pem";
|
||||
ldap = {
|
||||
# ca = "/etc/${container-fudo-ca-cert}";
|
||||
server-urls = cfg.dovecot.ldap.server-urls;
|
||||
reader-dn = cfg.dovecot.ldap.reader-dn;
|
||||
reader-passwd = cfg.dovecot.ldap.reader-passwd;
|
||||
|
|
|
@ -21,11 +21,18 @@ in {
|
|||
description = "The main and default domain name for this email server.";
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
mail-hostname = mkOption {
|
||||
type = types.str;
|
||||
description = "The domain name to use for the mail server.";
|
||||
};
|
||||
|
||||
|
||||
ldap-url = mkOption {
|
||||
type = types.str;
|
||||
description = "URL of the LDAP server to use for authentication.";
|
||||
example = "ldaps://auth.fudo.org/";
|
||||
};
|
||||
|
||||
monitoring = mkEnableOption "Enable monitoring for the mail server.";
|
||||
|
||||
mail-user = mkOption {
|
||||
|
|
|
@ -4,7 +4,6 @@ with lib;
|
|||
let
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
cfg = config.fudo.prometheus;
|
||||
fudo-cfg = config.fudo.common;
|
||||
|
||||
in {
|
||||
|
||||
|
@ -76,9 +75,6 @@ in {
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
security.acme.certs.${cfg.hostname}.email = fudo-cfg.admin-email;
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
|
@ -111,7 +107,8 @@ in {
|
|||
|
||||
webExternalUrl = "https://${cfg.hostname}";
|
||||
|
||||
listenAddress = "127.0.0.1:9090";
|
||||
listenAddress = "127.0.0.1";
|
||||
port = 9090;
|
||||
|
||||
scrapeConfigs = [
|
||||
{
|
||||
|
|
|
@ -9,7 +9,10 @@ let
|
|||
webmail-user = cfg.user;
|
||||
webmail-group = cfg.group;
|
||||
|
||||
base-data-path = "/var/run/rainloop";
|
||||
base-data-path = "/run/rainloop";
|
||||
|
||||
concatMapAttrs = f: attrs:
|
||||
foldr (a: b: a // b) {} (mapAttrsToList f attrs);
|
||||
|
||||
fastcgi-conf = builtins.toFile "fastcgi.conf" ''
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
@ -301,7 +304,7 @@ in {
|
|||
site-config-file = builtins.toFile "${site}-rainloop.cfg"
|
||||
(import ./include/rainloop.nix lib site site-cfg site-pkgs.${site}.version);
|
||||
|
||||
domain-cfg-file = builtins.toFile "${site}-domain.cfg" ''
|
||||
domain-config-file = builtins.toFile "${site}-domain.cfg" ''
|
||||
imap_host = "${site-cfg.mail-server}"
|
||||
imap_port = 143
|
||||
imap_secure = "TLS"
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
{ lib, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
base-host-config = host-path: let
|
||||
let
|
||||
hostname-from-file = filename: builtins.replaceStrings [".nix"] [""] filename;
|
||||
|
||||
is-nix-file = filename: type: (builtins.match ".+\.nix$" filename) != null;
|
||||
is-regular-file = filename: type: type == "regular" || type == "link";
|
||||
|
||||
host-files = attrNames (filterAttrs is-nix-file (filterAttrs is-regular-file (builtins.readDir host-path)));
|
||||
hosts = map hostname-from-file host-files;
|
||||
host-files = host-path:
|
||||
attrNames
|
||||
(filterAttrs is-nix-file
|
||||
(filterAttrs is-regular-file
|
||||
(builtins.readDir host-path)));
|
||||
|
||||
hosts = host-path:
|
||||
map hostname-from-file (host-files host-path);
|
||||
in {
|
||||
base-host-config = host-path: let
|
||||
load-host-file = hostname: import (host-path + "/${hostname}.nix");
|
||||
in genAttrs hosts (hostname: load-host-file hostname);
|
||||
in genAttrs (hosts host-path) (hostname: load-host-file hostname);
|
||||
|
||||
host-list = host-path: hosts host-path;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ with lib;
|
|||
let
|
||||
cfg = config.informis.cl-gemini;
|
||||
|
||||
lisp-helper = import ../lisp.nix { inherit pkgs; };
|
||||
|
||||
feedOpts = { ... }: with types; {
|
||||
options = {
|
||||
url = mkOption {
|
||||
|
@ -163,7 +161,7 @@ in {
|
|||
GEMINI_TEXTFILES_ROOT = cfg.textfiles-archive;
|
||||
GEMINI_FEEDS = "${generate-feeds cfg.feeds}";
|
||||
|
||||
CL_SOURCE_REGISTRY = "${lisp-helper.lisp-source-registry pkgs.cl-gemini}";
|
||||
CL_SOURCE_REGISTRY = "${pkgs.lib.fudo.lisp.lisp-source-registry pkgs.cl-gemini}";
|
||||
};
|
||||
|
||||
path = with pkgs; [
|
||||
|
|
|
@ -51,6 +51,11 @@ in {
|
|||
type = attrsOf (submodule user.userOpts);
|
||||
description = "List of users who should have access to the local host";
|
||||
};
|
||||
|
||||
build-seed = mkOption {
|
||||
type = str;
|
||||
description = "Seed used to generate configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
|
@ -86,15 +91,21 @@ in {
|
|||
config.fudo.domains.${local-domain}.local-networks //
|
||||
config.fudo.sites.${local-site}.local-networks;
|
||||
|
||||
local-profile = host.profile;
|
||||
|
||||
build-seed = builtins.readFile config.fudo.secrets.files.build-seed;
|
||||
|
||||
in {
|
||||
instance = {
|
||||
local-domain = local-domain;
|
||||
local-site = local-site;
|
||||
local-users = local-users;
|
||||
local-admins = local-admins;
|
||||
local-groups = local-groups;
|
||||
local-hosts = local-hosts;
|
||||
local-profile = host.profile;
|
||||
inherit
|
||||
build-seed
|
||||
local-domain
|
||||
local-site
|
||||
local-users
|
||||
local-admins
|
||||
local-groups
|
||||
local-hosts
|
||||
local-profile;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ lib, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with pkgs.lib;
|
||||
let
|
||||
pow = x: e: if (e == 0) then 1 else x * (pow x (e - 1));
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
let
|
||||
in rec {
|
||||
rec {
|
||||
gather-dependencies = pkg: unique (pkg.propagatedBuildInputs ++ (concatMap gather-dependencies pkg.propagatedBuildInputs));
|
||||
|
||||
lisp-source-registry = pkg: concatStringsSep ":" (map (p: "${p}//") (gather-dependencies pkg));
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
(final: prev: let
|
||||
ip = import ./ip.nix { lib = prev.lib; };
|
||||
dns = import ./dns.nix { lib = prev.lib; };
|
||||
in {
|
||||
(final: prev: {
|
||||
lib = prev.lib // {
|
||||
fudo = {
|
||||
inherit ip dns;
|
||||
fudo = let
|
||||
lib = prev.lib;
|
||||
in {
|
||||
ip = import ./ip.nix { pkgs = prev; };
|
||||
dns = import ./dns.nix { pkgs = prev;};
|
||||
passwd = import ./passwd.nix { pkgs = prev;};
|
||||
lisp = import ./lisp.nix { pkgs = prev;};
|
||||
};
|
||||
};
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ lib, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with pkgs.lib;
|
||||
let
|
||||
hash-ldap-passwd-pkg = name: passwd-file: pkgs.stdenv.mkDerivation {
|
||||
name = "${name}-ldap-passwd";
|
||||
|
@ -14,7 +14,7 @@ let
|
|||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
mkdir -p $out
|
||||
mv ldap-passwd $out
|
||||
'';
|
||||
};
|
||||
|
@ -26,17 +26,26 @@ let
|
|||
generate-random-passwd = name: length: pkgs.stdenv.mkDerivation {
|
||||
name = "${name}-random-passwd";
|
||||
|
||||
phases = [ "buildPhase" "installPhase" ];
|
||||
phases = [ "installPhase" ];
|
||||
|
||||
buildInputs = with pkgs; [ pwgen ];
|
||||
|
||||
buildPhase = ''
|
||||
pwgen --symbols --num-passwords=1 ${length} > passwd
|
||||
installPhase = ''
|
||||
pwgen --secure --num-passwords=1 ${length} > $out
|
||||
'';
|
||||
};
|
||||
|
||||
generate-stablerandom-passwd = name: { seed, length ? 20, ... }:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "${name}-stablerandom-passwd";
|
||||
|
||||
phases = [ "installPhase" ];
|
||||
|
||||
buildInputs = with pkgs; [ pwgen ];
|
||||
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
mv passwd $out
|
||||
echo "${name}-${seed}" > seedfile
|
||||
pwgen --secure --num-passwords=1 -H seedfile ${toString length} > $out
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -44,5 +53,8 @@ in {
|
|||
hash-ldap-passwd = hash-ldap-passwd;
|
||||
|
||||
random-passwd-file = name: length:
|
||||
toPath "${generate-random-passwd name length}/passwd";
|
||||
builtins.toPath "${generate-random-passwd name length}";
|
||||
|
||||
stablerandom-passwd-file = name: seed:
|
||||
builtins.toPath "${generate-stablerandom-passwd name { seed = seed; }}";
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
{ lib, ... }:
|
||||
|
||||
with lib;
|
||||
rec {
|
||||
let
|
||||
passwd = import ../passwd.nix { inherit lib; };
|
||||
|
||||
in rec {
|
||||
encryptedFSOpts = { ... }: let
|
||||
mountpoint = { mp, ... }: {
|
||||
options = with types; {
|
||||
|
@ -31,6 +34,12 @@ rec {
|
|||
'';
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
world-readable = mkOption {
|
||||
type = bool;
|
||||
description = "Whether to leave the top level world-readable.";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
|
@ -81,7 +90,9 @@ rec {
|
|||
};
|
||||
};
|
||||
|
||||
hostOpts = { hostname, ... }: {
|
||||
hostOpts = { name, ... }: let
|
||||
hostname = name;
|
||||
in {
|
||||
options = with types; {
|
||||
master-key = mkOption {
|
||||
type = nullOr (submodule masterKeyOpts);
|
||||
|
@ -284,6 +295,11 @@ rec {
|
|||
description = "Configuration parameters to set up initrd SSH network.";
|
||||
default = null;
|
||||
};
|
||||
|
||||
backplane-password-file = mkOption {
|
||||
options = path;
|
||||
description = "File containing the password used by this host to connect to the backplane.";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
with lib;
|
||||
rec {
|
||||
systemUserOpts = { username, ... }: {
|
||||
systemUserOpts = { name, ... }: {
|
||||
options = with lib.types; {
|
||||
username = mkOption {
|
||||
type = str;
|
||||
description = "The system user's login name.";
|
||||
default = username;
|
||||
default = name;
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
|
@ -23,7 +23,9 @@ rec {
|
|||
};
|
||||
};
|
||||
|
||||
userOpts = { username, ... }: {
|
||||
userOpts = { name, ... }: let
|
||||
username = name;
|
||||
in {
|
||||
options = with lib.types; {
|
||||
username = mkOption {
|
||||
type = str;
|
||||
|
|
Loading…
Reference in New Issue