What you end up with
You drop a scan, a phone photo or a PDF into Paperless-ngx. If it has no text yet, it is read with OCR (optical character recognition, the step that turns a picture of a page into words a computer can search), and a searchable PDF/A copy is saved next to your original; the original is never changed. A PDF that already has text, like a statement you downloaded, is indexed and kept just as it is. Then Paperless suggests tags, the sender and the kind of document from what you filed before.
What you get is one search box over everything you own on paper. Because it runs on your server rather than someone's app, the files, the text and the database are yours to keep, move or export whenever you like.
How much server does your paperwork need?
Less than you might think for daily use, and more for the first big scanning weekend. The project does not publish minimum specs, and its FAQ notes that even a Raspberry Pi 3 B can run it, just slowly when reading pages. What decides how it feels:
- Processor cores do the reading. Paperless splits the work into task workers (one by default) and threads per worker, and the docs warn that workers times threads should not go above your core count, or everything crawls.
- Languages matter: telling OCR to try two languages on every page, such as
deu+eng, takes much more processor time than one. - Memory grows with web workers, since each one loads the whole app. One is the default and is fine for a family or a small office.
- Disk holds each original, a PDF/A copy of every scan, thumbnails and the database. Our suggestion: leave room for one complete export on the same disk too, since that is how backups are made.
Back-scanning ten years of folders keeps the cores busy for hours. After that, a few pages a day barely registers.
The server that fits
Paperless-ngx is one job with its database beside it, which is what our small cartridge servers are for. A four-core Xeon E3 with NVMe storage is plenty for a household archive. Planning a big back-scan? The Xeon D cartridge has 16 cores and 1.92 TB of NVMe, so you can run more workers and clear the pile sooner. Each one is yours entirely: root access, and nobody else on it; compare them on the dedicated servers page.
Think about the disks before the processor. Our blade and rack servers can be ordered with a hardware RAID controller, so two drives can mirror each other and one can fail without losing your archive; read what they include on the enterprise servers page. The cartridges have no RAID card, so on those your nightly export is your only second copy. Either way, we do not sell a backup product: keeping a copy elsewhere is your job, and the steps below cover it.
Nobody meters the port, so uploading an existing library of scans, or pulling your full export home every night, never shows up on the invoice.
Up and running in an evening
- Install Ubuntu from the control panel, then Docker and its Compose plugin. Switch on the firewall with SSH allowed before you start anything.
- Your server arrives with a root login only, so make yourself a normal user with admin rights and use it for everything after this. The first lines of the commands below do it and hand your SSH key to the new user; if root signs in with a password instead, put your public key in the new user's
.ssh/authorized_keysyourself. Log in as the new user before you close the root session. - Make a folder and fetch three files from the project's GitHub: the PostgreSQL version of the compose file (save it as
docker-compose.yml), plus the two settings filesdocker-compose.envand.env. - Open
docker-compose.ymland edit the ports line so it reads"127.0.0.1:8000:8000". Docker opens published ports past the firewall on its own, on both IPv4 and IPv6; this line keeps the page reachable from the server itself and nowhere else. - Make a secret key with the command the docs give, open
docker-compose.envin nano, and replacechange-meafterPAPERLESS_SECRET_KEY=with the key. Paperless uses it to sign logins, so it has to be long, random and private. Save, then make the file readable only by you. - While the file is open, remove the # in front of
PAPERLESS_OCR_LANGUAGEandPAPERLESS_TIME_ZONE, then set the first to the language most of your papers are in (a 3-letter code such asdeu) and the second to where you live (such asEurope/Berlin). Typeid -uandid -g: if either answer is not 1000, also uncommentUSERMAP_UIDplusUSERMAP_GIDand fill in your own numbers, so Paperless can write into yourconsumeandexportfolders. - Start it. The first start takes a minute or two while the database is prepared.
# logged in as root, one time only:
adduser you && usermod -aG sudo you
install -d -m 700 -o you -g you /home/you/.ssh
install -m 600 -o you -g you /root/.ssh/authorized_keys /home/you/.ssh/
# now log in as you@your-server and run the rest
sudo ufw allow OpenSSH && sudo ufw enable
mkdir -p ~/paperless/consume ~/paperless/export && cd ~/paperless
U=https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose
curl -fsSL $U/docker-compose.postgres.yml -o docker-compose.yml
curl -fsSL $U/docker-compose.env -o docker-compose.env
curl -fsSL $U/.env -o .env
nano docker-compose.yml # ports: "127.0.0.1:8000:8000"
# prints a key on screen; paste it into the env file
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
nano docker-compose.env # PAPERLESS_SECRET_KEY=<the key>
chmod 600 docker-compose.env
sudo docker compose pull && sudo docker compose up -d
sudo ss -ltnp | grep 8000 # should show only 127.0.0.1:8000
Make your admin account where nobody else can see it
The very first visit to a new Paperless-ngx asks whoever arrives to create the superuser, the account that can read every document. That is why port 8000 is still private. From your own computer, start an SSH tunnel using the login you already use for the server, browse to the page through it, and create the account yourself.
# run on your laptop, not the server
ssh -N -L 8000:127.0.0.1:8000 you@your-server
# leave it open, then visit http://localhost:8000
# prefer the terminal? on the server, in ~/paperless:
sudo docker compose exec webserver createsuperuser
The docs suggest a second, ordinary account for everyday use, because a superuser sees everything. Add one under Users & Groups and switch on two-factor login under My Profile.
Getting paper in
The easy routes need nothing extra: drag files onto the web page, let Paperless check a mailbox you forward bills to, or copy files into ~/paperless/consume with scp or rsync. Anything in that folder is taken in and then removed from it, so it is an inbox, not a filing cabinet. Some scanners want to save straight to a network share; if yours does, put that share behind a VPN such as your own WireGuard server instead of opening it to the internet.
Keeping your archive safe for years
Paperless includes document_exporter, which writes every document, thumbnail and the full database contents into the export folder. Run it again and it only adds what changed, so a nightly copy to your laptop or a second server stays quick. Two rules from the docs: it must be told not to expect a terminal when run on a schedule (-T), and an export only goes back into a Paperless-ngx install of the exact same version, so write the version down with each copy.
# sudo crontab -e, then add (every night at 03:00):
0 3 * * * cd /home/you/paperless && docker compose exec -T webserver document_exporter ../export --no-progress-bar
# on your laptop or backup box:
rsync -a you@your-server:paperless/export/ ~/paperless-backup/
To update, read the release notes and take a fresh export. Then stop it with docker compose down, fetch the new image with docker compose pull, and start it again with docker compose up -d. When you want the archive reachable from anywhere, add a reverse proxy with HTTPS on ports 80 and 443, allow those in the firewall and set PAPERLESS_URL to your address, while 8000 stays private. After that Paperless only answers to that address and localhost, so keep using http://localhost:8000 through your tunnel.
When something smaller makes more sense
If it is just you, with a shoebox of papers and no plans to scan the back catalogue, a Cloud VPS can carry the same Docker setup for less. A whole server pays off when the archive is large, several people use it, or you want mirrored disks under it.
Questions people ask
- Do I really have to change the secret key?
- Yes. The docs call
PAPERLESS_SECRET_KEYrequired and say Paperless will not start if it is missing. The sample env file fills it withchange-meso things boot, which is exactly why you replace it: a known key would let others forge logins. - Can my family each have their own login?
- Yes. Paperless-ngx has users, groups and per-document permissions. By default a document is visible to its owner, and the owner can share it with other users or groups.
- Will it understand documents in my language?
- The Docker image comes with English, German, Italian, Spanish and French for OCR. Others can be added with
PAPERLESS_OCR_LANGUAGES, andPAPERLESS_OCR_LANGUAGEsets the one used by default. - Can I get my files back out if I stop using it?
- Yes. Originals are stored as plain files and never modified, and the exporter writes them out with readable names based on date, sender and title, plus the metadata in JSON.
- Does Paperless-ngx send my documents to an AI service?
- Not unless you ask it to. The optional AI features are off by default, and the built-in suggestions use a local model. If you switch the AI features on, the content goes to whichever backend you configure.