Self-Hosting

Reverse Proxy

Put Retrospend behind a reverse proxy to serve it over HTTPS with your own domain.

Note

Make sure your PUBLIC_URL env var matches your domain exactly (e.g. https://your-domain.com). This is used for auth redirects and email links.

Nginx

Install Nginx and Certbot for automatic TLS certificates from Let's Encrypt.

bashbash
# Ubuntu / Debian
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com

Then create a site config:

/etc/nginx/sites-available/retrospendnginx
server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;

    ssl_certificate     /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

    # Recommended SSL settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:1997;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support (required for some features)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_read_timeout 300s;
        proxy_connect_timeout 300s;
    }
}
bashbash
sudo ln -s /etc/nginx/sites-available/retrospend /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Caddy

Caddy handles TLS automatically; no Certbot required. It fetches and renews certificates from Let's Encrypt on its own.

bashbash
# Install Caddy (Ubuntu)
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy
/etc/caddy/Caddyfiletext
your-domain.com {
    reverse_proxy localhost:1997 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }

    # Optional: increase body size limit for file imports
    request_body {
        max_size 50MB
    }
}
bashbash
sudo systemctl reload caddy

Cloudflare Tunnel

Cloudflare Tunnel is a good option if your server is behind NAT or you don't want to expose ports 80/443 directly. No port forwarding or static IP required.

bashbash
# Install cloudflared, then:
cloudflared tunnel login
cloudflared tunnel create retrospend

# Create config.yml
cat > ~/.cloudflared/config.yml << EOF
tunnel: <your-tunnel-id>
credentials-file: /root/.cloudflared/<your-tunnel-id>.json

ingress:
  - hostname: your-domain.com
    service: http://localhost:1997
  - service: http_status:404
EOF

cloudflared tunnel route dns retrospend your-domain.com
cloudflared tunnel run retrospend

Run the tunnel as a service: cloudflared service install

Trusted origins

If you access Retrospend through multiple hostnames (e.g., a tunnel URL and your own domain), add the extra origins to the TRUSTED_ORIGINS env var as a comma-separated list.

Trusted Origins

Better-auth validates the Origin header on auth requests. By default, PUBLIC_URL is trusted. To allow additional origins:

.env
TRUSTED_ORIGINS="https://tunnel.your-domain.com,https://other.your-domain.com"