Security
Nano Cloud runs as root, because it manages VMs, disks and host networking. Whoever controls it controls the machine, and everything below follows from that.
Report a vulnerability
Report it privately through GitHub's vulnerability reporting, not in a public issue. Include the version (nanocloud version), your platform and the steps to reproduce. I'll answer within a week; the fix ships as a release, and the advisory is published once it's out.
What the login protects
- Every API route and console needs a login, apart from
/health, the login itself and the page's own files. With no password set, the daemon refuses everything. - The password is stored as a bcrypt hash; sessions and API tokens only as SHA-256 hashes of 32 random bytes.
- Browser sessions use an
HttpOnly,Secure,SameSite=Strictcookie that expires after 30 days unused. - Requests that change anything, and every console connection, are refused if they come from another site.
- Password guessing is slowed per address: after a few failures, each one doubles the wait, up to 15 minutes.
- Traffic is HTTPS, with a certificate made on first start or one you configure (
certandkeyundertls:in the configuration). - Updates are checked against a GPG key built into the binary and the installer, then by checksum, before anything is replaced.
Files on the machine
- VM disks and cloud-init seeds are created readable by root only (mode 0600). That matters most for a service, whose seed holds its passwords in plain text. The VM specs that repeat a seed's files and commands are 0600 too.
- The directories Nano Cloud creates for them are 0711: QEMU runs as its own user and opens a disk by its path, so other accounts can pass through but can't list or read anything.
- On Linux, libvirt hands a VM's disks and seed to QEMU's user while it runs, and gives the disks back to root when it stops; a seed stays with QEMU's user, still 0600. That's libvirt's
dynamic_ownership, on by default. If/etc/libvirt/qemu.confturns it off, VMs can't start, andnanocloud doctorsays so. - VMs made by an older release are tightened the next time the daemon starts, unless
dynamic_ownershipis off, so that they keep starting. - Downloaded cloud images stay readable by everyone: they're the distributions' public images.
What it does not protect
- Anyone with root owns the machine. Use a host where every login belongs to someone you'd trust with root. VM disks are not encrypted, so a backup of them or a stolen drive can be read.
- A storage pool in a directory you made yourself keeps that directory's mode. Its disks are 0600 all the same, but if anyone can list the directory, anyone can see your VMs' names.
- VMs on the NAT network can reach each other, and a bridged VM is on your network like any other machine.
- The VMs themselves. Their passwords, keys, open ports and updates are yours to manage.
- With
enabled: falseundertls:(for a reverse proxy), the password crosses the network in the clear unless something in front adds TLS. - The internet. The daemon listens on every interface, so keep port 8080 to your network or a VPN.
There's one login and any number of API tokens. A token can do everything except change the password or create and revoke tokens, which need a signed-in browser. There are no users or roles, so don't give a login or a token to anyone you wouldn't give root.
Release signing key
Every release is signed with this key, and the installer and nanocloud update both check against it:
nano-cloud releases <releases@nanocloud.io>
ed25519, fingerprint 5289 9456 DD0B C728 383E 1910 39DE 3648 2CBD 9253
expires 2028-07-03
What it sends, and to whom
At most every 12 hours the daemon asks GitHub for the latest release; you can turn that off in Settings → Updates. Anything else it fetches, you asked for: cloud images from each distribution's servers, and SSH keys from GitHub when you name a GitHub user. There is no telemetry.
This site has no analytics, cookies or third-party scripts, and serves its own fonts.