SSD Nodes Learn 8GB RAM — $66/taon
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-02

Paperless-ngx sa VPS: Self-Host ng mga Dokumento

Alamin ang tamang Docker Compose stack para sa Paperless-ngx, kasama ang Postgres, PAPERLESS_URL, consume folder, OCR languages, HTTPS, at backups.

Ano ang binubuo mo

Ginagawang searchable archive ng Paperless-ngx sa isang VPS ang isang folder ng mga na-scan na papel. Maglagay ng PDF sa mino-monitor na directory. Magpapatakbo ang server ng OCR (optical character recognition) dito, ie-extract ang text, tatantiyahin ang petsa at correspondent, at ia-archive ito. Isang Docker Compose file na may apat na service ang kailangan para sa pag-install. Pagkatapos nito, configuration na ang lahat. Mahaba ang bahaging ito ng guide dahil dito kadalasang nagkakaproblema ang mga installation.

Ang Paperless-ngx ay ang komunidad na pinapanatiling fork ng orihinal na Paperless project. Libre ito, self-hosted, at ini-store ang mga dokumento bilang plain files sa disk, kaya hindi ka mawawalan ng access sa sarili mong archive. Kapag pinatakbo ito sa VPS sa halip na sa home computer, maa-access ang mga scan mula kahit saan nang hindi nagbubukas ng port sa home router. Maayos din itong ipares sa isang private Nextcloud instance para sa mga file na hindi papel.

Ano talaga ang pinapatakbo ng stack

Nagsisimula ang opisyal na compose file ng apat na container. Kapag alam mo ang gawain ng bawat isa, mas madaling basahin ang mga log.

  • webserver: ang mismong paperless-ngx image. Pinapatakbo nito ang web interface, API, consumer na nagmo-monitor sa input folder, at mga Celery task worker na nagsasagawa ng OCR.
  • db: PostgreSQL. Dito nakalagay ang metadata, tag, correspondent, at mga table ng full-text search index. Hindi nito iniimbak ang iyong mga PDF.
  • broker: Valkey, isang Redis-compatible na key-value store. Ito ang task queue sa pagitan ng web process at mga worker.
  • gotenberg at tika: opsyonal lamang at ginagamit sa mga -tika compose variant. Kino-convert ng mga ito ang mga Office document (.docx, .xlsx, .odt) sa PDF upang ma-index ng paperless.

Noong July 2026, naka-pin ang docker.io/library/postgres:18 at docker.io/valkey/valkey:9-alpine sa postgres compose file, at kinukuha nito ang app mula sa ghcr.io/paperless-ngx/paperless-ngx:latest.

Mga Kinakailangan

  • Isang Ubuntu 24.04 KVM VPS na may sudo access, at may naka-install nang Docker at Compose plugin. Kung bago sa iyo ang bahaging iyon, magsimula sa mga pangunahing konsepto ng Docker Compose para sa VPS at bumalik dito.
  • Isang domain name na may A record na nakaturo sa VPS. Tumatanggi ang Paperless na mag-serve sa hostname na hindi pa nito nakikilala, kaya mas maaga itong kailangang i-configure kaysa sa inaasahan mo.
  • Ang memory ang pangunahing limitasyon. Maaaring sabay na manatili sa memory ang PostgreSQL, Valkey, gunicorn at isang Tesseract OCR worker sa loob ng 2 GB para sa magaan na paggamit. Maglaan ng 4 GB kung plano mong mag-import ng backlog na daan-daang scan, dahil ang OCR ng malaking multi-page PDF ang maaaring magdulot ng biglang pagtaas ng paggamit ng memory at pagpatay ng kernel out-of-memory killer sa isang worker.
  • Disk: dalawang beses naiimbak ang archive mo—ang orihinal na file at isang OCR'd archive PDF—kaya maglaan ng humigit-kumulang doble sa laki ng iyong mga scan.

Kunin ang opisyal na compose files

May interactive installer:

bash -c "$(curl --location --silent --show-error https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"

Nagtatanong ito at isinusulat ang mga file para sa iyo. Apat na command lang ang manu-manong paraan, at malalaman mo kung saan nakalagay ang lahat. Ito ang kailangan mo sa server na ikaw ang magpapanatili.

mkdir -p ~/paperless && cd ~/paperless
curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.postgres.yml
curl -fsSL -o docker-compose.env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.env
curl -fsSL -o .env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.env

Nasa parehong directory ang mga variant: docker-compose.sqlite.yml, docker-compose.mariadb.yml, at isang -tika version ng bawat isa. Piliin ang postgres para sa bagong install. Maayos ang SQLite para sa ilang daang dokumento, pero bumabagal ang full-text search index bago pa bumagal ang PostgreSQL.

May isang linya ang file na .env: COMPOSE_PROJECT_NAME=paperless. Ang pangalang ito ang nagiging prefix sa bawat container at volume. Huwag itong burahin at saka magtaka kung bakit hindi mahanap ng docker compose down -v ang iyong data.

I-configure ang docker-compose.env bago ang unang pagsisimula

Hindi optional ang dalawang setting. I-generate ang secret key gamit ang command na nakadokumento sa project:

python3 -c "import secrets; print(secrets.token_urlsafe(64))"

Pagkatapos, i-edit ang docker-compose.env:

PAPERLESS_SECRET_KEY=<the long string you just generated>
PAPERLESS_URL=https://paperless.example.com
PAPERLESS_TIME_ZONE=Europe/Berlin
PAPERLESS_OCR_LANGUAGE=deu+eng
USERMAP_UID=1000
USERMAP_GID=1000

Ang PAPERLESS_SECRET_KEY ay may literal na value na change-me kapag inilabas. Ginagamit nito ang key para pirmahan ang session cookies. Kapag iniwan ito, maaaring gumawa ng session ang sinumang nakaaalam ng default value. Itakda ito bago ang unang pagsisimula, dahil kapag binago ito sa ibang pagkakataon, ila-log out ang lahat ng user.

Ang PAPERLESS_URL ang setting na makapagliligtas ng isang oras. Django application ang Paperless, at bina-validate ng Django ang Host header ng bawat request. Itakda ang PAPERLESS_URL upang awtomatiko nitong punan ang ALLOWED_HOSTS, CORS_ALLOWED_HOSTS at CSRF_TRUSTED_ORIGINS. Kapag iniwan itong walang laman, nag-point ng domain sa server, at bawat page ay magbabalik ng Bad Request (400) na may DisallowedHost sa container log. Isulat ito nang walang trailing slash at walang path.

Itinatakda ng USERMAP_UID at USERMAP_GID ang user na gagamitin ng container. Itugma ang mga ito sa sarili mong account, na sinusuri gamit ang id -u at id -g. Kung hindi magtutugma ang mga ito, hindi mababasa ng consumer ang mga file na kinopya mo sa consume folder, at magpapakita ang log ng permission error sa halip na isang import.

Simulan ang stack at gumawa ng unang user

docker compose pull
docker compose up -d
docker compose run --rm webserver createsuperuser
docker compose logs -f webserver

Hinihingi ng createsuperuser ang username, email, at password. Walang default na login, kaya kapag nilaktawan ang hakbang na ito, mapupunta ka sa sign-in page na walang tatanggapin na login. Hintayin ang log line na nag-uulat na nakikinig ang server sa port 8000 bago gamitin ang browser. Sa unang pagsisimula, nagpapatakbo rin ito ng database migrations, na karaniwang tumatagal ng isa o dalawang minuto.

Suriin muna ito nang lokal bago gumamit ng domain:

curl -I http://127.0.0.1:8000

Ang 302 redirect sa /accounts/login/ ay nangangahulugang maayos ang stack.

Ilagay ang HTTPS sa harap nito

Ang stock compose file ay nagpa-publish ng 8000:8000, na nagba-bind sa lahat ng interface. Sa isang pampublikong VPS, inilalantad nito ang buong document archive mo sa plain HTTP sa sinumang makahanap ng address. Baguhin ang port line para loopback lang ang i-bind:

    ports:
      - "127.0.0.1:8000:8000"

I-terminate ang TLS (transport layer security) sa isang reverse proxy, pagkatapos ay i-forward sa 127.0.0.1:8000. Kung ito lang ang app sa server, sapat na ang anumang proxy na may ACME (automatic certificate management environment) client. Kung nagpapatakbo ka ng ilang container sa iisang certificate setup, sundin ang pattern ng Traefik reverse proxy para sa maraming Docker Compose app at i-attach ang webserver service sa proxy network nang walang published port.

Anumang proxy ang gamitin mo, dapat nitong ipadala ang X-Forwarded-Proto: https. Kung wala ito, iisipin ng Django na dumating ang request sa HTTP, mabibigo ang origin check sa login form, at makakakuha ka ng CSRF verification failed. Request aborted. sa page na mukhang tama. Ang kabilang bahagi ng fix na ito ay ang pagtatakda ng PAPERLESS_URL sa eksaktong https:// address na tina-type mo sa browser.

Itaas din ang upload size limit ng proxy. Ang 40 MB na scan sa proxy na naglilimita sa body sa 1 MB ay mare-reject bago pa ito makita ng paperless, at magpapakita ang browser ng generic na upload failure.

Paano gumagana ang consume directory

Ang compose file ay nagba-bind-mount ng ./consume mula sa compose directory papunta sa container. Anumang ilagay mo roon ay ini-import at pagkatapos ay binubura mula sa folder, dahil ang file ay nasa media volume na sa ilalim ng pamamahala ng paperless.

cp ~/scan-2026-07-14.pdf ~/paperless/consume/
docker compose logs -f webserver

Dapat mong makitang kinukuha ng consumer ang filename, nagpapatakbo ng OCR, at nagtatapos sa isang linyang nagsasabing naidagdag ang dokumento. Ilang segundo ang buong proseso para sa isang pahinang scan, ngunit maaaring umabot ng isang minuto o higit pa para sa mahabang dokumento.

Dalawang setting ang nagbabago kung paano hinahanap ang mga file. Ginagawa ng PAPERLESS_CONSUMER_RECURSIVE=true na maghanap ang paperless sa mga subfolder, at ginagawang tag ng PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=true ang pangalan ng bawat subfolder. Kaya kapag naglagay ka ng file sa consume/invoices/2026/, ita-tag ito bilang invoices at 2026. Ito ang pinakamurang filing system na maaari mong gawin.

Ang detection ang kabilang bahagi. Bilang default, ang PAPERLESS_CONSUMER_POLLING_INTERVAL ay 0. Ibig sabihin, gumagamit ang paperless ng mga kernel filesystem notification na agad na nagti-trigger. Hindi tumatawid ang mga notification na ito sa network filesystem. Kung ang consume folder mo ay isang NFS o SMB share na sinusulatan ng isang network scanner, walang made-detect kailanman. Ang solusyon ay itakda ang interval sa positibong bilang ng mga segundo upang sa halip ay i-scan ng paperless ang folder.

Mga wika ng OCR at ang gastos ng mga ito

PAPERLESS_OCR_LANGUAGE ay tumatanggap ng three-letter Tesseract code, eng bilang default. Pagsamahin ang mga wika gamit ang plus sign, gaya ng deu+eng. Susubukan ng Tesseract ang bawat isa at pananatilihin ang pinakamagandang resulta, kaya minumultiply ng bawat karagdagang wika ang CPU time na ginagamit sa bawat page. Sa isang VPS na may shared vCPU, ito ang pagkakaiba sa pagitan ng scan na natatapos sa ten seconds at scan na natatapos sa isang minuto. Ilista lamang ang mga wikang aktuwal na ginagamit sa mga dokumento mo.

Kasama sa image ang English, German, Italian, Spanish at French. Para sa iba pang wika, idagdag ang wika sa PAPERLESS_OCR_LANGUAGES bilang listahang pinaghihiwalay ng spaces, halimbawa PAPERLESS_OCR_LANGUAGES=tur ces, at mag-restart. Dina-download ng container ang Tesseract data packs sa startup, kaya mas mabagal ang unang boot pagkatapos ng pagbabagong iyon.

I-back up ang database at media

Ang pagkopya ng Docker volumes habang tumatakbo ang PostgreSQL ay lumilikha ng backup na maaaring hindi ma-restore. May sarili itong exporter ang Paperless, na nagsusulat ng mga dokumento at JSON manifest ng lahat ng metadata sa ./export bind mount:

docker compose exec webserver document_exporter ../export --delete --no-progress-bar

Inaalis ng --delete ang mga na-export na file na hindi na tumutugma sa kasalukuyang dokumento, kaya nananatiling mirror ang folder sa halip na patuloy na lumaki. Pinananatiling malinis ng --no-progress-bar ang output kapag pinapatakbo ito mula sa cron.

Ang pag-restore ay document_importer sa parehong folder sa isang bagong stack. Dahil dito, ang export directory lang ang kailangan mong panatilihing ligtas. Ipadala ito sa offsite ayon sa iskedyul gamit ang encrypted at deduplicated na restic backups mula sa iyong VPS, at patakbuhin muna ang export para hindi makuha ng restic ang archive na hindi pa tapos maisulat.

I-verify ang backup sa pamamagitan ng pag-check kung umiiral ang export/manifest.json at kung tugma ang bilang ng mga file sa bilang ng mga dokumento sa interface. Ang backup na hindi mo pa naililista ay hindi backup.

FAQ

Bakit nagbabalik ng “Bad Request (400)” ang bawat page matapos kong ituro rito ang domain ko?

Tinanggihan ng Django ang Host header dahil wala ang domain mo sa ALLOWED_HOSTS. Itakda ang PAPERLESS_URL=https://paperless.example.com sa docker-compose.env, nang walang trailing slash, pagkatapos patakbuhin ang docker compose up -d para muling malikha ang container. Walang epekto ang pag-edit lamang sa env file dahil ginagamit pa rin ng tumatakbong container ang environment na itinakda noong nagsimula ito.

Naglagay ako ng PDF sa consume folder pero walang nangyari. Ano ang mali?

Suriin muna ang docker compose logs webserver. Ibig sabihin ng permission error ay hindi tugma ang USERMAP_UID at USERMAP_GID sa account na may-ari ng file, kaya ayusin ang mga iyon at muling likhain ang container. Kung walang anumang log line, hindi dumating ang file event. Nangyayari ito sa network shares dahil hindi tumatawid sa mga ito ang kernel notifications. Itakda ang PAPERLESS_CONSUMER_POLLING_INTERVAL sa gaya ng 30, at sa halip ay isa-scan ng paperless ang folder bawat 30 segundo.

Maaari ko bang patakbuhin ang paperless-ngx gamit ang SQLite sa halip na PostgreSQL?

Oo, sinusuportahan ang docker-compose.sqlite.yml at mas kaunti ang memory na ginagamit nito, kaya angkop ito sa maliit na VPS. Makikita ang kapalit nito habang lumalaki ang archive: kapansin-pansing bumabagal ang full-text search at maramihang pag-edit ng tag kapag umabot sa libo-libo ang mga dokumento. Ang paglipat sa ibang database sa susunod ay nangangailangan ng export at import, kaya piliin na ngayon ang PostgreSQL kung inaasahan mong patuloy na lalaki ang archive.

Gaano karaming disk space ang aktuwal na kailangan ng archive ng mga scan?

Humigit-kumulang dalawang beses ng laki ng mga source file. Pinananatili ng Paperless ang orihinal na file at nag-iimbak ito ng pangalawang OCR'd PDF na may searchable text layer, pati maliliit na thumbnail. Mananatiling maliit ang 200 KB na text-only scan. Ang 30 MB na color scan ng mahabang kontrata ay kumokonsumo ng humigit-kumulang 60 MB. Idagdag ang export directory kung pananatilihin mo ito sa parehong disk, at magiging tatlong beses ang paggamit ng disk ng parehong archive.

Kailangan ko ba ang Tika at Gotenberg containers?

Kailangan lamang ang mga ito kung gusto mong ma-index ang mga Word, Excel o OpenDocument file kasama ng mga PDF mo. Kino-convert nila ang mga format na iyon sa PDF upang ma-OCR at ma-search ng paperless. Nagdaragdag din sila ng dalawa pang tumatakbong container at ilang daang megabytes ng memory, kaya laktawan ang mga ito sa maliit na server kung PDF o image na ang lahat ng bina-file mo.

#paperless-ngx#documents#self-hosting#docker#ocr