sid.ovh/modules/nixos/rsshub-oci/default.nix
sid f1d652f370
All checks were successful
Flake check / flake-check (pull_request) Successful in 25s
Build hosts / build-hosts (pull_request) Successful in 28s
corrected port
2026-05-05 20:13:49 +02:00

199 lines
6.1 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.rsshub-oci;
domain = config.networking.domain;
subdomain = cfg.reverseProxy.subdomain;
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
images = {
# https://github.com/DIYgod/RSSHub/pkgs/container/rsshub
rsshub = pkgs.dockerTools.pullImage {
imageName = "ghcr.io/diygod/rsshub";
imageDigest = "sha256:93660573e0fbfe1062e4fc512acf5043e1399519cdd9a11f130a8332306e8fdd";
hash = "sha256-cP2RnV6zmLoYzHgvuuHpqlRcNngD+YFRfRkFMNFQxG8=";
finalImageName = "ghcr.io/diygod/rsshub";
finalImageTag = "2026-05-04";
};
# https://github.com/browserless/browserless/pkgs/container/chromium
browserless = pkgs.dockerTools.pullImage {
imageName = "ghcr.io/browserless/chromium";
imageDigest = "sha256:af3483eb7f125978d511df0d227d37931941b43d2cdb5f768da57263a7a132bf";
hash = "sha256-qKx/I9X/GTnoWpHY3gtZUoeL65ndOzU29bGjR6QLYp4=";
finalImageName = "ghcr.io/browserless/chromium";
finalImageTag = "v2.48.2";
};
# https://github.com/hyoban/puppeteer-real-browser-hono/pkgs/container/puppeteer-real-browser-hono
real-browser = pkgs.dockerTools.pullImage {
imageName = "ghcr.io/hyoban/puppeteer-real-browser-hono";
imageDigest = "sha256:21bb4cd27144a61ca2f85eb3b4f555a074165bc6beaee318873ced0eb4046a04";
hash = "sha256-O8qV8Wfh75rhtEnSAlUBzBUVNGpypNF1sNY2F4zVqZE=";
finalImageName = "ghcr.io/hyoban/puppeteer-real-browser-hono";
finalImageTag = "sha-6c6cbbc";
};
# https://hub.docker.com/_/redis
redis = pkgs.dockerTools.pullImage {
imageName = "redis";
imageDigest = "sha256:c5e375abb885e6b2021c0377879e4890bf76f9065b8922ffc113f2b226b9fc17";
hash = "sha256-ls1be+fp+chENJ7OrYng5EY3zdHsfiZCW3fmvwzwzj8=";
finalImageName = "redis";
finalImageTag = "8.6.2-alpine";
};
};
defaultEnv = {
NODE_ENV = "production";
CACHE_TYPE = "redis";
REDIS_URL = "redis://127.0.0.1:6379/";
PUPPETEER_WS_ENDPOINT = "ws://127.0.0.1:3000";
PUPPETEER_REAL_BROWSER_SERVICE = "http://127.0.0.1:3001";
};
inherit (lib)
mkEnableOption
mkIf
mkOption
mkOverride
optional
types
;
inherit (lib.utils)
mkReverseProxyOption
mkVirtualHost
;
in
{
options.services.rsshub-oci = {
enable = mkEnableOption "RSSHub service stack with Podman";
port = mkOption {
type = types.port;
default = 1200;
description = "The port RSSHub will listen on.";
};
environment = mkOption {
type = types.attrsOf types.str;
default = { };
description = "Extra environment variables for RSSHub.";
};
environmentFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Environment file for secrets.";
};
reverseProxy = mkReverseProxyOption "RSSHub" "rsshub";
};
config = mkIf cfg.enable {
virtualisation.podman = {
enable = true;
autoPrune.enable = true;
dockerCompat = true;
};
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
"${fqdn}" = mkVirtualHost {
inherit (cfg) port;
ssl = cfg.reverseProxy.forceSSL;
};
};
networking.firewall.interfaces =
let
matchAll = if !config.networking.nftables.enable then "podman+" else "podman*";
in
{
"${matchAll}".allowedUDPPorts = [ 53 ];
};
virtualisation.oci-containers.backend = "podman";
virtualisation.oci-containers.containers = {
rsshub-browserless = {
image = with images.browserless; imageName + ":" + imageTag;
imageFile = images.browserless;
log-driver = "journald";
extraOptions = [ "--network=host" ];
};
rsshub-real-browser = {
image = with images.real-browser; imageName + ":" + imageTag;
imageFile = images.real-browser;
log-driver = "journald";
environment = {
PORT = "3001";
};
extraOptions = [ "--network=host" ];
};
rsshub-redis = {
image = with images.redis; imageName + ":" + imageTag;
imageFile = images.redis;
volumes = [ "rsshub_redis-data:/data:rw" ];
log-driver = "journald";
extraOptions = [ "--network=host" ];
};
rsshub-rsshub = {
image = with images.rsshub; imageName + ":" + imageTag;
imageFile = images.rsshub;
log-driver = "journald";
environment =
defaultEnv
// cfg.environment
// {
PORT = "${toString cfg.port}";
};
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
extraOptions = [ "--network=host" ];
};
};
systemd.services =
let
commonServiceCfg = {
serviceConfig.Restart = mkOverride 90 "always";
partOf = [ "podman-compose-rsshub-root.target" ];
wantedBy = [ "podman-compose-rsshub-root.target" ];
};
in
{
podman-rsshub-browserless = commonServiceCfg;
podman-rsshub-real-browser = commonServiceCfg;
podman-rsshub-redis = commonServiceCfg // {
after = [ "podman-volume-rsshub_redis-data.service" ];
requires = [ "podman-volume-rsshub_redis-data.service" ];
};
podman-rsshub-rsshub = commonServiceCfg // {
after = [
"podman-rsshub-redis.service"
"podman-rsshub-browserless.service"
"podman-rsshub-real-browser.service"
];
};
podman-volume-rsshub_redis-data = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect rsshub_redis-data || podman volume create rsshub_redis-data
'';
partOf = [ "podman-compose-rsshub-root.target" ];
wantedBy = [ "podman-compose-rsshub-root.target" ];
};
};
systemd.targets."podman-compose-rsshub-root" = {
unitConfig.Description = "Root target for RSSHub services.";
wantedBy = [ "multi-user.target" ];
};
};
}