SSD Nodes Learn RAM 8GB — $66/tahun
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-01

Cara Menjalankan Paperless-ngx di VPS dengan Docker

Pelajari cara menjalankan paperless-ngx di VPS memakai Docker Compose, termasuk stack Postgres resmi, PAPERLESS_URL, folder consume, OCR, HTTPS, dan pencadangan.

Yang Anda bangun

Paperless-ngx di VPS mengubah folder berisi dokumen hasil pemindaian menjadi arsip yang dapat ditelusuri. Anda cukup menaruh PDF ke direktori yang dipantau. Server kemudian menjalankan OCR (optical character recognition), mengekstrak teks, memperkirakan tanggal dan koresponden, lalu mengarsipkannya. Instalasinya menggunakan satu file Docker Compose dengan empat layanan. Setelah itu, semuanya berupa konfigurasi. Panduan ini membahas konfigurasi tersebut secara mendalam karena sebagian besar kegagalan instalasi terjadi pada tahap ini.

Paperless-ngx adalah fork komunitas yang masih dipelihara dari proyek Paperless asli. Perangkat lunak ini gratis, dapat di-host sendiri, dan menyimpan dokumen Anda sebagai file biasa di disk. Dengan demikian, Anda tidak pernah kehilangan akses ke arsip Anda sendiri. Menjalankannya di VPS, bukan di komputer rumah, membuat hasil pemindaian dapat diakses dari mana saja tanpa membuka port pada router rumah. Paperless-ngx juga cocok dipadukan dengan instance Nextcloud pribadi untuk file yang bukan dokumen kertas.

Komponen yang sebenarnya dijalankan stack

File compose resmi memulai empat container. Dengan mengetahui fungsi masing-masing, Anda dapat membaca log dengan lebih mudah.

  • webserver: image paperless-ngx itu sendiri. Komponen ini menjalankan antarmuka web, API, consumer yang memantau folder input, serta worker tugas Celery yang melakukan OCR.
  • db: PostgreSQL. Komponen ini menyimpan metadata, tag, koresponden, dan tabel indeks pencarian teks lengkap. Komponen ini tidak menyimpan PDF Anda.
  • broker: Valkey, penyimpanan key-value yang kompatibel dengan Redis. Komponen ini menjadi antrean tugas antara proses web dan worker.
  • gotenberg dan tika: opsional, hanya dalam varian compose -tika. Komponen ini mengonversi dokumen Office (.docx, .xlsx, .odt) menjadi PDF agar paperless dapat mengindeksnya.

Per Juli 2026, file compose postgres menetapkan docker.io/library/postgres:18 dan docker.io/valkey/valkey:9-alpine, serta mengambil aplikasi dari ghcr.io/paperless-ngx/paperless-ngx:latest.

Prasyarat

  • VPS KVM Ubuntu 24.04 dengan akses sudo, serta Docker dan plugin Compose yang sudah terpasang. Jika bagian ini masih baru bagi Anda, mulai dengan dasar-dasar Docker Compose untuk VPS, lalu kembali ke sini.
  • Nama domain dengan record A yang mengarah ke VPS. Paperless menolak melayani hostname yang belum dikonfigurasi untuknya. Karena itu, konfigurasi ini penting dilakukan lebih awal daripada yang mungkin Anda perkirakan.
  • Memori adalah batasan utama. PostgreSQL, Valkey, gunicorn, dan satu worker OCR Tesseract yang aktif secara bersamaan dapat berjalan dalam 2 GB untuk penggunaan ringan. Gunakan 4 GB jika Anda berencana mengimpor tumpukan ratusan hasil pemindaian. OCR pada PDF besar dengan banyak halaman dapat menyebabkan lonjakan penggunaan memori yang membuat kernel menghentikan worker melalui out-of-memory killer.
  • Disk: arsip Anda disimpan dua kali, yaitu file asli dan PDF arsip hasil OCR. Karena itu, siapkan kapasitas kira-kira dua kali ukuran hasil pemindaian Anda.

Dapatkan file compose resmi

Tersedia installer interaktif:

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

Installer tersebut mengajukan pertanyaan dan menulis file untuk Anda. Melakukannya secara manual hanya memerlukan empat perintah. Cara ini juga membuat Anda mengetahui lokasi semua komponen, yang penting untuk server yang akan Anda kelola.

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

Varian tersebut berada di direktori yang sama: docker-compose.sqlite.yml, docker-compose.mariadb.yml, dan versi -tika untuk masing-masing varian. Pilih postgres untuk instalasi baru. SQLite cukup untuk beberapa ratus dokumen, tetapi indeks pencarian teks lengkap menjadi lambat jauh sebelum PostgreSQL mengalaminya.

File .env berisi satu baris, COMPOSE_PROJECT_NAME=paperless. Nama tersebut menjadi awalan untuk setiap container dan volume. Jadi, jangan menghapusnya lalu bertanya-tanya mengapa docker compose down -v tidak dapat menemukan data Anda.

Konfigurasikan docker-compose.env sebelum memulai untuk pertama kali

Dua pengaturan wajib diisi. Buat secret key dengan perintah yang didokumentasikan oleh proyek:

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=1000

PAPERLESS_SECRET_KEY berisi nilai literal change-me secara default. Nilai ini menandatangani cookie sesi. Jika dibiarkan, siapa pun yang mengetahui nilai default tersebut dapat memalsukan sesi. Tetapkan nilainya sebelum memulai untuk pertama kali, karena perubahan setelah itu akan mengeluarkan semua pengguna dari sesi mereka.

PAPERLESS_URL adalah pengaturan yang paling menghemat waktu. Paperless adalah aplikasi Django, dan Django memvalidasi header Host pada setiap permintaan. Tetapkan PAPERLESS_URL, lalu Django akan mengisi ALLOWED_HOSTS, CORS_ALLOWED_HOSTS, dan CSRF_TRUSTED_ORIGINS secara otomatis. Jika dibiarkan kosong dan Anda mengarahkan domain ke server tersebut, setiap halaman akan mengembalikan Bad Request (400), sementara log container menampilkan DisallowedHost. Tulis nilainya tanpa garis miring di akhir dan tanpa path.

USERMAP_UID dan USERMAP_GID menentukan pengguna yang menjalankan container. Samakan nilainya dengan akun Anda, lalu periksa menggunakan id -u dan id -g. Jika nilainya tidak cocok, file yang Anda salin ke folder consume tidak dapat dibaca oleh consumer. Log akan menampilkan kesalahan izin, bukan proses impor.

Jalankan stack dan buat pengguna pertama

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

createsuperuser meminta nama pengguna, alamat email, dan kata sandi. Tidak ada login default, sehingga melewati langkah ini akan membawa Anda ke halaman masuk yang tidak akan menerima kredensial apa pun. Tunggu baris log yang melaporkan bahwa server sedang listening pada port 8000 sebelum mencoba mengaksesnya melalui browser. Saat pertama kali dijalankan, proses ini juga menjalankan migrasi database, yang memerlukan waktu satu atau dua menit.

Periksa secara lokal sebelum menghubungkan domain:

curl -I http://127.0.0.1:8000

Pengalihan 302 ke /accounts/login/ berarti stack berfungsi dengan baik.

Letakkan HTTPS di depannya

File compose bawaan memublikasikan 8000:8000, yang mengikat ke semua antarmuka. Pada VPS publik, konfigurasi ini menyajikan seluruh arsip dokumen Anda melalui HTTP biasa kepada siapa pun yang menemukan alamatnya. Ubah baris port agar hanya mengikat ke loopback:

    ports:
      - "127.0.0.1:8000:8000"

Kemudian, akhiri TLS (keamanan lapisan transport) di reverse proxy dan teruskan ke 127.0.0.1:8000. Jika ini satu-satunya aplikasi di server, proxy apa pun yang memiliki klien ACME (lingkungan pengelolaan sertifikat otomatis) dapat digunakan. Jika Anda menjalankan beberapa container di balik satu konfigurasi sertifikat, ikuti pola reverse proxy Traefik untuk beberapa aplikasi Docker Compose dan hubungkan layanan webserver ke jaringan proxy tanpa port yang dipublikasikan sama sekali.

Apa pun proxy yang Anda gunakan, proxy tersebut harus mengirim X-Forwarded-Proto: https. Tanpa header ini, Django menganggap permintaan datang melalui HTTP, pemeriksaan origin pada formulir login gagal, dan CSRF verification failed. Request aborted. muncul pada halaman yang terlihat benar. Bagian lain dari perbaikan ini adalah menetapkan PAPERLESS_URL ke alamat https:// yang sama persis dengan yang Anda ketik di browser.

Naikkan juga batas ukuran unggahan pada proxy. Pemindaian berukuran 40 MB yang melewati proxy dengan batas isi 1 MB akan ditolak sebelum paperless menerimanya, dan browser akan melaporkan kegagalan unggah umum.

Cara kerja direktori consume

File compose memasang-bind ./consume dari direktori compose ke dalam container. Apa pun yang Anda letakkan di sana akan diimpor lalu dihapus dari folder tersebut, karena file itu kini berada di volume media yang dikelola oleh paperless.

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

Anda akan melihat consumer mengambil nama file, menjalankan OCR, lalu selesai dengan baris yang melaporkan bahwa dokumen telah ditambahkan. Seluruh siklus ini berlangsung dalam hitungan detik untuk hasil pemindaian satu halaman dan dapat berlangsung satu menit atau lebih untuk dokumen yang panjang.

Dua pengaturan mengubah cara file ditemukan. PAPERLESS_CONSUMER_RECURSIVE=true membuat paperless mencari di subfolder, sedangkan PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=true mengubah setiap nama subfolder menjadi tag. Dengan demikian, file yang diletakkan di consume/invoices/2026/ akan diberi tag invoices dan 2026. Itulah sistem pengarsipan termurah yang dapat Anda buat.

Deteksi adalah bagian lainnya. Secara default, PAPERLESS_CONSUMER_POLLING_INTERVAL bernilai 0. Artinya, paperless menggunakan notifikasi filesystem dari kernel yang muncul segera. Notifikasi tersebut tidak melewati filesystem jaringan. Jika folder consume Anda adalah share NFS atau SMB yang digunakan scanner jaringan untuk menulis file, tidak ada file yang akan terdeteksi. Solusinya adalah menetapkan interval ke jumlah detik positif agar paperless memindai folder tersebut.

Bahasa OCR dan biayanya

PAPERLESS_OCR_LANGUAGE memerlukan kode Tesseract tiga huruf, yaitu eng secara default. Gabungkan beberapa bahasa dengan tanda tambah, seperti pada deu+eng. Tesseract kemudian mencoba setiap bahasa dan mempertahankan hasil terbaik. Karena itu, setiap bahasa tambahan meningkatkan waktu CPU yang digunakan untuk setiap halaman. Pada VPS dengan vCPU bersama, perbedaannya dapat berupa pemindaian yang selesai dalam sepuluh detik atau baru selesai dalam satu menit. Cantumkan hanya bahasa yang benar-benar digunakan dalam dokumen Anda.

Image ini menyertakan bahasa Inggris, Jerman, Italia, Spanyol, dan Prancis. Untuk bahasa lainnya, tambahkan bahasa tersebut ke PAPERLESS_OCR_LANGUAGES sebagai daftar yang dipisahkan spasi, misalnya PAPERLESS_OCR_LANGUAGES=tur ces, lalu mulai ulang. Container mengunduh paket data Tesseract saat startup, sehingga boot pertama setelah perubahan tersebut memerlukan waktu lebih lama.

Cadangkan basis data dan media

Menyalin volume Docker saat PostgreSQL sedang berjalan menghasilkan cadangan yang mungkin tidak dapat dipulihkan. Paperless menyediakan exporter sendiri, yang menulis dokumen dan manifes JSON berisi semua metadata ke dalam bind mount ./export:

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

--delete menghapus file hasil ekspor yang tidak lagi sesuai dengan dokumen saat ini, sehingga folder tetap menjadi cermin dan tidak terus membesar. --no-progress-bar menjaga keluaran tetap bersih saat perintah ini dijalankan dari cron.

Pemulihan dilakukan dengan document_importer terhadap folder yang sama pada stack baru. Artinya, direktori ekspor adalah satu-satunya hal yang harus Anda simpan dengan aman. Kirimkan direktori tersebut ke lokasi di luar server secara berkala menggunakan cadangan restic terenkripsi dan dideduplikasi dari VPS Anda, lalu jalankan ekspor terlebih dahulu agar restic tidak pernah menangkap arsip yang belum selesai ditulis.

Verifikasi cadangan dengan memeriksa keberadaan export/manifest.json dan memastikan jumlah file sesuai dengan jumlah dokumen di antarmuka. Cadangan yang belum pernah Anda tampilkan daftarnya bukan cadangan.

FAQ

Mengapa setiap halaman mengembalikan "Bad Request (400)" setelah saya mengarahkan domain ke sana?

Django menolak header Host karena domain Anda tidak tercantum dalam ALLOWED_HOSTS. Tetapkan PAPERLESS_URL=https://paperless.example.com di docker-compose.env, tanpa garis miring di akhir, lalu jalankan docker compose up -d untuk membuat ulang container. Mengedit file env saja tidak berpengaruh karena container yang sedang berjalan tetap menggunakan environment saat container tersebut dimulai.

Saya menaruh PDF di folder consume, tetapi tidak terjadi apa pun. Apa masalahnya?

Periksa docker compose logs webserver terlebih dahulu. Error izin berarti USERMAP_UID dan USERMAP_GID tidak cocok dengan akun pemilik file. Perbaiki keduanya, lalu buat ulang container. Jika tidak ada baris log sama sekali, berarti event file tidak pernah diterima. Hal ini terjadi pada network share karena notifikasi kernel tidak dapat melintasi network share. Tetapkan PAPERLESS_CONSUMER_POLLING_INTERVAL ke nilai seperti 30 agar paperless memindai folder setiap 30 detik.

Apakah paperless-ngx dapat dijalankan dengan SQLite, bukan PostgreSQL?

Ya, docker-compose.sqlite.yml didukung dan menggunakan lebih sedikit memori, sehingga sesuai untuk VPS kecil. Kekurangannya terlihat ketika arsip bertambah besar: pencarian teks lengkap dan pengeditan tag secara massal menjadi jauh lebih lambat saat jumlah dokumen mencapai ribuan. Migrasi nanti memerlukan export dan import. Jadi, pilih PostgreSQL sekarang jika Anda memperkirakan arsip akan terus bertambah.

Berapa kapasitas disk yang sebenarnya diperlukan untuk arsip hasil pemindaian?

Kira-kira dua kali ukuran file sumber. Paperless mempertahankan file asli tanpa perubahan dan menyimpan PDF kedua yang telah diproses dengan OCR serta memiliki lapisan teks yang dapat dicari, ditambah thumbnail berukuran kecil. Hasil pemindaian teks saja berukuran 200 KB tetap kecil. Hasil pemindaian berwarna berukuran 30 MB untuk kontrak panjang akan menggunakan sekitar 60 MB. Tambahkan direktori export jika direktori tersebut disimpan di disk yang sama. Dengan demikian, arsip yang sama akan menggunakan kapasitas disk tiga kali lipat.

Apakah saya memerlukan container Tika dan Gotenberg?

Hanya jika Anda ingin file Word, Excel, atau OpenDocument diindeks bersama PDF. Container tersebut mengonversi format itu menjadi PDF agar paperless dapat melakukan OCR dan mencarinya. Keduanya juga menambah dua container yang berjalan dan penggunaan memori beberapa ratus megabyte. Jadi, lewati container tersebut pada mesin kecil jika semua file yang Anda arsipkan sudah berupa PDF atau gambar.

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