Reverse Proxy
SkySend should be placed behind a reverse proxy for production use. This provides TLS termination, custom domain support, and additional security.
Required for Production
SkySend share links contain the encryption key in the URL fragment (#). Using HTTPS is essential to prevent the link from being intercepted in transit.
Access logs
Traefik, Nginx, and Cloudflare write the full request path into their access logs, and SkySend cannot influence that.
This normally holds nothing sensitive, because the key lives in the URL fragment and browsers never send it. A mail security gateway that rewrites a share link breaks that assumption: the key then arrives inside the path and lands in the proxy log. SkySend truncates its own log at the resource ID, so the proxy is the remaining place where such a key can persist.
If your instance handles sensitive content, disable the access log for /file/ and /note/ paths or strip everything after the ID before it is written. See Troubleshooting for what causes this.
Caddy (Recommended)
Caddy automatically provisions and renews TLS certificates:
skysend.example.com {
reverse_proxy localhost:3000
}That's it. Caddy handles HTTPS automatically.
Nginx
server {
listen 443 ssl http2;
server_name skysend.example.com;
ssl_certificate /etc/letsencrypt/live/skysend.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/skysend.example.com/privkey.pem;
client_max_body_size 2G;
location / {
proxy_pass http://localhost:3000;
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;
# Required for streaming uploads
proxy_request_buffering off;
# Required for streaming downloads
proxy_buffering off;
# Required for the WebSocket upload transport (FILE_UPLOAD_WS)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Keep long-running WebSocket uploads from timing out.
# Adjust to the largest expected upload duration.
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
# Map required to select the correct Connection header for WebSocket upgrade.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name skysend.example.com;
return 301 https://$server_name$request_uri;
}Important Nginx Settings
client_max_body_sizemust match yourFILE_MAX_SIZEsettingproxy_request_buffering offis required for streaming uploadsproxy_buffering offis required for streaming downloads- The
Upgrade/Connectionheaders and the$connection_upgrademap are required for the WebSocket upload transport (FILE_UPLOAD_WS, default on) proxy_read_timeout/proxy_send_timeoutmust be larger than the longest expected upload or Nginx will close the WebSocket mid-upload
Traefik
Using Docker labels with Traefik:
services:
skysend:
build: .
restart: always
volumes:
- "${DATA_DIR:-./data}:/app/data"
env_file:
- .env
environment:
- DATA_DIR=/app/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.skysend.rule=Host(`skysend.example.com`)"
- "traefik.http.routers.skysend.entrypoints=websecure"
- "traefik.http.routers.skysend.tls.certresolver=letsencrypt"
- "traefik.http.services.skysend.loadbalancer.server.port=3000"Traefik and the WebSocket upload transport
Traefik forwards WebSocket upgrade requests automatically, so no extra labels are required to use the WebSocket upload transport (FILE_UPLOAD_WS, enabled by default). However the upload must finish within the Traefik idle timeouts. For long uploads on slow connections, raise the entrypoint read/write timeouts in your static configuration:
entryPoints:
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: 3600s
writeTimeout: 3600s
idleTimeout: 3600sIf the upgrade fails (for example because a middleware strips the Upgrade header), clients automatically fall back to the HTTP chunked upload.
Trust Proxy
When running behind a reverse proxy, set TRUST_PROXY=true so that SkySend correctly reads the client IP from X-Forwarded-For and X-Real-IP headers. This is important for rate limiting and upload quotas.
TRUST_PROXY=trueSecurity Warning
Only enable TRUST_PROXY when SkySend is behind a trusted reverse proxy. If exposed directly to the internet with this setting enabled, clients can spoof their IP address.
BASE_URL
Set the BASE_URL to your public domain so that generated upload URLs are correct:
BASE_URL=https://skysend.example.com