Thoughts on ideal file size and packaging strategy
When I first built the static binary build tools, the goal was to produce a fully self-contained OpenEMR executable — something you could download and run without installing PHP, extensions, or other runtime dependencies.
Today, we achieve that, but we actually ship three artifacts totaling ~710MB:
- OpenEMR PHAR (~280MB)
Contains all static assets (images, CSS, JS, etc.). At runtime we extract this so the webserver can serve static content. - Static PHP CLI (~80MB)
Used only to extract the PHAR above. - OpenEMR runtime binary (~350MB)
A PHP interpreter (version configurable) with all needed extensions compiled in, plus a second PHAR of OpenEMR executed directly from memory — no PHP install required.
Why I believe this three-file model is the right default
We could push this further and bundle everything into a single monolithic binary by embedding the PHAR and adding a tiny extraction utility (e.g., dd) so it self-unpacks before booting. That hypothetical binary would likely be ~450MB uncompressed, and ~135–225MB with UPX compression, given typical 50–70% UPX reductions.
However, I intentionally didn’t include this in the toolchain because:
- UPX compression tends to increase memory usage and introduce measurable performance hit — the effect on OpenEMR would be interesting to benchmark, but probably not worth it for clinical workloads.
- Saving ~0.5GB of disk space rarely matters in modern deployments — reliability, predictability, and maintainability matter far more.
- A single-binary self-extracting process (reading its embedded PHAR, streaming it through a PHP runtime, unpacking it into place, etc.) increases complexity and brittleness — which is undesirable for medical systems where breakage isn’t an option.
So I think our current “three-part runtime” is actually beneficial: simpler, clearer, debuggable, and easier to evolve.
Easy disk optimizations available today
We can document optional disk-reduction behaviors without touching packaging:
- Delete the static PHP CLI (~80MB) after boot.
It’s only required for PHAR extraction — keeping it is useful only if you want future re-extraction capability. - Delete the OpenEMR PHAR (~280MB) after extraction.
Once static assets are unpacked, OpenEMR runs fine without the PHAR. Keeping it provides configuration provenance and makes re-extraction possible if corruption occurs.
Users who don’t care about rollback capability could reclaim ~360MB immediately.
I’m on the fence about prominently documenting this because losing the PHAR eliminates the ability to recover if static assets become corrupted and the internet is unavailable. Trade-off worth noting, but maybe best left as an advanced-ops footnote.
Platform support notes
This entire system is powered by Static PHP CLI, which also supports FreeBSD and Windows compilation targets. If there’s interest, we should be able to produce native builds for those platforms as well.