Getting Started

This tutorial walks you through your first inspectah scan. By the end, you will have scanned a host, reviewed the output artifacts, and opened the refine UI to triage findings. Total time: about 10 minutes.

Prerequisites

  • A Fedora, CentOS Stream, or RHEL host (the system you want to migrate)
  • Podman installed (dnf install podman)
  • Root access on the target host (inspectah reads system configuration)

For RHEL users: inspectah pulls the matching base image to classify findings. RHEL base images require registry authentication:

sudo podman login registry.redhat.io

Fedora and CentOS Stream base images are available from public registries and do not require authentication. If you skip registry auth on RHEL, inspectah will fail to pull the baseline image.

For disconnected or air-gapped environments: Pull the base image on a connected machine, save it as a tarball (podman save -o baseline.tar <image-ref>), transfer the tarball to your target host, and load it (podman load -i baseline.tar). Alternatively, configure a local or mirror registry.

Install inspectah

RPM (Fedora / RHEL / CentOS Stream)

sudo dnf copr enable mrussell/inspectah
sudo dnf install inspectah

macOS (Homebrew)

brew tap marrusl/inspectah
brew install inspectah

Apple Silicon only. For Intel Macs, build from source below.

From source

git clone https://github.com/marrusl/inspectah.git
cd inspectah
cargo build --release -p inspectah-cli
sudo install target/release/inspectah /usr/local/bin/

Requires Rust 1.80+ and a C linker.

Verify the install:

inspectah version

You should see the version number, git commit, and build date.

How inspectah works

Before diving into the commands, here is a visual overview of what inspectah does when you scan a host:

The inspectah pipeline: from host inspection through baseline subtraction to migration artifacts. Click "Open interactive diagram" for zoom, pan, and click-to-expand detail.

Scan your first host

Run inspectah as root on the system you want to migrate:

sudo inspectah scan

inspectah runs a four-stage pipeline:

  1. Detect the OS and resolve a matching base image
  2. Pull the base image (you will see download progress)
  3. Inspect the system — RPMs, configs, services, users, repos, containers, storage, and more (11 inspectors by default)
  4. Render migration artifacts and package them into a tarball

A typical scan takes 30–90 seconds depending on the number of installed packages and network speed for the base image pull. On subsequent runs, the base image is cached locally.

When the scan finishes, you will see output like:

  ✓ RPM packages               847 packages, 6 repos
  ✓ Services                    27 units
  ✓ Storage                     done
  ✓ Kernel & boot               done
  ✓ Network                     done
  ✓ Containers                  2 found
  ✓ Users & groups              done
  ✓ Scheduled tasks             done
  ✓ Config files                12 modified
  ✓ SELinux                     done
  ✓ Non-RPM packages            2 ecosystems
      pip packages 23 · npm packages 69 · 1 repo-less RPM (cached)

  ┄┄┄
  12 modified configs · 23 pip packages · 69 npm packages · 1 repo-less

  Inspected in 42.3s
  Report: myhost-20260527-143000.tar.gz
  To review: inspectah refine myhost-20260527-143000.tar.gz

The tarball is written to your current directory. The filename includes the hostname and a timestamp.

Understand the output

Extract the tarball to see what inspectah produced:

tar tzf myhost-*.tar.gz

Key files inside:

File Purpose
Containerfile Image build definition — the starting point for podman build
audit-report.md Findings summary: what was detected, storage plan, version drift
audit-report.html HTML audit report of all findings
secrets-review.md Details of redacted sensitive content for your review
README.md Build commands and a FIXME checklist
kickstart-suggestion.ks Deploy-time settings (network, storage, boot)
inspection-snapshot.json Structured data — the full snapshot, re-renderable
config/ Modified config files to COPY into the image

Conditional files may also appear depending on your system: quadlet/ for container workloads, language-packages/ for pip/npm/gem environments, repoless-packages/ for RPMs with no repository source, inspectah-users.toml / inspectah-users.ks for user and group definitions, and subscription/ for RHEL subscription data.

For a complete description of every artifact, see Output Artifacts.

Beyond RPMs

inspectah detects language packages (pip, npm, gem) automatically. The Containerfile includes install directives for detected environments, with confidence levels that control whether directives are active, commented-out, or advisory. See Handle Non-RPM Software for details.

To also capture files under /opt, /srv, /usr/local that are not managed by any package manager, add --include-unmanaged:

sudo inspectah scan --include-unmanaged

Packages installed from local .rpm files or disabled repositories are flagged automatically. See Handle Repo-less RPMs for the upload and resolution workflow.

Open the refine UI

The refine command starts a local web server so you can review and curate the scan findings in your browser:

inspectah refine myhost-*.tar.gz

You will see:

Loading snapshot...
Starting refine server on http://127.0.0.1:8642
Press Ctrl-C to stop.

Your browser opens automatically. If it does not, navigate to http://127.0.0.1:8642 manually.

The refine UI shows every finding organized by section (packages, configs, services, language packages, unmanaged files, etc.). Each item has a triage classification and an include/exclude toggle. Your changes are autosaved – close the browser and stop the server with Ctrl-C when you are done.

If you are accessing a remote host over SSH, forward the port:

ssh -L 8642:localhost:8642 user@remote-host

Then open http://127.0.0.1:8642 in your local browser.

The end-to-end user workflow: scan, refine, aggregate aggregate, and build. Click "Open interactive diagram" for zoom, pan, and click-to-expand detail.

Understand triage classifications

inspectah classifies every finding into one of three buckets:

Classification Meaning Action
Baseline Already provided by the base image — no action needed Excluded from the Containerfile (subtracted from scope)
Site Specific to this host — likely needs to be carried forward Included in the Containerfile by default
Investigate Ambiguous — inspectah could not confidently classify it Review manually and decide include or exclude

Baseline subtraction is the core value of running inspectah against a known base image. Instead of migrating everything, you only carry forward what the base image does not already provide.

For details on how classification works and the aggregate-level extensions (Universal, Partial, Divergent), see Triage Classification.

Next steps

You have scanned a host, reviewed the output, and seen the triage model in action. From here:

  • Review and refine findings — use the refine UI to curate include/exclude decisions. See How to Review and Refine.
  • Build a bootc image — use inspectah build to build the image directly from the scan tarball, or use podman build manually with the generated Containerfile. See How to Build a bootc Image.
  • Roll up multiple hosts — migrating more than one system? Scan them all and aggregate the results to find common patterns. See How to Aggregate Multiple Hosts.
  • Handle non-RPM software — pip, npm, and gem packages are detected automatically. See Handle Non-RPM Software.
  • Resolve repo-less packages — packages without a repository source need manual handling. See Handle Repo-less RPMs.
  • Explore the full CLI — see all available commands and flags in the CLI Reference.