@@ -0,0 +1,78 @@
1+{ config, pkgs, lib, ... }:
2+
3+with lib;
4+
5+let
6+ cfg = config.services.n8n;
7+ format = pkgs.formats.json {};
8+ configFile = format.generate "n8n.json" cfg.settings;
9+in
10+{
11+ options.services.n8n = {
12+
13+ enable = mkEnableOption "n8n server";
14+
15+ openFirewall = mkOption {
16+ type = types.bool;
17+ default = false;
18+ description = "Open ports in the firewall for the n8n web interface.";
19+ };
20+
21+ settings = mkOption {
22+ type = format.type;
23+ default = {};
24+ description = ''
25+ Configuration for n8n, see <link xlink:href="https://docs.n8n.io/reference/configuration.html"/>
26+ for supported values.
27+ '';
28+ };
29+
30+ };
31+
32+ config = mkIf cfg.enable {
33+ services.n8n.settings = {
34+ # We use this to open the firewall, so we need to know about the default at eval time
35+ port = lib.mkDefault 5678;
36+ };
37+
38+ systemd.services.n8n = {
39+ description = "N8N service";
40+ after = [ "network.target" ];
41+ wantedBy = [ "multi-user.target" ];
42+ environment = {
43+ # This folder must be writeable as the application is storing
44+ # its data in it, so the StateDirectory is a good choice
45+ N8N_USER_FOLDER = "/var/lib/n8n";
46+ N8N_CONFIG_FILES = "${configFile}";
47+ };
48+ serviceConfig = {
49+ Type = "simple";
50+ ExecStart = "${pkgs.n8n}/bin/n8n";
51+ Restart = "on-failure";
52+ StateDirectory = "n8n";
53+
54+ # Basic Hardening
55+ NoNewPrivileges = "yes";
56+ PrivateTmp = "yes";
57+ PrivateDevices = "yes";
58+ DevicePolicy = "closed";
59+ DynamicUser = "true";
60+ ProtectSystem = "strict";
61+ ProtectHome = "read-only";
62+ ProtectControlGroups = "yes";
63+ ProtectKernelModules = "yes";
64+ ProtectKernelTunables = "yes";
65+ RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
66+ RestrictNamespaces = "yes";
67+ RestrictRealtime = "yes";
68+ RestrictSUIDSGID = "yes";
69+ MemoryDenyWriteExecute = "yes";
70+ LockPersonality = "yes";
71+ };
72+ };
73+
74+ networking.firewall = mkIf cfg.openFirewall {
75+ allowedTCPPorts = [ cfg.settings.port ];
76+ };
77+ };
78+}