Cloud-init and machine images
Two ways to skip the manual install: paste a cloud-init template when you create a VPS, or build a machine image that already has everything installed.
Cloud-init (one server at a time)
panel/deploy/cloud-init.yaml is a user-data template. Edit the few settings at the
top, paste it into your provider's "user data" box when creating the server, and the
panel is up when the server finishes booting. Progress and any failure land in
/var/log/nimbopanel-provision.log.
Do not treat user data as a secret store
This is the part worth reading twice. On every major provider, user data stays
retrievable from inside the running instance over HTTP at 169.254.169.254 —
and that address is reachable by any process on the machine, including a hosting
customer's PHP script.
So a licence key pasted into user data is readable by every customer you host, unless something stops it. The template stops it in two steps, in this order:
- it closes the metadata service to everyone except root, before the key reaches disk;
- after the installer has stored the key in root-only configuration, it shreds the on-disk copy of the user data.
If you would rather not put the key there at all, leave it blank and enter it from the panel afterwards. The server runs unlicensed until you do, which is a supported state.
Machine images (many servers from one build)
panel/deploy/packer/nimbopanel.pkr.hcl builds an image with the whole stack
installed. That is where the minutes go — packages, PHP, mail, DNS, the database —
and none of it differs between servers.
The mistake that makes every clone the same server
An image must contain no identity. If it does, every server built from it shares that identity:
| Baked in by mistake | What happens on every clone |
|---|---|
| SSH host keys | They all present the same key. Anyone positioned between a customer and their server can impersonate it, on all of them, with no warning shown |
| The Nimbopanel instance-id | The licence fingerprint derives from it, and the installer never re-seeds an id that already exists — so a thousand servers look like one activation |
/etc/machine-id |
systemd, DHCP leases and journald identity collide |
| The panel database and config | Admin password, licence key and every account ship inside a file strangers download |
| DKIM keys, TLS certificates | Issued for the build machine; meaningless on a clone, and leaked to everyone who has the image |
None of these announce themselves. They are found later, by somebody else.
panel/deploy/image-deidentify.sh removes all of it, and the Packer build runs it
as the last step and then re-runs it with --check, so a build fails rather
than producing a snapshot that only looks clean. Everything removed is recreated on
the clone's first boot: sshd generates new host keys, systemd writes a new
machine-id, the installer seeds a fresh instance-id.
/etc/machine-id is left empty, not deleted — systemd reads an empty file as
"generate one at boot", while a missing file stops some images booting at all.
Verify before you publish
sudo ./image-deidentify.sh # remove
sudo ./image-deidentify.sh --check # confirm, exits non-zero if anything survives
Run the check on a booted clone too, not just at build time. If it reports anything, do not publish the image.
Marketplace listings
Provider "1-click app" programmes (Vultr, DigitalOcean, Linode, Contabo) each have their own submission format and review. The image above is the artefact they ask for; the paperwork is per-provider and is not something this tooling can do for you.