Deploying Paperman Server with HTTPS

This guide covers deploying the paperman search server with HTTPS and authentication on your server.


Option 2: Using Nginx (Alternative)

If you prefer nginx over Apache:

Step 1: Install Nginx

# On your server
sudo apt update
sudo apt install nginx

# Stop Apache if you want nginx on port 80/443
sudo systemctl stop apache2
sudo systemctl disable apache2

Step 2: Create SSL Certificate

Same as Apache Option A or B above.

Step 3: Install Nginx Configuration

# Copy configuration
sudo cp nginx-paperman.conf /etc/nginx/sites-available/paperman

# Edit configuration
sudo nano /etc/nginx/sites-available/paperman
# Update server_name and SSL certificate paths

# Enable site
sudo ln -s /etc/nginx/sites-available/paperman /etc/nginx/sites-enabled/

# Remove default site (optional)
sudo rm /etc/nginx/sites-enabled/default

# Test configuration
sudo nginx -t

# If OK, reload
sudo systemctl reload nginx

Step 4: Deploy Paperman Server

Same as Apache Step 4 above.


Firewall Configuration

Allow HTTPS through firewall

# UFW (if using)
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp  # For Let's Encrypt or HTTP redirect
sudo ufw status

# Or iptables
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo netfilter-persistent save

Block direct access to port 8080 (optional security)

# Only allow localhost to access paperman-server directly
sudo ufw deny 8080/tcp

# Or with iptables
sudo iptables -A INPUT -p tcp --dport 8080 -i lo -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8080 -j DROP
sudo netfilter-persistent save

Security Checklist

  • ☐ SSL/TLS enabled (HTTPS)

  • ☐ API key authentication enabled

  • ☐ Firewall configured (443 open, 8080 blocked externally)

  • ☐ Strong API key generated (use openssl rand -base64 32)

  • ☐ Systemd service running as non-root user

  • ☐ Logs being monitored (sudo journalctl -u paperman-server -f)

  • ☐ Automatic updates enabled on your server

  • ☐ Backups configured


Generating Strong API Key

# Generate a strong random API key
openssl rand -base64 32

# Example output:
# XzY9mK3nP8qR2vB5jN7hL4wT6dC1sF0g

# Use this in your systemd service:
Environment="PAPERMAN_API_KEY=XzY9mK3nP8qR2vB5jN7hL4wT6dC1sF0g"

Troubleshooting

Check if services are running

# Paperman server
sudo systemctl status paperman-server

# Apache
sudo systemctl status apache2

# Nginx
sudo systemctl status nginx

View logs

# Paperman server logs
sudo journalctl -u paperman-server -n 50
sudo journalctl -u paperman-server -f  # Follow

# Apache logs
sudo tail -f /var/log/apache2/paperman-error.log
sudo tail -f /var/log/apache2/paperman-access.log

# Nginx logs
sudo tail -f /var/log/nginx/paperman-error.log
sudo tail -f /var/log/nginx/paperman-access.log

Test SSL certificate

# Check certificate
openssl s_client -connect your-server.example.com:443 -showcerts

# Check what's listening on ports
sudo netstat -tlnp | grep -E ':(80|443|8080)'

Common issues

“Connection refused” - Check firewall: sudo ufw status - Check service running: sudo systemctl status paperman-server - Check port binding: sudo netstat -tlnp | grep 8080

“502 Bad Gateway” - Paperman server not running: sudo systemctl start paperman-server - Wrong proxy_pass URL in config

“401 Unauthorized” - Check API key matches in systemd service and client request - Check logs: sudo journalctl -u paperman-server | grep Authentication

SSL certificate warnings - Self-signed cert: Expected, use -k flag with curl or add exception in browser - Let’s Encrypt: Check domain name and renewal


Client Configuration Examples

Browser Bookmarklet

Create a bookmarklet to add API key automatically:

javascript:(function(){
  var url = 'https://your-server.example.com/search?q=' +
            encodeURIComponent(window.getSelection().toString() || prompt('Search:'));
  fetch(url, {
    headers: {'X-API-Key': 'your-api-key-here'}
  }).then(r=>r.json()).then(console.log);
})();

Python Script

#!/usr/bin/env python3
import requests

API_KEY = "your-api-key-here"
BASE_URL = "https://your-server.example.com"

def search_papers(query):
    response = requests.get(
        f"{BASE_URL}/search",
        params={'q': query},
        headers={'X-API-Key': API_KEY},
        verify=True  # Set to False for self-signed certs (not recommended)
    )
    return response.json()

if __name__ == "__main__":
    results = search_papers("invoice")
    print(f"Found {results['count']} files")
    for file in results.get('files', []):
        print(f"  - {file['name']}")

Shell Script

#!/bin/bash
# paperman-search.sh

API_KEY="your-api-key-here"
BASE_URL="https://your-server.example.com"

search() {
    curl -s -H "X-API-Key: $API_KEY" \
         "$BASE_URL/search?q=$1" | jq .
}

download() {
    curl -H "X-API-Key: $API_KEY" \
         "$BASE_URL/file?path=$1" -o "$2"
}

# Usage:
# ./paperman-search.sh search invoice
# ./paperman-search.sh download path/to/file.pdf output.pdf

Monitoring and Maintenance

Set up log rotation

Apache and nginx handle their own log rotation. For paperman-server:

# Create /etc/logrotate.d/paperman-server
sudo nano /etc/logrotate.d/paperman-server
/var/log/paperman-server/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 paperman paperman
    sharedscripts
    postrotate
        systemctl reload paperman-server > /dev/null
    endscript
}

Monitor with systemd

# Enable email notifications on failure (requires mail setup)
sudo systemctl edit paperman-server.service

Add:

[Service]
OnFailure=status-email@%n.service

Performance Tuning

For Apache, increase timeout for large PDF conversions:

# In /etc/apache2/sites-available/paperman.conf
ProxyTimeout 120
Timeout 120

For nginx:

# In /etc/nginx/sites-available/paperman
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;