Patching
Omniglass compiles Zabbix from source using the zabbix-docker build system, injecting source patches at build time. If a patch fails to apply, the build fails. If Zabbix ships the feature upstream, the patch is removed.
Repositories
Section titled “Repositories”| Repo | Purpose |
|---|---|
| zabbix/zabbix | Upstream source (read-only) |
| hyperscaleav/zabbix | Fork for patch development |
| zabbix/zabbix-docker | Build system (cloned at build time, not forked) |
| hyperscaleav/omniglass | Product repo; carries .patch files as build artifacts |
How it works
Section titled “How it works”The build-zabbix.sh script:
- Clones
zabbix-dockerat the tag matchingZABBIX_VERSION - Copies
patches/*.patchinto the build-pgsql patches directory - Runs
docker buildx bakewhich clones Zabbix source, applies patches withpatch -p1, and compiles everything
One build produces all patched component images: server, web, proxy. Schema changes in schema.tmpl are compiled into create.sql.gz and schema.inc.php automatically.
Omniglass Dockerfiles then layer branding, modules, and configuration on top of the patched base images.
Directory structure
Section titled “Directory structure”patches/ # Zabbix source modifications 0000-security-deps.patch # Composer/dependency CVE fixes 0001-sla-severity.patch # Feature patches (future)
components/core/db/migrations/ # Omniglass-owned schema (dbmate) 20260211052804_create_omniglass_schema.sql # Sequential, tracked, run once ...Ownership boundary:
patches/*.patch= modifications to Zabbix (applied at build time, removed when upstream ships the feature)components/core/db/migrations/= tables Omniglass owns (applied at runtime by dbmate)
Developing a new patch
Section titled “Developing a new patch”1. Branch from the Zabbix version tag
Section titled “1. Branch from the Zabbix version tag”cd /path/to/zabbix-forkgit fetch origin --tagsgit checkout 7.4.8git checkout -b omniglass/my-feature2. Make changes and generate the patch
Section titled “2. Make changes and generate the patch”git diff 7.4.8 > /path/to/omniglass/patches/NNNN-my-feature.patch3. Build and test
Section titled “3. Build and test”Patches are applied in alphabetical order by numeric prefix (0000-, 0001-, etc.).
rm -rf /tmp/zabbix-docker-* # clear cache if patches changedmake build # full build: zabbix base + omniglass layersmake test-e2e4. Push the branch and tag
Section titled “4. Push the branch and tag”cd /path/to/zabbix-forkgit push omniglass omniglass/my-featuregit tag omniglass/7.4.8/my-featuregit push omniglass omniglass/7.4.8/my-featureUpgrading Zabbix version
Section titled “Upgrading Zabbix version”git fetch origin --tagsin the Zabbix fork- Rebase each
omniglass/*branch onto the new tag - Regenerate patches with
git diff <new-tag> make set-zabbix-version VERSION=<new-version>rm -rf /tmp/zabbix-docker-*(clear build cache)make build && make test-e2e
Naming conventions
Section titled “Naming conventions”og_prefix for all columns added to Zabbix tables (avoids namespace collisions)0000-security-deps.patchfor dependency CVE fixes (always first alphabetically)NNNN-feature-name.patchfor feature patches (numeric prefix controls apply order)- Patch branches in the fork:
omniglass/<feature> - Tags after generating patches:
omniglass/<version>/<feature>
Hardened base images
Section titled “Hardened base images”All Alpine-based images build on Docker Hardened Images (DHI). DHI images ship with near-zero CVEs, continuous patching, and SLSA Build Level 3 provenance. The free tier is Apache 2.0 licensed with no usage restrictions.
Base image chain
Section titled “Base image chain”dhi.io/alpine-base:3.23-dev # DHI hardened Alpine (FROM in zabbix-base-alpine Dockerfile) -> omniglass-zabbix-base-alpine:latest # Compatibility shim (restores missing system groups) -> zabbix-build-base # Toolchain (compilers, headers, Go) -> zabbix-build-pgsql # Patched Zabbix source compilation -> zabbix-build-sqlite3 # Patched Zabbix source compilation (proxy) -> zabbix-server-pgsql # Server runtime -> zabbix-web-nginx-pgsql # Web frontend runtime -> zabbix-proxy-sqlite3 # Proxy runtimeThe omniglass-zabbix-base-alpine shim exists because DHI strips system groups and users that stock Alpine includes (e.g. dialout). Upstream zabbix-docker Dockerfiles expect these to exist. The shim restores only what is actually needed, keeping the zabbix-docker clone unmodified.
How it works
Section titled “How it works”build-zabbix.shbuildsscripts/zabbix-base-alpine.Dockerfile, which layers compatibility fixes on top of the DHI image and tags it asomniglass-zabbix-base-alpine:latest- The tag is passed as
OS_BASE_IMAGEto all threedocker buildx bakephases - zabbix-docker Dockerfiles consume it as their
FROMwithout modification
Keeping zabbix-docker clean
Section titled “Keeping zabbix-docker clean”The patching strategy is designed so that the zabbix-docker clone requires zero modifications beyond injecting .patch files into the patches directory:
- Base image override: Handled via
--set "*.args.OS_BASE_IMAGE"at bake time, not by editing Dockerfiles - Missing system groups: Handled by the
zabbix-base-alpineshim layer, not by sed-patching Dockerfiles - Source patches: Copied into the existing patches directory that zabbix-docker already reads from
This means rm -rf /tmp/zabbix-docker-* and a fresh clone always produces a working build.
Updating the DHI version
Section titled “Updating the DHI version”- Update the
FROMline inscripts/zabbix-base-alpine.Dockerfile - Update DHI image tags in
components/core/Dockerfile,components/gateway/Dockerfile, andcomponents/zabbix-proxy-sqlite3/Dockerfile rm -rf /tmp/zabbix-docker-*(clear build cache)make build && make test-e2e- If the build fails on a missing group or user, add it to
zabbix-base-alpine/Dockerfile
Non-Zabbix images
Section titled “Non-Zabbix images”Other Omniglass components use DHI images directly in their own Dockerfiles:
| Component | Base image |
|---|---|
| core | dhi.io/golang (build) + dhi.io/alpine-base (runtime) |
| gateway | dhi.io/nginx |
| zabbix-proxy-sqlite3 | dhi.io/golang (Go builder stage only) |
| nodered | nodered/node-red (vendor image, not swappable) |
These do not go through the zabbix-base-alpine shim since they don’t consume zabbix-docker Dockerfiles.
- Patches are generated artifacts. Never hand-edit a
.patchfile. - Patches are applied alphabetically by filename. Use numeric prefixes to control order.
- Schema changes to Zabbix tables go through source patches on
schema.tmpl, not runtime migrations. - Omniglass-owned tables go through dbmate migrations, not source patches.
- Every patch branch in the fork must be tagged with the Zabbix version it was generated against.