1# FoundationDB {#module-services-foundationdb}
2
3*Source:* {file}`modules/services/databases/foundationdb.nix`
4
5*Upstream documentation:* <https://apple.github.io/foundationdb/>
6
7*Maintainer:* Austin Seipp
8
9*Available version(s):* 7.1.x
10
11FoundationDB (or "FDB") is an open source, distributed, transactional
12key-value store.
13
14## Configuring and basic setup {#module-services-foundationdb-configuring}
15
16To enable FoundationDB, add the following to your
17{file}`configuration.nix`:
18```nix
19{
20 services.foundationdb.enable = true;
21 services.foundationdb.package = pkgs.foundationdb73; # FoundationDB 7.3.x
22}
23```
24
25The {option}`services.foundationdb.package` option is required, and
26must always be specified. Due to the fact FoundationDB network protocols and
27on-disk storage formats may change between (major) versions, and upgrades
28must be explicitly handled by the user, you must always manually specify
29this yourself so that the NixOS module will use the proper version. Note
30that minor, bugfix releases are always compatible.
31
32After running {command}`nixos-rebuild`, you can verify whether
33FoundationDB is running by executing {command}`fdbcli` (which is
34added to {option}`environment.systemPackages`):
35```ShellSession
36$ sudo -u foundationdb fdbcli
37Using cluster file `/etc/foundationdb/fdb.cluster'.
38
39The database is available.
40
41Welcome to the fdbcli. For help, type `help'.
42fdb> status
43
44Using cluster file `/etc/foundationdb/fdb.cluster'.
45
46Configuration:
47 Redundancy mode - single
48 Storage engine - memory
49 Coordinators - 1
50
51Cluster:
52 FoundationDB processes - 1
53 Machines - 1
54 Memory availability - 5.4 GB per process on machine with least available
55 Fault Tolerance - 0 machines
56 Server time - 04/20/18 15:21:14
57
58...
59
60fdb>
61```
62
63You can also write programs using the available client libraries. For
64example, the following Python program can be run in order to grab the
65cluster status, as a quick example. (This example uses
66{command}`nix-shell` shebang support to automatically supply the
67necessary Python modules).
68```ShellSession
69a@link> cat fdb-status.py
70#! /usr/bin/env nix-shell
71#! nix-shell -i python -p python pythonPackages.foundationdb73
72
73import fdb
74import json
75
76def main():
77 fdb.api_version(520)
78 db = fdb.open()
79
80 @fdb.transactional
81 def get_status(tr):
82 return str(tr['\xff\xff/status/json'])
83
84 obj = json.loads(get_status(db))
85 print('FoundationDB available: %s' % obj['client']['database_status']['available'])
86
87if __name__ == "__main__":
88 main()
89a@link> chmod +x fdb-status.py
90a@link> ./fdb-status.py
91FoundationDB available: True
92a@link>
93```
94
95FoundationDB is run under the {command}`foundationdb` user and group
96by default, but this may be changed in the NixOS configuration. The systemd
97unit {command}`foundationdb.service` controls the
98{command}`fdbmonitor` process.
99
100By default, the NixOS module for FoundationDB creates a single SSD-storage
101based database for development and basic usage. This storage engine is
102designed for SSDs and will perform poorly on HDDs; however it can handle far
103more data than the alternative "memory" engine and is a better default
104choice for most deployments. (Note that you can change the storage backend
105on-the-fly for a given FoundationDB cluster using
106{command}`fdbcli`.)
107
108Furthermore, only 1 server process and 1 backup agent are started in the
109default configuration. See below for more on scaling to increase this.
110
111FoundationDB stores all data for all server processes under
112{file}`/var/lib/foundationdb`. You can override this using
113{option}`services.foundationdb.dataDir`, e.g.
114```nix
115{ services.foundationdb.dataDir = "/data/fdb"; }
116```
117
118Similarly, logs are stored under {file}`/var/log/foundationdb`
119by default, and there is a corresponding
120{option}`services.foundationdb.logDir` as well.
121
122## Scaling processes and backup agents {#module-services-foundationdb-scaling}
123
124Scaling the number of server processes is quite easy; simply specify
125{option}`services.foundationdb.serverProcesses` to be the number of
126FoundationDB worker processes that should be started on the machine.
127
128FoundationDB worker processes typically require 4GB of RAM per-process at
129minimum for good performance, so this option is set to 1 by default since
130the maximum amount of RAM is unknown. You're advised to abide by this
131restriction, so pick a number of processes so that each has 4GB or more.
132
133A similar option exists in order to scale backup agent processes,
134{option}`services.foundationdb.backupProcesses`. Backup agents are
135not as performance/RAM sensitive, so feel free to experiment with the number
136of available backup processes.
137
138## Clustering {#module-services-foundationdb-clustering}
139
140FoundationDB on NixOS works similarly to other Linux systems, so this
141section will be brief. Please refer to the full FoundationDB documentation
142for more on clustering.
143
144FoundationDB organizes clusters using a set of
145*coordinators*, which are just specially-designated
146worker processes. By default, every installation of FoundationDB on NixOS
147will start as its own individual cluster, with a single coordinator: the
148first worker process on {command}`localhost`.
149
150Coordinators are specified globally using the
151{command}`/etc/foundationdb/fdb.cluster` file, which all servers and
152client applications will use to find and join coordinators. Note that this
153file *can not* be managed by NixOS so easily:
154FoundationDB is designed so that it will rewrite the file at runtime for all
155clients and nodes when cluster coordinators change, with clients
156transparently handling this without intervention. It is fundamentally a
157mutable file, and you should not try to manage it in any way in NixOS.
158
159When dealing with a cluster, there are two main things you want to do:
160
161 - Add a node to the cluster for storage/compute.
162 - Promote an ordinary worker to a coordinator.
163
164A node must already be a member of the cluster in order to properly be
165promoted to a coordinator, so you must always add it first if you wish to
166promote it.
167
168To add a machine to a FoundationDB cluster:
169
170 - Choose one of the servers to start as the initial coordinator.
171 - Copy the {command}`/etc/foundationdb/fdb.cluster` file from this
172 server to all the other servers. Restart FoundationDB on all of these
173 other servers, so they join the cluster.
174 - All of these servers are now connected and working together in the
175 cluster, under the chosen coordinator.
176
177At this point, you can add as many nodes as you want by just repeating the
178above steps. By default there will still be a single coordinator: you can
179use {command}`fdbcli` to change this and add new coordinators.
180
181As a convenience, FoundationDB can automatically assign coordinators based
182on the redundancy mode you wish to achieve for the cluster. Once all the
183nodes have been joined, simply set the replication policy, and then issue
184the {command}`coordinators auto` command
185
186For example, assuming we have 3 nodes available, we can enable double
187redundancy mode, then auto-select coordinators. For double redundancy, 3
188coordinators is ideal: therefore FoundationDB will make
189*every* node a coordinator automatically:
190
191```ShellSession
192fdbcli> configure double ssd
193fdbcli> coordinators auto
194```
195
196This will transparently update all the servers within seconds, and
197appropriately rewrite the {command}`fdb.cluster` file, as well as
198informing all client processes to do the same.
199
200## Client connectivity {#module-services-foundationdb-connectivity}
201
202By default, all clients must use the current {command}`fdb.cluster`
203file to access a given FoundationDB cluster. This file is located by default
204in {command}`/etc/foundationdb/fdb.cluster` on all machines with the
205FoundationDB service enabled, so you may copy the active one from your
206cluster to a new node in order to connect, if it is not part of the cluster.
207
208## Client authorization and TLS {#module-services-foundationdb-authorization}
209
210By default, any user who can connect to a FoundationDB process with the
211correct cluster configuration can access anything. FoundationDB uses a
212pluggable design to transport security, and out of the box it supports a
213LibreSSL-based plugin for TLS support. This plugin not only does in-flight
214encryption, but also performs client authorization based on the given
215endpoint's certificate chain. For example, a FoundationDB server may be
216configured to only accept client connections over TLS, where the client TLS
217certificate is from organization *Acme Co* in the
218*Research and Development* unit.
219
220Configuring TLS with FoundationDB is done using the
221{option}`services.foundationdb.tls` options in order to control the
222peer verification string, as well as the certificate and its private key.
223
224Note that the certificate and its private key must be accessible to the
225FoundationDB user account that the server runs under. These files are also
226NOT managed by NixOS, as putting them into the store may reveal private
227information.
228
229After you have a key and certificate file in place, it is not enough to
230simply set the NixOS module options -- you must also configure the
231{command}`fdb.cluster` file to specify that a given set of
232coordinators use TLS. This is as simple as adding the suffix
233{command}`:tls` to your cluster coordinator configuration, after the
234port number. For example, assuming you have a coordinator on localhost with
235the default configuration, simply specifying:
236
237```
238XXXXXX:XXXXXX@127.0.0.1:4500:tls
239```
240
241will configure all clients and server processes to use TLS from now on.
242
243## Backups and Disaster Recovery {#module-services-foundationdb-disaster-recovery}
244
245The usual rules for doing FoundationDB backups apply on NixOS as written in
246the FoundationDB manual. However, one important difference is the security
247profile for NixOS: by default, the {command}`foundationdb` systemd
248unit uses *Linux namespaces* to restrict write access to
249the system, except for the log directory, data directory, and the
250{command}`/etc/foundationdb/` directory. This is enforced by default
251and cannot be disabled.
252
253However, a side effect of this is that the {command}`fdbbackup`
254command doesn't work properly for local filesystem backups: FoundationDB
255uses a server process alongside the database processes to perform backups
256and copy the backups to the filesystem. As a result, this process is put
257under the restricted namespaces above: the backup process can only write to
258a limited number of paths.
259
260In order to allow flexible backup locations on local disks, the FoundationDB
261NixOS module supports a
262{option}`services.foundationdb.extraReadWritePaths` option. This
263option takes a list of paths, and adds them to the systemd unit, allowing
264the processes inside the service to write (and read) the specified
265directories.
266
267For example, to create backups in {command}`/opt/fdb-backups`, first
268set up the paths in the module options:
269
270```nix
271{ services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ]; }
272```
273
274Restart the FoundationDB service, and it will now be able to write to this
275directory (even if it does not yet exist.) Note: this path
276*must* exist before restarting the unit. Otherwise,
277systemd will not include it in the private FoundationDB namespace (and it
278will not add it dynamically at runtime).
279
280You can now perform a backup:
281
282```ShellSession
283$ sudo -u foundationdb fdbbackup start -t default -d file:///opt/fdb-backups
284$ sudo -u foundationdb fdbbackup status -t default
285```
286
287## Known limitations {#module-services-foundationdb-limitations}
288
289The FoundationDB setup for NixOS should currently be considered beta.
290FoundationDB is not new software, but the NixOS compilation and integration
291has only undergone fairly basic testing of all the available functionality.
292
293 - There is no way to specify individual parameters for individual
294 {command}`fdbserver` processes. Currently, all server processes
295 inherit all the global {command}`fdbmonitor` settings.
296 - Ruby bindings are not currently installed.
297 - Go bindings are not currently installed.
298
299## Options {#module-services-foundationdb-options}
300
301NixOS's FoundationDB module allows you to configure all of the most relevant
302configuration options for {command}`fdbmonitor`, matching it quite
303closely. A complete list of options for the FoundationDB module may be found
304[here](#opt-services.foundationdb.enable). You should
305also read the FoundationDB documentation as well.
306
307## Full documentation {#module-services-foundationdb-full-docs}
308
309FoundationDB is a complex piece of software, and requires careful
310administration to properly use. Full documentation for administration can be
311found here: <https://apple.github.io/foundationdb/>.