Secure Self-Hosted File Sharing
Self-Hosted File Sharing Is Only as Secure as Your Configuration
Running your own file sharing server gives you control that cloud services can’t match — but control without security is a liability. A misconfigured Send instance exposes every uploaded file. A PairDrop server without TLS leaks file contents to anyone on the network path. A Gokapi deployment with default credentials is an open storage bucket.
This guide covers the security fundamentals for self-hosted file sharing: encryption (in transit and at rest), access control, network hardening, and operational practices that prevent data leaks.
Encryption in Transit: TLS Is Non-Negotiable
Every self-hosted file sharing service must sit behind TLS. Without it, file contents, authentication tokens, and metadata travel in plaintext across the network.
Reverse Proxy with Automatic TLS
The simplest approach: run your file sharing service behind a reverse proxy that handles TLS termination.
| Reverse Proxy | Auto-Renewal | Config Complexity | Best For |
|---|---|---|---|
| Caddy | Yes (built-in ACME) | Minimal | Simplest setup |
| Nginx Proxy Manager | Yes (GUI-managed) | Low (web UI) | Non-technical users |
| Traefik | Yes (ACME + Docker labels) | Moderate | Docker-native setups |
| Nginx + Certbot | Yes (cron job) | Moderate | Maximum control |
Caddy example for a Send instance:
send.yourdomain.com {
reverse_proxy send:1443
}
That’s it. Caddy automatically obtains and renews a Let’s Encrypt certificate. No certificate management, no cron jobs.
TLS Configuration Checklist
- TLS 1.2 minimum (disable TLS 1.0 and 1.1)
- Strong cipher suites only (ECDHE + AES-GCM or ChaCha20-Poly1305)
- HSTS header enabled (
Strict-Transport-Security: max-age=31536000) - HTTP → HTTPS redirect active
- Certificate auto-renewal tested (Let’s Encrypt certificates expire every 90 days)
Verify Your TLS Setup
After deployment, test with:
# Check certificate and TLS version
curl -vI https://send.yourdomain.com 2>&1 | grep -E 'SSL|TLS|issuer|expire'
# Full audit (use SSL Labs)
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=send.yourdomain.com
Target: SSL Labs grade A or A+.
Encryption at Rest: Protect Stored Files
TLS protects files in transit. Encryption at rest protects files stored on your server’s disk — from physical access, server compromise, or hosting provider access.
Application-Level Encryption
Some file sharing tools encrypt files before storing them:
| Tool | Encryption at Rest | Key Management |
|---|---|---|
| Send | Yes (AES-GCM, browser-side) | Key embedded in URL fragment (never sent to server) |
| PairDrop | N/A (files never stored) | N/A |
| Gokapi | No | N/A |
| Zipline | No | N/A |
| PicoShare | No | N/A |
| XBackBone | No | N/A |
| Chibisafe | No | N/A |
Send is the only self-hosted file sharing tool with true end-to-end encryption. The encryption key lives in the URL fragment (the part after #), which browsers never send to the server. Even if someone compromises your server, they get only encrypted blobs.
For tools without built-in encryption, add filesystem-level protection.
Filesystem-Level Encryption
LUKS (Linux Unified Key Setup) encrypts the entire partition or volume where files are stored:
# Create an encrypted volume for file storage
cryptsetup luksFormat /dev/sdb1
cryptsetup luksOpen /dev/sdb1 fileshare-data
mkfs.ext4 /dev/mapper/fileshare-data
mount /dev/mapper/fileshare-data /opt/fileshare-data
For Docker volumes, mount the encrypted filesystem and point your container volumes to it:
volumes:
- /opt/fileshare-data/uploads:/uploads
This protects against physical disk access and hosting provider snooping. The trade-off: someone with root access on the running server can still read files (the volume is decrypted while mounted).
Docker Volume Security
| Practice | Why |
|---|---|
| Use named volumes or explicit paths | Avoid anonymous volumes that are hard to track and encrypt |
| Set restrictive permissions | chmod 700 on host directories mounted into containers |
| Avoid bind-mounting sensitive paths | Don’t mount /etc, /root, or other system directories |
| Separate data from config | Use different volumes for application data vs uploaded files |
Access Control
Authentication
Never expose a file sharing service without authentication. Even tools like PairDrop (where files don’t touch the server) should require authentication to prevent unauthorized use of your signaling server.
| Method | When to Use |
|---|---|
| Built-in auth | Most file sharing tools include user/password auth. Use it. |
| Reverse proxy auth | Add HTTP Basic Auth or OAuth2 Proxy in front of tools without built-in auth |
| API tokens | For ShareX and automated uploads, use long random tokens |
| SSO (Authelia/Authentik) | For multi-service setups, centralize auth with a self-hosted SSO provider |
Strong Credentials
# Generate a strong API token
openssl rand -hex 32
# Generate a strong password
openssl rand -base64 24
Never use default credentials in production. Every self-hosted tool with default passwords (admin/admin, etc.) should have credentials changed immediately after first login.
Access Expiry
For file sharing, time-limited access is critical:
- Download limits: Set files to expire after N downloads (Send, Gokapi)
- Time-based expiry: Set files to auto-delete after hours/days (Send, Gokapi, PicoShare)
- Combine both: Expire after 10 downloads OR 7 days, whichever comes first (Gokapi)
- Review shared links periodically: Remove links that are no longer needed
Network Security
Firewall Rules
Only expose the ports your services actually need:
# UFW example — allow only HTTPS and SSH
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 443/tcp # HTTPS (reverse proxy)
ufw enable
Do NOT expose application ports directly (Send’s 1443, Zipline’s 3000, etc.). Route everything through your reverse proxy on port 443.
Docker Network Isolation
Use Docker networks to isolate file sharing services from other containers:
networks:
fileshare:
driver: bridge
proxy:
external: true
services:
send:
networks:
- fileshare
- proxy # Only if the reverse proxy needs direct access
redis:
networks:
- fileshare # Not exposed to proxy network
Rate Limiting
Prevent abuse with rate limiting at the reverse proxy level:
# Caddy rate limiting
send.yourdomain.com {
rate_limit {
zone upload_zone {
key {remote_host}
events 10
window 1m
}
}
reverse_proxy send:1443
}
| Parameter | Recommended Value | Why |
|---|---|---|
| Upload rate | 10-20 requests/minute per IP | Prevents storage abuse |
| Download rate | 50-100 requests/minute per IP | Prevents bandwidth abuse |
| Auth attempts | 5 per minute per IP | Prevents credential brute-forcing |
Fail2Ban for File Sharing
Monitor logs for failed authentication attempts and ban offending IPs:
# /etc/fail2ban/jail.local
[fileshare]
enabled = true
port = https
filter = fileshare
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600
findtime = 600
Operational Security
Backup Strategy
File sharing services need two types of backups:
- Configuration backup: Docker Compose files, environment variables, TLS certificates, application config
- Data backup (optional): Uploaded files — whether you back these up depends on whether files are ephemeral (auto-deleting) or persistent
For ephemeral file sharing (Send, Gokapi with auto-expiry), backing up uploaded files is often unnecessary — they’re designed to be temporary. Back up the configuration so you can redeploy quickly.
For persistent file hosting (Zipline, XBackBone), back up both config and data:
# Backup example using restic
restic backup /opt/fileshare-data/config /opt/fileshare-data/uploads
Update Strategy
| Component | Update Frequency | Method |
|---|---|---|
| Docker images | Monthly (check for security patches) | Pin version tags, test before updating |
| Reverse proxy | Monthly | Follow upstream release notes |
| OS packages | Weekly (security updates) | apt update && apt upgrade |
| TLS certificates | Automatic (Let’s Encrypt) | Verify auto-renewal with certbot renew --dry-run |
Monitoring
Watch for signs of compromise or abuse:
- Disk usage spikes — someone may be uploading large files without your knowledge
- Unusual download patterns — high download counts on specific files could indicate leaked links
- Failed authentication attempts — brute-force attacks against your upload endpoints
- Outbound network traffic — compromised containers may exfiltrate data
Tools like Uptime Kuma can monitor your file sharing endpoints. Netdata or Beszel can alert on disk and network anomalies.
Logging
Enable access logging at the reverse proxy level. For compliance-sensitive environments, log:
- Upload timestamps and source IPs
- Download timestamps and source IPs
- File sizes and expiry settings
- Authentication events (success and failure)
Rotate logs regularly and set retention policies that match your compliance requirements.
Security Checklist
Use this checklist when deploying any self-hosted file sharing service:
- TLS enabled with auto-renewal (grade A on SSL Labs)
- HTTP → HTTPS redirect active
- HSTS header set
- Default credentials changed
- Authentication required for all upload endpoints
- Firewall configured (only 22 and 443 open)
- Application ports not directly exposed
- Docker networks isolate services
- Rate limiting configured at reverse proxy
- File size limits set (prevent disk exhaustion)
- Auto-expiry enabled for temporary file sharing
- Backups configured and tested
- Monitoring active for disk, network, and auth failures
- Fail2Ban or equivalent protecting auth endpoints
- Logs enabled and rotated
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments