The Tembo self-hosted stack runs as a single NixOS machine. All services sit behind nginx on port 80:
Service
Path
Port (internal)
tembo-web (Next.js frontend)
/
3000
tembo-ts-api (REST API)
/api/*
3001
Admin UI
/admin/
3002
Installer / setup wizard
/installer/
3999
PostgreSQL 16
—
5432
PGAdmin Console
—
5050
Redis
—
6379
Prometheus
—
9090
Tembo distributes a pre-built NixOS AMI (Amazon Machine Image) to your AWS account. You launch an EC2 instance from that AMI, open the required ports, and configure a single JSON file. No OS setup or image building is required on your end.
To get started with Tembo self-hosted, you will need a license key and access to the Tembo AMI. Book a demo with the Tembo team to get set up:Once you have a license key, contact Tembo to have the AMI shared with your AWS account. You will need to provide:
Your license key
Your AWS Account ID (12-digit number, found in the AWS Console under your account menu or via aws sts get-caller-identity --query Account --output text)
Your preferred AWS region (e.g. us-east-1)
Tembo will share the AMI with your account. You will receive an AMI ID (e.g. ami-0abc1234def56789) once sharing is confirmed.
The AMI contains no embedded secrets. Initial configuration is written to /var/lib/tembo/config.json at first boot by the tembo-config-seed service.
We recommend c5.metal for the best experience more than any other instance type. The other .metal instances are also good choices.
Instances that have 8th-gen Intel Nitro will also work (Eg. m8i.*), just slower than metal. We also support virtualization.
All other instance types are not fully supported.
Tembo services route through nginx on port 80. Do not open ports 3000, 3001, or 3002 publicly — those are internal-only ports. Accessing the app directly on port 3000 bypasses nginx and will break authentication.
Once the instance is running, open the installer in your browser:
http://<instance-ip>:3999
Follow the on-screen steps to complete the install workflow. This provisions the Tembo services and prepares the instance for use. This install can take up to an hour to fully complete. Subsequent updates will be faster.
After the installer finishes, open the VS Code server to edit the configuration file:
http://<instance-ip>:8888
The VS Code server opens directly to /var/lib/tembo/config.json. You can also see it in the VS Code file explorer on the right as config.json A few values must be set correctly for the install to work.Ensure these keys are present and correct:
{ "betterAuth.secret": "<random string, at least 32 characters>", "api.base": "http://<instance-public-ip>/api/", "frontend.url": "http://<instance-public-ip>"}
Key
Notes
betterAuth.secret
Auto-generated on first boot if missing. Leave it if it is already set.
api.base
Must match the public URL of the API. Must end with a trailing /.
frontend.url
Defaults to http://localhost:3000, which breaks auth on a remote VM. Set this to the actual public IP or hostname.
For the full list of available configuration keys, see Environment Variables.After saving, restart the API. There is a background service that should restart the API for you on finishing edits, but you can also do this from a terminal in the VS Code server, or via SSH:
sudo systemctl restart tembo-ts-api
The config seed runs before tembo-ts-api, tembo-ts-cron, and agent workers on every boot. Manual edits are preserved — the seed only writes values that are missing or empty.
If you have a domain name, set both api.base and frontend.url to the domain (e.g. https://tembo.example.com/api/ and https://tembo.example.com) rather than the raw IP. This makes it easier to rotate instances or add a load balancer later.
You should see the Tembo sign-up or sign-in screen.Check service status on the instance:
systemctl status tembo-ts-apisystemctl status tembo-ts-agent-Xsystemctl status tembo-websystemctl status nginx
For the tembo-ts-agent-X, depending on how many agents you chose to provision in the install step, X will be that number. (Eg. 3 agents make tembo-ts-agent-1, tembo-ts-agent-2, tembo-ts-agent3)
Symptom:POST http://<ip>:3000/api/auth/sign-up/email returns 404.Cause: You are hitting the Next.js frontend directly on port 3000, bypassing nginx. The /api/auth/* handler does not exist at that port.Fix: Access the app through nginx on port 80:
http://<instance-ip> # correcthttp://<instance-ip>:3000 # wrong — internal port only
If port 80 is blocked, check your EC2 security group inbound rules.
Symptom: Sign-up succeeds but all subsequent API requests return 401.Cause: Billing is enabled by default. Without Stripe configured, organization creation fails silently, leaving the user with no active org.Fix: Confirm BILLING_ENABLED = "false" is set in the API environment in your NixOS configuration. Contact Tembo support if this was not set in the distributed image.
Symptom: Sign-in redirects back to the login page, or cookies are not set.Cause:api.base or frontend.url in config.json does not match the URL you are accessing the app from. Better Auth uses these for trusted origins and cookie domain validation.Fix: Edit /var/lib/tembo/config.json and set both keys to the exact origin you are using in the browser. Restart the API:
# Check all Tembo services at oncesystemctl list-units 'tembo-*'# View logs for a specific servicejournalctl -u tembo-ts-api -n 100journalctl -u tembo-web -n 100
The tembo-config-seed service must complete before the API and agents start. If the API fails immediately at boot, check: