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