Add setup-forgejo-runner.sh and document the full from-scratch deployment
The CI runner setup was done by hand this session (download, verify, register, systemd unit) - script it the same idempotent way as install-graylog.sh so a fresh deployment can reproduce it instead of requiring manual SSH archaeology. Wire it into create-graylog-lxc.sh's payload copy, and add step 9 to both READMEs covering the one-time setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
3e46b08db5
commit
458aada5a5
4 changed files with 193 additions and 9 deletions
44
README.md
44
README.md
|
|
@ -184,6 +184,30 @@ See "Verifying a test alert" further down - send one of the known-critical
|
||||||
log lines via `logger` from inside the container and watch it land in
|
log lines via `logger` from inside the container and watch it land in
|
||||||
Discord within about a minute.
|
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.
|
||||||
|
|
||||||
|
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 <VMID> -- env \
|
||||||
|
FORGEJO_URL="https://your-forgejo-instance" \
|
||||||
|
FORGEJO_RUNNER_TOKEN="<token from step 1>" \
|
||||||
|
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.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
All flags have an environment-variable equivalent (see the top of
|
All flags have an environment-variable equivalent (see the top of
|
||||||
|
|
@ -484,9 +508,15 @@ channel.
|
||||||
|
|
||||||
This project's Forgejo repo (`git.zotac.keenetic.link/zotac/graylog-deploy`)
|
This project's Forgejo repo (`git.zotac.keenetic.link/zotac/graylog-deploy`)
|
||||||
has a manually-triggered deploy workflow: `.forgejo/workflows/deploy.yml`.
|
has a manually-triggered deploy workflow: `.forgejo/workflows/deploy.yml`.
|
||||||
Running it (Actions tab → Deploy Graylog config → Run workflow) clones the
|
Running it clones the repo fresh and re-runs `install-graylog.sh` - the
|
||||||
repo fresh and re-runs `install-graylog.sh` - the same idempotent script
|
same idempotent script described throughout this README, just automated
|
||||||
described throughout this README, just automated instead of scp'd by hand.
|
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.
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
- **Trigger is manual on purpose** (`workflow_dispatch` only, no
|
- **Trigger is manual on purpose** (`workflow_dispatch` only, no
|
||||||
`on: push`) - this repo drives a production monitoring system, so a
|
`on: push`) - this repo drives a production monitoring system, so a
|
||||||
|
|
@ -500,6 +530,14 @@ described throughout this README, just automated instead of scp'd by hand.
|
||||||
- **No `actions/checkout`** - that action needs Node.js, which this
|
- **No `actions/checkout`** - that action needs Node.js, which this
|
||||||
appliance container doesn't have and shouldn't need just for CI. The
|
appliance container doesn't have and shouldn't need just for CI. The
|
||||||
workflow does a plain `git clone --depth 1` instead.
|
workflow does 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
|
||||||
|
(confirmed against Forgejo's own docs: it works even when the repo is
|
||||||
|
private, and any attempt to use it against a different repo returns
|
||||||
|
404). Nothing to configure - it's provided by the platform, not a secret
|
||||||
|
this project manages. This is what keeps the clone working if the repo
|
||||||
|
is later made private.
|
||||||
- **Secrets** (`GRAYLOG_ADMIN_PASSWORD`, `DISCORD_WEBHOOK_URL`) are stored
|
- **Secrets** (`GRAYLOG_ADMIN_PASSWORD`, `DISCORD_WEBHOOK_URL`) are stored
|
||||||
as repo-level Forgejo Actions secrets, not in any tracked file.
|
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
|
`GRAYLOG_EXTERNAL_URI` isn't secret (it's the public Web UI address) so
|
||||||
|
|
|
||||||
44
README.uk.md
44
README.uk.md
|
|
@ -188,6 +188,30 @@ Graylog під кожен пристрій не потрібно — inputs і
|
||||||
критичних рядків логу через `logger` зсередини контейнера і подивіться,
|
критичних рядків логу через `logger` зсередини контейнера і подивіться,
|
||||||
як він приходить у Discord протягом приблизно хвилини.
|
як він приходить у Discord протягом приблизно хвилини.
|
||||||
|
|
||||||
|
### 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'а.
|
||||||
|
|
||||||
|
1. У веб-інтерфейсі Forgejo: репо → Settings → Actions → Runners →
|
||||||
|
"Create new Runner", щоб отримати токен реєстрації (одноразове
|
||||||
|
значення, не вгадуйте й не перевикористовуйте з іншого репо).
|
||||||
|
2. Запустіть скрипт налаштування всередині контейнера:
|
||||||
|
```bash
|
||||||
|
pct exec <VMID> -- 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, прив'язаним лише до цього репо.
|
||||||
|
|
||||||
## Параметри
|
## Параметри
|
||||||
|
|
||||||
Кожен флаг має відповідник у вигляді змінної середовища (див. початок
|
Кожен флаг має відповідник у вигляді змінної середовища (див. початок
|
||||||
|
|
@ -503,10 +527,15 @@ Discord-канал.
|
||||||
|
|
||||||
Forgejo-репозиторій проєкту (`git.zotac.keenetic.link/zotac/graylog-deploy`)
|
Forgejo-репозиторій проєкту (`git.zotac.keenetic.link/zotac/graylog-deploy`)
|
||||||
має вручну-запускний деплой-workflow: `.forgejo/workflows/deploy.yml`.
|
має вручну-запускний деплой-workflow: `.forgejo/workflows/deploy.yml`.
|
||||||
Його запуск (вкладка Actions → Deploy Graylog config → Run workflow)
|
Його запуск клонує репо наново й повторно запускає `install-graylog.sh` —
|
||||||
клонує репо наново й повторно запускає `install-graylog.sh` — той самий
|
той самий ідемпотентний скрипт, описаний по всьому цьому README, просто
|
||||||
ідемпотентний скрипт, описаний по всьому цьому README, просто
|
автоматизований замість ручного scp. Одноразове налаштування —
|
||||||
автоматизований замість ручного scp.
|
`setup-forgejo-runner.sh` (див. крок 9 вище); цей розділ описує, що робить
|
||||||
|
workflow і як його запускати щодня.
|
||||||
|
|
||||||
|
**Як запускати:** репо → вкладка **Actions** → **Deploy Graylog config** у
|
||||||
|
лівому меню → кнопка **Run workflow** → підтвердити. Прогрес і логи
|
||||||
|
кожного кроку з'являються одразу під списком запусків.
|
||||||
|
|
||||||
- **Тригер навмисно ручний** (тільки `workflow_dispatch`, без
|
- **Тригер навмисно ручний** (тільки `workflow_dispatch`, без
|
||||||
`on: push`) — це репо керує продакшн-системою моніторингу, тож людина
|
`on: push`) — це репо керує продакшн-системою моніторингу, тож людина
|
||||||
|
|
@ -520,6 +549,13 @@ Forgejo-репозиторій проєкту (`git.zotac.keenetic.link/zotac/gr
|
||||||
- **Без `actions/checkout`** — ця дія вимагає Node.js, якого немає (і не
|
- **Без `actions/checkout`** — ця дія вимагає Node.js, якого немає (і не
|
||||||
повинно бути) на цьому appliance-контейнері лише заради CI. Замість неї
|
повинно бути) на цьому appliance-контейнері лише заради CI. Замість неї
|
||||||
workflow робить звичайний `git clone --depth 1`.
|
workflow робить звичайний `git clone --depth 1`.
|
||||||
|
- **Clone автентифікований через `secrets.GITHUB_TOKEN`** — короткоживучий
|
||||||
|
токен, який Forgejo сама створює на початок кожного запуску workflow і
|
||||||
|
знищує по завершенню, прив'язаний тільки до цього репо (підтверджено
|
||||||
|
офіційною документацією Forgejo: працює навіть коли репо приватне, а
|
||||||
|
спроба використати його проти іншого репо повертає 404). Нічого
|
||||||
|
налаштовувати — це видає платформа, а не секрет, яким керує цей проєкт.
|
||||||
|
Саме це не дає clone зламатись, якщо репо пізніше зробити приватним.
|
||||||
- **Секрети** (`GRAYLOG_ADMIN_PASSWORD`, `DISCORD_WEBHOOK_URL`) зберігаються
|
- **Секрети** (`GRAYLOG_ADMIN_PASSWORD`, `DISCORD_WEBHOOK_URL`) зберігаються
|
||||||
як repo-level секрети Forgejo Actions, а не в жодному відстежуваному
|
як repo-level секрети Forgejo Actions, а не в жодному відстежуваному
|
||||||
файлі. `GRAYLOG_EXTERNAL_URI` не є секретом (це публічна адреса Web UI),
|
файлі. `GRAYLOG_EXTERNAL_URI` не є секретом (це публічна адреса Web UI),
|
||||||
|
|
|
||||||
|
|
@ -192,9 +192,9 @@ check_apparmor_hint() {
|
||||||
copy_install_payload() {
|
copy_install_payload() {
|
||||||
log "Copying install payload into the container (/opt/graylog-deploy)..."
|
log "Copying install payload into the container (/opt/graylog-deploy)..."
|
||||||
sudo /usr/sbin/pct exec "$VMID" -- mkdir -p /opt/graylog-deploy
|
sudo /usr/sbin/pct exec "$VMID" -- mkdir -p /opt/graylog-deploy
|
||||||
tar czf - -C "$SCRIPT_DIR" rules streams pipelines alerts dashboards install-graylog.sh docker-compose.yml nftables.conf \
|
tar czf - -C "$SCRIPT_DIR" rules streams pipelines alerts dashboards install-graylog.sh setup-forgejo-runner.sh docker-compose.yml nftables.conf \
|
||||||
| sudo /usr/sbin/pct exec "$VMID" -- bash -c 'tar xzf - -C /opt/graylog-deploy'
|
| sudo /usr/sbin/pct exec "$VMID" -- bash -c 'tar xzf - -C /opt/graylog-deploy'
|
||||||
sudo /usr/sbin/pct exec "$VMID" -- chmod +x /opt/graylog-deploy/install-graylog.sh
|
sudo /usr/sbin/pct exec "$VMID" -- chmod +x /opt/graylog-deploy/install-graylog.sh /opt/graylog-deploy/setup-forgejo-runner.sh
|
||||||
}
|
}
|
||||||
|
|
||||||
run_install() {
|
run_install() {
|
||||||
|
|
|
||||||
110
setup-forgejo-runner.sh
Normal file
110
setup-forgejo-runner.sh
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Runs INSIDE the Graylog LXC container as root (invoked via `pct exec <vmid> -- bash setup-forgejo-runner.sh`).
|
||||||
|
# Idempotent: safe to re-run after a partial failure.
|
||||||
|
#
|
||||||
|
# Registers a Forgejo Actions self-hosted runner in "host" mode (no Docker -
|
||||||
|
# it runs shell steps directly on this container, which already has
|
||||||
|
# everything install-graylog.sh needs) and wires it up as a systemd service
|
||||||
|
# so it survives reboots.
|
||||||
|
#
|
||||||
|
# The registration token is a one-time credential from Forgejo itself, not
|
||||||
|
# something this script invents - get it from:
|
||||||
|
# Repo -> Settings -> Actions -> Runners -> "Create new Runner", or
|
||||||
|
# GET /api/v1/repos/<owner>/<repo>/actions/runners/registration-token
|
||||||
|
# (requires a personal access token with repo admin rights)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
FORGEJO_URL="${FORGEJO_URL:?Set FORGEJO_URL, e.g. https://git.zotac.keenetic.link}"
|
||||||
|
FORGEJO_RUNNER_TOKEN="${FORGEJO_RUNNER_TOKEN:?Set FORGEJO_RUNNER_TOKEN (registration token from the repo's Actions -> Runners page)}"
|
||||||
|
RUNNER_NAME="${RUNNER_NAME:-graylog-container-$(hostname)}"
|
||||||
|
RUNNER_VERSION="12.13.1"
|
||||||
|
RUNNER_DIR="/opt/forgejo-runner"
|
||||||
|
|
||||||
|
if [ -t 2 ]; then
|
||||||
|
C_RESET=$'\033[0m'; C_CYAN=$'\033[36m'; C_GREEN=$'\033[32m'; C_YELLOW=$'\033[33m'; C_RED=$'\033[1;31m'
|
||||||
|
else
|
||||||
|
C_RESET=''; C_CYAN=''; C_GREEN=''; C_YELLOW=''; C_RED=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
log() { echo "${C_CYAN}[setup-forgejo-runner]${C_RESET} $*" >&2; }
|
||||||
|
ok() { echo "${C_GREEN}[setup-forgejo-runner] ✓${C_RESET} $*" >&2; }
|
||||||
|
skip() { echo "${C_YELLOW}[setup-forgejo-runner] ⏭${C_RESET} $*" >&2; }
|
||||||
|
die() { echo "${C_RED}[setup-forgejo-runner] ✗ ERROR:${C_RESET} $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
[ "$(id -u)" -eq 0 ] || die "must run as root inside the container (use pct exec)"
|
||||||
|
|
||||||
|
step_install_binary() {
|
||||||
|
if [ -x /usr/local/bin/forgejo-runner ] && /usr/local/bin/forgejo-runner --version 2>/dev/null | grep -q "$RUNNER_VERSION"; then
|
||||||
|
skip "forgejo-runner $RUNNER_VERSION already installed"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
log "Downloading and verifying forgejo-runner $RUNNER_VERSION..."
|
||||||
|
local base="https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}"
|
||||||
|
local tmp; tmp="$(mktemp -d)"
|
||||||
|
( cd "$tmp" \
|
||||||
|
&& curl -fsSL -o "forgejo-runner-${RUNNER_VERSION}-linux-amd64" "$base/forgejo-runner-${RUNNER_VERSION}-linux-amd64" \
|
||||||
|
&& curl -fsSL -o "forgejo-runner-${RUNNER_VERSION}-linux-amd64.sha256" "$base/forgejo-runner-${RUNNER_VERSION}-linux-amd64.sha256" \
|
||||||
|
&& sha256sum -c "forgejo-runner-${RUNNER_VERSION}-linux-amd64.sha256" )
|
||||||
|
chmod +x "$tmp/forgejo-runner-${RUNNER_VERSION}-linux-amd64"
|
||||||
|
mv "$tmp/forgejo-runner-${RUNNER_VERSION}-linux-amd64" /usr/local/bin/forgejo-runner
|
||||||
|
rm -rf "$tmp"
|
||||||
|
ok "installed forgejo-runner $RUNNER_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
|
step_register() {
|
||||||
|
mkdir -p "$RUNNER_DIR"
|
||||||
|
if [ -f "$RUNNER_DIR/.runner" ]; then
|
||||||
|
skip "runner already registered ($RUNNER_DIR/.runner exists)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
log "Registering runner '$RUNNER_NAME' with $FORGEJO_URL (host mode, label self-hosted:host)..."
|
||||||
|
( cd "$RUNNER_DIR" && /usr/local/bin/forgejo-runner register --no-interactive \
|
||||||
|
--instance "$FORGEJO_URL" \
|
||||||
|
--token "$FORGEJO_RUNNER_TOKEN" \
|
||||||
|
--name "$RUNNER_NAME" \
|
||||||
|
--labels self-hosted:host )
|
||||||
|
ok "runner registered"
|
||||||
|
}
|
||||||
|
|
||||||
|
step_config() {
|
||||||
|
if [ -f "$RUNNER_DIR/config.yaml" ]; then
|
||||||
|
skip "config.yaml already exists"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
( cd "$RUNNER_DIR" && /usr/local/bin/forgejo-runner generate-config > config.yaml )
|
||||||
|
ok "generated config.yaml"
|
||||||
|
}
|
||||||
|
|
||||||
|
step_service() {
|
||||||
|
if systemctl is-active --quiet forgejo-runner; then
|
||||||
|
skip "forgejo-runner service already running"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
cat > /etc/systemd/system/forgejo-runner.service <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Forgejo Actions Runner
|
||||||
|
After=network.target docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=$RUNNER_DIR
|
||||||
|
ExecStart=/usr/local/bin/forgejo-runner daemon --config $RUNNER_DIR/config.yaml
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now forgejo-runner
|
||||||
|
ok "forgejo-runner service started and enabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
step_install_binary
|
||||||
|
step_register
|
||||||
|
step_config
|
||||||
|
step_service
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
Loading…
Add table
Reference in a new issue