272 lines
8.3 KiB
Nix
272 lines
8.3 KiB
Nix
![]() |
{ config, pkgs, lib, ... }:
|
||
|
|
||
|
with lib;
|
||
|
let
|
||
|
cfg = config.fudo.backplane.dns;
|
||
|
|
||
|
dns = import ../../../lib/dns.nix { inherit lib; };
|
||
|
|
||
|
backup-directory = "/var/lib/fudo/backplane/dns";
|
||
|
|
||
|
powerdns-home = "/var/lib/powerdns";
|
||
|
|
||
|
powerdns-conf-dir = "${powerdns-home}/conf.d";
|
||
|
|
||
|
backplaneOpts = { ... }: {
|
||
|
options = {
|
||
|
host = mkOption {
|
||
|
type = types.str;
|
||
|
description = "Hostname of the backplane jabber server.";
|
||
|
};
|
||
|
|
||
|
role = mkOption {
|
||
|
type = types.str;
|
||
|
description = "Backplane XMPP role name for the DNS server.";
|
||
|
default = "service-dns";
|
||
|
};
|
||
|
|
||
|
password-file = mkOption {
|
||
|
type = types.str;
|
||
|
description = "File containing XMPP password for backplane role.";
|
||
|
};
|
||
|
|
||
|
database = mkOption {
|
||
|
type = with types; submodule databaseOpts;
|
||
|
description = "Database settings for backplane server.";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
databaseOpts = { ... }: {
|
||
|
options = {
|
||
|
host = mkOption {
|
||
|
type = types.str;
|
||
|
description = "Hostname or IP of the PostgreSQL server.";
|
||
|
};
|
||
|
|
||
|
database = mkOption {
|
||
|
type = types.str;
|
||
|
description = "Database to use for DNS backplane.";
|
||
|
default = "backplane_dns";
|
||
|
};
|
||
|
|
||
|
username = mkOption {
|
||
|
type = types.str;
|
||
|
description = "Database user for DNS backplane.";
|
||
|
default = "backplane_dns";
|
||
|
};
|
||
|
|
||
|
password-file = mkOption {
|
||
|
type = types.str;
|
||
|
description = "File containing password for database user.";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
lisp-libs = [];
|
||
|
|
||
|
launchScript = pkgs.writeText "launch-backplane-dns.lisp" ''
|
||
|
(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))
|
||
|
(ql:quickload :backplane-dns)
|
||
|
(backplane-dns:start-listener-with-env)
|
||
|
(loop (sleep 600))
|
||
|
'';
|
||
|
|
||
|
in {
|
||
|
options.fudo.backplane.dns = {
|
||
|
enable = mkEnableOption "Enable backplane dynamic DNS server.";
|
||
|
|
||
|
port = mkOption {
|
||
|
type = types.port;
|
||
|
description = "Port on which to serve authoritative DNS requests.";
|
||
|
default = 53;
|
||
|
};
|
||
|
|
||
|
listen-addresses = mkOption {
|
||
|
type = with types; listOf str;
|
||
|
description = "IP addresses on which to listen for dns requests.";
|
||
|
default = [ "0.0.0.0" ];
|
||
|
};
|
||
|
|
||
|
required-services = mkOption {
|
||
|
type = with types; listOf str;
|
||
|
description = "A list of services required before the DNS server can start.";
|
||
|
};
|
||
|
|
||
|
user = mkOption {
|
||
|
type = types.str;
|
||
|
description = "User as which to run DNS backplane listener service.";
|
||
|
default = "backplane-dns";
|
||
|
};
|
||
|
|
||
|
group = mkOption {
|
||
|
type = types.str;
|
||
|
description = "Group as which to run DNS backplane listener service.";
|
||
|
default = "backplane-dns";
|
||
|
};
|
||
|
|
||
|
database = mkOption {
|
||
|
type = with types; submodule databaseOpts;
|
||
|
description = "Database settings for the DNS server.";
|
||
|
};
|
||
|
|
||
|
backplane = mkOption {
|
||
|
type = with types; submodule backplaneOpts;
|
||
|
description = "Backplane Jabber settings for the DNS server.";
|
||
|
};
|
||
|
};
|
||
|
|
||
|
config = mkIf cfg.enable {
|
||
|
users = {
|
||
|
users = {
|
||
|
"${cfg.user}" = {
|
||
|
isSystemUser = true;
|
||
|
group = cfg.group;
|
||
|
createHome = true;
|
||
|
home = "/var/home/${cfg.user}";
|
||
|
};
|
||
|
backplane-powerdns = {
|
||
|
isSystemUser = true;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
groups = {
|
||
|
"${cfg.group}" = {
|
||
|
members = [cfg.user];
|
||
|
};
|
||
|
backplane-powerdns = {
|
||
|
members = [ "backplane-powerdns" ];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
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-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 = {
|
||
|
description = "Generate postgres configuration for backplane DNS server.";
|
||
|
requiredBy = [ "backplane-powerdns.service" ];
|
||
|
requires = cfg.required-services;
|
||
|
serviceConfig.Type = "oneshot";
|
||
|
restartIfChanged = true;
|
||
|
partOf = [ "backplane-dns.target" ];
|
||
|
|
||
|
# This builds the config in a bash script, to avoid storing the password
|
||
|
# in the nix store at any point
|
||
|
script = ''
|
||
|
if [ ! -d ${powerdns-conf-dir} ]; then
|
||
|
mkdir ${powerdns-conf-dir}
|
||
|
fi
|
||
|
|
||
|
TMPDIR=$(${pkgs.coreutils}/bin/mktemp -d -t pdns-XXXXXXXXXX)
|
||
|
TMPCONF=$TMPDIR/pdns.local.gpgsql.conf
|
||
|
|
||
|
if [ ! -f ${cfg.database.password-file} ]; then
|
||
|
echo "${cfg.database.password-file} does not exist!"
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
touch $TMPCONF
|
||
|
chown backplane-powerdns:backplane-powerdns $TMPCONF
|
||
|
chmod go-rwx $TMPCONF
|
||
|
PASSWORD=$(cat ${cfg.database.password-file})
|
||
|
echo "launch+=gpgsql" >> $TMPCONF
|
||
|
echo "gpgsql-host=${cfg.database.host}" >> $TMPCONF
|
||
|
echo "gpgsql-dbname=${cfg.database.database}" >> $TMPCONF
|
||
|
echo "gpgsql-user=${cfg.database.username}" >> $TMPCONF
|
||
|
echo "gpgsql-password=$PASSWORD" >> $TMPCONF
|
||
|
echo "gpgsql-dnssec=yes" >> $TMPCONF
|
||
|
|
||
|
mv $TMPCONF ${powerdns-conf-dir}/pdns.local.gpgsql.conf
|
||
|
|
||
|
rm -rf $TMPDIR
|
||
|
|
||
|
exit 0
|
||
|
'';
|
||
|
};
|
||
|
|
||
|
backplane-dns = {
|
||
|
description = "Fudo DNS Backplane Server";
|
||
|
restartIfChanged = true;
|
||
|
|
||
|
serviceConfig = {
|
||
|
ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init";
|
||
|
ExecStart = "${pkgs.sbcl}/bin/sbcl --load ${launchScript}";
|
||
|
Restart = "on-failure";
|
||
|
PIDFile = "/run/backplane-dns.$USERNAME.pid";
|
||
|
User = cfg.user;
|
||
|
Group = cfg.group;
|
||
|
};
|
||
|
|
||
|
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;
|
||
|
FUDO_DNS_BACKPLANE_DATABASE_HOSTNAME = cfg.backplane.database.host;
|
||
|
FUDO_DNS_BACKPLANE_DATABASE_NAME = cfg.backplane.database.database;
|
||
|
FUDO_DNS_BACKPLANE_DATABASE_USERNAME = cfg.backplane.database.username;
|
||
|
FUDO_DNS_BACKPLANE_DATABASE_PASSWORD_FILE = cfg.backplane.database.password-file;
|
||
|
|
||
|
CL_SOURCE_REGISTRY = lib.concatStringsSep ":" (map (pkg: "${pkg}//")
|
||
|
(lisp-libs ++ [pkgs.backplane-dns]));
|
||
|
};
|
||
|
|
||
|
requires = cfg.required-services;
|
||
|
partOf = [ "backplane-dns.target" ];
|
||
|
wantedBy = [ "multi-user.target" ];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
}
|