Install cache and safe updates#
DUMB keeps reproducible downloads, package-manager data, and selected compiled
service artifacts under /config/.cache/dumb. The cache accelerates container
startup, updates, and exact-source reinstalls without treating a cached file as
trusted merely because it already exists.
Service configuration, databases, media, symlinks, credentials, and active runtime directories are not cache entries.
Destructive update clears are built from guarded exclusions rather than trusting
only the saved exclude_dirs list. DUMB automatically preserves an in-tree
service config file, explicit config/data/database paths, conventional persistent
data/database directories, root-level SQLite files and their active sidecars,
and symlinked data directories. The guarded paths are also excluded from archive
merges, while replaceable source and runtime output can still be refreshed.
Installing a configured release#
For services using the shared release installer, an explicit configured-target install applies the selected fixed release even when automatic updates are enabled or that release is already installed. Scheduled setup still respects release pins; saving a release selector alone does not request a reinstall.
Services with dedicated source installers retain their own installation behavior. Manual installs continue to use the existing snapshot and failure-recovery flow. A failed release download is reported as an installation failure, rather than a successful restart of the existing version.
Safety model#
An external project can always fail to download or build. DUMB's goal is to make that failure non-destructive:
- Resolve the requested release, branch head, or exact commit.
- Download into a content-addressed cache and verify its SHA-256 digest. For GitHub release assets, also require the published SHA-256 digest when available. Conditional requests and offline reuse still check that published digest before accepting cached content.
- Validate the complete archive before applying files. Unsafe paths, links, malformed archives, extraction errors, and configured size limits fail the installation.
- Build and verify the replacement runtime.
- Stop the old process only when the replacement is ready where the service layout supports candidate activation.
- Start the replacement and require it to remain healthy for the configured stabilization period.
- Restore the previous runtime automatically if activation or health stabilization fails.
Traefik Proxy Admin uses full same-filesystem candidate activation. Other source-built services retain a rollback snapshot of replaceable runtime files while their persistent paths stay in place. Services whose package manager or database owns the upgrade transaction keep their existing service-specific recovery behavior.
Application database migrations
A runtime rollback cannot safely undo every application-owned database migration. DUMB never replaces persistent data with a cached copy. If an upstream migration is not backward compatible, leave the restored service stopped and follow that application's documented database recovery path.
If an archive install fails and restoring a previous file also fails, DUMB keeps the recovery backup and reports its location. Preserve that backup until the service's files have been recovered. Further archive installs and automatic directory clears stop while a recovery workspace remains, so a retry cannot erase that evidence. A failure to remove backups after a successful install is reported separately and does not undo the new runtime.
Download verification#
DUMB uses different checks for different download sources:
| Download | Verification |
|---|---|
| Managed Bun runtime | Verify the publisher-signed checksum manifest against a bundled, pinned Bun key, then check the selected ZIP's SHA-256 before extraction or execution. |
| Local .NET SDK bootstrap | Verify Microsoft's installer-script signature against its bundled, pinned key before running the script to resolve an SDK version. Check the SDK archive's SHA-512 against official Microsoft HTTPS release metadata before extraction or execution. |
| Shared GitHub release assets | Check the selected asset's published SHA-256 digest when the release API supplies it, including cached and offline reuse. |
| Ubuntu packages, including Tini | Use APT's authenticated repository metadata and package checksums. |
A required Bun or Microsoft signature that is missing, invalid, or signed by an unrecognized key stops provisioning. Checksum mismatches also stop provisioning. The existing Bun binary or local .NET SDK stays in place until a verified candidate passes its version check. DUMB does not retry these failures with an unsigned installer or trust a replacement key automatically.
Some GitHub release assets have no published digest. Those remain installable with HTTPS and DUMB's cache integrity checks; the log explicitly reports the missing published checksum. A present but malformed or unsupported digest refuses the download. A cache's own checksum detects changed cached bytes, but does not establish who originally published them.
Published SDK and GitHub checksums provide integrity checks, rather than a separate publisher signature. OCI digests and package-manager lockfile hashes also do not imply universal publisher-signature or provenance verification. Bundled signing keys need maintenance when their publishers announce rotations or revocations; verification does not fetch new trust roots at runtime.
Configuration#
{
"dumb": {
"install_cache": {
"enabled": true,
"path": "/config/.cache/dumb",
"max_size_gib": 25,
"artifact_retention_count": 2,
"clean_retry": true,
"max_download_size_mb": 4096,
"max_archive_entries": 250000,
"max_unpacked_size_gib": 50,
"activation_health_timeout_seconds": 120,
"activation_stabilization_seconds": 15
}
}
}
Keep the cache on persistent local storage when possible. It may reside on a
different filesystem from service runtimes. The shared archive installer
stages extracted files and rollback backups on the service's filesystem,
including directly mounted service directories, so file activation uses atomic
same-filesystem renames. Allow enough free space there for the candidate and
temporary backups. DUMB refuses broad system/data roots such as
/, /config, /data, and /mnt as the cache root and falls back to the
default cache directory.
The cache is owned by the DUMB controller rather than managed service users.
If the cache root or one of its managed namespaces is recursively chowned,
DUMB validates the tree and restores controller ownership before the next
cache operation. The repair removes group/other write permission while
preserving executable bits required by cached runtimes. It does not follow
symlinks or cross a nested mount inside the cache tree.
If the configured cache is a symlink, has an unsupported file type, contains
an unexpected nested mount during ownership repair, or cannot be repaired due
to filesystem permissions, DUMB leaves active runtimes untouched and uses a
new controller-only cache under /tmp for the current process. The dashboard
shows this fallback and its reason. Correct the configured path or ownership
and restart DUMB to resume the persistent cache; the temporary fallback is not
reused after restart.
Package-manager behavior#
- pnpm uses a shared content-addressed store grouped by pnpm major, verifies store integrity, and attempts a frozen lockfile install first. A lockfile compatibility retry is allowed only after pnpm specifically reports a lockfile mismatch; it remains inside the rollback-protected install phase.
- Python services receive a clean virtual environment. pip and Poetry share
download caches by Python ABI and architecture, and DUMB runs
pip checkbefore accepting the environment. - NuGet packages are shared by architecture. Projects with
packages.lock.jsonrestore in locked mode; publish remains--no-restore. - Go module and build caches are persistent and architecture-scoped.
- Bun, Yarn, and Deno retain persistent shared caches and use immutable/frozen lock behavior when their project supplies a lockfile.
- mediastorm OCI data remains digest-addressed and verified.
Dashboard maintenance#
Newer backends advertise install_cache_management. The dashboard Updates
panel then shows three distinct totals:
- Managed cache is the current
/config/.cache/dumbtree and is the value governed bymax_size_gib. - Legacy release caches are exact DUMB-owned package-manager locations discovered from older releases.
- Combined install cache is the complete managed plus legacy disk usage.
The panel also shows current namespace sizes and actions to:
- save a managed-cache limit from 1 through 1024 GiB when the backend advertises
install_cache_limit_settings; - verify downloaded objects and quarantine corrupt entries;
- prune least-recently-used entries down to the configured limit; and
- clear compiled artifacts so the next reinstall performs a clean build.
Backends that additionally advertise install_cache_cleanup expose a
user-directed cleanup selector. It can remove only legacy caches, quarantine,
compiled artifacts, verified downloads, dependency caches, or all rebuildable
cache. Every scope requires confirmation. DUMB accepts named scopes rather
than filesystem paths, re-discovers legacy entries immediately before
deletion, and refuses symlinked, mounted, or moved paths. Maintenance returns
HTTP 409 until startup completes and while DUMB's service-update lock is active.
Saving the limit persists dumb.install_cache.max_size_gib. It does not delete
anything immediately. Select Prune to limit when you want DUMB to reclaim
least-recently-used rebuildable cache entries down to the new target. This split
prevents an accidental number change from immediately removing a warm cache.
Legacy discovery covers the old per-project pnpm/Bun buckets, Maintainerr Yarn
cache, Profilarr Deno cache, and DUMB-created per-service pip, Poetry, and NuGet
package caches. It does not classify generic application cache directories as
install cache, and it preserves the current Traefik Proxy Admin runtime data
that still intentionally lives below /config/.pnpm-store.
The frontend hides the entire section for APIs without
install_cache_management and independently hides scoped cleanup unless
install_cache_cleanup=true. The editable limit is independently gated by
install_cache_limit_settings=true, so a newer frontend does not submit the
new nested config field to an older backend schema.
Pruning and clearing artifacts never stop services or remove active runtimes.
Cleaning downloads or dependency caches makes later installs slower until the
cache warms again. DUMB serializes these actions against managed updates, but
operators should still avoid cleanup while another install path is actively
building.
Do not manually delete transaction journals or dumb-previous directories
while an update is active.
Recovery guidance#
If an update reports that the previous runtime was restored:
- Confirm that the service is running and inspect its service log.
- Open Updates → Install cache and run Verify downloads.
- Use Clear build artifacts if the failure points to missing or invalid compiled output.
- Retry the update. DUMB will reuse valid dependency downloads but rebuild the service runtime.
- If rollback itself failed, do not repeatedly update. Preserve the service directory and logs, then restore the application's data from its normal backup process.