From ac91cdc0532e6770348e10480d0366e6b7a1be0b Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Thu, 10 Mar 2022 10:12:03 +0800 Subject: [PATCH] archivebox: update the service module It can now add and schedule archiving tasks. Since archivebox will use Crontab module (which uses `/usr/bin/crontab`), the scheduling with the interface is out of the question. What better way to make it possible than creating a home-manager module for it? --- modules/home-manager/services/archivebox.nix | 173 +++++++++++++++--- secrets/archive/borg-ssh-key | Bin 0 -> 1198 bytes users/home-manager/foo-dogsquared/default.nix | 39 +++- 3 files changed, 184 insertions(+), 28 deletions(-) create mode 100644 secrets/archive/borg-ssh-key diff --git a/modules/home-manager/services/archivebox.nix b/modules/home-manager/services/archivebox.nix index e0cb9ce5..65d8adca 100644 --- a/modules/home-manager/services/archivebox.nix +++ b/modules/home-manager/services/archivebox.nix @@ -1,41 +1,168 @@ { config, options, lib, pkgs, ... }: -let cfg = config.services.archivebox; +let + cfg = config.services.archivebox; + 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" + ] + ''; + }; + + extraOptions = lib.mkOption { + type = with lib.types; listOf str; + description = '' + Additional arguments for adding links (i.e., archivebox add + $LINK) from . + ''; + 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 systemd.time(5). + ''; + default = "daily"; + defaultText = "daily"; + example = "*-*-01/2"; + }; + }; + }; in { options.services.archivebox = { enable = lib.mkEnableOption "Archivebox service"; - port = lib.mkOption { - type = lib.types.port; - description = "The port number to be used for the server at localhost."; - default = 8000; - example = 8888; - }; - archivePath = lib.mkOption { type = with lib.types; either path str; description = "The path of the Archivebox archive."; example = "\${config.xdg.dataHome}/archivebox"; }; - }; - config = lib.mkIf cfg.enable { - systemd.user.services.archivebox-server = { - Unit = { - Description = "Archivebox server for ${cfg.archivePath}"; - After = "network.target"; - Documentation = [ "https://docs.archivebox.io/" ]; - }; + jobs = lib.mkOption { + type = with lib.types; attrsOf (submodule jobType); + description = "A map of archiving tasks for the service."; + default = { }; + defaultText = lib.literalExpression "{}"; + example = lib.literalExpression '' + { + illustration = { + links = [ + "https://www.davidrevoy.com/" + "https://www.youtube.com/c/ronillust" + ]; + startAt = "weekly"; + }; - Install.WantedBy = [ "graphical-session.target" ]; + research = { + links = [ + "https://arxiv.org/rss/cs" + "https://distill.pub/" + ]; + extraOptions = [ "--depth 1" ]; + startAt = "daily"; + }; + } + ''; + }; - Service = { - ExecStart = "${pkgs.archivebox}/bin/archivebox server localhost:${ - toString cfg.port - }"; - WorkingDirectory = cfg.archivePath; - Restart = "on-failure"; + withDependencies = + lib.mkEnableOption "additional dependencies to be installed"; + + webserver = { + enable = lib.mkEnableOption "web UI for Archivebox"; + + port = lib.mkOption { + type = lib.types.port; + description = "The port number to be used for the server at localhost."; + default = 8000; + example = 8888; }; }; }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.archivebox" pkgs + lib.platforms.linux) + ]; + + home.packages = [ pkgs.archivebox ] ++ (lib.optionals cfg.withDependencies + (with pkgs; [ chromium nodejs_latest wget curl youtube-dl ])); + + systemd.user.services = lib.mkMerge [ + (lib.mapAttrs' (name: value: + lib.nameValuePair "archivebox-add-${name}" { + Unit = { + Description = "Archivebox archive group '${name}' for ${cfg.archivePath}"; + After = "network.target"; + Documentation = [ "https://docs.archivebox.io/" ]; + }; + + Install.WantedBy = [ "default.target" ]; + + Service = let + scriptName = "archivebox-job-${config.home.username}-${name}"; + script = pkgs.writeShellApplication { + name = scriptName; + runtimeInputs = with pkgs; [ coreutils archivebox ]; + text = '' + echo "${lib.concatStringsSep "\n" value.links}" \ + | archivebox add ${lib.concatStringsSep " " value.extraOptions} + ''; + }; + in { + ExecStart = "${script}/bin/${scriptName}"; + WorkingDirectory = cfg.archivePath; + }; + }) cfg.jobs) + + (lib.mkIf cfg.webserver.enable { + archivebox-server = { + Unit = { + Description = "Archivebox server for ${cfg.archivePath}"; + After = "network.target"; + Documentation = [ "https://docs.archivebox.io/" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + ExecStart = "${pkgs.archivebox}/bin/archivebox server localhost:${ + toString cfg.webserver.port + }"; + WorkingDirectory = cfg.archivePath; + Restart = "on-failure"; + }; + }; + }) + ]; + + systemd.user.timers = lib.mapAttrs' (name: value: + lib.nameValuePair "archivebox-add-${name}" { + Unit = { + Description = "Archivebox additions for ${cfg.archivePath}"; + After = "network.target"; + Documentation = [ "https://docs.archivebox.io/" ]; + }; + + Timer = { + Persistent = true; + OnCalendar = value.startAt; + RandomizedDelaySec = 120; + }; + + Install.WantedBy = [ "timers.target" ]; + }) cfg.jobs; + }; } diff --git a/secrets/archive/borg-ssh-key b/secrets/archive/borg-ssh-key new file mode 100644 index 0000000000000000000000000000000000000000..734930be8b48135d217ceac4e921f2d546557913 GIT binary patch literal 1198 zcmZ9{`)?Bk007{r5v70xdXl4DDCxn>lFy`+TQj0y0+KXt`gCe538i7jiz zYF3sO%H_0K1r4U9#!4k);yEh}gAQXgn}f~O5EmX zcT&D~l>{lCrew)x$h$NtBoI1jF)Ka2msSdyqTB24InK+~>bq`|5>!N~VQGW&iX7wMIAX=~9ez9sW+<)X7KOmGrz&sE3rgO=05Bf)>YyPgdL zWHbs9LI!rZV9c!L5WQB7(+0D@idkKv7-QJ5%%@_iS`B1%f#izSatEG;c)Wmjpl&8)qpEoGdf)?TfsO0B14?321P?YyO~h^sDO7=4ABY;1H9X8 zi`o^Ah?7AX%{jAmDT#5A!x1Pa2-bsROw5W|{@0{MZ<^9&o~iK01#L+&7c~Ire`%A+ zsERU^(aER{0w6@h;Z%Z5=maT3oY%$!#kAnC_%mjOLz1YWe|KNgu{|ex56Zj#fgk*| z6P*o>&aU~_H1~(BJ0}-1r{4PT%#{ai=iO_R(=_wUk(}}Q8QZSj?Rhxz(zOM_#+y@G z_IA#)%sKR^W!0<9(nY(?`l(w(0{hwUoCD0{LuWVSFD3^%uO2N=t^W!IOv4Z0(3W^S z@O6(tTzl#4m(%;lM-H!ajDn+A-u749dZ zJLx-6nm<0@@Z2AR7f*JNO>3Bc7@T`~*1f+Qf1W<(KV7`_)JNZ5KB|3wV^L&rwyV_N zGcVVC^7#D|#J*$WL-(gNINxKsoBx`;{^s>_-VR4Cd;W>m^;&6O_&uqMX^3y)& z;CXR;X4i$~S96nKWUaQmVPEsz@98~`+PX83&wbD(5B)H5`{3Rs5C2@