nethera

Recipes

Self-host Paperless-ngx with a public URL

Deploy Paperless-ngx as a Docker Compose app and reach it from anywhere over HTTPS, without port forwarding or a static IP.


This deploys Paperless-ngx, a document management and OCR system, along with its Postgres and Redis dependencies, and exposes the web UI at a public HTTPS URL that Nethera assigns. For a full introduction to how Nethera works, see /docs.

Why self-host Paperless-ngx

The realistic alternative to this isn't "no document management," it's Paperless-ngx running on a home server or NAS that you can only reach on your LAN. That works fine at your desk, but it breaks the actual use case: scanning a receipt or ID at the point you need it, then pulling it up later from your phone, a client's office, or anywhere that isn't your home network. The usual fixes for that (port forwarding to a self-hosted box, or dropping the documents into Google Drive/Dropbox instead) either open a raw port on your home connection or hand tax records, contracts, and IDs to someone else's cloud. Deploying via Nethera keeps the documents on infrastructure you control and still gives you a URL that works from outside your network, without you configuring the router or trusting a third party with the files.

Requirements

  • Nethera CLI (neth) installed
  • A machine running the Nethera agent, reachable by the CLI

See /docs/quickstart for setup of both.

nethera.yml

nethera.yml
appName: paperless
services:
web:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
environment:
PAPERLESS_REDIS: redis://redis:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless
PAPERLESS_URL: ${NETHERA_PUBLIC_URL}
PAPERLESS_ADMIN_USER: admin
volumes:
- paperless-data:/usr/src/paperless/data
- paperless-media:/usr/src/paperless/media
- paperless-export:/usr/src/paperless/export
- /mnt/nethera/paperless/consume:/usr/src/paperless/consume
depends_on:
- db
- redis
nethera:
public: 8000 # exposes container port 8000 (Paperless's web UI) at the public HTTPS URL
auth: login # requires Nethera login before Paperless-ngx loads
secrets:
- PAPERLESS_SECRET_KEY
- PAPERLESS_DBPASS
- PAPERLESS_ADMIN_PASSWORD
 
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
volumes:
- paperless-db:/var/lib/postgresql/data
nethera:
secrets:
- POSTGRES_PASSWORD
 
redis:
image: redis:7-alpine
volumes:
- paperless-redis:/data
 
volumes:
paperless-data:
paperless-media:
paperless-export:
paperless-db:
paperless-redis:

Only web has public: 8000, so only the Paperless-ngx web UI is exposed through Nethera. Postgres and Redis stay internal to the Compose network.

Deploy

Initialize the app and set Paperless-ngx secrets:

bash
$neth init
$neth secrets set PAPERLESS_SECRET_KEY
$neth secrets set PAPERLESS_DBPASS
$neth secrets set POSTGRES_PASSWORD
$neth secrets set PAPERLESS_ADMIN_PASSWORD
$neth deploy

Use the same value for PAPERLESS_DBPASS and POSTGRES_PASSWORD, unless you also change the database/user setup.

neth init prepares the Nethera metadata for the app, including the generated app identifier and target machine selection.

Nethera injects NETHERA_PUBLIC_URL into the deployment env file, so Paperless-ngx gets the correct public URL during the first deploy.

Open and verify

Open the HTTPS endpoint printed by neth deploy. You'll be prompted for Nethera login before Paperless-ngx loads. Then log in to Paperless-ngx with the admin user configured in this recipe:

text
username: admin
password: the value you set with neth secrets set PAPERLESS_ADMIN_PASSWORD

Check that the UI loads correctly over the public URL before relying on it.

Data and config notes

  • /mnt/nethera/paperless/consume is the drop folder on the machine running the Nethera agent: anything placed in it gets OCR'd and imported automatically.
  • paperless-media holds the processed originals and thumbnails; paperless-data holds the search index and app state. Back both up, not just the database.
  • paperless-export is where Paperless-ngx writes bulk exports if you run one; it's empty until you do.
  • PAPERLESS_URL uses NETHERA_PUBLIC_URL, which Nethera injects automatically from the public endpoint.
  • PAPERLESS_SECRET_KEY, PAPERLESS_DBPASS, POSTGRES_PASSWORD, and PAPERLESS_ADMIN_PASSWORD are stored as Nethera secrets and injected into the containers at deploy time.

Troubleshooting

CSRF or "Bad Request" errors on login. Usually means PAPERLESS_URL doesn't match the URL you're actually accessing. Check that it still uses ${NETHERA_PUBLIC_URL}.

web container restarts on first deploy. db and redis may not be ready yet when web starts, since depends_on here doesn't wait for a health check. Give it a minute and check web's logs; it should come up once Postgres is accepting connections.

Files dropped in consume aren't showing up. Confirm they're going into /mnt/nethera/paperless/consume on the machine running the Nethera agent, not a local folder on your development machine.

Paperless-ngx cannot connect to Postgres. Check that PAPERLESS_DBPASS and POSTGRES_PASSWORD were set to the same value, unless you intentionally changed the database setup.

FAQ

Can I access my Paperless-ngx instance from outside my home network? Yes. The public: 8000 field maps the web UI to the HTTPS URL Nethera assigns, so it's reachable from anywhere, no port forwarding or dynamic DNS setup on your end.

Why not just use a VPN, like Tailscale or WireGuard?

A VPN works well if it's just you, or a small group who already have a client installed. Nethera's endpoint is a normal HTTPS link instead, useful once you want to share access without asking someone to install anything. auth: login still gates who's let through if you want that.

Why run Paperless-ngx myself instead of just scanning documents into Google Drive? Because the documents stay on infrastructure you control instead of a third party's cloud, while you still get the remote access that makes scanning-on-the-go useful in the first place, without opening a port on your home router to get it.

How do I change the domain after I've already deployed? Use Nethera-generated endpoint env vars for the default endpoint. Custom-domain support is documented separately when available.

Can I use auth: none instead? Yes, if you want Paperless-ngx's own users to be the only access layer and you're comfortable with the Paperless login page being reachable by anyone with the URL. This recipe uses auth: login by default because document storage is usually sensitive.

Can I redeploy or update this without SSHing into the machine?

Yes, neth deploy from your project directory redeploys in place. If you're managing more than one machine, the same command and nethera.yml work whether you're targeting one or several, see fleet management for pairing multiple machines under one workspace.

Notes

  • Back up paperless-data and paperless-media, not just the Postgres volume; the search index and originals live outside the database.
  • Keep PAPERLESS_SECRET_KEY stable. Changing or losing it later can break existing sessions and security-related state.
  • The consume folder is a host path at /mnt/nethera/paperless/consume, so files must be placed there on the machine running the agent.