Reverse Proxy
For production deployments, place PicPeak behind a reverse proxy for SSL termination and routing.
Routing schema
| Path | Service | Port | Description |
|---|---|---|---|
/api/* | Backend | 3001 | All API endpoints |
/photos/* | Backend | 3001 | Protected photo files |
/thumbnails/* | Backend | 3001 | Protected thumbnail files |
/uploads/* | Backend | 3001 | Upload files |
/* (everything else) | Frontend | 3000 | React SPA (including /admin/*, /gallery/*) |
The /admin/* routes are served by the frontend (React SPA), not the backend. The backend only handles /api/admin/* requests.
Nginx
Create /etc/nginx/sites-available/picpeak:
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$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;
# Backend: API endpoints
location /api/ {
proxy_pass http://localhost:3001;
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;
}
# Backend: Protected media files
location ~ ^/(photos|thumbnails|uploads)/ {
proxy_pass http://localhost:3001;
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;
}
# Frontend: Everything else (React SPA)
location / {
proxy_pass http://localhost:3000;
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;
}
}Enable the site:
sudo ln -s /etc/nginx/sites-available/picpeak /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxFor video uploads, increase the body size limit:
client_max_body_size 10G;
proxy_read_timeout 3600;
proxy_send_timeout 3600;Mixed HTTPS + LAN HTTP access
Some self-hosted setups want two working entry points to the same PicPeak instance:
- Public HTTPS via the reverse proxy on a domain (
https://photos.example.com) - Direct HTTP on the LAN for admin access (
http://192.168.1.50:3001)
With the default COOKIE_SECURE setting, only one of these works at a time — the Secure cookie flag either blocks LAN HTTP (when true) or weakens HTTPS cookies (when false).
Set COOKIE_SECURE=auto in your .env to make PicPeak decide per request:
# .env
COOKIE_SECURE=autoIn this mode the backend reads req.secure from Express. The flag is set to true when the request arrived over HTTPS (either directly or via a trusted proxy forwarding X-Forwarded-Proto: https) and false otherwise. The end result: both public HTTPS login and LAN HTTP login work with correctly-flagged cookies.
The Nginx, Traefik, and Caddy configurations shown above already forward X-Forwarded-Proto correctly. PicPeak’s Express trust proxy is preset to loopback, linklocal, uniquelocal, which covers Docker networks and private-network proxies out of the box.
See Environment Variables → Authentication cookies for the full reference.