From 9e745510d9fd98a876594e5c01d9d2cfb0a6801e Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Wed, 29 Jul 2026 09:50:02 -0600 Subject: [PATCH 1/7] docs: add Fern scaffolding and publish agent docs to docs.nvidia.com/fleet-intel/agent - Restructure docs/ into versioned subdirectories (1.2/, 1.3/) sourced from the v1.2.1 and v1.3.1 release tags respectively, making the repo the single source of truth for agent documentation - Add fern/ scaffold (docs.yml, fern.config.json) targeting docs.nvidia.com/fleet-intel/agent with a 1.2/1.3 version selector; version management is manual per minor release, not per patch tag - Add docs/index-1.2.yml and docs/index-1.3.yml navigation files - Add GitHub Actions workflows for Fern CI (check + lychee link check), PR preview (build + comment), and publish on release - Fix MDX safety issues in both doc versions (bare angle brackets, autolink syntax) and replace cross-directory ../CONTRIBUTING.md link with a GitHub blob URL - Update README to direct users to docs.nvidia.com/fleet-intel/agent rather than the in-repo docs/ files Co-Authored-By: Claude Sonnet 4.6 (1M context) Signed-off-by: Ed Balduf --- .github/workflows/fern-docs-ci.yml | 124 ++++++ .github/workflows/fern-docs-preview-build.yml | 140 +++++++ .../workflows/fern-docs-preview-comment.yml | 152 +++++++ .github/workflows/publish-fern-docs.yml | 65 +++ README.md | 12 +- docs/{ => 1.2}/architecture.md | 0 docs/1.2/configuration.md | 202 +++++++++ docs/{ => 1.2}/development.md | 4 +- docs/1.2/install-deb.md | 91 +++++ docs/1.2/install-helm.md | 228 +++++++++++ docs/1.2/install-rpm.md | 115 ++++++ docs/1.2/usage.md | 385 ++++++++++++++++++ docs/1.3/architecture.md | 93 +++++ docs/{ => 1.3}/configuration.md | 0 docs/1.3/development.md | 194 +++++++++ docs/{ => 1.3}/install-deb.md | 6 +- docs/{ => 1.3}/install-helm.md | 0 docs/{ => 1.3}/install-rpm.md | 6 +- docs/{ => 1.3}/usage.md | 2 +- docs/index-1.2.yml | 25 ++ docs/index-1.3.yml | 25 ++ fern/.gitignore | 2 + fern/docs.yml | 41 ++ fern/fern.config.json | 4 + 24 files changed, 1898 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/fern-docs-ci.yml create mode 100644 .github/workflows/fern-docs-preview-build.yml create mode 100644 .github/workflows/fern-docs-preview-comment.yml create mode 100644 .github/workflows/publish-fern-docs.yml rename docs/{ => 1.2}/architecture.md (100%) create mode 100644 docs/1.2/configuration.md rename docs/{ => 1.2}/development.md (96%) create mode 100644 docs/1.2/install-deb.md create mode 100644 docs/1.2/install-helm.md create mode 100644 docs/1.2/install-rpm.md create mode 100644 docs/1.2/usage.md create mode 100644 docs/1.3/architecture.md rename docs/{ => 1.3}/configuration.md (100%) create mode 100644 docs/1.3/development.md rename docs/{ => 1.3}/install-deb.md (88%) rename docs/{ => 1.3}/install-helm.md (100%) rename docs/{ => 1.3}/install-rpm.md (90%) rename docs/{ => 1.3}/usage.md (99%) create mode 100644 docs/index-1.2.yml create mode 100644 docs/index-1.3.yml create mode 100644 fern/.gitignore create mode 100644 fern/docs.yml create mode 100644 fern/fern.config.json diff --git a/.github/workflows/fern-docs-ci.yml b/.github/workflows/fern-docs-ci.yml new file mode 100644 index 00000000..2d8d698f --- /dev/null +++ b/.github/workflows/fern-docs-ci.yml @@ -0,0 +1,124 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Validates Fern docs configuration on pull requests that touch docs or fern/. + +name: Fern Docs CI + +on: + pull_request: + paths: + - 'docs/**' + - 'fern/**' + - '.github/workflows/fern-docs-ci.yml' + workflow_dispatch: {} + ## --- OPTION: NVIDIA copy-PR-bot trigger --- + ## Replace the pull_request block above with: + # push: + # branches: + # - "pull-request/[0-9]+" + # paths: + # - 'docs/**' + # - 'fern/**' + # - '.github/workflows/fern-docs-ci.yml' + ## and add the changed-files gating job below (uncomment the full block). + +permissions: + contents: read + +jobs: + ## --- OPTION: copy-PR-bot changed-files gate --- + ## Uncomment this job and add "needs: changed-files" + + ## "if: needs.changed-files.outputs.docs == 'true'" to fern-check when + ## using push-to-pull-request/* triggers without paths: filters. + # + # changed-files: + # runs-on: ubuntu-latest + # outputs: + # docs: ${{ steps.changes.outputs.docs }} + # steps: + # - name: Checkout code + # uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + # with: + # fetch-depth: 0 + # + # - name: Check for docs changes + # id: changes + # run: | + # if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + # echo "docs=true" >> $GITHUB_OUTPUT + # elif [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then + # echo "docs=true" >> $GITHUB_OUTPUT + # elif git diff --name-only "${{ github.event.before }}" HEAD 2>/dev/null | grep -qE '^(docs/|fern/)'; then + # echo "docs=true" >> $GITHUB_OUTPUT + # else + # echo "docs=false" >> $GITHUB_OUTPUT + # fi + + fern-check: + name: Fern Check + runs-on: ubuntu-latest + # runs-on: linux-amd64-cpu8 # NVIDIA self-hosted runner + timeout-minutes: 10 + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + ## --- OPTION: filename convention check (warning) --- + # - name: Warn on non-lowercase or underscore markdown filenames + # run: | + # find docs/ -name "*.md" | while read f; do + # base=$(basename "$f") + # if echo "$base" | grep -qE '[A-Z]|_'; then + # suggested=$(echo "$base" | tr '[:upper:]' '[:lower:]' | tr '_' '-') + # echo "::warning file=$f::Filename '$base' should be lowercase with hyphens (e.g. '$suggested')" + # fi + # done + + ## --- OPTION: filename convention check (hard fail) --- + # - name: Check markdown filename conventions + # run: | + # BAD=$(find docs/ -name '*.md' | grep -E '[A-Z_]' || true) + # if [ -n "$BAD" ]; then + # echo "::error::Markdown filenames must be lowercase with hyphens only:" + # echo "$BAD" + # exit 1 + # fi + + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20' + + - name: Install Fern CLI + run: npm install -g fern-api@$(jq -r .version fern/fern.config.json) + + - name: Check MDX safety + run: | + BAD=$(grep -rn ']*[^/]>\|' docs/ fern/ --include="*.md" --include="*.mdx" || true) + if [ -n "$BAD" ]; then + echo "::error::Non-self-closing tags found (MDX requires ):" + echo "$BAD" + exit 1 + fi + + - name: Fern check + run: fern check + + - name: Check links + uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0 + with: + args: --offline --no-progress 'docs/**/*.md' + fail: true diff --git a/.github/workflows/fern-docs-preview-build.yml b/.github/workflows/fern-docs-preview-build.yml new file mode 100644 index 00000000..b6274688 --- /dev/null +++ b/.github/workflows/fern-docs-preview-build.yml @@ -0,0 +1,140 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Workflow 1 of 2 for Fern doc previews. +# +# Collects the fern/ and docs/ sources plus PR metadata from the PR branch and +# uploads them as an artifact. Both directories are needed because +# fern/docs.yml references ../docs/index.yml; omitting docs/ causes +# `fern generate --docs` to fail in the companion workflow. No secrets are +# used here, so this is safe to run on fork PRs via the regular pull_request +# trigger. +# +# The companion workflow (fern-docs-preview-comment.yml) picks up the artifact, +# builds the preview with DOCS_FERN_TOKEN, and posts the PR comment. + +name: "Preview Fern Docs: Build" + +on: + pull_request: + paths: + - 'docs/**' + - 'fern/**' + - '.github/workflows/fern-docs-preview-build.yml' + ## --- OPTION: NVIDIA copy-PR-bot trigger --- + ## Replace the pull_request block above with: + # push: + # branches: + # - "pull-request/[0-9]+" + # paths: + # - 'docs/**' + # - 'fern/**' + # - '.github/workflows/fern-docs-preview-build.yml' + ## and switch the "Save PR metadata" step to the copy-PR-bot variant below. + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + ## --- OPTION: copy-PR-bot changed-files gate --- + ## Uncomment this job and add "needs: changed-files" + + ## "if: needs.changed-files.outputs.docs == 'true'" to collect when using + ## push-to-pull-request/* triggers without paths: filters. + # + # changed-files: + # runs-on: ubuntu-latest + # outputs: + # docs: ${{ steps.changes.outputs.docs }} + # steps: + # - name: Checkout code + # uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + # with: + # fetch-depth: 0 + # + # - name: Check for docs changes + # id: changes + # run: | + # if [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then + # echo "docs=true" >> $GITHUB_OUTPUT + # elif git diff --name-only "${{ github.event.before }}" HEAD 2>/dev/null | grep -qE '^(docs/|fern/)'; then + # echo "docs=true" >> $GITHUB_OUTPUT + # else + # echo "docs=false" >> $GITHUB_OUTPUT + # fi + + collect: + runs-on: ubuntu-latest + # runs-on: linux-amd64-cpu8 # NVIDIA self-hosted runner + timeout-minutes: 10 + steps: + - name: Checkout PR + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Save PR metadata + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + HEAD_REF: ${{ github.head_ref }} + BASE_REF: ${{ github.base_ref }} + run: | + mkdir -p preview-metadata + echo "$PR_NUMBER" > preview-metadata/pr_number + echo "$HEAD_REF" > preview-metadata/head_ref + git diff --name-only "origin/${BASE_REF}...HEAD" -- '*.md' > preview-metadata/changed_md_files 2>/dev/null || true + ## --- OPTION: copy-PR-bot metadata extraction --- + ## Replace the step above with this when using push-to-pull-request/*: + # - name: Save PR metadata + # env: + # BRANCH_NAME: ${{ github.ref_name }} + # run: | + # mkdir -p preview-metadata + # echo "${BRANCH_NAME#pull-request/}" > preview-metadata/pr_number + # echo "$BRANCH_NAME" > preview-metadata/head_ref + # git diff --name-only "origin/main...HEAD" -- '*.md' > preview-metadata/changed_md_files 2>/dev/null || true + + - name: Checkout frozen version content + run: | + set -eo pipefail + for version_file in fern/versions/v*.yml; do + [ -f "$version_file" ] || continue + version=$(basename "$version_file" .yml) + if git show-ref --verify --quiet "refs/tags/${version}"; then + mkdir -p "fern/versions/${version}-content" + git archive "refs/tags/${version}" -- docs/ | tar -x --strip-components=1 -C "fern/versions/${version}-content" + find "fern/versions/${version}-content" -name '*.md' -print0 | xargs -0 -r sed -i \ + -e 's/{/\\{/g' \ + -e 's/}/\\}/g' \ + -e 's/> "$GITHUB_OUTPUT" + echo "head_ref=$(cat preview-metadata/head_ref)" >> "$GITHUB_OUTPUT" + + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20' + + - name: Install Fern CLI + run: | + set -euo pipefail + VERSION=$(jq -r .version fern/fern.config.json) + if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?$ ]]; then + echo "::error::fern.config.json .version '$VERSION' is not a valid semver" + exit 1 + fi + npm install -g "fern-api@${VERSION}" + + - name: Generate preview URL + id: generate-docs + env: + FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }} + HEAD_REF: ${{ steps.metadata.outputs.head_ref }} + working-directory: ./fern + run: | + set -o pipefail + fern generate --docs --preview --id "$HEAD_REF" 2>&1 | tee /tmp/fern-output.log + URL=$(grep -oP 'Published docs to \K.*(?= \()' /tmp/fern-output.log || true) + if [ -z "$URL" ]; then + echo "::error::Failed to generate preview URL. See fern output above." + exit 1 + fi + echo "preview_url=$URL" >> "$GITHUB_OUTPUT" + + - name: Build page links for changed files + id: page-links + env: + FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }} + PREVIEW_URL: ${{ steps.generate-docs.outputs.preview_url }} + run: | + CHANGED_FILES="" + if [ -f preview-metadata/changed_md_files ]; then + CHANGED_FILES=$(cat preview-metadata/changed_md_files) + fi + + if [ -z "$CHANGED_FILES" ] || [ -z "$PREVIEW_URL" ]; then + echo "page_links=" >> "$GITHUB_OUTPUT"; exit 0 + fi + + BASE_URL=$(echo "$PREVIEW_URL" | grep -oP 'https?://[^/]+') + FILES_PARAM=$(echo "$CHANGED_FILES" | tr '\n' ',' | sed 's/,$//' \ + | python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=',/'))") + RESPONSE=$(curl -sf -H "FERN_TOKEN: $FERN_TOKEN" "${PREVIEW_URL}/api/fern-docs/get-slug-for-file?files=${FILES_PARAM}" 2>/dev/null) || { + echo "page_links=" >> "$GITHUB_OUTPUT"; exit 0 + } + + PAGE_LINKS=$(echo "$RESPONSE" | jq -r --arg url "$BASE_URL" \ + '.mappings[] | select(.slug != null) | "- [\(.slug)](\($url)/\(.slug))"') + + if [ -n "$PAGE_LINKS" ]; then + { echo "page_links<> "$GITHUB_OUTPUT" + else + echo "page_links=" >> "$GITHUB_OUTPUT" + fi + + - name: Post or update PR comment + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ steps.metadata.outputs.pr_number }} + PREVIEW_URL: ${{ steps.generate-docs.outputs.preview_url }} + PAGE_LINKS: ${{ steps.page-links.outputs.page_links }} + run: | + BODY=":herb: **Preview your docs:** <${PREVIEW_URL}>" + if [ -n "${PAGE_LINKS}" ]; then + BODY="${BODY} + + Here are the markdown pages you've updated: + ${PAGE_LINKS}" + fi + + MARKER="" + BODY="${BODY} + + ${MARKER}" + + COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \ + --jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | tr -d '\r' | head -1) + + if [ -n "$COMMENT_ID" ]; then + gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \ + -X PATCH -f body="$BODY" + else + gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \ + -f body="$BODY" + fi diff --git a/.github/workflows/publish-fern-docs.yml b/.github/workflows/publish-fern-docs.yml new file mode 100644 index 00000000..51956e72 --- /dev/null +++ b/.github/workflows/publish-fern-docs.yml @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Publishes the Fern documentation site on GitHub Release or manual dispatch. +# +# Version management (1.2, 1.3, ...) is handled manually in fern/docs.yml — +# individual patch releases do not create separate version tabs. Update +# fern/docs.yml and docs/index-.yml when a new minor version ships. +# +# Required configuration: +# - Organization secret: DOCS_FERN_TOKEN (from `fern token` for the nvidia Fern org) + +name: Publish Fern Docs + +on: + release: + types: [published] + workflow_dispatch: {} + +permissions: + contents: read + +concurrency: + group: fern-publish + cancel-in-progress: true + +jobs: + publish: + runs-on: ubuntu-latest + # runs-on: linux-amd64-cpu8 # NVIDIA self-hosted runner + timeout-minutes: 20 + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20' + + - name: Install Fern CLI + run: npm install -g fern-api@$(jq -r .version fern/fern.config.json) + + - name: Publish docs + env: + FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }} + run: | + set -o pipefail + fern generate --docs 2>&1 | tee /tmp/fern-output.log + URL=$(grep -oP 'Published docs to \K.*(?= \()' /tmp/fern-output.log || true) + if [ -n "$URL" ]; then + echo "### Published: [$URL]($URL)" >> "$GITHUB_STEP_SUMMARY" + fi diff --git a/README.md b/README.md index 8e86429f..8f2de673 100644 --- a/README.md +++ b/README.md @@ -47,15 +47,9 @@ contains enrollment credentials. ## Documentation -**Important:** Documentation links are relative to the branch or tag you are viewing. The default GitHub view uses `main`, which may describe unreleased changes. When installing or upgrading a specific agent version, switch to that version's release tag first. - -- [Helm Installation](docs/install-helm.md) - Kubernetes (Helm) installation and troubleshooting -- [DEB Installation](docs/install-deb.md) - Ubuntu package install, update, and uninstall -- [RPM Installation](docs/install-rpm.md) - RHEL/Rocky/Alma/Amazon package install, update, and uninstall -- [Architecture](docs/architecture.md) - Bare metal and Kubernetes architecture, dependencies, and runtime flow -- [Usage](docs/usage.md) - Commands, HTTP API, integration, and troubleshooting -- [Configuration](docs/configuration.md) - Environment variables and service configuration -- [Development](docs/development.md) - Building from source and contributing +Full documentation is available at **[docs.nvidia.com/fleet-intel/agent](https://docs.nvidia.com/fleet-intel/agent)**, including installation guides, configuration reference, architecture overview, and usage examples. + +For the broader Fleet Intelligence platform documentation, see [docs.nvidia.com/fleet-intel](https://docs.nvidia.com/fleet-intel). ## Contributing diff --git a/docs/architecture.md b/docs/1.2/architecture.md similarity index 100% rename from docs/architecture.md rename to docs/1.2/architecture.md diff --git a/docs/1.2/configuration.md b/docs/1.2/configuration.md new file mode 100644 index 00000000..9ec52f38 --- /dev/null +++ b/docs/1.2/configuration.md @@ -0,0 +1,202 @@ +# Configuration + +This page documents the runtime configuration for `fleetint run`: +- configurable environment variables +- configurable `fleetint run` flags +- how to set them on bare metal and in Kubernetes + +## Where to configure + +### Bare Metal + +Package installs run `fleetint` through the `fleetintd` systemd service: + +```ini +ExecStart=/usr/bin/fleetint run $FLEETINT_FLAGS +``` + +Configure runtime settings in `/etc/default/fleetint`, then restart the service: + +```bash +sudo systemctl restart fleetintd +``` + +- Set environment variables directly in `/etc/default/fleetint` +- Set `fleetint run` flags through `FLEETINT_FLAGS="..."` + +### Kubernetes + +The Helm chart configures the container entrypoint as `fleetint run` and exposes: + +- environment variables under `env.*` +- common `run` flags through dedicated chart values such as `logLevel`, `listenAddress`, and `components` + +Apply changes by updating `values.yaml` or using `helm upgrade --set ...`. + +## Configurable Environment Variables + +These environment variables are read by `fleetint run` at startup. + +| Environment variable | Description | Default | Bare metal | Kubernetes | +| --- | --- | --- | --- | --- | +| `DCGM_URL` | DCGM HostEngine address used by the agent for DCGM-backed components. | bare metal: `localhost`, Helm chart: `nvidia-dcgm.gpu-operator.svc:5555` | `/etc/default/fleetint` | `env.DCGM_URL` | +| `DCGM_URL_IS_UNIX_SOCKET` | Treat `DCGM_URL` as a Unix socket path instead of a network address. | `false` | `/etc/default/fleetint` | `env.DCGM_URL_IS_UNIX_SOCKET` | +| `FLEETINT_COLLECT_INTERVAL` | Export interval for health data. Valid range: `1s` to `24h`. | `1m` | `/etc/default/fleetint` | `env.FLEETINT_COLLECT_INTERVAL` | +| `FLEETINT_INCLUDE_METRICS` | Include metrics data in export payloads. | `true` | `/etc/default/fleetint` | `env.FLEETINT_INCLUDE_METRICS` | +| `FLEETINT_INCLUDE_EVENTS` | Include event data in export payloads. | `true` | `/etc/default/fleetint` | `env.FLEETINT_INCLUDE_EVENTS` | +| `FLEETINT_INCLUDE_MACHINEINFO` | Include machine information in export payloads. | `true` | `/etc/default/fleetint` | `env.FLEETINT_INCLUDE_MACHINEINFO` | +| `FLEETINT_INCLUDE_HEALTHCHECKS` | Include component data and health details in export payloads. | `true` | `/etc/default/fleetint` | `env.FLEETINT_INCLUDE_HEALTHCHECKS` | +| `FLEETINT_METRICS_LOOKBACK` | Lookback window for metrics included in each export. | `1m` | `/etc/default/fleetint` | `env.FLEETINT_METRICS_LOOKBACK` | +| `FLEETINT_EVENTS_LOOKBACK` | Lookback window for events included in each export. | `1m` | `/etc/default/fleetint` | `env.FLEETINT_EVENTS_LOOKBACK` | +| `FLEETINT_CHECK_INTERVAL` | Health check interval for monitored components. Valid range: `1s` to `24h`. | `1m` | `/etc/default/fleetint` | `env.FLEETINT_CHECK_INTERVAL` | +| `FLEETINT_RETRY_MAX_ATTEMPTS` | Maximum retry attempts for failed exports. Minimum: `0`. | `3` | `/etc/default/fleetint` | `env.FLEETINT_RETRY_MAX_ATTEMPTS` | +| `FLEETINT_ATTESTATION_JITTER_ENABLED` | Enable random startup jitter for attestation scheduling. | `true` | `/etc/default/fleetint` | `env.FLEETINT_ATTESTATION_JITTER_ENABLED` | +| `FLEETINT_ATTESTATION_INTERVAL` | Attestation interval override. | `24h` | `/etc/default/fleetint` | `env.FLEETINT_ATTESTATION_INTERVAL` | +| `HTTP_PROXY` | Proxy URL for outbound HTTP requests. | empty | `/etc/default/fleetint` | `env.HTTP_PROXY` | +| `HTTPS_PROXY` | Proxy URL for outbound HTTPS requests. | empty | `/etc/default/fleetint` | `env.HTTPS_PROXY` | + +Notes: + +- Duration-valued environment variables use Go duration syntax such as `30s`, `1m`, `10m`, or `24h`. +- These environment variables modify the health exporter configuration used by `fleetint run`. +- `DCGM_URL` and `DCGM_URL_IS_UNIX_SOCKET` configure connectivity to DCGM HostEngine for DCGM-backed components. + +### Bare Metal Example + +```bash +sudoedit /etc/default/fleetint +``` + +```bash +FLEETINT_FLAGS="--log-level=info --components=all,-accelerator-nvidia-dcgm-prof" +DCGM_URL="localhost" +DCGM_URL_IS_UNIX_SOCKET="false" +FLEETINT_COLLECT_INTERVAL="2m" +FLEETINT_INCLUDE_EVENTS="false" +FLEETINT_CHECK_INTERVAL="30s" +HTTPS_PROXY="http://proxy.example.com:3128" +``` + +```bash +sudo systemctl restart fleetintd +``` + +### Kubernetes Example + +```yaml +logLevel: info +listenAddress: 0.0.0.0:15133 +retentionPeriod: 24h +components: all,-accelerator-nvidia-dcgm-prof + +env: + DCGM_URL: "nvidia-dcgm.gpu-operator.svc:5555" + DCGM_URL_IS_UNIX_SOCKET: "false" + FLEETINT_COLLECT_INTERVAL: "2m" + FLEETINT_INCLUDE_EVENTS: "false" + FLEETINT_CHECK_INTERVAL: "30s" + HTTPS_PROXY: "http://proxy.example.com:3128" +``` + +Apply with: + +```bash +helm upgrade --install fleet-intelligence-agent \ + oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + -n \ + -f values.yaml +``` + +## Configurable `fleetint run` Flags + +These are the `fleetint run` flags supported by the CLI. + +| Flag | Description | Default | Bare metal | Kubernetes | +| --- | --- | --- | --- | --- | +| `--log-level` | Log level: `debug`, `info`, `warn`, `error`. | unset by CLI; packaged bare-metal default is `warn` via `FLEETINT_FLAGS` | `FLEETINT_FLAGS="--log-level=..."` | `logLevel` | +| `--log-file` | Log file path. Leave empty to log to stdout/stderr. | empty | `FLEETINT_FLAGS="--log-file=..."` | not exposed by chart by default | +| `--listen-address` | Listen address for the agent API server. An absolute path creates a Unix socket; a `host:port` value opens a TCP listener. | `/run/fleetint/fleetint.sock` | `FLEETINT_FLAGS="--listen-address=..."` | `listenAddress` | +| `--retention-period` | Retention period for stored metrics and events. Minimum `1m`. | `24h` | `FLEETINT_FLAGS="--retention-period=..."` | `retentionPeriod` | +| `--components` | Comma-separated component selection. Use `all`, `*`, explicit names, and `-name` exclusions. | empty flag value, which means enable all components by default | `FLEETINT_FLAGS="--components=..."` | `components` | +| `--offline-mode` | Disable the HTTP API server and write telemetry to files instead. | `false` | `FLEETINT_FLAGS="--offline-mode ..."` | not exposed by chart by default | +| `--path` | Absolute path to the output directory for offline mode. Must not point inside restricted system directories. Required with `--offline-mode`. | empty | `FLEETINT_FLAGS="--path=/path ..."` | not exposed by chart by default | +| `--duration` | Offline-mode collection duration in `HH:MM:SS` format. Required with `--offline-mode`. | empty | `FLEETINT_FLAGS="--duration=00:05:00 ..."` | not exposed by chart by default | +| `--format` | Offline-mode output format: `json` or `csv`. | `json` | `FLEETINT_FLAGS="--format=csv ..."` | not exposed by chart by default | +| `--enable-fault-injection` | Enable the local fault-injection endpoint for testing. | `false` | `FLEETINT_FLAGS="--enable-fault-injection"` | not exposed by chart by default | + +## Component Selection + +Use `--components` to control which monitoring components are enabled. + +Examples: + +```bash +# Enable all components +fleetint run --components=all + +# Enable only specific components +fleetint run --components=accelerator-nvidia-dcgm-thermal,accelerator-nvidia-dcgm-utilization,cpu,memory + +# Start from the default set and disable one component +fleetint run --components=all,-accelerator-nvidia-dcgm-prof +``` + +Rules: + +- `all`, `*`, or an empty component list enables all components. +- `all,-` starts with all components, then disables specific ones. +- An explicit comma-separated list enables only the named components. +- A non-matching explicit value effectively disables all components. + +Available component names: + +**NVIDIA GPU components** + +- `accelerator-nvidia-infiniband` +- `accelerator-nvidia-nccl` +- `accelerator-nvidia-peermem` +- `accelerator-nvidia-persistence-mode` +- `accelerator-nvidia-processes` +- `accelerator-nvidia-error-sxid` +- `accelerator-nvidia-error-xid` + +**NVIDIA GPU DCGM components** + +- `accelerator-nvidia-dcgm-clock` +- `accelerator-nvidia-dcgm-cpu` +- `accelerator-nvidia-dcgm-inforom` +- `accelerator-nvidia-dcgm-mem` +- `accelerator-nvidia-dcgm-nvlink` +- `accelerator-nvidia-dcgm-nvswitch` +- `accelerator-nvidia-dcgm-pcie` +- `accelerator-nvidia-dcgm-power` +- `accelerator-nvidia-dcgm-prof` +- `accelerator-nvidia-dcgm-thermal` +- `accelerator-nvidia-dcgm-utilization` + +**System components** + +- `cpu` +- `disk` +- `memory` +- `network-ethernet` +- `os` +- `library` + +## Verify Effective Configuration + +### Bare Metal + +```bash +sudo cat /etc/default/fleetint +sudo systemctl status fleetintd +sudo journalctl -u fleetintd -f +``` + +### Kubernetes + +```bash +helm get values fleet-intelligence-agent -n +kubectl get daemonset fleet-intelligence-agent -n -o yaml +kubectl logs -n -l app.kubernetes.io/name=fleet-intelligence-agent --tail=100 +``` diff --git a/docs/development.md b/docs/1.2/development.md similarity index 96% rename from docs/development.md rename to docs/1.2/development.md index c376dfc2..51f4b9f1 100644 --- a/docs/development.md +++ b/docs/1.2/development.md @@ -11,7 +11,7 @@ cd fleet-intelligence-agent ### Prerequisites -- **Go**: 1.26.5 +- **Go**: 1.26.2 - **GoReleaser**: For building packages (install from [goreleaser.com](https://goreleaser.com/install/)) - **For ARM64 cross-compilation** (optional): `gcc-aarch64-linux-gnu` and `g++-aarch64-linux-gnu` @@ -191,4 +191,4 @@ make package-snapshot # Build packages (no git tag required) ## Contributing -See [CONTRIBUTING.md](../CONTRIBUTING.md) for detailed contribution guidelines. +See [CONTRIBUTING.md](https://github.com/NVIDIA/fleet-intelligence-agent/blob/main/CONTRIBUTING.md) for detailed contribution guidelines. diff --git a/docs/1.2/install-deb.md b/docs/1.2/install-deb.md new file mode 100644 index 00000000..26862d7e --- /dev/null +++ b/docs/1.2/install-deb.md @@ -0,0 +1,91 @@ +# DEB Installation + +## Prerequisites + +The Fleet Intelligence Agent DEB package has the following runtime dependencies: + +- `datacenter-gpu-manager-4-proprietary` (DCGM) +- `nvattest` (NVIDIA Attestation SDK CLI, NVAT) +- `corelib` (NVAT GPU evidence source dependency) + +Before installing Fleet Intelligence Agent, ensure the following prerequisites are met: + +- NVIDIA package repository is configured (network or local CUDA repository) so `datacenter-gpu-manager-4-proprietary`, `nvattest`, and `corelib` can be installed +- DCGM HostEngine `4.2.3` or newer +- NVIDIA Datacenter Driver major version `510` or newer is installed +- Install/upgrade commands are run as `root` or with `sudo` +- Attestation for the fleetint use case only supports Blackwell and newer GPUs, and applies to non-CC mode systems +- For NVSwitch systems (driver branch must match installed datacenter driver): + - Hopper (pre-4th gen NVSwitch): install `cuda-drivers-fabricmanager-` + - Blackwell (4th gen NVSwitch): install `nvidia-open-` and `nvlink5-` + +References: +- DCGM: [Installation](https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/getting-started.html#installation) +- Fabric Manager: [Installing Fabric Manager](https://docs.nvidia.com/datacenter/tesla/fabric-manager-user-guide/index.html#installing-fabric-manager) +- NVAT (`nvattest`/`corelib`): [NV Attestation SDK](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/overview.html) + +Fleet Intelligence Agent package dependencies (`datacenter-gpu-manager-4-proprietary`, `nvattest`, and `corelib`) are available through NVIDIA's CUDA repository. Before installing Fleet Intelligence Agent, add the appropriate NVIDIA CUDA repository for your system: + +```bash +# Ubuntu 22.04 (x86_64) +wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb +sudo dpkg -i cuda-keyring_1.1-1_all.deb +sudo apt-get update + +# Ubuntu 24.04 (x86_64) +wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb +sudo dpkg -i cuda-keyring_1.1-1_all.deb +sudo apt-get update + +# Ubuntu 22.04 (ARM64) +wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/sbsa/cuda-keyring_1.1-1_all.deb +sudo dpkg -i cuda-keyring_1.1-1_all.deb +sudo apt-get update + +# Ubuntu 24.04 (ARM64) +wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/sbsa/cuda-keyring_1.1-1_all.deb +sudo dpkg -i cuda-keyring_1.1-1_all.deb +sudo apt-get update +``` + +After adding the CUDA repository, package dependencies (`datacenter-gpu-manager-4-proprietary`, `nvattest`, and `corelib`) are resolved automatically by `apt` during Fleet Intelligence Agent installation. + +## Install package + +Download the package from [Latest stable release](https://github.com/NVIDIA/fleet-intelligence-agent/releases/latest), then install: + +```bash +# Ubuntu (x86_64) +sudo apt install ./fleetint_VERSION_amd64.deb + +# Ubuntu (ARM64) +sudo apt install ./fleetint_VERSION_arm64.deb +``` + +Verify: + +```bash +fleetint --version +systemctl status fleetintd +``` + +## Update + +Install the newer package version: + +```bash +# Ubuntu (x86_64) +sudo apt install ./fleetint_VERSION_amd64.deb + +# Ubuntu (ARM64) +sudo apt install ./fleetint_VERSION_arm64.deb +``` + +The service will automatically restart with the new version. + +## Uninstall + +```bash +sudo apt remove fleetint +sudo apt purge fleetint # Also removes configuration files +``` diff --git a/docs/1.2/install-helm.md b/docs/1.2/install-helm.md new file mode 100644 index 00000000..3165dbca --- /dev/null +++ b/docs/1.2/install-helm.md @@ -0,0 +1,228 @@ +# Helm Installation + +## Prerequisites + +- NVIDIA GPU Operator installed with DCGM HostEngine enabled. +- NVIDIA Datacenter Driver major version `510` or newer on the cluster nodes. +- DCGM HostEngine `4.2.3` or newer. +- A DCGM service endpoint reachable from the cluster (defaults to `nvidia-dcgm.gpu-operator.svc:5555`). +- Access to GitHub Container Registry (`ghcr.io`) from your cluster/network. + +Set shared variables once for the examples below: + +```bash +# Namespace (override if needed) +NS=fleet-intelligence + +CHART_VERSION='' # e.g. 0.3.2 or 0.3.2-rc.1 + +# DCGM endpoint (usually the default is correct) +DCGM_URL='nvidia-dcgm.gpu-operator.svc:5555' + +# Enrollment configuration - Go to the Fleet Intelligence UI to: +# 1. Generate an enrollment token (ENROLL_TOKEN) +# 2. Get the enrollment endpoint URL (ENROLL_ENDPOINT) +ENROLL_ENDPOINT='' +ENROLL_TOKEN='' +ENROLL_TOKEN_SECRET_NAME='fleet-intelligence-enroll-token' # Recommended secret name +``` + +## Create namespace + +```bash +kubectl create namespace "$NS" || true +``` + +## Create enrollment secret + +If you need to enroll nodes, create the token Secret. The secret name should match the `ENROLL_TOKEN_SECRET_NAME` variable set above: + +```bash +kubectl create secret generic "$ENROLL_TOKEN_SECRET_NAME" \ + --namespace "$NS" \ + --from-literal=token="$ENROLL_TOKEN" +``` + +## Install or upgrade + +Install: + +```bash +helm install fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" \ + --set enroll.enabled=true \ + --set enroll.endpoint="$ENROLL_ENDPOINT" \ + --set enroll.tokenSecretName="$ENROLL_TOKEN_SECRET_NAME" +``` + +Install (no enrollment): + +```bash +helm install fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" +``` + +Upgrade: + +```bash +helm upgrade fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" \ + --set enroll.enabled=true \ + --set enroll.endpoint="$ENROLL_ENDPOINT" \ + --set enroll.tokenSecretName="$ENROLL_TOKEN_SECRET_NAME" +``` + +Upgrade (no enrollment): + +```bash +helm upgrade fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" +``` + +Upgrade and explicitly remove persisted enrollment metadata: + +```bash +helm upgrade fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" \ + --set enroll.enabled=false \ + --set enroll.unenroll=true +``` + +`enroll.enabled` and `enroll.unenroll` are mutually exclusive. Setting both to `true` causes Helm template rendering to fail. + +To use a different image registry/repository, add: + +```bash +--set image.repository="" +``` + +If DCGM is exposed at a different service name or port, set `env.DCGM_URL`: + +```bash +--set env.DCGM_URL="$DCGM_URL" +``` + +## Verifying deployment + +After installation, verify the agent is running correctly: + +```bash +# Check DaemonSet status +kubectl get daemonset fleet-intelligence-agent -n "$NS" + +# Check pods (should be one per GPU node) +kubectl get pods -n "$NS" -l app.kubernetes.io/name=fleet-intelligence-agent + +# View pod logs +kubectl logs -n "$NS" -l app.kubernetes.io/name=fleet-intelligence-agent --tail=50 + +# Watch rollout status +kubectl rollout status daemonset/fleet-intelligence-agent -n "$NS" +``` + +Check a specific pod in detail: + +```bash +# Get a pod name +POD_NAME=$(kubectl get pods -n "$NS" -l app.kubernetes.io/name=fleet-intelligence-agent -o jsonpath='{.items[0].metadata.name}') + +# Describe the pod +kubectl describe pod -n "$NS" "$POD_NAME" + +# View full logs +kubectl logs -n "$NS" "$POD_NAME" --follow +``` + +## Troubleshooting + +**Pods not starting:** + +```bash +# Check pod events +kubectl describe pod -n "$NS" -l app.kubernetes.io/name=fleet-intelligence-agent +``` + +Common issues: +- **ImagePullBackOff**: Verify nodes can reach `ghcr.io` and the image tag exists +- **Pending**: Check node labels match `nodeSelector` (default: `nvidia.com/gpu.deploy.dcgm=true`) +- **CrashLoopBackOff**: Check logs for errors + +**Enrollment failures:** + +```bash +# Check init container logs +kubectl logs -n "$NS" "$POD_NAME" -c enroll + +# Verify enrollment secret exists +kubectl get secret "$ENROLL_TOKEN_SECRET_NAME" -n "$NS" + +# Check secret content (verify token is not empty) +kubectl get secret "$ENROLL_TOKEN_SECRET_NAME" -n "$NS" -o jsonpath='{.data.token}' | base64 -d | wc -c +``` + +**DCGM connection issues:** + +```bash +# Verify DCGM service is accessible +kubectl get svc -n gpu-operator nvidia-dcgm + +# Test DCGM connectivity from a pod +kubectl exec -n "$NS" "$POD_NAME" -- curl -v telnet://nvidia-dcgm.gpu-operator.svc:5555 + +# Check DCGM URL environment variable +kubectl get pods -n "$NS" "$POD_NAME" -o jsonpath='{.spec.containers[0].env[?(@.name=="DCGM_URL")].value}' +``` + +If DCGM is at a different location, update the URL: + +```bash +helm upgrade fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" \ + --reuse-values \ + --set env.DCGM_URL=":" +``` + +## Node Scheduling + +**By default**, the agent only deploys to nodes where DCGM is running, using the nodeSelector: + +```yaml +nodeSelector: + nvidia.com/gpu.deploy.dcgm: "true" +``` + +The agent requires a DCGM HostEngine to collect GPU metrics, so it must co-locate with DCGM. This label is +automatically set by the NVIDIA GPU Operator when DCGM is enabled — no manual labeling is required. + +If you need a different node selector or tolerations for GPU taints, you can override them. +The examples below use a generic label to illustrate the override syntax — replace it with the actual label used in your cluster. + +Using `--set` (quote the tolerations for zsh, and escape dots in the label key): + +```bash +helm upgrade --install fleet-intelligence-agent oci://ghcr.io/nvidia/charts/fleet-intelligence-agent \ + --version "$CHART_VERSION" \ + --namespace "$NS" \ + --set-string nodeSelector.my-org\\.com/gpu-node=true \ + --set 'tolerations[0].key=nvidia.com/gpu' \ + --set 'tolerations[0].operator=Exists' \ + --set 'tolerations[0].effect=NoSchedule' +``` + +Using a values file: + +```yaml +nodeSelector: + my-org.com/gpu-node: "true" + +tolerations: + - key: "nvidia.com/gpu" + operator: "Exists" + effect: "NoSchedule" +``` diff --git a/docs/1.2/install-rpm.md b/docs/1.2/install-rpm.md new file mode 100644 index 00000000..90c83bc4 --- /dev/null +++ b/docs/1.2/install-rpm.md @@ -0,0 +1,115 @@ +# RPM Installation + +## Prerequisites + +The Fleet Intelligence Agent RPM package has the following runtime dependencies: + +- `datacenter-gpu-manager-4-proprietary` (DCGM) +- `nvattest` (NVIDIA Attestation SDK CLI, NVAT) +- `corelib` (NVAT GPU evidence source dependency) + +Before installing Fleet Intelligence Agent, ensure the following prerequisites are met: + +- NVIDIA package repository is configured (network or local CUDA repository) so `datacenter-gpu-manager-4-proprietary`, `nvattest`, and `corelib` can be installed +- DCGM HostEngine `4.2.3` or newer +- NVIDIA Datacenter Driver major version `510` or newer is installed +- Install/upgrade commands are run as `root` or with `sudo` +- `dnf-plugins-core` is installed (required for `dnf config-manager`) +- Attestation for the fleetint use case only supports Blackwell and newer GPUs, and applies to non-CC mode systems +- For NVSwitch systems (driver branch must match installed datacenter driver): + - Hopper (pre-4th gen NVSwitch): install `nvidia-driver:/fm` + - Blackwell (4th gen NVSwitch): install `nvidia-driver--open` and `nvlink-` + +References: +- DCGM: [Installation](https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/getting-started.html#installation) +- Fabric Manager: [Installing Fabric Manager](https://docs.nvidia.com/datacenter/tesla/fabric-manager-user-guide/index.html#installing-fabric-manager) +- NVAT (`nvattest`/`corelib`): [NV Attestation SDK](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/overview.html) + +Fleet Intelligence Agent package dependencies (`datacenter-gpu-manager-4-proprietary`, `nvattest`, and `corelib`) are available through NVIDIA's CUDA repository. Before installing Fleet Intelligence Agent, add the appropriate NVIDIA CUDA repository for your system. + +Install `dnf-plugins-core` first if `dnf config-manager` is not available: + +```bash +sudo dnf install -y dnf-plugins-core +``` + +### RHEL/Rocky/AlmaLinux Systems + +```bash +# RHEL/Rocky/AlmaLinux 8 (x86_64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/x86_64/cuda-rhel8.repo +sudo dnf clean all + +# RHEL/Rocky/AlmaLinux 9 (x86_64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo +sudo dnf clean all + +# RHEL/Rocky/AlmaLinux 10 (x86_64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel10/x86_64/cuda-rhel10.repo +sudo dnf clean all + +# RHEL/Rocky/AlmaLinux 8 (ARM64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/sbsa/cuda-rhel8.repo +sudo dnf clean all + +# RHEL/Rocky/AlmaLinux 9 (ARM64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/sbsa/cuda-rhel9.repo +sudo dnf clean all + +# RHEL/Rocky/AlmaLinux 10 (ARM64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel10/sbsa/cuda-rhel10.repo +sudo dnf clean all +``` + +### Amazon Linux 2023 + +```bash +# Amazon Linux 2023 (x86_64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/amzn2023/x86_64/cuda-amzn2023.repo +sudo dnf clean all + +# Amazon Linux 2023 (ARM64) +sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/amzn2023/sbsa/cuda-amzn2023.repo +sudo dnf clean all +``` + +After adding the CUDA repository, package dependencies (`datacenter-gpu-manager-4-proprietary`, `nvattest`, and `corelib`) are resolved automatically by `dnf` during Fleet Intelligence Agent installation. + +## Install package + +Download the package from [Latest stable release](https://github.com/NVIDIA/fleet-intelligence-agent/releases/latest), then install: + +```bash +# RHEL/Rocky/AlmaLinux/Amazon Linux (x86_64) +sudo dnf install ./fleetint-VERSION-1.x86_64.rpm + +# RHEL/Rocky/AlmaLinux/Amazon Linux (ARM64) +sudo dnf install ./fleetint-VERSION-1.aarch64.rpm +``` + +Verify: + +```bash +fleetint --version +systemctl status fleetintd +``` + +## Update + +Install the newer package version: + +```bash +# RHEL/Rocky/AlmaLinux/Amazon Linux (x86_64) +sudo dnf install ./fleetint-VERSION-1.x86_64.rpm + +# RHEL/Rocky/AlmaLinux/Amazon Linux (ARM64) +sudo dnf install ./fleetint-VERSION-1.aarch64.rpm +``` + +The service will automatically restart with the new version. + +## Uninstall + +```bash +sudo dnf remove fleetint +``` diff --git a/docs/1.2/usage.md b/docs/1.2/usage.md new file mode 100644 index 00000000..bbb5cb8c --- /dev/null +++ b/docs/1.2/usage.md @@ -0,0 +1,385 @@ +# Usage + +## Basic Commands + +### Quick Health Scan + +```bash +sudo fleetint scan +``` + +Performs a quick health scan of GPUs and system components. Returns immediately with a summary of any detected issues. + +**Aliases:** `sudo fleetint check`, `sudo fleetint s` + +### Start Monitoring Server + +```bash +sudo fleetint run +``` + +Starts the API server. By default it listens on a Unix socket at `/run/fleetint/fleetint.sock` (access controlled by file permissions). Pass `--listen-address` to switch to TCP. + +**Options:** +- `--log-level`: Set logging level (debug, info, warn, error) +- `--listen-address`: Listen address. An absolute path (e.g. `/run/fleetint/fleetint.sock`) creates a Unix socket; a `host:port` value (e.g. `127.0.0.1:15133`) opens a TCP listener. Default: `/run/fleetint/fleetint.sock`. See [Exposing the Agent for External Monitoring](#exposing-the-agent-for-external-monitoring) for details on exposing to Prometheus and other tools. +- `--components`: Enable/disable specific components + +### Check Status + +```bash +sudo fleetint status +``` + +Displays the current status of the fleetint service and monitored components. + +**Alias:** `sudo fleetint st` + +### Machine Information + +```bash +sudo fleetint machine-info +``` + +Shows detailed information about the machine: +- Hardware specifications (CPU, memory, disk) +- GPU configuration and driver version +- CUDA runtime version +- Operating system and kernel version +- Network interfaces +- System UUID and machine ID + +### View/Update Metadata + +```bash +# View current metadata +sudo fleetint metadata + +# Set metadata key-value pair +sudo fleetint metadata --set-key="key" --set-value="value" +``` + +Used to view or update the agent's metadata store, including remote export configuration. + +### Compact State Database + +```bash +sudo fleetint compact +``` + +Compacts the local Fleet Intelligence state database to reduce disk usage. + +Requirements: +- `fleetintd` must be stopped before running `compact` +- the agent must not be running (no active listener on the default socket or port) +- the command needs write access to the state database, so package installs typically require `sudo` + +Typical workflow: + +```bash +sudo systemctl stop fleetintd +sudo fleetint compact +sudo systemctl start fleetintd +``` + +### Validate Prerequisites + +```bash +sudo fleetint precheck +``` + +Validates the local prerequisites required for installation and enrollment. + +**What it checks:** +- NVIDIA GPU presence +- supported GPU architecture (`Hopper`, `Blackwell`, `Rubin`) +- NVIDIA driver major version (`510` or newer) +- DCGM HostEngine reachability +- DCGM HostEngine minimum version (`4.2.3`) +- `nvattest` availability + +The command prints each check result and exits non-zero if any hard requirement fails. + +**Environment Variables (DCGM connection):** +- `DCGM_URL`: Address of the DCGM HostEngine (default: `localhost`) +- `DCGM_URL_IS_UNIX_SOCKET`: Set to `true` if `DCGM_URL` is a Unix socket path (default: `false`) + +### Enroll Agent + +```bash +# Pass token directly (visible in process list) +sudo fleetint enroll --endpoint=https://api.example.com --token= + +# Read token from a file (recommended) +sudo fleetint enroll --endpoint=https://api.example.com --token-file=/path/to/token + +# Read token from stdin +echo "$TOKEN" | sudo fleetint enroll --endpoint=https://api.example.com --token-file=- +``` + +Enrolls the agent with the Fleet Intelligence backend by exchanging a Service Account Key (SAK) token for a JWT token. The JWT token and backend endpoints are stored locally for subsequent data exports. + +**Required Options:** +- `--endpoint`: Base endpoint URL for the Fleet Intelligence backend (must use HTTPS) +- `--token`: Service Account Key (SAK) token for authentication (mutually exclusive with `--token-file`) +- `--token-file`: Path to a file containing the SAK token, or `-` to read from stdin (mutually exclusive with `--token`). Preferred over `--token` because it avoids exposing the token in `/proc//cmdline`. + +One of `--token` or `--token-file` is required. + +**Optional Flags:** +- `--force`: Continue enrollment even if `fleetint precheck` fails + +**What it does:** +1. Runs the same prerequisite validation as `fleetint precheck` +2. Validates the endpoint URL (must be HTTPS) +3. Makes an enrollment request to exchange the SAK token for a JWT token +4. Stores the JWT token and backend endpoints (metrics, logs, nonce) in the local metadata database +5. The stored credentials are used automatically by the agent for data export + +**Example output:** +``` +Enrollment succeeded +``` + +**Error handling:** +- precheck failure: Enrollment is blocked unless `--force` is set +- 400: Token format is incorrect +- 401: Token is invalid +- 403: Token is expired or revoked +- 404: Endpoint not found +- 429: Server is rate limiting (retry later) +- 502/503/504: Temporary server issues (retry) + +### Unenroll Agent + +```bash +sudo fleetint unenroll +``` + +Removes all enrollment credentials and backend endpoints from the agent. After unenrolling, the agent will no longer export data to the backend until re-enrolled. + +**What it does:** +1. Clears the JWT token from local storage +2. Clears the SAK token from local storage +3. Removes all stored backend endpoints (enroll, metrics, logs, nonce) + +Use this command when: +- Decommissioning a machine +- Switching to a different backend +- Troubleshooting authentication issues + +## Offline Data Collection + +For environments without network access or when you need to collect data to files: + +```bash +sudo fleetint run --offline-mode --path=/tmp/fleetint --duration=00:05:00 --format=csv +``` + +**Options:** +- `--offline-mode`: Disable HTTP API server and export to files +- `--path`: Absolute path to the output directory. Must not be inside restricted system directories (`/etc`, `/usr`, `/sys`, `/bin`, `/boot`, `/dev`, `/lib`, `/proc`, `/run`, `/sbin`). +- `--duration`: How long to collect data (format: HH:MM:SS) +- `--format`: Output format (`csv` or `json`) + +## Running as a Service + +After package installation, the agent runs as a systemd service: + +```bash +# Check service status +sudo systemctl status fleetintd + +# Start/stop/restart service +sudo systemctl start fleetintd +sudo systemctl stop fleetintd +sudo systemctl restart fleetintd + +# View logs +sudo journalctl -u fleetintd -f +``` + +## HTTP API + +The fleetint API server listens on a Unix socket (`/run/fleetint/fleetint.sock`) by default. When started with a TCP address (e.g. `--listen-address=127.0.0.1:15133`), the REST endpoints are also available over plain HTTP. + +**Using curl with the default Unix socket** (requires sudo since the socket is owner-only): + +```bash +sudo curl --unix-socket /run/fleetint/fleetint.sock http://localhost/healthz +``` + +**Using curl with TCP** (requires `--listen-address=127.0.0.1:15133`): + +```bash +curl http://localhost:15133/healthz +``` + +The examples below use the TCP form for brevity. For the default socket, prefix with `sudo` and substitute `--unix-socket /run/fleetint/fleetint.sock http://localhost` for the hostname. + +### Health Check + +```bash +curl http://localhost:15133/healthz +``` + +Returns the health status of the API server + +**Response:** +```json +{ + "status": "ok", + "version": "v1" +} +``` + +### Machine Information + +```bash +curl http://localhost:15133/machine-info +``` + +Returns basic machine info + +Note: Detailed hardware and GPU information is available via the `fleetint machine-info` CLI command. + +### Current Health States + +```bash +curl http://localhost:15133/v1/states +``` + +Returns the current health states of all monitored components + +### Component Metrics + +```bash +curl http://localhost:15133/v1/metrics +``` + +Returns metrics data in JSON format from all monitored components + +**Query Parameters:** +- `startTime`: Unix timestamp to retrieve metrics since a specific time +- `components`: Filter metrics by component name + +**Example:** +```bash +# Get metrics from the last hour +curl "http://localhost:15133/v1/metrics?startTime=$(date -d '1 hour ago' +%s)" + +# Get metrics for specific component +curl "http://localhost:15133/v1/metrics?components=accelerator-nvidia-temperature" +``` + +### Component Events + +```bash +curl http://localhost:15133/v1/events +``` + +Returns event data from all monitored components (errors, warnings, state changes) + +**Query Parameters:** +- `since`: Unix timestamp to retrieve events since a specific time (default: last hour) +- `components`: Filter events by component name + +**Example:** +```bash +# Get events from the last hour +curl "http://localhost:15133/v1/events?since=$(date -d '1 hour ago' +%s)" + +# Get events for specific component +curl "http://localhost:15133/v1/events?components=accelerator-nvidia-error-xid" +``` + +### Prometheus Metrics + +```bash +curl http://localhost:15133/metrics +``` + +Returns metrics in Prometheus exposition format for integration with monitoring systems + +## Exposing the Agent for External Monitoring + +By default, fleetint uses a Unix socket for security. To allow external monitoring tools like Prometheus to scrape metrics over the network, switch to a TCP listener with the `--listen-address` flag: + +```bash +# Expose on all interfaces +sudo fleetint run --listen-address=0.0.0.0:15133 + +# Or expose on a specific IP address +sudo fleetint run --listen-address=192.168.1.100:15133 +``` + +### Prometheus Configuration Example + +Configure Prometheus to scrape the exposed endpoint: + +```yaml +# prometheus.yml +scrape_configs: + - job_name: 'fleetint' + scrape_interval: 60s + static_configs: + - targets: + - 'gpu-server-1:15133' + - 'gpu-server-2:15133' + metrics_path: /metrics +``` + +**For production deployments** with persistent configuration and security considerations, see the [Configuration Guide](configuration.md#where-to-configure). + +## Troubleshooting + +### Service won't start + +1. Check service status: + ```bash + sudo systemctl status fleetintd + ``` + +2. View recent logs: + ```bash + sudo journalctl -u fleetintd -n 50 + ``` + +3. Verify NVIDIA drivers are installed (if using GPUs): + ```bash + nvidia-smi + ``` + +4. Check that the daemon is listening: + ```bash + # Default (unix socket) + sudo ls -la /run/fleetint/fleetint.sock + + # TCP mode + sudo netstat -tlnp | grep 15133 + ``` + +### Export issues + +1. Check the logs: + ```bash + sudo journalctl -u fleetintd -f + ``` + +2. Verify your configuration: + ```bash + sudo fleetint metadata + ``` + +3. Test connectivity to the export endpoint manually with `curl` + +4. Check proxy settings in `/etc/default/fleetint` if behind a firewall + +### High resource usage + +The agent should use <100MB RAM and <1% CPU. Higher usage might indicate: + +- Very frequent collection intervals (check `FLEETINT_COLLECT_INTERVAL`) +- Large lookback windows (check `FLEETINT_METRICS_LOOKBACK` and `FLEETINT_EVENTS_LOOKBACK`) +- Many GPUs in the system (resource usage scales with GPU count) +- Debug logging enabled (use `--log-level=warn` or `error`) diff --git a/docs/1.3/architecture.md b/docs/1.3/architecture.md new file mode 100644 index 00000000..02874dcb --- /dev/null +++ b/docs/1.3/architecture.md @@ -0,0 +1,93 @@ +# Architecture + +This document explains how the Fleet Intelligence Agent works at runtime on bare metal and Kubernetes. + +## Agent runtime model + +At runtime, the agent follows a consistent pipeline: + +1. Discover available components (GPU/DCGM and system-level checks). +2. Collect telemetry and health signals. +3. Evaluate component health and status. +4. Publish results through: + - HTTP API + - Prometheus metrics endpoint (`/metrics`) + - Optional remote export + - Optional local file export + +## Bare metal runtime architecture + +On bare metal, the agent runs directly on the host and talks to local NVIDIA stack dependencies. + +### Dependency graph + +```mermaid +flowchart LR + GPU["NVIDIA GPUs"] --> DRV["NVIDIA Driver"] --> NVML["NVML"] + NVML --> DCGM["DCGM HostEngine"] + DCGM --> AGENT["fleetint agent process"] + + AGENT --> COMP["Component checks + health evaluation"] + COMP --> API["HTTP API + /metrics"] + COMP --> EXPORT["Export pipeline"] +``` + +### Runtime behavior + +- GPU/DCGM components read health and telemetry from DCGM/NVML-backed data paths. +- System components read host state (CPU, memory, disk, network, OS/kernel/library/PCI views). +- The agent evaluates component health continuously and serves current state via API/metrics. +- Exporters serialize telemetry/events/health data for downstream ingestion. + +## Kubernetes runtime architecture + +In Kubernetes, the same agent runtime executes inside a pod (typically one pod per GPU node). + +### Dependency graph + +```mermaid +flowchart LR + subgraph CL["Kubernetes cluster"] + subgraph NODE["GPU node"] + GPU["NVIDIA GPUs"] --> DRV["NVIDIA Driver"] --> NVML["NVML"] + + subgraph GOP["GPU platform services"] + DCGM["DCGM HostEngine"] + SVC["DCGM Service endpoint"] + end + + subgraph POD["fleet-intelligence-agent pod"] + AGENT["fleetint runtime"] + COMP["Component checks + health evaluation"] + API["HTTP API + /metrics"] + end + end + end + + DCGM --> SVC --> AGENT + AGENT --> COMP --> API +``` + +### Runtime behavior + +- Agent component logic is the same as bare metal. +- DCGM-backed components consume DCGM over the cluster endpoint (`DCGM_URL`). +- The pod reads required host-level views through mounted paths and runtime-provided device access. +- Health evaluation and export behavior remain identical to host mode. + +## Data flow inside the agent + +```mermaid +flowchart TD + INPUT["GPU + DCGM + System signals"] --> COLLECT["Collectors"] + COLLECT --> STATE["Component state model"] + STATE --> HEALTH["Health evaluation"] + HEALTH --> API["HTTP/metrics output"] + HEALTH --> EXPORT["Exporters (remote/file)"] +``` + +## Dependency and failure behavior + +- If DCGM is unavailable, DCGM-backed GPU components degrade while non-DCGM components can continue. +- If GPU runtime/device access is unavailable in Kubernetes, GPU-facing checks may fail or report degraded state. +- If upstream signals recover, component health transitions back based on normal collection/evaluation cycles. diff --git a/docs/configuration.md b/docs/1.3/configuration.md similarity index 100% rename from docs/configuration.md rename to docs/1.3/configuration.md diff --git a/docs/1.3/development.md b/docs/1.3/development.md new file mode 100644 index 00000000..ecdf7666 --- /dev/null +++ b/docs/1.3/development.md @@ -0,0 +1,194 @@ +# Development + +## Setup + +### Clone Repository + +```bash +git clone https://github.com/NVIDIA/fleet-intelligence-agent.git +cd fleet-intelligence-agent +``` + +### Prerequisites + +- **Go**: 1.26.4 +- **GoReleaser**: For building packages (install from [goreleaser.com](https://goreleaser.com/install/)) +- **For ARM64 cross-compilation** (optional): `gcc-aarch64-linux-gnu` and `g++-aarch64-linux-gnu` + +### Build + +```bash +# Build the binary +make fleetint + +# Build all targets +make all + +# Run tests +make test +``` + +## Project Structure + +``` +fleetint/ +├── cmd/ +│ └── fleetint/ # Main CLI application +├── internal/ +│ ├── cmdutil/ # Command utilities +│ ├── config/ # Configuration management +│ ├── exporter/ # Data export functionality +│ │ ├── collector/ # Data collection +│ │ ├── converter/ # Format conversion (CSV, OTLP) +│ │ └── writer/ # Output writers (file, HTTP) +│ ├── machineinfo/ # Machine information gathering +│ ├── server/ # HTTP API server +│ └── version/ # Version information +├── deployments/ +│ └── packages/ # Package build configurations +│ ├── scripts/ # Install/uninstall scripts +│ └── systemd/ # Systemd service files +└── docs/ # Documentation +``` + +## Building Packages + +Packages are built using [GoReleaser](https://goreleaser.com), which handles .deb, .rpm, and tarball creation automatically. + +### Install GoReleaser + +```bash +# Using Homebrew (macOS/Linux) +brew install goreleaser + +# Using snap (Linux) +snap install --classic goreleaser + +# Or download from https://github.com/goreleaser/goreleaser/releases +``` + +### Build Snapshot Packages + +Build packages without a git tag (for testing): + +```bash +# Using Make +make package-snapshot + +# Or directly with GoReleaser +goreleaser release --snapshot --clean +``` + +This creates in the `dist/` directory: +- `.deb` packages for Debian/Ubuntu (amd64, arm64) +- `.rpm` packages for RHEL/Rocky/AlmaLinux 8, 9, 10 (x86_64, aarch64) +- Binary tarballs for direct installation +- Checksums and metadata + +### Create a Release + +To create an official release, tag a version and push it to GitHub. The GitHub Actions workflow will automatically build and publish the release: + +```bash +# Tag a version +git tag v0.2.0 + +# Push the tag to trigger the release workflow +git push origin v0.2.0 +``` + +The GitHub Actions workflow will: +- Build packages for all supported platforms (amd64, arm64) +- Create `.deb` packages for Ubuntu +- Create `.rpm` packages for RHEL/Rocky/AlmaLinux 8, 9, 10 +- Generate binary tarballs +- Publish the release with all artifacts to GitHub Releases + +## Testing + +### Run Tests with Coverage + +```bash +make test +``` + +This runs all tests and generates a coverage report in `coverage/coverage.html`. + +### Run Linting + +```bash +make lint +``` + +Runs `golangci-lint` if installed, otherwise runs basic Go formatting and vet checks. + +### Format Code + +```bash +make fmt +``` + +### Vulnerability Scanning + +```bash +make vuln +``` + +Scans the built binary for known vulnerabilities using `govulncheck`. + +### Manual Testing + +```bash +# Build and run locally +make fleetint +./bin/fleetint scan + +# Test with different configurations +./bin/fleetint run --log-level=debug --listen-address=127.0.0.1:8080 + +# Test offline mode +./bin/fleetint run --offline-mode --path=/tmp/test --duration=00:01:00 --format=csv +``` + +## Development Workflow + +1. **Create a branch** for your changes +2. **Make changes** and add tests +3. **Run tests**: `make test` +4. **Format code**: `make fmt` +5. **Run linting**: `make lint` +6. **Build locally**: `make fleetint` +7. **Test changes** manually +8. **Build packages** (optional): `make package-snapshot` +9. **Submit PR** with description of changes + +## Code Guidelines + +- Follow standard Go conventions and idioms +- Add tests for new functionality +- Update documentation for user-facing changes +- Ensure all tests pass before submitting PRs +- Use `make fmt` to format code before committing +- Keep commits focused and write clear commit messages + +## Available Make Targets + +```bash +make help # Show all available targets +make all # Build all binaries +make fleetint # Build fleetint binary +make test # Run tests with coverage +make lint # Run linting tools +make fmt # Format Go code +make vuln # Run vulnerability check +make clean # Clean up binaries and artifacts +make package-snapshot # Build packages (no git tag required) +``` + +## Related Projects + +- **[leptonai/gpud](https://github.com/leptonai/gpud)**: Upstream dependency providing core monitoring functionality + +## Contributing + +See [CONTRIBUTING.md](https://github.com/NVIDIA/fleet-intelligence-agent/blob/main/CONTRIBUTING.md) for detailed contribution guidelines. diff --git a/docs/install-deb.md b/docs/1.3/install-deb.md similarity index 88% rename from docs/install-deb.md rename to docs/1.3/install-deb.md index 6ea3e246..f97fe38f 100644 --- a/docs/install-deb.md +++ b/docs/1.3/install-deb.md @@ -85,6 +85,6 @@ sudo apt purge fleetint # Also removes configuration files ``` References: -- DCGM: -- Fabric Manager: -- NVAT (`nvattest`/`corelib`): \ No newline at end of file +- DCGM: [Installation](https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/getting-started.html#installation) +- Fabric Manager: [Installing Fabric Manager](https://docs.nvidia.com/datacenter/tesla/fabric-manager-user-guide/index.html#installing-fabric-manager) +- NVAT (`nvattest`/`corelib`): [NV Attestation SDK](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/overview.html) \ No newline at end of file diff --git a/docs/install-helm.md b/docs/1.3/install-helm.md similarity index 100% rename from docs/install-helm.md rename to docs/1.3/install-helm.md diff --git a/docs/install-rpm.md b/docs/1.3/install-rpm.md similarity index 90% rename from docs/install-rpm.md rename to docs/1.3/install-rpm.md index ce32f4ff..d3320f44 100644 --- a/docs/install-rpm.md +++ b/docs/1.3/install-rpm.md @@ -109,6 +109,6 @@ sudo dnf remove fleetint ``` References: -- DCGM: -- Fabric Manager: -- NVAT (`nvattest`/`corelib`): \ No newline at end of file +- DCGM: [Installation](https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/getting-started.html#installation) +- Fabric Manager: [Installing Fabric Manager](https://docs.nvidia.com/datacenter/tesla/fabric-manager-user-guide/index.html#installing-fabric-manager) +- NVAT (`nvattest`/`corelib`): [NV Attestation SDK](https://docs.nvidia.com/attestation/nv-attestation-sdk-cpp/latest/overview.html) \ No newline at end of file diff --git a/docs/usage.md b/docs/1.3/usage.md similarity index 99% rename from docs/usage.md rename to docs/1.3/usage.md index 630e3b8e..305ed490 100644 --- a/docs/usage.md +++ b/docs/1.3/usage.md @@ -384,7 +384,7 @@ scrape_configs: ### High resource usage -The agent should use <500MB RAM and <1% CPU. Higher usage might indicate: +The agent should use <500MB RAM and <1% CPU. Higher usage might indicate: - Very frequent collection intervals (check `FLEETINT_COLLECT_INTERVAL`) - Large lookback windows (check `FLEETINT_METRICS_LOOKBACK` and `FLEETINT_EVENTS_LOOKBACK`) diff --git a/docs/index-1.2.yml b/docs/index-1.2.yml new file mode 100644 index 00000000..d3982dac --- /dev/null +++ b/docs/index-1.2.yml @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +navigation: + - page: Architecture + path: 1.2/architecture.md + slug: architecture + - page: Usage + path: 1.2/usage.md + slug: usage + - page: Configuration + path: 1.2/configuration.md + slug: configuration + - page: DEB Installation + path: 1.2/install-deb.md + slug: install-deb + - page: RPM Installation + path: 1.2/install-rpm.md + slug: install-rpm + - page: Helm Installation + path: 1.2/install-helm.md + slug: install-helm + - page: Development + path: 1.2/development.md + slug: development diff --git a/docs/index-1.3.yml b/docs/index-1.3.yml new file mode 100644 index 00000000..ccf462a6 --- /dev/null +++ b/docs/index-1.3.yml @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +navigation: + - page: Architecture + path: 1.3/architecture.md + slug: architecture + - page: Usage + path: 1.3/usage.md + slug: usage + - page: Configuration + path: 1.3/configuration.md + slug: configuration + - page: DEB Installation + path: 1.3/install-deb.md + slug: install-deb + - page: RPM Installation + path: 1.3/install-rpm.md + slug: install-rpm + - page: Helm Installation + path: 1.3/install-helm.md + slug: install-helm + - page: Development + path: 1.3/development.md + slug: development diff --git a/fern/.gitignore b/fern/.gitignore new file mode 100644 index 00000000..ff9bdf6f --- /dev/null +++ b/fern/.gitignore @@ -0,0 +1,2 @@ +.fern/ +node_modules/ diff --git a/fern/docs.yml b/fern/docs.yml new file mode 100644 index 00000000..09d75600 --- /dev/null +++ b/fern/docs.yml @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +instances: + - url: fleet-intelligence-agent.docs.buildwithfern.com/fleet-intel/agent + custom-domain: docs.nvidia.com/fleet-intel/agent + multi-source: true + +title: NVIDIA Fleet Intelligence Agent + +global-theme: nvidia + +metadata: + canonical-host: "docs.nvidia.com/fleet-intel/agent" + +versions: + - display-name: "1.3 (Current)" + path: ../docs/index-1.3.yml + slug: "1.3" + - display-name: "1.2" + path: ../docs/index-1.2.yml + slug: "1.2" + +redirects: + - source: "/fleet-intel/agent/index.html" + destination: "/fleet-intel/agent/" + +logo: + href: /fleet-intel/agent + right-text: Fleet Intelligence Agent + +navbar-links: + - type: secondary + text: Fleet Intelligence Docs + url: https://docs.nvidia.com/fleet-intel + - type: github + value: https://github.com/NVIDIA/fleet-intelligence-agent + +experimental: + mdx-components: + - ./components diff --git a/fern/fern.config.json b/fern/fern.config.json new file mode 100644 index 00000000..3baac063 --- /dev/null +++ b/fern/fern.config.json @@ -0,0 +1,4 @@ +{ + "organization": "nvidia", + "version": "5.67.1" +} From e8bdda8519e8feb1ee88444c190b1da5773e843a Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Wed, 29 Jul 2026 13:03:07 -0600 Subject: [PATCH 2/7] Fix deceptive example enrollment endpoints Signed-off-by: Ed Balduf --- docs/1.2/usage.md | 6 +++--- docs/1.3/usage.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/1.2/usage.md b/docs/1.2/usage.md index bbb5cb8c..73d4553f 100644 --- a/docs/1.2/usage.md +++ b/docs/1.2/usage.md @@ -108,13 +108,13 @@ The command prints each check result and exits non-zero if any hard requirement ```bash # Pass token directly (visible in process list) -sudo fleetint enroll --endpoint=https://api.example.com --token= +sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com--token= # Read token from a file (recommended) -sudo fleetint enroll --endpoint=https://api.example.com --token-file=/path/to/token +sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token-file=/path/to/token # Read token from stdin -echo "$TOKEN" | sudo fleetint enroll --endpoint=https://api.example.com --token-file=- +echo "$TOKEN" | sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token-file=- ``` Enrolls the agent with the Fleet Intelligence backend by exchanging a Service Account Key (SAK) token for a JWT token. The JWT token and backend endpoints are stored locally for subsequent data exports. diff --git a/docs/1.3/usage.md b/docs/1.3/usage.md index 305ed490..a4c79d31 100644 --- a/docs/1.3/usage.md +++ b/docs/1.3/usage.md @@ -108,13 +108,13 @@ The command prints each check result and exits non-zero if any hard requirement ```bash # Pass token directly (visible in process list) -sudo fleetint enroll --endpoint=https://api.example.com --token= +sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token= # Read token from a file (recommended) -sudo fleetint enroll --endpoint=https://api.example.com --token-file=/path/to/token +sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token-file=/path/to/token # Read token from stdin -echo "$TOKEN" | sudo fleetint enroll --endpoint=https://api.example.com --token-file=- +echo "$TOKEN" | sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token-file=- ``` Enrolls the agent with the Fleet Intelligence backend by exchanging a Service Account Key (SAK) token for a JWT token. The JWT token and backend endpoints are stored locally for subsequent data exports. From c4cdfd6a88bbe70965fedc9290a29e3d21bb858f Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Thu, 30 Jul 2026 14:11:55 -0600 Subject: [PATCH 3/7] Update .github/workflows/fern-docs-preview-comment.yml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Ed Balduf Signed-off-by: Ed Balduf --- .github/workflows/fern-docs-preview-comment.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/fern-docs-preview-comment.yml b/.github/workflows/fern-docs-preview-comment.yml index 442aad8e..8b02081f 100644 --- a/.github/workflows/fern-docs-preview-comment.yml +++ b/.github/workflows/fern-docs-preview-comment.yml @@ -43,7 +43,9 @@ jobs: runs-on: ubuntu-latest # runs-on: linux-amd64-cpu8 # NVIDIA self-hosted runner timeout-minutes: 15 - if: ${{ github.event.workflow_run.conclusion == 'success' }} + if: >- + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.head_repository.full_name == github.repository steps: - name: Download fern sources and metadata uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 From 6546837f5ffc22afe6c5409dfd9e69fa66d3d477 Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Thu, 30 Jul 2026 14:12:15 -0600 Subject: [PATCH 4/7] Update docs/1.2/usage.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Ed Balduf Signed-off-by: Ed Balduf --- docs/1.2/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/1.2/usage.md b/docs/1.2/usage.md index 73d4553f..022cf6ec 100644 --- a/docs/1.2/usage.md +++ b/docs/1.2/usage.md @@ -108,7 +108,7 @@ The command prints each check result and exits non-zero if any hard requirement ```bash # Pass token directly (visible in process list) -sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com--token= +sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token= # Read token from a file (recommended) sudo fleetint enroll --endpoint=https://data.fleet-intelligence.nvidia.com --token-file=/path/to/token From 03ce309f253b75dc7ce833b0ebf0867d57426f3c Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Thu, 30 Jul 2026 14:13:30 -0600 Subject: [PATCH 5/7] Update .github/workflows/publish-fern-docs.yml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Ed Balduf Signed-off-by: Ed Balduf --- .github/workflows/publish-fern-docs.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-fern-docs.yml b/.github/workflows/publish-fern-docs.yml index 51956e72..49d2f1d4 100644 --- a/.github/workflows/publish-fern-docs.yml +++ b/.github/workflows/publish-fern-docs.yml @@ -60,6 +60,8 @@ jobs: set -o pipefail fern generate --docs 2>&1 | tee /tmp/fern-output.log URL=$(grep -oP 'Published docs to \K.*(?= \()' /tmp/fern-output.log || true) - if [ -n "$URL" ]; then - echo "### Published: [$URL]($URL)" >> "$GITHUB_STEP_SUMMARY" + if [ -z "$URL" ]; then + echo "::error::Failed to determine the published documentation URL." + exit 1 fi + echo "### Published: [$URL]($URL)" >> "$GITHUB_STEP_SUMMARY" From 4af959df9124e596beafd98c610edb0fdf216511 Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Thu, 30 Jul 2026 15:11:25 -0600 Subject: [PATCH 6/7] ci(fern): gate publish on stable releases and fail on missing URL - Skip publish job for pre-release tags (e.g. v1.3.2-rc.1); only stable releases and manual workflow_dispatch trigger production publish - Explicitly fail the publish step when fern generate --docs does not emit a published URL, preventing silent success on output format changes Co-Authored-By: Claude Sonnet 4.6 (1M context) Signed-off-by: Ed Balduf --- .github/workflows/publish-fern-docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-fern-docs.yml b/.github/workflows/publish-fern-docs.yml index 49d2f1d4..55cf6243 100644 --- a/.github/workflows/publish-fern-docs.yml +++ b/.github/workflows/publish-fern-docs.yml @@ -41,6 +41,7 @@ jobs: runs-on: ubuntu-latest # runs-on: linux-amd64-cpu8 # NVIDIA self-hosted runner timeout-minutes: 20 + if: ${{ github.event_name == 'workflow_dispatch' || !github.event.release.prerelease }} steps: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -61,7 +62,7 @@ jobs: fern generate --docs 2>&1 | tee /tmp/fern-output.log URL=$(grep -oP 'Published docs to \K.*(?= \()' /tmp/fern-output.log || true) if [ -z "$URL" ]; then - echo "::error::Failed to determine the published documentation URL." + echo "::error::Fern did not emit a published URL — verify the publish succeeded" exit 1 fi echo "### Published: [$URL]($URL)" >> "$GITHUB_STEP_SUMMARY" From f155707979bf9461c87e58e9439faed000aedfd9 Mon Sep 17 00:00:00 2001 From: Ed Balduf Date: Thu, 30 Jul 2026 15:13:04 -0600 Subject: [PATCH 7/7] ci(fern): use set -euo pipefail in publish step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without -e, a fern generate failure would not terminate the step immediately — execution would continue to the URL grep and fail with a misleading error. -u catches unset variable references as an added guard. Co-Authored-By: Claude Sonnet 4.6 (1M context) Signed-off-by: Ed Balduf --- .github/workflows/publish-fern-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-fern-docs.yml b/.github/workflows/publish-fern-docs.yml index 55cf6243..5eaef46a 100644 --- a/.github/workflows/publish-fern-docs.yml +++ b/.github/workflows/publish-fern-docs.yml @@ -58,7 +58,7 @@ jobs: env: FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }} run: | - set -o pipefail + set -euo pipefail fern generate --docs 2>&1 | tee /tmp/fern-output.log URL=$(grep -oP 'Published docs to \K.*(?= \()' /tmp/fern-output.log || true) if [ -z "$URL" ]; then