Notes

Pi 4・5+Paperless-ngxで実用的な文書管理システムを作る

Raspberry Piも高くなりました。値上げと円安の影響で気軽に買えなくなりました。

もし古いPi 4の使い道に困っていたら、領収書や請求書などのPDFをOCRして書類管理に仕立ててはどうでしょう。

Zero2wやPi 3系ではスペック不足ですが、Pi 4かPi 5であれば充分な性能です。

私はPi 4が余っていなかったのでPi 5で構築しました。

paperless-13

検証環境
Model: Raspberry Pi 5 Model B Rev 1.0
MEM: 8GB
OS: Debian GNU/Linux 13 (trixie)
Kernel: 6.18.34+rpt-rpi-2712

Paperless-ngxとは?

Paperless-ngxは、紙をスキャンしたPDFや画像だけでなく、WordやExcelなどのOffice文書もテキスト抽出して一元管理できるオープンソースの文書管理システムです。

サーバーを自宅や社内に構築して運用できるため、文書をクラウドへ預けることなくローカル環境だけで完結することも大きな特長です。

プライバシーの観点からも安心ですね。

Webブラウザから検索・閲覧ができるのも利便性が高いと思います。

公式:https://docs.paperless-ngx.com/

github:https://github.com/paperless-ngx/paperless-ngx/tree/main

主な対応形式

・PDF(OCR対応)
・JPEG / PNG / TIFF(OCR対応)
・Word(.doc / .docx)
・Excel(.xls / .xlsx)
・PowerPoint(.ppt / .pptx)
・OpenDocument(.odt / .ods / .odp)
・テキスト(.txt)
・HTML
・メール(.eml)

この内、PDFとWord、Eccelを実際に取り込んで確認しました。 実用的ですよ。

おすすめのセットアップ方法

paperless-1

OSとして、通常のRaspberry Pi OSではなく、GUIのないliteが最適です。 Paperless-ngxで扱うファイルは、別のNASへ保存すると良いでしょう。ファイルサイズが大きくなるのと、操作はこれまた別のマシン(私はMac)なので、ファイルをPi 4や5の領域で直接扱うのは余計な設定が必要だからです。

  • Raspberry Pi 4または5
  • Raspberry Pi OS Lite 最新
  • microSD 32GB
  • Docker導入
  • 外部NASにデータ保存
  • SMB自動マウント
  • bind mountの確認
  • 公式compose.ymlを配置

OCRを実行するのも管理するのも、ディスクへ細かなアクセスが発生しますので、本来はSSDドライブ起動が望ましいです。 今回は利便性を優先してmicroSD起動で済ませました。 データはNASへ置くことにするので、容量は32GBでも足ります。

NASと連携させる

最初にRaspberry Piが単体で外部のNASを問題なくマウントできるところまで進めます。 実際にPaperless-ngxをDockerでインストールするのはまだ先です。 docker-compose.yamlにNASの領域をバインドマウントしたいからです。

このとき、Paperless-ngxで使うフォルダ名をそのままNASで作成します。

folder-means

paperless-2

NASの任意の場所へ手動でフォルダ作成します。 例えばpaperlessというフォルダの中に必要な3つを配置します。

paperless
├── consume
├── export
└── media

マウントするのは、この親であるpaperlessだけで済みます。

Raspberry Pi側でpaperlessフォルダを作り、これをマウントポイントとします。

sudo mkdir -p /mnt/paperless

mountコマンドを使い、最初は手動でマウントします。

sudo mount -t cifs //192.168.0.10/paperless /mnt/paperless \
-o username=xxxx,password=xxxx,uid=1000,gid=1000

NASのIPアドレスと作成したpaperlessまでのパス、NASへ接続するユーザー名とパスワードをそのまま入力します。 uidとgidは、インストールしたばかりならデフォルトで1000です。これは後ほどもこの1000で合わせて設定します。 分からなければid $USERコマンド。

fstabに追記して、次回から自動でマウントできるようにしておきます。

sudo nano /etc/fstab

//192.168.0.10/paperless  /mnt/paperless  cifs  username=xxxx,password=xxxx,uid=1000,gid=1000,_netdev,nofail,x-systemd.automount  0  0

オプション解説:

fstab-options

もしもパスワードを平文で残したくないなら、credentials=/root/.smbcredentialsに変え、新規作成した.smbcredentialsにusernameとpasswordを書きます。 更に権限をsudo chmod 600 /root/.smbcredentialsとすれば安心です。

username=xxxx
password=xxxxxxxx

自分しか使わないですし、外部に公開することもないので、私はいつも平文でfstabに書いています。

fstabに追記した後、sudo mount -aと実行後、一度再起動して自動マウントできているのか確認します。

Dockerのインストール

DockerでPaperless-ngxをインストールして構築します。 先にls /mnt/paperlessで自動マウントできているのか確認してから、実際にdocker-compose.ymlでバインドマウントさせます。

Docker自体のインストールは、過去に書いた記事を少し修正してありますので参考にしてください。

Raspberry Pi 4でDockerのインストール方法 2026年

Dockerのバージョン:

docker -v
Docker version 29.6.2, build dfc4efb

docker compose version
Docker Compose version v5.3.1

Paperless-ngxをymlで構築

公式が推奨している方法があります。

  • 自分のデータベースに合った docker-compose.*.ymlをダウンロードし、docker-compose.yml にリネーム
  • docker-compose.env.envも同じディレクトリへ配置
  • 自分の環境で必要な箇所だけ変更

本記事では保存先だけをNASに合わせて変更します。

なお、新規インストールではPostgreSQL版が推奨されています。

今回はhttps://github.com/paperless-ngx/paperless-ngx/tree/main/docker/composeにあるdocker-compose.postgres-tika.ymlを使いました。

WordやExcelの文書も使いたいなら、Apache Tika(Office文書などのテキスト抽出)とGotenberg(Office文書をPDFへ変換)が必要だからです。

Docker Compose v2推奨名「docker-compose.yml」にリネームしてダウンロードしておきます。

cd ~/paperless-ngx
wget -O docker-compose.yml https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.postgres-tika.yml

同じく、docker-compose.envと.envもダウンロードしておきます。

wget https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.env
wget https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.env

同じフォルダに3つのファイルを配置すればOKです。

── paperless-ngx
   ├── docker-compose.env
   ├── docker-compose.yml
   └── .env

docker-compose.ymlの編集

ダウンロードしたymlの中で変更するのは、webserver:volumesと、最後のvolumesmediaを外すだけです。 バインドマウント先はそれぞれ/mnt/paperlessにします。

    volumes:
      - data:/usr/src/paperless/data
      - /mnt/paperless/media:/usr/src/paperless/media
      - /mnt/paperless/export:/usr/src/paperless/export
      - /mnt/paperless/consume:/usr/src/paperless/consume

mediaはNASへ保存するために外した。

volumes:
  data:
  dbdata:
  redisdata:

/usr/src/paperless/dataはそのままでOKでしょう。 中身はインデックスや各種内部データなので、直接ユーザーが利用することはないからです。

日本語の設定

WebUIはシステム言語を使用してくれるため、日本語表示になります。 しかし、OCRの読み込みは言語設定しないとなりません。

設定はdocker-compose.env に以下を最下段に追加するだけです。

PAPERLESS_OCR_LANGUAGE=jpn
PAPERLESS_OCR_LANGUAGES=jpn

確認はdockr起動後、以下コマンドの結果通り、jpnが追加されているかで確認できます。 upで起動した後に一度確認しておくと良いでしょう。

docker compose exec webserver tesseract --list-langs
List of available languages in "/usr/share/tesseract-ocr/5/tessdata/" (7):
deu
eng
fra
ita
jpn
osd
spa

dockerで起動

準備ができたら、dockerのコマンドで実行するだけです。pullした後にupです。

docker compose pull
docker compose up -d

※pull実行の途中でDNSタイムアウトした場合、名前解決が正常ならDockerを再起動(sudo systemctl restart docker)して再実行します。

操作はWebブラウザのみ

WebUIですべて操作できます。

http://ラズベリーパイのIPアドレス:8000

paperless-3

初回だけユーザーアカウントを作成します。 ここで設定するのはスーパーユーザー権限なので、複数人で使いたい場合は、ログインした後にユーザーを個別に作成してください。 私のように個人で利用するだけなら、最初に作成したユーザーで使い続けても良いと思います。

文書ファイルの取り込み

文書を取り込むのも簡単です。 ダッシュボード右上にある”ドキュメントのアップロード”をクリックしてファイルを選ぶか、そこにファイルをドラッグ&ドロップするだけです。

paperless-4

右下に進捗バーが表示され、ファイルサイズによりますが数秒で取りこめます。

paperless-6

取り込まれたら、クリックして開いて確認できます。

paperless-7

ログで確認

早速、厚生労働省が発行したPDFで、ファイル名を「高額介護サービス費44400yen.pdf」としたものを取り込ませました。

paperless-8

その時のログは、OCRができないメタデータに警告が出ていますが、それはその通りのことだからOKです。 インデックス化もされ、成功したとあります。

メニュー項目にあるログ:

[2026-07-18 02:49:26,386] [WARNING] [ocrmypdf._validation] The output file size is 1.62× larger than the input file.
Possible reasons for this include:
--deskew was issued, causing transcoding.
PDF/A conversion was enabled. (Try `--output-type pdf`.)
[2026-07-18 02:49:26,389] [DEBUG] [paperless.parsing.tesseract] Using text from sidecar file
[2026-07-18 02:49:26,389] [DEBUG] [paperless.consumer] Generating thumbnail for 高額介護サービス費44400yen.pdf...
[2026-07-18 02:49:26,393] [DEBUG] [paperless.parsing] Execute: convert -density 300 -scale 500x5000> -alpha remove -strip -auto-orient -define pdf:use-cropbox=true /tmp/paperless/paperless-_r3b61fw/archive.pdf[0] /tmp/paperless/paperless-_r3b61fw/convert.webp
[2026-07-18 02:49:28,453] [INFO] [paperless.parsing] convert exited 0
[2026-07-18 02:49:28,458] [DEBUG] [paperless.classifier] Document classification model does not exist (yet), not performing automatic matching.
[2026-07-18 02:49:28,461] [DEBUG] [paperless.consumer] Saving record to database
[2026-07-18 02:49:28,461] [DEBUG] [paperless.consumer] Creation date from st_mtime: 2026-07-18 02:48:57+00:00
[2026-07-18 02:49:28,559] [DEBUG] [paperless.index] Index updated for document 1.
[2026-07-18 02:49:28,771] [DEBUG] [paperless.consumer] Deleting original file /tmp/paperless/tmp1qz7rhz2/高額介護サービス費44400yen.pdf
[2026-07-18 02:49:28,772] [DEBUG] [paperless.consumer] Deleting working copy /tmp/paperless/paperless-ngxzmb_nuyk/高額介護サービス費44400yen.pdf
[2026-07-18 02:49:28,779] [DEBUG] [paperless.parsing.tesseract] Deleting directory /tmp/paperless/paperless-_r3b61fw
[2026-07-18 02:49:28,779] [INFO] [paperless.consumer] Document 2026-07-18 高額介護サービス費44400yen consumption finished
[2026-07-18 02:49:28,784] [INFO] [paperless.tasks] ConsumeTaskPlugin completed with: Success. New document id 1 created
[2026-07-18 02:49:55,612] [DEBUG] [paperless.classifier] Document classification model does not exist (yet), not performing automatic matching.
[2026-07-18 02:49:55,897] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/illustrator/1.0/}StartupProfile: Basic CMYK. Error: 'http://ns.adobe.com/illustrator/1.0/'
[2026-07-18 02:49:55,898] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/illustrator/1.0/}CreatorSubTool: Adobe Illustrator. Error: 'http://ns.adobe.com/illustrator/1.0/'
[2026-07-18 02:49:55,898] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/xap/1.0/t/pg/}NPages: 1. Error: 'http://ns.adobe.com/xap/1.0/t/pg/'
[2026-07-18 02:49:55,898] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/xap/1.0/t/pg/}HasVisibleTransparency: True. Error: 'http://ns.adobe.com/xap/1.0/t/pg/'
[2026-07-18 02:49:55,899] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/xap/1.0/t/pg/}HasVisibleOverprint: False. Error: 'http://ns.adobe.com/xap/1.0/t/pg/'
[2026-07-18 02:49:55,899] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/xap/1.0/t/pg/}MaxPageSize: . Error: 'http://ns.adobe.com/xap/1.0/t/pg/'
[2026-07-18 02:49:55,899] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/xap/1.0/t/pg/}PlateNames: Cyan Magenta Yellow Black. Error: 'http://ns.adobe.com/xap/1.0/t/pg/'
[2026-07-18 02:49:55,900] [WARNING] [paperless.parsing.tesseract] Error while reading metadata {http://ns.adobe.com/xap/1.0/t/pg/}SwatchGroups:
                  . Error: 'http://ns.adobe.com/xap/1.0/t/pg/'
[2026-07-18 02:51:12,833] [DEBUG] [paperless.classifier] Document classification model does not exist (yet), not performing automatic matching.

OCRされた内容を確認

結論から言うと、文書中でしか使われていない言葉で検索してみたらちゃんとヒットしました。成功です。

OCRされたメタデータの内容を見ると、およそ問題ないレベルです。 元のPDFがイラスト調になっている部分は認識が難しいものの、文章はほとんどは読み込めている結果でした。

この中の文字を検索で拾えれば文書管理としては問題ありません。

OCRされた文章(クリックで開く)
ここ 利用分/がら
医サビバ費(の

加

暫家度紀の見直 (され4ま19』

〇介護サービスを利用された際は、自己負担割合に応じた利用料を負担していただいております。

高額介護サービス費とは、 1ヵ月に支払った利用者負担の合計が負担限度額を超えたときは、

超えた分が払い戻される制度です。一般的な所得の方の負担限度額は月額 44.400 円です。
令和3年8月からは、負担能力に応じた負担を図る観点から、一定年収以上の高所得者世帯に

ついて、人負担限度額の見直しを行います。

どのような改正がおこなわれるのですか?

し] 医 医療保険制度の高額療養費制度に合わせ、8月1日以降に利用されたサービス分より一定年収以上の

高所得者の負担限度額を以下のとおり見直します。

区 分

課税所得 690 万円 (年収約 1.160 万円) 以上

課税所得 380 万円 (年収約 770 万円) ~ 課税所得 690 万円
(年収約 1.160 万円) 未満

時 ※

市町村民税課税一課税所得 380 万円 (年収約 770 万円) 未満
世帯の全員が市町村民税非課税

前年の公的年金等収入金額オすその他の合計所得金額
合計が 80 万円以下の方等

生活保護を受給している方等

見直しの対象となるケースは、どのような場合ですか?
し| 介護

がいる場合が対象となります。

負担の上限額(月額)

140,

93,

44.
24.

24,
15,

15,

100円 (世帯)

000円 (世帯)

400円 (世帯)
600円 (世帯)

600円 (世帯)
000円 (個人)

000円 (世帯)

サービスの利用者又は同一世帯に課税所得 380 万円 (年収約 770 万円) 以上の 65 歳以上の万

医療費・介護サービス費ともに高額で、高客介護合算療養費制度 (年間の医療費・介護サービス費

が負担限度額を超えた場合に払戻しを行う制度) により医療費・介護サービス費の払い戻しを受け

ています。 今回の見直しで負担が増えることはありませんか?

し] 高額介護合算療養費制度等の支給要件や負担上限額に変更はないため、収入や医療・介護

等が同じであれば、実邊的な負担はこれまでこと同額こなります。

(厚生働省

サービス費

印刷された請求書PDF

次はiPhoneのカメラで撮影したPDFを読み込ませてみました。 iPhoneだとドキュメントの撮影モードがあります。

こちらは請求書です。個人情報は私がモザイクをかけています。

paperless-10

こちらも日付だったり、請求者名や病院といった言葉から、請求書として検索が可能になりました。 先ほど同様に、色とか罫線といった部分が多いと上手く読み込めないものの、文章の部分などは認識精度が高いです。

手書きの領収書PDF

更に手書きの領収書もiPhoneで撮影してPDFにして試しました。 古書店で購入した際の領収書です。

paperless-12

これが精度は一番悪かった。 なんとか読み取り内容に店名があり、ファイル名に金額も入れたので検索できそうです。これで問題ないと判断します。

OCRされた内容も変更できますが、メモも保存できるのでスキャンされた以外のことも追記できます。

paperless-11

メモを活用すれば、大抵は回避できると思いました。

Excel文書

次はPDFではなく、Excelのxlsx形式のファイルです。

Excelで作成した文章は完璧ですね。 グラフのタイトルまでちゃんと読み取れています。

paperless-14

Word文書

Wordのdoc形式にも試します。 LibreOfficeなどのods形式にも対応しています。

paperless-15

このようにWord文書も完璧でした。 これなら何で検索してもきちんとヒットするでしょう。

検索して絞り込めるかが大事

実用する際、たくさんあるPDFの書類から目的の書類が探せれば用は済むので、検索してヒットすればあとは中身を開けば良いと思います。

どうしてもOCRの認識精度に目が行きがちですが、別に完璧ではなくても良い運用です。 実際、OCRとしてはそれなりに拾っていますから、自分でキーワードやメモを付ける必要もなく絞り込めると思います。

あくまでも絞り込んで該当する文書が見つかればそれでヨシという実用度は満たしていると思いました。

macOSとの違い

macOSには標準でSpotlightがありOCRは実行されています。初回はかなり時間がかかるのですが、裏でずっと動いている感じです。

今だと、Apple IntelligenceもM4 Macでは使えますから、今回のPaperless-ngxと同等のことが可能です。 恐らく今後は、Siriも連携して「去年の介護保険の書類を探して」と話しかければ済むことになるでしょう。

では、Paperless-ngxが要らないかというと、そうでもありません。

シンプルな文書管理であるPaperless-ngxは、macOSのSpotlightとは違い、発信元、タグ、ドキュメントタイプ、日付、カスタムといった項目で管理できます。 何よりも自分が登録した文書ファイルだけをWeb UIで一元管理できるのはシンプルに思えます。 元ファイルのPDFなども保存場所が1ヶ所になるため分かりやすい。

保存場所をNASにしたので、別のPCやiPhoneから使えるうえ、Macの電源ONは関係ないのが便利です。 省電力であるRaspberry Pi を電源1つで放置できるのも気楽です。

個人や小さな組織でも実用的

使ってみて実感するのは、かなり実用的な動作です。

Web UIで一元管理できるため、Webブラウザだけで事足ります。 今回のようにNASへ保存するように連携すれば、複数のPCやスマホからでも閲覧できるからです。

更にPDFだけではなく、Wordで作成した議事録.docx、Excelで作成した備品一覧.xlsx、PowerPointで作成した研修資料.pptxなど、Office文書も扱えるため会社組織でも有効です。 管理者と閲覧ユーザーなど、権限の変更ができる点も複数人いる会社組織では重宝します。

私は個人利用なので管理者アカウント1つで運用しています。

今後に運用していく課題

手元にざっと1万以上のPDFファイルがあります。これを少しずつ保存していきたい。 ファイルの選別も同時にできるので良い機会だなと思います。かなり面倒ではありますが。

登録していく中で、少し課題が残っています。

  • タグをどう付けるか
  • ドキュメントタイプをどう分けるか
  • 発信元とされている項目を登録するか
  • カスタム項目をどう使うか
  • PostgreSQLのバックアップ方法

データベースにOCRのテキストなどが含まれるため、バックアップは仕組み化しておきたいですね。 データベースのバックアップ方法は別記事で紹介していこうと思います。