7.1 KiB
Reverse Proxy & Subpath Hosting
Shelfmark can run behind a reverse proxy at the root path (recommended) or under a subpath like /shelfmark.
Root path setup (Recommended)
If you can serve Shelfmark at the root path (https://shelfmark.example.com/), leave URL_BASE empty. This is the simplest option and avoids extra subpath configuration.
Define this once in your Nginx http block so websocket upgrades are only sent when the client actually requests them:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name shelfmark.example.com;
location / {
proxy_pass http://shelfmark:8084;
proxy_http_version 1.1;
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 Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Subpath setup
Running Shelfmark under a subpath like /shelfmark is supported without extra rewrite rules.
1. Set the base path in Shelfmark
- UI: Settings → Advanced → Base Path →
/shelfmark/ - Environment variable:
URL_BASE=/shelfmark/
2. Configure your reverse proxy
All Shelfmark paths (UI, API, assets, Socket.IO) are served under the base path. A single location block is enough.
Without Authentication Proxy
Complete Nginx configuration for subpath deployment:
location /shelfmark/ {
proxy_pass http://shelfmark:8084/shelfmark/;
proxy_http_version 1.1;
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-Forwarded-Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_buffering off;
}
With Authentication Proxy (Authelia, Authentik, etc.)
Shelfmark supports Proxy Authentication. When enabled, Shelfmark trusts the authenticated user from headers set by your auth proxy.
Shelfmark Settings
Configure in Settings → Security:
| Setting | Value |
|---|---|
| Authentication Method | Proxy Authentication |
| Proxy Auth User Header | Remote-User |
| Proxy Auth Logout URL | https://auth.example.com/logout |
| Proxy Auth Admin Group Header | Remote-Groups |
| Proxy Auth Admin Group Name | admins (or your admin group) |
Nginx Configuration with Authelia
This example uses Authelia snippets. Adapt for your auth proxy.
Authelia auth request snippet (/etc/nginx/snippets/authelia-authrequest.conf):
location /authelia {
internal;
proxy_pass http://authelia:9091/api/authz/auth-request;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Original-Method $request_method;
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;
}
Authelia location snippet (/etc/nginx/snippets/authelia-location.conf):
auth_request /authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
error_page 401 =302 https://auth.example.com/?rd=$target_url;
Complete Nginx configuration with Authelia:
# Include Authelia auth endpoint in your server block
include /etc/nginx/snippets/authelia-authrequest.conf;
# Main shelfmark location
location /shelfmark/ {
include /etc/nginx/snippets/authelia-location.conf;
proxy_pass http://shelfmark:8084/shelfmark/;
proxy_http_version 1.1;
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-Forwarded-Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_buffering off;
}
Troubleshooting false network errors
If login, settings saves, or downloads appear to fail in the browser but the action still completes on the server, check your proxy headers first.
- Do not force
Connection: upgradeon every request. That can break normalPOSTandPUTresponses while the backend still processes them. - If your proxy UI does not support conditional websocket headers, remove the forced websocket headers entirely and let Shelfmark fall back to polling.
- Keep the standard forwarded headers:
Host,X-Forwarded-For,X-Forwarded-Proto, andX-Forwarded-Hostwhen using a subpath or OIDC.
This is especially relevant for Nginx Proxy Manager or custom advanced config snippets that add websocket headers globally.
Nginx Proxy Manager
If you are using Nginx Proxy Manager and see errors like "proxy interrupted the response", slow UI interactions, or missing real-time updates:
- Do not force
Connection: upgradein the main proxy host config. - Keep the normal Shelfmark proxy host for
/or/shelfmark/. - Add a dedicated Socket.IO location block in the Proxy Host's Advanced config so Socket.IO can negotiate correctly.
- Match the location to your public path: use
location /socket.io/at the root path, orlocation /shelfmark/socket.io/if you run Shelfmark under/shelfmark. - If you use an auth proxy such as Authentik or Authelia, keep the same
auth_requestlogic inside the/socket.io/block too.
Example Advanced config snippet for a root-path install:
location /socket.io/ {
auth_request /authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
proxy_pass http://shelfmark:8084;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
Adapt the auth-related lines for your setup. If you are not using proxy authentication, you can omit the auth_request and Remote-* header lines.
Health checks
Health checks work at /shelfmark/api/health when using a subpath configuration.