Paperclip SSL Setup: HTTPS with Let's Encrypt
Running Paperclip over plain HTTP is fine for local development, but any production instance needs HTTPS. Certbot and Let's Encrypt give you free, auto-renewing SSL certificates in minutes.
Deploy on Railway instead →Prerequisites
- A domain name pointing to your server's IP (A record set and propagated)
- nginx installed and running
- Port 80 and 443 open in your firewall
Step 1: Install Certbot
sudo apt install -y certbot python3-certbot-nginx
Step 2: Obtain a certificate
Make sure nginx is running with a basic HTTP config for your domain first. Then run:
sudo certbot --nginx -d paperclip.yourdomain.com
Certbot will:
- Verify domain ownership via HTTP challenge
- Issue the certificate
- Automatically update your nginx config with SSL settings
- Redirect HTTP to HTTPS
Follow the prompts — enter your email for renewal notices and agree to the terms of service.
Step 3: Verify
sudo nginx -t && sudo systemctl reload nginx
Open https://paperclip.yourdomain.com in your browser. You should see the green padlock.
What Certbot adds to nginx
After running certbot, your nginx server block will have these additions:
ssl_certificate /etc/letsencrypt/live/paperclip.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/paperclip.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
And a redirect server block:
server {
listen 80;
server_name paperclip.yourdomain.com;
return 301 https://$server_name$request_uri;
}
Don't remove these — they're what makes HTTPS work.
Step 4: Set up auto-renewal
Let's Encrypt certificates expire every 90 days. Certbot installs a systemd timer that renews them automatically.
Verify the timer is active:
sudo systemctl status certbot.timer
Test renewal without actually renewing:
sudo certbot renew --dry-run
If the dry run succeeds, auto-renewal is working. You won't need to do anything manually.
Multiple domains
To add multiple domains to the same certificate:
sudo certbot --nginx -d paperclip.yourdomain.com -d www.paperclip.yourdomain.com
Or add an additional domain to an existing cert:
sudo certbot --nginx -d paperclip.yourdomain.com -d another.yourdomain.com --expand
Wildcard certificates
For *.yourdomain.com wildcard certificates, use the DNS challenge instead of HTTP:
sudo certbot certonly --manual \
--preferred-challenges=dns \
-d *.yourdomain.com \
-d yourdomain.com
This requires adding a TXT record to your DNS, then press Enter. Useful if you're managing multiple subdomains.
Manual nginx SSL (without Certbot)
If you have your own certificate (e.g., from ZeroSSL or a paid CA), configure nginx manually:
server {
listen 443 ssl http2;
server_name paperclip.yourdomain.com;
ssl_certificate /path/to/your/fullchain.pem;
ssl_certificate_key /path/to/your/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# ... rest of your config
}
HTTPS behind a load balancer
If your server is behind a load balancer that terminates SSL (AWS ALB, Cloudflare, etc.), configure Paperclip to trust forwarded headers:
# Set this if Paperclip is behind a proxy that adds X-Forwarded-Proto
PAPERCLIP_TRUST_PROXY=true
Also set in nginx:
proxy_set_header X-Forwarded-Proto $scheme;
This tells Paperclip the connection is HTTPS even though the server-side connection is HTTP.
Common errors
Challenge failed (HTTP 404): nginx isn't configured for your domain yet, or the A record hasn't propagated. Check: curl http://paperclip.yourdomain.com — does it reach your server?
Connection timed out during challenge: Port 80 is blocked by your firewall. Run: sudo ufw allow 80
Certificate already exists but is expired: Run sudo certbot renew --force-renewal
ssl_dhparam file missing: Generate it: openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 2048 (takes a few minutes)
Checking certificate expiry
sudo certbot certificates
Shows all certificates, their domains, and expiry dates.
Check a specific domain:
echo | openssl s_client -connect paperclip.yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates
Cloudflare as an alternative
If your DNS is on Cloudflare, you can use Cloudflare's free SSL instead of Let's Encrypt. Set the SSL mode to Full (strict) and Cloudflare handles certificate management. Your server still needs a certificate (can be self-signed since Cloudflare terminates at the edge), or use Cloudflare's origin certificate.
Managed platforms like Railway handle all of this automatically — no SSL configuration needed.
Ready to deploy?
Affiliate disclosure: this link may earn us a commission at no extra cost to you.
This is an independent guide. Paperclip Hosting is not affiliated with the official Paperclip project. Guide steps are based on real deployments and are subject to change as the software evolves.
Related articles
Deploy Paperclip on Fly.io
Run Paperclip on Fly.io with persistent storage, zero-downtime deploys, and global edge distribution — full setup guide.
Deploy Paperclip on Render
Host Paperclip on Render with a persistent disk, free SSL, and auto-deploys from GitHub — step-by-step setup guide.
Deploy Paperclip on Hetzner Cloud
Host Paperclip on Hetzner for as little as €4.51/month — one of the cheapest VPS options in Europe with great performance.
