LinkMesh Server 1.399.3
Breaking Changes
LinkMesh is in Early Access and this release carries 28 breaking changes: read every upgrade note before you upgrade, and if you use single sign-on, read that note first. It adds custom OpenTelemetry sources and destinations with extensions that are checked before they can stop a collector, rolls a collector back when a pushed config fails, makes every save a version, and fixes the fleet view for groups, Kubernetes and restarts.
Breaking Changes
This release contains breaking changes. Read the upgrade notes below before upgrading.
Single sign-on (auth.mode=external) now requires an Enterprise licence. On a server with no licence file, a Community licence or a Read-only licence, new SSO sign-ins and external tokens are refused at once with 403 license_sso_required; SSO sessions that already exist end when their token expires, at most 24h after the upgrade. Local administrator password login always keeps working.
Von uns verfasstVor dem Upgrade
WHO IS AFFECTED. Only servers that use single sign-on (auth.mode=external) AND run with no licence file, a Community licence, or a Read-only licence. A paid or unlimited (Enterprise) licence in Active or Grace state keeps SSO exactly as before. Servers that do not use SSO are not affected.
WHAT HAPPENS. New SSO sign-ins are refused immediately after the upgrade. SSO sessions created before the upgrade keep working until their token expires (auth.tokenExpiry, 24h by default), then end. SSO sessions created on this version end at once if the licence later lapses.
BEFORE YOU UPGRADE, if you are affected:
- Confirm you can sign in with the LOCAL ADMINISTRATOR PASSWORD (the local admin account), not through your identity provider. Sign in with it once, now, on the version you run today. If you do not know it, reset it on the server host with
linkmesh-server reset-password --email <admin email>(linkmesh-server list-usersshows the local accounts). This step is what keeps you from being locked out: SSO sign-in is refused after the upgrade until an Enterprise licence is uploaded. - Tell your SSO users that they cannot sign in again through SSO until step 4 is done, and that a session they already have ends within 24 hours of the upgrade.
- If SSO must keep working, obtain an Enterprise licence (https://linkmesh.io/pricing/) before you upgrade.
AFTER YOU UPGRADE:
- Sign in with the local administrator password and upload the Enterprise licence under Settings -> License (or
linkmesh-server license apply). SSO works again immediately, without a restart. - Without an Enterprise licence, keep working with local accounts. Your SSO configuration and claim mappings are kept and can still be edited; they take effect again once an Enterprise licence is uploaded.
HOW TO RECOGNISE IT: SSO sign-in fails with the code license_sso_required, and the login page says "Single sign-on requires an Enterprise license". The SSO claim-mapping screen carries an "Enterprise feature" badge.
- Confirm you can sign in with the LOCAL ADMINISTRATOR PASSWORD (the local admin account), not through your identity provider. Sign in with it once, now, on the version you run today. If you do not know it, reset it on the server host with
Every config save is now its own commit in the config repository, so the separate commit step is gone; publish no longer commits pending changes and only re-pushes the live commit; GET /settings/git returns liveSha instead of publishedSha; the production clone directory is no longer used.
Von uns verfasstVor dem Upgrade
BEFORE YOU UPGRADE:
- Optional: commit or discard pending changes on the version you run today. You do not have to: pending changes are not lost, because the upgrade itself records them as a version named "Snapshot at upgrade: N change(s) that were live but not yet in version history", authored by LinkMesh System.
- Back up the server's data directory (the bolt state file, or your MongoDB database) and the config repository directory. A downgrade back to an older release is not supported after this upgrade: older releases deploy from the production clone, which this release stops updating, so a downgraded server would push a stale configuration.
AFTER YOU UPGRADE:
- Saving is live: each save becomes a version, authored by the user who saved. There is no separate "commit" step in the UI any more. If Version History shows a "Snapshot at upgrade" version, it holds the changes that were pending when you upgraded.
- Scripts: stop reading publishedSha from GET /settings/git; read liveSha (the commit your collectors run). POST /config-as-code/publish and /publish/{collectorId} no longer create a commit or pull a connected remote; they re-push the live commit and return liveSha. POST /config-as-code/rollback now accepts any commit in history and returns the target as sha plus liveSha, the new revert commit.
- If a save answers 500, the change is already live but was not recorded; record it with POST /config-as-code/commit.
- productionClonePath in your configuration is ignored and can be removed.
On installs with a connected Git repository, the repository becomes a read-only mirror: Deploy no longer pulls from it and the Git webhook no longer applies commits, so changes made directly in the repository never reach collectors. A diverged remote refuses pushes until you overwrite it.
Von uns verfasstVor dem Upgrade
WHO IS AFFECTED. Only installs with a connected Git repository (Settings -> GitOps). Local-only installs are unaffected.
THE MIRROR NEEDS AN ACCESS TOKEN ON THE REMOTE. Only an https remote configured with an access token is mirrored. A remote without a token (an SSH key or a local path) is not mirrored at all, and LinkMesh currently shows no warning about it. If you rely on the repository as a copy of LinkMesh's history, configure the remote as https with an access token.
BEFORE YOU UPGRADE:
- Make sure every change you want is in LinkMesh: if anyone edits configuration directly in the repository, apply those edits in LinkMesh (or Deploy them on the current version) first. After the upgrade, commits made in the repository are never applied to collectors.
- Stop any process that writes to that repository (CI jobs, scripts, other people's pushes). Make changes in LinkMesh instead.
AFTER YOU UPGRADE:
- Open Settings -> GitOps. If it shows "Remote mirror out of sync", the repository holds commits LinkMesh does not have and pushes are being refused. Re-apply any of those changes you want in LinkMesh, then use "Overwrite remote with LinkMesh history" (POST /api/v1/settings/git/mirror/force-push).
- Scripts: the
pushedfield of commit responses is now false whenever the push was refused, and commit, publish and rollback responses carry a newmirrorobject describing the remote's state.
POST /config-as-code/rollback now answers 409 rollback_pending_changes while there are changes not yet in Version History, instead of silently discarding them.
Von uns verfasstVor dem Upgrade
Only API users and scripts are affected; the UI offers the choice itself. Before upgrading, find any automation that calls POST /config-as-code/rollback. After upgrading, such a call either records pending changes first (POST /config-as-code/commit), discards them, or sends "commitPending": true to record them as a snapshot version and roll back in one request. A script that relied on rollback discarding unrecorded changes must now discard them explicitly.
Agents enrolled with a reusable Kubernetes fleet token now appear once per node, named after their pod, instead of as one shared "fleet:<fleetId>" entry; the old shared entry goes offline and is removed after fleet.reapAfter (default 24h).
Von uns verfasstVor dem Upgrade
WHO IS AFFECTED. Installs with Kubernetes agents enrolled through a reusable fleet token. No action is needed before upgrading. After upgrading, expect the Agents page to show one entry per node, named after its pod; the old shared "fleet:<fleetId>" entry goes offline and disappears after fleet.reapAfter (default 24h), and each node's entry is removed the same way after its pod is replaced. Update any dashboard, alert or script that looked for the shared "fleet:<fleetId>" agent. On first start the server removes the default OTLP Input source and Default route it had written under collectors/fleet:<fleetId>/ (they configured nothing). Files there that you edited are kept.
Behind a reverse proxy, the client IP in the audit log and the login throttle now comes from the X-Forwarded-For entry appended by the last proxy listed in http.trustedProxies; True-Client-IP is no longer honoured.
Von uns verfasstVor dem Upgrade
WHO IS AFFECTED. Servers behind one or more reverse proxies, load balancers or CDNs. BEFORE YOU UPGRADE: list EVERY proxy a request passes through in http.trustedProxies (for example both your CDN ranges and your nginx ingress). If one is missing, the outermost unlisted proxy's address is recorded instead of the user's, and the login throttle then counts all users behind that proxy as one client. AFTER YOU UPGRADE: sign in once and check in the Audit Log that your own address is recorded, not a proxy's. If you relied on True-Client-IP, configure your proxy to append X-Forwarded-For instead.
Creating or editing a route whose destinationIds names a destination that is not activated on the route's collector (or its group, or for a group route on one of its members) is now refused with 400. Such a route never delivered anything.
Von uns verfasstVor dem Upgrade
Nothing changes for routes that work today. If a route save is refused after upgrading: activate the destination on the collector or group where the route runs, then reference that activation's id in the route. Scripts that create routes must reference destination activations on the same collector or group. Guide: https://linkmesh.io/docs/how-to/create-a-custom-source-or-destination/
Assigning an HTTP Check or TCP Port Check source to a Kubernetes collector group with more than one member is now refused (400 port_check_on_kubernetes_fleet); it used to run the check once per pod and send identical series.
Von uns verfasstVor dem Upgrade
Checks already assigned to such a group keep running unchanged after the upgrade, still once per pod. To stop the duplicated series, remove the check from the multi-member Kubernetes group and assign it to a single-replica (Deployment) group or to one collector instead. The same refusal now also applies to the older POST /collector-groups/{id}/sources route.
lockedByGroup in GET /api/v1/collectors/{id} no longer carries the group's full record; it now holds only id, groupId, name and kind.
Von uns verfasstVor dem Upgrade
Only API clients are affected. If a script read collectorIds, description or other group fields from lockedByGroup, read the group itself with GET /api/v1/collector-groups/{id} using lockedByGroup.groupId.
GET /api/v1/collectors/{id}/events now returns 50 events per page by default instead of the newest 100, and answers 404 for an unknown collector instead of an empty list.
Von uns verfasstVor dem Upgrade
Only API clients are affected. Pass ?limit= (up to 200) and ?page=, or follow the Link header, to read further back. Treat 404 as "this collector does not exist" rather than expecting an empty list.
GET /api/v1/sources/throughput and GET /api/v1/destinations/throughput now return data as an object keyed by entity id instead of an (always empty) array.
Von uns verfasstVor dem Upgrade
Only API clients are affected. A client that parsed data as an array must read it as a map keyed by source or destination id. The array was never populated, so no value was ever read from it.
The destination setting auth_extension now means "authenticate through the declared extension with this label". A destination that carried a stray auth_extension key (until now ignored) is left out of collectors where that label is not declared and out of every Grafana Alloy collector; saving it beside basic_auth credentials or on a Kafka, File or Debug destination is refused.
Von uns verfasstVor dem Upgrade
BEFORE YOU UPGRADE: search your destinations for an auth_extension key (in the UI or via GET /api/v1/destinations). For each one, either remove the key, or plan to declare an authenticator extension with that label on every collector or group the destination runs on. AFTER YOU UPGRADE: check the config generation warnings for destinations that were left out, and confirm each destination still delivers. Do not combine auth_extension with basic_auth credentials; Kafka, File and Debug destinations cannot use it.
An authenticator reference (a destination's auth_extension, or ${ext:<label>} under auth.authenticator in a custom body) must now resolve to an extension type that can authenticate that component; anything else is refused with extension_not_authenticator, and a stored one is left out of the collector's config with a warning.
Von uns verfasstVor dem Upgrade
After upgrading, check the config generation warnings. If a source or destination was left out with extension_not_authenticator, point its reference at a permitted authenticator extension (see "Which extensions can authenticate" in the collector extensions documentation) or clear the reference. Retyping an extension that is in use as an authenticator to a non-authenticator type is also refused.
Saving a declared extension, or attaching a source, is refused with 400 (extension_port_in_use / source_port_in_use) when it would listen on a port another source or extension on the same collector already binds, including two extensions of the same type that both use the default port.
Von uns verfasstVor dem Upgrade
Such a configuration never started, so nothing that runs today stops. If a save is refused after upgrading, give one of the two a different port in its body or source config and save again.
A custom destination whose stored config already carries durable_queue: true (previously ignored) now gets a disk-backed sending queue on its next config push; turning durable delivery on for a custom destination whose body sets sending_queue.storage, block_on_overflow, enabled: false or a conflicting queue_size is refused with 400 durable_queue_raw_body_conflict.
Von uns verfasstVor dem Upgrade
BEFORE YOU UPGRADE: check custom (raw-body) destinations for durable_queue: true. After the upgrade they start writing a persistent queue to disk on the collector; make sure the collector has a writable storage directory and disk space, or set durable_queue to false. AFTER YOU UPGRADE: if enabling durable delivery is refused with durable_queue_raw_body_conflict, keep only one of the two: either the Durable Delivery switch, or the sending_queue settings in the body.
Attaching a custom (raw-body) source or destination to an OpenTelemetry Collector is refused with 422 component_not_on_collector when the collector's component inventory lacks that component, or its inventory is unknown and LinkMesh has no template for the type.
Von uns verfasstVor dem Upgrade
Already attached components keep running. If an attach is refused after upgrading, attach it to a collector whose version or reported component inventory includes that component (the collector page now shows its inventory), or upgrade the collector to a distribution that contains it.
OPAMP COLLECTORS INSTALLED WITH AN OLDER SCRIPT. Collectors installed by an older install-opamp.sh keep reporting a static component list after the server upgrade, because their supervisor configuration (supervisor.yaml) does not ask the collector for its real inventory; only collectors enrolled on this version report it. Re-run install-opamp.sh on those hosts (or add the reports_available_components capability to their supervisor.yaml and restart the supervisor) so LinkMesh checks attaches against the collector's real component list.
Guide: https://linkmesh.io/docs/how-to/create-a-custom-source-or-destination/
Changing the receiver or exporter type of a custom (raw-body) source or destination that is attached to an OpenTelemetry Collector is refused with 422 component_not_on_collector when that collector lacks the new type, or its inventory is unknown and LinkMesh has no template for it.
Von uns verfasstVor dem Upgrade
If a retype is refused after upgrading, detach the source or destination from the collectors that lack the new component first, or pick a type those collectors contain.
A custom (raw) source or destination body containing a value shaped like an OpenTelemetry Collector extension id (for example file_storage/x or bearertokenauth/y) is refused on save, and a stored one is left out of the generated config with a warning.
Von uns verfasstVor dem Upgrade
Extension ids are generated by LinkMesh, so such a value never named a working extension. After upgrading, check the config generation warnings; for each affected body, declare the extension on the collector or group and reference it as ${ext:<label>} instead of the literal id.
A destination template with a custom body must now name its exporterType; one saved without it is refused (422) on its next save, including a rename.
Von uns verfasstVor dem Upgrade
After upgrading, when you next edit such a destination template, set exporterType to the exporter its body configures; the save is refused until you do. Templates you do not edit keep working.
A custom source or destination body that sets a key its OpenTelemetry Collector component does not have is refused on save (400 raw_yaml_unknown_key), and a stored one is left out of the generated config with a warning.
Von uns verfasstVor dem Upgrade
Such a body made the collector reject its whole configuration and restart in a loop, so removing it lets the rest of the collector run. After upgrading, check the config generation warnings; fix the key's spelling or nesting level (the error names the path and the keys accepted there) and save again.
A source or destination with a custom (raw) body that is attached to a Grafana Alloy collector is no longer rendered there (Alloy used to silently ignore the body and use the type's defaults); attaching one to an Alloy collector is refused.
Von uns verfasstVor dem Upgrade
BEFORE YOU UPGRADE: find custom-body sources and destinations attached to Grafana Alloy collectors. They were running with the type's defaults, not with your body; after the upgrade they stop running on Alloy and the config apply reports a warning. To keep them, move them to an OpenTelemetry Collector (OpAMP) collector, which renders the body as written, or replace them on Alloy with a built-in (non-custom) source or destination. In a group that mixes both runtimes, custom bodies are refused for the whole group.
A source or destination custom body (rawYaml) that references a collector extension directly (auth.authenticator, a storage key, or a literal extension) is refused on save, and a stored one is left out of the generated config with a warning.
Von uns verfasstVor dem Upgrade
Such a body passed validation and then stopped the collector at start. After upgrading, check the config generation warnings. Declare the extension on the collector or group and reference it as ${ext:<label>} (or, for durable delivery on a custom destination, use the Durable Delivery switch), then save again.
On Grafana Alloy collectors, journald sources now apply their Minimum Priority, which they used to ignore; a source set to or defaulting to info stops collecting debug entries there, and every journald source gets a new configuration on the next push.
Von uns verfasstVor dem Upgrade
WHO IS AFFECTED. journald sources running on Grafana Alloy collectors. Before upgrading, decide whether you rely on debug entries from them. If you do, set Minimum Priority to debug on those sources (before or right after the upgrade). Expect lower log volume from Alloy journald sources otherwise; OpenTelemetry Collector journald sources already behaved this way.
An HTTP Check source's timeout now takes effect: an endpoint that does not answer within the timeout (10s unless set) is reported down; a timeout without a unit (for example "10" or "0s") is refused on save.
Von uns verfasstVor dem Upgrade
BEFORE YOU UPGRADE: list HTTP Check sources that probe slow endpoints and raise their Timeout above the endpoint's normal response time; otherwise they start reporting the endpoint as down after the upgrade. Change any timeout written without a unit to a duration such as "10s", or the next save of that source or override is refused.
A source receiverType or destination exporterType that no collector runtime can load is refused with 422 instead of stored (destination templates included); a stored activation with such a type is dropped from the collector's config and reported in the generation warnings.
Von uns verfasstVor dem Upgrade
Collectors that were crash-looping on such a component now start and run everything else, with that component absent. After upgrading, check the config generation warnings; if a source or destination stops reporting data, change its type to one the collector supports.
A config push that needs an extension the collector does not have is no longer sent: the collector keeps its current configuration and is marked incompatible on its detail page.
Von uns verfasstVor dem Upgrade
Declared as breaking by product management, not by a commit footer: before this release such a push reached the collector and stopped it. After upgrading, check collector detail pages for an incompatible marker; it means your latest change has NOT been applied there. Remove the extension requirement or move the collector to a distribution that contains the extension, and the next push goes through.
When a pushed configuration fails to start on an OpenTelemetry Collector (OpAMP), the server now rolls that collector back to its last good configuration instead of leaving it crash-looping on the new one.
Von uns verfasstVor dem Upgrade
Declared as breaking by product management, not by a commit footer: a failed change no longer shows up as a down collector, so anything that relied on that signal (an alert on collector restarts) will stay quiet. After upgrading, watch for collectors and destinations marked misconfigured: that means the last change was rolled back and is NOT running. Fix the cause the destination names (for example a missing TLS file) and push again. How the rollback, the per-source rates on collector cards and the route rule work: https://linkmesh.io/docs/how-to/create-a-custom-source-or-destination/
Upgrading a Debian or Ubuntu package install whose /etc/linkmesh/config.yaml you have edited stops at a dpkg prompt asking whether to keep or replace that file; an unattended upgrade waits there indefinitely.
Von uns verfasstVor dem Upgrade
Declared by product management, not by a commit footer: this release ships new configuration defaults, so dpkg treats config.yaml as a changed configuration file. WHO IS AFFECTED. .deb installs where /etc/linkmesh/config.yaml was edited after installation. WHEN YOU UPGRADE: answer N (keep your currently installed version) when dpkg asks about /etc/linkmesh/config.yaml. For unattended or scripted upgrades pass --force-confold, for example
dpkg -i --force-confold linkmesh-server_<version>.deborapt-get -o Dpkg::Options::=--force-confold install linkmesh-server. AFTER YOU UPGRADE: the new defaults are written beside your file as /etc/linkmesh/config.yaml.dpkg-dist. Compare the two and copy over any new setting you want.
Sicherheitsupdates
This release includes 1 security update in shipped dependencies. Severity not stated by the advisory source.
1 davon hat keinen veröffentlichten Schweregrad; der höchste Schweregrad oben beschreibt sie also nicht.
Welche Pakete und welche Advisories
| Paket | Auf | Schweregrad | Advisory |
|---|---|---|---|
| github.com/klauspost/compress | v1.18.7 | nicht veröffentlicht | GHSA-259r-337f-4rfw |
Fehlerbehebungen
- S-4754 S-5076Source and destination changes on a collector group, Sync Config and Deploy to Fleet now reach every member collector; before, some members never received the configuration.
- S-5112Deploy to Fleet offers fresh collectors for an OTLP source again, instead of claiming that every collector already has the source activated.
- S-4753 S-4904 S-4906Collectors no longer appear offline after a server restart, an offline collector comes back as soon as it reports again, and a restart no longer writes failed logins to the Audit Log.
- S-4896 S-4750 S-4752 S-4579Kubernetes: each node enrolled with a fleet token is its own agent, the Add Collector wizard issues a fleet token for Kubernetes, the Alloy Helm values mount /var/log, and a File Tail position survives a pod being replaced.
- S-5078 S-4836 S-4885 S-4660 S-4529 S-4886 S-4878 S-5080 S-4872Throughput and counts are right: no more millions of records per second after a restart, rates read rec/s, each source shows its own rate on the topology card and the Inputs tab, queue capacity and drop rate are kept on both storage backends, and Active On and the Dashboard count collectors and destinations that run through a group.
- S-4611 S-4578 S-4685Grafana Alloy collectors apply a journald source's minimum priority, run a pipeline's log parser, and no longer report every batch as failed at the last route.
- S-4582An HTTP Check source's timeout now actually bounds the probe.
- S-4905Behind a reverse proxy, the audit log and the login throttle record the real client address taken from your trusted proxies, and a client can no longer choose the address it is recorded under.
- S-4875A route can no longer reference a destination that is not active where the route runs, which previously delivered nothing without saying so.
- S-5079 S-5109The Topology layout saves on single-node (bolt) installs and survives a reload, and an expanded collector card no longer hides under its neighbour.
- S-4832Alert rules can be created, edited and switched on and off again on installs that have the seeded anomaly rules.
- S-4454 S-4455Single sign-on no longer reports a failure after a successful sign-in, and explains why it cannot start on an insecure origin.
- S-4567Git settings can be read again on MongoDB installs.
- S-4620 S-4684Typed source settings and edits in the Add Input dialog are no longer overwritten when the template list finishes loading.
- S-4914 S-4576A plain OAuth token URL is no longer stored as a secret, and a refused credential shows its error on the secret field.
- S-4901 S-5110 S-4908 S-4669 S-4909 S-4584 S-4903 S-4902Smaller fixes: reloading the Health page shows the app, the Health page's Recent Events line up and a collector name there opens without a page reload, activation rows show real dates instead of Never, group details use the same tab layout as collectors, the managed-by tag opens its group, a slow server reads as a timeout, and the SMTP relay is logged at startup.
Funktionen und Verbesserungen
- S-4438 S-4439 S-4441 S-4870Custom sources and destinations: on OpenTelemetry Collector (OpAMP) collectors you can write a component's own configuration body, including component types LinkMesh has no template for, directly from the create and edit dialogs.
- S-4761 S-4763 S-4762 S-4887 S-4951Collector extensions: declare any OpenTelemetry Collector extension on a collector or a group, reference it from a custom body as ${ext:<label>}, and let a built-in destination authenticate through a declared authenticator extension.
- S-4443 S-4871 S-4874 S-4883 S-4882 S-4445 S-4440A custom body or extension that would stop a collector is refused when you save it, not discovered when the collector crash-loops: unknown settings, component types the collector does not have, ports already in use and non-authenticator references are all caught at the write, and a push that needs an extension a collector lacks is withheld and the collector is marked incompatible.
- S-4446 S-4766 S-4447LinkMesh reads each OpenTelemetry Collector's real component inventory and shows which sources, destinations and extensions it cannot run.
- S-4444A custom source or destination now shows its own throughput on the topology canvas and in the route's live throughput, and reads "not reported" when its component emits no throughput counters, instead of borrowing the collector's total.
- S-5077 S-4879When a pushed configuration fails to start, the server rolls the collector back to its last good configuration, and the destination that caused it stays marked misconfigured, naming the missing file.
- S-4898 S-4897 S-4895 S-4900 S-5019Every configuration save is now its own version: Version History marks the configuration your collectors actually run, names the sources and destinations a version touched, and a rollback never discards unsaved changes and says what it does not restore.
- S-4899A connected Git repository is now a read-only mirror of LinkMesh's history: rollbacks reach it, and Settings shows when the repository has diverged, with a way to overwrite it.
- S-4760 S-4916Custom destinations can use durable (disk-backed) delivery, with the Durable Delivery switch available in the UI for raw-mode destinations too.
- S-4910 S-4911The Events tab of a collector and of a group can be searched and paged back through history.
- S-4665 S-4666 S-4667 S-4668 S-4654 S-4912The source and destination dialogs are organised into sections with a table of contents, long field help folds into an icon beside its label, and an agent opens its own detail page.
- S-4907Dark mode is a compact light/dark switch in the top bar that starts from your system setting and remembers your choice, and the help icon is an outlined question mark in the same gray as the other icons.
- S-4862The login page and the SSO settings say plainly when single sign-on needs an Enterprise licence.