diff --git a/README.md b/README.md index 96734df8..d5891406 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ The installer will: > **Monitoring**: After installation, open `https://monitoring.your-domain.com` right away. It is protected by basic auth (user `admin`, password shown at the end of the install); behind it, the first visitor creates the Beszel admin account. > -> Then pair the agent once: in Beszel, click **Add system**, use host `/beszel_socket/beszel.sock`, copy the public key and token into `.env` as `BESZEL_AGENT_KEY` and `BESZEL_AGENT_TOKEN`, add `COMPOSE_PROFILES=monitoring`, and run `docker compose -f docker-compose.prod.yml up -d`. See the [Monitoring guide](https://florianjs.github.io/trackarr/guide/monitoring). +> Then pair the agent once: in Beszel, click **Add system** with host `/beszel_socket/beszel.sock`, then run `sudo ./scripts/pair-monitoring.sh` on the server and paste the public key and token it shows. Step by step in the [Monitoring guide](https://florianjs.github.io/trackarr/guide/monitoring#pairing-the-agent). > > Application and tracker figures (growth charts, tracker health, security alerts) are in the Trackarr admin dashboard. diff --git a/doc/guide/monitoring.md b/doc/guide/monitoring.md index 0f67f262..22e4f91b 100644 --- a/doc/guide/monitoring.md +++ b/doc/guide/monitoring.md @@ -30,24 +30,68 @@ In production, Caddy puts basic auth in front of Beszel (`MONITORING_USER` / `MO ### Pairing the agent -Do this once, after the first start (or after upgrading from Grafana): +Do this once, after the first install (or after upgrading from Grafana). It connects the agent, which collects the stats, to the Beszel web UI. Until then, Beszel shows no system. -1. Open the monitoring URL **right away**: the first visitor creates the Beszel admin account, which is why basic auth stays in front of it. -2. Create the admin account. -3. Click **Add system** and use `/beszel_socket/beszel.sock` as the host. -4. Copy the public key and token shown into `.env`, and enable the profile: +You need two windows: a **browser** for Beszel, and a **terminal on the server** for the agent. - ```bash - BESZEL_AGENT_KEY= - BESZEL_AGENT_TOKEN= - COMPOSE_PROFILES=monitoring - ``` +#### 1. Create the Beszel admin account -5. Start the agent: +Open `https://monitoring.your-domain.com` **right away**: the first visitor creates the Beszel admin account. - ```bash - docker compose -f docker-compose.prod.yml up -d - ``` +1. The browser first asks for the basic auth login: user `admin`, and the monitoring password shown at the end of the install. +2. Beszel then asks you to create its own admin account (email and password). Keep them: this is your Beszel login from now on. + +#### 2. Add the server in Beszel + +1. Click **Add system** (top right). +2. Fill in the form: + + | Field | Value | + | --------- | ---------------------------- | + | Name | anything, e.g. `trackarr` | + | Host / IP | `/beszel_socket/beszel.sock` | + + The host is a socket shared by the two containers, not an address: the **Port** field disappears once you type it. +3. Below, the dialog shows a **public key** (starts with `ssh-ed25519`) and a **token**, each with a copy button. You will paste them on the server in the next step. +4. Click **Add system**. The system appears with a yellow dot: it is waiting for the agent. + +#### 3. Start the agent on the server + +Connect to the server and go to the Trackarr directory (`/opt/trackarr` when installed with `install.sh`): + +```bash +ssh root@your-server +cd /opt/trackarr +sudo ./scripts/pair-monitoring.sh +``` + +Paste the public key, then the token, when asked. The script writes them to `.env`, turns the monitoring profile on, starts the agent and checks it stays up. + +The dot turns green in Beszel within a minute. + +::: details Doing it by hand instead +Open `.env` in the Trackarr directory (`nano .env`). The installer left three commented lines for the agent: uncomment them and fill in the values, without quotes: + +```bash +BESZEL_AGENT_KEY=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... +BESZEL_AGENT_TOKEN=0d1e2f3a-... +COMPOSE_PROFILES=monitoring +``` + +Save (Ctrl+O, Enter, Ctrl+X in nano), then start the agent: + +```bash +docker compose -f docker-compose.prod.yml up -d +``` +::: + +For the local production stack, run `./scripts/pair-monitoring.sh --local` (it uses `.env.local-prod`). + +#### If the dot does not turn green + +- Check the agent: `docker compose -f docker-compose.prod.yml ps beszel-agent` should say `running`. +- Read its logs: `docker compose -f docker-compose.prod.yml logs beszel-agent`. A key or token error means a copy/paste mistake: run the script again with the values from Beszel. To see them again, click **⋯** at the end of the system's row, then **Edit**. +- More cases in [Troubleshooting](/guide/troubleshooting). The installers keep `BESZEL_AGENT_KEY`, `BESZEL_AGENT_TOKEN` and `COMPOSE_PROFILES` when you re-run them. diff --git a/doc/guide/troubleshooting.md b/doc/guide/troubleshooting.md index 731272f0..1636e233 100644 --- a/doc/guide/troubleshooting.md +++ b/doc/guide/troubleshooting.md @@ -323,7 +323,7 @@ e21V5@postgres:5432/trackarr = host=postgres port=5432 auth_user=tracker **Solutions:** -1. Pair the agent as described in [Monitoring](/guide/monitoring#pairing-the-agent) (host `/beszel_socket/beszel.sock`), and check `.env`: +1. Pair the agent as described in [Monitoring](/guide/monitoring#pairing-the-agent): add the system in Beszel (host `/beszel_socket/beszel.sock`), then run `sudo ./scripts/pair-monitoring.sh` in the Trackarr directory. It writes these lines to `.env`: ``` BESZEL_AGENT_KEY=... diff --git a/scripts/install.sh b/scripts/install.sh index 02149e32..3fed3b6e 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -734,7 +734,9 @@ print_summary() { echo -e " 2. Monitoring is paired and running." else echo -e " 2. Open ${CYAN}https://${MONITORING_DOMAIN}${NC} now: the first visitor creates the" - echo -e " Beszel admin. Then pair this server: ${CYAN}${DOCS_URL}/guide/monitoring${NC}" + echo -e " Beszel admin. Click Add system, host ${CYAN}/beszel_socket/beszel.sock${NC}, then run" + echo -e " ${CYAN}sudo ${INSTALL_DIR}/scripts/pair-monitoring.sh${NC} and paste the key and token." + echo -e " Step by step: ${CYAN}${DOCS_URL}/guide/monitoring#pairing-the-agent${NC}" fi echo "" echo -e " ${BOLD}Useful commands${NC} (in ${INSTALL_DIR})" diff --git a/scripts/pair-monitoring.sh b/scripts/pair-monitoring.sh new file mode 100755 index 00000000..ecd13ae5 --- /dev/null +++ b/scripts/pair-monitoring.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# ============================================================================= +# Trackarr - Pair the Beszel agent +# ============================================================================= +# Asks for the public key and token shown by Beszel's "Add system" dialog, +# writes them to .env, enables the monitoring profile and starts the agent. +# +# Usage: sudo ./scripts/pair-monitoring.sh [--local] +# --local local production stack (docker-compose.local.yml, .env.local-prod) +# +# Unattended: BESZEL_AGENT_KEY=... BESZEL_AGENT_TOKEN=... ./scripts/pair-monitoring.sh +# ============================================================================= + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +BOLD='\033[1m' +NC='\033[0m' + +ok() { echo -e " ${GREEN}✓${NC} $1"; } +warn() { echo -e " ${YELLOW}!${NC} $1"; } +die() { echo -e " ${RED}✗${NC} $1" >&2; exit 1; } + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +ENV_FILE="$PROJECT_DIR/.env" +COMPOSE_FILE="docker-compose.prod.yml" + +case "${1:-}" in + --local) + COMPOSE_FILE="docker-compose.local.yml" + ENV_FILE="$PROJECT_DIR/.env.local-prod" + ;; + -h|--help) sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; + "") ;; + *) die "Unknown option: $1 (see --help)" ;; +esac + +[[ -f $ENV_FILE ]] || die "$ENV_FILE not found: run the installer first" +COMPOSE=(docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE") +LOGS_CMD="${COMPOSE[*]} logs beszel-agent" +[[ -w $ENV_FILE && -w $PROJECT_DIR ]] || die "Cannot write $ENV_FILE: run with sudo" +command -v docker >/dev/null || die "Docker is not installed" + +# Replace KEY=... (or a commented # KEY=...) in .env, or append it. +# Written to a copy next to .env, then renamed over it: a failed write +# (full disk) never leaves a truncated .env, which holds every secret +set_env() { + local key=$1 value=$2 tmp + tmp=$(mktemp "$ENV_FILE.XXXXXX") + if ! awk -v k="$key" -v v="$value" ' + $0 ~ "^#? *" k "=" { if (!done) print k "=" v; done = 1; next } + { print } + END { if (!done) print k "=" v } + ' "$ENV_FILE" > "$tmp"; then + rm -f "$tmp" + die "Could not update $ENV_FILE (disk full?): it was left unchanged" + fi + # Keep the original mode and owner (GNU stat, then BSD stat) + chmod "$(stat -c %a "$ENV_FILE" 2>/dev/null || stat -f %Lp "$ENV_FILE")" "$tmp" + chown "$(stat -c %u:%g "$ENV_FILE" 2>/dev/null || stat -f %u:%g "$ENV_FILE")" "$tmp" 2>/dev/null || true + mv -f "$tmp" "$ENV_FILE" +} + +current_value() { + grep -m1 "^$1=" "$ENV_FILE" | cut -d= -f2- || true +} + +echo "" +echo -e " ${BOLD}Trackarr · pair the monitoring agent${NC}" +echo "" +echo " In Beszel: Add system, host /beszel_socket/beszel.sock, then copy the" +echo " public key and the token the dialog shows." +echo "" + +KEY=${BESZEL_AGENT_KEY:-} +TOKEN=${BESZEL_AGENT_TOKEN:-} +while [[ ! $KEY =~ ^ssh-ed25519\ [A-Za-z0-9+/=]+$ ]]; do + [[ -n $KEY ]] && warn "That is not a Beszel public key (it starts with ssh-ed25519)" + read -rp " Public key: " KEY \ + || die "No input: unattended, set BESZEL_AGENT_KEY and BESZEL_AGENT_TOKEN to valid values" + KEY=$(echo "$KEY" | xargs) +done +while [[ ! $TOKEN =~ ^[A-Za-z0-9_-]+$ ]]; do + [[ -n $TOKEN ]] && warn "That token contains unexpected characters" + read -rp " Token: " TOKEN \ + || die "No input: unattended, set BESZEL_AGENT_KEY and BESZEL_AGENT_TOKEN to valid values" + TOKEN=$(echo "$TOKEN" | xargs) +done + +set_env BESZEL_AGENT_KEY "$KEY" +set_env BESZEL_AGENT_TOKEN "$TOKEN" +profiles=$(current_value COMPOSE_PROFILES) +if [[ ,$profiles, != *,monitoring,* ]]; then + set_env COMPOSE_PROFILES "${profiles:+$profiles,}monitoring" +fi +ok "Key, token and monitoring profile saved in $ENV_FILE" + +cd "$PROJECT_DIR" +"${COMPOSE[@]}" up -d --force-recreate beszel-agent docker-proxy >/dev/null 2>&1 \ + || die "Could not start the agent: $LOGS_CMD" + +# The agent exits right away when the key is wrong: give it a moment +sleep 5 +if [[ $(docker inspect -f '{{.State.Running}}' trackarr-beszel-agent 2>/dev/null) == true ]]; then + ok "Agent running" + echo "" + echo " The system turns green in Beszel within a minute. If it does not," + echo -e " check the key and token, then: ${CYAN}${LOGS_CMD}${NC}" + echo "" +else + "${COMPOSE[@]}" logs --tail 20 beszel-agent >&2 || true + die "The agent stopped: check the key and token, then run this script again" +fi