Portabase Logo

Reverse Proxy

Expose your Dashboard to the internet securely with HTTPS.

By default, the Portabase Dashboard listens on http://localhost:8887. To make it accessible from the outside (e.g. portabase.example.com) and secure it with HTTPS, use a Reverse Proxy.


This setup assumes you already run a Traefik instance on your server and it watches the Docker network (commonly traefik_network or proxy).

Docker Compose changes

Modify your docker-compose.yml to:

  1. Remove direct host port exposure (no 8887:80).
  2. Connect the container to Traefik's network.
  3. Add Traefik labels.
docker-compose.yml
name: portabase-dashboard

services:
  portabase:
    container_name: portabase-app
    image: portabase/portabase:latest
    restart: always
    env_file: .env
    environment:
        - TZ=Europe/Paris
    expose:
      - 80
    volumes:
      - portabase-data:/data
    depends_on:
      db:
        condition: service_healthy
    networks:
      - traefik_network # Network where Traefik lives
      - default # To talk to the local database
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portabase.entrypoints=web,websecure"
      - "traefik.http.routers.portabase.rule=Host(`portabase.example.com`)"
      - "traefik.http.routers.portabase.tls.certresolver=myresolver"

  db:
    container_name: portabase-pg
    image: postgres:17-alpine
    restart: always
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - default

volumes:
  postgres-data:
  portabase-data:

networks:
  traefik_network:
  external: true

Name conflicts

If you host multiple dashboards on the same Traefik server, change the router name in labels to unique values:

  • Instance 1: traefik.http.routers.portabase-prod...
  • Instance 2: traefik.http.routers.portabase-dev...

If you use a traditional web server like Nginx, Apache or Caddy on the host:

1. Portabase configuration

Keep the default config that binds the service to localhost.

ports:
- "127.0.0.1:8887:80" # Listen only on localhost

2. WebSocket variable

The dashboard uses WebSockets. Nginx has no built-in variable to forward the Connection header only when needed, so declare one in the http block (for example in /etc/nginx/conf.d/upgrade.conf):

/etc/nginx/conf.d/upgrade.conf
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

Do not hardcode Connection "upgrade"

Setting proxy_set_header Connection "upgrade" on every request breaks keepalive to the upstream. The map above sends upgrade for WebSocket requests and close for the rest.

3. Nginx server blocks

A complete setup with an HTTP → HTTPS redirect, HTTP/2 and WebSocket support.

/etc/nginx/sites-available/portabase
server {
    listen 80;
    http2 on;

    server_name portabase.example.com;

    return 301 https://portabase.example.com$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name portabase.example.com;

    include /etc/nginx/snippets/ssl.conf;

    location / {
        proxy_pass http://127.0.0.1:8887;

        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;
        proxy_set_header        X-Scheme $scheme;
        proxy_set_header        Upgrade $http_upgrade;
        proxy_set_header        Connection $connection_upgrade;

        proxy_read_timeout 120s;
        proxy_send_timeout 60s;
        proxy_connect_timeout 10s;
    }
}

Adapt to your setup

  • proxy_pass http://127.0.0.1:8887 matches step 1. If Nginx itself runs in Docker on the same network as the dashboard, use the container name instead: proxy_pass http://portabase-app:80.
  • /etc/nginx/snippets/ssl.conf holds your certificate and TLS settings (ssl_certificate, ssl_certificate_key, …). Certbot generates the equivalent lines directly in the server block.

4. Enable the site

ln -s /etc/nginx/sites-available/portabase /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

🚧 Work in progress 🚧


PROJECT_URL environment variable

Whatever reverse proxy you use, update the .env file so generated links and emails use the correct public URL.

.env
# Before
PROJECT_URL=http://localhost:8887

# After (your public domain)
PROJECT_URL=https://portabase.example.com

Restart the dashboard after changing this:

portabase restart .
docker-compose down && docker-compose up -d

Last updated on

On this page