Skip to main content

apps

Docker Engine containers and images (hoserva app list): every container the Engine reports, managed and unmanaged alike, with the same lifecycle actions for both: start, stop, restart, recreate, remove, logs and stats. The Compose stack model is served by the stacks operations (listStacks, createStack, getStack, updateStack, getStackConfig, updateStackConfig, startStack, removeStack). available is false, with no error, whenever Docker itself is not reachable: a missing prerequisite is Apps' normal state, not a failed request.

📄️Convert an Unraid XML template to Compose

Converts one Unraid container template to a Compose file for review. Nothing is created, written or run: the result is the generated `compose` beside the `source` XML as it was sent, every warning, and the privilege summary computed from the generated Compose content, so the caller reads all of it before it acts on any of it. Every part of the template that is not translated is reported, never dropped: an `<ExtraParams>` flag outside the translate table is listed in a comment at the top of the service and as an `untranslated_flag` warning; a host path outside the pool and the cache (`/boot`, `/mnt/disks/`, `/mnt/user0`, another pool) is kept as written and listed as a `flagged_path` warning; a custom network the template names is a `missing_network` warning carrying the `docker network create` command, with placeholders for what the template does not say; two entries for the same target with different values are a `conflict`; the possibility of state inside the source container that no template expresses is always a `writable_layer` warning. `clean` is true when no warning is of the classes that need manual action (`writable_layer` and `note` never count against it). A body that is not an Unraid container template is refused with 400 `invalid_unraid_template`.

📄️List Docker networks

Every network the Docker Engine holds, sorted by name: the built-in `bridge`, `host` and `none` and the networks the user created (macvlan and ipvlan included). The install wizard offers the existing ones as network modes; Hoserva never creates a network. `available` is false, with no error, whenever Docker itself is not reachable, and then `networks` is empty without meaning there are none: a caller that needs the list must treat it as unknown. Any other failure to read the list is an error, never an empty list.

📄️Container update status

What the daily registry check last found for each container's image: a new build of the same tag (`new_build`) is reported apart from a newer version tag (`new_version`, named by `availableTag`). The check asks each registry for manifests and tag names only, never a pull. `skipped` means the registry was rate limiting requests and is asked again at the next check, `failed` that the check could not tell (including a registry whose saved credential cannot be used or was refused: it is never asked anonymously instead), and `not_checked` that no check has reached the image yet or that it could not look: the registry wants a login and no credential is saved for it (`putRegistryCredential`) or the container is pinned to an image digest, so there is no tag to update. The `message` says which. None of them means up to date. available is false, with no error, whenever Docker itself is not reachable.

📄️Update several containers

Queues one `container_update` job (service class) that updates the named containers one after another, each as `updateApp` does: an appdata snapshot first when its appdata sits on the cache disk, then the update, keeping the image it ran before for a revert. One container's failure does not stop the others; the job fails, naming each, once they have all been tried, and a container that failed is left on its previous image. With no `containers`, the targets are the containers the last update check found a newer image for, minus those that opted out of bulk updates (`setAppUpdatePolicy`); those come back in `skipped`. Naming a container updates it whether or not it opted out. When there is nothing to update no job is queued and `job` is absent. Refused with 409 `array_stopped` while the array is stopped (maintenance mode) or its storage is not ready, and with 503 `array_state_unknown` if the array's state cannot be read; no job is queued. An unknown container is 404 and queues nothing.

📄️Container updates that can be reverted

Every update Hoserva made that kept the image the container ran before it, newest first: when it was made, the previous image, the appdata snapshot taken just before it (absent for a container with no appdata on the cache disk) and until when the previous image is kept (`keepUntil`, set by `imageKeepDays` in the app settings). `revertible` says whether `revertApp` would go ahead now: only the newest update of a container can be reverted, once, within the keep period and while the previous image is still held and the container still runs the image it was updated to. A snapshot that has gone from its destination only shows when the revert is tried. available is false, with no error, whenever Docker itself is not reachable.

📄️Save a registry's credential

Saves the username and password the update check logs in to this registry with, replacing any it already has, sealed under the machine key. The password is write-only: no operation returns it and it is never logged. The credential is sent only to this registry's own host (and, for Docker Hub, its token service `auth.docker.io`), only over https, and never follows a redirect to another host or scheme; a registry whose address would send it in plain HTTP, or whose token service is on another host, is not logged in to and its images are reported `failed`. It is carried in a config archive's `secrets.age`, so a restore with the backup passphrase brings it back; without it the credential is cleared and the restore report names it. A host that is not a registry host name, or an empty username or password, a username with a colon, or a value with control characters is 400 `invalid_registry_credential`.

📄️Remove a container

Removes a stopped container (`app_running`, 409, for one that is not stopped). The container's appdata is kept unless `deleteAppdata` is explicitly true: then the bind-mount directories strictly inside the appdata location (the cache disk's `appdata` directory) are deleted, together with the container's anonymous volumes. Anything outside that location, the location itself, and any directory another container mounts, or that lies inside a directory of appdata another container mounts, is never deleted — a request that would delete one is refused (`appdata_shared`, 409) and removes nothing. `deleteAppdata` with no appdata location is refused (`appdata_unavailable`, 409). `deleteAppdata` is refused with 409 `array_stopped` while the array is stopped (maintenance mode) or its storage is not ready, because the cache disk is not mounted and the appdata on it could not be deleted, and with 503 `array_state_unknown` if the array's state cannot be read. A remove that keeps appdata is allowed on a stopped array. Every refusal happens before the container is removed.

📄️Recreate a container

Queues a `container_recreate` job (service class): it pulls the container's image again and replaces the container with one built from the same configuration, volumes and networks. If the pull or the creation of the replacement fails, or the replacement does not start, the original container is left as it was — same name and volumes, running again if it was running. A container started with `--rm` cannot be recreated: the Engine deletes it the moment it stops, so the job fails before changing anything. Refused with 409 `array_stopped` while the array is stopped (maintenance mode) or its storage is not ready, and with 503 `array_state_unknown` if the array's state cannot be read; no job is queued. The job checks again when it runs and fails, changing nothing, if the array has stopped since.

📄️Update a container

Queues a `container_update` job (service class) that updates the container. The job pulls the container's image again first, which changes nothing about the container: a failed pull, or one that finds nothing newer, ends the job with no snapshot taken and the container left alone. Otherwise, when its appdata sits on the cache disk, a snapshot of it is written (a `pre-update` archive on the appdata backup's destinations) and the update does not go ahead if that snapshot cannot be written; then the container is replaced by one built from the pulled image with the same configuration, volumes and networks, as `recreateApp` does, and the image it ran before is kept locally for `imageKeepDays`. If any step after the pull fails, the container is left on its previous image, with the image tag the pull moved pointed back at it and the update's record removed, so nothing is left to revert. A container pinned to an image digest cannot be updated. Refused with 409 `array_stopped` while the array is stopped (maintenance mode) or its storage is not ready, and with 503 `array_state_unknown` if the array's state cannot be read; no job is queued. The job checks again when it runs.

📄️Revert a container's last update

Queues a `container_update` job (service class) that puts the container back on the image it ran before its latest update and restores the appdata snapshot taken just before it. A running container is stopped first, so it never runs the updated image against the restored data; the snapshot is restored, writing a snapshot of the appdata it replaces (`pre-restore`), so anything written since the update is kept in an archive; the container is recreated from the kept image without pulling; then it is started, once, on the previous image. A container that was stopped stays stopped. A revert deletes nothing from the pool. Refused with 409 `nothing_to_revert` when the container has no update to revert (see `listAppUpdateHistory`), with 409 `revert_unavailable` when the update is on record but can no longer be undone (the previous image was removed, its keep period ended, or the snapshot is gone from its destination), and with 409 `array_stopped` / 503 `array_state_unknown` while the array is stopped or unreadable; no job is queued and nothing is changed. If the job fails after it has stopped the container, the container is left stopped, because the restore may already have replaced its data and the updated image must not run against that; reverting again finishes it, while the snapshot is still on its destination, after which the container is started by hand.