Offline Repackaging Utility
Relevant source files
The following files were used as context for generating this wiki page:
The Offline Repackaging Utility provides a mechanism to rebuild OPSI packages using existing, verified installers without contacting upstream vendor sources. You use this utility when packaging logic or OPSI scripts change but the software version remains the same. It ensures deployment consistency by reusing previously validated binary payloads while incrementing the OPSI package revision.
Sources: README.md:280-284, builder/builder/repackage.py:1-5
Core Functionality
The utility executes as a separate recovery command that bypasses upstream metadata discovery. It performs rigorous verification of existing artifacts before allowing a repackage operation.
Operational Constraints
- Revision Requirement: You must increase the
package_revisionin the catalog before running the utility. The utility rejects operations where the catalog revision is less than or equal to the recorded revision in the existing package provenance. - Verification: The utility validates the SHA256 hash of the existing
.opsiarchive against its recorded provenance. It also verifies the extracted installer hash against the original download record. - Locking: The process acquires a file lock (
builder.lock) to prevent concurrent modifications by the periodic builder.
Sources: builder/builder/repackage.py:23-45, README.md:285-290
Repackaging Workflow Logic
The following diagram illustrates the sequence of operations performed during an offline repackage:
The utility ensures that the upstream_version and original source_url are preserved in the new package's provenance metadata.
Sources: builder/builder/repackage.py:31-78, builder/builder/opsi.py:84-118
Technical Components
Verification and Security
The utility uses the verify_archive and protect_checksum functions to ensure data integrity.
| Function | Purpose | Logic |
|---|---|---|
verify_archive | Validates OPSI file | Compares file SHA256 against package_sha256 in .provenance.json. |
protect_checksum | Guards installer | Rejects the operation if the extracted installer hash differs from the original record. |
inventory | Locates artifacts | Scans the repository for .opsi files matching the product ID. |
Sources: builder/builder/repackage.py:23-26, builder/builder/download.py:112-117, builder/builder/repository.py:12-21
Implementation Detail: Source Generation
When repackaging, the utility calls builder.opsi.generate. This function renders OPSI scripts and control files using Jinja2 templates. If overrides exist in catalog/overrides/<product_id>/, they replace the default templates.
source = generate(
p,
release,
proof["opsi_version"],
tmp / product,
Path(__file__).resolve().parents[1] / "templates",
catalog.parent / "overrides",
installer,
)
Sources: builder/builder/repackage.py:61-69, builder/builder/opsi.py:27-46
Execution
You trigger the utility using the Python module interface. The project recommends stopping the periodic repo-builder service before manual execution to avoid lock contention.
Command Syntax
docker compose run --rm --entrypoint python repo-builder -m builder.repackage <opsi_product_id>
Sources: README.md:285-290, builder/builder/repackage.py:87-97
Summary of Differences: Periodic vs. Offline
| Feature | Periodic Builder | Offline Repackaging |
|---|---|---|
| Upstream Check | Required (GitHub API, etc.) | Skipped |
| Installer Source | Download from Vendor | Extracted from existing OPSI |
| Revision Control | Automatic or Catalog-based | Requires Catalog increment |
| Integrity Check | New Hash vs. Known Version | Extracted Hash vs. Original Hash |
Sources: builder/builder/repackage.py:1-10, builder/builder/main.py:65-110
Conclusion
The Offline Repackaging Utility is a critical tool for repository maintenance. It allows administrators to update deployment logic (such as PowerShell helper scripts or OPSI setup instructions) while maintaining absolute binary parity with previously validated vendor installers. By enforcing hash verification and revision increments, it prevents accidental downgrades and ensures the repository state remains consistent.
Sources: README.md:280-295, builder/builder/repackage.py:1-8