1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.neo4j;
7
8 serverConfig = pkgs.writeText "neo4j.conf" ''
9 dbms.directories.data=${cfg.dataDir}/data
10 dbms.directories.certificates=${cfg.certDir}
11 dbms.directories.logs=${cfg.dataDir}/logs
12 dbms.directories.plugins=${cfg.dataDir}/plugins
13 dbms.connector.http.type=HTTP
14 dbms.connector.http.enabled=true
15 dbms.connector.http.address=${cfg.listenAddress}:${toString cfg.port}
16 ${optionalString cfg.enableBolt ''
17 dbms.connector.bolt.type=BOLT
18 dbms.connector.bolt.enabled=true
19 dbms.connector.bolt.tls_level=OPTIONAL
20 dbms.connector.bolt.address=${cfg.listenAddress}:${toString cfg.boltPort}
21 ''}
22 ${optionalString cfg.enableHttps ''
23 dbms.connector.https.type=HTTP
24 dbms.connector.https.enabled=true
25 dbms.connector.https.encryption=TLS
26 dbms.connector.https.address=${cfg.listenAddress}:${toString cfg.httpsPort}
27 ''}
28 dbms.shell.enabled=true
29 ${cfg.extraServerConfig}
30
31 # Default JVM parameters from neo4j.conf
32 dbms.jvm.additional=-XX:+UseG1GC
33 dbms.jvm.additional=-XX:-OmitStackTraceInFastThrow
34 dbms.jvm.additional=-XX:+AlwaysPreTouch
35 dbms.jvm.additional=-XX:+UnlockExperimentalVMOptions
36 dbms.jvm.additional=-XX:+TrustFinalNonStaticFields
37 dbms.jvm.additional=-XX:+DisableExplicitGC
38 dbms.jvm.additional=-Djdk.tls.ephemeralDHKeySize=2048
39
40 dbms.jvm.additional=-Dunsupported.dbms.udc.source=tarball
41 '';
42
43in {
44
45 ###### interface
46
47 options.services.neo4j = {
48 enable = mkOption {
49 description = "Whether to enable neo4j.";
50 default = false;
51 type = types.bool;
52 };
53
54 package = mkOption {
55 description = "Neo4j package to use.";
56 default = pkgs.neo4j;
57 defaultText = "pkgs.neo4j";
58 type = types.package;
59 };
60
61 listenAddress = mkOption {
62 description = "Neo4j listen address.";
63 default = "127.0.0.1";
64 type = types.str;
65 };
66
67 port = mkOption {
68 description = "Neo4j port to listen for HTTP traffic.";
69 default = 7474;
70 type = types.int;
71 };
72
73 enableBolt = mkOption {
74 description = "Enable bolt for Neo4j.";
75 default = true;
76 type = types.bool;
77 };
78
79 boltPort = mkOption {
80 description = "Neo4j port to listen for BOLT traffic.";
81 default = 7687;
82 type = types.int;
83 };
84
85 enableHttps = mkOption {
86 description = "Enable https for Neo4j.";
87 default = false;
88 type = types.bool;
89 };
90
91 httpsPort = mkOption {
92 description = "Neo4j port to listen for HTTPS traffic.";
93 default = 7473;
94 type = types.int;
95 };
96
97 certDir = mkOption {
98 description = "Neo4j TLS certificates directory.";
99 default = "${cfg.dataDir}/certificates";
100 type = types.path;
101 };
102
103 dataDir = mkOption {
104 description = "Neo4j data directory.";
105 default = "/var/lib/neo4j";
106 type = types.path;
107 };
108
109 extraServerConfig = mkOption {
110 description = "Extra configuration for neo4j server.";
111 default = "";
112 type = types.lines;
113 };
114 };
115
116 ###### implementation
117
118 config = mkIf cfg.enable {
119 systemd.services.neo4j = {
120 description = "Neo4j Daemon";
121 wantedBy = [ "multi-user.target" ];
122 after = [ "network.target" ];
123 environment = {
124 NEO4J_HOME = "${cfg.package}/share/neo4j";
125 NEO4J_CONF = "${cfg.dataDir}/conf";
126 };
127 serviceConfig = {
128 ExecStart = "${cfg.package}/bin/neo4j console";
129 User = "neo4j";
130 PermissionsStartOnly = true;
131 LimitNOFILE = 40000;
132 };
133 preStart = ''
134 mkdir -m 0700 -p ${cfg.dataDir}/{data/graph.db,conf,logs}
135 ln -fs ${serverConfig} ${cfg.dataDir}/conf/neo4j.conf
136 if [ "$(id -u)" = 0 ]; then chown -R neo4j ${cfg.dataDir}; fi
137 '';
138 };
139
140 environment.systemPackages = [ cfg.package ];
141
142 users.extraUsers = singleton {
143 name = "neo4j";
144 uid = config.ids.uids.neo4j;
145 description = "Neo4j daemon user";
146 home = cfg.dataDir;
147 };
148 };
149}