From ec0965e2672899d25a5a3a8c072de3ea734076a2 Mon Sep 17 00:00:00 2001 From: V Date: Wed, 9 Jun 2021 15:43:16 +0200 Subject: fleet: init Co-authored-by: edef Change-Id: I36d2c4cca542ed91630b1b832f3c7a7b97b33c65 --- fleet/modules/public-inbox.nix | 134 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 fleet/modules/public-inbox.nix (limited to 'fleet/modules/public-inbox.nix') diff --git a/fleet/modules/public-inbox.nix b/fleet/modules/public-inbox.nix new file mode 100644 index 0000000..a8aa06b --- /dev/null +++ b/fleet/modules/public-inbox.nix @@ -0,0 +1,134 @@ +# SPDX-FileCopyrightText: V +# SPDX-License-Identifier: OSL-3.0 + +# TODO(V): Figure out what the coderepo/cgit stuff is about +# TODO(V): Consider a different architecture to what we're currently using + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.public-inbox; + + environment.PI_CONFIG = "${pkgs.writeText "public-inbox-config" (generators.toGitINI public-inbox-config)}"; + + # TODO(V): Port this to a Nix type + # $ng =~ m![^A-Za-z0-9/_\.\-\~\@\+\=:]! and + # die "--newsgroup `$ng' is not valid\n"; + # ($ng =~ m!\A\.! || $ng =~ m!\.\z!) and + # die "--newsgroup `$ng' must not start or end with `.'\n"; + + public-inbox-config = recursiveUpdate { + publicinbox = mapAttrs (inbox: config: { + address = [ "${inbox}@${config.domain}" ]; + url = "https://${config.domain}/${inbox}"; # TODO(V): Allow using a different location than this + inboxdir = "/var/lib/public-inbox/${inbox}.git"; + inherit (config) watch; + }) cfg.inboxes; + } cfg.settings; + + inboxOpts = { + options = { + description = mkOption { + description = "Description of the inbox."; + type = types.str; + }; + + domain = mkOption { + description = "Domain of the inbox."; + type = types.str; + example = "example.org"; + }; + + watch = mkOption { + description = "Directory to watch for incoming mails in."; + type = types.str; + }; + }; + }; +in { + options.services.public-inbox = { + enable = mkOption { + type = types.bool; + default = false; + }; + + inboxes = mkOption { + type = with types; attrsOf (submodule inboxOpts); + default = {}; + }; + + settings = mkOption { + type = types.attrs; # TODO: Use freeformType + default = {}; + }; + }; + + config = mkIf cfg.enable { + users.users.public-inbox = { + isSystemUser = true; + group = "public-inbox"; + + home = "/var/lib/public-inbox"; + createHome = true; + }; + + users.groups.public-inbox = {}; + + systemd.services.public-inbox-init = { + description = "public-inbox mailing-list archive (initialization)"; + + wantedBy = [ "public-inbox-watch.service" "multi-user.target" ]; + before = [ "public-inbox-watch.service" ]; + + # TODO(V): Add ${pi-config.inboxdir}/description to the reload conditions, since new descriptions don't get picked up after being updated. + script = concatStrings (mapAttrsToList (inbox: config: let pi-config = public-inbox-config.publicinbox.${inbox}; in '' + ${pkgs.public-inbox-init-lite}/bin/public-inbox-init-lite ${inbox} ${pi-config.inboxdir} ${head pi-config.address} + ln -sf ${pkgs.writeText "public-inbox-description" config.description} ${pi-config.inboxdir}/description + ${pkgs.public-inbox}/bin/public-inbox-index ${pi-config.inboxdir} + '') cfg.inboxes); + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = "public-inbox"; + }; + }; + + # FIXME(V): Currently, if new mail appears in the mlmmj archive while public-inbox-watch is not running, it never gets added! + # This directly contradicts what the manpage states: "Upon startup, it scans the mailbox for new messages to be imported while it was not running." + # This might be a bug in public-inbox! + # We currently save a copy of all mails received by mlmmj to ensure none are lost if this happens. + systemd.services.public-inbox-watch = { + description = "public-inbox mailing-list archive (incoming mail monitor)"; + wantedBy = [ "multi-user.target" ]; + inherit environment; + serviceConfig = { + ExecStart = "${pkgs.public-inbox}/bin/public-inbox-watch"; + # TODO(V): ExecReload + User = "public-inbox"; + SupplementaryGroups = [ "mlmmj" ]; + }; + }; + + # TODO(V): Consider using public-inbox.cgi + cgiserver instead? + systemd.sockets.public-inbox-httpd = { + description = "public-inbox mailing-list archive (web server)"; + listenStreams = [ "/run/public-inbox/httpd.sock" ]; + wantedBy = [ "sockets.target" ]; + }; + + systemd.services.public-inbox-httpd = { + description = "public-inbox mailing-list archive (web server)"; + inherit environment; + serviceConfig = { + ExecStart = "${pkgs.public-inbox}/bin/public-inbox-httpd"; + DynamicUser = true; + SupplementaryGroups = [ "public-inbox" ]; + }; + }; + }; + + meta.maintainers = with maintainers; [ V ]; +} -- cgit 1.4.1