Archives#

archive demo

This tutorial walks through packaging a workspace into a portable archive and restoring it on another machine or in CI.

Prerequisites#

  • conda (>= 26.3) with the conda-workspaces plugin installed

  • A workspace with a manifest (conda.toml, pixi.toml, or pyproject.toml) and conda.lock

Create a workspace archive#

An archive bundles your manifest, lockfile, and source files into a single .tar.zst (or .tar.gz) file. In a git repo, only tracked files are included.

conda workspace archive -o my-project.tar.zst

The resulting file contains everything needed to reproduce the workspace elsewhere:

my-project.tar.zst
  conda.toml
  conda.lock
  src/
    app.py
    ...

If no -o is given, the archive is named after the workspace (<name>.tar.zst) and placed in the project root.

Use gzip compression#

For broader compatibility, use a .tar.gz extension:

conda workspace archive -o my-project.tar.gz

Exclude files#

Some files should not be included in archives. Configure permanent exclusions in your manifest:

[workspace.archive]
exclude = ["docs/**", "*.log", "data/raw/**"]

Or pass one-off exclusions on the command line:

conda workspace archive --exclude "benchmarks/**" --exclude "*.csv"

Both sources are combined. Built-in exclusions (.git, __pycache__, .conda/envs, .pixi) always apply regardless of configuration.

Extract an archive#

On the receiving end, extract the archive with:

conda workspace unarchive my-project.tar.zst

This creates a my-project/ directory (derived from the archive filename) containing the full workspace. To choose a different location:

conda workspace unarchive my-project.tar.zst --target /path/to/destination

After extraction, install the environments from the lockfile:

cd my-project
conda workspace install --locked

Extract and install in one step#

archive install demo

Pass --install to extract the archive and install all environments from the lockfile in a single command:

conda workspace unarchive my-project.tar.zst --target /path/to/destination --install

This is equivalent to extracting, changing into the directory, and running conda workspace install --locked, but without the extra steps.

Lock before archiving#

If your lockfile is out of date or does not exist yet, pass --lock to solve and write conda.lock before creating the archive:

conda workspace archive --lock

This is equivalent to running conda workspace lock followed by conda workspace archive, but in a single command.

Bundle packages for offline use#

archive bundle demo

When the target machine has no internet access, use --bundle to include all resolved .conda packages inside the archive.

You need a lockfile first. Pass --lock to generate one automatically, or run conda workspace lock beforehand.

conda workspace archive --lock --bundle -o my-project-offline.tar.zst

This adds a packages/ directory inside the archive. Package hashes are verified against the lockfile before bundling.

On the receiving end, conda workspace unarchive detects the bundled packages, verifies their hashes, and copies them into the local conda cache before installation:

conda workspace unarchive my-project-offline.tar.zst
# packages are primed into the conda cache automatically
cd my-project-offline
conda workspace install --locked

Pass --no-install to skip cache priming if you only want the files:

conda workspace unarchive my-project-offline.tar.zst --no-install

Security#

Archives are extracted with path traversal protection. Every member is validated before extraction: absolute paths, .. components, symlinks escaping the target directory, and special file types (device nodes, FIFOs) are all rejected. On Python 3.12+ the filter="data" parameter provides additional defense-in-depth.

When --bundle is used, package hashes are verified against the lockfile’s SHA256 entries both at archive creation and at extraction. Packages without a SHA256 entry in the lockfile produce a warning and are not verified.

Trust model for bundled archives#

A bundled archive is self-consistent: the package hashes match the lockfile that ships inside the archive. However, the lockfile itself is not externally signed. If the archive came from an untrusted source, the lockfile inside it could have been tampered with to match altered packages.

To guard against this:

  • Obtain archives only from trusted sources.

  • When possible, compare the lockfile inside the archive against a separately obtained copy (e.g. from version control).

  • Use conda workspace install --locked so the solver does not silently add packages beyond what the lockfile specifies.

Next steps#