-
Notifications
You must be signed in to change notification settings - Fork 0
Server persistence
The server stores its data in a PostgeSQL database that the server connects with via the (local) network. PostgreSQL is an industry standard and an easy choice as a server database due to its performance, robustness, reliability and full SQL compliance. It's a widely used and well maintained open source software project a large community.
On the Rust side of things, the sqlx
crate provides excellent support for all features the server requires such as parallel access and transactions.
The server is conceptually split into authentication service (AS), delivery service (DS) and queuing service (QS). The data for each of these services is independent and the corresponding database tables are not linked in any way.
The AS stores user and client data indexed by the users' real user names (or client IDs containing them). Additionally, it stores the key material it uses to sign client credentials and Privacy Pass tokens. The AS also maintains queues for each client for use in the connection establishment process.
- User records
- User name
- OPAQUE server registration
- Client records
- Client ID
- Queue ratchet key material
- Activity time
- Client credential
- Token allowance
- Connection packages
- Client ID
- Connection package
- Client queues
- Client ID
- Queue messages
- AS credentials
- AS credential
- AS credential signing key
- AS intermediate credentials
- AS intermediate Credential
- AS intermediate Credential signing key
- Revoked (intermediate) AS credentials
- Credential Fingerprint
- Privacy Pass key material
- Privacy Pass public key
- Privacy Pass private key
The DS only stores the MLS group data of its users, which is encrypted at rest. It also keeps a record of which group IDs have been claimed by users for later use, although that data is relatively ephemeral.
- Own domain
- Group IDs
- Reserved group IDs
- Group states
- Encrypted group state
- Activity time
- Deleted queue IDs
The main purpose of the QS is to maintain the regular message queues for its clients, as well as the add packages that clients can use to add one-another to groups. Note that in contrast to the AS, the user and client IDs stored by the QS are pseudonymous and not linked to the "real" IDs and user names stored by the AS.
- User record
- User ID
- User verifying key
- Friendship token
- Client record
- Client ID
- User ID
- Encrypted push token (optional)
- Queue ratchet key material
- Client verifying key
- Activity time
- Add packages
- Client ID
- Encrypted Add packages
- Client queues
- Client ID
- Queue messages
- QS auth key material
- Signature public key
- Signature private key
- QS configuration
Due to the highly parallel nature of the homeserver and the resulting concurrent access to the database, maintaining consistency across the different datasets is vital. The server achieves this by making use of PostgreSQL's row-locking feature, transactions and cross-table consistency features such as foreign keys.
In contrast to the client, the server has a limited number of relatively straight-forward state access patterns. For database backend portability and to establish a clean abstraction each of the different services interacts with the database through a StorageProvider
trait that provides the necessary functions to access the individual types of state. The trait has allowed us to experiment with other backends such as sqlite, or an in-memory backend for testing.