
rootless Podman コンテナ内で Firefox を実行し、capabilities を削除してネットワークを分離、一時ストレージを使用することで、サンドボックスエスケープを封じ込め、ホストの侵害を防ぎます。
ルートレスPodmanコンテナでFirefoxを実行し、セキュリティを分離します。ブラウザはほぼすべてのLinuxケーパビリティを持たず、独自のユーザーおよびネットワーク名前空間でホストから分離された状態で動作します。それでもGPUアクセラレーション、オーディオ、DRMサポートは完全に利用できます。
Firefoxにはすでに、Linux名前空間とseccomp-bpfを使用してWebコンテンツレンダラーを分離するマルチプロセスサンドボックスがあります。ほとんどの脅威に対しては、これで効果的です。foxcageは第二の壁を追加します。攻撃者がFirefoxのサンドボックスを脱出する脆弱性(実際に存在し、CVEもあります)を悪用した場合、攻撃者は完全なユーザーセッションではなく、ロックダウンされたコンテナ内に着地します。
~/.ssh、~/.gnupg、他のブラウザのプロファイル、パスワードマネージャーのデータベース、ドキュメント、ソースコード)へのアクセスを許します。foxcageでは、攻撃者は明示的にマウントしたものだけを見ることができます。@tmp一時ケージは、ウィンドウを閉じた後にディスク上に痕跡を一切残しません。Firefoxのプライベートブラウジングが依然として保持する拡張機能、HSTS状態、TLSセッションキャッシュ、DNSキャッシュも含みます。複数の@tmpケージは互いに干渉せずに同時に実行できます。~/.config/autostart、~/.bashrc、cron、その他の場所に書き込んで再起動後も生き残ることができます。foxcageの一時コンテナ(--rm)は、バインドマウントしない限り何も永続化しないことを意味します。localhost上のサービスをプローブできません。素のFirefoxでは、サンドボックス脱出は完全なネットワークアクセスを持ちます。(ローカル開発などでケージがlocalhostアクセスを必要とする場合は[network] mode = "host"を使用してください。ただし「ネットワーク」の下の注意事項を参照してください。ホストモードはホストの抽象Unixソケットも公開します。)CAP_SYS_CHROOTを除くすべてのLinuxケーパビリティをドロップし、新しい権限の取得をブロックします。Setuidバイナリ、不明瞭なシステムコールによるカーネルエクスプロイト、および同様の昇格経路は遮断されます。profile、downloads_dir、追加のバインドマウント)は、侵害されたブラウザから完全にアクセス可能です。ホストのプロファイルディレクトリをマウントした場合、攻撃者は素のFirefoxと同様にそれを改ざんできます。コンテナは以下で実行されます:
CAP_SYS_CHROOTのみ追加で戻す。init.rootが設定されている場合はCAP_SETUID/CAP_SETGIDを一時的に追加)no-new-privileges--userns keep-id)/dev/shm(ホストと共有しない)— shm_sizeでサイズ設定可能network.dnsで設定可能)XDG_RUNTIME_DIRからの特定のソケットのみがバインドマウントされる(Wayland、PulseAudio、PipeWire、およびフィルタリングされたD-Busプロキシ)— ホストのランタイムディレクトリ全体が公開されることはありませんxdg-dbus-proxyによって仲介されます。org.freedesktop.Notifications、org.freedesktop.portal.Desktop、、および(フォークの場合)フォーク自身の名前空間(例:)のみが到達可能です。キーリングやSSH/GPGエージェントなどのセッションサービスはブロックされます有効にする各[network]および[mounts]オプションは、利便性のために分離の一部を犠牲にします。デフォルトは、使用可能なブラウザを提供する最も制限的な設定です。
sudo apt install passt)— network.mode = "host"でない限りsudo apt install xdg-dbus-proxy)/dev/driがない場合、foxcageは警告し、Firefoxはソフトウェアレンダリングになります。Intel、AMD、nouveau用のVA-APIドライバーがイメージにインストールされているため、ホストのドライバーパッケージなしでハードウェアビデオデコードが機能します — ハードウェアビデオデコードを参照foxcageを通常のデスクトップユーザーとして実行してください。rootやsudo経由では実行しないでください。サンドボックスはユーザーをコンテナにマップし、rootとして実行するとfoxcageが存在する目的である分離が失われます。rootとしての起動は拒否されます。
テスト済み環境: GNOME 3を搭載したDebian 13(Trixie)。他のLinuxディストリビューションやWaylandコンポジターでも動作する可能性がありますが、テストされていません。
foxcageは、Python標準ライブラリ以外に依存関係のない単一のPythonスクリプトです。PATH内のディレクトリにコピーしてください:```sh
sudo cp foxcage /usr/local/bin/foxcage
またはユーザーローカルインストールの場合:```sh
cp foxcage ~/.local/bin/foxcage
スクリプトを実行可能にしてください(chmod +x foxcage)。
問題を報告する際に役立つので、foxcage --version でリビジョンを確認してください。foxcage は単一ファイルのコピーでインストールされるためです。
./foxcage
初回実行時、スクリプトはコンテナイメージをビルドし(MozillaからFirefoxをダウンロードし、最小限のDebian依存関係をインストール)、その後Firefoxを起動します。以降の実行では、foxcageはFirefoxのアップデートを確認し、新しいバージョンが利用可能な場合に自動的にイメージを再ビルドします。また、イメージは定期的に(デフォルトでは7日ごと)再ビルドされ、システムパッケージのアップデートを反映します。アップデート確認が失敗した場合(ネットワークエラー、タイムアウト)、警告がログに記録され、既存のイメージが使用されます — 起動がブロックされることはありません。
Firefoxに引数を渡す:```sh
./foxcage https://example.com
名前付きケージとFirefoxフラグを組み合わせる:```sh ./foxcage @work --kiosk https://example.com
既存のケージが実行中の場合は、2つ目のコンテナを起動する代わりに、既存のブラウザの新しいタブでURLが開きます。実行中のケージに対してURLなしで`foxcage`(または`foxcage @cage`)を実行すると、「cage is already running」というメッセージとともに正常に終了します。foxcageはコンテナの外部から既存のWaylandウィンドウを前面に出すことはできないため、試行は行われません。
起動時フラグは、ケージがすでに実行中の場合は**適用されません**。`--dns`、`--ipv4-only`、`--lifetime`、`--color`、`--fork`はコンテナ起動時に消費され、実行中のコンテナの設定は外部から変更できないため、警告付きで無視されます。これらを適用するには、ケージを閉じて再実行してください。
> プライベートモードのセッションには、`private_browsing`設定キーを使用してください。Firefoxの生の`--private-window`CLIフラグは使用しないでください。設定キーはセッション全体のプライベートモード(`browser.privatebrowsing.autostart`)を設定するため、後続の`foxcage @cage URL`呼び出しでタブ内に再度開くことができます。Firefoxのパススルーとしての`--private-window`は最初のウィンドウのみをプライベートにし、上記のタブ内再オープン動作を壊してしまいます。
>
> **注意:** `private_browsing = true`で有効化されたセッションでは、Firefoxの通常のプライベートウィンドウUI表示(紫色のアクセントバー、マスクアイコン、タイトル内の「(Private Browsing)」)は表示されません。これは、セッション内のすべてのウィンドウがプライベートであるため、Firefoxが視覚的に対比できる非プライベートウィンドウを持たず、インジケーターを抑制するためです。セッションは実際にプライベートです。確認したい場合は、ケージ内で`about:privatebrowsing`にアクセスするか(標準のプライベートブラウジング情報ページが表示されます)、`about:config`で`browser.privatebrowsing.autostart = true`を確認してください。
### `@tmp`による一時ブラウジング
痕跡を残さない一回限りのリンクには、予約済みの`tmp`ケージを使用してください。```sh
./foxcage @tmp https://somewhere-suspicious.example
Every @tmp 起動は、永続プロファイルを持たない使い捨ての Firefox です。ウィンドウを閉じると、すべてが消えます — Cookie、キャッシュ、履歴、拡張機能、HSTS 状態、TLS セッションキャッシュ、DNS キャッシュ、保存されたタブ状態。これは、拡張機能とかなりの量のディスク上の状態を保持する Firefox のプライベートブラウジングよりもさらに徹底しています。
複数の @tmp ケージは同時に実行され、それぞれが他から分離されています。メニューバーには FoxCage - tmp (<short id>) と表示されるため、同時実行中の一時的なウィンドウを区別できます。
一時的なケージは起動時に空白ページと空白の新しいタブを開きます — デフォルトの Firefox ホームページと新しいタブのコンテンツ(トップサイト、Pocket のおすすめ、アクティビティストリーム)は、破棄される予定の新しいプロファイルでは単なるノイズなので、抑制されます。永続的なケージは Firefox のデフォルトを維持します。
使い捨てセッションに意味のある名前を付けたい場合(たとえば、新しいタブで再度開きたい調査の深掘りなど)、@tmp-<name> を使用します:```sh
./foxcage @tmp-research https://example.com # first call → new window
./foxcage @tmp-research https://another.example # second call → new tab in the existing window
`@tmp-<name>` は依然として一時的です。ウィンドウを閉じると、すべてが消えます。素の `@tmp` との違いは、同じ名前で2回目に起動すると**既存のウィンドウを再利用する**ことです(永続ケージと同じ)。そのため、後から並列コピーを開始せずにタブを追加できます。素の `@tmp` は「起動するたびに新しい使い捨て」という動作を維持します。
メニューバーのラベルには、選択した名前(`FoxCage - tmp-research`)が表示されるため、ウィンドウに意味のあるラベルが付きます。
#### 一時的デフォルトのカスタマイズ
`~/.config/foxcage/tmp.toml` を作成すると、すべての一時的ケージ(素の `@tmp` とすべての `@tmp-<name>` の両方)のデフォルトを設定できます。例:```toml
private_browsing = true
lifetime = "30m"
extensions = ["ublock-origin"]
[network]
dns = "cloudflare"
すべての一時起動は、プライベートウィンドウ、uBlock Origin、Cloudflare DoHを備え、30分後に自動終了します。完全な一時性はそのまま維持されます。名前付きの一時プロファイルは、デフォルトでtmp.tomlを継承します。名前ごとに上書きしたい場合は、~/.config/foxcage/tmp-<name>.tomlを作成してください。そのファイルはtmp.tomlの代わりに適用されます。マージは行われず、より具体的なファイルが完全に優先されます。共有のデフォルト設定が必要な場合は、そのファイルにコピーしてください。
通常のケージの設定で設定できるものはすべてここでも機能します。ただし、一時性そのものを無効化する1つのキーだけは例外です:
profile — ハードエラー。これは、ホスト上の永続的なプロファイルディレクトリを指すもので、@tmpの目的と直接矛盾します。永続的なプロファイルを持つサンドボックス化されたケージが必要な場合は、tmp-で始まらない通常の名前付きケージ(@work、@researchなど)を使用してください。
ケージには、イメージに組み込まれた拡張機能を持たせ、毎回の起動時に強制インストールさせることができます:```toml extensions = ["ublock-origin"]
`~/.config/foxcage/tmp.toml` にこれを入れると、**使い捨てケージは毎回 uBlock Origin がすでに起動した状態で始まります**。これは重要です。なぜなら、一時的なケージは、あなたが最も信頼していないリンクを開くために使う、それ以外では最も保護されていないブラウザだからです。新しい `@tmp` プロファイルには拡張機能が一切入っておらず、閉じるときに自分自身を破棄するセッションで手動でインストールするのは無意味です。
各エントリには、アドオンの addons.mozilla.org URL の短い名前、そのリスト URL 自体、またはアドオン ID を指定できます。```toml
extensions = [
"ublock-origin",
"https://addons.mozilla.org/firefox/addon/noscript/",
"[email protected]",
]
アドオンは起動時にaddons.mozilla.org APIを通じて解決され、イメージビルド中にダウンロードされ、AMOが公開するSHA-256ダイジェストと照合されます。解決されたバージョンはContainerfileの一部であるため、拡張機能の新リリースはイメージハッシュを変更し、再ビルドをトリガーします。拡張機能はFirefoxと同じ方法で、同じ理由で更新されます。つまり、ランタイムには何もインストールされないため、新しい一時プロファイルが何かを再ダウンロードすることは決してありません。
手動ではなくエンタープライズポリシーでインストールされるため、次のようになります。
about:addonsには組織によってインストールされたものとして表示されます)。private_browsing = trueで実行されているケージでも引き続き機能します。これにはFirefox 136またはESR 128.8が必要です。古いバージョンではこの設定を無視し、プライベートウィンドウではアドオンが無効のままになります。制限事項:
.xpi URLは拒否されます。@tmpとすべての@tmp-<name>は単一のfoxcage-tmpイメージをビルドするため、名前付きの一時ケージにtmp.tomlとは異なるextensionsリストを指定すると、起動のたびに互いを上書きするように再ビルドされます。一時拡張機能リストはtmp.tomlに保持してください。--dnsフラグ(および同等のnetwork.dns設定キー)は3つの形式を受け入れます。```sh
./foxcage @tmp --dns 1.1.1.1 https://example.com # IP
./foxcage @tmp --dns cloudflare https://example.com # alias
./foxcage @tmp --dns https://dns.nextdns.io/ # custom DoH URI
**値が既知のプロバイダー(エイリアスまたはIPで)と一致する場合、foxcageは自動的にそのプロバイダーへの強制DNS over HTTPSを有効にします。** FirefoxのTRRはモード3(厳格、平文フォールバックなし)に設定され、ブートストラップアドレスが入力されるため、起動時に暗号化されていない解決リークは発生しません。`Enabling DNS over HTTPS via Cloudflare` のような1行の通知がstderrに表示されます。
組み込みエイリアス:
| エイリアス | IP | フィルタリング |
|-------|------|-----------|
| `cloudflare` | 1.1.1.1 | なし |
| `cloudflare-security` | 1.1.1.2 | マルウェアをブロック |
| `cloudflare-family` | 1.1.1.3 | マルウェア + アダルトをブロック |
| `google` | 8.8.8.8 | なし |
| `quad9` | 9.9.9.9 | マルウェアをブロック(Quad9デフォルト) |
| `quad9-unfiltered` | 9.9.9.10 | なし |
| `adguard` | 94.140.14.14 | 広告 + トラッカーをブロック |
| `adguard-family` | 94.140.14.15 | 広告 + トラッカー + アダルト |
| `opendns` | 208.67.222.222 | 一部 |
テーブルにないIP(例: LAN上のPi-hole)は平文のままです — foxcageが対応するDoHエンドポイントを知らないため、DoHは有効になりません。その場合はURI形式を使用してください: `--dns https://pi.hole/dns-query`(有効な証明書付き)でDoHが有効になり、コンテナのDNSはそのままになります。
URI形式はコンテナの平文DNSの設定をスキップするため、コンテナ内でFirefox以外のものがホストのDNSを引き続き使用します。これは意図的です — `--dns URI` は「FirefoxにこのDoHリゾルバーを使用させる」という意味で、それ以上でもそれ以下でもありません。
`--dns` は `network.mode = "host"` と互換性がありません。これはすでに完全なホストネットワークアクセスを持っています。
### 視覚的なケージ識別
名前付きの各ケージにはメニューバーにアクセントカラーが付与され、ウィンドウを一目で区別できます。**設定は一切不要です** — 色はケージ名から決定的に導出されます(SHA256ハッシュで色相に変換され、彩度と明度は固定)。`@banking`、`@work`、`@personal`、`@tmp-research` はすべて、何もしなくても個別の安定した色を取得します。
デフォルト(匿名)ケージは組み込みのオレンジを維持します。
自動導出された色を上書きしたい場合は、明示的に設定してください:```toml
# ~/.config/foxcage/banking.toml
color = "#dc2626" # red — overrides the auto-derived colour
翻訳対象のMarkdownコンテンツが入力されていません。```sh ./foxcage @experiment --color "#10b981" https://example.com # teal, one-off
Accepts standard CSS hex: `#rgb`, `#rrggbb`, or `#rrggbbaa` (with alpha). The auto-derived colours are tuned to be visible on both light and dark menubars (lightness fixed at 55%, saturation at 75%), so you shouldn't need to override for theme reasons.
### Time-limited cages
The `--lifetime` flag (and equivalent `lifetime` config key) auto-closes a cage after a set duration. Format is `<number><unit>` with unit `s`, `m`, or `h`:```sh
./foxcage @tmp --lifetime 10m https://example.com
./foxcage @work --lifetime 2h
カウントダウンは、Firefoxが実際にケージ内で起動した時点から始まります — コンテナの起動時間やイメージのビルド時間は予算に含まれません。ケージのメニューバーのラベルには、ケージの識別情報とともにカウントダウンが表示されます — 例: FoxCage - tmp (a3f2b1) | 9m — 残り時間が1分を超えている間は毎分更新され、最後の1分間は毎秒更新されます。カウントダウンがゼロに達すると、Firefoxは自動的に閉じられ、コンテナは終了します。有効期限が切れる前に自分でFirefoxを閉じた場合、特別なことは何も起こりません。
各ケージの設定で、デフォルトの有効期限を設定します:```toml
lifetime = "15m" private_browsing = true
`--lifetime` をコマンドラインで指定すると、設定ファイルの値よりも優先されます。
完全なイメージの再ビルドを強制します(Firefox とすべてのシステムパッケージを再ダウンロードします):```sh
./foxcage --rebuild
実行中のコンテナは、foxcageがイメージタグを再ビルドした後でも、起動時に使用したイメージを保持し続けます。--rebuild、Firefoxのアップデート、またはスケジュールされた再ビルドによってイメージが更新されたケージ内のタブを開こうとすると、foxcageはエラー(デスクトップ通知としても表示されます)で拒否し、Firefoxを終了して再起動するよう求めます。これにより、現在のイメージ上で新しいコンテナが起動します。ライブケージでの--rebuildでは、foxcageは事前に警告し、ビルドを実行してから、同じチェックを適用します。
foxcageは起動のたびに新しいブラウザリリースをチェックします。FirefoxにはMozillaのリリースAPI、LibreWolfにはGitLabのリリースエンドポイントを使用します。アップデートが利用可能な場合、コンテナイメージは自動的に再ビルドされます。また、Debianのセキュリティアップデートを取り込むために、イメージは定期的に(デフォルトでは7日ごとに)再ビルドされます。ブラウザの内蔵自動アップデーターは、アップデートがイメージレベルで処理されるため無効化されています。
アップデートチェックが失敗した場合(ネットワークなし、APIタイムアウト)、警告が表示され、既存のイメージが使用されます。ブラウジングは常に可能です。
アップデートの頻度は設定の最上位レベルにあり、バージョンとチャネルの固定はフォークごとのセクションにあります。```toml rebuild_days = 14 # rebuild for base-image updates every 14 days (0 to disable)
[firefox] channel = "beta" # track the beta channel instead of stable (firefox only) version = "149" # pin to Firefox 149.x (latest patch release)
**ESRバージョンを固定するには、チャンネルも指定する必要があります。** Mozillaのバージョンインデックスには、ダウンロード時に付く`esr`サフィックスなしでESRリリースがリストされるため、デフォルトチャンネルで単に`version = "140"`と指定すると、存在しないリリースに解決されてしまいます。両方を設定してください:```toml
[firefox]
channel = "esr"
version = "140" # → 140.13.0esr
リリースに一致しないピンは、静かに最新リリースへフォールバックするのではなく、そのピンを指定したエラーになります。MozillaのAPIに一時的に到達できない場合は、引き続き警告を出して既存のイメージで続行するため、不安定なネットワークが起動を妨げることはありません。
接尾辞付きピンは完全修飾である必要があります — "140.13.0esr" と "150.0b9" は機能しますが、"140esr" と "150b9" は、それに一致するリリースが存在しないため、設定読み込み時に拒否されます。これはLibreWolfのリビジョンにも同様に適用されます: "146.0.1-1" は機能しますが、"146-1" は機能しません。
即時の完全リビルドを強制するには: ./foxcage --rebuild
foxcageは、上流プロジェクトが侵害されたとして失効させた署名サブキー(RFC 4880の失効理由 0x02)によって署名されたブラウザビルドのインストールを拒否します。gpg --verify はこれを単独では行いません: 警告を出力して終了コード0で終了するため、追加のチェックがなければ、漏洩した署名鍵でも改ざんされたダウンロードを認証してしまうことになります。
拒否は次のようになり、インストールする代わりにビルドを失敗させます:``` foxcage: REFUSING /tmp/SHA512SUMS - signed by 09BEED63F3462A2DFFAB3B875ECB6497C1A20256, which its owner revoked as compromised. This build cannot be trusted; wait for upstream to re-sign this release with a current key.
foxcage は、設定やオーバーライドを必要としません。この問題に遭遇した場合、修正は上流側にあります。現在の鍵で署名されたリリースを固定するか、影響を受けるリリースが再署名されるのを待ってください。
定期的な鍵のローテーションは異なる扱いを受けます。置き換え、退役、または理由なしで失効したサブキーは、失効*前*に行われた署名を無効にしないため、それらのリリースは警告付きでインストールされます。失効*後*の日付の署名は、理由に関係なく拒否されます。
**Mozilla の 2026年8月の鍵ローテーション。** Mozilla は、暗号化されていないコピーがプライベート GitHub リポジトリにコミットされた後、2026-08-06 に署名サブキー `09BEED63…C1A20256` を失効させ、`827E6586…76767AA3` に置き換えました。古いサブキーで署名された Firefox リリース — 2025-03-13 から 2026-08-06 までのすべて(執筆時点では、現在の ESR(`140.13.0esr`)と、その期間内の `version` ピンを含みます)— は、上記のチェックで拒否されます。リリースチャンネルとベータチャンネルは影響を受けません。foxcage は `keyserver.ubuntu.com` ではなく `keys.openpgp.org` から鍵を取得します。後者は、ローテーション後数日間、置換サブキーも失効情報も提供しなかったためです。古い鍵サーバーは、ビルドを完全に壊すだけでなく、失効チェックを黙って無効化(no-op)にしてしまいます。
### Firefox フォーク(LibreWolf)
foxcage は、上流の Firefox の代わりにプライバシー重視の Firefox フォークを実行できます。```toml
fork = "librewolf" # default is "firefox"
[librewolf]
version = "146.0.1-1" # optional pin; partial pins ("146", "146.0.1") also work
起動ごとにCLI経由で:```sh foxcage @tmp --fork librewolf https://example.com
**LibreWolf**: プライバシー強化版 Firefox フォーク — 厳格なトラッキング保護、DoH、RFP、テレメトリーはデフォルトで無効化。GitLab(`librewolf-community/browser/bsys6`)から署名済み Linux tarball を取得し、LibreWolf メンテナの鍵 `662E 3CDD 6FE3 2900 2D0C A5BB 4033 9DD8 2B12 EF16` に対して GPG 検証し、併せて `.sha256sum` の相互チェックも実施。Firefox と同じ[失効ルール](#revoked-signing-keys)に従います。LibreWolf に同梱される `librewolf.cfg` は保持され、foxcage は上書きせずに独自の設定をその上に追加します。メンテナは 2026-04-25 に理由を明示せず署名サブキーをローテーションしました。現在の tarball はその日付より前に署名されているため、拒否されるのではなく警告付きでインストールされます。
**チャネルは Firefox のみ**: `fork` が `"firefox"` 以外の場合、`firefox.channel = "beta" | "esr"` は拒否されます。LibreWolf には単一のリリーストラックしかありません。
`fork` を(設定または `--fork` で)切り替えると Containerfile のハッシュが変わり、次回起動時にリビルドがトリガーされます — 手動の `--rebuild` は不要です。
#### プロファイル互換性
> **フォークごとに専用プロファイルを使用してください。** 最も安全なデフォルトは、foxcage に独自のプロファイルをプロビジョニングさせることです(設定から `profile` を省略する)、または `profile` をホストからも開かないディレクトリに指定します。
- **LibreWolf**: ホストの Firefox プロファイルと共有しても*通常は*問題ありません — LibreWolf は Firefox のバージョンを数日以内に追従するため、`compatibility.ini` のスキーマ競合はまれです。リスク: (1) 順次使用のみ安全です(Firefox のロックファイルにより同時起動が防止されます); (2) Firefox 安定版リリース直後の短い期間に、Firefox を先に起動してから LibreWolf を起動すると「新しいバージョンで使用されています」という移行ダイアログが表示される可能性があります; (3) LibreWolf が削除する機能(Sync、Pocket、Mozilla アカウント)は静かに動作しませんが、データを破損することはありません。
### 名前付きケージ
独自の設定と Firefox プロファイルを持つ個別のサンドボックスインスタンスを実行します:```sh
./foxcage @work
これは ~/.config/foxcage/work.toml を読み込み、別のイメージ(foxcage-work)、コンテナ(foxcage-work)、およびボリューム(foxcage-work-profile)を使用します。名前付きケージでは設定ファイルが存在している必要があります。ケージ名には、英字、数字、ハイフン、アンダースコアのみを使用できます。
設定ファイルは $XDG_CONFIG_HOME/foxcage/(デフォルトは ~/.config/foxcage/)に置かれます。
config.toml — デフォルトのケージ(任意。これがなくても適切なデフォルト値が使用されます)<name>.toml — 名前付きケージ。@<name> で読み込まれます(必須)不明な設定キーはエラーとして拒否されます。利用可能なすべてのオプションとデフォルト値については、config.toml.example を参照してください。
profile = "~/.mozilla/firefox/xxxxxxxx.default-release"
downloads_dir = "~/Downloads"
[firefox]
[librewolf]
[network]
[mounts]
bind = [ "~/Documents:ro", ]
[init]
### ホストFirefoxプロファイル
ケージとホストのFirefoxプロファイルを共有するには、`profile`をプロファイルディレクトリに設定します。ホスト上のFirefoxで`about:profiles`にアクセスしてプロファイルのパスを確認してください。あるいは、ホスト上に保持されるクリーンなプロファイルでケージを起動したい場合は、新しい空のディレクトリを指定するだけでも構いません。```toml
profile = "~/.mozilla/firefox/xxxxxxxx.default-release"
このディレクトリのみがケージにバインドマウントされます。~/.mozilla/firefox/ 配下の兄弟プロファイルや profiles.ini レジストリは公開されません。侵害されたケージはそれらを改ざんできません。
profile が未設定の場合、名前付き Podman ボリュームが Firefox プロファイルを保存します(下記の「永続化されるもの」を参照)。同じプロファイルがホスト上の Firefox で既に開かれている場合、Firefox のプロファイルごとのロックファイルが競合を引き起こします。ケージごとに専用のプロファイルを使用してください。
デフォルトでは、コンテナはホストのループバックをブロックし、ホストの DNS を使用する pasta を使用します。pasta には podman 4.4 以降が必要です(podman 5.0 以降、rootless のデフォルトとなっています)。
ホストネットワーク はネットワーク分離を完全に解除します。ケージがホストの localhost 上のサービス(例: ローカル開発サーバー、127.0.0.1 上のデータベース)に到達する必要がある場合にこれを使用します:```toml
[network]
mode = "host"
`dns` は `mode = "host"` と組み合わせることはできません。ホストネットワーキングはすでにホストのリゾルバを使用しているためです。
> **ホストモードは localhost 以上のものを放棄します。** ケージをホストのネットワーク名前空間に配置するため、抽象 Unix ソケットはファイルシステムではなくその名前空間にスコープされます。したがって、ホストモードのケージはホスト上の抽象アドレスソケットに直接到達できます。これには、X11 または Xwayland を実行している場合の Xwayland の `@/tmp/.X11-unix/X0`(foxcage は Wayland 専用ですが、入力ログが取得される可能性があります)、および `unix:abstract=…` で構成されたセッションバスが含まれ、フィルタリングされた D-Bus プロキシを迂回する可能性があります。これはネットワークスタックを共有することに内在するものであり、foxcage がフィルタリングできるものではありません。必要な場合にのみホストモードを使用し、その目的専用に起動する名前付きケージを優先してください。
**IPv4 専用ケージ** は IPv6 を完全に無効にします:```toml
[network]
ipv4_only = true
Or per launch with the --ipv4-only flag (short form -4, as in ssh/curl/pasta):```sh
./foxcage @tmp -4 https://example.com
これはpastaをIPv4専用モード(`-4`)で実行するため、コンテナにはIPv6スタックがまったく存在せず、さらにFirefoxで`network.dns.disableIPv6`を設定してAAAAレコードを解決しないようにします。これはDoHが有効な場合に重要です。DoHの応答はコンテナのリゾルバを迂回するためです。`ipv4_only`は`mode = "host"`と組み合わせることはできません。ホストネットワークはホストのネットワークスタックを直接使用するため、代わりにホスト側でIPv6を無効にしてください。
### Initコマンド
`[init]`を使用して、ビルド時またはコンテナ起動時にカスタムコマンドを実行します:
- **`build`** — イメージビルド時にrootとして実行されます。パッケージのインストールやその他の時間のかかるセットアップに使用します。ビルドコマンドへの変更は、自動的にイメージの再ビルドをトリガーします。
- **`root`** — コンテナ起動時にFirefoxの前にrootとして実行されます。迅速なランタイムのrootタスク(権限の調整、設定ファイルの書き込み)に使用します。
- **`user`** — コンテナ起動時にFirefoxの前にユーザーとして実行されます。ディレクトリの作成やユーザーレベルの状態の設定に使用します。```toml
[init]
build = [
"apt-get update && apt-get install -y --no-install-recommends fonts-noto-cjk",
"rm -rf /var/lib/apt/lists/*",
]
root = ["chmod 777 /tmp/shared"]
user = ["mkdir -p ~/workspace"]
すべての3つのキーは、シェルコマンド文字列のリストです。いずれかのコマンドが失敗すると、コンテナはFirefoxを起動せずに終了します。
セキュリティ上の注意: init.root が設定されている場合、コンテナは CAP_SETUID と CAP_SETGID が追加された状態(デフォルトの CAP_SYS_CHROOT に加えて)でrootとして起動し、通常ユーザーに権限を落とすことができます。これらのケーパビリティはroot初期化フェーズ中のみ保持され、権限降下後は通常ユーザーのプロセスには追加のケーパビリティはありません。init.root がない場合、コンテナはデフォルトの最小ケーパビリティセットで実行されます。
設定がない場合、名前付きPodmanボリュームがFirefoxプロファイル(ブックマーク、設定、拡張機能、Widevine DRMプラグイン)を保存します。その他はすべて一時的です。
foxcage-profilefoxcage-<name>-profile新しく開始するには、ボリュームを削除します:```sh podman volume rm foxcage-profile
`profile` が設定されている場合、ホストディレクトリは直接バインドマウントされ、ボリュームは作成されません。
`extensions` にリストされた拡張機能はその状態の一部ではありません。それらはイメージ内に存在し、起動のたびに再インストールされるため、ボリュームを削除しても(またはボリュームを持たない一時的なケージを使用しても)失われることはありません。
### ディスク使用量
各ケージイメージは約1 GBです。リビルドするとイメージが再タグ付けされ、以前のイメージはタグなしの`<none>`エントリとして残るため、foxcageはビルドが成功するたびに、置き換えた直後のイメージを削除します。削除されるのはその特定のイメージのみで、実行中のケージがまだ使用しているイメージが削除されることはありません。
この動作が存在する前に孤立したイメージは、遡ってクリーンアップされません。それらを回収するには:```sh
podman images --filter dangling=true # review first
podman image prune # then remove
Firefoxの更新は、起動のたびに自動的に検出されます。完全な再ビルドを強制するには(例:システムのセキュリティ更新をすぐに反映させる場合):```sh ./foxcage --rebuild
## テーマ設定
foxcageはホストから以下を自動的に透過させるため、コンテナ内のFirefoxはネイティブアプリケーションのように見え、動作します:
- **フォント。** システムフォント(`/usr/share/fonts`)とユーザーフォント(`~/.local/share/fonts`)は読み取り専用でバインドマウントされます。`~/.config/fontconfig` のフォント設定も透過されます。
- **GTKテーマとダークモード。** `GTK_THEME` または `gsettings` で検出され、コンテナに渡されます。`~/.config/gtk-3.0` と `~/.config/gtk-4.0` のGTK設定は読み取り専用でバインドマウントされます。
- **タイムゾーン。** ホストのタイムゾーン名(`TZ`、`/etc/localtime` シンボリックリンク、または `/etc/timezone` から検出)は `TZ` としてコンテナに渡され、`/etc/localtime` は読み取り専用でバインドマウントされます。両方が必要です: FirefoxはJavaScriptのタイムゾーンをゾーン*名*から導出し、ファイルの内容からは導出しません — `TZ` がないと、ウェブサイトはUTCで時刻を表示します。
- **ロケール。** `LANG` が透過されます。ホストのロケールはビルド時にコンテナイメージ内で生成されます。
**Cageラベル。** Firefoxのメニューバーには「FoxCage」(名前付きcageの場合は「FoxCage - name」)と表示されるため、コンテナ化されたセッションにいることが一目でわかります。メニューバーはエンタープライズポリシーにより常に表示されます。
コンテナにはAdwaita GTKテーマのみが含まれています。GNOMEデスクトップではそのまま動作します。KDEやその他のデスクトップでは、GTKテーマ(例: Breeze)がコンテナにインストールされていない場合、FirefoxはAdwaitaにフォールバックします。ダークモード検出は、`gsettings` または `GTK_THEME` で設定が行われている限り、引き続き機能します。
## ハードウェアビデオデコード(VA-API)
コンテナには独自のユーザーランドがあるため、ホストにインストールされているVA-APIドライバーは
無関係です — イメージには独自のものが同梱されています。`va-driver-all` は `i965-va-driver`(旧型
Intel)と `mesa-va-drivers`(AMD、nouveau)を引き込み、さらに `intel-media-va-driver-non-free`
(Intel Gen8+、iHDドライバー)と `libva2`/`libva-drm2` も含まれます。これらはFirefoxが実行時に読み込みます。
ハードウェアデコードには `/dev/dri` の透過が必要ですが、foxcageはホストにそれが存在する場合に
自動的に行います。設定は不要です。
Intelドライバーは**非フリー**ビルドのため、イメージはDebianの `non-free`
コンポーネントを有効にします。Debianのフリー版 `intel-media-va-driver` は、再配布不可の
コーデックカーネルを除去した `+dfsg` リパックであり、失われるのはAV1デコードです — YouTubeが
現在デフォルトで配信している形式です。フリービルドでは、すべてのIntelマシンでAV1がソフトウェアに
フォールバックすることになります。
実際に動作しているか確認するには、ライブcage内で `vainfo` を実行します:```bash
podman exec foxcage-<name> vainfo
使用中のドライバ(IntelではiHD、AMDではradeonsi)と、サポートされているプロファイル(VAProfileH264*、VAProfileVP9Profile0、VAProfileAV1Profile0など)が表示されるはずです。ブラウザ内からの同等の確認方法は、about:support → メディアで、ハードウェアデコード列がH264、VP8、VP9、HEVC、AV1でSupportedと表示されるかどうかです。動画を再生している状態で、ホスト上のintel_gpu_topにVideoエンジンのアクティビティが表示されます。
ハードウェアエンコードは別物で、Intelでは同じドライバから提供されます。H264とHEVCはその列でSupportedと表示されるはずです。これは、WebRTCがビデオ通話の送信カメラストリームで使用し、MediaRecorderも使用するものです。VP8、VP9、AV1のエンコードはUnsupportedのままです。Firefoxは、GPUの能力に関係なく、H264とHEVCのVA-APIエンコーダのみを接続します。
オーディオコーデック(AAC、MP3、Opus、Vorbis、FLAC、Wave)は、どのマシンでもハードウェアデコードの下でUnsupportedと表示されます。コンシューマー向けGPUにオーディオデコードブロックは存在しないためです。その行は設定ミスではありません。
vainfoがfailed to initialize displayを報告する場合、コンテナが/dev/dri/renderD128を開けていません。通常のsystemdデスクトップでは、logindがそのデバイスへのACLをユーザーに付与するため、これは通常、foxcageがシートを所有しないセッション(SSH、別のTTY)から実行されていることを意味します。
Widevine DRMはそのまま動作します。DRM保護されたサイトへの初回アクセス時に、FirefoxがWidevine CDMを自動的にダウンロードします。これには少し時間がかかる場合があります。
foxcageはフィルタリングされたD-Busプロキシを使用して、FirefoxにホストのXDG Desktop Portalと通知デーモンへのアクセスを提供します。これらの機能は、すべてのアクセスがユーザー仲介型であるため安全です。ホストがネイティブダイアログを表示し、ユーザーが操作する必要があります。侵害されたブラウザがホストリソースに静かにアクセスすることはできません。
mailto:、magnetリンクなどはホストのアプリ選択ダイアログで開くこれらはホストデバイスをコンテナに直接渡すもので、デフォルトではオフです。上記のポータル機能とは異なり、ホスト側での確認はありません。侵害されたブラウザがハードウェアを静かに使用する可能性があります。```toml webcam = true # /dev/video* — webcam for video calls local_printers = true # CUPS socket — USB printers (network printers work by default) security_keys = true # /dev/hidraw* — FIDO2/U2F hardware keys
## まだサポートされていません
一部のWebプラットフォーム機能は、ホスト統合が欠如しているためコンテナ内では動作しません。透明性のため、ここに列挙します。
**Bluetooth、USB、シリアル、NFC。** Web Bluetooth、WebUSB、Web Serial、WebNFC APIは、コンテナ内では利用できないデバイスアクセスとシステムサービス(BlueZ、udev)を必要とします。
**ゲームパッドとMIDI。** Gamepad APIは`/dev/input/`へのアクセスを必要とします。Web MIDIはALSAシーケンサーへのアクセスを必要とします。どちらも透過されません。
**PWAインストール。** プログレッシブWebアプリは、コンテナ内からホストのデスクトップにインストールできません。
**アクセシビリティ。** AT-SPIによるスクリーンリーダーサポートは無効です(`NO_AT_BRIDGE=1`)— コンテナはホストのアクセシビリティバスに接続されていません。Web Speech APIの合成は動作します:`espeak-ng`エンジンを備えた`speech-dispatcher`がケージにインストールされ、初回使用時に自動起動され、オーディオは共有PulseAudioソケット経由でルーティングされます。
## ホスト設定
### 推奨:オーバーレイストレージ
Rootless Podmanは、オーバーレイマウントを使用する代わりにイメージレイヤー全体をコピーする`vfs`ストレージドライバーにフォールバックする場合があります。これにより、ビルド後のコンテナ起動が大幅に遅くなります。使用しているドライバーを確認してください:```sh
podman info --format '{{.Store.GraphDriverName}} {{.Store.GraphStatus}}'
overlay と Native Overlay Diff:true の組み合わせは高速パスであり、設定は不要です。カーネル5.13以降で、バッキングファイルシステムがext4/xfsの場合、Podmanは非特権overlayfsを直接使用します。その状態であれば、何もする必要はなく、fuse-overlayfs をインストールしても役に立ちません。
vfs に該当する場合(古いカーネル、または非特権overlayをサポートできないバッキングファイルシステム)のみ、fuse-overlayfs をインストールし、~/.config/containers/storage.conf に以下を追加してください:```toml
[storage]
driver = "overlay"
[storage.options.overlay] mount_program = "/usr/bin/fuse-overlayfs"
これはフォールバックであり、アップグレードではありません。FUSEはすべてのファイルシステム操作をユーザースペース経由でルーティングするため、ネイティブのオーバーレイよりも遅くなります。ネイティブのオーバーレイをサポートするシステムで`mount_program`を設定すると、状況が悪化するだけで改善されません。
### foxcageをデフォルトブラウザとして設定する
まず、`foxcage`スクリプトが恒久的な場所(例:`~/bin/foxcage`または`/usr/local/bin/foxcage`)にあることを確認してください。インストールコマンドは、スクリプトの現在のパスを`.desktop`ファイルに記録するため、後で移動するとランチャーが壊れます。
次に、以下を実行します。```sh
foxcage --install
これにより、スクリプトの現在の場所を指す.desktopファイルが作成され、foxcageアイコンがインストールされ、デスクトップとアイコンのデータベースが更新されます。その後、FoxCageがアプリケーションメニューに表示されるはずです。
foxcageをデフォルトのWebブラウザとして設定し、他のアプリケーションでクリックされたリンクがfoxcageで開かれるようにするには:```sh xdg-settings set default-web-browser foxcage.desktop
既存のブラウザでケージが実行中の場合、URLは新しいタブとして開かれます。
元に戻すには:```sh
foxcage --uninstall
StartupNotify=true が .desktop ファイルに設定されており、foxcage の起動中にコンポジタがスピナーカーソルを表示するよう指示します。イメージビルドが必要な場合(数分かかることがあります)、foxcage はデスクトップ通知を送信して、Firefox が起動準備中であることを知らせます。早期終了エラー(設定のタイポ、依存関係の欠落、cage 名の不正など)もデスクトップ通知として表示されるため、ターミナルなしでデスクトップから起動したユーザーが、foxcage が失敗した際に何も表示されずに放置されることはありません。どちらも notify-send(Debian/Ubuntu では libnotify-bin に含まれる)が必要です。インストールされていない場合、通知は静かにスキップされ、エラーは引き続き stderr に出力されます。
.desktop ファイルを手動で作成したい場合は、~/.local/share/applications/foxcage.desktop を作成します:```ini
[Desktop Entry]
Type=Application
Name=FoxCage
Comment=Firefox in a rootless Podman container
Exec=/path/to/foxcage %u
Icon=foxcage
MimeType=text/html;x-scheme-handler/http;x-scheme-handler/https;
Terminal=false
Categories=Network;WebBrowser;
StartupNotify=true
StartupWMClass=foxcage
`/path/to/foxcage` をスクリプトの実際のパスに置き換えてください。登録します:```sh
update-desktop-database ~/.local/share/applications
テストスイートはpytest + pytest-covを使用しており、これらはrequirements-dev.txtで開発専用の依存関係として宣言されています。```
pip install -r requirements-dev.txt
pytest
テストは完全に密閉されています — podman なし、ネットワークなし、pytest の `tmp_path` 以外の実ファイルシステムなし。スイートは**100%の行・ブランチカバレッジ**をゲートとして要求します(`pytest.ini` と `.coveragerc` で設定)。カバーされていない行、または条件分岐の未実行側があると、実行は失敗します。CI は `.gitlab-ci.yml` により、プッシュのたびにスイートを実行します。
## 謝辞
このプロジェクトは Mike Cardwell によって開発され、Anthropic の AI コーディングツールである [Claude Code](https://claude.ai/claude-code) の支援を受けています。
## 私の活動を支援/評価する
- [Bitcoin](bitcoin:1PQLtWnjUi1itHLG6QCQeHM3Nxua8pRsq1): 1PQLtWnjUi1itHLG6QCQeHM3Nxua8pRsq1
- [Paypal](https://www.paypal.me/grepular)
org.mozilla.*org.librewolf.*org.freedesktop.portal.Desktopは全体として許可されています。これはファイルピッカー、「リンクを別のアプリで開く」、画面共有が機能する方法だからです。また、RemoteDesktop(セッション全体の合成キーボード/マウス)、Camera、Locationも公開します。これらはfoxcageではなく、デスクトップ自身の承認ダイアログによってゲートされます。また、RemoteDesktopプロンプトは画面共有プロンプトに似ているため、承認ダイアログを読んでから受け入れてください。xdg-dbus-proxyには「1つのインターフェースを拒否する」ルールがないため、これを狭めるにはFirefoxが必要とするすべてのインターフェースを列挙する必要があります。デフォルトでこれを行わない理由についてはdocs/DESIGN.mdを参照してくださいprofile、downloads_dir、追加の[mounts] bind)はnosuid,noexecを使用gpg --verifyよりも厳格です。gpg --verifyは失効したキーによる署名やキーリング内の任意のキーに対してexit 0を返します。foxcageはさらに、署名が固定されたプライマリキーにチェーンすることを要求し、所有者が侵害されたとして失効させたサブキーによって署名されたリリースを拒否します — 失効した署名キーを参照--rm)— ファイルシステムへの書き込みは終了時に失われます