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