Getting started
Step 1 · ~10 min

Tephra on AWS

One small EC2 server with its own disk.

You'll need An AWS account, with the aws CLI signed inA domain you can add DNS records to
AWS account EC2 instance reads + writes You browser + Obsidian Your domain notes.yourname.com Elastic IP firewall 80 / 443 Caddy automatic HTTPS .env file locked to root Tephra web app + sync API EBS volume /data · your notes
swipe to see it all → your requests settings it reads where your notes live
  1. 1

    Grab Tephra

    git clone https://github.com/championswimmer/tephra && cd tephra
  2. 2

    Launch it

    Swap in your own domain. The server, disk, IP and HTTPS are all set up for you.

    DOMAIN=notes.yourname.com scripts/deploy/aws.sh
  3. 3

    Point your domain at it

    The script prints an IP address. At your domain provider, add an A record for your domain pointing to that IP. On Route 53? Add HOSTED_ZONE_ID=… to the command above and this is done for you.

  4. 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.

    grep BOOTSTRAP ~/.tephra-aws-notes.yourname.com.env
Reference

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.

Where they live on AWS

The /opt/tephra/.env file on the instance (mode 600), loaded by Docker Compose. The CloudFormation path keeps the two secrets in Secrets Manager and writes them into that file at boot.

grep BOOTSTRAP ~/.tephra-aws-notes.yourname.com.env

The one-command script sets TEPHRA_PUBLIC_URL and both secrets, and keeps a local copy of the secrets in ~/.tephra-aws-<domain>.env.

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. Delete the TEPHRA_BOOTSTRAP_TOKEN line from /opt/tephra/.env and run docker compose up -d in /opt/tephra. Both AWS paths expose only ports 80/443, so add temporary SSH or SSM access first. The bootstrap endpoint is disabled permanently once a user exists.

Want every detail, every knob? The full AWS guide is on GitHub.