Tephra on Google Cloud
One small VM, launched right from your browser.
- 1
Open Cloud Shell
Use the button above. You're already signed in and Tephra is already downloaded.
- 2
Launch it
Swap in your project ID and domain.
PROJECT=my-project ZONE=us-central1-a DOMAIN=notes.yourname.com scripts/deploy/gcp.sh - 3
Point your domain at it
The script prints an IP address. At your domain provider, add an
Arecord for your domain pointing to that IP. - 4
Copy your setup token
Give the server about 5 minutes to warm up. You'll paste the token once, when you create your login.
gcloud secrets versions access latest --secret=tephra-bootstrap-token
Environment variables
The steps above already set everything Tephra needs. This is the complete list for a manual install, a different host, or a change later on.
Secret Manager for the two secrets, plus /opt/tephra/tephra.env on the VM, written at first boot. The script creates tephra-session-secret and tephra-bootstrap-token for you.
gcloud secrets versions access latest --secret=tephra-bootstrap-token The deploy script sets TEPHRA_PUBLIC_URL=https://<domain> and reads both secrets from Secret Manager on every boot.
| Variable | When | Default | What it does |
|---|---|---|---|
TEPHRA_PUBLIC_URL | Always | none | Browser-visible origin, including the scheme (https://notes.yourname.com). Used for redirects, cookies and MCP OAuth discovery. It must match the address people open. |
TEPHRA_SESSION_SECRET | Always | none | Signs and protects browser sessions. Use at least 32 random bytes, for example openssl rand -hex 32. Never reuse the bootstrap token here. |
TEPHRA_BOOTSTRAP_TOKEN | First boot | none | One-time proof for creating the first admin account at /setup. Delete it from the environment after that account exists. |
HOST | Optional | 0.0.0.0 in the image | HTTP bind address. Leave it at 0.0.0.0 inside a container. |
PORT | Optional | 8080 | Single port for the API and the web app. Railway injects its own value, so do not set it there. |
NODE_ENV | Optional | production in the image | When set to production, session cookies are marked Secure. The container image already sets it. |
TEPHRA_DATABASE_DRIVER | Optional | sqlite | Must be sqlite. Tephra refuses to start with any other value: live storage is disk-only. |
TEPHRA_SQLITE_PATH | Optional | /data/tephra.db in the image | SQLite database file. Keep it on the persistent disk, never in the container layer. |
TEPHRA_BLOB_DRIVER | Optional | filesystem | Must be filesystem, matching the disk-only profile. |
TEPHRA_BLOB_PATH | Optional | /data/blobs in the image | Content-addressed attachment store. Must sit next to the database on the same disk. |
TEPHRA_MAX_BLOB_BYTES | Optional | 104857600 (100 MiB) | Largest attachment Tephra accepts. Platform request limits can be lower; raise both or neither. |
TEPHRA_WEB_ROOT | Optional | /app/tephra-server/apps/web/dist in the image | Directory of the built web app served by the API process. Only change it for custom builds. |
Delete TEPHRA_BOOTSTRAP_TOKEN after your first login. It only exists to create the first admin. Remove the TEPHRA_BOOTSTRAP_TOKEN line from /opt/tephra/tephra.env and restart the container, then delete the secret in Secret Manager.
Want every detail, every knob? The full Google Cloud guide is on GitHub.