- TypeScript 92.1%
- Nix 6.5%
- Dockerfile 1.4%
| test-app | ||
| .envrc | ||
| .gitignore | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| README.md | ||
Spacetime TanStack start docker compose
This is for TanStack spacetime application,
Note
Please read everything carefully before continuing the deployment
To avoid data loss.
- Everything from the beginning
- Setting up authentication keys
- Dev setup
- Prod setup
- Prod address
- Nginx proxy setup
- Clearing database
- Fixing spacetimedb openess
- Backing up owner identity
everything from the beginning
Install spacetimedb cli tool and add it to your path https://spacetimedb.com/install
curl -sSf https://install.spacetimedb.com | sh
# .bashrc
export PATH="~/.local/bin:$PATH"
spacetime init --template tanstack-ts --local
# SKIP SPACETIME LOGIN (N)
# Select bun as package manager
cd your-project
bun install
# generate typescript bindings
spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb
Copy the docker-compose files and Dockerfile to the project src folder
Update your database name and address in .env.local
Setting up authentication keys
Start with making a spacetime-config.toml file
mkdir -p ./spacetime-config
nvim spacetime-config/config.toml
With the following contents
[certificate-authority]
jwt-priv-key-path = "/etc/spacetimedb/id_ecdsa"
jwt-pub-key-path = "/etc/spacetimedb/id_ecdsa.pub"
Generating keys
For dev
cd test-app
mkdir -p ./spacetime-keys
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ./spacetime-keys/id_ecdsa
openssl pkey -in ./spacetime-keys/id_ecdsa -pubout -out ./spacetime-keys/id_ecdsa.pub
echo "spacetime-keys/" >> .gitignore
Now the keys persist and you dont to generate new keys after every docker restart
For prod
mkdir -p ./spacetime-keys-prod
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ./spacetime-keys-prod/id_ecdsa
openssl pkey -in ./spacetime-keys-prod/id_ecdsa -pubout -out ./spacetime-keys-prod/id_ecdsa.pub
echo "spacetime-keys-prod/" >> .gitignore
For more control on who can do what with the database, consider using SpacetimeAuth
Dev setup
Clear your web browser localstorage
localStorage.clear();
Start everything up
cd test-app
bun install
# generate typescript bindings
spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb
# Start spacetimedb as a docker container
docker compose -f docker-compose.dev.yml up -d --build
spacetime logout
spacetime server add local-docker --url http://localhost:3000
spacetime login --server-issued-login http://localhost:3000
spacetime publish -s local-docker
bun run dev
# TanStack dev using bun development server for frontend
server is up in http://localhost:5173
TanStack changes hot-reload automatically. Module changes require republishing.
incase you need to relogin
spacetime logout
spacetime login --server-issued-login http://localhost:3000
spacetime publish -s local-docker
After any spacedb module changes
spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb
spacetime publish -s local-docker
Prod setup
Change build configs for bun to use nitro/vite
// vite.config.ts
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsConfigPaths from "vite-tsconfig-paths";
import { nitro } from "nitro/vite";
export default defineConfig({
server: {
port: 5173,
},
plugins: [
tsConfigPaths({
projects: ["./tsconfig.json"],
}),
tanstackStart(),
nitro({ preset: "bun" }),
react(),
],
});
bun install
# generate typescript bindings
spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb
docker compose -f docker-compose.yml up -d --build
spacetime server add production --url https://your-database-domain.com
spacetime login --server-issued-login https://your-database-domain.com
spacetime publish -s production
# Code change to TanStack
docker compose -f docker-compose.prod.yml up -d --build
# Code change to SpacetimeDB module
spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb
spacetime publish -s production
# Update SpacetimeDB itself
docker compose pull spacetimedb && docker compose -f docker-compose.prod.yml up -d spacetimedb
For prod you can change key management for something more robust, like external secret management tools or environment variables, up to you
Prod addresses
# .env.local
# Generic / backend
SPACETIMEDB_DB_NAME=test-app-1tw1t
SPACETIMEDB_HOST=ws://localhost:3000
# Spacetimedb_host should be your spacetime docker container
# for example ws://spacetimedb:3000
# Vite
VITE_SPACETIMEDB_DB_NAME=test-app-1tw1t
VITE_SPACETIMEDB_HOST=ws://localhost:3000
# we use our spacetimedb domain
# (separate api domain or sub-domain wss://spacetime.example.com for example)
Nginx proxy setup
first setup spacetime.example.com
spacetime.example.com
http tanstack:3000
websocket support
SSL on
Add custom nginx configuration to it
# Block publishes from outside of the machine
# Don't include this if you want to publish from outside
#----
location ~ ^/v1/publish {
deny all;
return 403;
}
#----
location /v1/ {
proxy_pass http://spacetimedb:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
if you are running nginx in a docker container, add your spacetimedb and tanstack containers to the same network as nginx
docker network inspect nginx-proxy
then add in your docker-compose.prod.yml
spacetimedb:
# Remove ports if you route network with containers
...
networks:
- nginx-proxy
tanstack:
# Remove ports if you route network with containers
...
networks:
- nginx-proxy
networks:
nginx-proxy:
external: true
Clearing database
To clear database, you just need to use a docker compose command that removes volumes
docker compose down -v
Or if you prefer to clear without downtime
spacetime publish -s local-prod -c
Fixing spacetimedb openess
By default, spacetimedb is fairly open and the publishing is not being blocked
from outside
to enable only ssh publishing, block /v1/publish with nginx
Heres recommended nginx setup from official self-hosted docs integrated to this setup
# Nginx custom config under spacetime.example.com
# Block publish
location ~ ^/v1/publish {
deny all;
return 403;
}
# Block SQL
location ~ ^/v1/database/[^/]+/sql$ {
allow 127.0.0.1;
deny all;
}
# WebSocket subscribe - required
location ~ ^/v1/database/[^/]+/subscribe$ {
proxy_pass http://spacetimedb:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# Identity - required for TypeScript SDK
location /v1/identity {
proxy_pass http://spacetimedb:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
and setup a local login from the server itself
spacetime server add local-prod --url http://127.0.0.1:3001 --no-fingerprint
spacetime login --server-issued-login http://127.0.0.1:3001
spacetime publish -s local-prod
# Code change to SpacetimeDB module
spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb
spacetime publish -s local-prod
Note
If you do this after the setup, you need to wipe your database
docker compose -f docker-compose.yml down -v
docker compose -f docker-compose.yml up -d --build
spacetime login --server-issued-login http://127.0.0.1:3001
spacetime publish -s local-prod
Backing up owner identity
Everytime you relogin to the database, even in the same server your database is in, you generate new identity token for yourself. So if you logout from the owner identity YOU LOSE ACCESS TO THE DATABASE if you do logout, Use the backed up identity for the token.
Its important to backup the private/public keys AND your owner indentification. I suggest using something really secure, like encrypted secret manager or such.
cat spacetime-keys-prod/id_ecdsa
cat spacetime-keys-prod/id_ecdsa.pub
cat ~/.config/spacetime/cli.toml
# Grab the spacetimedb_token
Caution
This identity has owner access to your database keep It secure!
TanStack page routes
I have included a test.tsx in src/routes/test.tsx that shows an example of how
to add a simple page to the app