{ config, lib, pkgs, foodogsquaredLib, ... }: let hostCfg = config.users.foo-dogsquared; cfg = hostCfg.services.archivebox; inherit (config.home) homeDirectory; port = builtins.toString config.state.ports.archivebox.value; url = "localhost:${port}"; archiveboxDir = "${config.xdg.userDirs.documents}/ArchiveBox"; jobUnitName = name: "archivebox-job-${name}"; jobType = { name, options, ... }: { options = { links = lib.mkOption { type = with lib.types; listOf str; description = "List of links to archive."; example = lib.literalExpression '' [ "https://guix.gnu.org/feeds/blog.atom" "https://nixos.org/blog/announcements-rss.xml" ] ''; }; extraArgs = lib.mkOption { type = with lib.types; listOf str; description = '' Additional arguments for adding links (i.e., {command}`archivebox add $LINK`) from {option}`links`. ''; default = [ ]; example = lib.literalExpression '' [ "--depth" "1" ] ''; }; startAt = lib.mkOption { type = with lib.types; str; description = '' Indicates how frequent the scheduled archiving will occur. Should be a valid string format as described from {manpage}`systemd.time(5)`. ''; default = "daily"; defaultText = "daily"; example = "*-*-01/2"; }; }; }; in { options.users.foo-dogsquared.services.archivebox = { enable = lib.mkEnableOption "ArchiveBox web UI server (through Podman)"; jobs = lib.mkOption { type = with lib.types; attrsOf (submodule jobType); default = { }; defaultText = lib.literalExpression "{}"; example = lib.literalExpression '' { illustration = { links = [ "https://www.davidrevoy.com/" "https://www.youtube.com/c/ronillust" ]; startAt = "weekly"; }; research = { links = [ "https://arxiv.org/rss/cs" "https://distill.pub/" ]; extraArgs = [ "--depth" "1" ]; startAt = "daily"; }; } ''; }; }; config = lib.mkIf cfg.enable { state.ports = { archivebox.value = 8932; sonic.value = 9141; }; home.packages = [ (pkgs.writeShellScriptBin "archivebox" '' podman run --interactive --tty --volume ${archiveboxDir}:/data docker.io/archivebox/archivebox:latest '') ]; sops.secrets = foodogsquaredLib.sops-nix.getSecrets ./secrets.yaml { "archivebox/env" = { }; "sonic/env" = { }; }; services.podman.containers = lib.mkMerge [ (lib.mapAttrs' (name: value: lib.nameValuePair (jobUnitName name) { image = "docker.io/archivebox/archivebox:latest"; description = "ArchiveBox job '${name}'"; volumes = [ "${archiveboxDir}:/data" ]; autoUpdate = "registry"; exec = ''echo "${lib.concatStringsSep "\n" value.links}" | archivebox add ${lib.concatStringsSep " " value.extraArgs}''; environmentFile = config.services.podman.containers.archivebox-webui.environmentFile; environment = config.services.podman.containers.archivebox-webui.environment; }) cfg.jobs) { archivebox-webui = { image = "docker.io/archivebox/archivebox:latest"; description = "ArchiveBox web server"; ports = [ "${port}:${port}" ]; volumes = [ "${archiveboxDir}:/data" ]; autoUpdate = "registry"; exec = "archivebox server ${url}"; environmentFile = [ "${config.sops.secrets."archivebox/env".path}" ]; environment = { SEARCH_BACKEND_ENGINE = "sonic"; SEARCH_BACKEND_HOST_NAME = "sonic"; PUBLIC_SNAPSHOTS = "True"; PUBLIC_INDEX = "True"; PUBLIC_ADD_VIEW = "False"; SAVE_ARCHIVE_DOT_ORG = "False"; SAVE_GIT = "False"; }; }; } { archivebox-sonic-search = { image = "docker.io/archivebox/sonic:latest"; description = "Sonic search instance for ArchiveBox"; ports = let port = builtins.toString config.state.ports.sonic.value; in [ "${port}:${port}" ]; environmentFile = [ "${config.sops.secrets."sonic/env".path}" ]; volumes = [ "${config.xdg.userDirs.documents}/ArchiveBox/Sonic:/var/lib/sonic/store" "${./config/sonic/sonic.cfg}:/etc/sonic.cfg:ro" ]; extraConfig.Unit.After = [ "podman-archivebox-webui.service" ]; }; } ]; users.foo-dogsquared.programs.custom-homepage.sections.services.links = lib.singleton { url = "${url}/public"; text = "Link archive"; }; }; }