This repository contains the open source code for the Buckets relay server, which allows users to share budget data between their devices in an end-to-end encrypted way.
If you want to run the relay on your own computer with only one user account, do the following:
- Install Nim
- Build the relay:
git clone https://github.com/buckets/relay.git buckets-relay.git
cd buckets-relay.git
nimble singleuserbins
- Run the server:
RELAY_USERNAME=someusername
RELAY_PASSWORD=somepassword
bin/brelay server
This will launch the relay on the default port. Run brelay --help
for more options.
If instead of nimble singleuserbins
you run nimble multiuserbins
the server will be built in multi-user mode.
Register users via brelay adduser ...
or through the web interface.
Registration-related emails are sent through Postmark. Set POSTMARK_API_KEY
to your Postmark key to use it. Otherwise, disable emails with -d:nopostmark
.
Users can authenticate with their Buckets license if you set an environment variable AUTH_LICENSE_PUBKEY=<A PEM FORMATTED PUBKEY>
- You should ensure that connections to this relay server are made with TLS.
- This relay server can see all traffic, so clients should encrypt data intended for other clients.
- Clients should also authenticate each other through the relay and not trust the authentication done by this server.
To run the server locally:
nimble run brelay server
If you'd like to run a relay server on fly.io, sign up for the service then do one of the following. If you'd like to host somewhere else, you could use the Dockerfiles in docker/ as a starting point.
fly launch --dockerfile docker/singleuser.Dockerfile
fly secrets set RELAY_USERNAME='someusername' RELAY_PASSWORD='somepassword'
Variable | Description |
---|---|
RELAY_USERNAME |
Username or email you'll use to authenticate to the relay. |
RELAY_PASSWORD |
Password you'll use to authenticate to the relay. |
fly launch --dockerfile docker/multiuser.Dockerfile
fly secrets set POSTMARK_API_KEY='your key' AUTH_LICENSE_PUBKEY='the key' LICENSE_HASH_SALT='choose something here'
Variable | Description |
---|---|
POSTMARK_API_KEY |
API key from Postmark |
AUTH_LICENSE_PUBKEY |
RSA public key of Buckets licenses. If empty, license authentication is disabled. |
LICENSE_HASH_SALT |
A hashing salt for the case when a license needs to be disabled. Any random, but consistent value is fine. |
Relay clients communicate with the relay server using the following protocol. See ./src/bucketsrelay/proto.nim for more information, and ./src/bucketsrelay/stringproto.nim for encoding details.
In summary, devices connect with websockets and exchange messages. Messages sent from client to server are called commands. Messages sent from server to client are called events.
Clients authenticate with the server in two ways:
- With a relay account via HTTP Basic authentication. This is used to group together a user's various clients and prevent abuse.
- With a public/private key. This is used to identify and connect individual clients.
A single relay account can have multiple public/private keys; typically one for each device.
Clients send the following commands:
Command | Description |
---|---|
Iam |
In response to a Who event, proves that this client has the private key for their public key. |
Connect |
Asks the server for a connection to another client identified by the client's public key. |
Disconnect |
Asks the server to disconnect a connection to another client. |
SendData |
Sends bytes to another client. |
The relay server sends the following events:
Event | Description |
---|---|
Who |
Challenge for authenticating a client's public/private keys |
Authenticated |
Sent when a client successfully completes authentication |
Connected |
Sent when a client has connected to another client |
Disconnected |
Sent when a client has been disconnected from another client |
Data |
Data payload from another, connected client |
Entered |
Sent when a client within the same user account has authenticated to the relay |
Exited |
Sent when a client within the same user account has disconnected from the relay |
ErrorEvent |
Sent when errors happen with authentication, connection or message sending |
Authentication happens like this:
- On connection, server sends
Who(challenge=ABCD...)
- Client responds with
Iam(pubkey=MYPK..., signature=SIGN...)
- If the signature is correct, server sends
Authenticated
Client Relay
│ │
│ Who │
│◄────────────────┤
│ │
│ Iam │
├────────────────►│
│ │
│ Authenticated │
│◄────────────────┤
│ │
After authenticating, clients connect to each other and send data like this:
- Alice sends
Connect(pubkey=BOBPK)
- Bob sends
Connect(pubkey=ALICEPK)
- Server sends Alice
Connected(pubkey=BOBPK)
- Server sends Bob
Connected(pubkey=ALICEPK)
- Alice sends data with
SendData(data=hello, pubkey=BOBPK)
- Server sends Bob data with
Data(data=hello, sender=ALICEPK)
Alice Relay Bob
│ │ │
├───Authenticated─┼─Authenticated───┤
│ │ │
│Connect(Bob) │ │
├────────────────►│ Connect(Alice) │
│ │◄────────────────┤
│ │ │
│ Connected(Bob) │ Connected(Alice)│
│◄────────────────┼────────────────►│
│ │ │
│SendData(Bob) │ │
├────────────────►│ Data(Alice) │
│ ├────────────────►│
│ │ │
The relay server will announce client presence to all clients that use the same HTTP Auth credentials. For example, if both Alice and Bob signed in as [email protected]
the following would happen:
- Alice finishes authenticating
- Bob finishes authenticating
- Server sends Alice
Entered(pubkey=BOBPK)
- Server sends Bob
Entered(pubkey=ALICEPK)
- Alice disconnects
- Server sends Bob
Exited(pubkey=ALICEPK)