Document custom host vitals support for Host vitals labels (#50661)

**Related issue:** N/A

## Summary

Fleet's "Host vitals" label type already supports matching on a custom
host vital's exact value (in addition to the existing IdP-based
criteria), but this wasn't documented anywhere outside the custom host
vitals guide (see companion PR #50660). Adds that coverage across the
remaining references:

- `articles/managing-labels-in-fleet.md`: the "Host vitals" label type
bullet only listed the two IdP criteria; now also mentions custom host
vitals, and notes the type is exact-match only.
- `docs/Configuration/yaml-files.md`:
- Adds a `custom_host_vital` example to the labels GitOps reference,
alongside the existing IdP example.
- Adds a new `## custom_host_vitals` section documenting the top-level
GitOps key used to define vitals in the first place (referenced by the
labels criteria above), which had no reference-doc coverage at all.
Calls out that, unlike `labels`, omitting the key entirely deletes every
existing custom host vital rather than leaving them intact.
- `docs/REST API/rest-api.md`:
- The `criteria` parameter table was missing `custom_host_vital` as a
valid `vital` value and missing `custom_host_vital_id` entirely — added
both.
- None of the 6 registered custom host vitals endpoints (list, create,
update, delete, set a host's value, and the spec/replace-all endpoint
GitOps uses) had reference entries at all. Adds a full "Custom host
vitals" section following the existing "Custom variables" section's
format, including the same destructive replace-all behavior called out
in the YAML reference above.

# Checklist for submitter

- [ ] QA'd all new/changed functionality manually

---------

Co-authored-by: Rachael Shaw <r@rachael.wtf>
This commit is contained in:
kitzy
2026-08-06 12:17:45 -05:00
committed by GitHub
co-authored by Rachael Shaw
parent e0ab271ff1
commit 7d59390b5c
3 changed files with 261 additions and 6 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ In Fleet, labels organize hosts into groups you can target with [software](https
- **Dynamic:** Query-based; auto-applied to any host returning a result for the label's SQL query. Optionally restrict to a platform (`darwin`, `windows`, `ubuntu`, `centos`).
- **Manual:** Applied to an explicit list of hosts, specified by `hardware_serial`, `uuid`, or Fleet host ID. Useful for one-off groupings (e.g., a pilot group).
- **Host vitals:** Auto-applied to hosts matching a host vital from your IdP. Supported criteria: `end_user_idp_group` and `end_user_idp_department`. Requires a connected IdP (Okta, Microsoft Entra ID, Google Workspace, authentik, or any SCIM provider; see [Foreign host vitals](https://fleetdm.com/guides/foreign-vitals-map-idp-users-to-hosts)).
- **Host vitals:** Auto-applied to hosts matching a single host vital's value (exact match only). Supported criteria: `end_user_idp_group` and `end_user_idp_department`, which require a connected IdP (Okta, Microsoft Entra ID, Google Workspace, authentik, or any SCIM provider; see [Foreign host vitals](https://fleetdm.com/guides/foreign-vitals-map-idp-users-to-hosts)), or any [custom host vital](https://fleetdm.com/guides/custom-host-vitals) you've defined.
> To change a dynamic label's query/platform or a host vitals label's criteria in the UI, you must delete and re-create it.
+31 -1
View File
@@ -6,6 +6,29 @@ Quick start: [install fleetctl](https://fleetdm.com/guides/fleetctl#installing-f
> Want to get hands-on? We run [free GitOps workshops globally](https://fleetdm.com/gitops-workshop) where you can get certified.
## custom_host_vitals
[Custom host vitals](https://fleetdm.com/guides/custom-host-vitals) are global and can only be specified inline in your `default.yml` file. They cannot be specified in `fleets/fleet-name.yml` or `fleets/unassigned.yml`.
- `name` specifies the vital's name. Must be unique across all custom host vitals.
Each vital is assigned an ID by Fleet when it's created, which isn't set in YAML. Find it in the Custom host vitals table in the Fleet UI to reference the vital as `$FLEET_HOST_VITAL_<id>` in scripts and configuration profiles, or as `custom_host_vital_id` in a [Host vitals label](#labels)'s `criteria`.
> `custom_host_vitals` is an optional key, but unlike `labels`, omitting it entirely deletes every existing custom host vital. To keep existing vitals, list them.
>
> Removing an entry deletes that vital on the next GitOps run. A run fails if the vital is still referenced by a script, configuration profile, or Host vitals label. Remove the reference first.
### Example
`default.yml`
```yaml
custom_host_vitals:
- name: Asset tag
- name: Function
- name: ITAM device ID
```
## labels
Labels can be specified in your `default.yml` and `fleets/fleet-name.yml` files using inline configuration or references to separate files in your `lib/` folder. Labels cannot be specified in `fleets/unassigned.yml`.
@@ -19,7 +42,7 @@ Labels support `path:` (single file) and `paths:` (glob pattern) references. See
- `label_membership_type` specifies label type which determines how hosts are added to the label. Choices for type are `dynamic` , `manual`, and `host_vitals` (default: `dynamic`).
- `query` is the query in SQL syntax used to filter the hosts. Only supported if `label_membership_type` is `dynamic`.
- `hosts` is a list of host identifiers (`id`, `hardware_serial`, or `uuid`). The label will apply to any host with a matching identifier. Only supported if `label_membership_type` is `manual`. If omitted, existing host membership is preserved (no changes). If provided but empty, all hosts are removed from the label.
- `criteria` - is the criteria for adding hosts to a host vitals label. Hosts with `vital` data matching the specified `value` will be added to the label. See [criteria](https://fleetdm.com/docs/rest-api/rest-api#criteria) documentation for details.
- `criteria` is the criteria for adding hosts to a host vitals label. Hosts with `vital` data matching the specified `value` will be added to the label. To match on a [custom host vital](https://fleetdm.com/guides/custom-host-vitals), set `vital` to `custom_host_vital` and also specify `custom_host_vital_id`. See [criteria](https://fleetdm.com/docs/rest-api/rest-api#criteria) documentation for details.
Only one of `query`, `hosts`, or `criteria` can be specified. If none are specified, a manual label with no hosts will be created.
@@ -58,6 +81,13 @@ labels:
criteria:
vital: end_user_idp_department
value: Engineering
- name: Point of sale terminals
description: Hosts whose "Function" custom host vital is set to "Point of sale"
label_membership_type: host_vitals
criteria:
vital: custom_host_vital
custom_host_vital_id: 2
value: Point of sale
```
#### Separate file
+229 -4
View File
@@ -23,6 +23,7 @@
- [Translator](#translator)
- [Users](#users)
- [Custom variables](#custom-variables)
- [Custom host vitals](#custom-host-vitals)
- [API errors](#api-responses)
Use the Fleet APIs to automate Fleet.
@@ -6392,10 +6393,11 @@ The `hostname` host identifier is deprecated. Please use `host_ids`, `hardware_s
#### criteria
| Name | Type | Description |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vital | string | The type of host vital to use when creating a host vital label. Can be `"end_user_idp_group"` or `"end_user_idp_department"`. |
| value | string | Hosts with vital data matching this value will be added to the label. |
| Name | Type | Description |
| --------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vital | string | The type of host vital to use when creating a host vital label. Can be `"end_user_idp_group"`, `"end_user_idp_department"`, or `"custom_host_vital"`. |
| custom_host_vital_id | integer | The ID of the [custom host vital](https://fleetdm.com/guides/custom-host-vitals) to match on. Required when `vital` is `"custom_host_vital"`. |
| value | string | Hosts with vital data matching this value will be added to the label. |
#### Example
@@ -16652,6 +16654,229 @@ Removes a custom variable from Fleet.
`Status: 200`
## Custom host vitals
- [List custom host vitals](#list-custom-host-vitals)
- [Create custom host vital](#create-custom-host-vital)
- [Update custom host vital](#update-custom-host-vital)
- [Delete custom host vital](#delete-custom-host-vital)
- [Update host's custom host vital value](#update-hosts-custom-host-vital-value)
- [Replace all custom host vitals](#replace-all-custom-host-vitals)
### List custom host vitals
Lists all [custom host vitals](https://fleetdm.com/guides/custom-host-vitals), which can be referenced as `$FLEET_HOST_VITAL_<id>` in scripts and configuration profiles, or as `custom_host_vital_id` in a Host vitals label's [`criteria`](#criteria).
`GET /api/v1/fleet/custom_host_vitals`
#### Parameters
| Name | Type | In | Description |
|:--------------- |:------- |:----- |:------------------------------------------------------------|
| query | string | query | Search query. Matches against the vital's name or its `$FLEET_HOST_VITAL_<id>` variable. |
| page | integer | query | Page number of the results to fetch. |
| per_page | integer | query | Results per page. |
| order_key | string | query | What to order results by. Allowed fields are `name`, `id`, and `updated_at`. Default is `name`. |
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `"asc"` and `"desc"`. Default is `"asc"`. |
| after | string | query | The value to get results after. This needs `order_key` defined, as that's the column that would be used. |
#### Example
`GET /api/v1/fleet/custom_host_vitals`
##### Default response
`Status: 200`
```json
{
"custom_host_vitals": [
{
"id": 1,
"name": "Asset tag",
"created_at": "2026-06-04T15:22:36Z",
"updated_at": "2026-06-04T15:22:36Z"
}
],
"meta": {
"has_next_results": false,
"has_previous_results": false
},
"count": 1
}
```
### Create custom host vital
Creates a custom host vital.
`POST /api/v1/fleet/custom_host_vitals`
#### Parameters
| Name | Type | In | Description |
|:---- |:------ |:---- |:--------------------------------------------|
| name | string | body | **Required.** The vital's name, without the `FLEET_HOST_VITAL_` prefix. Must be unique across all custom host vitals (case-insensitive), and 255 characters or fewer. |
Fails with a `409` if a custom host vital with this name already exists.
#### Example
`POST /api/v1/fleet/custom_host_vitals`
##### Request body
```json
{
"name": "Asset tag"
}
```
##### Default response
`Status: 200`
```json
{
"custom_host_vital": {
"id": 1,
"name": "Asset tag",
"created_at": "2026-06-04T15:22:36Z",
"updated_at": "2026-06-04T15:22:36Z"
}
}
```
### Update custom host vital
Renames a custom host vital. The vital's ID, its `$FLEET_HOST_VITAL_<id>` variable, and any host values already set for it, are unaffected.
`PATCH /api/v1/fleet/custom_host_vitals/:id`
#### Parameters
| Name | Type | In | Description |
|:---- |:------- |:---- |:----------------------------------------|
| id | integer | path | **Required.** The custom host vital's ID. |
| name | string | body | **Required.** The vital's new name. |
Fails with a `409` if another custom host vital already has this name.
#### Example
`PATCH /api/v1/fleet/custom_host_vitals/1`
##### Request body
```json
{
"name": "Asset tag number"
}
```
##### Default response
`Status: 200`
```json
{
"custom_host_vital": {
"id": 1,
"name": "Asset tag number",
"created_at": "2026-06-04T15:22:36Z",
"updated_at": "2026-06-05T09:03:11Z"
}
}
```
### Delete custom host vital
Deletes a custom host vital, along with any per-host values set for it.
`DELETE /api/v1/fleet/custom_host_vitals/:id`
#### Parameters
| Name | Type | In | Description |
|:---- |:------- |:---- |:----------------------------------------|
| id | integer | path | **Required.** The custom host vital's ID. |
Fails with a `409` if the vital is still referenced by a script, configuration profile, or Host vitals label. Remove the reference first.
#### Example
`DELETE /api/v1/fleet/custom_host_vitals/1`
##### Default response
`Status: 200`
### Update host's custom host vital value
Sets a host's value for a custom host vital.
`PUT /api/v1/fleet/hosts/:host_id/custom_host_vitals/:id`
#### Parameters
| Name | Type | In | Description |
|:------- |:------- |:---- |:---------------------------------------------------|
| host_id | integer | path | **Required.** The host's ID. |
| id | integer | path | **Required.** The custom host vital's ID. |
| value | string | body | **Required.** The value to set for this host. |
#### Example
`PUT /api/v1/fleet/hosts/123/custom_host_vitals/1`
##### Request body
```json
{
"value": "C02XL0Zerato"
}
```
##### Default response
`Status: 200`
### Replace all custom host vitals
Replaces all existing custom host vital definitions with the provided list. Existing vitals not included in the list are deleted, which fails if one of them is still referenced by a script, configuration profile, or Host vitals label.
`PUT /api/v1/fleet/spec/custom_host_vitals`
#### Parameters
| Name | Type | In | Description |
|:------------------ |:------- |:---- |:---------------------------------------------------|
| custom_host_vitals | array | body | The full list of custom host vitals. Each item is an object with a `name`. |
| dry_run | boolean | body | If `true`, validates the request without applying changes. Default is `false`. |
> Omitting `custom_host_vitals` from the request, or sending an empty list, deletes every existing custom host vital. This is the endpoint `fleetctl gitops` uses to apply the `custom_host_vitals:` key in `default.yml`.
#### Example
`PUT /api/v1/fleet/spec/custom_host_vitals`
##### Request body
```json
{
"custom_host_vitals": [
{ "name": "Asset tag" },
{ "name": "Function" },
{ "name": "ITAM device ID" }
]
}
```
##### Default response
`Status: 200`
## API errors
Fleet returns API errors as a JSON document with the following fields: