DockerでHoarderを使ったセルフホスト型ブックマークマネージャー:AIサマリーと全文検索

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

誰も語らないブックマーク問題

「あとで読む」というフォルダに847件のリンクが入っている。いつの間にか「あとで読む」は「永遠に読まない」と同義になってしまった。心当たりがあるだろうか?

本当の問題はリンクを保存することではなく、後から見つけ出すことだ。PocketもブラウザのブックマークもこのUXを解決できていない。Kubernetesのネットワークに関する記事を保存したのは覚えているが、8ヶ月前に「infra」という曖昧なタグで保存したきり。探し出すのはほぼ不可能だ。

Pocketが無料プランを廃止し、Mozillaによる買収で先行きが不透明になったのを機に、保存問題だけでなく検索・取り出し問題を本当に解決できるセルフホスト型の代替を探した。そこで見つけたのがHoarderだ。AIサマリーと全文検索を内蔵したオープンソースのブックマークマネージャーで、Dockerでクリーンに動作する。

3ヶ月間毎日使い続けた結果、あのフォルダは今では本当に役に立っている。セットアップ方法を紹介しよう。

Hoarderが実際にできること

Hoarderは自ら「AIファースト」と称しており、機能一覧はその名に恥じない:

  • 自動コンテンツスクレイピング — ブックマーク時に各ページのスナップショットを保存するため、リンク切れになってもコンテンツは失われない
  • AIによる自動要約 — OpenAIまたはローカルのOllamaモデルを使って各保存ページを要約する
  • 全文検索 — タイトルやURLだけでなく、スクレイピングしたコンテンツの中身まで検索できる
  • 自動タグ付け — AIがコンテンツに基づいてタグを提案する
  • ブラウザ拡張機能 — ChromeとFirefoxの拡張機能でワンクリック保存が可能
  • モバイル対応UI — ネットワーク内のどのデバイスからでもアクセスできる

内部構成はNext.jsフロントエンド、クロール用バックグラウンドワーカー、全文インデックス用のMeilisearch、そしてオプションのAIレイヤーだ。すべてコンテナ化されている。

始める前の前提条件

必要なもの:

  • DockerとDocker Composeがインストール済みのLinuxサーバー(ベアメタルまたはVM
  • 最低2GB RAM — MeilisearchはメモリをよくあそこうするためAIを有効にするなら4GB以上を推奨
  • OpenAI APIキー(オプションだがAI機能には推奨)、またはローカルのOllamaセットアップ
  • HTTPSが必要な場合はドメインまたはローカルDNS — ローカルIPでも問題なく動作する

Docker ComposeでHoarderをセットアップする

作業ディレクトリとComposeファイルを作成する:

mkdir -p ~/homelab/hoarder && cd ~/homelab/hoarder
nano docker-compose.yml

以下の設定を貼り付ける:

version: "3.8"

services:
  web:
    image: ghcr.io/hoarder-app/hoarder:release
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - hoarder_data:/data
    env_file:
      - .env
    depends_on:
      - meilisearch
      - chrome

  meilisearch:
    image: getmeili/meilisearch:v1.6
    restart: unless-stopped
    volumes:
      - meilisearch_data:/meili_data
    environment:
      - MEILI_NO_ANALYTICS=true
      - MEILI_MASTER_KEY=${MEILI_MASTER_KEY}

  chrome:
    image: gcr.io/zenika-hub/alpine-chrome:123
    restart: unless-stopped
    command:
      - --no-sandbox
      - --disable-gpu
      - --disable-dev-shm-usage
      - --remote-debugging-address=0.0.0.0
      - --remote-debugging-port=9222
      - --hide-scrollbars

volumes:
  hoarder_data:
  meilisearch_data:

次に、シークレットを生成して完全な.envファイルを一度に書き出す。これにより重複キーや変数参照の問題を回避できる:

NEXTAUTH_SECRET=$(openssl rand -base64 36)
MEILI_KEY=$(openssl rand -base64 36)

cat > .env << EOF
NEXTAUTH_SECRET=$NEXTAUTH_SECRET
MEILI_MASTER_KEY=$MEILI_KEY
NEXTAUTH_URL=http://YOUR_SERVER_IP:3000
HOARDER_LOG_LEVEL=info
BROWSER_WEB_URL=http://chrome:9222
MEILISEARCH_URL=http://meilisearch:7700
MEILISEARCH_MASTER_KEY=$MEILI_KEY
OPENAI_API_KEY=sk-your-openai-key-here
OPENAI_BASE_URL=https://api.openai.com/v1
# オプション:OpenAIの代わりにローカルのOllamaを使用する
# OLLAMA_BASE_URL=http://YOUR_SERVER_IP:11434
EOF

注意点として、MEILI_MASTER_KEYMEILISEARCH_MASTER_KEYは必ず同じ値にする必要がある。前者はMeilisearch自体の設定で、後者はHoarderのWebサービスがMeilisearchに認証する方法を指定するものだ。上記のスクリプトではこれを自動的に処理している。

すべてを起動する:

docker compose up -d
docker compose logs -f web

初回起動時は30〜60秒ほど待とう。MeilisearchがインデックスをInitializeするのに少し時間がかかる。ログにServer running on port 3000と表示されたら、ブラウザでhttp://YOUR_SERVER_IP:3000を開く。

初回ログインと初期設定

初回起動時、Hoarderはブラウザ上で直接管理者アカウントを作成できる。特に外部公開を予定している場合は強力なパスワードを使用すること。

ログイン後、設定 → AIに移動してOpenAIキーが認識されていることを確認する。テスト用のブックマークを保存して以下を確認しよう:

  1. ページコンテンツがスクレイピングされている(ブックマークの「キャッシュ」タブで確認)
  2. 1〜2分以内に要約が表示される
  3. タグが自動提案される

要約が表示されない場合はワーカーのログを確認する:

docker compose logs web | grep -i "openai\|summary\|error"

OpenAIの代わりにOllamaを使う

すでにHomeLab上でOllamaを動かしているなら、.envのAI設定を切り替えよう:

# OpenAIをコメントアウト
# OPENAI_API_KEY=...

# Ollamaを追加
OLLAMA_BASE_URL=http://YOUR_OLLAMA_HOST:11434
OLLAMA_MODEL=llama3.2

変更後はスタックを再起動する:

docker compose restart web

Ollamaは要約処理を十分にこなせる。自動タグ付けの精度については、llama3.2mistralが無難な結果を出す。GPT-4の品質には及ばないが、無料でプライベートな環境としては十分すぎるほどだ。

ブラウザ拡張機能のインストール

ブラウザ拡張機能こそがHoarderを日常的に使えるものにする要素だ。これがなければURLを手動でコピーするしかなく、本末転倒になってしまう。

  1. Chrome ウェブストアまたはFirefoxアドオンで「Hoarder」を検索する
  2. インストール後、拡張機能のアイコンをクリック → 設定
  3. サーバーURLにHoarderのアドレスを設定する:http://YOUR_SERVER_IP:3000
  4. Hoarderで APIキーを生成する:設定 → APIキー → 新しいキー
  5. 拡張機能の設定にAPIキーを貼り付ける

これ以降はワンクリックで保存できる。拡張機能はAIサマリーが生成されるとプレビューも表示してくれる。

毎日使って気づいた実践的なコツ

検索こそが最大の武器

ブックマークリストを眺めるのはやめよう。検索するだけでいい。Hoarderはページの全コンテンツをインデックス化するため、どこに保存したか忘れても読んだ内容のキーワードで見つけられる。記事本文の数単語を入力するだけで、Meilisearchがタイポも補正しながら検索してくれる。

進行中のプロジェクトにはリストを活用する

Hoarderの「リスト」機能は継続的な作業においてフォルダよりも優れている。アクティブなプロジェクトごとにリストを作成し、関連するブックマークを追加して、プロジェクト終了後はリストをアーカイブする。全体のブックマーク数を管理しやすい状態に保てる。

リモートアクセス用にリバースプロキシを設定する

自宅ネットワークの外からHoarderにアクセスしたいなら、Nginx Proxy ManagerやCaddyでHTTPSと合わせて配置しよう。最小限のCaddy設定例:

hoarder.yourdomain.com {
    reverse_proxy localhost:3000
}

HTTPSなしで公開してはいけない。そのままでは APIキーもブックマークも平文で通信されてしまう。

データボリュームをバックアップする

スクレイピングされたコンテンツは急速に蓄積される。私の環境では2ヶ月で約2GBに達した。両方のボリュームを定期的にバックアップしよう

# バックアップスクリプト — cronに追加する
docker run --rm \
  -v hoarder_hoarder_data:/source:ro \
  -v /backup/hoarder:/backup \
  alpine tar czf /backup/hoarder_data_$(date +%Y%m%d).tar.gz -C /source .

docker run --rm \
  -v hoarder_meilisearch_data:/source:ro \
  -v /backup/hoarder:/backup \
  alpine tar czf /backup/meili_data_$(date +%Y%m%d).tar.gz -C /source .

Hoarderをアップデートする

docker compose pull
docker compose up -d

Hoarderは安定版リリースを追跡するreleaseタグを使用している。変更内容を確認したい場合はpullする前にGitHubのリリースページを確認しよう。

まとめ

3ヶ月間毎日使い続けた結果、あの「あとで読む」フォルダは今では本当に役立つツールになった。全文検索とAIサマリーの組み合わせは、保存コンテンツとの向き合い方を根本から変える。ただリンクを溜め込む場所ではなく、実際にクエリを投げられるナレッジベースへと変わるのだ。

セットアップにかかる時間は約20分。私の環境ではAIなしでアイドル時のRAM使用量は約400MB、Ollama起動時は約900MBだ。アップデートとバックアップは他のHomeLab上のサービスと同じパターンに従う — docker compose pull一発と、cronで定期実行するボリュームバックアップだけだ。

まだブラウザのブックマークや先行きの怪しいクラウドサービスに頼っているなら、半日かけてでも試してみる価値は十分にある。

Share: