APT Plugin
The APT plugin provides support for Debian/Ubuntu APT repositories.
Overview
Status: ✅ Available
The APT plugin consists of:
AptSyncPlugin - Syncs packages from upstream APT repositories
AptPublisher - Publishes APT repositories with Debian-compliant metadata
Features
Repository Modes:
✅ Mirror Mode - Full metadata mirroring (InRelease, Release, Packages)
✅ Filtered Mode - Smart metadata regeneration for filtered repos (with optional GPG signing)
✅ Hosted Mode - Upload-only repositories for self-hosted
.debpackages (chantal package upload)
Package Management:
✅ InRelease/Release file parsing
✅ Packages(.gz) parsing
✅ DEB package downloading
✅ SHA256/SHA1/MD5 checksum verification
✅ Architecture filtering (amd64, arm64, armhf, i386, all, etc.)
✅ Component filtering (main, contrib, non-free, etc.)
✅ Pattern-based package filtering
✅ Source package mirroring (
.dsc/.orig.tar.*/.debian.tar.*) +Sourcesregeneration✅
Contents-<arch>index mirroring (apt-file; mirror mode)✅ Translation/i18n mirroring (
i18n/Translation-*+i18n/Index; mirror mode)✅
by-hashacquisition and publishing (Acquire-By-Hash)✅ Version filtering (only latest)
Metadata Support:
✅ RFC822-format Packages file generation
✅ Release file generation with MD5/SHA1/SHA256 checksums
✅ InRelease file preservation (GPG-signed)
✅ GPG signature generation for filtered mode (InRelease, Release.gpg)
✅ Multi-component and multi-architecture layouts
✅ Configurable Packages index compression (gzip, zstandard, bzip2, none)
✅ Dependency metadata (Depends, Recommends, Suggests, Conflicts, etc.)
Planned:
🚧 diff/Index support
Configuration
Basic APT Repository
repositories:
- id: ubuntu-jammy-main
name: Ubuntu 22.04 Jammy - Main
type: apt
feed: http://archive.ubuntu.com/ubuntu
enabled: true
apt:
distribution: jammy
components:
- main
architectures:
- amd64
Multi-Component Repository
repositories:
- id: ubuntu-jammy-full
name: Ubuntu 22.04 Jammy - Full
type: apt
feed: http://archive.ubuntu.com/ubuntu
enabled: true
apt:
distribution: jammy
components:
- main
- restricted
- universe
- multiverse
architectures:
- amd64
- arm64
Mirror Mode (Exact Copy)
repositories:
- id: debian-bookworm-mirror
name: Debian 12 Bookworm - Mirror
type: apt
feed: http://deb.debian.org/debian
enabled: true
mode: mirror
apt:
distribution: bookworm
components:
- main
- contrib
- non-free
architectures:
- amd64
With Authentication
repositories:
- id: private-apt-repo
name: Private APT Repository
type: apt
feed: https://apt.example.com/debian
enabled: true
apt:
distribution: stable
components:
- main
architectures:
- amd64
auth:
type: basic
username: myuser
password: mypassword
APT-Specific Options
The apt section in repository configuration supports these options:
Required Options
distribution(string) - APT distribution/suite nameExamples:
jammy,focal,bookworm,bullseye,stableUsed in the URL:
dists/{distribution}/
components(list) - Repository components to syncExamples:
main,restricted,universe,multiverse(Ubuntu)Examples:
main,contrib,non-free,non-free-firmware(Debian)Examples:
stable,edge,testing(third-party repos)
architectures(list) - Architectures to syncCommon:
amd64,arm64,armhf,i386,allSpecial:
source(for source packages, requiresinclude_source_packages: true)
Optional Options
include_source_packages(boolean, default: false)Sync source packages: download the
.dsc/.orig.tar.*/.debian.tar.*artifacts referenced by theSourcesindex, verify each against itsChecksums-Sha256entry, and publish them under<component>/source/with a regeneratedSourcesindex (referenced fromRelease).In filtered mode, source stanzas are filtered by component and by the
filters.patternsrules matched on the source-package name (which can differ from binary names, e.g. sourcefoo→ binarylibfoo1); priority andonly_latest_versionare binary-only.Note: source packages require significant additional space.
include_contents(boolean, default: false)Mirror
Contents-<arch>indices (the file→package map used byapt-file), includingContents-allandudebvariants where present, at both the component-scoped (<component>/Contents-<arch>) and suite-level paths.Mirror mode only: the indices are republished verbatim and referenced in the regenerated
Release. In filtered mode Contents are dropped — regenerating an accurate index would require per-.debfile-list extraction that chantal does not perform, and shipping the upstream one would reference packages that were filtered out.Note: Contents files are large (tens to hundreds of MB).
include_translations(boolean, default: false)Mirror the
i18n/Translation-<lang>.{gz,xz,bz2}files (localized package descriptions) and thei18n/Index, for every language/variant present inRelease, republished verbatim and referenced in the regeneratedRelease.Mirror mode only (dropped in filtered mode, like
include_contents): regenerating localized descriptions for the filtered set would require remapping each kept package’sDescription-md5; the full descriptions are already carried inline in the regeneratedPackages.
by_hash(boolean, default: false)On sync, fetch each index from
by-hash/SHA256/<checksum>(falling back to the plain path when upstream has no by-hash tree) so a mirror stays consistent while upstream is being updated.On publish, emit
by-hash/SHA256/<sha256>copies of every regenerated index (Packages/Sources/Contents/Translation) and setAcquire-By-Hash: yesin the generatedRelease. Recommendedtruefor modern apt clients.
Generated
Releasefields — the publishedReleaseis regenerated and re-signed, so its header fields are controllable:origin/label—Origin/Label(default:Chantal/ the repository name).suite/codename— distinctSuite/Codename(default: both thedistribution). Upstream often differs (e.g. Suitestable, Codenamebookworm).not_automatic(bool) →NotAutomatic: yes(apt won’t auto-select this repo’s packages — pin priority 1).but_automatic_upgrades(bool) →ButAutomaticUpgrades: yes(raises the pin to 100 so already-installed packages still upgrade). Only valid together withnot_automatic.valid_until_days(int) → emitValid-Until= publish time + N days. Omitted by default; the upstream date is never copied (it is usually already expired by publish time).Note: changing
suite/codenameon an already-deployed mirror makes clients fail the nextapt updatewith a “Repository changed its Suite/ Codename” error until they accept it (apt update --allow-releaseinfo-change). Set these once, up front.
flat_repository(boolean, default: false)Support for flat repositories (no dists/ structure)
Rare, used by some very old repositories
Metadata Compression
In filtered mode Chantal regenerates the Packages index. The uncompressed
Packages file is always written, alongside one compressed variant controlled
by the top-level metadata.compression option:
repositories:
- id: ubuntu-jammy-filtered
type: apt
feed: http://archive.ubuntu.com/ubuntu
mode: filtered
apt:
distribution: jammy
components: [main]
architectures: [amd64]
metadata:
compression: zstandard # gzip (default) | zstandard | bzip2 | none
Value |
Output |
Notes |
|---|---|---|
|
|
|
|
|
Universally supported |
|
|
Supported by modern apt (Ubuntu) |
|
|
Legacy |
|
|
Uncompressed index only |
All generated variants are listed with their checksums in the Release file, so
clients automatically pick a format they support.
Publishing
Publish Latest Repository State
chantal publish repo --repo-id ubuntu-jammy-main
Output structure:
/var/www/repos/ubuntu-jammy-main/
├── dists/
│ └── jammy/
│ ├── InRelease # GPG-signed (if available from upstream)
│ ├── Release # Contains MD5/SHA1/SHA256 checksums
│ └── main/
│ └── binary-amd64/
│ ├── Packages # RFC822 format
│ └── Packages.gz # Compressed
└── pool/
└── main/
└── d/
└── docker-ce/
└── docker-ce_20.10.21_amd64.deb
Client configuration (sources.list):
deb [arch=amd64] http://mirror.example.com/repos/ubuntu-jammy-main jammy main
Publish Snapshot
# Create snapshot first
chantal snapshot create --repo-id ubuntu-jammy-main --name 2026-01-12
# Publish the snapshot
chantal publish snapshot --snapshot 2026-01-12 --repo-id ubuntu-jammy-main
Client configuration for snapshot:
deb [arch=amd64] http://mirror.example.com/repos/snapshots/ubuntu-jammy-main/2026-01-12 jammy main
Unpublish
# Unpublish repository
chantal publish unpublish --repo-id ubuntu-jammy-main
# Unpublish snapshot
chantal publish unpublish --snapshot 2026-01-12 --repo-id ubuntu-jammy-main
Directory Structure
Standard APT Repository Layout
/var/www/repos/{repo-id}/
├── dists/
│ └── {distribution}/
│ ├── InRelease # GPG-signed Release (preserved in mirror mode)
│ ├── Release # Repository metadata with checksums
│ ├── Release.gpg # Detached GPG signature (if available)
│ ├── main/
│ │ ├── binary-amd64/
│ │ │ ├── Packages # Package metadata (RFC822 format)
│ │ │ └── Packages.gz # Compressed packages index
│ │ ├── binary-arm64/
│ │ │ ├── Packages
│ │ │ └── Packages.gz
│ │ └── source/ # If include_source_packages: true
│ │ ├── Sources
│ │ └── Sources.gz
│ └── contrib/
│ └── binary-amd64/
│ ├── Packages
│ └── Packages.gz
└── pool/
├── main/
│ ├── a/
│ │ └── apt/
│ │ └── apt_2.4.8_amd64.deb
│ └── d/
│ └── docker-ce/
│ └── docker-ce_24.0.7_amd64.deb
└── contrib/
└── v/
└── virtualbox/
└── virtualbox-7.0_7.0.12_amd64.deb
Content-Addressed Storage Pool
All .deb files are stored in the global content-addressed pool:
/var/lib/chantal/pool/
└── ab/
└── cd/
└── abcdef1234567890...sha256_docker-ce_24.0.7_amd64.deb
Publishing uses hardlinks (zero-copy) from the pool to the published directory.
Repository Modes
MIRROR Mode
Byte-for-byte 1:1 copy of upstream: packages keep their upstream pool/ paths,
and the Packages/Sources/Contents/Translation indices plus the signed
InRelease/Release/Release.gpg are republished verbatim. Nothing is
regenerated or re-signed, so the upstream signatures remain valid (and will
eventually expire along with upstream — expected for a true mirror; any gpg
signing config is ignored in mirror mode).
Behavior:
Stores and republishes InRelease/Release/Packages exactly as upstream (no regeneration, no re-signing)
Packages served at their upstream
Filename:/Directory:pathsPreserves the original upstream GPG signatures
Ideal for exact repository mirrors
Switching modes: mirror is only meaningful for a mirror-synced repo. Don’t sync in
filteredand then publish asmirror(the verbatim upstream indices would reference packages that filtering removed). When changing a repo’s mode, re-sync and publish to a clean target (unpublishfirst).
Use Cases:
Air-gapped environments requiring exact upstream copies
Compliance requirements for unmodified repositories
CDN/mirror acceleration
Example:
repositories:
- id: debian-mirror
name: Debian Bookworm Mirror
type: apt
feed: http://deb.debian.org/debian
mode: mirror
apt:
distribution: bookworm
components: [main, contrib, non-free]
architectures: [amd64, arm64]
FILTERED Mode
Status: ✅ Available (regenerated metadata is GPG-signed when a key is configured)
Regenerates metadata for filtered package sets based on configured filters.
Behavior:
Downloads and parses upstream Packages files
Applies configured filters:
Component filtering (main, contrib, non-free, etc.)
Priority filtering (required, important, standard, optional)
Pattern-based filtering (regex include/exclude)
Version filtering (only latest versions)
Regenerates Packages and Release files based on filtered packages
Optional GPG signing - signs the regenerated metadata when a
gpgsection is configured (see GPG Signing); otherwise publishes without InRelease/Release.gpgOptimal for curated/filtered repositories
Use Cases:
Security-focused repos (only specific packages)
Bandwidth optimization (exclude large packages)
Version control (only latest versions)
Curated package sets for specific use cases
Client Configuration:
⚠️ IMPORTANT: Since filtered repositories regenerate metadata, GPG signatures from upstream become invalid.
Recommended: Sign the repository (see GPG Signing).
Once a gpg section is configured, clients can use the repository securely
without [trusted=yes]:
deb [signed-by=/etc/apt/keyrings/chantal.asc] http://mirror.example.com/repos/ubuntu-filtered jammy main
If you do not configure signing, clients must explicitly trust the repository:
Option 1: Per-repository trust
deb [trusted=yes] http://mirror.example.com/repos/ubuntu-filtered jammy main
Option 2: Global insecure repository allow
# /etc/apt/apt.conf.d/99allow-insecure
APT::Get::AllowUnauthenticated "true";
Acquire::AllowInsecureRepositories "true";
Example Configuration:
repositories:
- id: ubuntu-jammy-webservers
name: Ubuntu 22.04 - Web Servers Only
type: apt
feed: http://archive.ubuntu.com/ubuntu
enabled: true
mode: filtered # Enable filtered mode
apt:
distribution: jammy
components:
- main
- universe
architectures:
- amd64
filters:
# Component filtering
deb:
components:
include: [main] # Only main component
priorities:
include: [important, optional] # Skip required/standard
# Pattern-based filtering
patterns:
include:
- "^nginx.*"
- "^apache2.*"
- "^php.*"
exclude:
- ".*-dbg$" # Exclude debug packages
- ".*-doc$" # Exclude documentation packages
# Post-processing
post_processing:
only_latest_version: true # Keep only latest version of each package
Workflow:
# Sync with filters applied
chantal repo sync --repo-id ubuntu-jammy-webservers
# Publish filtered repository
chantal publish repo --repo-id ubuntu-jammy-webservers
Output:
=== Applying Filters (Filtered Mode) ===
After filtering: 45 packages
⚠️ WARNING: Filtered mode will regenerate metadata without GPG signatures!
Clients must use [trusted=yes] or Acquire::AllowInsecureRepositories=1
Filtering Options:
See Filters Configuration for complete documentation on available filters:
Component Filters - Filter by APT component (main, universe, contrib, non-free)
Priority Filters - Filter by package priority (required, important, standard, optional)
Pattern Filters - Regex-based include/exclude by package name
Post-Processing - Keep only latest versions, limit to N versions
Limitations:
Without a
gpgsection, clients must explicitly trust the repositoryDependency resolution must be handled by client (APT)
Comparison with Mirror Mode:
Feature |
Mirror Mode |
Filtered Mode |
|---|---|---|
GPG Signatures |
✅ Preserved (upstream) |
✅ Re-signed with own key (optional) |
Package Filtering |
❌ All packages |
✅ Configurable |
Metadata Source |
Upstream |
Regenerated |
Client Trust |
Automatic (GPG) |
GPG (signed-by) or manual (trusted=yes) |
Use Case |
Exact mirrors |
Curated subsets |
HOSTED Mode
Status: ✅ Available
An upload-only repository with no upstream feed. Custom-built .deb
packages are added with chantal package upload; there is nothing to sync, so
chantal sync skips hosted repositories. Publishing regenerates the
Packages/Release indices and pool layout exactly like filtered mode, so the
result installs with stock apt.
repositories:
- id: internal-debs
name: Internal Debian Packages
type: apt
enabled: true
mode: hosted
# note: no 'feed' - hosted repos hold only uploaded packages
apt:
distribution: jammy
components: [main]
architectures: [amd64]
Uploading and publishing:
# A single .deb (defaults to component 'main')
chantal package upload --repo-id internal-debs --file ./demo_1.0_amd64.deb
# Choose the component
chantal package upload --repo-id internal-debs --file ./demo_1.0_amd64.deb --component contrib
# A whole directory (optionally recursive)
chantal package upload --repo-id internal-debs --directory ./debs/ --recursive
# Replace an existing same name/version/arch package with different content
chantal package upload --repo-id internal-debs --file ./demo_1.0_amd64.deb --force
# Regenerate metadata so clients can install
chantal publish repo --repo-id internal-debs --target /srv/repos/internal-debs
Package metadata is parsed from the .deb control file in pure Python (the
ar container plus a control.tar.{gz,xz,zst}) - no dpkg-deb binary is
required. Uploads are content-addressed and deduplicated by SHA-256:
re-uploading identical bytes just links the existing pool entry, while a
different build of a name/version/architecture already present requires
--force. The package’s architecture must be one the repo’s
apt.architectures lists (or all) and its --component one the consumer
requests, so it lands in the matching binary-<arch> index.
Client configuration is the same as filtered mode: configure a gpg
section to publish a signed Release (hosted Release files are signed when GPG
is configured), otherwise clients must use [trusted=yes].
Upstream Signature Verification
Status: ✅ Available
Chantal always verifies integrity (SHA256 of Packages/.deb against the
Release checksums). A verify section additionally checks authenticity —
that the upstream Release was signed by a key you trust — analogous to apt’s
own Release signature check.
When enabled, the upstream InRelease (inline-clearsigned) is verified against
the configured trusted key(s), and the verified payload is what gets parsed
(so the checksum chain that gates every subsequent download is anchored to the
signature). If only the split Release + Release.gpg form is published, the
detached signature is verified instead. Since Release carries the checksums of
Packages, a valid signature there transitively authenticates the whole repo.
repositories:
- id: ubuntu-jammy
type: apt
feed: http://archive.ubuntu.com/ubuntu
apt:
distribution: jammy
components: [main]
architectures: [amd64]
verify:
enabled: true
key_files:
- /usr/share/keyrings/ubuntu-archive-keyring.gpg
# keys: ["-----BEGIN PGP PUBLIC KEY BLOCK----- ..."] # inline alternative
# trusted_fingerprints: ["<fpr>"] # optional pinning
on_missing_signature: fail # fail | warn | skip
on_invalid_signature: fail
The verify section can also be set globally (a fallback for all repositories
without their own). Notes specific to APT:
Verification is gated on
enabled(andrepo_gpgcheck, defaulttrue). The RPM-onlygpgcheckfield has no APT meaning and is ignored — APT package authenticity is transitive via the signedRelease→Packages→ SHA256 chain, so there is no per-.debsignature step. To turn verification off, setenabled: false(the simple off-switch); don’t togglerepo_gpgcheckon its own, as the shared validator couples it to the RPMgpgcheckfield.A failed check under
on_invalid_signature: fail(or a missing signature underon_missing_signature: fail) aborts the sync before any metadata is trusted or any package is downloaded.Freshness (
Valid-Until): when verification is enabled, an otherwise-valid Release whoseValid-Untilis in the past is rejected (applying theon_invalid_signaturepolicy) — a valid signature proves authenticity, not freshness, so this blocks a replayed/rolled-back Release.
Note: this verifies the upstream signature on sync. Re-signing the regenerated metadata for your clients (filtered mode) is the separate
gpgsection below.
GPG Signing (Filtered Mode)
Status: ✅ Available
In filtered mode the regenerated Release file no longer matches the upstream
GPG signatures. Configure a gpg section to have Chantal sign the metadata with
its own key, so clients can verify the repository without [trusted=yes].
When signing is enabled, publishing produces:
dists/<dist>/InRelease- the clearsigned (inline)Releasedists/<dist>/Release.gpg- the detached ASCII-armored signature<repo-root>/key.gpg- the exported public key for client distribution
Configuration
The gpg section can be set per repository or globally (as a fallback for all
repositories that don’t define their own).
repositories:
- id: ubuntu-jammy-filtered
name: Ubuntu 22.04 - Filtered
type: apt
feed: http://archive.ubuntu.com/ubuntu
mode: filtered
apt:
distribution: jammy
components: [main]
architectures: [amd64]
filters:
patterns:
include: ["^nginx.*"]
gpg:
# Use an existing key already present in the keyring / gnupg_home
key_id: "ABCD1234EF567890"
# Or import a private key from a file:
key_file: /etc/chantal/keys/signing.asc
# Passphrase handling (file preferred over inline value):
passphrase_file: /etc/chantal/keys/passphrase.txt
# Keyring location (a private temporary one is used if omitted):
gnupg_home: /etc/chantal/gnupg
Options:
Option |
Description |
|---|---|
|
Enable/disable signing (default: |
|
Key ID/fingerprint of an existing key to sign with |
|
Path to an ASCII-armored private key to import before signing |
|
Signing key passphrase (inline; prefer |
|
Path to a file containing the passphrase |
|
GnuPG home directory (keyring location) |
|
Path to a public key to publish (exported from the keyring if unset) |
|
Filename of the published public key (default: |
|
Generate a new signing keypair if no key is provided (default: |
|
Identity used when generating a key |
At least one of key_id, key_file, or generate_key must be set when signing
is enabled.
Global Fallback
# Global GPG config applies to every APT repository without its own gpg section
gpg:
key_id: "ABCD1234EF567890"
gnupg_home: /etc/chantal/gnupg
repositories:
- id: ubuntu-jammy-filtered
type: apt
feed: http://archive.ubuntu.com/ubuntu
mode: filtered
apt:
distribution: jammy
components: [main]
architectures: [amd64]
# inherits the global gpg config
Key Generation Workflow
You can generate a dedicated signing key with gpg and reference it by ID:
# Create a keyring location for Chantal
export GNUPGHOME=/etc/chantal/gnupg
mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
# Generate a signing key (RSA 3072)
gpg --batch --gen-key <<EOF
Key-Type: RSA
Key-Length: 3072
Name-Real: Chantal Repository Signing Key
Name-Email: repo@example.com
Expire-Date: 0
%no-protection
%commit
EOF
# Find the key ID / fingerprint
gpg --list-secret-keys --keyid-format LONG
Then reference it in the config:
gpg:
key_id: "<fingerprint-from-above>"
gnupg_home: /etc/chantal/gnupg
Alternatively, let Chantal generate the key automatically on first publish with
generate_key: true (the keypair is created in gnupg_home).
Client Configuration (Signed Repository)
# Download the published public key and install it as a keyring
sudo mkdir -p /etc/apt/keyrings
wget -O /etc/apt/keyrings/chantal.asc \
http://mirror.example.com/repos/ubuntu-jammy-filtered/key.gpg
# Reference the keyring in the sources entry (no [trusted=yes] needed)
echo "deb [signed-by=/etc/apt/keyrings/chantal.asc] \
http://mirror.example.com/repos/ubuntu-jammy-filtered jammy main" \
| sudo tee /etc/apt/sources.list.d/chantal.list
sudo apt-get update
The legacy apt-key workflow also works but is deprecated on modern systems:
wget -O - http://mirror.example.com/repos/ubuntu-jammy-filtered/key.gpg | sudo apt-key add -
Workflow Examples
Example 1: Mirror Ubuntu LTS
repositories:
- id: ubuntu-jammy
name: Ubuntu 22.04 Jammy LTS
type: apt
feed: http://archive.ubuntu.com/ubuntu
enabled: true
mode: mirror
apt:
distribution: jammy
components:
- main
- restricted
- universe
- multiverse
architectures:
- amd64
retention:
policy: mirror
Sync and publish:
# Initial sync
chantal repo sync --repo-id ubuntu-jammy
# Create monthly snapshot
chantal snapshot create --repo-id ubuntu-jammy --name $(date +%Y-%m)
# Publish latest state
chantal publish repo --repo-id ubuntu-jammy
# Publish snapshot
chantal publish snapshot --snapshot $(date +%Y-%m) --repo-id ubuntu-jammy
Example 2: Docker CE Mirror
repositories:
- id: docker-ce-ubuntu-jammy
name: Docker CE - Ubuntu Jammy
type: apt
feed: https://download.docker.com/linux/ubuntu
enabled: true
mode: mirror
apt:
distribution: jammy
components:
- stable
architectures:
- amd64
include_source_packages: false
retention:
policy: keep-last-n
keep_count: 10
Automated workflow:
# Sync latest Docker packages
chantal repo sync --repo-id docker-ce-ubuntu-jammy
# Create snapshot with current date
chantal snapshot create --repo-id docker-ce-ubuntu-jammy --name $(date +%Y-%m-%d)
# Check what changed (positional SNAPSHOT1 SNAPSHOT2)
chantal snapshot diff --repo-id docker-ce-ubuntu-jammy 2026-01-01 $(date +%Y-%m-%d)
# Publish latest
chantal publish repo --repo-id docker-ce-ubuntu-jammy
Note: For filtered Docker repositories (specific packages only), use filtered mode with pattern-based filtering (see FILTERED Mode section above).
Troubleshooting
InRelease file not found
Some repositories don’t provide InRelease files, only Release + Release.gpg:
WARNING: InRelease file not found, trying Release + Release.gpg
This is normal for older repositories. Chantal will automatically fall back to Release file.
Architecture not found
If you request an architecture that doesn’t exist:
ERROR: Architecture arm64 not found for jammy/main
Check the upstream repository’s Release file to see available architectures.
Component not available
If a component doesn’t exist:
ERROR: Component 'non-free-firmware' not found in jammy
Note: non-free-firmware was added in Debian 12. Debian 11 uses non-free only.
Source packages missing
If include_source_packages: true but no sources are found:
WARNING: No source packages found for jammy/main
Some repositories don’t provide source packages. This is expected for third-party repos.
Advanced Topics
Dependency Resolution
Chantal preserves full dependency metadata:
Depends - Required packages
Pre-Depends - Pre-installation requirements
Recommends - Recommended packages (installed by default)
Suggests - Suggested packages
Enhances - Packages enhanced by this package
Breaks - Packages broken by this package
Conflicts - Conflicting packages
Replaces - Packages replaced by this package
Provides - Virtual packages provided
Multi-Arch Support
Chantal supports Debian’s multi-arch feature:
Multi-Arch: same- Can be installed for multiple architectures simultaneouslyMulti-Arch: foreign- Satisfies dependencies from any architectureMulti-Arch: allowed- Can satisfy dependencies from other architectures
Package Priorities
Standard Debian priorities are preserved:
required- Essential for system bootimportant- Important system packagesstandard- Standard system packagesoptional- Optional packagesextra- Conflicts with other packages (deprecated, useoptional)
Sections
Common package sections:
admin- System administrationbase- Base systemcomm- Communication programsdevel- Development toolsdoc- Documentationeditors- Text editorsgraphics- Graphics softwarelibs- Librariesmail- Mail programsnet- Network programsutils- Utilitiesweb- Web software
Integration with Other Tools
apt-mirror Replacement
Chantal can replace apt-mirror with additional features:
Feature |
apt-mirror |
Chantal |
|---|---|---|
Mirror mode |
✅ |
✅ |
Filtered sync |
❌ |
✅ |
Snapshots |
❌ |
✅ |
Content deduplication |
❌ |
✅ |
Multiple formats |
❌ |
✅ (RPM, Helm, APK) |
Database tracking |
❌ |
✅ |
aptly Comparison
Feature |
aptly |
Chantal |
|---|---|---|
APT mirroring |
✅ |
✅ |
Package filtering |
✅ |
✅ |
Snapshots |
✅ |
✅ |
GPG signing |
✅ |
✅ |
Package uploads |
✅ |
✅ |
Multi-format |
❌ |
✅ |
Views (virtual repos) |
❌ |
✅ |
Performance
Sync Speed:
Depends on upstream repository size and network bandwidth
Typical: 100-500 MB/s for package downloads
Content-addressed storage eliminates duplicate downloads across repositories
Storage:
Deduplication via content-addressing
Hardlinks for published repositories (zero-copy)
Typical compression: Packages.gz is ~5% of uncompressed size
Example:
Ubuntu Jammy main (amd64): ~70,000 packages, ~80 GB
Docker CE stable (amd64): ~50 packages, ~500 MB
See Also
Configuration Overview - Global configuration
Repository Configuration - Repository settings
Filters - Filtering options
SSL & Authentication - Authentication
CLI Commands - Command reference
Workflows - Common workflows