SpacetimeDB
SpacetimeDB copied to clipboard
[poc] SSL/TLS for standalone server
EDIT: future updates of this patch will be here: https://github.com/dare3path/spacetimedb-tls-patch because it's becoming too dependent on locally cloned modified/patched repos(for crates like rustls-pki-types, hyper-util) and these shouldn't have to be like a requirement for this PR to work.
Description of Changes
(description is a bit outdated)
This is just a proof-of-concept patch to add TLS (and mTLS) support for the standalone server and thus addresses issue https://github.com/clockworklabs/SpacetimeDB/issues/1076 It's here in the hope the it might be useful for others, to give an idea, or show it's possible this way, but it's not intended to be merged (it's not of expected quality, it was made with grok3 and grok2 's help), it's just what I intend to use locally for myself before delving more deeply into SpacetimeDB. Thus, this PR is submitted as draft.
How to use after patched:
- generate server private and public keys (maybe sign by your own local CA), can use this helper scripts for that https://github.com/dare3path/spacetimedb-cert-gen or just make sure you have the certificate (contains public key)
server.crtand private keyserver.keyand the certificate(contains public key) of the CA that signed the server's certificate asca.crtor if it's a self-signed server certificate then useserverSS.crtinstead(but you can't useserver.crt(instead ofca.crt) because it was signed by a CA thus it's not self-signed) in all places where--certis used (so whereca.crtandserver.crtis used). - start the spacetimedb standalone server in TLS mode:
spacetime start --edition standalone --listen-addr 127.0.0.1:3000 --ssl --cert ../spacetimedb-cert-gen/server.crt --key ../spacetimedb-cert-gen/server.key- can use
--ssl,--tls,--httpsor--secure, they're aliases of the same thing.
- can use
- start a rust client from a different terminal and connect to the server in TLS mode:
cd ./crates/sdk/ && cargo run --example quickstart-chat -- --cert ../../../spacetimedb-cert-gen/ca.crt
this will404if you haven't published it yet(see below) - use cli commands:
spacetime version list
spacetime version use 1.1.0
spacetime server list
spacetime server add --url https://127.0.0.1:3000 slocal --no-fingerprint
spacetime server set-default slocal(can usehttps://127.0.0.1:3000instead ofslocalhere)
spacetime server list, should show this:
WARNING: This command is UNSTABLE and subject to breaking changes.
DEFAULT HOSTNAME PROTOCOL NICKNAME
maincloud.spacetimedb.com https maincloud
127.0.0.1:3000 http local
*** 127.0.0.1:3000 https slocal
assuming you're still inside ./crates/sdk/:
$ spacetime login --server-issued-login slocal --cert ../../../my/spacetimedb-cert-gen/ca.crt
WARNING: the server that you specified here as 'slocal' isn't the one that will be used by commands like 'spacetime publish' but instead it's the one listed on 'spacetime server list' as the default (3 stars) that will be used, eg. 127.0.0.1:3000 if you haven't manually added any via 'spacetime server add'.
We will log in directly to your target server.
We have logged in directly to your target server.
WARNING: This login will NOT work for any other servers.
Saving config to /home/user/.config/spacetime/cli.toml.
$ spacetime publish -p ../../modules/quickstart-chat/ --cert ../../../my/spacetimedb-cert-gen/ca.crt quickstart-chat
Finished `release` profile [optimized] target(s) in 0.22s
Optimising module with wasm-opt...
Build finished successfully.
Uploading to slocal => https://127.0.0.1:3000
Publishing module...
Created new database with name: quickstart-chat, identity: c200ba48494b35ab616cea275571f895d0ac6bf6e16b391238bf59ec65d1410d
$ cargo run --example quickstart-chat -- --cert ../../../my/spacetimedb-cert-gen/ca.crt Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.48s
Running `/home/user/SOURCE/SpacetimeDB/target/debug/examples/quickstart-chat --cert ../../../my/spacetimedb-cert-gen/ca.crt`
Fully connected and all subscriptions applied.
Use /name to set your name, or type a message!
User c2001e6a388eaebd connected.
message here
c2001e6a388eaebd: message here
message2 here
c2001e6a388eaebd: message2 here
(Ctrl+D(+Z on Windows) to exit, or Ctrl+C)
- other cli commands you can run, in another terminal:
$ spacetime logs quickstart-chat --cert ../../../my/spacetimedb-cert-gen/ca.crt --follow
2025-04-13T05:10:45.901825Z INFO: spacetimedb: Creating table `message`
2025-04-13T05:10:45.902506Z INFO: spacetimedb: Creating table `user`
2025-04-13T05:10:45.904265Z INFO: spacetimedb: Invoking `init` reducer
2025-04-13T05:10:45.906885Z INFO: spacetimedb: Database initialized
$ spacetime server ping slocal --cert ../../../my/spacetimedb-cert-gen/ca.crt
WARNING: This command is UNSTABLE and subject to breaking changes.
Server is online: https://127.0.0.1:3000
$ spacetime server fingerprint slocal --cert ../../../my/spacetimedb-cert-gen/ca.crt
WARNING: This command is UNSTABLE and subject to breaking changes.
Fingerprint is unchanged for server slocal:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfwAqvSbxMUZKdCsvzr9tdQJOhuG/
24jZ+oMN18FS6Py9CDNzGeAzu2kqjlybtpYRqkchYqv8o44khX9TZlhyWA==
-----END PUBLIC KEY-----
Can use all relevant cli commands (that I'm aware of) that require server access by passing args --cert ca.crt(or --cert serverSS.crt if server was started with --cert serverSS.crt --key server.key --ssl), otherwise, without --cert, you'd have to have the public certificate of the CA(certificate authority) that signed the server's public key in your cert root store (eg. somewhere in /etc/ssl/ on Linux).
API and ABI breaking changes
TODO: evaluate this.
Expected complexity level and risk
3
Testing
TODO:
- [ ] zeroize private keys, on drop. (needs patched
rustls-pki-typescrate) - [ ] fix
load_root_cert's bad logic for the 1MiB limit read file(ie. this is wrongif reader.limit() == 0 && reader.get_ref().get_ref().metadata().await.is_ok() {), just likeread_file_limitgot fixed already . - [ ] possibly other fixes seen in the location where this actually gets updated from now on.
Thank you for putting this together as an example!
erm, this isn't meant to be merged, it's just a proof-of-concept, also it's outdated and some things remained unfixed. I stopped updating it here(in this PR) because I wanted to modify some dep crates (eg. ring,pki-types) (for the purpose of zeroize-ing the private keys) and thus I've had to use modified forks of them which shouldn't be in this PR via [patch.crates-io] section.
Did anyone only want to run the CI on it? I should probably rebase it first, but please let me know.
EDIT: Ah that comment must just be because you've just added CLAassistant and it's auto-commenting with that on all PRs. Carry on:)