
Define, build, boot, and test a headless Debian or Ubuntu server with SSH, services, storage, networking, and repeatable acceptance checks.
August 20, 2026
A reliable headless image needs more than an unattended installer. The useful contract is: the machine boots without a GUI, accepts the right remote access, starts its workload, exposes only the intended network services, and passes the same checks after reboot.
Debian and Ubuntu already provide solid installer automation. The Debian installer supports preconfiguration files that answer installer questions, as documented in the official Debian preseeding appendix. Ubuntu Server 20.04 and later supports YAML-based autoinstall configuration, and current Ubuntu Desktop installers support it as well. Canonical's autoinstall introduction explains how configuration can answer installation questions without interaction.
Those mechanisms solve installation. An image workflow must also solve specification, repeatability, boot validation, and release evidence. That is the layer this guide focuses on.
Begin with observable requirements, not a package list. The following example is specific enough to test:
Base: Debian stable, amd64
Role: headless reverse-proxy node
Access: SSH key only for operator; root login disabled
Network: DHCP; expose TCP 22, 80, and 443 only
Services: nginx enabled at boot
Storage: persistent data mounted at /srv
Updates: unattended security updates
Acceptance: boot, SSH, HTTPS health check, clean rebootFor Ubuntu, the same contract may be expressed through autoinstall identity, SSH, storage, package, and late-command sections. For Debian, preseed covers localization, networking, account setup, partitioning, package selection, and boot-loader installation. In OpenFactory, the contract becomes the starting point for a recipe and its tests.
Avoid installing a desktop task or display manager unless the system actually needs one. Set the default systemd target to multi-user.target. Use a serial console for recovery where the target platform supports it. Treat SSH configuration as a security control: place an explicit public key, disable password authentication when practical, and decide whether any direct root access is allowed.
Headless does not mean unobservable. Include the logs, metrics, health endpoint, or management agent needed to diagnose a system after deployment. A minimal image that cannot explain a failed first boot is expensive to operate.
| Gate | Evidence to require |
|---|---|
| Boot target | systemctl is-system-running reaches an expected operational state |
| No desktop | No display manager is enabled and the default target is multi-user |
| Remote access | SSH accepts the intended key and rejects disallowed authentication |
| Service | The workload is enabled, active, and listening on the declared interface |
| Storage | Required filesystems mount by stable identity with expected permissions |
| Restart | The same checks pass after a clean reboot |
Test from outside the guest when possible. An internal curl localhost check proves less than a request from another machine through the intended network path. Likewise, checking that an SSH process exists is weaker than proving that the expected key can log in and an invalid method cannot.
Keep the recipe, installer input, package versions, build result, test output, and release identifier together. Record which base release was used and when the security package set was resolved. If a later image behaves differently, that lineage narrows the investigation.
OpenFactory turns this into a short feedback loop: describe the headless role, build it, boot the real VM, attach checks, and refine the same recipe. Start from the Linux builders funnel or browse existing systems before creating one from scratch.
A headless system is designed to operate without a local graphical desktop. It normally boots to a multi-user target and is administered through SSH, a serial console, an API, or a management agent.
Use the format supported by the installer and release you are targeting. Current Debian installer automation uses preconfiguration files, while Ubuntu's current automated installer uses YAML autoinstall configuration.
No. Installation success does not prove that SSH is reachable, the intended service listens, storage is mounted correctly, or the machine survives reboot. Add acceptance checks against the booted result.
Create a bootable Linux system and inspect the real VM.
Build a bootable ISO from requirements, a recipe, or a repository.
Compare Autoinstall, Preseed, Kickstart, cloud-init, and image builds.
Turn a Subiquity YAML file into a server with release checks.
OpenFactory's free flow is for browsing. Persistent VMs, SSH access, snapshots, your own ISO, and fleet deployment live on a paid plan.