Pasang Paperless-ngx pada VPS dengan Docker Compose
Panduan Paperless-ngx pada VPS menggunakan Docker Compose, PostgreSQL, PAPERLESS_URL, folder consume, OCR, HTTPS dan sandaran untuk melindungi arkib anda.
Apa yang anda bina
Paperless-ngx pada VPS menukar folder yang mengandungi dokumen kertas yang diimbas menjadi arkib yang boleh dicari. Anda meletakkan fail PDF dalam direktori yang dipantau. Pelayan menjalankan OCR (pengecaman aksara optik) pada fail itu, mengekstrak teks, menganggarkan tarikh dan pihak pengutus, kemudian memfailkannya. Pemasangan ini menggunakan satu fail Docker Compose dengan empat perkhidmatan. Selepas itu, semuanya ialah konfigurasi. Panduan ini memberikan sebahagian besar tumpuan kepada konfigurasi kerana pemasangan sering gagal pada bahagian tersebut.
Paperless-ngx ialah fork komuniti yang diselenggarakan bagi projek Paperless asal. Perisian ini percuma, dihos sendiri, dan menyimpan dokumen anda sebagai fail biasa pada cakera. Oleh itu, anda tidak akan kehilangan akses kepada arkib anda sendiri. Menjalankannya pada VPS dan bukannya komputer di rumah membolehkan imbasan anda dicapai dari mana-mana sahaja tanpa membuka port pada penghala rumah. Ia juga sesuai digandingkan dengan instans Nextcloud persendirian untuk fail yang bukan dokumen kertas.
Perkara yang sebenarnya dijalankan oleh susunan ini
Fail compose rasmi memulakan empat bekas. Memahami fungsi setiap bekas memudahkan anda membaca log.
webserver: imej paperless-ngx itu sendiri. Ia menjalankan antara muka web, API, consumer yang memantau folder input anda, dan worker tugas Celery yang melaksanakan OCR.db: PostgreSQL. Ia menyimpan metadata, tag, koresponden, dan jadual indeks carian teks penuh. Ia tidak menyimpan fail PDF anda.broker: Valkey, iaitu stor nilai kunci yang serasi dengan Redis. Ia ialah baris gilir tugas antara proses web dengan worker.gotenbergdantika: pilihan, hanya dalam varian compose-tika. Ia menukar dokumen Office (.docx,.xlsx,.odt) kepada PDF supaya paperless dapat mengindeksnya.
Setakat July 2026, fail compose postgres menetapkan docker.io/library/postgres:18 dan docker.io/valkey/valkey:9-alpine, serta menarik aplikasi daripada ghcr.io/paperless-ngx/paperless-ngx:latest.
Prasyarat
- VPS KVM Ubuntu 24.04 dengan akses sudo, serta Docker dan pemalam Compose yang telah dipasang. Jika bahagian ini masih baharu bagi anda, mulakan dengan asas Docker Compose untuk VPS dan kembali ke sini.
- Nama domain dengan rekod A yang menunjuk ke VPS. Paperless enggan berkhidmat pada nama hos yang belum dikonfigurasikan untuknya, jadi perkara ini penting lebih awal daripada yang dijangka.
- Memori ialah kekangan utama. PostgreSQL, Valkey, gunicorn dan satu pekerja OCR Tesseract yang semuanya berjalan serentak boleh dimuatkan dalam 2 GB untuk penggunaan ringan. Sediakan 4 GB jika anda merancang untuk mengimport tunggakan ratusan imbasan, kerana OCR pada PDF berbilang halaman yang besar boleh menyebabkan lonjakan penggunaan memori dan pekerja dihentikan oleh pembunuh kehabisan memori kernel.
- Cakera: arkib anda disimpan dua kali, iaitu fail asal dan PDF arkib yang telah diproses dengan OCR. Oleh itu, peruntukkan kira-kira dua kali ganda saiz imbasan anda.
Dapatkan fail compose rasmi
Terdapat pemasang interaktif:
bash -c "$(curl --location --silent --show-error https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"Pemasang ini mengemukakan soalan dan menulis fail untuk anda. Jika dilakukan secara manual, prosesnya memerlukan empat arahan dan anda akan mengetahui lokasi setiap fail. Ini penting untuk pelayan yang akan anda selenggara.
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/.envVarian tersebut berada dalam direktori yang sama: docker-compose.sqlite.yml, docker-compose.mariadb.yml, dan versi -tika bagi setiap varian. Pilih postgres untuk pemasangan baharu. SQLite sesuai untuk beberapa ratus dokumen, tetapi indeks carian teks penuh menjadi perlahan jauh lebih awal berbanding PostgreSQL.
Fail .env mengandungi satu baris, COMPOSE_PROJECT_NAME=paperless. Nama itu menjadi awalan bagi setiap kontena dan volum. Oleh itu, jangan padamkannya kemudian tertanya-tanya mengapa docker compose down -v tidak dapat mencari data anda.
Konfigurasikan docker-compose.env sebelum permulaan pertama
Dua tetapan diperlukan. Jana kunci rahsia dengan perintah yang didokumenkan oleh projek:
python3 -c "import secrets; print(secrets.token_urlsafe(64))"Kemudian edit 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=1000PAPERLESS_SECRET_KEY dihantar dengan nilai literal change-me. Nilai ini menandatangani kuki sesi. Jika dibiarkan, sesi boleh dipalsukan oleh sesiapa yang mengetahui nilai lalai tersebut. Tetapkan nilai ini sebelum permulaan pertama, kerana perubahan selepas itu akan melog keluar semua pengguna.
PAPERLESS_URL ialah tetapan yang menjimatkan masa anda. Paperless ialah aplikasi Django, dan Django mengesahkan pengepala Host bagi setiap permintaan. Tetapkan PAPERLESS_URL dan Django akan mengisi ALLOWED_HOSTS, CORS_ALLOWED_HOSTS dan CSRF_TRUSTED_ORIGINS untuk anda. Jika dibiarkan kosong, kemudian domain diarahkan ke pelayan tersebut, setiap halaman akan mengembalikan Bad Request (400) dan log kontena akan memaparkan DisallowedHost. Tulis nilai ini tanpa garis condong di hujung dan tanpa laluan.
USERMAP_UID dan USERMAP_GID menetapkan pengguna yang digunakan oleh kontena. Padankan nilai tersebut dengan akaun anda sendiri, yang disemak menggunakan id -u dan id -g. Jika tidak sepadan, fail yang anda salin ke dalam folder consume tidak dapat dibaca oleh consumer, dan log akan memaparkan ralat kebenaran, bukannya melakukan import.
Mulakan tindanan dan cipta pengguna pertama
docker compose pull
docker compose up -d
docker compose run --rm webserver createsuperuser
docker compose logs -f webservercreatesuperuser menggesa anda memasukkan nama pengguna, e-mel dan kata laluan. Tiada log masuk lalai, jadi jika langkah ini dilangkau, anda akan melihat halaman log masuk yang tidak akan menerima sebarang maklumat. Tunggu baris log yang melaporkan bahawa server sedang mendengar pada port 8000 sebelum membuka pelayar. Permulaan pertama juga menjalankan migrasi pangkalan data, yang mengambil masa satu atau dua minit.
Semak secara setempat sebelum menggunakan domain:
curl -I http://127.0.0.1:8000302 yang mengubah hala ke /accounts/login/ bermakna tindanan berfungsi dengan baik.
Letakkan HTTPS di hadapannya
Fail compose standard menerbitkan 8000:8000, yang terikat pada semua antara muka. Pada VPS awam, tetapan ini mendedahkan seluruh arkib dokumen anda melalui HTTP biasa kepada sesiapa sahaja yang menemui alamat tersebut. Tukar baris port supaya hanya terikat pada loopback:
ports:
- "127.0.0.1:8000:8000"Kemudian tamatkan TLS (keselamatan lapisan pengangkutan) dalam proksi terbalik dan majukan trafik ke 127.0.0.1:8000. Jika ini satu-satunya aplikasi pada pelayan, mana-mana proksi dengan klien ACME (persekitaran pengurusan sijil automatik) boleh digunakan. Jika anda menjalankan beberapa bekas di sebalik satu persediaan sijil, ikut corak proksi terbalik Traefik untuk beberapa aplikasi Docker Compose dan sambungkan perkhidmatan webserver ke rangkaian proksi tanpa port yang diterbitkan.
Apa-apa proksi yang anda gunakan mesti menghantar X-Forwarded-Proto: https. Tanpa tetapan ini, Django menganggap permintaan itu tiba melalui HTTP, pemeriksaan asal pada borang log masuk gagal, dan anda menerima CSRF verification failed. Request aborted. pada halaman yang kelihatan betul. Bahagian lain pembaikan ini ialah menetapkan PAPERLESS_URL kepada alamat https:// tepat yang anda taip dalam pelayar.
Naikkan juga had saiz muat naik proksi. Imbasan berukuran 40 MB melalui proksi yang mengehadkan badan permintaan kepada 1 MB akan ditolak sebelum paperless menerimanya, dan pelayar akan melaporkan kegagalan muat naik umum.
Cara direktori consume berfungsi
Fail compose mengikat-mount ./consume daripada direktori compose ke dalam kontena. Apa-apa sahaja yang anda letakkan di situ akan diimport dan kemudian dipadam daripada folder tersebut, kerana fail itu kini disimpan dalam volum media di bawah pengurusan paperless.
cp ~/scan-2026-07-14.pdf ~/paperless/consume/
docker compose logs -f webserverAnda sepatutnya melihat consumer mengambil nama fail, menjalankan OCR dan selesai dengan baris yang melaporkan bahawa dokumen telah ditambahkan. Keseluruhan proses mengambil masa beberapa saat untuk imbasan satu halaman dan boleh mengambil masa seminit atau lebih untuk dokumen yang panjang.
Dua tetapan mengubah cara fail dicari. PAPERLESS_CONSUMER_RECURSIVE=true menyebabkan paperless mencari dalam subfolder, manakala PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=true menukar setiap nama subfolder menjadi tag. Oleh itu, fail yang diletakkan dalam consume/invoices/2026/ akan ditag dengan invoices dan 2026. Itulah sistem pemfailan paling murah yang boleh anda bina.
Pengesanan ialah bahagian yang satu lagi. Secara lalai, PAPERLESS_CONSUMER_POLLING_INTERVAL ialah 0, yang bermaksud paperless menggunakan pemberitahuan sistem fail kernel yang dicetuskan serta-merta. Pemberitahuan ini tidak merentasi sistem fail rangkaian. Jika folder consume anda ialah perkongsian NFS atau SMB supaya pengimbas rangkaian boleh menulis kepadanya, tiada apa-apa akan dikesan. Penyelesaiannya ialah menetapkan selang kepada bilangan saat yang positif supaya paperless mengimbas folder tersebut.
Bahasa OCR dan kosnya
PAPERLESS_OCR_LANGUAGE menerima kod Tesseract tiga huruf, eng secara lalai. Gabungkan bahasa dengan tanda tambah, seperti dalam deu+eng. Tesseract kemudian mencuba setiap bahasa dan mengekalkan hasil yang terbaik. Oleh itu, setiap bahasa tambahan menggandakan masa CPU yang digunakan untuk setiap halaman. Pada VPS dengan vCPU dikongsi, ini boleh menyebabkan imbasan yang biasanya selesai dalam sepuluh saat mengambil masa seminit. Senaraikan hanya bahasa yang digunakan dalam dokumen anda.
Imej tersebut disertakan dengan bahasa Inggeris, Jerman, Itali, Sepanyol dan Perancis. Untuk bahasa lain, tambahkan bahasa itu pada PAPERLESS_OCR_LANGUAGES sebagai senarai yang dipisahkan dengan ruang, contohnya PAPERLESS_OCR_LANGUAGES=tur ces, kemudian mulakan semula. Bekas memuat turun pek data Tesseract semasa dimulakan. Oleh itu, but pertama selepas perubahan itu akan mengambil masa lebih lama.
Sandarkan pangkalan data dan media
Menyalin volum Docker semasa PostgreSQL sedang berjalan menghasilkan sandaran yang mungkin tidak dapat dipulihkan. Paperless menyediakan pengeksportnya sendiri, yang menulis dokumen serta manifes JSON bagi semua metadata ke dalam lekap bind ./export:
docker compose exec webserver document_exporter ../export --delete --no-progress-bar--delete mengalih keluar fail yang dieksport tetapi tidak lagi sepadan dengan dokumen semasa, supaya folder itu kekal sebagai cermin dan tidak terus membesar. --no-progress-bar memastikan output kekal bersih apabila proses ini dijalankan melalui cron.
Pemulihan dilakukan dengan document_importer terhadap folder yang sama pada stack baharu. Oleh itu, direktori eksport ialah satu-satunya perkara yang perlu anda simpan dengan selamat. Hantar direktori itu ke lokasi luar tapak mengikut jadual menggunakan sandaran restic yang disulitkan dan dinyahduplikasi daripada VPS anda, dan jalankan eksport terlebih dahulu supaya restic tidak pernah menangkap arkib yang ditulis separa.
Sahkan sandaran dengan memeriksa kewujudan export/manifest.json dan memastikan kiraan fail sepadan dengan bilangan dokumen dalam antara muka. Sandaran yang tidak pernah anda senaraikan bukanlah sandaran.
FAQ
Mengapakah setiap halaman memulangkan "Bad Request (400)" selepas saya menghalakan domain saya kepadanya?
Django menolak pengepala Host kerana domain anda tiada dalam ALLOWED_HOSTS. Tetapkan PAPERLESS_URL=https://paperless.example.com dalam docker-compose.env tanpa garis condong di hujung, kemudian jalankan docker compose up -d untuk mencipta semula kontena. Mengedit fail env sahaja tidak mencukupi kerana kontena yang sedang berjalan mengekalkan persekitaran semasa ia dimulakan.
Saya meletakkan fail PDF dalam folder consume, tetapi tiada apa-apa berlaku. Apakah masalahnya?
Semak docker compose logs webserver terlebih dahulu. Ralat keizinan bermaksud USERMAP_UID dan USERMAP_GID tidak sepadan dengan akaun yang memiliki fail tersebut. Betulkan nilai itu dan cipta semula kontena. Jika tiada baris log langsung, peristiwa fail tidak pernah diterima. Keadaan ini berlaku pada perkongsian rangkaian kerana pemberitahuan kernel tidak merentasi perkongsian tersebut. Tetapkan PAPERLESS_CONSUMER_POLLING_INTERVAL kepada sesuatu seperti 30 supaya paperless mengimbas folder itu setiap 30 saat.
Bolehkah saya menjalankan paperless-ngx dengan SQLite dan bukannya PostgreSQL?
Ya, docker-compose.sqlite.yml disokong dan menggunakan kurang memori, maka ia sesuai untuk VPS kecil. Kekurangannya lebih ketara apabila arkib anda berkembang. Carian teks penuh dan pengeditan tag secara pukal menjadi jauh lebih perlahan apabila terdapat ribuan dokumen. Pemindahan kemudian memerlukan proses eksport dan import. Oleh itu, pilih PostgreSQL sekarang jika anda menjangka arkib terus berkembang.
Berapakah ruang cakera yang sebenarnya diperlukan oleh arkib imbasan?
Anggarkan kira-kira dua kali ganda saiz fail sumber anda. Paperless mengekalkan fail asal tanpa perubahan dan menyimpan PDF kedua yang diproses dengan OCR serta lapisan teks yang boleh dicari, di samping lakaran kecil. Imbasan teks sahaja berukuran 200 KB kekal kecil. Imbasan warna berukuran 30 MB bagi kontrak yang panjang memerlukan kira-kira 60 MB. Tambahkan direktori eksport jika anda menyimpannya pada cakera yang sama. Dalam keadaan itu, arkib yang sama menggunakan ruang cakera sebanyak tiga kali ganda.
Adakah saya memerlukan kontena Tika dan Gotenberg?
Hanya jika anda mahu fail Word, Excel atau OpenDocument diindeks bersama PDF. Kontena tersebut menukar format itu kepada PDF supaya paperless boleh menjalankan OCR dan mencarinya. Kontena tersebut juga menambah dua lagi kontena yang sedang berjalan dan penggunaan memori sebanyak beberapa ratus megabait. Oleh itu, jangan gunakannya pada sistem kecil jika semua fail yang anda arkibkan sudah berupa PDF atau imej.