Embedded gaming

On-Prem and Air-Gapped Software Delivery: A CTO’s Guide

Shipping Software Into Customer-Controlled Environments: On-Prem, Private Cloud and Air-Gapped Delivery

A practical guide for CTOs of enterprise software and device companies who are about to run their product somewhere they can't see.

By Subeesh Sivanandan, Founder & CEO, Stonetusker Systems · Updated November 2026 · Est. reading time: 13 minutes

Executive brief

  • Once a customer runs your software, you can't watch it, log in to it or push a fix in an hour, so everything you'd normally sort out after a release has to be sorted out before it leaves your building.
  • Ship one signed, versioned bundle that holds everything needed to install or upgrade, and test it by installing on a machine with all outbound traffic blocked. That single test surfaces most of the surprises.
  • An installer should run preflight checks before it changes anything, and upgrades should be enforced by tooling, tested from every supported version, and backed by a backup, because rollback usually means restore.
  • Licensing has to work offline and fail soft. Support has to work without a login, through a support bundle the customer can read before they send it.
  • You can't reproduce the customer's environment, but you can reproduce its hostility: no internet, TLS-intercepting proxies, private CAs, FIPS mode, old kernels. Turn every escalation into a permanent test.
  • Regulation is moving the same way. EU Cyber Resilience Act reporting duties already apply, and SBOM and technical documentation duties follow in December 2027.

What changes when the customer runs it

It usually starts with one line in a security questionnaire: can the product run in our environment, without access to the internet?

For a lot of software companies that's the first time anyone asks the question seriously. The product has been built, tested and released for years on the assumption that the vendor can see it, reach it and fix it. Then a hospital, a bank, a telecom or a government agency says they'll run it themselves, inside their own walls and on their own schedule, and the assumption quietly breaks.

Yes, you can do it. Just not by taking your SaaS release process and zipping it up.

Once the customer runs your software, the things that make modern delivery forgiving are gone. You can't watch it. You can't log in. A fix doesn't ship in an hour. What you get instead is a short list of things that must be right before release: a bundle that verifies itself, an installer that checks the environment before touching anything, upgrades tested from every version you still support, licensing that doesn't call home, and a way to get diagnostics out when something fails.

The sections below follow the order a customer meets these problems, not a project plan. The plan comes near the end.

Three models that get lumped together

People say "on-prem" when they mean three different things, and the differences decide almost every design choice that follows.

On-premisesPrivate cloudAir-gapped
Who runs itCustomer's ops team, in their data centerCustomer's team, in their own cloud account or private clusterCustomer's team, on an isolated network
Connection to youUsually outbound only, often through a proxyUsually outbound, sometimes tightly restrictedNone. Files move by approved media or a transfer gateway
How updates arriveDownload, or a bundle you sendRegistry pull, chart repository or bundleBundle delivered through the customer's transfer process
What you can seeWhatever they choose to shareWhatever they choose to shareNothing, unless they export it
What breaks firstProxies, certificates, firewall rulesCluster policies, storage classes, version skewAnything that quietly assumed internet access

Build the packaging for the strictest model you expect to meet and most of the packaging problems disappear for the other two. The environment problems don't. A private cloud customer will still hit cluster policies and storage classes that an air-gapped build never exercised, and a plain on-prem customer will still put you behind a proxy.

Start with the bundle, not the installer

The most important thing you'll ship is a single, versioned bundle that contains everything needed to install or upgrade, and nothing that has to be fetched later.

That means your own binaries, but also container images, charts or packages, OS-level and language dependencies, database migration scripts, default configuration and documentation. Pin container images by digest, not by tag. Include a manifest of everything inside, a checksum for every file, and an SBOM in a standard format such as SPDX or CycloneDX. The security team on the other side will ask for one.

Signing that works with no internet

Sign the bundle, and make sure the customer can verify the signature offline. Two details catch people out.

The public key has to reach the customer by a different route than the bundle, otherwise the signature proves nothing. And verification has to work on a machine with no network at all, which rules out anything that checks a transparency log or a revocation list online. Keyless signing flows that call a public log are out. Key-based signatures against a trust root the customer already holds work fine.

Kubernetes customers need a registry story

An air-gapped cluster can't pull from your registry, and it often can't pull from anyone's. So the bundle needs the images as archives, plus a loader that pushes them into the customer's private registry, plus charts where the registry host can be rewritten in one value. Skip this and the first thing a cluster operator does with your product is hand-edit image references across forty manifests.

The hidden outbound call

The most common failure at this stage is a call nobody knew was there. Something at install time pulls an image from a public registry, loads a font from a CDN, checks a certificate revocation list, resolves a telemetry endpoint, or asks a license server whether it may start. None of it shows up in your CI, because your CI has internet.

Operational test

Take a clean VM, block every outbound packet, copy the bundle over the way a customer would, and run the install. Does it finish without anyone editing a file or reading a log to find out what it was waiting for? If not, you have a hidden dependency, and your customer will find it first.

Make the installer check first

On the customer's side, your installer will be run by someone who has never met your engineers, in a maintenance window, often under a change ticket that allows four hours. A failure at hour three, halfway through, with a cryptic message, is how you lose a reference customer.

A good installer runs a preflight stage and refuses to continue if it can't be sure. Operating system and kernel version, CPU architecture, disk space and type, memory, required ports, DNS, time sync, trusted certificates, proxy settings, FIPS or SELinux mode, container runtime, storage classes. Each check should say what it found, what it expected, and what to do about it, in language the customer's operators can act on without calling you.

A few habits pay for themselves. Support a non-interactive mode driven by an answers file, because enterprises automate. Make the installer safe to re-run and resumable after a partial failure. Offer a dry run. Document exactly what it changes on the host. And ship an uninstall that works, since the customer's security team will want proof that they can remove the product cleanly before they agree to install it.

Operational test

Give the installer to an engineer who has never seen the product, on a host that's missing two prerequisites. Can they fix both from the preflight output alone, without a message to your team?

Upgrades are where customers judge you

Installing happens once. Upgrading happens for years, and that's where trust is built or lost.

Customers don't upgrade when you release. They upgrade when their change calendar, their validation process and their appetite for risk allow, which is often much later. At any moment you have customers spread across a range of versions, and each of them expects a path to the current one that works.

  • State which versions can upgrade directly to which, and enforce it in the upgrade tool instead of in a PDF.
  • Prefer expand-then-contract database migrations, so old and new versions can both run against the schema during the transition.
  • Assume rollback means restore. In a customer environment you usually can't cleanly undo a migration, so the upgrade should take a backup or insist on one, and the rollback procedure should be tested, not only written down.
  • Plan for partial upgrades. Agents, servers, user interfaces and firmware rarely update at the same moment. Decide how much version skew you support, and test exactly that much.
  • Write release notes for the customer's operator: what changes, what needs downtime, what to check afterward.

There's one upgrade path most teams forget to design: the urgent one. When a critical vulnerability is fixed, a connected customer gets the patch in days. An air-gapped customer gets it when your bundle clears their transfer process, which can take weeks. So decide ahead of time what a security patch bundle looks like, how small it can be, whether it can skip the full test cycle your feature releases go through, and how the customer finds out it exists at all.

Operational test

Pick the oldest version you still support, load it with realistic data, and upgrade to current while killing the process halfway through. What state does the system end up in, and can the operator get out of it without you?

Write the compatibility contract down

Support gets expensive when nobody can say what is and isn't supported. Publish a compatibility contract, and keep it short enough that people will read it.

  • Supported operating systems, kernels, Kubernetes versions, databases, and browser or client versions
  • Supported upgrade paths and the maximum version skew between components
  • How long each release is supported, and how much notice you give before dropping a platform
  • What "supported" means in practice: tested, or only expected to work

Then treat the contract as a test plan. Every line is a promise you have to be able to verify. If you can't test a combination, don't list it. A short, honest matrix beats a long, hopeful one.

Operational test

Choose any row in your compatibility matrix and ask who last tested it, and when. If the answer is "we think it works," take the row out.

Licensing without a phone home

A license check that needs a server on the internet is the quickest way to break an air-gapped deployment, and teams often find this out late.

Offline licensing generally means a signed license file that encodes the customer, the entitlements and an expiry, verified locally against a public key inside the product. For tighter control, add an offline activation exchange: the product produces a request file, you return a response file, and the customer carries both across the gap. Usage reporting works the same way, as an export the customer chooses to send you.

The design choices matter more than the mechanism.

  • Fail soft. When a license expires or can't be verified, warn and degrade long before you stop anything. A hospital or a factory floor should never lose a system at 3 a.m. because a date rolled over.
  • Expect wrong clocks. Isolated networks often have drifting or manually set clocks, and some are reset on purpose. Don't treat every time anomaly as tampering.
  • Be careful with hardware binding. It helps for devices. It hurts for virtual machines that get cloned, migrated and restored as routine.
  • Make renewal boring. Send it far enough ahead that the customer's own approval process can finish.

Don't design the license system for the customer you're afraid of. Design it for the honest one running a 24/7 operation, and deal with the rest commercially.

Operational test

Set the system clock a year forward, then back two years, on a running install. Does the product warn and keep working, or does it lock the customer out?

Support when you can't log in

In SaaS, debugging means looking at logs and metrics. Here you may get a screenshot and the words "it doesn't work." Build the support path into the product, on purpose.

  • A single command that creates a support bundle: versions, configuration with secrets removed, system information, recent logs and health checks. The customer should be able to read it before sending it, which also helps it get past their security team.
  • Logs that carry a version, a component name and a correlation ID, so one failing request can be followed across services.
  • A diagnostic mode that can be switched on temporarily and visibly switches itself off again.
  • Telemetry that is opt-in and documented line by line, and replaced by an exportable file wherever no connection is allowed.
  • Remote access the customer starts, that is time-limited and logged, and that goes through whatever they already approve: their jump host, their VPN, or a screen share where their admin does the typing.

Write the runbooks for the customer's operations team, not for your own engineers. They know their network and their tooling far better than you do. They don't know your architecture, and they shouldn't have to.

Operational test

Break something on a test install, then hand a colleague only the support bundle. Can they identify the failing component and the version it was running without asking a single question?

Testing an environment you can't see

This is the hard part, and it's mostly discipline rather than tooling. You can't reproduce the customer's environment, but you can reproduce its hostility. Build a lab, or a set of CI environments, that behaves like the worst networks and hosts you expect to meet.

Condition to reproduceWhat it tends to break
No outbound internet, or internet only through a proxyInstallers, license checks, anything fetched at runtime
A proxy that intercepts TLS and re-signs traffic with a private CAAlmost everything that makes an HTTPS call, because the JVM, Python, Node and Go each keep their own idea of which CAs to trust
Private CAs, short certificate lifetimes, drifting clocksService-to-service trust, license validity, token expiry
FIPS mode, SELinux or AppArmor enforcing, read-only filesystemsCrypto libraries, file writes, anything that assumed root
Older operating systems and kernels than you'd chooseSystem libraries, container runtimes, agents
Strict Kubernetes policies, odd storage classes, IPv4-only networks, restricted DNSCharts, persistent volumes, service discovery
Slow disks, small machines, data left behind by older versionsMigrations, startup timeouts, upgrade duration

Three rules for using the lab:

  1. Test the thing you ship. Run the install from the real, signed bundle, transferred and verified the way a customer would do it, not from a CI shortcut.
  2. Test upgrades from every supported version, with data that has lived through the previous versions, and interrupt some of them partway to see what state they leave behind.
  3. Turn every escalation into a test. Each time a customer environment surprises you, add that profile to the lab so it can't surprise you twice. After a few years the lab becomes a record of the real world.

For your first few customers, a design partner is worth more than any amount of lab work. Find a customer willing to run a release candidate in their own environment and give you honest feedback, and hand them a short acceptance checklist they can run themselves.

Operational test

List your last five customer escalations. For each one, is there now an automated test that would have caught it? Every "no" is a surprise you've agreed to have again.

If you also ship devices

Everything above applies, plus a few extras. Updates should be signed and verified on the device. Use A/B partitions or a similar mechanism that can return to the last good image if a boot fails. Define which firmware versions work with which companion software, because the two never update together. And plan for the update being applied in the field by someone who isn't an engineer, possibly under a regulatory change-control process.

For medical and other regulated devices, expect questions about SBOMs, patching and vulnerability handling, and have documented answers ready.

The regulatory angle

None of this is only good practice any more. Customer-run software is exactly where regulators have started to look, because a vendor that can't patch quickly or say what's inside its product is a risk to everyone downstream.

In the EU, the Cyber Resilience Act (Regulation (EU) 2024/2847) applies to products with digital elements, and where the software runs doesn't change that. Reporting duties for actively exploited vulnerabilities and severe incidents started on 11 September 2026, with an early warning due within 24 hours. The remaining requirements, including technical documentation and SBOMs, apply in full from 11 December 2027. The European Commission keeps an official Cyber Resilience Act page with the text and guidance.

Notice what that does to an air-gapped customer base. If you have to report within 24 hours, you also need a way to get a fix, or at least a mitigation notice, to customers you have no connection to. That's the urgent-patch path from the upgrades section, with a legal deadline attached.

Elsewhere, US federal buyers lean on NIST's Secure Software Development Framework (SP 800-218), and device makers face premarket expectations from the FDA, set out in its cybersecurity guidance for medical devices. For how we approach the supply chain side, see our related work on SBOMs and the Cyber Resilience Act.

A readiness checklist

Answer these honestly. Each "no" is a place a customer will find the problem before you do.

  1. Can you install from one signed bundle on a machine with no internet access?
  2. Do you know every outbound connection the product makes at install time and at runtime?
  3. Does the installer check the environment before it changes anything, with messages an operator can act on?
  4. Can a customer verify the bundle's signature and contents offline?
  5. Is there a published list of supported upgrade paths, enforced by the tooling?
  6. Have you tested an upgrade from every supported version, including an interrupted one?
  7. Do you have a defined path for getting an urgent security patch to a customer with no connection to you?
  8. Does the license work offline, and does it fail soft?
  9. Can the customer produce a support bundle with one command and review it before sending?
  10. Do you test behind a TLS-intercepting proxy and with a private CA?
  11. Does every customer escalation become a test case?

If you answered "no" to more than a few, that's common for teams whose product grew up as SaaS. It's also fixable, and the order matters more than the completeness.

Where to start

  1. Get an install working from one bundle with outbound traffic blocked. That alone surfaces most of the surprises, and everything else builds on it.
  2. Add the preflight checks and the support bundle. They lower the cost of every other problem you'll have.
  3. Build the upgrade test matrix and write the compatibility contract from what you can verify.
  4. Sort out licensing, signing and the urgent-patch path. These go quickly once the bundle exists.
  5. Keep going. The hostile-environment lab, the customer runbooks, a design partner.
  • Air-gapped delivery
  • Signed bundles
  • Offline verification
  • Preflight checks
  • Upgrade paths
  • Offline licensing
  • Support bundles
  • Hostile-environment testing
  • SBOM
  • Cyber Resilience Act

Frequently asked questions

What is air-gapped software delivery?

It's delivering and updating software on a network with no connection to the internet or to the vendor. Software, updates and licenses move in as files, carried on approved media or through a controlled transfer gateway, and anything that comes back out, such as logs or usage data, is exported by the customer.

How do you update software in an air-gapped environment?

With a signed update bundle that contains everything the update needs, delivered through the customer's own transfer process and verified offline. An upgrade tool then checks the current version and the environment before it changes anything. Take a backup first and test the rollback path, because undoing a migration in place is rarely possible.

How do you license software that can't phone home?

Use signed license files that the product verifies locally against a public key built into it. Add an offline activation exchange if you need tighter control, where the customer carries a request file out and a response file back. Make the product warn and degrade when a license expires instead of stopping.

What's the difference between on-premises and private cloud delivery?

On-premises means the customer runs your software on their own hardware in their own data center. Private cloud means they run it in their own cloud account or private cluster. The packaging work is similar, but the constraints differ: hardware and network policy in one case, cluster policy and managed services in the other.

How do you test software for an environment you can't see?

Recreate its constraints instead of its details: no internet, a TLS-intercepting proxy, private certificate authorities, FIPS mode, hardened hosts, older operating systems, and upgrades from every supported version. Then turn each customer escalation into a permanent test so the same surprise can't happen twice.

Does the EU Cyber Resilience Act affect on-prem software?

Yes, if you sell products with digital elements in the EU, and where the software runs doesn't change that. Vulnerability reporting duties began on 11 September 2026, and the full requirements, including technical documentation and SBOMs, apply from 11 December 2027. Customer-run deployments make it harder to patch and report quickly, so plan the update path now.

About to say yes to an on-prem or air-gapped customer?

If you're weighing whether your delivery side is ready, or you already ship into customer environments and keep getting surprised, we can give you a second opinion on where the gaps are. This is the work we do through our Secure Delivery and Embedded Systems DevOps engagements.

Talk to us about your delivery readiness

About the author

Subeesh Sivanandan is the Founder & CEO of Stonetusker Systems, with 27+ years across platform engineering, DevOps, CI/CD, release engineering and embedded Linux. Connect on LinkedIn.