# Anectico collector

> Install the host agent that sends OTLP host, log, forwarded and PostgreSQL/Redis telemetry to Anectico, and read whether it is delivering.

Canonical page: https://anectico.com/docs/start/collector/


The Anectico collector is a pinned, reproducible OpenTelemetry Collector distribution with Anectico's
own presets, installer and diagnostics. Run one per host (or per database you monitor) to send host
metrics, application log files, forwarded OTLP, and PostgreSQL or Redis server statistics without
writing a collector configuration from scratch.

**Supported**: Linux **amd64** and **arm64**, installed with **systemd** or run with **Docker**.
Artifacts are **checksummed (SHA-256), not signed** — the installer refuses any release whose
checksum does not match the one you give it.

**Not in scope**: fleet management, auto-discovery, eBPF instrumentation, and databases other than
PostgreSQL and Redis.

## Keys and sources

The collector authenticates with a `native_ingest` [intake key](/docs/instrument/native-intake-keys)
bound to one [ingestion source](/docs/manage/ingestion-pipelines). Create the source and key before
installing:

```bash
anectico sources create --purpose native_ingest --name "collector-web-01" --idempotency-key "collector-web-01-v1"
anectico apikey create --purpose native_ingest --source-id <source-id>
```

Run **one collector per source**. If two collectors share a source, their self-reported queue
telemetry ([collection health](#collection-health)'s `collector` field) becomes indistinguishable —
you cannot tell which one is behind.

## Install with systemd

Download the release tarball and its `SHA256SUMS` for your architecture, then:

```bash
anectico-collector install --tarball anectico-collector_<version>_linux_<arch>.tar.gz \
  --sha256-file SHA256SUMS \
  --endpoint https://api.anectico.com \
  --ingest-key-file ./ingest-key \
  --host-name "$(hostname)" \
  --presets host,filelog,otlp
```

- `--endpoint` is your OTLP intake origin, without credentials in the URL — an endpoint containing
  `user:pass@` is refused.
- `--ingest-key-file` reads the intake key from a file (never a command-line argument); it is stored
  as a `0600` file under `/etc/anectico-collector/secrets/`, never in the unit file, an environment
  file, or a process's command line.
- `--presets` is a comma-separated list: `host`, `filelog`, `otlp`, `postgresql`, `redis`. The
  `postgresql` preset additionally requires `--postgresql-endpoint`, `--postgresql-username` and
  `--postgresql-password-file`; the `redis` preset requires `--redis-endpoint` (its password file is
  optional — an empty file means no `AUTH`). An unknown preset name, or `postgresql` without a
  password file, is refused before anything is installed.
- Every setting value is checked for characters that could break out of its stored quoting (`'`, `\`,
  or a newline) and refused if it contains one.

Other systemd commands:

```bash
anectico-collector upgrade --tarball <file> --sha256-file SHA256SUMS   # switches, restarts, then
                                                                        # auto-restores the previous
                                                                        # release if the new one does
                                                                        # not become healthy
anectico-collector rollback                                           # returns to the previous release
anectico-collector validate                                           # dry-run its stored config
anectico-collector status                                             # version, presets, queue summary
anectico-collector diagnostics --output bundle.tar.gz                 # see "Diagnostics bundle" below
anectico-collector uninstall [--purge]                                # --purge also removes state and secrets
```

An upgrade that installs but fails its health check restores the previous release automatically and
reports the failure — it never leaves the host running a release that never became healthy.

## Install with Docker

```bash
install -d -m 0700 secrets && install -m 0600 /dev/stdin secrets/ingest-key   # paste the key, Ctrl-D
ANECTICO_COLLECTOR_ENDPOINT=https://api.anectico.com \
ANECTICO_COLLECTOR_HOST_NAME="$(hostname)" \
  docker compose up -d
```

The compose file mounts the host filesystem read-only for the `host` and `filelog` presets, runs as a
non-root user with every Linux capability dropped, and publishes the OTLP and self-telemetry ports
only on loopback (the OTLP listener has no authentication of its own). Add the `postgresql` or
`redis` preset's config file to `command` and its settings to `environment` to collect a database, the
same as the systemd `--presets` flag.

## Presets and settings

Every setting is an environment variable — on systemd, written to `/etc/anectico-collector/collector.env`
by `install`; in Docker, set directly in `environment`. None of them is a secret.

| Preset | What it collects | Key settings |
| --- | --- | --- |
| `host` | CPU, memory, load, filesystem, disk and network | `ANECTICO_COLLECTOR_HOST_NAME` (required), `ANECTICO_COLLECTOR_HOST_ROOT` (`/`, or `/hostfs` in Docker) |
| `filelog` | Application log files | `ANECTICO_COLLECTOR_FILELOG_INCLUDE` (required): a JSON array of glob patterns, e.g. `["/var/log/app/*.log"]` |
| `otlp` | Forwards OTLP you already emit elsewhere | `ANECTICO_COLLECTOR_OTLP_GRPC_ENDPOINT` (`127.0.0.1:4317`), `ANECTICO_COLLECTOR_OTLP_HTTP_ENDPOINT` (`127.0.0.1:4318`) — keep on loopback or a trusted network; neither listener authenticates its own callers |
| `postgresql` | Server metrics from the statistics views | `ANECTICO_COLLECTOR_POSTGRESQL_ENDPOINT`, `ANECTICO_COLLECTOR_POSTGRESQL_USERNAME` (required), `ANECTICO_COLLECTOR_POSTGRESQL_DATABASES` (JSON array; empty means every visible database) |
| `redis` | Server metrics from `INFO` | `ANECTICO_COLLECTOR_REDIS_ENDPOINT` (required), `ANECTICO_COLLECTOR_REDIS_USERNAME` (optional) |

`ANECTICO_COLLECTOR_INTERVAL` (default `30s`) is the scrape interval shared by `host`, `postgresql`
and `redis`.

### Least-privilege database access

Create a monitoring role with **only** `LOGIN` and `CONNECT` on the databases you list — the
statistics views the `postgresql` preset reads are visible to any role, so nothing further is
required, and granting more (for example the `pg_monitor` role) adds replication and WAL visibility
the collector does not need:

```sql
CREATE ROLE anectico_monitor WITH LOGIN PASSWORD '…';
GRANT CONNECT ON DATABASE app TO anectico_monitor;
```

For Redis 6 or later, create an ACL user restricted to exactly the two commands the preset calls:

```
ACL SETUSER anectico_monitor on >password ~* -@all +info +ping
```

Query-sample and top-query collection are disabled in the shipped preset: they would copy statement
text — which can contain literal values — off the database host.

## Bounds

| Bound | Value |
| --- | --- |
| Memory | 128 MiB hard limit, 32 MiB spike allowance |
| Persistent queue | 80 MiB per telemetry signal queue (at most 3 queues in use at once) |
| Retry horizon | 300 seconds per batch, then dropped and counted, never retried indefinitely |
| Queue or disk full | Refused, never blocked: your exporter sees `503`/back-pressure and should back off, the collector keeps serving, and the refusal is counted |
| Log file backlog | Reads from the end of a file the first time it is seen; up to 64 files and 64 KiB per line, with checkpointed offsets — a refused batch is retried from the file itself, so the backlog is never lost, only delayed |

A metric point's series counts against your plan's monthly active-series allowance. Measured per
collector: the `host` preset is about 46 series, `postgresql` about 35 for one database, `redis`
about 31, and the collector's own self-telemetry about 48. A series your allowance has already
exhausted is reported back to the collector as an OTLP partial success and is not retried — it is
refused the same way an over-quota event is, not silently dropped as if it had never been sent.

## Diagnostics bundle

`anectico-collector diagnostics` collects version and component information, non-secret settings, a
listing of secret file **names and sizes only**, service and queue state, the collector's own
`otelcol_*` metrics, and a scrubbed slice of its service log, into a single archive at most 1 MiB.
Every secret value, anything shaped like an Anectico API key, and credential-bearing URLs and headers
are removed before the bundle is written; if a secret would still survive, the command refuses to
write the bundle rather than produce one that leaks it. Attach this bundle rather than raw logs when
asking for help.

## Collection health

`GET /api/v1/projects/{projectId}/ingestion/sources/{sourceId}/collection-health` (also
`anectico sources collection-health <source-id>`, and the `get_collection_health` MCP tool) answers
"is this collector delivering?" for one `native_ingest` source, from stored signal counts, the
collector's own last-reported queue telemetry, the source's transform-pipeline refusals, and how many
keys bound to the source can still authenticate — metadata and counts only, never telemetry content.

| State | Meaning |
| --- | --- |
| `VERIFIED` | Signals from this source were stored in the window; nothing below holds |
| `NO_SIGNALS` | Nothing from this source was stored in the window |
| `AUTHENTICATION_REJECTED` | The source is revoked, or every key bound to it is revoked, expired, frozen, or lacks `ingest:write` |
| `QUEUED` | The collector's last two reports both show data waiting in its queue, or its queue refused data — delivery is behind |
| `PARSER_REFUSAL` | The source's transform pipeline refused records in the window |

See the [full field reference](/docs/reference/rest-api#ingestion-sources-and-pipelines) for the
`signals`, `collector`, `pipeline_refusal_reasons` and `credentials` fields, and
[no data is appearing](/docs/help/no-data#9-using-the-anectico-collector)
for how to use this read when a signal you expect is missing.

## Dashboard presets

Each preset ships a ready-made dashboard: `anectico collector dashboards install --preset host` (or
`postgresql`, `redis`, or `all`) creates it in your active project. Installing the same preset twice
is a safe no-op — it prints `already installed` and returns the existing dashboard rather than
creating a duplicate, because presets are created with a fixed
[`idempotency_key`](/docs/reference/rest-api#dashboards). Each dashboard visualizes the series that
preset collects, plus the collector's own queue depth.

To look at an installed dashboard, ask your agent for it (`list_dashboards` finds it and
`get_dashboard` reads it). The result links to the dashboard's read-only proof page. See
[Proof pages](/docs/agents/proof-pages).
