Files
worker/README.md
Gleb Tv 674a7d82bf
Все проверки выполнены успешно
CI / test (push) Successful in 4m30s
Docker / Build and publish worker image (push) Successful in 17m26s
feat(installer): activate source builds atomically
2026-08-13 02:26:37 +03:00

271 строка
12 KiB
Markdown

# RSMon Worker
Standalone distributed monitoring worker for [rsmon.ru](https://rsmon.ru). It
connects to the RSMon control plane over WebSocket, executes checks locally,
delivers delegated notifications, and reports results back to the service.
This repository is **source available, not open source**. Building and running
the worker with rsmon.ru and private research/evaluation are permitted. See
[LICENSE](LICENSE) for the complete terms.
## Requirements
- A worker token created in the rsmon.ru worker settings.
- Outbound HTTPS/WebSocket access to rsmon.ru.
- Chromium for browser-backed HTTP checks when running the binary directly.
- `CAP_NET_RAW` or an unprivileged ICMP configuration for ping checks.
## Build
Go 1.26 or newer is required.
```bash
make build
./bin/rsmon-worker --version
```
The binary reads `.env` from its working directory when present. The minimum
configuration is `RSMON_URL`, `RSMON_TOKEN`, `WORKER_LOGIN`, and
`WORKER_PASSWORD`.
## Docker Compose
```bash
cp .env.example .env
# Edit .env and set the worker token and operator-console password.
docker compose up -d
docker compose logs -f worker
```
Compose constructs an immutable image reference from
`RSMON_WORKER_IMAGE_DIGEST`. Set that variable in `.env` to the published
64-character lowercase digest before running Compose; a mutable tag cannot be
selected through this configuration.
The operator console is bound to `127.0.0.1:27401` by default. Set
`WORKER_BIND_IP` only when a firewall or TLS reverse proxy protects the port.
Persistent web and cluster state is stored in the `worker-data` volume.
## Docker
```bash
IMAGE='reg.rsxx.ru/rsmon/rsmon-worker@sha256:<published-64-character-digest>'
docker pull "$IMAGE"
docker run --rm \
--cap-add NET_RAW \
--env-file .env \
-p 127.0.0.1:27401:27401 \
-v rsmon-worker-data:/var/lib/rsmon-worker \
"$IMAGE"
```
Published images have tags for discovery:
- `sha-<12-character-commit>` for every push;
- `latest` for `master`;
- the `v*` release ref, with Docker-invalid characters replaced by `-`.
Resolve a trusted published tag through the registry, then deploy the resulting
`repository@sha256:...` digest. Tags are mutable and are not accepted by the
installer or deploy command; Compose requires the resolved digest to be
configured explicitly.
The Gitea workflow reads `HARBOR_REGISTRY`, `HARBOR_USER`, and
`HARBOR_PASSWORD`. `HARBOR_REGISTRY` may be a host such as `reg.rsxx.ru` or an
HTTP(S) URL; the workflow strips the scheme and trailing slash before composing
Docker image references. The Harbor project is appended separately as `rsmon`.
## systemd
The `install` subcommand turns a built binary into an enabled systemd service:
it writes a hardened unit, a mode-0600 env file, the data directory, then
enables and starts the worker. It reads configuration from flags, `--env-file`,
a `.env` in the working directory, or the process environment (in that order),
and supports several co-located workers per host via `--name`. The full
reference is in [`docs/install.md`](docs/install.md).
Install host dependencies first. On Debian or Ubuntu:
```bash
sudo apt-get update
sudo apt-get install -y ca-certificates chromium libcap2-bin tzdata
```
Build and install with a token file so the token does not enter shell history or
the process list:
```bash
make build
printf '%s\n' 'WORKER_TOKEN' > worker-token
chmod 600 worker-token
sudo ./bin/rsmon-worker install --token-file worker-token
rm worker-token
```
`install` copies the running binary to `/usr/local/bin/rsmon-worker`, writes the
mode-0600 configuration at `/etc/rsmon-worker/worker.env`, installs a simple
root-run systemd unit, and enables and starts it. Use `--url` to override
`https://rsmon.ru`, `--binary` to install another binary, or `--no-start` to
configure without starting. When using `--env-file`, installation verifies its
`RSMON_URL` and `RSMON_TOKEN` before changing the host. Environment files use
portable `KEY=VALUE` lines (plus blank lines and `#` comments); quoting,
interpolation, whitespace in values, and YAML-style assignments are rejected
because systemd and Docker interpret them differently.
The Docker alternative pulls the prebuilt image and installs a systemd unit
that runs it:
```bash
sudo ./bin/rsmon-worker install --docker --token-file worker-token \
--image 'reg.rsxx.ru/rsmon/rsmon-worker@sha256:<published-64-character-digest>'
```
Docker installation requires `--image` with an immutable
`repository@sha256:<64-lowercase-hex-characters>` reference. This is a breaking
change: prior `--docker` invocations that relied on the `latest` default, or
passed only a tag, now fail before Docker is invoked or any host file is changed.
The token can also be passed as `--token` or `--api-key`, but that can expose it
through shell history and process inspection. The legacy repository-based
installer remains available:
```bash
sudo ./scripts/install-systemd.sh --binary ./rsmon-worker --env ./worker.env
```
Operational commands:
```bash
systemctl status rsmon-worker
journalctl -u rsmon-worker -f
sudo systemctl restart rsmon-worker
```
The service runs as root, reads secrets from
`/etc/rsmon-worker/worker.env`, and can execute ICMP checks without additional
capability setup.
## SSH deployment
`deploy` uploads the selected worker binary and a temporary mode-0600
configuration over SSH, then runs the binary's `install` command through root or
`sudo`. The remote host needs Linux, systemd, `base64`, and either root SSH or
sudo access.
```bash
./bin/rsmon-worker deploy \
--host worker.example.com \
--user deploy \
--identity-file ~/.ssh/id_ed25519 \
--token-file worker-token
```
Add `--docker` to install remotely by uploading only the configuration and
systemd unit, then running `docker pull` on the target. This mode does not upload
or execute the local worker binary, so the local and remote architectures may
differ. It also requires `--image repository@sha256:...`; tag-only references
are rejected before connecting to the remote host.
The default SSH port is 22 and the default RSMon URL is `https://rsmon.ru`.
Encrypted keys use `--key-passphrase-file`; password authentication uses
`--password-file`; password-protected sudo uses `--sudo-password-file`. Strongly
prefer the file options for automation: a secret supplied through a direct flag
is visible in the process list and shell history, while a file option never
exposes it through argv. The direct flags remain available for interactive
convenience.
SSH host keys are checked against `~/.ssh/known_hosts` by default. Use
`--known-hosts PATH` or pin `--host-key-fingerprint SHA256:...`. The explicit
`--insecure-host-key` option disables host authentication and should only be
used in a trusted disposable environment.
A Go SSH source installer is implemented as the `source-install` subcommand: it
detects the remote distro and architecture over the existing SSH transport,
installs the minimal build prerequisites, downloads and SHA-256-verifies the
pinned Go 1.26 toolchain, clones/updates the public repository, records the
resolved branch and commit, builds the worker to a staging path, and then
atomically activates the staged binary together with the validated environment,
data directory, and the detected init's service definition. It starts the
worker and verifies the process and `/healthz`; any activation, start, or
health failure rolls back to the previous working install (preserving the
prior binary/env/unit and its enable state), concurrent activations are
serialized by a lock, a run killed mid-flight is recovered from its
leftover backup marker on the next activation, and reruns are idempotent
(exactly one worker process, no leaked temp files). Pass `--no-activate`
to stop at the staging build, and `--no-start` to install the layout
without starting the worker. The pure detection/planning layer and the
Docker/OpenSSH test harness that accepts it are implemented; see
[`docs/source-installation.md`](docs/source-installation.md); run the live
fixture matrix with `make test-ssh`.
```bash
./bin/rsmon-worker source-install \
--host worker.example.com \
--user deploy \
--identity-file ~/.ssh/id_ed25519 \
--token-file ./worker.token
```
By default the installer builds the remote's default branch and records what it
resolves to (the public repository currently publishes `master`). Pass
`--branch <name>` to pin an explicit branch; it must exist on the remote or the
install fails before building. The repository must be an `https://` URL without
userinfo.
The built binary is staged at `/opt/rsmon-worker-src/rsmon-worker` (override with
`--build-dir` / `--stage-binary`), the toolchain at `/usr/local/go` (replaced
atomically: download, verify, stage, swap with rollback), and the resolved
branch and commit in `/opt/rsmon-worker-src/rsmon-worker.commit` (written only
after a successful build). Activation installs the binary to
`/usr/local/bin/rsmon-worker`, the environment to
`/etc/rsmon-worker/worker.env` (mode 0600), the data directory to
`/var/lib/rsmon-worker`, and a systemd unit or OpenRC init script for the
detected init (an embedded supervisor manages the process when no init is
running, as in containers). The env and unit are uploaded into a server-side
0700 `mktemp -d` directory so no local user can race a predictable `/tmp` path,
and the env file is read/rendered exactly once. The same SSH auth,
secret-file, and host-key options as `deploy` apply; the worker token is
supplied with `--token`/`--token-file` and written only to the mode-0600 env
file. Prefer `--key-passphrase-file`, `--password-file`, and
`--sudo-password-file` over their direct-flag equivalents: file options keep
secrets out of the process list and shell history.
## Configuration
| Variable | Required | Default | Purpose |
| --- | --- | --- | --- |
| `RSMON_URL` | yes | `https://rsmon.ru` for health only | Control-plane base URL. |
| `RSMON_TOKEN` | yes | none | Worker bearer token. |
| `WORKER_HOST` | no | `0.0.0.0` | Operator-console bind address. |
| `WORKER_PORT` | no | `27401` | Operator-console port. |
| `PUBLIC_URL` | no | none | Advertised public origin (scheme + host, no path). Canonical name; the legacy `WORKER_URL` is still read during the bounded migration in `docs/public-endpoint-and-identity.md`. |
| `WORKER_LOGIN` | yes | none | Operator-console basic-auth login. |
| `WORKER_PASSWORD` | yes | none | Operator-console basic-auth password. |
| `RSMON_WEBAPP_DATA_DIR` | no | user data directory | SQLite and local UI state. |
| `WORKER_CLUSTER_ENABLED` | no | `false` | Enable the optional Raft cluster. |
| `WORKER_CLUSTER_ID` | with cluster | none | Unique Raft node ID. |
| `WORKER_CLUSTER_PORT` | no | `WORKER_PORT+10000` | Raft transport port. |
| `WORKER_CLUSTER_PEERS` | no | none | Comma-separated `node@host:port` peers. |
| `WORKER_CLUSTER_DATA_DIR` | with cluster | none | Persistent Raft state directory. |
The public liveness endpoint is `GET /healthz`; the image probes it with
`rsmon-worker liveness`. `rsmon-worker health` separately checks the configured
control plane's `/up` endpoint for connectivity diagnostics.
## Implementation Documentation
Worker architecture, protocol, inventory, private-worker isolation, network
diagnostics, web console, and critical-cluster work are specified in
[`docs/README.md`](docs/README.md). These documents replace worker-owned planning
material formerly kept in the RSMon control-plane repository and include a
source migration ledger.
## Security
- Do not commit `.env`, worker tokens, or operator-console credentials.
- Expose the operator console only on loopback or behind authenticated TLS.
- Each worker should have its own control-plane token.
- Keep `/etc/rsmon-worker/worker.env` mode `0600`.
Report security issues privately through the contact channel at rsmon.ru.