mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-01-14 15:44:24 +00:00
* refactor: replace art template with jsx * fix: tsx files * fix: renderToString import * fix: hono html raw import * feat: remove art
309 lines
9.3 KiB
Nix
309 lines
9.3 KiB
Nix
{
|
||
description = "RSSHub - Make RSS Great Again!";
|
||
|
||
inputs = {
|
||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||
flake-utils.url = "github:numtide/flake-utils";
|
||
devenv.url = "github:cachix/devenv";
|
||
};
|
||
|
||
outputs = inputs@{ self, nixpkgs, flake-utils, devenv }:
|
||
let
|
||
# Helper to define the RSSHub package
|
||
makeRSSHub = pkgs:
|
||
let
|
||
pnpm = pkgs.pnpm_9;
|
||
deps = pnpm.fetchDeps {
|
||
pname = "rsshub";
|
||
src = ./.;
|
||
hash = "sha256-ErMPvlOIDqn03s2P+tzbQbYPZFEax5P61O1DJputvo4=";
|
||
fetcherVersion = 2;
|
||
};
|
||
in
|
||
pkgs.stdenv.mkDerivation rec {
|
||
pname = "rsshub";
|
||
version = "1.0.0";
|
||
|
||
src = ./.;
|
||
|
||
nativeBuildInputs = with pkgs; [
|
||
nodejs_22
|
||
pnpm.configHook
|
||
git
|
||
];
|
||
|
||
buildInputs = with pkgs; [
|
||
# Optional: Add chromium for routes that need browser automation
|
||
# chromium
|
||
];
|
||
|
||
pnpmDeps = deps;
|
||
|
||
# 修补构建脚本以支持离线构建(Nix 构建环境无网络访问)
|
||
postPatch = ''
|
||
# 在 registry.ts 中添加 BUILD_ROUTES 模式,使用 directoryImport 但不实际导入模块
|
||
substituteInPlace lib/registry.ts \
|
||
--replace-fail 'if (config.isPackage)' \
|
||
'if (process.env.BUILD_ROUTES_MODE) {
|
||
modules = directoryImport({
|
||
targetDirectoryPath: path.join(__dirname, "./routes"),
|
||
importPattern: /\.tsx?$/,
|
||
}) as typeof modules;
|
||
} else if (config.isPackage)'
|
||
'';
|
||
|
||
# The build phase
|
||
buildPhase = ''
|
||
runHook preBuild
|
||
|
||
# 先构建路由元数据(使用 directoryImport 但避免执行模块顶层代码)
|
||
export BUILD_ROUTES_MODE=1
|
||
pnpm run build:routes
|
||
unset BUILD_ROUTES_MODE
|
||
|
||
# 然后构建应用
|
||
export NODE_ENV=production
|
||
${pnpm}/bin/pnpm run build
|
||
|
||
runHook postBuild
|
||
'';
|
||
|
||
# The install phase
|
||
installPhase = ''
|
||
runHook preInstall
|
||
mkdir -p $out/lib/rsshub
|
||
cp -r dist $out/lib/rsshub/
|
||
cp -r node_modules $out/lib/rsshub/
|
||
cp package.json $out/lib/rsshub/
|
||
|
||
mkdir -p $out/bin
|
||
cat > $out/bin/rsshub <<EOF
|
||
#!${pkgs.bash}/bin/bash
|
||
export NODE_ENV=production
|
||
export NODE_OPTIONS='--max-http-header-size=32768'
|
||
exec ${pkgs.nodejs_22}/bin/node $out/lib/rsshub/dist/index.mjs "\$@"
|
||
EOF
|
||
chmod +x $out/bin/rsshub
|
||
runHook postInstall
|
||
'';
|
||
|
||
meta = with pkgs.lib; {
|
||
description = "Everything is RSSible";
|
||
homepage = "https://github.com/DIYgod/RSSHub";
|
||
license = licenses.mit;
|
||
maintainers = [ ];
|
||
platforms = platforms.all;
|
||
};
|
||
};
|
||
|
||
# NixOS module definition
|
||
makeNixOSModule = { lib, pkgs, config, ... }:
|
||
with lib;
|
||
let
|
||
cfg = config.services.rsshub;
|
||
in
|
||
{
|
||
options.services.rsshub = {
|
||
enable = mkEnableOption "RSSHub service";
|
||
|
||
package = mkOption {
|
||
type = types.package;
|
||
default = makeRSSHub pkgs;
|
||
defaultText = literalExpression "pkgs.rsshub";
|
||
description = "The RSSHub package to use.";
|
||
};
|
||
|
||
port = mkOption {
|
||
type = types.port;
|
||
default = 1200;
|
||
description = "Port on which RSSHub will listen.";
|
||
};
|
||
|
||
listenAddress = mkOption {
|
||
type = types.str;
|
||
default = "0.0.0.0";
|
||
description = "Address on which RSSHub will listen.";
|
||
};
|
||
|
||
openFirewall = mkOption {
|
||
type = types.bool;
|
||
default = false;
|
||
description = "Whether to open the firewall for the specified port.";
|
||
};
|
||
|
||
user = mkOption {
|
||
type = types.str;
|
||
default = "rsshub";
|
||
description = "User account under which RSSHub runs.";
|
||
};
|
||
|
||
group = mkOption {
|
||
type = types.str;
|
||
default = "rsshub";
|
||
description = "Group under which RSSHub runs.";
|
||
};
|
||
|
||
dataDir = mkOption {
|
||
type = types.path;
|
||
default = "/var/lib/rsshub";
|
||
description = "Directory for RSSHub data.";
|
||
};
|
||
|
||
environment = mkOption {
|
||
type = types.attrsOf types.str;
|
||
default = { };
|
||
example = literalExpression ''
|
||
{
|
||
PORT = "1200";
|
||
CACHE_TYPE = "redis";
|
||
REDIS_URL = "redis://localhost:6379/";
|
||
ALLOW_LOCALHOST = "true";
|
||
}
|
||
'';
|
||
description = ''
|
||
Environment variables for RSSHub.
|
||
See https://docs.rsshub.app/deploy/config for available options.
|
||
'';
|
||
};
|
||
|
||
redis = {
|
||
enable = mkOption {
|
||
type = types.bool;
|
||
default = false;
|
||
description = "Whether to enable and configure Redis for caching.";
|
||
};
|
||
|
||
createLocally = mkOption {
|
||
type = types.bool;
|
||
default = true;
|
||
description = "Whether to create a local Redis instance.";
|
||
};
|
||
|
||
url = mkOption {
|
||
type = types.str;
|
||
default = "redis://localhost:6379/";
|
||
description = "Redis connection URL.";
|
||
};
|
||
};
|
||
};
|
||
|
||
config = mkIf cfg.enable (
|
||
let
|
||
baseEnv = cfg.environment;
|
||
redisEnv = optionalAttrs cfg.redis.enable {
|
||
CACHE_TYPE = "redis";
|
||
REDIS_URL = cfg.redis.url;
|
||
};
|
||
derivedEnv =
|
||
{
|
||
PORT = toString cfg.port;
|
||
}
|
||
// optionalAttrs (cfg.listenAddress == "0.0.0.0") {
|
||
LISTEN_INADDR_ANY = "1";
|
||
};
|
||
finalEnv = baseEnv // redisEnv // derivedEnv;
|
||
environmentFile = pkgs.writeText "rsshub.env" (
|
||
concatStringsSep "\n" (
|
||
mapAttrsToList (name: value: "${name}=${toString value}") finalEnv
|
||
)
|
||
);
|
||
in
|
||
{
|
||
# Set up Redis if enabled
|
||
services.redis.servers.rsshub = mkIf (cfg.redis.enable && cfg.redis.createLocally) {
|
||
enable = true;
|
||
port = 6379;
|
||
};
|
||
|
||
# Create user and group
|
||
users.users.${cfg.user} = {
|
||
isSystemUser = true;
|
||
group = cfg.group;
|
||
home = cfg.dataDir;
|
||
createHome = true;
|
||
description = "RSSHub service user";
|
||
};
|
||
|
||
users.groups.${cfg.group} = { };
|
||
|
||
# SystemD service
|
||
systemd.services.rsshub = {
|
||
description = "RSSHub - Everything is RSSible";
|
||
wantedBy = [ "multi-user.target" ];
|
||
after = [ "network.target" ] ++ optional (cfg.redis.enable && cfg.redis.createLocally) "redis-rsshub.service";
|
||
requires = optional (cfg.redis.enable && cfg.redis.createLocally) "redis-rsshub.service";
|
||
|
||
serviceConfig = {
|
||
Type = "simple";
|
||
User = cfg.user;
|
||
Group = cfg.group;
|
||
WorkingDirectory = cfg.dataDir;
|
||
EnvironmentFile = environmentFile;
|
||
ExecStart = "${cfg.package}/bin/rsshub";
|
||
Restart = "on-failure";
|
||
RestartSec = "5s";
|
||
|
||
# Hardening
|
||
NoNewPrivileges = true;
|
||
PrivateTmp = true;
|
||
ProtectSystem = "strict";
|
||
ProtectHome = true;
|
||
ReadWritePaths = [ cfg.dataDir ];
|
||
ProtectKernelTunables = true;
|
||
ProtectKernelModules = true;
|
||
ProtectControlGroups = true;
|
||
};
|
||
};
|
||
|
||
# Open firewall if requested
|
||
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
|
||
}
|
||
);
|
||
};
|
||
|
||
in
|
||
{
|
||
# NixOS module
|
||
nixosModules.default = makeNixOSModule;
|
||
nixosModules.rsshub = makeNixOSModule;
|
||
|
||
# Overlay
|
||
overlays.default = final: prev: {
|
||
rsshub = makeRSSHub final;
|
||
};
|
||
}
|
||
//
|
||
# Per-system outputs
|
||
flake-utils.lib.eachDefaultSystem (system:
|
||
let
|
||
pkgs = nixpkgs.legacyPackages.${system};
|
||
in
|
||
{
|
||
# Package
|
||
packages = {
|
||
default = makeRSSHub pkgs;
|
||
rsshub = makeRSSHub pkgs;
|
||
};
|
||
|
||
# Development shell using devenv
|
||
devShells.default = devenv.lib.mkShell {
|
||
inherit inputs pkgs;
|
||
modules = [
|
||
{
|
||
# devenv requires knowing the project root
|
||
# https://devenv.sh/guides/using-with-flakes/
|
||
packages = [ ];
|
||
}
|
||
./devenv.nix
|
||
];
|
||
};
|
||
|
||
# Apps
|
||
apps.default = {
|
||
type = "app";
|
||
program = "${self.packages.${system}.default}/bin/rsshub";
|
||
};
|
||
}
|
||
);
|
||
}
|