SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

HRConvert2を自分でホストしてファイルを変換する方法

HRConvert2を自分のVPSで動かし、顧客ファイルを無料変換サイトに送らず処理します。DockerまたはApacheの導入、bubblewrapのサンドボックス、アップロード制限、削除設定を解説します。

自分でファイル変換サーバーを運用する理由

自分で運用するファイル変換サーバーなら、ファイルを自分のディスク上に保持できます。これが運用する最大の理由です。無料の変換サイトでは、ファイルをアップロードした後にどう扱われたかを知る方法がありません。署名済みの顧客契約書やスキャンした診療記録の場合、アップロード自体がインシデントになります。HRConvert2 は、PHP で記述され、GPLv3 のライセンスで提供される、ドラッグアンドドロップ対応のファイル変換サーバーです。このガイドは、2026 年 8 月 18 日にリリースされた version 3.7.4 を基準にしています。その後もプロジェクトは速いペースで更新されています。2026 年 10 月 13 日時点の最新リリースは、2026 年 9 月 6 日に公開された v3.9.1 です。プロジェクトでは、488 の形式をサポートしているとしています。

データベース、アカウント、Cookie はありません。ユーザーごとに一時ディレクトリが作成されます。変換処理はすべて、ローカルのコマンドラインツールが実行します。文書には LibreOffice、音声と動画には FFmpeg、画像には ImageMagick、光学文字認識(OCR)には Tesseract を使用し、その他の形式には多数の小規模なツールを使用します。HRConvert2 は、アップロードページ、処理パイプライン、およびその周辺のクリーンアップ処理を担います。

ファイルを別の形式に変換します。ブラウザ上で使用するオフィススイートではありません。ブラウザのタブで複数のユーザーが文書を編集する用途であれば、自分で運用する OnlyOffice と Collabora を比較してください。また、ストレージでもありません。変換後の出力は削除することを前提としています。ファイルを保存する必要がある場合は、自分で運用するファイルマネージャーがその役割を担います。

必要なもの

Debian または Ubuntu、Apache 2.4、PHP 8 以降、そして bubblewrap が必要です。Bubblewrap(bwrap)はサンドボックスとして動作するため、必須です。サンドボックスを構築できないサーバーでは、サンドボックスなしで実行せず、変換を拒否します。upstream の README には Raspberry Pi Model B+ で十分とあります。これは PHP 部分については正しい説明です。実際に必要なハードウェアの性能は converter バイナリによって決まり、その詳細は後述します。

導入方法は 2 つあります。Docker image なら今夜から動かせます。Apache と PHP をインストールする方法は夕方から始める作業になりますが、サーバー上で実際に何が動作しているかを正確に確認できます。

Docker で今夜実行する

このイメージにはすべての変換バイナリが含まれるため、サイズが大きく、2026 年 8 月時点で約 3 GB あります。pull する前に空きディスク容量を確認してください。

ここではタグが重要です。このガイドでは v3.7.2 を固定しています。これは 2026 年 8 月 17 日時点で Docker Hub の最新タグであり、同日の最新 GitHub リリースでもありました。v3.7.4 は 8 月 18 日に続いてリリースされました。2026 年 10 月 13 日時点では、最新の GitHub リリースは v3.9.1(2026 年 9 月 6 日)です。最新の Docker Hub タグは edge(2026 年 9 月 22 日)と latest で、後者は v3.8.4(2026 年 8 月 31 日)です。latest タグの内容は変わるため、このアプリケーションは解析対象が広く、バージョンを固定したうえで意図的にアップグレードしてください。

docker pull zelon88/hrconvert2:v3.7.2
docker run -d --name hrconvert2 \
  -p 127.0.0.1:8080:80 \
  --security-opt seccomp=unconfined \
  zelon88/hrconvert2:v3.7.2
docker ps
curl -I http://127.0.0.1:8080/

正常なコンテナは Up 状態を維持し、curl は HTTP/1.1 200 OK を返します。コンテナが再起動を繰り返す場合は起動に問題があるため、ほかの変更を行う前に docker logs hrconvert2 を確認してください。

重要なフラグが 2 つあります。-p 127.0.0.1:8080:80 を指定すると、ポートは loopback でのみ公開されます。そのため、意図的にプロキシを前段に置くまで、変換サービスには外部から到達できません。プロジェクトの現在の例では -p 8080:80 を割り当てており、パブリック側を含むすべてのインターフェースで待ち受けます。--security-opt seccomp=unconfined が必要なのは、bubblewrap が user namespace と mount のシステムコールを使ってサンドボックスを構築し、Docker のデフォルト seccomp プロファイルがこれらをブロックするためです。3.7 の config.php のコメントには、一部のホストでは --security-opt apparmor=unconfined も必要だと記載されています。このフラグがないと変換に失敗し、アプリケーションが理由を表示します。A sandbox blocks the required syscalls unless it was started with the correct options.

このフラグには明確なトレードオフがあります。コンテナのシステムコールフィルターを緩和し、アプリケーションがコンテナ内部でより厳格なサンドボックスを構築できるようにします。動作を決める設定は、Resources/config.php 内の $RequireSandbox と $RequireSandboxOnDocker です。v3.7.4 のリリースでは、これらが TRUE と FALSE で提供されます。ここで固定している v3.7.2 タグでは、コメントに従って両方が FALSE です。コンテナでは $RequireSandbox を無効にし、$RequireSandboxOnDocker に判断させる必要があります。Docker の要件はデフォルトで無効なため、seccomp フラグを付けないコンテナではサンドボックスなしで変換できます。フラグを追加したうえで $RequireSandboxOnDocker = TRUE; を設定すると、コンテナ内部でも拒否動作に戻せます。

新しいイメージでは動作が異なります。プロジェクトは v3.8.0(2026 年 8 月 25 日)で Docker の処理を変更しました。現在の README と Docker Hub ページでは、seccomp オプションの代わりに --cap-add SYS_ADMIN を指定してコンテナを実行し、これがない場合は変換を拒否すると説明しています。3.8 または 3.9 のタグに固定先を変更する場合は、そのイメージのドキュメントに記載されたフラグを使用してください。この機能は広範な権限を持つため、127.0.0.1 のポートバインドを維持してください。

このマシンで Docker を初めて使用する場合は、先にデーモンを設定してください。VPS で Docker を実行する では、インストール、ストレージドライバー、Docker が独自のファイアウォールルールを書き込む方法を説明しています。

Apache と PHP にインストールする

v3.7.4 まで、リポジトリの Documentation/INSTALLATION_INSTRUCTIONS.txt では、これを 9 個の手順による手動インストールとして説明していました。このセクションも、その手順に従います。v3.8.0 以降、同じファイルではセットアップスクリプトを説明しています。クローンしたリポジトリで sudo bash Documentation/Build/hrconvert2-setup.sh を実行すると、依存関係をインストールし、php.ini を編集する代わりに PHP の設定を drop-in ファイルとして書き込み、bubblewrap 用に AppArmor プロファイルを拡張します。その後、php convertCore.php -v と --status で結果を確認します。手動の方法は時間がかかりますが、サーバーに何を配置したかを正確に把握できます。全体の構成は次のとおりです。まず Web サーバー、言語、サンドボックスを用意します。

sudo apt update
sudo apt install -y apache2 php libapache2-mod-php php-all-dev php8.3-zip php8.3-gd bubblewrap

php8.3-* の名前は Ubuntu 24.04 に対応しています。php -v を実行し、使用しているバージョンに合う prefix を指定してください。PHP のリリースごとにパッケージ名が変わるため、誤った名前を指定すると Unable to locate package になります。

次に、各種コンバーターをインストールします。これでドキュメント、画像、音声、動画、OCR に対応できます。実際に変換する対象の大部分をカバーします。

sudo apt install -y imagemagick ffmpeg libreoffice-common libreoffice-java-common \
  default-jre ghostscript poppler-utils libgxps-utils tesseract-ocr inkscape \
  xvfb clamav curl tar libxcb-cursor0

アーカイブ形式、3D モデル、電子書籍、起動可能な ISO イメージには、これより多くのパッケージが必要です。一部のパッケージは Ubuntu の multiverse コンポーネントに含まれています。v3.7.4 では、公式手順の Step 3 に完全な apt リストがあり、Step 5 にソースからのビルド手順がありました。現在のガイドにはパッケージリストがありません。インストーラーはマニフェスト Resources/Engine/Contract/depends.php を読み込み、php convertCore.php --setup --check-depends で現在のリストと状態を表示します。依存関係のうち 2 つは、ソースからビルドすることもできます。リポジトリには、パッケージ版の FFmpeg にないエンコーダー用の Documentation/Build/ffmpeg-build.sh と、ImageMagick 7 用の Documentation/Build/build-imagemagick-v7.sh が含まれています。Ubuntu 22.04 または 24.04 では、現在も ImageMagick の 6.9 ブランチがパッケージ化されています。Ubuntu 25.10 と 26.04 LTS では ImageMagick 7.1 がパッケージ化されています。電子書籍のサポートは calibre 独自のインストーラーで提供されます。3.7 の手順では、次の 1 行で実行していました。

sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdin

これは、ベンダーのスクリプトを root として shell にパイプする方法です。上流プロジェクトが案内する方法ですが、必須ではありません。省略すると、電子書籍の変換だけが利用できなくなります。

次に PHP の制限値を設定します。変換には時間がかかり、ファイルサイズも大きいため、標準値では小さすぎます。3.7 の手順では、これらを php.ini に設定していました。

max_execution_time = 1200
max_input_time = 90
memory_limit = 512M
post_max_size = 5000M
upload_max_filesize = 5000M
max_file_uploads = 100
display_errors = Off
zlib.output_compression = On

これらの値は、十分な余裕があるマシンを前提としています。小規模な VPS で使用する前に値を下げてください。upload_max_filesize = 5000M と max_file_uploads = 100 の組み合わせでは、1 回のリクエストで 40 GB のディスク容量を大幅に超えるデータを書き込めるためです。Apache を再起動し、PHP が実際に読み込んだ値を確認します。

sudo service apache2 restart
php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"

次に、作業ディレクトリを設定します。Resources/config.php 内の $ConvertLoc がそのディレクトリを指定し、デフォルト値は /DATA/HRConvert2 です。Web サーバーのユーザーを所有者にする必要があります。

sudo mkdir -p /DATA/HRConvert2
sudo chmod -R 0755 /DATA/HRConvert2
sudo chown -R www-data:www-data /DATA/HRConvert2

Apache のドキュメントルートにリリースを展開します。デフォルトの構成では HRProprietary/HRConvert2 フォルダーに配置します。Resources/config.php 内の $InstLoc には、実際に配置した場所を指定する必要があります。その後、組み込みの診断機能を実行します。ユーザーが問題に遭遇する前に、依存関係の不足を見つける最も早い方法です。

sudo php /path/to/HRConvert2/convertCore.php -v

-v は、インストール全体を確認します。コアのバージョン、依存関係、サンドボックスの状態、言語パックを検査します。コマンドラインからのファイル変換には対応していないため、この引数セットは管理用です。

新規の Ubuntu 24.04 インストールで、すべての変換が失敗するのはなぜですか?

サンドボックスが原因です。これは、初日に最も多く発生する問題です。Ubuntu 24.04 は、AppArmor により非特権ユーザー名前空間をデフォルトで制限します。Bubblewrap はサンドボックスを構築するためにユーザー名前空間を必要とするため、bwrap を起動できません。アプリケーションはサンドボックスなしの変換を拒否するため、すべてのジョブが失敗します。

次のコマンドで直接確認します。

bwrap --ro-bind / / --dev /dev /bin/true && echo sandbox ok

permission denied エラーが表示された場合、名前空間がブロックされています。bwrap バイナリ用の AppArmor プロファイルを設定すると解決できます。まず ABI ファイルを一覧表示し、存在する中で最も大きい番号を確認します。

ls /etc/apparmor.d/abi/

次に、4.0 をその最大番号に置き換えて /etc/apparmor.d/bwrap を作成します。

abi <abi/4.0>,
include <tunables/global>

profile bwrap /usr/bin/bwrap flags=(unconfined) {
  userns,
  include if exists <local/bwrap>
}

プロファイルを読み込みます。

sudo apparmor_parser -r /etc/apparmor.d/bwrap

出力がなければ、プロファイルは読み込まれています。もう一度 bwrap のチェックを実行すると、sandbox ok と表示されるはずです。以降は変換が動作します。

Debian 12 では、この問題は発生しません。カーネルが非特権ユーザー名前空間を許可しており、bubblewrap パッケージが起動時に kernel.unprivileged_userns_clone を 1 に設定するためです。そのため、Debian 12 ではプロファイルなしで上記のチェックに合格します。v3.8.0 以降では、セットアップスクリプトがディストリビューション標準の bubblewrap AppArmor プロファイルを自動的に拡張します。

公開コンバーターは、見知らぬ相手に公開されたパーサーです

この記事の残りは、この点を説明するためにあります。インターネットからアクセスできるファイルコンバーターは、匿名の利用者から任意のファイルを受け取り、それを LibreOffice、ImageMagick、FFmpeg、または Ghostscript に渡します。これらは、パーサーのバグが長年報告されている大規模な C および C++ コードベースです。アップロードする利用者が形式を選ぶため、実行されるパーサーと、その内部で通るコードパスも利用者が選ぶことになります。

HRConvert2 は、すべての依存関係を bubblewrap の namespace 内で実行します。各変換処理から見えるディレクトリは、入力を保持する読み取り専用でマウントされたディレクトリと、出力を受け取るディレクトリの 2 つです。ネットワークは共有されません。プロジェクトの表現では、closes every URL handler in every dependency at once ということです。この影響は、見た目以上に大きいものです。ImageMagick と Ghostscript は、URL を取得する参照をいずれも受け付けます。そのため、コンバーターが、ネットワーク内部からクラウドのメタデータエンドポイントへ到達するサーバーサイドリクエストフォージェリ(SSRF)ツールになる可能性があります。namespace 内にネットワークがなければ、その取得は実行できません。

拒否動作も、もう一つの重要な要素です。A server that cannot build a sandbox refuses the conversion rather than quietly running without one. ログを誰も確認しない状況で警告するだけのツールより、処理を安全側に停止するツールのほうが価値があります。そのため、前述の AppArmor の手順は任意ではありません。また、コンテナを公開する前に $RequireSandboxOnDocker も確認する必要があります。

policy.xml で ImageMagick を強化する

ImageMagick 自身の policy ファイルは、sandbox の下に追加する第 2 層です。設定する価値があります。ImageMagick 6 を使用する Ubuntu 24.04 では、ファイルは /etc/ImageMagick-6/policy.xml にあります。現在有効な設定を表示します。

identify -list policy

プロジェクトは Documentation/Build/policy.xml に policy を提供しており、よい見本になります。この policy は PS、PS2、PS3、EPS、XPS、MVG coder を拒否します。また、URL、HTTPS、HTTP、gs delegate も拒否し、PDF は許可します。

<policy domain="coder" rights="none" pattern="PS" />
<policy domain="coder" rights="none" pattern="MVG" />
<policy domain="delegate" rights="none" pattern="URL" />
<policy domain="delegate" rights="none" pattern="gs" />
<policy domain="coder" rights="read|write" pattern="PDF" />

重要なのは gs の行です。ImageMagick は PostScript を自ら解析しません。Ghostscript を外部プロセスとして実行します。既知の ImageMagick リモートコード実行の脆弱性は、ここにある delegate に存在します。この delegate を拒否すると、ファイルの内容が何を名乗っていても、ImageMagick はアップロードされたファイルを gs に渡しません。

同じ policy ではリソース上限も設定します。これにより、細工された 1 つの画像がマシンのリソースを使い果たすことを防ぎます。

<policy domain="resource" name="memory" value="256MiB"/>
<policy domain="resource" name="map" value="512MiB"/>
<policy domain="resource" name="disk" value="1GiB"/>
<policy domain="resource" name="width" value="16KP"/>
<policy domain="resource" name="height" value="16KP"/>
<policy domain="resource" name="area" value="128MP"/>

decompression bomb は、巨大な寸法を宣言する小さなファイルです。width、height、area の上限により、メモリ割り当てが発生する前に拒否されます。そのため、kernel が別のプロセスを強制終了する前に処理が終了します。

逆方向にも注意点があります。Ubuntu の標準 policy は PDF coder を完全に拒否します。そのため、変更していないシステムでは PDF 処理が attempt to perform an operation not allowed by the security policy 'PDF' で失敗します。この文字列は、policy が正しく機能していることを示します。coder を再び許可するかどうかは、意図的に判断してください。その場合でも、gs delegate は拒否したままにします。

小規模 VPS で依存関係が必要とするリソース

アイドル時には、これらの処理に大きなコストはかかりません。Apache と PHP は数十 MB 程度で、変換用バイナリはまったく実行されていません。コストが一度に発生するのは、ファイルが配置されたときです。

ドキュメント変換を開始すると LibreOffice が起動し、LibreOffice が Java ランタイムを起動します。画像変換では、上記のポリシーにより ImageMagick に 256 MiB のメモリと 512 MiB のメモリマップが割り当てられます。動画変換では、FFmpeg が利用可能なすべてのコアを使用します。動画を処理する FFmpeg の動作がそのようになっているためです。PHP 自体の memory_limit は、プロジェクトの設定で 512M です。これらの値は、オペレーティングシステムと Web サーバーに加えて、1 つのジョブ中に積み重なります。

そのため、1 GB の VPS は最初の本格的なドキュメント処理でスワップを使い始め、その後スラッシングが発生します。メモリが枯渇すると、カーネルの OOM killer は常駐メモリ使用量が最大のプロセスを終了します。通常は soffice.bin が対象になり、ユーザーには有用なメッセージがない変換失敗だけが表示されます。場合によっては apache2 が終了し、サイト全体が停止します。事後には dmesg -T | grep -i "killed process" で確認できます。

これはベンチマークではなく、サイジングの目安です。小規模なチームであれば、RAM 4 GB と 2 コアなら余裕があります。負荷がドキュメントと画像に限られ、待ち時間を許容できるなら、スワップファイルを設定した 2 GB でも動作します。スワップファイルによって変換が速くなるわけではありません。処理の急増を致命的な障害ではなく低速化として処理できるため、ページの停止とサービス停止の違いが生まれます。3 GB の画像、大きなアップロード上限、変換後の出力が合わさると、ほかのリソースが枯渇するより先にディスクを使い切ることがあります。そのため、必要だと思う容量よりもディスクに余裕を持たせてください。

変換は本質的にバースト的に発生します。2 人が同時に動画をアップロードすると、すべてのコアが使用され、次のリクエストはその処理が終わるまで待機します。この構成の前段にはジョブキューがないため、制御手段は制限だけです。

ディスクを 1 件のアップロードで使い切らせないための上限を設定する

まず PHP の値を引き下げます。共有の 4 GB サーバーでは、upload_max_filesize = 512M、post_max_size = 512M、max_file_uploads = 20 などが妥当な開始値です。max_execution_time = 1200 により 1 件の PHP リクエストを 20 分間実行できる点に注意してください。長時間の動画変換には実際に必要ですが、その分、遅いアップロード 1 件が worker を 20 分間占有します。

次に、リクエストが PHP に到達する前に、プロキシでサイズと速度を制限します。

limit_req_zone $binary_remote_addr zone=convert:10m rate=6r/m;

server {
    listen 443 ssl;
    server_name convert.example.com;

    client_max_body_size 512M;
    client_body_timeout 300s;

    location / {
        limit_req zone=convert burst=4 nodelay;
        proxy_pass http://127.0.0.1:8080;
        proxy_read_timeout 1200s;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

変換対象にする最大ファイル以上の値を client_max_body_size に設定する必要があります。そうしないと、nginx が 413 Request Entity Too Large を返し、PHP はアップロードを受け取りません。proxy_read_timeout は最長の変換時間を上回る値にする必要があります。そうしないと、プロキシの背後で正常に実行中のジョブでも、ブラウザーには 504 Gateway Time-out が返されます。TLS(transport layer security)の終端を含む server block の残りの設定については、nginx reverse proxy の設定を行ごとに解説で説明しています。

変換済みファイルを削除する

変換のたびに、Web サーバーが読み取れるディレクトリへ機密ファイルのコピーが残ります。クリーンアップを行うかどうかで、コンバーターと、誰かが変換したすべてのファイルを保存するアーカイブは分かれます。

$DeleteThreshold の Resources/config.php はセッションが期限切れになるまでの時間を分単位で指定し、デフォルトは 60 です。コンテンツが機密情報を含む場合は、15 に下げます。スイープ自体は core に渡すコマンドライン引数です。

sudo -u www-data php /path/to/HRConvert2/convertCore.php -c
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c=15

-c は、設定したしきい値に基づき、2 つのデータ保存場所から期限切れのセッションを削除します。-c=15 は、その実行時だけ 15 分を使用します。-c=now は経過時間に関係なくすべてのセッションを削除します。その時点でユーザーが変換中のセッションも含まれるため、メンテナンス時にだけ使用してください。同じ引数を docker exec 経由でコンテナ内でも使用できます。

誰かがページを読み込むことにクリーンアップが依存しないように、スイープをタイマーに登録します。/etc/cron.d/hrconvert2 に次の 1 行を追加すれば十分です。

*/10 * * * * www-data php /path/to/HRConvert2/convertCore.php -c

数分後に ls /DATA/HRConvert2 で確認し、古いセッションディレクトリが消えることを監視します。そのディレクトリの所有者は Web サーバーのユーザーです。したがって、パーサーを悪用された場合に攻撃者が取得するのも、まさにそのアカウントです。このアカウントには、価値のある他のリソースへの所有権を与えないでください。VPS の最小権限ユーザーアカウントが一般的な設計パターンであり、このケースでは特に重要です。

認証を前段に置く。公開が目的の場合を除く

デフォルトのインストールでは、設計上アカウントが作成されません。ページに到達できる人は誰でもファイルをアップロードし、変換用バイナリを実行できます。レート制限は処理を遅くするだけです。そのため、まず自分の状況を判断してください。

自分と数人の同僚だけが使う場合は、外部に公開しないでください。上記のようにコンテナを loopback に bind し、プライベートネットワークまたは SSH トンネル経由でアクセスします。これにより、public internet 上の誰もファイルを送信できなくなります。単にアクセスをフィルタリングするのではなく、攻撃対象領域全体をなくせます。同僚が、hostname を公開したりポートを開いたりせずにブラウザーで開く必要がある場合は、v3 onion service として提供することで、converter を loopback に bind したままアクセス先を提供できます。

ブラウザーから到達可能にする必要がある場合は、proxy の前段に認証を置いてください。Basic auth は2つのコマンドで設定でき、知らない相手を upload form から締め出せます。

sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd alice
location / {
    auth_basic "Converter";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://127.0.0.1:8080;
}

nginx を reload してページを開きます。認証プロンプトが表示されれば機能しています。プロンプトが表示されなければ、編集した location block がリクエストを処理していません。共有パスワードではなく実際のアカウントを使う場合は、single sign-on provider で認証を終端します。self-hosted Authentik SSO server を使えば、独自のログイン機能を持たないアプリケーションの前段で forward authentication を提供できます。

本当に公開された converter が目的であれば、その意味を受け入れて準備してください。sandbox が調査されることを前提にします。image tag を固定し、ImageMagick policy を厳格に保ち、upload limits を小さく設定し、重要なデータを保持していない VPS 上で実行してください。

失敗パターンと表示される文字列

すべての変換が直ちに失敗する。 サンドボックスを構築できません。通常の Ubuntu 24.04 のインストールでは、原因は AppArmor プロファイルです。固定された 3.7 Docker イメージでは、--security-opt seccomp=unconfined がありません。アプリケーションはその内容を示します。A sandbox blocks the required syscalls unless it was started with the correct options. と表示し、See --Require Sandbox-- & --Require Sandbox On Docker-- in config.php. を指します。

画像変換だけが失敗する。 Bubblewrap is missing or non functional, so this image conversion cannot be isolated! は、bwrap が存在しないか、Web サーバーのユーザーが使用する PATH から到達できないことを示します。

1 つの形式だけが失敗し、残りは動作する。 バイナリがない場合は、明確に次のように報告されます。ImageMagick may not be installed, or may not be reachable on the system path used by the web server user. FFmpeg と LibreOffice でも同じメッセージが表示されます。convertCore.php -v を実行して、インストールから検出できるものを確認してください。Apache worker の PATH は、ログインシェルの PATH とは異なる点にも注意してください。

PDF 処理がポリシーエラーで失敗する。 attempt to perform an operation not allowed by the security policy 'PDF' は HRConvert2 ではなく、ImageMagick の policy.xml によるものです。

大きなアップロードで 413 が返る。 nginx の client_max_body_size がファイルサイズより小さくなっています。この処理経路には、nginx に 1 つ、PHP に 2 つの合計 3 つの制限があり、最も小さい値が適用されます。

変換が停止し、明らかな変更もない。 The device where data is stored has an insufficient amount of storage space available. 空き容量を確認し、クリーンアップ処理が実際に実行されていることを確認してください。

ログにクリーンアップのエラーが記録される。 Could not clean the temporary location! と Could not clean the convert location! は所有権の問題です。Web サーバーのユーザーが、$ConvertLoc で指定されたディレクトリを所有している必要があります。

FAQ

自分でホストするファイル変換サービスをインターネットに公開しても安全ですか?

見知らぬ利用者に公開するパーサーとして扱う場合に限り、十分安全です。アップロードされたファイルはすべて LibreOffice、ImageMagick、FFmpeg、または Ghostscript に渡され、どのツールを使うかはアップロードした利用者が選択します。HRConvert2 は、ネットワーク接続を無効にし、入力ディレクトリを読み取り専用にした bubblewrap namespace 内でこれらのツールを実行します。また、sandbox 化できない変換は拒否します。これは安全性を重視した適切なデフォルト設定です。それでも、認証を必須にし、アップロードサイズの上限を小さく設定し、重要なデータをほかに保持していない VPS 上で実行することを推奨します。

新規にインストールした Ubuntu 24.04 で、すべての変換が失敗するのはなぜですか?

Ubuntu 24.04 は AppArmor により、権限のないユーザーによる user namespace の利用を制限しています。bubblewrap は sandbox の構築に user namespace を必要とします。アプリケーションは sandbox なしの変換を拒否するため、一部のジョブだけでなく、すべてのジョブが失敗します。/usr/bin/bwrap 用の AppArmor profile を flags=(unconfined) で作成し、sudo apparmor_parser -r /etc/apparmor.d/bwrap で読み込んでから、bwrap --ro-bind / / --dev /dev /bin/true で確認してください。Debian 12 では、権限のないユーザーによる user namespace の利用がデフォルトで許可されるため、この手順は必要ありません。

Docker では変換に失敗するのに、通常のインストールでは成功するのはなぜですか?

Docker のデフォルトの seccomp profile は、bubblewrap が使用する system call をブロックします。そのため、コンテナ内で sandbox を作成できません。ここで固定している 3.7 image では、--security-opt seccomp=unconfined を指定して起動してください。これは、その release の config.php comments で指定されている方法です。v3.8.0 以降、プロジェクトは代わりに --cap-add SYS_ADMIN を案内しています。$RequireSandboxOnDocker のデフォルト値は FALSE です。そのため、flag を指定していないコンテナでは、sandbox なしで変換される可能性があります。seccomp flag を設定したら、$RequireSandboxOnDocker を TRUE にしてください。

ファイル変換サーバーには、どの程度の RAM が必要ですか?

アイドル時の使用量は小さいですが、変換中は異なります。LibreOffice は Java runtime を起動します。ImageMagick は、提供される policy の下で 256 MiB のメモリと 512 MiB の map を使用します。さらに、PHP 自身の上限は 512M です。1 GB の VPS では、この組み合わせにより swap が発生し、out of memory killer が soffice.bin または apache2 を終了させます。小規模なチームで使用する場合は、4 GB の RAM と 2 cores を確保してください。変換がメッセージなしで終了した場合は、dmesg -T | grep -i "killed process" を確認してください。

変換済みファイルはどこに保存され、いつ削除されますか?

変換済みファイルは、Resources/config.php 内の $ConvertLoc で指定された作業ディレクトリに保存されます。デフォルトは /DATA/HRConvert2 です。$DeleteThreshold は session が期限切れになるまでの時間を分単位で指定し、デフォルトは 60 です。削除処理は command line から実行します。php convertCore.php -c は期限切れの session を削除し、-c=now は active な session を含め、すべての session を直ちに削除します。サイトへのアクセスに削除処理を依存させないよう、cron entry または systemd timer に -c を設定してください。