Wire Newshosting/Tweaknews via secrets-driven configure script, NZBgeek through Prowlarr, and /data/usenet paths for hardlinks with the Arrs.
185 lines
8.6 KiB
Markdown
185 lines
8.6 KiB
Markdown
# Quickstart
|
||
|
||
Homelab host: **`192.168.8.123`** (SER5, Ubuntu 24.04)
|
||
Stack: **`/opt/stack`** · Media: **`/storage`** · User: **`tim`**
|
||
|
||
---
|
||
|
||
## Ansible
|
||
|
||
From a machine with this repo and SSH key `~/.ssh/id_ed25519`:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-galaxy collection install -r requirements.yml
|
||
|
||
ansible-playbook site.yml -K # -K only if sudo still asks once; playbook installs NOPASSWD for tim
|
||
```
|
||
|
||
What it does: OS updates, tools (incl. Microsoft `edit`), Docker, AMD/Vulkan, UFW (LAN only), `/opt/stack` + `/storage`, `.env`, `arr-stack.service`, and **tim** as local admin (passwordless sudo, docker/video/render/…, owns stack + storage, permissive GPU nodes).
|
||
|
||
**Code on the server:** `/opt/stack` is a **git clone** of Forgejo `tim/stack` (`stack_deploy_method: git`).
|
||
Day-to-day updates on ser5:
|
||
|
||
```bash
|
||
ssh tim@192.168.8.123
|
||
cd /opt/stack
|
||
git pull
|
||
docker compose up -d # if compose/images changed
|
||
```
|
||
|
||
Ansible can also refresh code: `ansible-playbook site.yml -K --tags stack,deploy` (runs `git fetch` + checkout).
|
||
Local-only (not in git): `.env`, `config/`, `models/**/*.gguf`, `wireguard/wg0.conf`.
|
||
|
||
**Before first full stack start** (on ser5):
|
||
|
||
```bash
|
||
ssh tim@192.168.8.123
|
||
# new login so docker/video/render groups apply
|
||
cd /opt/stack
|
||
# wireguard/wg0.conf must exist (no IPv6; Endpoint = IP not hostname)
|
||
./scripts/download-bonsai-model.sh # ~7.2 GB GGUF
|
||
docker compose build bonsai
|
||
docker compose up -d
|
||
# or: sudo systemctl enable --now arr-stack
|
||
docker compose ps
|
||
```
|
||
|
||
**Compose GPU notes**
|
||
- Keep `devices`/`group_add` only in `docker-compose.override.yml` (not also in the main file).
|
||
- Use **numeric GIDs** for `group_add`, not names (`video`/`render` fail inside the image). Or omit `group_add` if `/dev/dri` is mode `0666`.
|
||
|
||
|
||
Re-run playbook anytime: `ansible-playbook site.yml -K`
|
||
Tags: `--tags common,docker,amd,firewall,stack`
|
||
|
||
---
|
||
|
||
## Remotes
|
||
|
||
LAN URLs (UFW allows **`192.168.8.0/24`**). Replace host if needed.
|
||
|
||
| Service | URL |
|
||
|---------|-----|
|
||
| Jellyfin | http://192.168.8.123:8096 |
|
||
| qBittorrent | http://192.168.8.123:8080 |
|
||
| Prowlarr | http://192.168.8.123:9696 |
|
||
| Sonarr | http://192.168.8.123:8989 |
|
||
| Radarr | http://192.168.8.123:7878 |
|
||
| Bazarr | http://192.168.8.123:6767 |
|
||
| Lidarr | http://192.168.8.123:8686 |
|
||
| SABnzbd | http://192.168.8.123:8085 |
|
||
| Open WebUI | http://192.168.8.123:3000 |
|
||
| Bonsai API | http://192.168.8.123:8081/v1 |
|
||
| OpenHands | http://192.168.8.123:3001 |
|
||
| **Forgejo** | http://192.168.8.123:3002 |
|
||
| Forgejo Git SSH | `ssh://git@192.168.8.123:2222/user/repo.git` |
|
||
|
||
OpenHands only runs with: `docker compose --profile coding up -d` (or `stack_compose_profiles: [coding]` in Ansible).
|
||
Images are from **GHCR** (`ghcr.io/all-hands-ai/...`); the old `docker.all-hands.dev` host often does not resolve.
|
||
|
||
### Manual config (once)
|
||
|
||
**qBittorrent** — temp password in `docker logs qbittorrent`; user `admin`.
|
||
Advanced → Network interface: `tun0`.
|
||
Depends on **gluetun** healthy. If gluetun is unhealthy with `lookup … i/o timeout`, WireGuard is not passing traffic — usually a **stale Endpoint IP** in `wireguard/wg0.conf`.
|
||
|
||
**Auto-heal:** `scripts/gluetun-endpoint-watch.sh` + systemd timer every **5 minutes** (installed by Ansible). When gluetun is not healthy it: digs `WIREGUARD_ENDPOINT_HOST` → updates `Endpoint` in `wg0.conf` → recreates gluetun → recreates qbittorrent → tests exit IP.
|
||
Manual run: `cd /opt/stack && ./scripts/gluetun-endpoint-watch.sh`
|
||
Logs: `journalctl -u gluetun-endpoint-watch.service -n 50`
|
||
Set host in `.env`: `WIREGUARD_ENDPOINT_HOST=las-183-wg.whiskergalaxy.com`
|
||
|
||
Default save path + categories (WebUI):
|
||
|
||
1. **Tools → Options → Downloads**
|
||
- Default Save Path: `/data/torrents`
|
||
- Keep “Keep incomplete torrents in” off (or a subfolder under `/data/torrents` if you prefer).
|
||
2. **Categories** (same Options → Downloads page, or right‑click empty area in the left “Categories” panel → **Add category**):
|
||
|
||
| Category name | Save path |
|
||
|---------------|-----------|
|
||
| `movies` | `/data/torrents/movies` |
|
||
| `tv` | `/data/torrents/tv` |
|
||
| `music` | `/data/torrents/music` |
|
||
|
||
For each: **Add category** → name exactly `movies` / `tv` / `music` (lowercase, matches Sonarr/Radarr/Lidarr) → set **Save path** to the path above → OK.
|
||
|
||
3. Sonarr/Radarr/Lidarr download-client “Category” fields must match those names so torrents land in the right folder for hardlinks.
|
||
|
||
**Sonarr / Radarr / Lidarr** — Download client qBittorrent: host **`gluetun`**, port **`8080`**, categories `tv` / `movies` / `music`.
|
||
Root folders: `/data/media/tv`, `/data/media/movies`, `/data/media/music` (hardlinks on).
|
||
|
||
**Prowlarr** — Add indexers. Apps: Sonarr `http://sonarr:8989`, Radarr `http://radarr:7878`, Lidarr `http://lidarr:8686` + each API key (*Settings → General*).
|
||
|
||
**FlareSolverr** (Cloudflare / JS challenges for some indexers) — container `flaresolverr` on `arr-net`, no public port by default.
|
||
Prowlarr → **Settings → Indexers** (or **Settings → Connect** / FlareSolverr section depending on version) → add FlareSolverr host:
|
||
|
||
- Host: `http://flaresolverr:8191`
|
||
- Then enable FlareSolverr on indexers that show Cloudflare errors.
|
||
|
||
Does **not** solve every captcha (Turnstile/hCaptcha image puzzles, etc.). Prefer indexers without CF; paid APIs (2captcha / CapSolver) are optional external services, not a free self-hosted magic box.
|
||
|
||
**Bazarr** — Sonarr/Radarr URLs + API keys; paths `/data/media/tv`, `/data/media/movies`.
|
||
|
||
**Jellyfin** — Libraries: Movies `/data/media/movies`, Shows `/data/media/tv`, Music `/data/media/music`.
|
||
|
||
**Open WebUI** — Create admin on first visit. Model connection is pre-set to Bonsai (`http://bonsai:8080/v1`). Enable web search in chat if desired. RAG: Workspace → Knowledge (uploads) or files under `/workspace`.
|
||
|
||
**Bonsai** — No UI login. Smoke test: `curl -s http://192.168.8.123:8081/v1/models`. Needs GGUF in `models/bonsai/` and `docker compose build bonsai` once.
|
||
|
||
**OpenHands** — On the server (`/opt/stack`): `docker compose --profile coding up -d openhands`.
|
||
UI: http://192.168.8.123:3001
|
||
|
||
**LLM (required once)**
|
||
Settings → Advanced: base URL `http://bonsai:8080/v1`, API key `sk-local-bonsai`, model `openai/<id from /v1/models>`.
|
||
|
||
**Connect to Forgejo (pick A and/or B)**
|
||
|
||
**A — Provider (browse / open repos in OpenHands)**
|
||
1. Forgejo → avatar → **Settings → Applications** → generate a token (scopes: `read:repository`, `write:repository`, `read:user` — or full access on a trusted LAN).
|
||
2. OpenHands → **Settings → Git / Integrations** (or **Secrets** / provider list):
|
||
- Provider: **Forgejo** or **Gitea** (same API)
|
||
- Base URL: `http://forgejo:3000` (Docker DNS on `arr-net`; use this from OpenHands)
|
||
From a browser on your PC you use `http://192.168.8.123:3002` — that is *not* what the OpenHands container should use.
|
||
- Token: paste the Forgejo token
|
||
3. Start a conversation → choose repository → `tim/stack`.
|
||
|
||
**B — Workspace mount (most reliable for editing + git push)**
|
||
Compose already mounts `${AI_WORKSPACE_DIR}` (default `/opt/stack/workspace`) into the agent sandbox as `/workspace`.
|
||
On the **server**:
|
||
|
||
```bash
|
||
# HTTPS with token (one-time; token in URL — prefer SSH below)
|
||
# git clone http://tim:TOKEN@192.168.8.123:3002/tim/stack.git /opt/stack/workspace/stack
|
||
|
||
# SSH (key already on Forgejo for user tim)
|
||
git clone ssh://git@192.168.8.123:2222/tim/stack.git /opt/stack/workspace/stack
|
||
```
|
||
|
||
Then in OpenHands: work in `/workspace/stack` (or set the conversation workspace to that path).
|
||
Agent can `git commit` / `git push` if the host clone has credentials (SSH agent or stored remote URL).
|
||
|
||
If OpenHands cannot reach `forgejo` by name, ensure both services are on `arr-net` (`docker compose up -d forgejo openhands`).
|
||
|
||
**Forgejo** — http://192.168.8.123:3002
|
||
If connection refused: crash-loop from dual SSH; compose uses `START_SSH_SERVER=false`. Recreate: `docker compose up -d forgejo --force-recreate`.
|
||
|
||
---
|
||
|
||
## Locals
|
||
|
||
Bound to loopback on the host (not LAN-reachable as published):
|
||
|
||
| Service | URL / path |
|
||
|---------|------------|
|
||
| SearXNG | http://127.0.0.1:8888 |
|
||
|
||
Open WebUI talks to SearXNG on the Docker network (`http://searxng:8080`); you only need the loopback URL for direct browser checks on the server.
|
||
|
||
### Manual config
|
||
|
||
**SearXNG** — None for normal use. Settings: `/opt/stack/searxng/settings.yml`. Secret comes from `.env` (`SEARXNG_SECRET`).
|
||
|
||
**WireGuard** — File only: `/opt/stack/wireguard/wg0.conf` (not a web UI). Must be ready before gluetun is healthy.
|
||
|
||
**Host shell** — `ssh tim@192.168.8.123` · stack logs: `docker compose -f /opt/stack/docker-compose.yml logs -f` · unit: `systemctl status arr-stack`.
|