-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Expand file tree
/
Copy pathflake.nix
More file actions
322 lines (284 loc) · 9.88 KB
/
flake.nix
File metadata and controls
322 lines (284 loc) · 9.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
{
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_10;
deps = pkgs.fetchPnpmDeps {
pname = "rsshub";
src = ./.;
hash = "sha256-QG1cIkZh+qBA5Dipt0iDLuQpEOI45wdFhuG/CTcRVU8=";
fetcherVersion = 2;
};
in
pkgs.stdenv.mkDerivation rec {
pname = "rsshub";
version = "1.0.0";
src = ./.;
nativeBuildInputs = with pkgs; [
nodejs_22
pnpm
pnpmConfigHook
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.
'';
};
environmentFiles = mkOption {
type = types.listOf types.path;
default = [ ];
example = literalExpression ''
[ config.sops.secrets.rsshub.path ]
'';
description = ''
Environment variables stored in files for RSSHub.
It can be used for secrets like agenix, sops-nix, etc.
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] ++ cfg.environmentFiles;
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";
};
}
);
}