Import a config archive
POST/config/import
Required role: admin. Only an account or token with the admin role can call this operation.
curl --request POST \
--header "Authorization: Bearer $HOSERVA_TOKEN" \
--header "Content-Type: application/json" \
--data @body.json \
"https://$HOSERVA_HOST:8008/api/v1/config/import"
Restores from a configuration archive. Requires confirm: true — this replaces the running configuration: the database, the custom config files (*.custom.conf), the installed app templates and each stack's compose and meta.json files, after which every managed config file is regenerated from the restored database and the result applied to the running pool. It also restores the passphrase-protected part of the archive, its stacks' .env files: with the optional passphrase if one is given, otherwise with the configured backup passphrase. Without a passphrase that opens it, everything else is restored and the report says the .env files were not. When the import restores .env files, the pre-import archive's own secrets.age is sealed with the passphrase that opened the imported archive's, so it holds every .env the import replaces; a failure to write it refuses the import. The answer is the restore report: what was restored per category, what was not and why, the name of the pre-import archive and which passphrase seals its secrets. Every refusal happens before anything is written, including the pre-import backup: 400 invalid_archive (it does not unpack or checksum, holds a file its manifest does not list or lacks one it lists, holds a link, device, FIFO or duplicate entry, or has a secrets.age or identity.age that is not readable, which shows once a passphrase is tried against it), 400 backup_passphrase_incorrect (a passphrase was given and it does not open the archive's secrets.age or, for an archive with an identity.age and no secrets.age, its identity.age; one that opens secrets.age but not identity.age is not refused), 400 incompatible_archive (another schema version), 409 job_in_progress, 409 archive_other_installation (its machine key check value differs from this installation's or is missing; a different installation's archive is restored only onto a fresh install) and 409 archive_array_mismatch (its disks, their removal state or the relocation in flight differ from the live array; the message names each difference), and 409 restore_path_unsafe (a file it would restore lands on a symbolic link or on something that is not a regular file, or it names a path outside the directory it is restored into; nothing is followed). A bare-metal restore that would replace a Samba or NFS file already on this server also refuses with 409 host_files_not_saved when no backup destination is enabled to take the copy of it that the pre-import archive carries. A failure to stage the files answers 500 import_failed with nothing changed; a failure once the database has been replaced answers 500 import_failed naming the pre-import archive to restore from and which of the file categories were restored and which left as they were. The array's own state, running, in maintenance mode or stopped, is kept as it is, never restored from the archive, so an import cannot return a stopped array to normal operation.
On a fresh install, one with no array configured, whatever admin accounts it has, the import is the bare-metal restore of another installation's archive. It takes the archive's array disks from the archived database and matches each against the attached disks by identity; the mapping is what previewConfigImport shows, and the import refuses with 409 disk_mapping_required without diskMapping, the mapping the user confirmed, and with 409 disk_mapping_stale when it no longer matches the attached disks. An archive from an older schema version is upgraded on a staged copy of its database by the same migration runner a normal upgrade uses; one from a newer version is refused with 409 archive_newer_version. This box's own machine key check is kept, so hoservad starts. With a backup passphrase that opens the archive's secrets.age, every database secret in it (ACME, UPS, backup destination and notification channel credentials) is sealed under this box's machine key and written back into its own table, column and row, and the stack .env files are restored; the passphrase becomes this box's backup passphrase; and, when it opens identity.age, the archive's backup recipient replaces this box's own, so archives written from then on are encrypted to it. Without such a passphrase everything else is restored, this box keeps its own backup recipient (reported as backup_recipient), and every secret sealed under the archive's key is cleared and reported in notRestored. TOTP enrolment and any secret the archive does not carry are always cleared and reported, so the next sign-in of an account with TOTP enrols again. A passphrase given that does not open the archive's secrets.age, or, for an archive with an identity.age and no secrets.age, its identity.age, is refused with 400 backup_passphrase_incorrect before anything is written; one that opens secrets.age but not identity.age is restored, and the report says the recipient was kept. Only matched disks are mounted; an absent, replaced or ambiguous disk stays a row of the restored array, unmounted, and is reported in notRestored (the replace flow adopts a replacement disk), and no disk is ever formatted or partitioned. While no admin account exists this operation and previewConfigImport are served on the Unix socket only; the TCP listener answers 409 setup_required.
Request
Responses
- 200
- default
Import completed; what it restored and what it did not.
An error response.