diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-05-17 00:49:27 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-05-17 01:31:05 +0200 |
commit | 182ae57f53731be220075bc87aff4d47a35563b8 (patch) | |
tree | 79b523057406db394668bbfd720660d6a1e24094 /modules/private | |
parent | 6c97d2d715620a1cdc3b8a785174590ec0dafb98 (diff) | |
download | Nix-182ae57f53731be220075bc87aff4d47a35563b8.tar.gz Nix-182ae57f53731be220075bc87aff4d47a35563b8.tar.zst Nix-182ae57f53731be220075bc87aff4d47a35563b8.zip |
Move databases configs to modules
Diffstat (limited to 'modules/private')
-rw-r--r-- | modules/private/databases/default.nix | 18 | ||||
-rw-r--r-- | modules/private/databases/mariadb.nix | 125 | ||||
-rw-r--r-- | modules/private/databases/openldap/default.nix | 130 | ||||
-rw-r--r-- | modules/private/databases/openldap/immae.schema | 167 | ||||
-rw-r--r-- | modules/private/databases/postgresql.nix | 141 | ||||
-rw-r--r-- | modules/private/databases/redis.nix | 57 | ||||
-rw-r--r-- | modules/private/default.nix | 6 |
7 files changed, 644 insertions, 0 deletions
diff --git a/modules/private/databases/default.nix b/modules/private/databases/default.nix new file mode 100644 index 0000000..78d91dc --- /dev/null +++ b/modules/private/databases/default.nix | |||
@@ -0,0 +1,18 @@ | |||
1 | { lib, config, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databases; | ||
4 | in | ||
5 | { | ||
6 | options.myServices = { | ||
7 | databases.enable = lib.mkEnableOption "my databases service"; | ||
8 | databasesCerts = lib.mkOption { | ||
9 | description = "Default databases configurations for certificates as accepted by acme"; | ||
10 | }; | ||
11 | }; | ||
12 | config.myServices.databases = lib.mkIf cfg.enable { | ||
13 | mariadb.enable = true; | ||
14 | openldap.enable = true; | ||
15 | postgresql.enable = true; | ||
16 | redis.enable = true; | ||
17 | }; | ||
18 | } | ||
diff --git a/modules/private/databases/mariadb.nix b/modules/private/databases/mariadb.nix new file mode 100644 index 0000000..21f4359 --- /dev/null +++ b/modules/private/databases/mariadb.nix | |||
@@ -0,0 +1,125 @@ | |||
1 | { lib, pkgs, config, myconfig, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databases.mariadb; | ||
4 | in { | ||
5 | options.myServices.databases = { | ||
6 | mariadb = { | ||
7 | enable = lib.mkOption { | ||
8 | default = cfg.enable; | ||
9 | example = true; | ||
10 | description = "Whether to enable mariadb database"; | ||
11 | type = lib.types.bool; | ||
12 | }; | ||
13 | dataDir = lib.mkOption { | ||
14 | type = lib.types.path; | ||
15 | default = "/var/lib/mysql"; | ||
16 | description = '' | ||
17 | The directory where Mariadb stores its data. | ||
18 | ''; | ||
19 | }; | ||
20 | # Output variables | ||
21 | socketsDir = lib.mkOption { | ||
22 | type = lib.types.path; | ||
23 | default = "/run/mysqld"; | ||
24 | description = '' | ||
25 | The directory where Mariadb puts sockets. | ||
26 | ''; | ||
27 | }; | ||
28 | sockets = lib.mkOption { | ||
29 | type = lib.types.attrsOf lib.types.path; | ||
30 | default = { | ||
31 | mysqld = "${cfg.socketsDir}/mysqld.sock"; | ||
32 | }; | ||
33 | readOnly = true; | ||
34 | description = '' | ||
35 | Mariadb sockets | ||
36 | ''; | ||
37 | }; | ||
38 | }; | ||
39 | }; | ||
40 | |||
41 | config = lib.mkIf cfg.enable { | ||
42 | networking.firewall.allowedTCPPorts = [ 3306 ]; | ||
43 | |||
44 | # for adminer, ssl is implemented with mysqli only, which is | ||
45 | # currently disabled because it’s not compatible with pam. | ||
46 | # Thus we need to generate two users for each 'remote': one remote | ||
47 | # with SSL, and one localhost without SSL. | ||
48 | # User identified by LDAP: | ||
49 | # CREATE USER foo@% IDENTIFIED VIA pam USING 'mysql' REQUIRE SSL; | ||
50 | # CREATE USER foo@localhost IDENTIFIED VIA pam USING 'mysql'; | ||
51 | services.mysql = { | ||
52 | enable = true; | ||
53 | package = pkgs.mariadb; | ||
54 | dataDir = cfg.dataDir; | ||
55 | extraOptions = '' | ||
56 | ssl_ca = ${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt | ||
57 | ssl_key = /var/lib/acme/mysql/key.pem | ||
58 | ssl_cert = /var/lib/acme/mysql/fullchain.pem | ||
59 | ''; | ||
60 | }; | ||
61 | |||
62 | users.users.mysql.extraGroups = [ "keys" ]; | ||
63 | security.acme.certs."mysql" = config.myServices.databasesCerts // { | ||
64 | user = "mysql"; | ||
65 | group = "mysql"; | ||
66 | plugins = [ "fullchain.pem" "key.pem" "account_key.json" ]; | ||
67 | domain = "db-1.immae.eu"; | ||
68 | postRun = '' | ||
69 | systemctl restart mysql.service | ||
70 | ''; | ||
71 | }; | ||
72 | |||
73 | secrets.keys = [ | ||
74 | { | ||
75 | dest = "mysql/mysqldump"; | ||
76 | permissions = "0400"; | ||
77 | user = "root"; | ||
78 | group = "root"; | ||
79 | text = '' | ||
80 | [mysqldump] | ||
81 | user = root | ||
82 | password = ${myconfig.env.databases.mysql.systemUsers.root} | ||
83 | ''; | ||
84 | } | ||
85 | { | ||
86 | dest = "mysql/pam"; | ||
87 | permissions = "0400"; | ||
88 | user = "mysql"; | ||
89 | group = "mysql"; | ||
90 | text = with myconfig.env.databases.mysql.pam; '' | ||
91 | host ${myconfig.env.ldap.host} | ||
92 | base ${myconfig.env.ldap.base} | ||
93 | binddn ${dn} | ||
94 | bindpw ${password} | ||
95 | pam_filter ${filter} | ||
96 | ssl start_tls | ||
97 | ''; | ||
98 | } | ||
99 | ]; | ||
100 | |||
101 | services.cron = { | ||
102 | enable = true; | ||
103 | systemCronJobs = [ | ||
104 | '' | ||
105 | 30 1,13 * * * root ${pkgs.mariadb}/bin/mysqldump --defaults-file=${config.secrets.location}/mysql/mysqldump --all-databases > ${cfg.dataDir}/backup.sql | ||
106 | '' | ||
107 | ]; | ||
108 | }; | ||
109 | |||
110 | security.pam.services = let | ||
111 | pam_ldap = "${pkgs.pam_ldap}/lib/security/pam_ldap.so"; | ||
112 | in [ | ||
113 | { | ||
114 | name = "mysql"; | ||
115 | text = '' | ||
116 | # https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/ | ||
117 | auth required ${pam_ldap} config=${config.secrets.location}/mysql/pam | ||
118 | account required ${pam_ldap} config=${config.secrets.location}/mysql/pam | ||
119 | ''; | ||
120 | } | ||
121 | ]; | ||
122 | |||
123 | }; | ||
124 | } | ||
125 | |||
diff --git a/modules/private/databases/openldap/default.nix b/modules/private/databases/openldap/default.nix new file mode 100644 index 0000000..850f3ff --- /dev/null +++ b/modules/private/databases/openldap/default.nix | |||
@@ -0,0 +1,130 @@ | |||
1 | { lib, pkgs, config, myconfig, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databases.openldap; | ||
4 | ldapConfig = let | ||
5 | kerberosSchema = pkgs.fetchurl { | ||
6 | url = "https://raw.githubusercontent.com/krb5/krb5/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema"; | ||
7 | sha256 = "17fnkkf6s3lznsl7wp6914pqsc78d038rh38l638big8z608ksww"; | ||
8 | }; | ||
9 | puppetSchema = pkgs.fetchurl { | ||
10 | url = "https://raw.githubusercontent.com/puppetlabs/puppet/master/ext/ldap/puppet.schema"; | ||
11 | sha256 = "11bjf5zfvqlim7p9vddcafs0wiq3v8ys77x8h6fbp9c6bdfh0awh"; | ||
12 | }; | ||
13 | in '' | ||
14 | include ${pkgs.openldap}/etc/schema/core.schema | ||
15 | include ${pkgs.openldap}/etc/schema/cosine.schema | ||
16 | include ${pkgs.openldap}/etc/schema/inetorgperson.schema | ||
17 | include ${pkgs.openldap}/etc/schema/nis.schema | ||
18 | include ${puppetSchema} | ||
19 | include ${kerberosSchema} | ||
20 | include ${./immae.schema} | ||
21 | |||
22 | pidfile ${cfg.pids.pid} | ||
23 | argsfile ${cfg.pids.args} | ||
24 | |||
25 | moduleload back_hdb | ||
26 | backend hdb | ||
27 | |||
28 | moduleload memberof | ||
29 | database hdb | ||
30 | suffix "${myconfig.env.ldap.base}" | ||
31 | rootdn "${myconfig.env.ldap.root_dn}" | ||
32 | include ${config.secrets.location}/ldap/password | ||
33 | directory ${cfg.dataDir} | ||
34 | overlay memberof | ||
35 | |||
36 | TLSCertificateFile /var/lib/acme/ldap/cert.pem | ||
37 | TLSCertificateKeyFile /var/lib/acme/ldap/key.pem | ||
38 | TLSCACertificateFile /var/lib/acme/ldap/fullchain.pem | ||
39 | TLSCACertificatePath ${pkgs.cacert.unbundled}/etc/ssl/certs/ | ||
40 | #This makes openldap crash | ||
41 | #TLSCipherSuite DEFAULT | ||
42 | |||
43 | sasl-host kerberos.immae.eu | ||
44 | include ${config.secrets.location}/ldap/access | ||
45 | ''; | ||
46 | in | ||
47 | { | ||
48 | options.myServices.databases = { | ||
49 | openldap = { | ||
50 | enable = lib.mkOption { | ||
51 | default = cfg.enable; | ||
52 | example = true; | ||
53 | description = "Whether to enable ldap"; | ||
54 | type = lib.types.bool; | ||
55 | }; | ||
56 | dataDir = lib.mkOption { | ||
57 | type = lib.types.path; | ||
58 | default = "/var/lib/openldap"; | ||
59 | description = '' | ||
60 | The directory where Openldap stores its data. | ||
61 | ''; | ||
62 | }; | ||
63 | socketsDir = lib.mkOption { | ||
64 | type = lib.types.path; | ||
65 | default = "/run/slapd"; | ||
66 | description = '' | ||
67 | The directory where Openldap puts sockets and pid files. | ||
68 | ''; | ||
69 | }; | ||
70 | # Output variables | ||
71 | pids = lib.mkOption { | ||
72 | type = lib.types.attrsOf lib.types.path; | ||
73 | default = { | ||
74 | pid = "${cfg.socketsDir}/slapd.pid"; | ||
75 | args = "${cfg.socketsDir}/slapd.args"; | ||
76 | }; | ||
77 | readOnly = true; | ||
78 | description = '' | ||
79 | Slapd pid files | ||
80 | ''; | ||
81 | }; | ||
82 | }; | ||
83 | }; | ||
84 | |||
85 | config = lib.mkIf cfg.enable { | ||
86 | secrets.keys = [ | ||
87 | { | ||
88 | dest = "ldap/password"; | ||
89 | permissions = "0400"; | ||
90 | user = "openldap"; | ||
91 | group = "openldap"; | ||
92 | text = "rootpw ${myconfig.env.ldap.root_pw}"; | ||
93 | } | ||
94 | { | ||
95 | dest = "ldap/access "; | ||
96 | permissions = "0400"; | ||
97 | user = "openldap"; | ||
98 | group = "openldap"; | ||
99 | text = builtins.readFile "${myconfig.privateFiles}/ldap.conf"; | ||
100 | } | ||
101 | ]; | ||
102 | users.users.openldap.extraGroups = [ "keys" ]; | ||
103 | networking.firewall.allowedTCPPorts = [ 636 389 ]; | ||
104 | |||
105 | services.cron = { | ||
106 | systemCronJobs = [ | ||
107 | '' | ||
108 | 35 1,13 * * * root ${pkgs.openldap}/bin/slapcat -v -b "dc=immae,dc=eu" -f ${pkgs.writeText "slapd.conf" ldapConfig} -l ${cfg.dataDir}/backup.ldif | ${pkgs.gnugrep}/bin/grep -v "^# id=[0-9a-f]*$" | ||
109 | '' | ||
110 | ]; | ||
111 | }; | ||
112 | |||
113 | security.acme.certs."ldap" = config.myServices.databasesCerts // { | ||
114 | user = "openldap"; | ||
115 | group = "openldap"; | ||
116 | plugins = [ "fullchain.pem" "key.pem" "cert.pem" "account_key.json" ]; | ||
117 | domain = "ldap.immae.eu"; | ||
118 | postRun = '' | ||
119 | systemctl restart openldap.service | ||
120 | ''; | ||
121 | }; | ||
122 | |||
123 | services.openldap = { | ||
124 | enable = true; | ||
125 | dataDir = cfg.dataDir; | ||
126 | urlList = [ "ldap://" "ldaps://" ]; | ||
127 | extraConfig = ldapConfig; | ||
128 | }; | ||
129 | }; | ||
130 | } | ||
diff --git a/modules/private/databases/openldap/immae.schema b/modules/private/databases/openldap/immae.schema new file mode 100644 index 0000000..f5ee5d5 --- /dev/null +++ b/modules/private/databases/openldap/immae.schema | |||
@@ -0,0 +1,167 @@ | |||
1 | # vim: set filetype=slapd: | ||
2 | objectIdentifier Immaeroot 1.3.6.1.4.1.50071 | ||
3 | |||
4 | objectIdentifier Immae Immaeroot:2 | ||
5 | objectIdentifier ImmaeattributeType Immae:3 | ||
6 | objectIdentifier ImmaeobjectClass Immae:4 | ||
7 | |||
8 | # TT-RSS | ||
9 | attributetype ( ImmaeattributeType:1 NAME 'immaeTtrssLogin' | ||
10 | DESC 'login for TTRSS' | ||
11 | EQUALITY caseIgnoreMatch | ||
12 | SUBSTR caseIgnoreSubstringsMatch | ||
13 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) | ||
14 | |||
15 | objectclass ( ImmaeobjectClass:1 NAME 'immaeTtrssClass' | ||
16 | DESC 'Expansion of the existing object classes for ttrss' | ||
17 | SUP top AUXILIARY | ||
18 | MUST ( immaeTtrssLogin ) ) | ||
19 | |||
20 | # FTP | ||
21 | attributetype ( ImmaeattributeType:2 NAME 'immaeFtpDirectory' | ||
22 | DESC 'home directory for ftp' | ||
23 | EQUALITY caseExactIA5Match | ||
24 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) | ||
25 | |||
26 | attributetype ( ImmaeattributeType:3 NAME 'immaeFtpUid' | ||
27 | DESC 'user id for ftp' | ||
28 | EQUALITY integerMatch | ||
29 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) | ||
30 | |||
31 | attributetype ( ImmaeattributeType:4 NAME 'immaeFtpGid' | ||
32 | DESC 'group id for ftp' | ||
33 | EQUALITY integerMatch | ||
34 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) | ||
35 | |||
36 | objectclass ( ImmaeobjectClass:2 NAME 'immaeFtpClass' | ||
37 | DESC 'Expansion of the existing object classes for ftp' | ||
38 | SUP top AUXILIARY | ||
39 | MUST ( immaeFtpDirectory $ immaeFtpGid $ immaeFtpUid ) ) | ||
40 | |||
41 | |||
42 | # SSH keys | ||
43 | attributetype ( ImmaeattributeType:5 NAME 'immaeSshKey' | ||
44 | DESC 'OpenSSH Public key' | ||
45 | EQUALITY octetStringMatch | ||
46 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) | ||
47 | |||
48 | objectClass ( ImmaeobjectClass:3 NAME 'immaeSshClass' | ||
49 | DESC 'OpenSSH class' | ||
50 | SUP top AUXILIARY | ||
51 | MAy ( immaeSSHKey ) ) | ||
52 | |||
53 | # Specific access | ||
54 | attributetype (ImmaeattributeType:6 NAME 'immaeAccessDn' | ||
55 | EQUALITY distinguishedNameMatch | ||
56 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) | ||
57 | |||
58 | attributetype (ImmaeattributeType:17 NAME 'immaeAccessWriteDn' | ||
59 | EQUALITY distinguishedNameMatch | ||
60 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) | ||
61 | |||
62 | attributetype (ImmaeattributeType:18 NAME 'immaeAccessReadSubtree' | ||
63 | EQUALITY distinguishedNameMatch | ||
64 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) | ||
65 | |||
66 | objectClass ( ImmaeobjectClass:4 NAME 'immaeAccessClass' | ||
67 | DESC 'Access class' | ||
68 | SUP top AUXILIARY | ||
69 | MAY ( immaeAccessDn $ immaeAccessWriteDn $ immaeAccessReadSubtree ) ) | ||
70 | |||
71 | # Xmpp uid | ||
72 | attributetype ( ImmaeattributeType:7 NAME 'immaeXmppUid' | ||
73 | DESC 'user part for Xmpp' | ||
74 | EQUALITY caseIgnoreMatch | ||
75 | SUBSTR caseIgnoreSubstringsMatch | ||
76 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) | ||
77 | |||
78 | objectclass ( ImmaeobjectClass:5 NAME 'immaeXmppClass' | ||
79 | DESC 'Expansion of the existing object classes for XMPP' | ||
80 | SUP top AUXILIARY | ||
81 | MUST ( immaeXmppUid ) ) | ||
82 | |||
83 | # Postfix accounts | ||
84 | attributetype ( ImmaeattributeType:8 NAME 'immaePostfixAddress' | ||
85 | DESC 'the dovecot address to match as username' | ||
86 | EQUALITY caseIgnoreIA5Match | ||
87 | SUBSTR caseIgnoreIA5SubstringsMatch | ||
88 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) | ||
89 | |||
90 | attributetype ( ImmaeattributeType:9 NAME 'immaePostfixHome' | ||
91 | DESC 'the postfix home directory' | ||
92 | EQUALITY caseExactIA5Match | ||
93 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) | ||
94 | |||
95 | attributetype ( ImmaeattributeType:10 NAME 'immaePostfixMail' | ||
96 | DESC 'the dovecot mail location' | ||
97 | EQUALITY caseExactIA5Match | ||
98 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) | ||
99 | |||
100 | attributetype ( ImmaeattributeType:11 NAME 'immaePostfixUid' | ||
101 | DESC 'the dovecot uid' | ||
102 | EQUALITY caseExactIA5Match | ||
103 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) | ||
104 | |||
105 | attributetype ( ImmaeattributeType:12 NAME 'immaePostfixGid' | ||
106 | DESC 'the dovecot gid' | ||
107 | EQUALITY caseExactIA5Match | ||
108 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) | ||
109 | |||
110 | objectclass ( ImmaeobjectClass:6 NAME 'immaePostfixClass' | ||
111 | DESC 'Expansion of the existing object classes for Postfix' | ||
112 | SUP top AUXILIARY | ||
113 | MUST ( immaePostfixAddress $ immaePostfixHome $ | ||
114 | immaePostfixMail $ immaePostfixUid $ immaePostfixGid ) | ||
115 | ) | ||
116 | |||
117 | # Tinc informations | ||
118 | # Domaine = une classe a part ou une partie du dn ? | ||
119 | # attributetype ( ImmaeattributeType:13 NAME 'immaeTincIpSegment' | ||
120 | # DESC 'the internal ip segment in tinc' | ||
121 | # EQUALITY caseIgnoreIA5Match | ||
122 | # SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) | ||
123 | # | ||
124 | # attributetype ( ImmaeattributeType:14 NAME 'immaeTincSubdomain' | ||
125 | # DESC 'the host subdomain' | ||
126 | # EQUALITY caseIgnoreIA5Match | ||
127 | # SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) | ||
128 | # | ||
129 | # attributetype ( ImmaeattributeType:15 NAME 'immaeTincHostname' | ||
130 | # DESC 'the host name' | ||
131 | # EQUALITY caseIgnoreIA5Match | ||
132 | # SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) | ||
133 | # | ||
134 | # objectclass ( ImmaeobjectClass:7 NAME 'immaeTincHostClass' | ||
135 | # DESC 'Expansion of the existing object classes for Tinc' | ||
136 | # SUP top AUXILIARY | ||
137 | # MUST ( immaeTincInternalIp $ immaeTincSubdomain $ | ||
138 | # immaeTincHostname ) | ||
139 | # ) | ||
140 | |||
141 | attributetype (ImmaeattributeType:16 NAME 'immaePuppetJson' | ||
142 | DESC 'Puppet hiera json' | ||
143 | EQUALITY octetStringMatch | ||
144 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) | ||
145 | |||
146 | objectclass ( ImmaeobjectClass:8 NAME 'immaePuppetClass' | ||
147 | DESC 'Expansion of the existing object classes for Puppet' | ||
148 | SUP top AUXILIARY | ||
149 | MUST ( immaePuppetJson ) | ||
150 | ) | ||
151 | |||
152 | attributetype (ImmaeattributeType:19 NAME 'immaeTaskId' | ||
153 | DESC 'Taskwarrior server Org:Name:Key' | ||
154 | EQUALITY caseIgnoreMatch | ||
155 | SUBSTR caseIgnoreSubstringsMatch | ||
156 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) | ||
157 | |||
158 | objectclass ( ImmaeobjectClass:9 NAME 'immaeTaskClass' | ||
159 | DESC 'Expansion of the existing object classes for Task' | ||
160 | SUP top AUXILIARY | ||
161 | MUST ( immaeTaskId ) | ||
162 | ) | ||
163 | |||
164 | # Last: | ||
165 | # attributetype (ImmaeattributeType:19 NAME 'immaeTaskId' | ||
166 | # objectclass ( ImmaeobjectClass:9 NAME 'immaeTaskClass' | ||
167 | |||
diff --git a/modules/private/databases/postgresql.nix b/modules/private/databases/postgresql.nix new file mode 100644 index 0000000..26242a8 --- /dev/null +++ b/modules/private/databases/postgresql.nix | |||
@@ -0,0 +1,141 @@ | |||
1 | { lib, pkgs, config, myconfig, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databases.postgresql; | ||
4 | in { | ||
5 | options.myServices.databases = { | ||
6 | postgresql = { | ||
7 | enable = lib.mkOption { | ||
8 | default = cfg.enable; | ||
9 | example = true; | ||
10 | description = "Whether to enable postgresql database"; | ||
11 | type = lib.types.bool; | ||
12 | }; | ||
13 | # Output variables | ||
14 | socketsDir = lib.mkOption { | ||
15 | type = lib.types.path; | ||
16 | default = "/run/postgresql"; | ||
17 | description = '' | ||
18 | The directory where Postgresql puts sockets. | ||
19 | ''; | ||
20 | readOnly = true; | ||
21 | }; | ||
22 | systemdRuntimeDirectory = lib.mkOption { | ||
23 | type = lib.types.str; | ||
24 | # Use ReadWritePaths= instead if socketsDir is outside of /run | ||
25 | default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir; | ||
26 | lib.strings.removePrefix "/run/" cfg.socketsDir; | ||
27 | description = '' | ||
28 | Adjusted Postgresql sockets directory for systemd | ||
29 | ''; | ||
30 | readOnly = true; | ||
31 | }; | ||
32 | }; | ||
33 | }; | ||
34 | |||
35 | config = lib.mkIf cfg.enable { | ||
36 | nixpkgs.overlays = [ (self: super: rec { | ||
37 | postgresql = self.postgresql_11_custom; | ||
38 | }) ]; | ||
39 | |||
40 | networking.firewall.allowedTCPPorts = [ 5432 ]; | ||
41 | |||
42 | security.acme.certs."postgresql" = config.myServices.databasesCerts // { | ||
43 | user = "postgres"; | ||
44 | group = "postgres"; | ||
45 | plugins = [ "fullchain.pem" "key.pem" "account_key.json" ]; | ||
46 | domain = "db-1.immae.eu"; | ||
47 | postRun = '' | ||
48 | systemctl reload postgresql.service | ||
49 | ''; | ||
50 | }; | ||
51 | |||
52 | systemd.services.postgresql.serviceConfig = { | ||
53 | SupplementaryGroups = "keys"; | ||
54 | RuntimeDirectory = cfg.systemdRuntimeDirectory; | ||
55 | }; | ||
56 | services.postgresql = rec { | ||
57 | enable = true; | ||
58 | package = pkgs.postgresql; | ||
59 | enableTCPIP = true; | ||
60 | extraConfig = '' | ||
61 | max_connections = 100 | ||
62 | wal_level = logical | ||
63 | shared_buffers = 512MB | ||
64 | work_mem = 10MB | ||
65 | max_wal_size = 1GB | ||
66 | min_wal_size = 80MB | ||
67 | log_timezone = 'Europe/Paris' | ||
68 | datestyle = 'iso, mdy' | ||
69 | timezone = 'Europe/Paris' | ||
70 | lc_messages = 'en_US.UTF-8' | ||
71 | lc_monetary = 'en_US.UTF-8' | ||
72 | lc_numeric = 'en_US.UTF-8' | ||
73 | lc_time = 'en_US.UTF-8' | ||
74 | default_text_search_config = 'pg_catalog.english' | ||
75 | ssl = on | ||
76 | ssl_cert_file = '/var/lib/acme/postgresql/fullchain.pem' | ||
77 | ssl_key_file = '/var/lib/acme/postgresql/key.pem' | ||
78 | ''; | ||
79 | authentication = '' | ||
80 | local all postgres ident | ||
81 | local all all md5 | ||
82 | hostssl all all 188.165.209.148/32 md5 | ||
83 | hostssl all all 178.33.252.96/32 md5 | ||
84 | hostssl all all all pam | ||
85 | hostssl replication backup-1 2001:41d0:302:1100::9:e5a9/128 pam pamservice=postgresql_replication | ||
86 | hostssl replication backup-1 54.37.151.137/32 pam pamservice=postgresql_replication | ||
87 | ''; | ||
88 | }; | ||
89 | |||
90 | secrets.keys = [ | ||
91 | { | ||
92 | dest = "postgresql/pam"; | ||
93 | permissions = "0400"; | ||
94 | group = "postgres"; | ||
95 | user = "postgres"; | ||
96 | text = with myconfig.env.databases.postgresql.pam; '' | ||
97 | host ${myconfig.env.ldap.host} | ||
98 | base ${myconfig.env.ldap.base} | ||
99 | binddn ${dn} | ||
100 | bindpw ${password} | ||
101 | pam_filter ${filter} | ||
102 | ssl start_tls | ||
103 | ''; | ||
104 | } | ||
105 | { | ||
106 | dest = "postgresql/pam_replication"; | ||
107 | permissions = "0400"; | ||
108 | group = "postgres"; | ||
109 | user = "postgres"; | ||
110 | text = '' | ||
111 | host ${myconfig.env.ldap.host} | ||
112 | base ${myconfig.env.ldap.base} | ||
113 | binddn ${myconfig.env.ldap.host_dn} | ||
114 | bindpw ${myconfig.env.ldap.password} | ||
115 | pam_login_attribute cn | ||
116 | ssl start_tls | ||
117 | ''; | ||
118 | } | ||
119 | ]; | ||
120 | |||
121 | security.pam.services = let | ||
122 | pam_ldap = "${pkgs.pam_ldap}/lib/security/pam_ldap.so"; | ||
123 | in [ | ||
124 | { | ||
125 | name = "postgresql"; | ||
126 | text = '' | ||
127 | auth required ${pam_ldap} config=${config.secrets.location}/postgresql/pam | ||
128 | account required ${pam_ldap} config=${config.secrets.location}/postgresql/pam | ||
129 | ''; | ||
130 | } | ||
131 | { | ||
132 | name = "postgresql_replication"; | ||
133 | text = '' | ||
134 | auth required ${pam_ldap} config=${config.secrets.location}/postgresql/pam_replication | ||
135 | account required ${pam_ldap} config=${config.secrets.location}/postgresql/pam_replication | ||
136 | ''; | ||
137 | } | ||
138 | ]; | ||
139 | }; | ||
140 | } | ||
141 | |||
diff --git a/modules/private/databases/redis.nix b/modules/private/databases/redis.nix new file mode 100644 index 0000000..a1c2c75 --- /dev/null +++ b/modules/private/databases/redis.nix | |||
@@ -0,0 +1,57 @@ | |||
1 | { lib, config, myconfig, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databases.redis; | ||
4 | in { | ||
5 | options.myServices.databases.redis = { | ||
6 | enable = lib.mkOption { | ||
7 | default = cfg.enable; | ||
8 | example = true; | ||
9 | description = "Whether to enable redis database"; | ||
10 | type = lib.types.bool; | ||
11 | }; | ||
12 | socketsDir = lib.mkOption { | ||
13 | type = lib.types.path; | ||
14 | default = "/run/redis"; | ||
15 | description = '' | ||
16 | The directory where Redis puts sockets. | ||
17 | ''; | ||
18 | }; | ||
19 | # Output variables | ||
20 | systemdRuntimeDirectory = lib.mkOption { | ||
21 | type = lib.types.str; | ||
22 | # Use ReadWritePaths= instead if socketsDir is outside of /run | ||
23 | default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir; | ||
24 | lib.strings.removePrefix "/run/" cfg.socketsDir; | ||
25 | description = '' | ||
26 | Adjusted redis sockets directory for systemd | ||
27 | ''; | ||
28 | readOnly = true; | ||
29 | }; | ||
30 | sockets = lib.mkOption { | ||
31 | type = lib.types.attrsOf lib.types.path; | ||
32 | default = { | ||
33 | redis = "${cfg.socketsDir}/redis.sock"; | ||
34 | }; | ||
35 | readOnly = true; | ||
36 | description = '' | ||
37 | Redis sockets | ||
38 | ''; | ||
39 | }; | ||
40 | }; | ||
41 | |||
42 | config = lib.mkIf cfg.enable { | ||
43 | users.users.redis.uid = config.ids.uids.redis; | ||
44 | users.groups.redis.gid = config.ids.gids.redis; | ||
45 | services.redis = rec { | ||
46 | enable = true; | ||
47 | bind = "127.0.0.1"; | ||
48 | unixSocket = cfg.sockets.redis; | ||
49 | extraConfig = '' | ||
50 | unixsocketperm 777 | ||
51 | maxclients 1024 | ||
52 | ''; | ||
53 | }; | ||
54 | systemd.services.redis.serviceConfig.RuntimeDirectory = cfg.systemdRuntimeDirectory; | ||
55 | }; | ||
56 | } | ||
57 | |||
diff --git a/modules/private/default.nix b/modules/private/default.nix index 394a85b..a7a23c2 100644 --- a/modules/private/default.nix +++ b/modules/private/default.nix | |||
@@ -3,4 +3,10 @@ | |||
3 | httpdInte = import ../websites/httpd-service-builder.nix { httpdName = "Inte"; withUsers = false; }; | 3 | httpdInte = import ../websites/httpd-service-builder.nix { httpdName = "Inte"; withUsers = false; }; |
4 | httpdProd = import ../websites/httpd-service-builder.nix { httpdName = "Prod"; withUsers = false; }; | 4 | httpdProd = import ../websites/httpd-service-builder.nix { httpdName = "Prod"; withUsers = false; }; |
5 | httpdTools = import ../websites/httpd-service-builder.nix { httpdName = "Tools"; withUsers = true; }; | 5 | httpdTools = import ../websites/httpd-service-builder.nix { httpdName = "Tools"; withUsers = true; }; |
6 | |||
7 | databases = ./databases; | ||
8 | mariadb = ./databases/mariadb.nix; | ||
9 | openldap = ./databases/openldap; | ||
10 | postgresql = ./databases/postgresql.nix; | ||
11 | redis = ./databases/redis.nix; | ||
6 | } | 12 | } |