> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://rivet.chrisboulton.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://rivet.chrisboulton.com/_mcp/server.

# Package

> Apt repository packages and confined, bundled dpkg archives.

`package` installs, upgrades, holds, and removes Debian packages, either from apt repositories or from `.deb` archives bundled with your configuration. Both providers use the same package database, so a package name and architecture can be declared only once, whichever provider you use. An `all`-architecture package conflicts with any other declaration of that name.

```hcl
package "curl" {
  ensure = "present"

  apt {
    install_recommends = false
    update_cache      = "if_stale"
    cache_valid_for   = "1h"
  }
}
```

An omitted provider selects apt when target facts advertise `package.apt.v1`. `provider = "apt"` or `provider = "dpkg"` chooses one; approved [plugins](/contributing/plugins#service-and-package-providers) can add further providers, which pin their implementation identity into the catalog and never join automatic selection unless they declare a priority. A provider block must match the selected provider; unrelated blocks, duplicate blocks, and unknown options fail.

| Common field      | Default                   | Behavior                                                                                                                                                            |
| ----------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`            | resource label            | Exact Debian package name; option, wildcard, and apt suffix syntax is refused.                                                                                      |
| `provider`        | Automatic apt selection   | Explicit `apt` or `dpkg`; requires the matching capability and provider block.                                                                                      |
| `ensure`          | `present`                 | `present`, `latest`, `absent`, or `purged`; dpkg rejects `latest`.                                                                                                  |
| `version`         | unmanaged                 | Exact version; requires `present`.                                                                                                                                  |
| `architecture`    | native `amd64` or `arm64` | Debian architecture; compiler normalizes `x86_64` to `amd64` and `aarch64` to `arm64`. `all` is architecture-independent.                                           |
| `source`          | omitted                   | Dpkg archive, bundled from a confined path relative to the configuration root. Requires explicit `provider = "dpkg"` and `present`.                                 |
| `checksum`        | omitted                   | Optional bare 64-character lowercase SHA-256 hex digest of the source (no `sha256:` prefix); verified when compiling. Bundled assets always carry verified digests. |
| `held`            | unmanaged                 | Optional boolean, only for installed desired states; `true` conflicts with `latest`.                                                                                |
| `allow_downgrade` | `false`                   | Permit a declared exact or archive version older than the installed version.                                                                                        |

Null omits optional `version`, `source`, `checksum`, and `held`. Required policy fields reject null. All [common metadata](/language/metadata), including ordering, notifications, noop, sensitivity, tags, description, and timeout, is available. Resource handles and static `name`, `ensure`, `version`, `architecture`, and `held` references preserve dependencies. Omitted runtime-derived values cannot be exported. Outputs can declare `resource("package")`.

## Apt provider

The apt provider handles candidate selection, index refresh, command options, and mutation behavior. It uses `apt-cache policy`, `apt-get`, and the shared `dpkg-query` installed-state reader.

| `apt` field          | Default   | Behavior                                                                              |
| -------------------- | --------- | ------------------------------------------------------------------------------------- |
| `install_recommends` | `true`    | Include recommended dependencies during installation.                                 |
| `update_cache`       | `"never"` | `"never"`, `"if_stale"`, or `"always"`; refresh at most once per apply.               |
| `cache_valid_for`    | `"1h"`    | Positive integer followed by `s`, `m`, `h`, or `d`; checked for overflow.             |
| `default_release`    | omitted   | Exact repository release preference, passed to candidate selection and mutation.      |
| `conffile_policy`    | `"keep"`  | `"keep"` preserves locally modified conffiles; `"replace"` selects the packaged copy. |

`present` preserves any fully installed version unless `version` is supplied. `latest` selects the repository candidate using Debian version ordering and preserves an installed version newer than the candidate. Installs pin the selected version and forbid implicit package removals. A read-only apt simulation validates dependency resolution before mutation; removals that would remove unrelated packages are refused. Apt retains its native authentication and essential-package protections.

Refresh success updates `/var/lib/apt/periodic/update-success-stamp`; `if_stale` uses its modification time, treating missing or future stamps as stale. A failed refresh fails the resource and is not retried by other apt resources in the same run. Only present/latest resources request refresh. Refresh alone reports `unchanged`, so it does not imply a package consumer changed.

Noop never refreshes indexes. A missing candidate or a latest candidate that may change after refresh is reported with `uncertain = true`; unresolved predictions defer dependents. Real apply fails if no candidate is available after any requested refresh.

## Dpkg provider

The dpkg provider handles archive metadata checks, archive installation, and removal behavior. It uses `dpkg-deb` through stdin to inspect archives without creating candidates during plan. It verifies the archive digest, package name, architecture, and any declared version before installation.

```hcl
package "application" {
  name     = "example-application"
  provider = "dpkg"
  source   = "assets/example-application.deb"

  dpkg {
    conffile_policy = "keep"
  }
}
```

| `dpkg` field      | Default  | Behavior                                                   |
| ----------------- | -------- | ---------------------------------------------------------- |
| `conffile_policy` | `"keep"` | `"keep"` or `"replace"` for package-managed configuration. |

Dpkg installs a bundled archive using an anonymous seekable file that is unlinked immediately, so interruption leaves no archive candidate to clean up. It does not fetch dependencies or invoke apt repair. Missing dependencies may leave an unpacked or partly configured package; those states are reported and fail convergence until dependencies are satisfied.

URL downloads and target-host archive paths are not implemented. Bundle a configuration-relative archive instead. Foreign architectures must already be enabled on the host; Rivet does not mutate the architecture registry.

## Execution and verification

Local real apply requires root and the existing host apply lock. Apt and dpkg also acquire their native package database locks and fail when another package manager holds them. A package resource has a shared 300-second deadline across inspection, refresh, mutation, and verification. Commands use explicit argv and a controlled noninteractive environment. Stdout capture is bounded to 1 MiB for queries; mutation output and stderr are drained and discarded. Timeouts terminate the owned process group; escaped descendants may remain.

Changing a currently held package requires `held = false`; the provider never silently overrides a hold. A held package must be unheld (`held = false`) while present before declaring it absent. `absent` removes the package while preserving conffiles; `purged` also removes package-managed configuration.

Mutation intent is durable before refresh, hold changes, or package changes. Postcondition inspection confirms package status, managed version, and hold state. Failed/partial mutations preserve uncertainty in the journal. A subsequent compatible apply re-inspects current state and converges it, reporting historical uncertainty; obsolete intent is retained as with files. There is no automatic rollback or automatic retry.

The disposable-host test `tests/host/package_workflow.py` exercises these behaviors; see [testing](/contributing/testing).

Tool contracts: [apt-get](https://manpages.debian.org/bookworm/apt/apt-get.8.en.html), [dpkg](https://manpages.debian.org/bookworm/dpkg/dpkg.1.en.html), [dpkg-query](https://manpages.debian.org/bookworm/dpkg/dpkg-query.1.en.html), and [dpkg-deb](https://manpages.debian.org/bookworm/dpkg/dpkg-deb.1.en.html).