1{ config, pkgs, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.services.n8n;
7 format = pkgs.formats.json {};
8 configFile = format.generate "n8n.json" cfg.settings;
9in
10{
11 options.services.n8n = {
12
13 enable = mkEnableOption (lib.mdDoc "n8n server");
14
15 openFirewall = mkOption {
16 type = types.bool;
17 default = false;
18 description = lib.mdDoc "Open ports in the firewall for the n8n web interface.";
19 };
20
21 settings = mkOption {
22 type = format.type;
23 default = {};
24 description = lib.mdDoc ''
25 Configuration for n8n, see <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 HOME = "/var/lib/n8n";
47 N8N_CONFIG_FILES = "${configFile}";
48 };
49 serviceConfig = {
50 Type = "simple";
51 ExecStart = "${pkgs.n8n}/bin/n8n";
52 Restart = "on-failure";
53 StateDirectory = "n8n";
54
55 # Basic Hardening
56 NoNewPrivileges = "yes";
57 PrivateTmp = "yes";
58 PrivateDevices = "yes";
59 DevicePolicy = "closed";
60 DynamicUser = "true";
61 ProtectSystem = "strict";
62 ProtectHome = "read-only";
63 ProtectControlGroups = "yes";
64 ProtectKernelModules = "yes";
65 ProtectKernelTunables = "yes";
66 RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
67 RestrictNamespaces = "yes";
68 RestrictRealtime = "yes";
69 RestrictSUIDSGID = "yes";
70 MemoryDenyWriteExecute = "no"; # v8 JIT requires memory segments to be Writable-Executable.
71 LockPersonality = "yes";
72 };
73 };
74
75 networking.firewall = mkIf cfg.openFirewall {
76 allowedTCPPorts = [ cfg.settings.port ];
77 };
78 };
79}