From 2998c6fe406c1d7ed6a74a276734281b116da03b Mon Sep 17 00:00:00 2001 From: Danilo Reyes Date: Sun, 9 Jun 2024 14:15:32 -0600 Subject: [PATCH] fixed servers/nginx quirks on 24.05 --- hosts/miniserver/configuration.nix | 11 +- hosts/miniserver/nginx.nix | 66 ++++----- hosts/miniserver/servers.nix | 195 ++++++++++---------------- modules/scripts.nix | 17 ++- modules/scripts/nextcloud-cronjob.nix | 13 -- modules/scripts/sub-sync.nix | 13 -- pkgs/shiori/shiori-service.nix | 130 +++++++++++++++++ pkgs/shiori/shiori.nix | 28 ++++ 8 files changed, 285 insertions(+), 188 deletions(-) delete mode 100644 modules/scripts/nextcloud-cronjob.nix delete mode 100644 modules/scripts/sub-sync.nix create mode 100644 pkgs/shiori/shiori-service.nix create mode 100644 pkgs/shiori/shiori.nix diff --git a/hosts/miniserver/configuration.nix b/hosts/miniserver/configuration.nix index f02a21f..6d3f2b8 100644 --- a/hosts/miniserver/configuration.nix +++ b/hosts/miniserver/configuration.nix @@ -22,9 +22,9 @@ in { ffmpreg.enable = true; ffmpeg4discord.enable = true; manage-library.enable = true; - sync-subs.enable = true; pika-list.enable = true; find-dup-episodes.enable = true; + update-dns.enable = true; }; }; fonts.fontconfig.enable = true; @@ -112,14 +112,7 @@ in { # }; }; systemd = { - packages = let - pkgs = import (builtins.fetchTarball { - url = - "https://github.com/NixOS/nixpkgs/archive/9957cd48326fe8dbd52fdc50dd2502307f188b0d.tar.gz"; - }) { }; - - myPkg = pkgs.qbittorrent-nox; - in [ myPkg ]; + packages = [ pkgs.qbittorrent-nox ]; services = { "qbittorrent-nox@jawz" = { enable = true; diff --git a/hosts/miniserver/nginx.nix b/hosts/miniserver/nginx.nix index 8493915..f353107 100644 --- a/hosts/miniserver/nginx.nix +++ b/hosts/miniserver/nginx.nix @@ -2,30 +2,30 @@ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ config, ... }: let localhost = "127.0.0.1"; - workstation = "192.168.1.64"; + # workstation = "192.168.1.64"; domain = "servidos.lat"; jellyfinPort = 8096; - nextcloudPort = 80; + shioriPort = 4368; + # nextcloudPort = 80; collaboraPort = 9980; flamePort = 5005; secretFlamePort = 5007; - lidarrPort = 8686; + # lidarrPort = 8686; qbitPort = 9091; - prowlarrPort = 9696; - radarrPort = 7878; - sonarrPort = 8989; + # prowlarrPort = 9696; + # radarrPort = 7878; + # sonarrPort = 8989; mealiePort = 9925; ryotPort = 8765; scrobblePort = 9078; malojaPort = 42010; darkwirePort = 3001; - jiraPort = 8091; metatubePort = 8881; - bazarrPort = config.services.bazarr.listenPort; - kavitaPort = config.services.kavita.port; + # bazarrPort = config.services.bazarr.listenPort; + # kavitaPort = config.services.kavita.port; vaultPort = config.services.vaultwarden.config.ROCKET_PORT; audiobookPort = config.services.audiobookshelf.port; microbinPort = config.services.microbin.settings.MICROBIN_PORT; @@ -52,21 +52,21 @@ in { http2 = true; }; proxy = port: - base { "/".proxyPass = "http://${localhost}:${toString (port)}/"; }; - proxyArr = port: - proxy port // { - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $http_connection; + base { "/".proxyPass = "http://${localhost}:${toString port}/"; }; + # proxyArr = port: + # proxy port // { + # extraConfig = '' + # proxy_set_header Host $host; + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header X-Forwarded-Host $host; + # proxy_set_header X-Forwarded-Proto $scheme; + # proxy_set_header Upgrade $http_upgrade; + # proxy_set_header Connection $http_connection; - proxy_redirect off; - proxy_http_version 1.1; - ''; - }; + # proxy_redirect off; + # proxy_http_version 1.1; + # ''; + # }; in { # "movies.${domain}" = proxyArr radarrPort // { }; # "indexer.${domain}" = proxyArr prowlarrPort // { }; @@ -81,13 +81,13 @@ in { "tracker.${domain}" = proxy ryotPort // { }; "scrobble.${domain}" = proxy scrobblePort // { }; "maloja.${domain}" = proxy malojaPort // { }; - "jira.${domain}" = proxy jiraPort // { }; + "bookmarks.${domain}" = proxy shioriPort // { }; "bajameesta.${domain}" = proxy metatubePort // { }; "qampqwn4wprhqny8h8zj.${domain}" = proxy secretFlamePort // { }; "xfwmrle6h6skqujbeizw.${domain}" = proxy qbitPort // { }; "audiobooks.${domain}" = base { "/" = { - proxyPass = "http://${localhost}:${toString (audiobookPort)}"; + proxyPass = "http://${localhost}:${toString audiobookPort}"; extraConfig = '' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; @@ -103,7 +103,7 @@ in { }; "dontcancelmeplz.${domain}" = base { "/" = { - proxyPass = "http://${localhost}:${toString (darkwirePort)}"; + proxyPass = "http://${localhost}:${toString darkwirePort}"; proxyWebsockets = true; extraConfig = '' # Ensuring it can use websockets @@ -143,7 +143,7 @@ in { location = /web/ { # Proxy main Jellyfin traffic proxy_pass http://${localhost}:${ - toString (jellyfinPort) + toString jellyfinPort }/web/index.html; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -155,11 +155,11 @@ in { ''; locations = { "/" = { - proxyPass = "http://${localhost}:${toString (jellyfinPort)}"; + proxyPass = "http://${localhost}:${toString jellyfinPort}"; proxyWebsockets = true; }; "/socket" = { - proxyPass = "http://${localhost}:${toString (jellyfinPort)}"; + proxyPass = "http://${localhost}:${toString jellyfinPort}"; extraConfig = '' proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; @@ -167,7 +167,7 @@ in { ''; }; "~ /Items/(.*)/Images" = { - proxyPass = "http://${localhost}:${toString (jellyfinPort)}"; + proxyPass = "http://${localhost}:${toString jellyfinPort}"; extraConfig = '' proxy_cache jellyfin; proxy_cache_revalidate on; @@ -175,7 +175,7 @@ in { ''; }; "~* ^/Videos/(.*)/(?!live)" = { - proxyPass = "http://${localhost}:${toString (jellyfinPort)}"; + proxyPass = "http://${localhost}:${toString jellyfinPort}"; extraConfig = '' # Set size of a slice (this amount will be always requested from the backend by nginx) # Higher value means more latency, lower more overhead @@ -219,7 +219,7 @@ in { }; "collabora.${domain}" = let - collaboraString = "http://${localhost}:${toString (collaboraPort)}"; + collaboraString = "http://${localhost}:${toString collaboraPort}"; collaboraProxy = { proxyPass = collaboraString; extraConfig = '' diff --git a/hosts/miniserver/servers.nix b/hosts/miniserver/servers.nix index 62ee029..0941507 100644 --- a/hosts/miniserver/servers.nix +++ b/hosts/miniserver/servers.nix @@ -1,49 +1,44 @@ -{ config, lib, pkgs, modulesPath, ... }: +{ config, pkgs, ... }: let localhost = "127.0.0.1"; postgresSocket = "/run/postgresql"; - unstable = import - (builtins.fetchTarball "https://github.com/nixos/nixpkgs/tarball/master") { - config = config.nixpkgs.config; - }; in { - - imports = [ ./nginx.nix ]; + disabledModules = [ "services/web-apps/shiori.nix" ]; + imports = [ ./nginx.nix ../../pkgs/shiori/shiori-service.nix ]; nixpkgs.config = { permittedInsecurePackages = [ "nodejs-14.21.3" "openssl-1.1.1v" ]; }; - environment.systemPackages = with pkgs; - [ - # Upgrades postgres - (let - # XXX specify the postgresql package you'd like to upgrade to. - # Do not forget to list the extensions you need. - newPostgres = pkgs.postgresql_16.withPackages (pp: - [ - # pp.plv8 - ]); - in pkgs.writeScriptBin "upgrade-pg-cluster" '' - set -eux - # XXX it's perhaps advisable to stop all services that depend on postgresql - systemctl stop postgresql + environment.systemPackages = [ + # Upgrades postgres + (let + # XXX specify the postgresql package you'd like to upgrade to. + # Do not forget to list the extensions you need. + newPostgres = pkgs.postgresql_16.withPackages (pp: + [ + # pp.plv8 + ]); + in pkgs.writeScriptBin "upgrade-pg-cluster" '' + set -eux + # XXX it's perhaps advisable to stop all services that depend on postgresql + systemctl stop postgresql - export NEWDATA="/var/lib/postgresql/${newPostgres.psqlSchema}" + export NEWDATA="/var/lib/postgresql/${newPostgres.psqlSchema}" - export NEWBIN="${newPostgres}/bin" + export NEWBIN="${newPostgres}/bin" - export OLDDATA="${config.services.postgresql.dataDir}" - export OLDBIN="${config.services.postgresql.package}/bin" + export OLDDATA="${config.services.postgresql.dataDir}" + export OLDBIN="${config.services.postgresql.package}/bin" - install -d -m 0700 -o postgres -g postgres "$NEWDATA" - cd "$NEWDATA" - sudo -u postgres $NEWBIN/initdb -D "$NEWDATA" + install -d -m 0700 -o postgres -g postgres "$NEWDATA" + cd "$NEWDATA" + sudo -u postgres $NEWBIN/initdb -D "$NEWDATA" - sudo -u postgres $NEWBIN/pg_upgrade \ - --old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \ - --old-bindir $OLDBIN --new-bindir $NEWBIN \ - "$@" - '') - ]; + sudo -u postgres $NEWBIN/pg_upgrade \ + --old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \ + --old-bindir $OLDBIN --new-bindir $NEWBIN \ + "$@" + '') + ]; users.groups = { piracy.gid = 985; }; users.users = let base = { isSystemUser = true; }; in { @@ -94,7 +89,7 @@ in { # bazarr = base // { }; jellyfin = base // { }; # prowlarr.enable = true; - jira.enable = true; + # jira.enable = true; microbin = { enable = true; settings = { @@ -107,39 +102,45 @@ in { MICROBIN_ENCRYPTION_SERVER_SIDE = true; }; }; + shiori = { + enable = true; + port = 4368; + package = pkgs.callPackage ../../pkgs/shiori/shiori.nix { }; + httpSecretKey = "password"; + databaseUrl = "postgres:///shiori?host=${postgresSocket}"; + }; # audiobookshelf = { # enable = true; # group = "piracy"; # port = 5687; # }; - # paperless = { - # enable = true; - # address = "0.0.0.0"; - # consumptionDirIsPublic = true; - # consumptionDir = "/home/jawz/Backups/Scans"; - # extraConfig = { - # PAPERLESS_DBENGINE = "postgress"; - # PAPERLESS_DBNAME = "paperless"; - # PAPERLESS_DBHOST = postgresSocket; - # PAPERLESS_CONSUMER_IGNORE_PATTERN = - # builtins.toJSON [ ".DS_STORE/*" "desktop.ini" ]; - # PAPERLESS_TIME_ZONE = "America/Mexico_City"; - # PAPERLESS_OCR_USER_ARGS = builtins.toJSON { - # optimize = 1; - # pdfa_image_compression = "lossless"; - # }; - # }; - # }; + paperless = { + enable = true; + address = "0.0.0.0"; + consumptionDirIsPublic = true; + consumptionDir = "/mnt/pool/scans/"; + settings = { + PAPERLESS_DBENGINE = "postgress"; + PAPERLESS_DBNAME = "paperless"; + PAPERLESS_DBHOST = postgresSocket; + PAPERLESS_CONSUMER_IGNORE_PATTERN = + builtins.toJSON [ ".DS_STORE/*" "desktop.ini" ]; + PAPERLESS_TIME_ZONE = "America/Mexico_City"; + PAPERLESS_OCR_USER_ARGS = builtins.toJSON { + optimize = 1; + pdfa_image_compression = "lossless"; + }; + }; + }; vaultwarden = { enable = true; dbBackend = "postgresql"; package = pkgs.vaultwarden; + environmentFile = "/var/lib/vaultwarden.env"; config = { ROCKET_ADDRESS = "${localhost}"; ROCKET_PORT = 8222; WEBSOCKET_PORT = 8333; - ADMIN_TOKEN = - "x9BLqz2QmnU5RmrMLt2kPpoPBTNPZxNFw/b8XrPgpQML2/01+MYENl87dmhDX+Jm"; DATABASE_URL = "postgresql:///vaultwarden?host=${postgresSocket}"; ENABLE_DB_WAL = false; WEBSOCKET_ENABLED = true; @@ -157,13 +158,16 @@ in { nextcloud = { enable = true; https = true; - package = pkgs.nextcloud28; + package = pkgs.nextcloud29; appstoreEnable = true; configureRedis = true; extraAppsEnable = true; enableImagemagick = true; maxUploadSize = "16G"; hostName = "cloud.servidos.lat"; + extraApps = { + inherit (config.services.nextcloud.package.packages.apps) calendar; + }; config = { adminpassFile = "${pkgs.writeText "adminpass" "Overlying-Hatchback-Charting-Encounter-Deface-Gallantly7"}"; @@ -193,6 +197,8 @@ in { short_open_tag = "Off"; }; settings = { + log_type = "file"; + log_level = 3; trusted_proxies = [ "nginx" ]; trusted_domains = [ "cloud.rotehaare.art" "danilo-reyes.com" ]; overwrite_protocol = "https"; @@ -214,32 +220,17 @@ in { }; phpExtraExtensions = all: [ all.pdlib all.bz2 ]; }; - postgresql = { + postgresql = let + dbNames = + [ "jawz" "paperless" "nextcloud" "ryot" "vaultwarden" "shiori" ]; + in { enable = true; - ensureDatabases = [ "jawz" "paperless" "nextcloud" "ryot" "vaultwarden" ]; + ensureDatabases = dbNames; package = pkgs.postgresql_16; - ensureUsers = [ - { - name = "jawz"; - ensureDBOwnership = true; - } - { - name = "nextcloud"; - ensureDBOwnership = true; - } - { - name = "paperless"; - ensureDBOwnership = true; - } - { - name = "ryot"; - ensureDBOwnership = true; - } - { - name = "vaultwarden"; - ensureDBOwnership = true; - } - ]; + ensureUsers = map (name: { + name = name; + ensureDBOwnership = true; + }) dbNames; authentication = pkgs.lib.mkOverride 10 '' local all all trust host all all ${localhost}/32 trust @@ -249,15 +240,12 @@ in { }; systemd = { services = { + nextcloud-cron = { path = [ pkgs.perl ]; }; # sub-sync = { # restartIfChanged = true; # description = "syncronizes subtitles downloaded & modified today"; # wantedBy = [ "default.target" ]; - # path = [ - # pkgs.bash - # pkgs.nix - # jawzSubs - # ]; + # path = [ pkgs.bash pkgs.nix jawzSubs ]; # serviceConfig = { # Restart = "on-failure"; # RestartSec = 30; @@ -267,16 +255,16 @@ in { # }; # }; nextcloud-cronjob = let - jawzNextcloudCronjob = pkgs.writeScriptBin "nextcloud-cronjob" + nextcloud-cronjob = pkgs.writeScriptBin "nextcloud-cronjob" (builtins.readFile ../../scripts/nextcloud-cronjob.sh); in { description = "Runs various nextcloud-related cronjobs"; wantedBy = [ "multi-user.target" ]; - path = [ pkgs.bash jawzNextcloudCronjob ]; + path = [ pkgs.bash nextcloud-cronjob ]; serviceConfig = { Restart = "on-failure"; RestartSec = 30; - ExecStart = "${jawzNextcloudCronjob}/bin/nextcloud-cronjob"; + ExecStart = "${nextcloud-cronjob}/bin/nextcloud-cronjob"; }; }; }; @@ -291,38 +279,9 @@ in { # enable = true; # description = "syncronizes subtitles downloaded & modified today"; # wantedBy = [ "timers.target" ]; - # timerConfig = { - # OnCalendar = "22:00"; - # }; + # timerConfig = { OnCalendar = "22:00"; }; # }; }; - user.services = { - update-dns = let - jawzUpdateDns = pkgs.writeScriptBin "update-dns" - (builtins.readFile ../../scripts/update-dns.sh); - in { - restartIfChanged = true; - description = "update DNS of my websites"; - wantedBy = [ "default.target" ]; - path = [ pkgs.bash pkgs.nix jawzUpdateDns ]; - serviceConfig = { - Restart = "on-failure"; - RestartSec = 30; - ExecStart = "${jawzUpdateDns}/bin/update-dns"; - }; - }; - }; - user.timers = { - update-dns = { - enable = true; - description = "update DNS of my websites"; - wantedBy = [ "timers.target" ]; - timerConfig = { - OnBootSec = "1min"; - OnUnitActiveSec = "30m"; - }; - }; - }; }; networking = { diff --git a/modules/scripts.nix b/modules/scripts.nix index 5d5c2e8..4eb7cab 100644 --- a/modules/scripts.nix +++ b/modules/scripts.nix @@ -5,12 +5,25 @@ ./scripts/ffmpreg.nix ./scripts/find-dup-episode.nix ./scripts/manage-library.nix - ./scripts/nextcloud-cronjob.nix ./scripts/pika-list.nix ./scripts/run.nix ./scripts/split-dir.nix - ./scripts/sub-sync.nix ./scripts/tasks.nix ./scripts/update-dns.nix ]; +<<<<<<< HEAD +======= + my.scripts = { + download.enable = lib.mkDefault false; + ffmpeg4discord.enable = lib.mkDefault false; + ffmpreg.enable = lib.mkDefault false; + find-dup-episodes.enable = lib.mkDefault false; + manage-library.enable = lib.mkDefault false; + pika-list.enable = lib.mkDefault false; + run.enable = lib.mkDefault false; + split-dir.enable = lib.mkDefault false; + tasks.enable = lib.mkDefault false; + update-dns.enable = lib.mkDefault false; + }; +>>>>>>> f7500a4 (fixed servers/nginx quirks on 24.05) } diff --git a/modules/scripts/nextcloud-cronjob.nix b/modules/scripts/nextcloud-cronjob.nix deleted file mode 100644 index 3c51592..0000000 --- a/modules/scripts/nextcloud-cronjob.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ pkgs, ... }: { - imports = [ ./base.nix ]; - config.my.scripts.nextcloud-cronjob = { - enable = true; - install = false; - service = true; - timer = "*:0/10"; - name = "nextcloud-cronjob"; - description = "runs tasks for nextcloud"; - package = pkgs.writeScriptBin "nextcloud-cronjob" - (builtins.readFile ../../scripts/nextcloud-cronjob.sh); - }; -} diff --git a/modules/scripts/sub-sync.nix b/modules/scripts/sub-sync.nix deleted file mode 100644 index cd057c5..0000000 --- a/modules/scripts/sub-sync.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ pkgs, ... }: { - imports = [ ./base.nix ]; - config.my.scripts.sub-sync = { - enable = true; - install = true; - service = true; - name = "sub-sync"; - timer = "22:00"; - description = "Syncronixes subtitles downloaded and modified the last day"; - package = pkgs.writeScriptBin "sub-sync" - (builtins.readFile ../../scripts/sub-sync.sh); - }; -} diff --git a/pkgs/shiori/shiori-service.nix b/pkgs/shiori/shiori-service.nix new file mode 100644 index 0000000..47c2ae6 --- /dev/null +++ b/pkgs/shiori/shiori-service.nix @@ -0,0 +1,130 @@ +{ config, lib, pkgs, ... }: + +with lib; +let cfg = config.services.shiori; +in { + options = { + services.shiori = { + enable = mkEnableOption "Shiori simple bookmarks manager"; + + package = mkPackageOption pkgs "shiori" { }; + + address = mkOption { + type = types.str; + default = ""; + description = '' + The IP address on which Shiori will listen. + If empty, listens on all interfaces. + ''; + }; + + port = mkOption { + type = types.port; + default = 8080; + description = "The port of the Shiori web application"; + }; + + webRoot = mkOption { + type = types.str; + default = "/"; + example = "/shiori"; + description = "The root of the Shiori web application"; + }; + + httpSecretKey = mkOption { + type = types.str; + example = "SuperSecretPassword"; + description = + "When empty all sessions will be invalidated on server restart"; + }; + + databaseUrl = mkOption { + type = types.str; + default = ""; + example = "postgresql:///shiori?host=/run/postgresql"; + description = "The connection URL to connect to MySQL or PostgreSQL"; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.shiori = with cfg; { + description = "Shiori simple bookmarks manager"; + wantedBy = [ "multi-user.target" ]; + + environment = { + SHIORI_DIR = "/var/lib/shiori"; + } // lib.optionalAttrs (cfg.databaseUrl != "") { + SHIORI_DATABASE_URL = cfg.databaseUrl; + } // lib.optionalAttrs (cfg.httpSecretKey != "") { + SHIORI_HTTP_SECRET_KEY = cfg.httpSecretKey; + }; + + serviceConfig = { + ExecStart = + "${package}/bin/shiori server --address '${address}' --port '${ + toString port + }' --webroot '${webRoot}'"; + + DynamicUser = true; + StateDirectory = "shiori"; + # As the RootDirectory + RuntimeDirectory = "shiori"; + + # Security options + + BindReadOnlyPaths = [ + "/nix/store" + + # For SSL certificates, and the resolv.conf + "/etc" + ] ++ lib.optional (lib.strings.hasInfix "postgres" cfg.databaseUrl) + "/run/postgresql" + ++ lib.optional (lib.strings.hasInfix "mysql" cfg.databaseUrl) + "/var/run/mysqld"; + + CapabilityBoundingSet = ""; + AmbientCapabilities = "CAP_NET_BIND_SERVICE"; + + DeviceAllow = ""; + + LockPersonality = true; + + MemoryDenyWriteExecute = true; + + PrivateDevices = true; + PrivateUsers = true; + + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + + RestrictNamespaces = true; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; + RestrictRealtime = true; + RestrictSUIDSGID = true; + + RootDirectory = "/run/shiori"; + + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = [ + "@system-service" + "~@cpu-emulation" + "~@debug" + "~@keyring" + "~@memlock" + "~@obsolete" + "~@privileged" + "~@setuid" + ]; + }; + }; + }; + + meta.maintainers = with maintainers; [ minijackson CaptainJawZ ]; +} diff --git a/pkgs/shiori/shiori.nix b/pkgs/shiori/shiori.nix new file mode 100644 index 0000000..51239ad --- /dev/null +++ b/pkgs/shiori/shiori.nix @@ -0,0 +1,28 @@ +{ lib, buildGoModule, fetchFromGitHub, nixosTests }: + +buildGoModule rec { + pname = "shiori"; + version = "1.6.2"; + + vendorHash = "sha256-LLiBRsh9HsadeHQh4Yvops1r2GfjtvQKt5ZelQnPGdI="; + + doCheck = false; + + src = fetchFromGitHub { + owner = "go-shiori"; + repo = pname; + rev = "v${version}"; + sha256 = "sha256-1ZZpQXlAHs5MTowCv3sWS3L7X5FTnU/b4trvHPiz+uE="; + }; + + passthru.tests = { + smoke-test = nixosTests.shiori; + }; + + meta = with lib; { + description = "Simple bookmark manager built with Go"; + homepage = "https://github.com/go-shiori/shiori"; + license = licenses.mit; + maintainers = with maintainers; [ minijackson ]; + }; +}