Savvy Docs

Reverse proxy

Put Savvy behind HTTPS with Traefik or Nginx Proxy Manager. Forwarded-header handling means HTTPS links and real client IPs work with no extra config.

Run Savvy behind a reverse proxy to terminate TLS and serve it on your own domain. Set APP_URL to your public https:// URL — Savvy honors the X-Forwarded-Proto and X-Forwarded-For headers from the proxy, so HTTPS link generation and real client IPs work automatically, with no extra configuration.

Always set APP_URL to the public HTTPS URL

Behind a proxy the app sees plain HTTP internally. APP_URL is what tells it the real external scheme and host. If it's wrong, redirects loop and logins fail.

Traefik handles routing and Let's Encrypt certificates via container labels:

docker-compose.yml (Traefik)
services:  savvy:    image: truenormis/savvy:v1.2.3    container_name: savvy    restart: unless-stopped    volumes:      - savvy-data:/data    environment:      - APP_URL=https://savvy.yourdomain.com      - TZ=Europe/Kyiv    labels:      - "traefik.enable=true"      - "traefik.http.routers.savvy.rule=Host(`savvy.yourdomain.com`)"      - "traefik.http.routers.savvy.entrypoints=websecure"      - "traefik.http.routers.savvy.tls.certresolver=letsencrypt"      - "traefik.http.services.savvy.loadbalancer.server.port=80"    networks:      - traefikvolumes:  savvy-data:networks:  traefik:    external: true

This assumes an existing external traefik network and a websecure entrypoint with a letsencrypt cert resolver already configured on your Traefik instance.

Expose the container on the internal network only, then point a proxy host at it from the NPM UI:

docker-compose.yml (Nginx Proxy Manager)
services:  savvy:    image: truenormis/savvy:v1.2.3    container_name: savvy    restart: unless-stopped    expose:      - "80"    volumes:      - savvy-data:/data    environment:      - APP_URL=https://savvy.yourdomain.com    networks:      - npm-networkvolumes:  savvy-data:networks:  npm-network:    external: true

In Nginx Proxy Manager, create a Proxy Host with:

  • Forward Hostname / IP: savvy
  • Forward Port: 80
  • Scheme: http
  • Enable Block Common Exploits and request an SSL certificate on the SSL tab.

Community example — verify before use

This raw nginx block is a typical configuration, not copied from the project's docs. Adjust paths and your TLS setup, and test before relying on it.

If you terminate TLS with a standalone nginx, proxy to the container and pass the forwarded headers Savvy expects:

server {
    listen 443 ssl;
    server_name savvy.yourdomain.com;

    # ssl_certificate     /etc/letsencrypt/live/savvy.yourdomain.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/savvy.yourdomain.com/privkey.pem;

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