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