# NR4Me NR4Me は、Ubuntu サーバーでニュースを収集し、必要なときだけ Windows GPU の ローカル LLM で分類・日本語要約する、個人用セルフホストニュースリーダーです。 原題・原文を保持し、Yes / No 評価を重要度へ小さく反映します。 ## 構成 - Ubuntu: Miniflux、PostgreSQL、NR4Me、SQLite、Web UI - Windows: `llama.cpp` server と `nr4me-worker` - 通信: Tailscale Tailnet 内だけ - 基準モデル: `unsloth/Qwen3.5-9B-GGUF:UD-Q4_K_XL` ## 初回セットアップ(Ubuntu) Docker Engine、Compose plugin、Tailscale を用意します。 ```bash git clone ~/nr4me cd ~/nr4me umask 077 nano .env ``` `.env` に次を設定します。値は Git やチャットへ保存しません。 ```dotenv POSTGRES_PASSWORD=<ランダムな値> MINIFLUX_ADMIN_PASSWORD=<ランダムな値> NR4ME_BIND_ADDRESS= MINIFLUX_BIND_PORT=8082 NR4ME_MINIFLUX_WEBHOOK_SECRET=bootstrap-placeholder NR4ME_WORKER_API_TOKEN=<ランダムな値> NR4ME_MINIFLUX_API_TOKEN=bootstrap-placeholder ``` 最初に Miniflux だけを起動します。 ```bash docker compose up -d miniflux-db miniflux docker compose ps ``` `http://:8082` で Miniflux にログインし、Settings → API Keys から NR4Me 用 API キーを作成します。その値で `.env` の `NR4ME_MINIFLUX_API_TOKEN` を置き換えてから、全サービスを起動します。 ```bash docker compose up -d --build docker compose ps ``` NR4Me は `http://:8787` で利用できます。公開範囲を広げないため、 `NR4ME_BIND_ADDRESS` に `0.0.0.0` や LAN IP は指定しません。 ## 情報源と同期 Miniflux でカテゴリと購読を管理します。NR4Me の「情報源」画面では、Miniflux カテゴリを選択して購読を追加できます。 「今すぐ同期」は Miniflux API から既存記事を取り込みます。初回同期後の新着は、 Miniflux Webhook で通知できます。Webhookの取りこぼしは、NR4Meが既定10分間隔で 実行するAPI差分同期によって回収します。 - URL: `http://nr4me-server:8000/api/v1/ingest/miniflux/webhook` - イベント: `new_entries` - secret: Minifluxが自動生成するWebhook secret Minifluxの「Settings → Integrations → Webhook」を開き、上記URLを保存します。 表示された自動生成secretを`.env`の`NR4ME_MINIFLUX_WEBHOOK_SECRET`へコピーし、 NR4Meサーバーへ反映します。独自に生成した値では署名が一致しません。 ```bash docker compose up -d --force-recreate nr4me-server docker compose logs --tail=100 nr4me-server ``` 確認するには、Minifluxへ試験用Feedを追加して更新し、NR4Meの「情報源」に記事が 現れることを確認します。届かない場合はMinifluxと`nr4me-server`のログを確認し、 Webhook URL、`X-Miniflux-Signature`の検証失敗、secretの転記ミスを調べます。 取り込み対象は既定で過去30日です。`NR4ME_MINIFLUX_MAX_ARTICLE_AGE_DAYS` で変更できます。 定期同期の間隔は `NR4ME_MINIFLUX_SYNC_INTERVAL_SECONDS` で変更でき、 `NR4ME_MINIFLUX_PERIODIC_SYNC_ENABLED=false` で無効化できます。 ## Windows GPU ワーカー Python 3.12以降、Git、CUDA対応版の`llama.cpp`を用意します。`llama-server.exe`を PATHへ追加するか、実行ファイルの絶対パスを控えてください。基準モデルのGGUFも Windows上の任意の場所へ保存します。モデルと秘密値はリポジトリへコミットしません。 Windows PCにリポジトリがない場合はcloneし、仮想環境へWorkerをインストールします。 ```powershell git clone "$HOME\nr4me" Set-Location "$HOME\nr4me" py -3.12 -m venv .venv .\.venv\Scripts\Activate.ps1 python -m pip install --upgrade pip python -m pip install -e . nr4me-worker --help ``` PowerShellが仮想環境の有効化を拒否する場合は、そのPowerShellプロセスだけ実行 ポリシーを緩和してから再実行します。 ```powershell Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass .\.venv\Scripts\Activate.ps1 ``` 手動で推論する場合は、まず接続・DB・トークン・LLMを確認してから、少数件で 開始します。`--dry-run` はキューを変更しません。 事前に Windows の PowerShell で仮想環境を有効化し、サーバー URL、Worker token、 ローカル LLM の OpenAI 互換 URL とモデル名を環境変数へ設定します。`llama-server` は別ターミナルで起動するか、モデルパスを指定して管理スクリプトから起動します。 ```powershell .\.venv\Scripts\Activate.ps1 $env:NR4ME_SERVER_URL = "http://:8787" $env:NR4ME_WORKER_API_TOKEN = "<.env と同じ値>" $env:NR4ME_LLM_PROVIDER = "openai_compatible" $env:NR4ME_LLM_BASE_URL = "http://127.0.0.1:8080/v1" $env:NR4ME_LLM_API_KEY = "local-only" $env:NR4ME_LLM_MODEL = "qwen3.5-9b-q4" ``` 別のPowerShellを開き、リポジトリへ移動して`llama-server`を起動します。PATHへ 追加していない場合は、`start-llama-server.ps1`内の呼び出しを行う前に `llama-server.exe`のディレクトリをPATHへ追加してください。 ```powershell Set-Location "$HOME\nr4me" .\scripts\start-llama-server.ps1 ` -ModelPath "C:\path\to\Qwen3.5-9B-UD-Q4_K_XL.gguf" ``` 最初のPowerShellへ戻り、診断と推論を順番に実行します。 ```powershell nr4me-worker doctor nr4me-worker run --limit 10 --dry-run nr4me-worker run --limit 10 ``` `doctor` はサーバー到達性、DB migration、Worker token、LLM ヘルスを確認します。 すべてが `ok: true` であることを確認してください。`--dry-run` は処理対象候補を 表示するだけで、ジョブをリースしません。最後のコマンドは最大10件を実際に リース・推論・保存します。完了後は NR4Me の「推論キュー」で pending / failed / dead の件数を確認します。LLM が未起動または不健康な場合、ワーカーはジョブをリースせず 終了します。推論を中断する場合はWorker側、LLMを停止する場合は`llama-server`側の PowerShellでそれぞれ`Ctrl+C`を押します。 LLM起動から診断・Worker実行までをまとめて管理する場合は、次のスクリプトを使用 します。`start`は`llama-server`を起動した後、診断に成功した場合だけWorkerを1回 実行します。手動の`nr4me-worker run`と同時には使用しません。 ```powershell .\scripts\manage-gpu-worker.ps1 start ` -ModelPath "C:\path\to\Qwen3.5-9B-UD-Q4_K_XL.gguf" ` -LlamaServerPath "C:\path\to\llama-server.exe" ` -WorkerCommand "$PWD\.venv\Scripts\nr4me-worker.exe" .\scripts\manage-gpu-worker.ps1 stop .\scripts\manage-gpu-worker.ps1 install-task ` -ModelPath "C:\path\to\Qwen3.5-9B-UD-Q4_K_XL.gguf" ` -LlamaServerPath "C:\path\to\llama-server.exe" ` -WorkerCommand "$PWD\.venv\Scripts\nr4me-worker.exe" .\scripts\manage-gpu-worker.ps1 status .\scripts\manage-gpu-worker.ps1 logs ``` 管理スクリプトの状態ファイルとログは `%LOCALAPPDATA%\NR4Me` に保存されます。 `llama-server` とWorkerの標準出力・標準エラーは別々のログファイルへ記録されます。 ログオン時タスクではPowerShellの一時的な`$env:`設定を引き継げないため、 `config\worker.env.example`を`%LOCALAPPDATA%\NR4Me\worker.env`へコピーし、 プレースホルダーを実値へ置き換えてください。このファイルはGit管理外に置きます。 ```powershell $workerConfigDirectory = Join-Path $env:LOCALAPPDATA "NR4Me" New-Item -ItemType Directory -Force $workerConfigDirectory | Out-Null Copy-Item .\config\worker.env.example ` (Join-Path $workerConfigDirectory "worker.env") notepad (Join-Path $workerConfigDirectory "worker.env") ``` 管理スクリプトは起動時にこのファイルを現在のプロセスだけへ読み込みます。別の場所を 使う場合は`-EnvironmentFile`で指定してください。 ## バックアップ ```bash ./scripts/backup.sh ./scripts/restore-test.sh /data/backups/ ``` バックアップには NR4Me DB、Miniflux dump、OPML、manifest を含めます。既定では 14 世代を保持します。日次バックアップを有効化する場合は、サービスファイル内の プレースホルダーを現在のリポジトリ絶対パスへ置換してからインストールします。 ```bash repository_root="$(pwd -P)" sed "s|@NR4ME_REPOSITORY_ROOT@|${repository_root}|g" \ systemd/nr4me-backup.service | sudo tee /etc/systemd/system/nr4me-backup.service >/dev/null sudo install -m 0644 systemd/nr4me-backup.timer /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now nr4me-backup.timer systemctl list-timers nr4me-backup.timer ``` タイマーを有効化する前に`./scripts/backup.sh`を手動実行し、成功することを確認して ください。状態とログは`systemctl status nr4me-backup.service`および `journalctl -u nr4me-backup.service`で確認できます。 ## 更新と確認 ```bash cd ~/nr4me git pull --ff-only sudo docker compose up -d --build sudo docker compose ps ``` 画面表示、Miniflux の同期状態、Windows 側の `nr4me-worker doctor` を確認します。 不具合時は `docker compose logs --tail=100 ` で確認してください。 ## 開発 ```powershell python -m pip install -e ".[dev]" pytest ruff check . ``` 設計の詳細は [NR4Me_System_Design.md](NR4Me_System_Design.md) を参照してください。