Only launch ejabberd if env is available

This commit is contained in:
niten 2023-10-15 21:10:05 -07:00
parent c629223e85
commit 356c452d66
1 changed files with 76 additions and 87 deletions

View File

@ -5,47 +5,46 @@ let
hostname = config.instance.hostname;
host-secrets = config.fudo.secrets.host-secrets.${hostname};
siteOpts = { ... }: with types; {
options = {
enableACME = mkOption {
type = bool;
description = "Use ACME to get SSL certificates for this site.";
default = true;
};
hostname = mkOption {
type = str;
description = "Hostname of this server.";
};
site-config = mkOption {
type = attrs;
description = "Site-specific configuration.";
siteOpts = { ... }:
with types; {
options = {
enableACME = mkOption {
type = bool;
description = "Use ACME to get SSL certificates for this site.";
default = true;
};
hostname = mkOption {
type = str;
description = "Hostname of this server.";
};
site-config = mkOption {
type = attrs;
description = "Site-specific configuration.";
};
};
};
};
config-dir = dirOf cfg.config-file;
concatMapAttrs = f: attrs:
foldr (a: b: a // b) {} (mapAttrs f attrs);
concatMapAttrs = f: attrs: foldr (a: b: a // b) { } (mapAttrs f attrs);
concatMapAttrsToList = f: attr:
concatMap (i: i) (attrValues (mapAttrs f attr));
host-domains = config.fudo.acme.host-domains.${hostname};
hostCerts = host: let
cert-copy = host-domains.${host}.local-copies.ejabberd;
in [
cert-copy.certificate
cert-copy.private-key
# cert-copy.full-certificate
];
hostCerts = host:
let cert-copy = host-domains.${host}.local-copies.ejabberd;
in [
cert-copy.certificate
cert-copy.private-key
# cert-copy.full-certificate
];
hostCertService = host:
host-domains.${host}.local-copies.ejabberd.service;
hostCertService = host: host-domains.${host}.local-copies.ejabberd.service;
config-file-template = let
jabber-config = {
@ -60,8 +59,7 @@ let
acl.admin = {
user = concatMap
(admin: map (site: "${admin}@${site}")
(attrNames cfg.sites))
(admin: map (site: "${admin}@${site}") (attrNames cfg.sites))
cfg.admins;
};
@ -77,48 +75,41 @@ let
starttls = true;
starttls_required = true;
};
in
if (cfg.listen-ips != null) then
map (ip: { ip = ip; } // common)
cfg.listen-ips
else [ common ];
in if (cfg.listen-ips != null) then
map (ip: { ip = ip; } // common) cfg.listen-ips
else
[ common ];
certfiles = concatMapAttrsToList
(site: siteOpts:
if (siteOpts.enableACME) then
(hostCerts siteOpts.hostname)
else [])
certfiles = concatMapAttrsToList (site: siteOpts:
if (siteOpts.enableACME) then (hostCerts siteOpts.hostname) else [ ])
cfg.sites;
host_config =
mapAttrs (site: siteOpts: siteOpts.site-config)
cfg.sites;
host_config = mapAttrs (site: siteOpts: siteOpts.site-config) cfg.sites;
};
config-file = builtins.toJSON jabber-config;
in pkgs.lib.text.format-json-file
(pkgs.writeText "ejabberd.config.yml.template" config-file);
(pkgs.writeText "ejabberd.config.yml.template" config-file);
enter-secrets = template: secrets: target: let
secret-swappers = map
(secret: "sed s/${secret}/\$${secret}/g")
secrets;
swapper = concatStringsSep " | " secret-swappers;
in pkgs.writeShellScript "ejabberd-generate-config.sh" ''
[ -f \$${target} ] && rm -f ${target}
echo "Copying from ${template} to ${target}"
touch ${target}
chmod go-rwx ${target}
chmod u+rw ${target}
cat ${template} | ${swapper} > ${target}
echo "Copying from ${template} to ${target} completed"
'';
enter-secrets = template: secrets: target:
let
secret-swappers = map (secret: "sed s/${secret}/\$${secret}/g") secrets;
swapper = concatStringsSep " | " secret-swappers;
in pkgs.writeShellScript "ejabberd-generate-config.sh" ''
[ -f \$''${target} ] && rm -f ${target}
echo "Copying from ${template} to ${target}"
touch ${target}
chmod go-rwx ${target}
chmod u+rw ${target}
cat ${template} | ${swapper} > ${target}
echo "Copying from ${template} to ${target} completed"
'';
cfg = config.fudo.jabber;
log-dir = "${cfg.state-directory}/logs";
spool-dir = "${cfg.state-directory}/spool";
in {
options.fudo.jabber = with types; {
enable = mkEnableOption "Enable ejabberd server.";
@ -128,7 +119,7 @@ in {
description = "IPs on which to listen for Jabber connections.";
default = null;
};
port = mkOption {
type = port;
description = "Port on which to listen for Jabber connections.";
@ -150,7 +141,7 @@ in {
admins = mkOption {
type = listOf str;
description = "List of admin users for the server.";
default = [];
default = [ ];
};
sites = mkOption {
@ -160,8 +151,9 @@ in {
secret-files = mkOption {
type = attrsOf str;
description = "Map of secret-name to file. File contents will be subbed for the name in the config.";
default = {};
description =
"Map of secret-name to file. File contents will be subbed for the name in the config.";
default = { };
};
config-file = mkOption {
@ -189,27 +181,20 @@ in {
environment = mkOption {
type = attrsOf str;
description = "Environment variables to set for the ejabberd daemon.";
default = {};
default = { };
};
};
config = mkIf cfg.enable {
users = {
users.${cfg.user} = {
isSystemUser = true;
};
users.${cfg.user} = { isSystemUser = true; };
groups.${cfg.group} = {
members = [ cfg.user ];
};
groups.${cfg.group} = { members = [ cfg.user ]; };
};
networking.firewall = {
allowedTCPPorts = [ 5222 5223 5269 8010 ];
};
networking.firewall = { allowedTCPPorts = [ 5222 5223 5269 8010 ]; };
fudo = let
host-fqdn = config.instance.host-fqdn;
fudo = let host-fqdn = config.instance.host-fqdn;
in {
acme.host-domains.${hostname} = mapAttrs' (site: siteOpts:
nameValuePair siteOpts.hostname {
@ -235,35 +220,39 @@ in {
"d ${config-dir} 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.state-directory} 0750 ${cfg.user} ${cfg.group} - -"
];
services = {
ejabberd = {
wants =
map hostCertService
(mapAttrsToList (_: siteOpts: siteOpts.hostname) cfg.sites);
wants = map hostCertService
(mapAttrsToList (_: siteOpts: siteOpts.hostname) cfg.sites);
requires = [ "ejabberd-config-generator.service" ];
environment = cfg.environment;
};
ejabberd-config-generator = let
config-generator =
enter-secrets config-file-template (attrNames cfg.secret-files) cfg.config-file;
enter-secrets config-file-template (attrNames cfg.secret-files)
cfg.config-file;
in {
description = "Generate ejabberd config file containing passwords.";
serviceConfig = {
User = cfg.user;
ExecStart = "${config-generator}";
ExecStartPost = pkgs.writeShellScript "protect-ejabberd-config.sh" ''
chown ${cfg.user}:${cfg.group} ${cfg.config-file}
chmod 0400 ${cfg.config-file}
'';
ExecStartPost =
pkgs.writeShellScript "protect-ejabberd-config.sh" ''
chown ${cfg.user}:${cfg.group} ${cfg.config-file}
chmod 0400 ${cfg.config-file}
'';
EnvironmentFile = host-secrets.ejabberd-password-env.target-file;
};
unitConfig.ConditionPathExists =
[ host-secrets.ejabberd-password-env.target-file ];
requires = [ host-secrets.ejabberd-password-env.service ];
after = [ host-secrets.ejabberd-password-env.service ];
};
};
};
services.ejabberd = {
enable = true;