Meshery Server Registration
Categories:
Layer5 Cloud is a Meshery Remote Provider. When a Meshery Server is configured to use Layer5 Cloud (SaaS or self-hosted), the server registers itself with Cloud on behalf of the authenticated user. Registration is what makes a particular Meshery Server visible inside Cloud β it appears as a meshery Connection on the user’s account, scoped to their Organization, and becomes the anchor point for everything else the user does through that server (designs, environments, workspaces, events, capabilities).
This page documents the registration behavior implemented by Layer5 Cloud: what the server sends, how Cloud identifies an existing registration vs a new one, and what fields are preserved across re-registration.
Why Registration Exists π
The Meshery Server / Remote Provider boundary has two requirements:
- Identity β Cloud needs to know which Meshery Server is calling, so multiple Meshery deployments can talk to the same Cloud tenant without colliding.
- Ownership β Every Meshery Server registration is owned by exactly one user (and therefore one Organization). All subsequent activity through that server is attributed to that user for audit, RBAC, and tenancy.
A registration record satisfies both: it associates a unique server identifier with a user and an Organization, and it survives across Meshery Server restarts.
Identifying a Meshery Server π
A Meshery Server is identified by a stable server_id it generates on first start and persists locally. The server_id travels in the Connection’s metadata payload.
Cloud’s uniqueness rule for an existing Meshery registration is the triple:
(kind = 'meshery', user_id, metadata.server_id)
The lookup is implemented in ConnectionDAO.CheckMesheryServerExistence. A given user can register many Meshery Servers, and the same Meshery Server can register for many users β but a given (user, server_id) pair maps to exactly one Connection row.
Registration Endpoint π
Meshery Server registers by POSTing a connection payload to:
POST /api/integrations/connections
The request must carry a valid Cloud session (Kratos browser session or JWT). The handler resolves the caller from session context and uses that user’s ID as the owning user_id.
Required payload fields:
| Field | Description |
|---|---|
kind | Must be meshery. |
metadata.server_id | Stable UUID generated by the Meshery Server. |
Optional payload fields:
| Field | Description |
|---|---|
name | Human-readable display name. If omitted, Cloud generates meshery-<random>. |
type / sub_type | Free-form classification fields. |
metadata | Additional JSON metadata (e.g. server version, hostname). |
status | Initial status (defaults to the system’s registered state). |
The handler chain is RegisterConnection β MesheryConnectionUtilityHandlerRegistration β either CreateConnection or UpdateConnection.
What Happens on First Registration π
- The handler validates that the resolved session has a non-nil
user_id. Theconnections.user_idcolumn isNOT NULL; a missing user at this point is a hard error and the request is rejected. CheckMesheryServerExistencelooks for a row matching(meshery, user_id, server_id).- No match is found, so a new row is inserted via
CreateConnection. - The new Connection inherits the user’s Organization for tenant isolation.
What Happens on Re-Registration π
A re-registration is any subsequent call from the same Meshery Server (same server_id) for the same user β typically after a Meshery Server restart, a new browser session, or a Cloud reconnect.
The handler:
- Validates the session’s
user_id(same as first registration). - Finds the existing row via
CheckMesheryServerExistence. - Preserves the existing row’s stable identity fields β
name,kind,type,sub_type,statusβ so a freshly-minted random name from a payload that omittednamecannot rename the existing Meshery Server, and missingtype/sub_typecannot blank them. - Preserves the existing row’s
created_at, setsupdated_at = now(). - Preserves a previously-set
user_id: if the row already has an owner, the existing owner wins; if the row’suser_idis somehow nil, the validated incominguser_idis kept (this guard exists because a historical narrowSELECT id, metadataprojection in the DAO could leave the in-memory row’s UserID nil, which would otherwise UPDATE the row to a nulluser_idand violate the NOT NULL constraint). - Calls
UpdateConnection, which updates every column exceptstatus.
The net effect: re-registering a Meshery Server is safe and idempotent with respect to identity. Only metadata and updated_at are intended to change across re-registrations.
Why status is excluded from updates
Connection status transitions are managed through dedicated lifecycle endpoints (e.g. connect / disconnect, ignore, delete), not through registration. A re-registration call cannot reset a previously-disconnected Meshery Server’s status by accident.Validation and Error Cases π
| Condition | Behavior |
|---|---|
| Session has no resolvable user | Registration is rejected before any DAO call. The caller sees an HTTP 500 with an error describing the missing user_id. |
kind is not in the supported list | HTTP 500 with an “unsupported connection kind” error. |
server_id is missing from metadata | The lookup degenerates to metadata->>'server_id' IS NULL, which will not match any prior registration; a fresh row will be created. Always send a stable server_id. |
| DB error during lookup or write | Wrapped in a structured MeshKit error and returned to the caller. |
Operator Guidance π
If you operate a self-hosted Layer5 Cloud and see registration-related errors, the symptoms below map to the most common root causes:
Postgres 23502/meshery-server-1345during auth completion β the registration call reached the DAO with a niluser_id. This is now caught by the handler-level guard described above; if you see it on a build that pre-dates that guard, upgrade. If you see it on a post-guard build, the session resolution itself is failing β check the logs around the request for missing JWT / Kratos session context.- A Meshery Server appears under the wrong user β check whether the operator authenticated as a different account against the Cloud session. The
user_idis taken from the session, not the payload. - A Meshery Server’s display name keeps changing β pre-fix builds would rename existing rows when the payload omitted
name. Upgrade to a build that preserves stable identity fields on re-registration (the behavior documented above).
Where the Code Lives π
- Handler:
server/handlers/connections.goβRegisterConnection,MesheryConnectionUtilityHandlerRegistration - DAO:
server/dao/connections.goβCheckMesheryServerExistence,CreateConnection,UpdateConnection - Schema:
meshery/schemasβ Connection