diff --git a/README.md b/README.md index 03af2e1..5745733 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,24 @@ the pipeline rules, and prints the admin credentials at the end. Both scripts are idempotent — re-running after a failure (or to apply an update) picks up from where it left off instead of duplicating work. +## Ways to run this + +Four ways to apply this project, from "type one command" to "click a +button in a browser" - pick whichever fits what changed and how much +setup you're willing to do first. + +| Way | Run from | What it does | One-time setup | When to use | +|---|---|---|---|---| +| **Manual, full** | terminal on the Proxmox host | `create-graylog-lxc.sh` → creates/repairs the LXC container, installs everything | none | first-ever deploy, or when you'd rather watch it happen | +| **Manual, config-only** | terminal, `pct exec` into the container | re-run `install-graylog.sh` directly | none | quick config-only fix without touching git | +| **CI, config-only** | Forgejo web UI | workflow `deploy.yml` → re-runs `install-graylog.sh` from the latest git commit | `setup-forgejo-runner.sh` *inside the container* (see step 9) | pushed a new rule/alert/dashboard, container already exists | +| **CI, full** | Forgejo web UI | workflow `deploy-from-scratch.yml` → runs `create-graylog-lxc.sh` from the latest git commit | `setup-forgejo-runner.sh` *on the Proxmox host* (see step 9) | one-click recreate after a manual `pct destroy`, no terminal needed | + +All four end up running the exact same idempotent scripts - there's no +"CI-only" behavior to diverge from what you'd type by hand. Neither CI +workflow runs `pct destroy` - that's always a deliberate, manual step (see +"CI/CD via Forgejo Actions" below for why). + ## Step-by-step deployment from scratch ### 0. Prerequisites @@ -187,27 +205,55 @@ Discord within about a minute. ### 9. (Optional) Set up Forgejo Actions CI -If you push this project to a Forgejo instance, `setup-forgejo-runner.sh` -registers a self-hosted Actions runner inside the container itself, so -`.forgejo/workflows/deploy.yml` can re-run `install-graylog.sh` on demand -straight from git instead of scp'ing files by hand. See "CI/CD via Forgejo -Actions" further down for what the workflow does and how to trigger it; -this step is just the one-time runner setup. +`setup-forgejo-runner.sh` registers a self-hosted Actions runner - it can +run in two different places, one script for both, just different +parameters. See "CI/CD via Forgejo Actions" further down for what each +workflow does; this step is just the one-time runner setup. Both are +optional and independent - set up either, neither, or both. -1. In the Forgejo web UI: repo → Settings → Actions → Runners → "Create - new Runner" to get a registration token (one-time value, not something - to guess or reuse from another repo). -2. Run the setup script inside the container: - ```bash - pct exec -- env \ - FORGEJO_URL="https://your-forgejo-instance" \ - FORGEJO_RUNNER_TOKEN="" \ - bash /opt/graylog-deploy/setup-forgejo-runner.sh - ``` -3. Add the two secrets the workflow needs (repo → Settings → Actions → - Secrets): `GRAYLOG_ADMIN_PASSWORD` and `DISCORD_WEBHOOK_URL`. A third - value, `secrets.GITHUB_TOKEN`, doesn't need creating - Forgejo issues it - automatically per job, scoped to just this repo. +**Shared first step:** repo → Settings → Actions → Runners → "Create new +Runner" to get a registration token (one-time value, not something to +guess or reuse from another repo - get a fresh one for each runner you +register). + +**9a. Runner inside the container** (for `deploy.yml` - config-only +redeploys): +```bash +pct exec -- env \ + FORGEJO_URL="https://your-forgejo-instance" \ + FORGEJO_RUNNER_TOKEN="" \ + bash /opt/graylog-deploy/setup-forgejo-runner.sh +``` + +**9b. Runner on the Proxmox host itself** (for `deploy-from-scratch.yml` - +full recreate). `git` must be installed on the host first (`apt-get +install -y git` - the container has it, the bare host usually doesn't). +`RUNNER_USER=claude-deploy` is required here, not optional: without it the +systemd service runs as root, handing every CI job unrestricted root on +the host instead of claude-deploy's narrowly-scoped sudo: +```bash +sudo env FORGEJO_URL="https://your-forgejo-instance" FORGEJO_RUNNER_TOKEN="" RUNNER_NAME="proxmox-host-runner" RUNNER_LABEL="proxmox-host:host" RUNNER_DIR="/opt/forgejo-runner-host" SERVICE_NAME="forgejo-runner-host" RUNNER_USER="claude-deploy" bash /home/claude-deploy/graylog-deploy/setup-forgejo-runner.sh +``` +(One line, no `\` continuations - multi-line pastes with backslashes have +been observed dropping the continuation in some terminals, silently +running `sudo env` with no arguments and none of the variables set.) + +**9c. Secrets** the workflows need (repo → Settings → Actions → Secrets): +`GRAYLOG_ADMIN_PASSWORD` and `DISCORD_WEBHOOK_URL`. A third value, +`secrets.GITHUB_TOKEN`, doesn't need creating - Forgejo issues it +automatically per job, scoped to just this repo. + +**Removing a runner later** (e.g. the host-level one, if you'd rather not +leave it registered when not actively deploying): +```bash +sudo systemctl disable --now forgejo-runner-host +sudo rm -f /etc/systemd/system/forgejo-runner-host.service +sudo systemctl daemon-reload +sudo rm -rf /opt/forgejo-runner-host +``` +then delete it from repo → Settings → Actions → Runners in the UI too. +Re-registering later needs a fresh token from that same page - the old +one won't be reused automatically. ## Parameters @@ -538,29 +584,59 @@ channel. ## CI/CD via Forgejo Actions This project's Forgejo repo (`git.zotac.keenetic.link/zotac/graylog-deploy`) -has a manually-triggered deploy workflow: `.forgejo/workflows/deploy.yml`. -Running it clones the repo fresh and re-runs `install-graylog.sh` - the -same idempotent script described throughout this README, just automated -instead of scp'd by hand. One-time setup is `setup-forgejo-runner.sh` -(see step 9 above); this section covers what the workflow does and how to -run it day to day. +has two manually-triggered workflows, each with its own runner (see step 9 +above for setup). Both just automate scripts already described elsewhere +in this README - there's nothing CI-specific about their actual behavior. + +### `deploy.yml` — config-only redeploy + +Clones the repo fresh and re-runs `install-graylog.sh` inside the +container. Use this after pushing a new rule/alert/dashboard/pipeline +change to an already-existing container. **Running it:** repo → **Actions** tab → **Deploy Graylog config** in the -left sidebar → **Run workflow** button → confirm. Progress and per-step -logs show up immediately under the run list. +left sidebar → **Run workflow** button → confirm. -- **Trigger is manual on purpose** (`workflow_dispatch` only, no - `on: push`) - this repo drives a production monitoring system, so a - human reviews the diff and clicks "Run workflow" rather than every push - silently redeploying. - **The runner lives inside the Graylog container itself** (VMID 200, `self-hosted:host` label, installed at `/usr/local/bin/forgejo-runner`, running as a systemd service). No new SSH keys or cross-host access were needed - the workflow just clones the repo into `/tmp/graylog-deploy-ci` and runs the script locally, exactly like a human operator would. -- **No `actions/checkout`** - that action needs Node.js, which this - appliance container doesn't have and shouldn't need just for CI. The - workflow does a plain `git clone --depth 1` instead. + +### `deploy-from-scratch.yml` — full recreate + +Clones the repo fresh and re-runs `create-graylog-lxc.sh` **on the Proxmox +host**. Use this after a manual `pct destroy` (or on a container that was +never created), when you'd rather click a button than type the full +`create-graylog-lxc.sh` invocation. + +**Running it:** repo → **Actions** tab → **Deploy Graylog from scratch +(host-level)** in the left sidebar → **Run workflow** button → confirm. + +- **The runner lives on the Proxmox host itself**, running as + `claude-deploy` (not root - see step 9b above for why that matters), + registered with a distinct label (`proxmox-host:host`) so it only picks + up jobs meant for this workflow, not `deploy.yml`'s. +- **`pct destroy` is deliberately NOT part of this workflow.** Recreating + infrastructure automatically is fine because `create-graylog-lxc.sh` is + idempotent (repairs in place if the container already exists, creates + fresh if it doesn't); destroying it is irreversible data loss and stays + a human typing the command on purpose. A CI button that can destroy + production with one accidental click was considered and rejected. + `pct destroy` isn't even in `claude-deploy`'s sudo scope, on purpose. +- **`git` must be installed on the bare host** - unlike the container + (which has it from the Debian 12 template), a fresh Proxmox host + usually doesn't (`apt-get install -y git`, one-time, root). + +### Common to both workflows + +- **Trigger is manual on purpose** (`workflow_dispatch` only, no + `on: push`) - these drive a production monitoring system, so a human + reviews the diff and clicks "Run workflow" rather than every push + silently redeploying. +- **No `actions/checkout`** - that action needs Node.js, which neither + runner has and shouldn't need just for CI. Both workflows do a plain + `git clone --depth 1` instead. - **The clone is authenticated with `secrets.GITHUB_TOKEN`** - a short-lived token Forgejo creates automatically at the start of each workflow run and destroys when it finishes, scoped to only this repo @@ -572,7 +648,7 @@ logs show up immediately under the run list. - **Secrets** (`GRAYLOG_ADMIN_PASSWORD`, `DISCORD_WEBHOOK_URL`) are stored as repo-level Forgejo Actions secrets, not in any tracked file. `GRAYLOG_EXTERNAL_URI` isn't secret (it's the public Web UI address) so - it's inlined directly in the workflow. + it's inlined directly in both workflows. ## What's still NOT included @@ -594,13 +670,22 @@ ones were built. ## File layout ``` -create-graylog-lxc.sh # run on the Proxmox host -install-graylog.sh # run inside the container (invoked automatically) -docker-compose.yml # MongoDB + OpenSearch + Graylog stack definition -nftables.conf # firewall ruleset applied inside the container -rules/*.json # Graylog Pipeline Rule definitions (imported via API) -pipelines/*.json # Graylog Pipeline definitions referencing the rules -streams/*.json # Graylog Stream definitions (routes by input port) +create-graylog-lxc.sh # run on the Proxmox host - creates/repairs the LXC container +install-graylog.sh # run inside the container (invoked automatically) +bootstrap-host.sh # one-time, root, Proxmox host - automates the AppArmor fix +cleanup-host.sh # reverses bootstrap-host.sh +fix-lxc-apparmor.sh # installed by bootstrap-host.sh, not run directly +setup-forgejo-runner.sh # registers a CI runner - in the container or on the host +docker-compose.yml # MongoDB + OpenSearch + Graylog stack definition +nftables.conf # firewall ruleset applied inside the container +rules/*.json # Graylog Pipeline Rule definitions (imported via API) +pipelines/*.json # Graylog Pipeline definitions referencing the rules +streams/*.json # Graylog Stream definitions (routes by input port) +alerts/*.json # Event Definitions + the Discord notification template +dashboards/search_*.json # Views API search objects, one pair per dashboard +dashboards/view_*.json # Views API dashboard/widget layout, paired with search_*.json +.forgejo/workflows/deploy.yml # CI: config-only redeploy (in-container runner) +.forgejo/workflows/deploy-from-scratch.yml # CI: full recreate (host-level runner) ``` Inside the container, everything lives under `/opt/graylog/` diff --git a/README.uk.md b/README.uk.md index c89db65..740c704 100644 --- a/README.uk.md +++ b/README.uk.md @@ -27,6 +27,24 @@ Обидва скрипти ідемпотентні — повторний запуск після збою (або для оновлення) продовжує з того місця, де зупинився, а не дублює роботу. +## Варіанти запуску + +Чотири способи застосувати цей проєкт — від "ввести одну команду" до +"натиснути кнопку в браузері". Обирайте залежно від того, що змінилося і +скільки налаштування готові зробити наперед. + +| Спосіб | Звідки запускається | Що робить | Одноразове налаштування | Коли використовувати | +|---|---|---|---|---| +| **Вручну, повний** | термінал на хості Proxmox | `create-graylog-lxc.sh` → створює/ремонтує LXC-контейнер, встановлює все | немає | перший деплой, або коли хочете бачити процес наживо | +| **Вручну, тільки конфіг** | термінал, `pct exec` у контейнер | повторний запуск `install-graylog.sh` напряму | немає | швидкий фікс конфігурації без git | +| **CI, тільки конфіг** | веб-інтерфейс Forgejo | workflow `deploy.yml` → перезапускає `install-graylog.sh` з останнього коміту | `setup-forgejo-runner.sh` **всередині контейнера** (див. крок 9) | запушили нове правило/алерт/дашборд, контейнер уже існує | +| **CI, повний** | веб-інтерфейс Forgejo | workflow `deploy-from-scratch.yml` → запускає `create-graylog-lxc.sh` з останнього коміту | `setup-forgejo-runner.sh` **на хості Proxmox** (див. крок 9) | одна кнопка для пересоздання після ручного `pct destroy`, без терміналу | + +Усі чотири варіанти виконують ті самі ідемпотентні скрипти — жодної +"CI-only" поведінки, яка б відрізнялась від того, що ввели б вручну. +Жоден з CI-workflow не виконує `pct destroy` — це завжди свідомий ручний +крок (дивіться "CI/CD через Forgejo Actions" нижче, чому саме так). + ## Покрокове розгортання з нуля ### 0. Передумови @@ -191,27 +209,56 @@ Graylog під кожен пристрій не потрібно — inputs і ### 9. (Опційно) Налаштувати Forgejo Actions CI -Якщо ви пушите цей проєкт на інстанс Forgejo, `setup-forgejo-runner.sh` -реєструє self-hosted Actions runner прямо всередині контейнера, тож -`.forgejo/workflows/deploy.yml` може повторно запускати `install-graylog.sh` -на вимогу прямо з git, замість ручного scp файлів. Див. "CI/CD через -Forgejo Actions" нижче — що саме робить workflow і як його запускати; цей -крок — лише одноразове налаштування runner'а. +`setup-forgejo-runner.sh` реєструє self-hosted Actions runner — він може +працювати у двох різних місцях, один скрипт для обох, просто різні +параметри. Див. "CI/CD через Forgejo Actions" нижче, що саме робить кожен +workflow; цей крок — лише одноразове налаштування раннера. Обидва +опційні й незалежні — налаштуйте один, жодного чи обидва. -1. У веб-інтерфейсі Forgejo: репо → Settings → Actions → Runners → - "Create new Runner", щоб отримати токен реєстрації (одноразове - значення, не вгадуйте й не перевикористовуйте з іншого репо). -2. Запустіть скрипт налаштування всередині контейнера: - ```bash - pct exec -- env \ - FORGEJO_URL="https://ваш-forgejo-інстанс" \ - FORGEJO_RUNNER_TOKEN="<токен з кроку 1>" \ - bash /opt/graylog-deploy/setup-forgejo-runner.sh - ``` -3. Додайте два секрети, які потребує workflow (репо → Settings → Actions → - Secrets): `GRAYLOG_ADMIN_PASSWORD` та `DISCORD_WEBHOOK_URL`. Третє - значення, `secrets.GITHUB_TOKEN`, створювати не треба — Forgejo видає - його автоматично на кожен job, прив'язаним лише до цього репо. +**Спільний перший крок:** у веб-інтерфейсі Forgejo: репо → Settings → +Actions → Runners → "Create new Runner", щоб отримати токен реєстрації +(одноразове значення, не вгадуйте й не перевикористовуйте з іншого репо +— беріть новий токен для кожного раннера, який реєструєте). + +**9a. Раннер усередині контейнера** (для `deploy.yml` — редеплой тільки +конфігурації): +```bash +pct exec -- env \ + FORGEJO_URL="https://ваш-forgejo-інстанс" \ + FORGEJO_RUNNER_TOKEN="<токен>" \ + bash /opt/graylog-deploy/setup-forgejo-runner.sh +``` + +**9b. Раннер на самому хості Proxmox** (для `deploy-from-scratch.yml` — +повне пересоздання). Спочатку на хості має бути встановлений `git` +(`apt-get install -y git` — у контейнері він уже є, на голому хості +зазвичай нема). `RUNNER_USER=claude-deploy` тут обов'язковий, не +опційний: без нього systemd-сервіс працює від root, видаючи кожному +CI-job необмежений root на хості замість вузько-скоупленого sudo +`claude-deploy`: +```bash +sudo env FORGEJO_URL="https://ваш-forgejo-інстанс" FORGEJO_RUNNER_TOKEN="<токен>" RUNNER_NAME="proxmox-host-runner" RUNNER_LABEL="proxmox-host:host" RUNNER_DIR="/opt/forgejo-runner-host" SERVICE_NAME="forgejo-runner-host" RUNNER_USER="claude-deploy" bash /home/claude-deploy/graylog-deploy/setup-forgejo-runner.sh +``` +(Одним рядком, без `\` — у деяких терміналах багаторядкова вставка з +переносами губила продовження, і `sudo env` виконувався зовсім без +аргументів і без жодної встановленої змінної.) + +**9c. Секрети**, які потребують workflow (репо → Settings → Actions → +Secrets): `GRAYLOG_ADMIN_PASSWORD` та `DISCORD_WEBHOOK_URL`. Третє +значення, `secrets.GITHUB_TOKEN`, створювати не треба — Forgejo видає +його автоматично на кожен job, прив'язаним лише до цього репо. + +**Видалення раннера пізніше** (наприклад, host-level, якщо не хочете +тримати його зареєстрованим, коли активно не деплоїте): +```bash +sudo systemctl disable --now forgejo-runner-host +sudo rm -f /etc/systemd/system/forgejo-runner-host.service +sudo systemctl daemon-reload +sudo rm -rf /opt/forgejo-runner-host +``` +а потім видаліть його й у UI: репо → Settings → Actions → Runners. +Повторна реєстрація пізніше потребує нового токена з тієї ж сторінки — +старий автоматично не перевикористається. ## Параметри @@ -556,29 +603,60 @@ Discord-канал. ## CI/CD через Forgejo Actions Forgejo-репозиторій проєкту (`git.zotac.keenetic.link/zotac/graylog-deploy`) -має вручну-запускний деплой-workflow: `.forgejo/workflows/deploy.yml`. -Його запуск клонує репо наново й повторно запускає `install-graylog.sh` — -той самий ідемпотентний скрипт, описаний по всьому цьому README, просто -автоматизований замість ручного scp. Одноразове налаштування — -`setup-forgejo-runner.sh` (див. крок 9 вище); цей розділ описує, що робить -workflow і як його запускати щодня. +має два вручну-запускні workflow, кожен зі своїм раннером (див. крок 9 +вище про налаштування). Обидва просто автоматизують скрипти, вже описані +в іншому місці цього README — жодної CI-специфічної поведінки немає. + +### `deploy.yml` — редеплой тільки конфігурації + +Клонує репо наново й повторно запускає `install-graylog.sh` усередині +контейнера. Використовуйте після пушу нового правила/алерту/дашборду/ +pipeline на вже існуючий контейнер. **Як запускати:** репо → вкладка **Actions** → **Deploy Graylog config** у -лівому меню → кнопка **Run workflow** → підтвердити. Прогрес і логи -кожного кроку з'являються одразу під списком запусків. +лівому меню → кнопка **Run workflow** → підтвердити. -- **Тригер навмисно ручний** (тільки `workflow_dispatch`, без - `on: push`) — це репо керує продакшн-системою моніторингу, тож людина - переглядає диф і сама натискає "Run workflow", а не кожен push тихо - передеплоює систему. - **Раннер живе прямо всередині контейнера Graylog** (VMID 200, лейбл `self-hosted:host`, встановлений у `/usr/local/bin/forgejo-runner`, працює як systemd-сервіс). Нових SSH-ключів чи міжхостового доступу не знадобилося — workflow просто клонує репо в `/tmp/graylog-deploy-ci` і запускає скрипт локально, точно як це робив би оператор вручну. -- **Без `actions/checkout`** — ця дія вимагає Node.js, якого немає (і не - повинно бути) на цьому appliance-контейнері лише заради CI. Замість неї - workflow робить звичайний `git clone --depth 1`. + +### `deploy-from-scratch.yml` — повне пересоздання + +Клонує репо наново й повторно запускає `create-graylog-lxc.sh` **на +хості Proxmox**. Використовуйте після ручного `pct destroy` (чи на +контейнері, якого ще ніколи не було), коли хочете просто натиснути +кнопку замість вводу повної команди `create-graylog-lxc.sh`. + +**Як запускати:** репо → вкладка **Actions** → **Deploy Graylog from +scratch (host-level)** у лівому меню → кнопка **Run workflow** → +підтвердити. + +- **Раннер живе прямо на хості Proxmox**, працює від `claude-deploy` + (не root — див. крок 9b вище, чому це важливо), зареєстрований з + окремим лейблом (`proxmox-host:host`), тож підхоплює лише job'и для + цього workflow, не для `deploy.yml`. +- **`pct destroy` навмисно НЕ входить у цей workflow.** Автоматичне + пересоздання інфраструктури безпечне, бо `create-graylog-lxc.sh` + ідемпотентний (ремонтує на місці, якщо контейнер уже існує, створює + заново, якщо ні); знищення — незворотна втрата даних і залишається + свідомим набором команди людиною. Кнопка в CI, яка може знищити + продакшн одним випадковим кліком, розглядалась і була відхилена. + `pct destroy` навіть не входить у sudo-скоуп `claude-deploy` — свідомо. +- **На голому хості має бути встановлений `git`** — на відміну від + контейнера (де він є з шаблону Debian 12), свіжий хост Proxmox зазвичай + його не має (`apt-get install -y git`, одноразово, root). + +### Спільне для обох workflow + +- **Тригер навмисно ручний** (тільки `workflow_dispatch`, без + `on: push`) — вони керують продакшн-системою моніторингу, тож людина + переглядає диф і сама натискає "Run workflow", а не кожен push тихо + передеплоює систему. +- **Без `actions/checkout`** — ця дія вимагає Node.js, якого немає в + жодного раннера й не повинно бути лише заради CI. Обидва workflow + роблять звичайний `git clone --depth 1`. - **Clone автентифікований через `secrets.GITHUB_TOKEN`** — короткоживучий токен, який Forgejo сама створює на початок кожного запуску workflow і знищує по завершенню, прив'язаний тільки до цього репо (підтверджено @@ -589,7 +667,7 @@ workflow і як його запускати щодня. - **Секрети** (`GRAYLOG_ADMIN_PASSWORD`, `DISCORD_WEBHOOK_URL`) зберігаються як repo-level секрети Forgejo Actions, а не в жодному відстежуваному файлі. `GRAYLOG_EXTERNAL_URI` не є секретом (це публічна адреса Web UI), - тож вказаний прямо у workflow. + тож вказаний прямо в обох workflow. ## Що ще НЕ реалізовано @@ -611,13 +689,22 @@ workflow і як його запускати щодня. ## Структура файлів ``` -create-graylog-lxc.sh # запускається на хості Proxmox -install-graylog.sh # запускається всередині контейнера (автоматично) -docker-compose.yml # опис стеку MongoDB + OpenSearch + Graylog -nftables.conf # firewall-правила, що застосовуються всередині контейнера -rules/*.json # визначення Graylog Pipeline Rule (імпортуються через API) -pipelines/*.json # визначення Graylog Pipeline, що посилаються на правила -streams/*.json # визначення Graylog Stream (маршрутизація за портом input) +create-graylog-lxc.sh # хост Proxmox - створює/ремонтує LXC-контейнер +install-graylog.sh # усередині контейнера (запускається автоматично) +bootstrap-host.sh # одноразово, root, хост Proxmox - автоматизує AppArmor-фікс +cleanup-host.sh # відкочує bootstrap-host.sh +fix-lxc-apparmor.sh # встановлюється bootstrap-host.sh, напряму не запускати +setup-forgejo-runner.sh # реєструє CI-раннер - у контейнері чи на хості +docker-compose.yml # опис стеку MongoDB + OpenSearch + Graylog +nftables.conf # firewall-правила, що застосовуються всередині контейнера +rules/*.json # визначення Graylog Pipeline Rule (імпортуються через API) +pipelines/*.json # визначення Graylog Pipeline, що посилаються на правила +streams/*.json # визначення Graylog Stream (маршрутизація за портом input) +alerts/*.json # Event Definitions + шаблон Discord-нотифікації +dashboards/search_*.json # об'єкти пошуку Views API, пара на кожен дашборд +dashboards/view_*.json # макет дашборду/віджетів Views API, у парі з search_*.json +.forgejo/workflows/deploy.yml # CI: редеплой тільки конфігурації (раннер у контейнері) +.forgejo/workflows/deploy-from-scratch.yml # CI: повне пересоздання (раннер на хості) ``` Всередині контейнера все лежить у `/opt/graylog/` (`docker-compose.yml`,