Skip to content

Backups and restore

The instance’s Backups tab makes hosted or local backups directly on the website. It offers a local backup only where the instance’s host has room for one of its disk, and shows what a backup costs per GiB to create, to restore and for storage. A backup is accepted for at most the charge of a backup as large as the disk, and needs that much available plus $1.

Destination Where it is kept Restores to
local On a drive of the instance’s host Its original host only
hosted Independent off-host storage: the platform’s object storage nearest to the instance’s host by distance, currently in Frankfurt (Germany), Los Angeles (USA), or Singapore Any architecture-compatible offering

What a backup costs, and when it is charged, is under Backups on the pricing page.

  • A hosted backup stays where it is kept. Its restores and the instances created from it read it from there, and when that storage is unavailable the backup fails rather than going elsewhere.
  • The host encrypts it before it leaves. The website creates hosted backups itself, encrypted to the account’s current recovery public key.
  • It uploads at up to its host’s backup upload limit, which all hosted backups of the host share: 32 Mbit/s, about 4 MB/s, unless the provider set another.
  • The source hypervisor compresses and encrypts each local or hosted backup while streaming it from the instance, and stores all-zero regions of the disk without data.
  • Backups and restores are streams of bounded size rather than full temporary disk copies. Running instances use a point-in-time pull backup; stopped instances use a read-only disk export.
  • A backup keeps the firmware, BIOS or UEFI, that its instance booted with.

A running instance can always be backed up, and keeps running meanwhile.

  • Its host keeps 16 GiB for the blocks the instance overwrites during the backup.
  • An instance that overwrites more than that before the backup has read its disk is paused until it has, and resumed then: nothing it wrote is lost, but it does not answer meanwhile, for as long as the rest of the backup takes. The job’s result says whether that happened (upload_parts.guest_paused).
  • An instance that writes a lot is best backed up while it is stopped, or when it writes least.
  • A stopped instance’s backup needs no room for writes, so its hosted backup keeps nothing on the host. The instance cannot be started until its backup has finished.

A host makes two backups or restores at a time, of running instances or stopped ones. A further one is accepted and waits for its turn, and its job says so and how many are ahead of it, for example waiting for a backup slot on its host, which works on 2 backups or restores at a time; 1 ahead. On the website, its progress line says so.

  • The backups of running instances also take turns at the host’s two 16 GiB scratches, so a third such backup can wait for one.
  • A host whose local backups are kept on hard disks makes one local backup or restore of them at a time, since two at once would each run far slower than one after the other. One that waits says waiting for the host's backup disk, which works on one backup or restore at a time; 1 ahead. Hosted backups, and local backups kept on SSD or NVMe, are not held up by it.
  • An instance takes no other job while its backup waits or runs.
State Meaning
queued Waiting for its turn
staging The host has begun it
uploading A hosted backup uploads and finishes
available Done

A local backup reserves room for its artifact, about the root disk, in the host’s backup storage. Each offering’s backup_limits says which backups fit on every one of its hosts while nothing else holds that storage: local_running, local_stopped, and hosted_running. When the host cannot take a local backup, Gigahost does not accept it. The message names the sizes and what would fit, and says whether a hosted backup would fit:

Code Meaning What to do
local_backups_unavailable The host has no backup storage and keeps no local backup of any size You can use --destination hosted
backup_too_large_for_host No backup storage of the host could hold a local backup’s artifact even when empty You can use --destination hosted
backup_storage_busy Other local backups fill that storage When some are still running, retry once they finish. Stored local backups keep their room until they are deleted, so otherwise you can delete a local backup of yours on that host, or use --destination hosted

An instance’s backup schedule makes its backups on time and deletes the old ones it made. It has up to 4 rules, each a destination (local or hosted), a frequency (daily, weekly on a weekday, or monthly on a day from 1 to 28, which every month has), a time of day in UTC, and how many of that rule’s backups to keep. “Daily local, keep 3; weekly hosted, keep 2” is two rules.

The Backup schedule section of the instance’s Backups tab lists its rules in a table, each with its storage, next run and how its last run went, and has a row for each rule the schedule can have: a frequency (Off for no rule, which switches the row’s other fields off), where its backups are stored, the time in UTC, the weekday (for a weekly rule only) or day of the month (for a monthly rule only), and how many to keep. Choosing a frequency fills in the usual values: 03:00 UTC, Sunday, day 1, and a keep of 3 for daily, weekly and monthly rules alike. Save schedule replaces the schedule with the rows: a row of an existing rule changes that rule (its storage can change only while it has no backups beyond failed or deleted ones), an empty row set to a frequency adds a rule, and all of them Off clears the schedule. When a lower keep would delete backups, Save schedule asks first and says how many of each rule’s oldest go. After a save the rows are the saved rules, so you can change them again without reloading the page. A row offers Local only where the host has room for a local backup of the running instance. In the backup lists, a scheduled backup names its rule beside where it is kept, such as Local · Daily schedule.

  • When it runs. Each backup starts within the hour after its rule’s time, at an offset that is the same for every rule of the instance and differs between instances, so a host’s backups do not all start at once; the host then runs it as it runs any backup, after the backups ahead of it. A run missed while the host or the platform was down runs once when it can, never once per missed time: a backup still waiting for its host counts as the run of the times the host misses. Two rules due together run one after the other. The instance is backed up whether it runs or is stopped.
  • What it keeps. Each scheduled backup records its rule. Only once a new one has completed are that rule’s oldest backups beyond its keep deleted, with the usual deletion. A failed run deletes nothing, so a rule never falls below what it keeps through failures. Backups you make by hand are never deleted by the schedule.
  • Changing it. A rule you change keeps its backups: its frequency, time, day and keep can change, and its next run follows its new time. A lower keep deletes its oldest backups beyond the new keep within a minute or so, as a completed run would, and the website and ghost ask first, naming how many; the answer gives each rule’s completed backups (completed_count) beside its keep. Its destination can change only while the rule has no backups other than failed or deleted ones, since its backups are kept there; otherwise the change is refused, and to back up elsewhere you remove the rule and add another. Changing a rule is your consent again to its runs’ charges.
  • Removing a rule. A rule you remove (set to Off, or left out) keeps its backups, and the schedule never deletes them: the answer, the message after Save schedule and the section on the website say how many each removed rule left, which you can delete by hand when you no longer need them.
  • Charges. Setting a schedule is your consent to each run’s charge: every run is charged as a backup made by hand, at the prices in force when it runs, and a price change reaches the runs with the usual notice. A run your balance cannot pay is skipped, and you get a notification (once, until a run makes its backup again). A run that a limit or the instance’s state refuses is skipped too, and the schedule shows why. The monthly spending counts the schedule’s backups once they exist, at their storage price as any backup; the runs to come and their creation charges are not projected.
  • Keys. Hosted scheduled backups are encrypted to the account’s recovery public key, as the website’s are, so a schedule needs no account key to run; restoring a hosted one needs it, as ever.
  • Limits. The keeps, with one more for each rule, must fit the account’s backups-per-instance limit (Resource limits) together: a rule holds one more backup than it keeps from when its next run starts until its oldest beyond the keep is deleted, and a backup is accepted only while the instance holds fewer than the limit. A schedule that keeps more is refused and names the limit. A schedule’s runs and its deletions are not counted toward the daily job limit, so many scheduled instances leave your own jobs room; a run is still skipped while your own jobs have reached it.
  • Ends. Deleting the instance ends its schedule; its scheduled backups stay, as any backup of a deleted instance does.

Cancel beside the backup on the instance’s Backups tab and the Backups page, or Cancel backup on the backup’s own page, withdraws a backup that still waits for its turn.

  • A backup that still waits is cancelled at once and costs nothing, and the instance takes other jobs again. The backup then counts as deleted, and its job, which the command names, as cancelled.
  • A backup the host has begun gets backup_started. It runs to its end, and you can delete it then.
  • Only the platform’s operator can cancel a backup the host has begun: if one holds your instance too long, open a support ticket. Such a backup reads failed (on the website, it shows as failed), its job is cancelled with cancelled_by_operator, and nothing is charged for it.
ghost backup list
ghost backup list <INSTANCE_UUID>
ghost backup list --all
ghost backup list --state failed --state in_progress
ghost backup list --hosted --sort cost
ghost backup list web-1 --local --sort size --asc
ghost backup list --tag env:prod
ghost backup get <BACKUP_UUID>

The website’s Backups page lists your backups, the first column being the Instance, and each backup has its own page (/backups/BACKUP_ID).

  • backup list leaves deleted backups out unless --all is given (include_deleted=true in the API).
  • The list can be narrowed to one instance, to some states and to where the backups are kept, and sorted by age, size or what their storage costs a month:
    • --state keeps the backups in a state: queued, in_progress (being made, restored or deleted), available, failed, lost or deleted. It can be given more than once. A state given takes the place of --all, so --state deleted lists the deleted ones alone.
    • --hosted keeps the backups Gigahost hosts, --local those on their instance’s host.
    • --tag keeps the backups of the instances that carry a tag, deleted instances too; given more than once, those of instances that carry every one of them.
    • --sort orders them by age (the default), size or cost, the newest, largest or costliest first; --asc turns the order round. Backups of the same size or cost follow each other in the same direction by their creation time. Backups without a size yet, which are still being made or failed before they were, come last either way.
    • On the website, the Backups page has the same filters above the list, and its Created, Size and Storage headers sort it; the page’s address keeps the filters and the sort, so a link or the back button brings the same list back. Its instance filter offers every instance you have backups of, deleted instances too, and its tag filter your tags. The API takes them as instance_id, state (repeated), destination (hosted or local), tag (repeated), sort and order (asc or desc) on GET /v1/backups.
  • It prints one line per backup: its ID, its instance’s name, status, destination (hosted or local), image, size, what its storage costs a month (per_month; none for a deleted or lost backup, which costs nothing more), and creation time, and its purpose when it is not a regular backup. When one of them is a container instance’s backup, a KIND column tells the two apart, and its image is the container image it ran.
  • backup get, a deleted backup included, and --json show all of it: its disk size, the smallest root it restores to, the firmware and image its instance had when it was taken, the hostname the instance had then (hostname) and its name, hostname and state now, its prices, the fingerprint of the key a hosted backup is encrypted for, and for a local backup the host and location that store it. In JSON, storage_cost_microusd_per_month is what its storage costs a month: its size in whole MiB times its storage rate per GiB, over 1024, rounded up. A deleted or lost backup is no longer charged; the field keeps what keeping it cost, and --sort cost orders it by that.
  • In JSON a hosted backup’s destination reads gigahost_s3.
  • A backup knows its instance, so backup cancel, backup restore and backup delete take the backup’s UUID alone. For the latter two, the older form with the instance’s UUID first still works.

The Backups page highlights final recovery backups left after balance exhaustion; see If your balance runs low.

Restoring a local backup over its instance is direct. Restoring a hosted backup opens an approval page.

  • Only an available backup can be restored or give a new instance: ghost declines any other before it signs anything, with backup_not_available, and says to retry once a backup still being made, or restored, is done.
  • A restore also gives the instance the backup’s image in ghost instance get.
  • While a restore writes the instance’s disk, the instance reads provisioning, as during a reinstall.
  • A restore writes only the data the backup holds, so it takes about as long as that data, not as the disk is large.
  • Restores retain the backed-up users and SSH keys and install no fresh ones. A restore over the original instance keeps its hostname, network configuration, SSH host keys, and /etc/machine-id.

A backup restores over its original instance only while that instance boots with the same firmware, BIOS or UEFI, as when the backup was taken. After a reinstall with an image that boots with the other firmware, create a new instance from the backup instead.

A container instance’s backup restores over its instance only while the instance runs the image the backup was taken of, at the same version. After a redeploy onto another image or version, the backup’s disk holds the old image, which would start with the new image’s settings, so creating a new instance from the backup is the way to get it back. Backups taken since the redeploy restore over the instance as usual.

  • Restore replaces the current root volume only after the size checks pass. The new root disk needs to be at least as large as the source.
  • The restored disk keeps its partitions and filesystem at their backed-up size, and the platform does not change them.
  • Every catalog image runs cloud-init’s growpart and resizefs on every boot, so a system restored from one grows into a larger disk on its next boot while cloud-init is still installed and enabled.
  • On other systems, growing the partition and filesystem is up to you, for example with growpart /dev/vda 1 and then resize2fs or xfs_growfs.

Only your account key can decrypt a hosted backup. A hosted backup’s restore from the website, over its instance or into a new instance, opens an approval page (/approvals/REQUEST_ID). The website makes local and hosted backups, restores local ones and creates instances from them itself.

The approval page, ghost and the desktop app approve the same request in the same way, so whichever you use, and however often you start over, it is one restore and one charge.

The page shows three ways to approve side by side: in the browser with your account key, in Gigahost desktop, and with the ghost account approve command for the request. A new instance gets the label set on the rent form whichever way approves it. The browser way takes your account key: open Approve with your account key and choose your account.seed file or paste its line. Before anything is signed, the form states the most the restore can charge (You authorize a charge of at most …). Approve then:

  1. checks that the key is one of this account’s and the one the backup was made for;
  2. signs that charge with the account’s billing key and starts the restore, or the new instance;
  3. waits up to 5 minutes for the destination host’s restore key, unwraps the backup’s data key with your recovery key and wraps it again for that host, then authorizes the restore;
  4. forgets the key, whatever the outcome, and the page shows the restore’s progress.

Keep the page open until it says the restore goes on without it; the browser asks before you leave meanwhile. If it was interrupted, approving again on the page, or with ghost or the desktop app, carries on with the restore that started, without signing or charging it again.

A backup made before the account moved to a new account key needs the account key it was made with, which the page does not take: the page says so, and ghost can approve it with that key (see Restoring after an account key migration).

  • The restore-key authorization happens on your side, in the browser, the CLI or the app; it does not share your recovery private key. For a hosted restore, the client unwraps and rewraps only the small backup data key locally. The account key and private recovery key are never sent to Gigahost or to the hypervisor.
  • Unstarted approvals expire after 15 minutes.
  • When the approval is not accepted, the page says why and that nothing was charged. Approving again once the cause is gone still works until the request expires. The page keeps checking after a lost connection.
  • The page, backup restore and instance create --backup of a hosted backup wait at most 5 minutes (ghost’s --authorization-timeout-seconds, 300) for the destination host’s key offer and authorize no offer that comes later or has expired. The job they started goes on, and approving again resumes it; ghost’s --json error names it.
  • An instance created from a hosted backup waits up to 15 minutes for its restore to be authorized; see Delete for deleting it meanwhile.

A backup’s page (/backups/BACKUP_ID) offers Choose an offering, which opens Capacity with only the offerings that can take the backup (/?backup=BACKUP_ID). The rent form on an offering’s page lists only the backups it can take, each with its restore charge. Creating an instance from a local backup is direct; from a hosted one it opens an approval page.

You can create a new instance from a backup instead of installing an OS.

  • The selected root disk needs to be at least the backup’s disk size.
  • The size needs the memory the backup’s operating system needs (1 GiB for Ubuntu 26.04).
  • Hosted backups can restore onto any architecture-compatible offering. A local backup can only use capacity on the physical host that stores it.
  • --for-backup keeps the offerings that take the backup’s kind (a VM’s or a container instance’s backup), with a large enough root and, for a local backup, with that host among their host_ids; Gigahost still checks the architecture and the memory the backup’s operating system needs (1 GiB for Ubuntu 26.04) when you create.
  • --host <HOST_UUID> alone keeps the offerings that can place an instance on one host. Gigahost applies both, as its minimum_root_disk_bytes and host_id filters.
  • An offering whose hosts do not include a local backup’s host gets backup_host_mismatch, which names that host and its location.
  • While that host is full or takes no new instances, creation from the backup gets capacity_unavailable, or offering_unavailable if it was the offering’s only host.
  • It keeps the restored system’s users and SSH keys, so the SSH-key and startup-command options are unavailable with --backup.
  • Anything else the new instance needs can go in a --cloud-init-file, which runs once at its first boot.
  • Gigahost supplies the new network assignment and hostname and boots only after restore finishes.
  • It starts with the tags the backup’s instance carries when it is created, unless --tag names others or --no-tags asks for none; on the website, tags typed in the rent form take their place.
  • At its first boot the new instance also gets new SSH host keys and, on systems with systemd, a new /etc/machine-id.

A local backup is kept on a drive of its host.

  • When the host is missing the drive (the backup pool) that holds it, the backup shows as Unavailable (unavailable), with what the host found in an unavailable column (in JSON the backup’s unavailable object). It cannot be restored, nor an instance made from it: Gigahost answers backup_pool_unavailable. Keeping it costs nothing until the host has the drive back.
  • Once the drive is back, the host checks that the backup’s data is still there before it can be restored again and its storage is charged again.
  • A backup whose data is gone then shows as Lost (lost): it can never be restored, costs nothing more from when the drive went missing, and you are notified. ghost backup delete removes it from your list.
ghost backup delete <BACKUP_UUID> --yes --wait
  • Completed backups remain in their selected storage until you request deletion.
  • Deletion is a background job and keeps an audit tombstone after storage confirms removal.
  • A backup deletion runs beside the instance’s other jobs, and several deletions run at once.
  • Deleting an instance does not delete its backups; see Delete.
ghost \
--seed-file "$HOME/.config/ghost/account.next.seed" \
--recovery-seed-file "$HOME/.config/ghost/account.seed" \
backup restore <BACKUP_UUID> --yes --wait

After migrating an account to a new account key, you authenticate with the new account key and select the older account key only when restoring a backup encrypted to its recovery key. The active --seed-file still authorizes the new restore charge. Here the replacement is account.next.seed, and the older account key is still the default account.seed that ghost key generate created.

A hosted backup whose key does not match the account key is stopped before anything is sent, with recovery_key_mismatch and the fingerprint of the key the backup was encrypted for:

  • without --recovery-seed-file, the message says that a backup made before an account key migration needs the account key it was made with;
  • with it, that the given account key does not match.

ghost key inspect shows an account key’s recovery_key_fingerprint.