Get started in minutes
Deploy Yotara on your own server. No vendor lock-in, no data leaving your infrastructure.
Before you start
Self-hosting is a small, one-time setup — but it does ask a few things of you. Make sure you're comfortable with these before you begin.
Set a strong secret
You must generate a
BETTER_AUTH_SECRET
to sign sessions. Without it the stack refuses to boot.
Plan for persistence
Your data lives in a SQLite file. Keep it on a named volume or mounted path so it survives container restarts.
Back it up
You own the data, which means you own the backups. Schedule a copy of the database file off-server.
Expose it safely
For real use, put it behind a domain with TLS. The included nginx config serves plain HTTP on port 80. Add a TLS-terminating reverse proxy (e.g. Caddy, nginx with certbot, or Cloudflare Tunnel) in front of it.
Quick start with Docker Compose
$ curl -o docker-compose.yml \ https://raw.githubusercontent.com/apauldev/yotara/main/docker-compose.hub.yml $ export BETTER_AUTH_SECRET=$(openssl rand -base64 32) $ docker compose up -d
→ Open http://localhost:8080
Recommended — manual Docker Compose
Create a
docker-compose.yml
in your project directory:
services: api: image: apauldev2/yotara-api:latest environment: DATABASE_URL: /app/apps/api/data/yotara.db APP_BASE_URL: ${APP_BASE_URL:-http://localhost:8080/api} TRUSTED_ORIGINS: ${TRUSTED_ORIGINS:-http://localhost:8080} BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET?set a strong secret} HOST: 0.0.0.0 PORT: ${PORT:-3000} NODE_ENV: ${NODE_ENV:-production} CONTENT_SECURITY_POLICY: ${CONTENT_SECURITY_POLICY:-default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'} volumes: - yotara_api_data:/app/apps/api/data security_opt: - no-new-privileges:true cap_drop: - ALL read_only: true tmpfs: - /tmp frontend: image: apauldev2/yotara-frontend:latest depends_on: - api environment: CONTENT_SECURITY_POLICY: ${CONTENT_SECURITY_POLICY:-default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'} ports: - "8080:80" volumes: yotara_api_data:
Then run:
$ export BETTER_AUTH_SECRET=$(openssl rand -base64 32) $ docker compose up -d
→ Open http://localhost:8080
System requirements
That's it. No external database, no Redis, no email server required. Generate your
BETTER_AUTH_SECRET
with
openssl rand -base64 32
and export it before
docker compose up.
Production checklist
Happy with the quick start? Before you rely on it day to day, run through this list.
- Use a strong, unique BETTER_AUTH_SECRET and keep it out of version control and shell history.
- Serve over HTTPS with a real domain and a valid certificate — the stack ships security headers, but TLS is on you.
- Persist the database on a named volume (the Compose file does this) or a backed-up mount.
- Automate backups of the SQLite file and test a restore occasionally.
- Pin your image tag for reproducible upgrades, then review the changelog before bumping.
- Restrict network access with a firewall; only expose what you intend.