> For the complete documentation index, see [llms.txt](https://docs.sealsecurity.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sealsecurity.io/setup-apps-os/seal-os-cicd.md).

# Seal OS in CI/CD

Seal OS remediates vulnerabilities in OS-level packages: the Alpine `apk`, Debian and Ubuntu `apt`, and Red Hat / CentOS / Amazon Linux `rpm` packages that ship inside a Linux container image alongside your application. The CLI command for this work is `seal fix --os`.

The deployment shape is almost always the same: `seal fix --os` runs inside a `Dockerfile` during `docker build`, after the base image's package manager has installed the OS packages and before the rest of the build finalizes the image. The resulting image ships with the sealed versions of the OS packages in place of the vulnerable originals.

This chapter is the canonical setup home for the Seal OS path through CI/CD. The same CLI also runs on a connected live host (a Linux VM or bare-metal server with outbound to Seal); the mechanics are identical to the in-Dockerfile flow described here, with the seal step invoked from the host's patching runbook instead of the image build. For environments where hosts cannot reach Seal at all, see [On-prem and air-gapped environments](/setup-apps-os/on-prem.md).

* [`seal fix --os` reference](/setup-apps-os/seal-os-cicd/seal-fix-os-reference.md): commands, flags, and environment variables.
* [Sealing OS packages in a Dockerfile](/setup-apps-os/seal-os-cicd/dockerfile.md): the per-distribution patterns for `apk`, `apt`, and `rpm` images.
* [Integrating with your container build pipeline](/setup-apps-os/seal-os-cicd/container-build-pipeline.md): wiring the Dockerfile build into the CI system that drives your image releases.

## Before you start

* A Linux container image you build yourself (an image whose `Dockerfile` is in your source tree). Seal OS on vendor-supplied images you do not rebuild is covered by Seal Vendor Apps, not this chapter.
* A [token](/getting-started/tokens.md) for authentication, set in the build environment as `SEAL_TOKEN`. Production tokens for production-equivalent CI; development tokens for developer machines and feature-branch pipelines.
* A [Seal Project](/getting-started/creating-a-seal-project.md) for the CLI to attribute its activity to, supplied as `SEAL_PROJECT`. The first run with a `SEAL_PROJECT` value that does not exist creates the project automatically. If the same build also runs `seal fix` for application dependencies, use a **different** Seal Project for it; see "Use a separate Seal Project for `seal fix --os`" below.
* Network access from the container build environment to the Seal Platform and to the per-distribution Seal OS artifact servers (`apk.sealsecurity.io`, `deb.sealsecurity.io`, `rpm.sealsecurity.io`).

## How the CLI seals OS packages

`seal fix --os` detects the distribution of the container it is running inside, identifies which OS packages are installed and vulnerable, pulls the sealed versions from the matching Seal OS artifact server, and replaces the package files on disk. After the replacement, the CLI updates the package-manager database (`apk`, `dpkg`, `rpm`) so its view of what is installed matches the sealed versions actually on disk. The resulting image is structurally indistinguishable from one built against the upstream packages: the same files in the same paths, with the same package-manager metadata, only with the vulnerabilities backported out.

Three OS-package families are supported today:

| Family | Distributions                                                          | Seal OS artifact server |
| ------ | ---------------------------------------------------------------------- | ----------------------- |
| `apk`  | Alpine Linux                                                           | `apk.sealsecurity.io`   |
| `deb`  | Debian, Ubuntu                                                         | `deb.sealsecurity.io`   |
| `rpm`  | Red Hat Enterprise Linux, CentOS, Rocky Linux, AlmaLinux, Amazon Linux | `rpm.sealsecurity.io`   |

The CLI selects the right family based on the image it runs inside; you do not configure it explicitly.

## When in the build the CLI runs

`seal fix --os` replaces installed OS packages **on the filesystem** of the container being built. A container always inherits some OS packages from its base image; on top of that, most `Dockerfile`s install additional packages (typically through `RUN apk add` / `RUN apt-get install` / `RUN dnf install`) and may upgrade some of the base-image packages along the way.

Run `seal fix --os` **after every step that installs or upgrades OS packages**, so the full installed set is in scope: the base image's packages plus anything your `Dockerfile` added or bumped. Running it earlier means the additions and bumps that came later are not considered, and the image ships with only the initial subset sealed.

The other constraint is privilege. The CLI needs to write to the package-manager database, which means it must run while the build is still `USER root`. If a `USER` directive has dropped privileges before the seal step, the step fails.

## Sealing Rules and OS packages

The CLI's [fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode.md) applies the same way for OS packages as for application dependencies: in **remote** mode the CLI fetches Sealing Rules from the Seal Platform; in **local** mode it reads them from `.seal-actions.yml`; in **all** mode it replaces every vulnerable OS package it has a sealed version for, without consulting any rule. The three modes map to the same three deployment methods that the application-dependency path uses.

## Use a separate Seal Project for `seal fix --os`

If your build also runs `seal fix` for application dependencies, do **not** point both invocations at the same `SEAL_PROJECT`. Each CLI scan reports the packages it discovered to the project; the next scan against the same project marks every package the previous scan reported (and the current one did not) as stale, so they drop off the Protection page. Because `seal fix` discovers application packages and `seal fix --os` discovers OS packages — two disjoint sets — running them back to back against the same `SEAL_PROJECT` makes the second run silently bury the first run's discovery.

The on-disk fixes in both invocations still happen correctly. Only Seal's view of the project's package coverage is affected.

The recommended setup is to create two Seal Projects per image — for example, `my-app` for the application-dependency scan and `my-app-os` for the OS-package scan — and pass the corresponding `SEAL_PROJECT` to each `seal fix` and `seal fix --os` invocation respectively. Both projects can sit under the same tenant; the rest of the configuration (tokens, Sealing Rules, the deployment method) is per-project.

## Related

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method.md): the decision page for the five deployment methods.
* [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd.md): the parallel chapter for application dependencies. The two share the CLI binary, the fix-mode model, and the token configuration; they diverge only in which `seal fix` subcommand runs.
* [On-prem and air-gapped environments](/setup-apps-os/on-prem.md): the alternate workflow when hosts cannot reach Seal directly.
