1{ config, lib, pkgs, ... }:
2
3with lib;
4let
5 cfg = config.services.miniflux;
6
7 defaultAddress = "localhost:8080";
8
9 dbUser = "miniflux";
10 dbName = "miniflux";
11
12 pgbin = "${config.services.postgresql.package}/bin";
13 preStart = pkgs.writeScript "miniflux-pre-start" ''
14 #!${pkgs.runtimeShell}
15 ${pgbin}/psql "${dbName}" -c "CREATE EXTENSION IF NOT EXISTS hstore"
16 '';
17in
18
19{
20 options = {
21 services.miniflux = {
22 enable = mkEnableOption (lib.mdDoc "miniflux and creates a local postgres database for it");
23
24 package = mkOption {
25 type = types.package;
26 default = pkgs.miniflux;
27 defaultText = literalExpression "pkgs.miniflux";
28 description = lib.mdDoc "Miniflux package to use.";
29 };
30
31 config = mkOption {
32 type = types.attrsOf types.str;
33 example = literalExpression ''
34 {
35 CLEANUP_FREQUENCY = "48";
36 LISTEN_ADDR = "localhost:8080";
37 }
38 '';
39 description = lib.mdDoc ''
40 Configuration for Miniflux, refer to
41 <https://miniflux.app/docs/configuration.html>
42 for documentation on the supported values.
43
44 Correct configuration for the database is already provided.
45 By default, listens on ${defaultAddress}.
46 '';
47 };
48
49 adminCredentialsFile = mkOption {
50 type = types.path;
51 description = lib.mdDoc ''
52 File containing the ADMIN_USERNAME and
53 ADMIN_PASSWORD (length >= 6) in the format of
54 an EnvironmentFile=, as described by systemd.exec(5).
55 '';
56 example = "/etc/nixos/miniflux-admin-credentials";
57 };
58 };
59 };
60
61 config = mkIf cfg.enable {
62
63 services.miniflux.config = {
64 LISTEN_ADDR = mkDefault defaultAddress;
65 DATABASE_URL = "user=${dbUser} host=/run/postgresql dbname=${dbName}";
66 RUN_MIGRATIONS = "1";
67 CREATE_ADMIN = "1";
68 };
69
70 services.postgresql = {
71 enable = true;
72 ensureUsers = [ {
73 name = dbUser;
74 ensurePermissions = {
75 "DATABASE ${dbName}" = "ALL PRIVILEGES";
76 };
77 } ];
78 ensureDatabases = [ dbName ];
79 };
80
81 systemd.services.miniflux-dbsetup = {
82 description = "Miniflux database setup";
83 requires = [ "postgresql.service" ];
84 after = [ "network.target" "postgresql.service" ];
85 serviceConfig = {
86 Type = "oneshot";
87 User = config.services.postgresql.superUser;
88 ExecStart = preStart;
89 };
90 };
91
92 systemd.services.miniflux = {
93 description = "Miniflux service";
94 wantedBy = [ "multi-user.target" ];
95 requires = [ "miniflux-dbsetup.service" ];
96 after = [ "network.target" "postgresql.service" "miniflux-dbsetup.service" ];
97
98 serviceConfig = {
99 ExecStart = "${cfg.package}/bin/miniflux";
100 User = dbUser;
101 DynamicUser = true;
102 RuntimeDirectory = "miniflux";
103 RuntimeDirectoryMode = "0700";
104 EnvironmentFile = cfg.adminCredentialsFile;
105 # Hardening
106 CapabilityBoundingSet = [ "" ];
107 DeviceAllow = [ "" ];
108 LockPersonality = true;
109 MemoryDenyWriteExecute = true;
110 PrivateDevices = true;
111 PrivateUsers = true;
112 ProcSubset = "pid";
113 ProtectClock = true;
114 ProtectControlGroups = true;
115 ProtectHome = true;
116 ProtectHostname = true;
117 ProtectKernelLogs = true;
118 ProtectKernelModules = true;
119 ProtectKernelTunables = true;
120 ProtectProc = "invisible";
121 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
122 RestrictNamespaces = true;
123 RestrictRealtime = true;
124 RestrictSUIDSGID = true;
125 SystemCallArchitectures = "native";
126 SystemCallFilter = [ "@system-service" "~@privileged" ];
127 UMask = "0077";
128 };
129
130 environment = cfg.config;
131 };
132 environment.systemPackages = [ cfg.package ];
133 };
134}