Quickstart
This guide takes you from zero to live telemetry on a single Linux host in about 10 minutes. By the end, you’ll have the LinkMesh server running, one enrolled collector reporting in, an active source, and a route forwarding events to the destination of your choice.
Prerequisites
- One Linux host with
sudo(Ubuntu 22.04 LTS or RHEL 9 verified — others should work) - 1 vCPU, 1 GB RAM, 5 GB disk is plenty for the server itself
- Outbound HTTPS access to
artifacts.saas.opensight.ch(for the install package) - Open port
8080on the host so you can reach the web UI from your browser - Optional: a Grafana Cloud Loki endpoint + write token if you want to verify end-to-end delivery
1. Install the LinkMesh server
Install runs in one shell session. The package ships a systemd unit, a default
admin account, and a gitops-backed config store. The server keeps its state in
an embedded database by default, so a single-host install needs no external
database. It serves plain HTTP on port 8080; TLS is terminated by a reverse
proxy or ingress in front (covered below).
curl -fsSL https://artifacts.saas.opensight.ch/binaries/linkmesh-server/latest/linkmesh-server_latest_amd64.deb -o linkmesh-server.debsudo apt install ./linkmesh-server.debcurl -fsSL https://artifacts.saas.opensight.ch/binaries/linkmesh-server/latest/linkmesh-server-latest.x86_64.rpm -o linkmesh-server.rpmsudo dnf install ./linkmesh-server.rpmdocker run -d --name linkmesh-server \ -p 8080:8080 \ -e AUTH_ADMIN_PASSWORD='choose-a-strong-password' \ -v linkmesh-data:/data \ docker.io/opensight/linkmesh-server:latestSet AUTH_ADMIN_PASSWORD on that first run to choose the admin account’s
password up front — the container starts with it already in place.
Mount the whole /data directory, not a subpath — all durable state lives
under it: the embedded database (/data/linkmesh/state.db), the GitOps config
clones (/data/linkmesh-config/), and the auto-generated secrets encryption
key (/data/linkmesh/secrets.key). Persisting only a subdirectory loses your
destinations, users, and secrets on the next container recreate. Everything is
served on the single HTTP port 8080 — the web UI, the REST API, the agent
control channel (a WebSocket at /v1/agent), and OTLP ingest. In production,
TLS is terminated by your ingress / reverse proxy in front of it.
The install starts the server right away and creates an admin account whose
random password is deliberately never written to any log. For the package
installs above, set your own password with the recovery command — it talks to
the local server, so no prior login is needed:
sudo linkmesh-server reset-password --email admin --password 'choose-a-strong-password'Omit --password to have a strong one generated and printed. (The Docker
install already set AUTH_ADMIN_PASSWORD above, so you can skip this step
there.)
2. Tell LinkMesh its public URL
Set externalUrl to the address collectors and browsers reach this server
on, then restart. This is the one post-install setting you should not skip.
Edit /etc/linkmesh/config.yaml:
# A DNS name (preferred — survives IP changes, and matches your TLS cert)externalUrl: "https://linkmesh.example.com"# Or a bare IP, for a lab / flat-network install with no TLS in frontexternalUrl: "http://192.0.2.10:8080"Then restart:
sudo systemctl restart linkmesh-serverSet it in the environment instead — LINKMESH_EXTERNALURL, or its shorter
alias EXTERNAL_URL:
docker run -d --name linkmesh-server \ -p 8080:8080 \ -e LINKMESH_EXTERNALURL='https://linkmesh.example.com' \ -e AUTH_ADMIN_PASSWORD='choose-a-strong-password' \ -v linkmesh-data:/data \ docker.io/opensight/linkmesh-server:latestUse the address collectors resolve — an Ingress hostname or a Service DNS
name like http://linkmesh-server.linkmesh.svc.cluster.local:8080, never a
pod IP.
3. Sign in
Open http://<your-host>:8080 in a browser. Sign in as admin with the
password you set in the previous step.
4. Enroll your first collector
Open Collectors in the sidebar. The list starts empty.
Click + Add Collector and pick a collector runtime — Grafana Alloy
(config via remotecfg) or otelcol-contrib + OpAMP (config pushed via
OpAMP). This walkthrough uses Alloy. The wizard creates an enrollment token and
shows the install commands to run on the host you want to monitor. Copy them,
SSH into the target host, and run them as root.
You install upstream Grafana Alloy from its OS package, then drop in a small
bootstrap config — a remotecfg block pointing at your server plus a
per-collector Bearer token from the wizard. On its first poll, Alloy enrols and
fetches its real pipeline config from the server directly; within ~10 seconds
the collector appears in the dashboard’s fleet table. See
Add a collector for the full per-runtime
templates and the otelcol-contrib + OpAMP alternative.
5. Activate a source
Click into your new collector. Switch to the Inputs tab.
Click + Add Input to open the source library. Pick a receiver type that matches what you want to ingest — syslog, OTLP, file tail, journald, Kafka, or anything else in the library.
Pick Syslog for this walkthrough — it accepts UDP traffic on port 5514 with no further configuration. The activation is saved as soon as you confirm, and the collector picks up the new config on its next heartbeat (typically within a few seconds).
6. Add a destination
Switch to the Destinations tab on the collector detail page, or open the Destinations library in the sidebar. Click + New Destination and pick an exporter type. Common choices:
- Debug — logs records to the collector’s own stdout. Zero credentials. Useful for the first end-to-end verification.
- Grafana Cloud Loki — push logs to a Loki tenant. Needs an endpoint and a write token (free tier works).
- OTLP — send to any OpenTelemetry-compatible backend.
For this walkthrough, Debug is the fastest path to “I can see events flowing.” Save the destination, then return to the collector detail page.
7. Wire a route
Switch to the Routing tab. A route is the matcher that ties a source to a destination through an optional processing pipeline.
Click + Create new Route. Pick the syslog source as input, leave the pipeline empty (no transformation), pick the Debug destination as output. Save.
The collector picks up the change within a few seconds. Generate test traffic from any host that can reach the collector on port 5514:
logger -d -n <collector-host> -P 5514 "hello from quickstart"8. See it work
Back on the dashboard, the Throughput card ticks within ~30 seconds.
The Fleet Status table shows your collector with current status, type, and last-seen timestamp — refreshed live as heartbeats land.
If you wired a real backend (Loki, ClickHouse, OTLP), check your downstream
tool to confirm records are arriving. The Debug destination just logs to the
collector’s journal — sudo journalctl -u alloy on the collector host shows
the records as they flow through.
What’s next
- Install on Kubernetes — if your collector hosts live in a K8s cluster, use the DaemonSet flow instead of the VM install above
- Concepts — what each entity (Collector, Source, Pipeline, Route, Destination) actually means and how they relate
- Drop noisy logs — strip health-check noise before it reaches your destination
- Mask PII — redact email addresses, phone numbers, and card patterns with one processor step
- Route to Grafana Cloud Loki — wire the destination you most likely already have running
If something didn’t work, open the Events feed on the dashboard — every config push, heartbeat, and error is logged there with context.