CasaOS-AppManagement

command module
v0.4.36 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

README

CasaOS-AppManagement

Not affiliated with IceWhale. An independent, community-maintained distribution of CasaOS, not produced or endorsed by Shanghai IceWhale Technology Limited. CASAOS is their trademark, used here only to say what this is a release of. The original project is IceWhaleTech/CasaOS; report problems with this distribution at ReCasaOS/CasaOS/issues.

The service that installs and runs apps on a CasaOS host. It is the Docker Compose layer of the system: it keeps the app store catalogues, turns a store entry into a docker-compose.yml, runs Compose against the local Docker daemon, and reports container status, logs and available updates back to the dashboard.

This repository is part of ReCasaOS, a maintained release of the project after upstream IceWhaleTech stopped shipping in 2025. It descends from alvins82's fork, whose Docker SDK bump is what keeps CasaOS installable on a current daemon.

What it does

The service listens on a random loopback port, writes that address to /var/run/casaos/app-management.url, and registers its paths with CasaOS-Gateway:

Path What is behind it
/v2/app_management the current API
/v1/apps, /v1/container, /v1/app-categories the v1 API, kept for older clients
/doc/v2/app_management, /v1doc/v1/app_management the OpenAPI specs and their viewer

Under /v2/app_management: /appstore registers and lists stores, /apps serves the merged catalogue (with /apps/upgradable and /apps/{id}/compose), /categories the category list and its counts, /compose and /compose/{id} install an app and then apply settings, update, start, stop or uninstall it (/status, /containers, /logs, /healthcheck), /container/{id} reports and health-checks a single container, and /image pulls images ahead of an install. /compose/{id}/env reads and replaces the .env next to that app's docker-compose.yml and re-creates the app so the new values apply. The full list is api/app_management/openapi.yaml; the Go server, types and MessageBus client are generated from it and are not committed.

Two jobs run on a schedule from main.go: the store catalogues are refreshed every 10 minutes, and every 15 seconds a sweep starts apps Docker abandoned at boot because their storage was not mounted yet.

On a host:

  • /etc/casaos/app-management.conf — paths and the app store URLs, written from build/sysroot/etc/casaos/app-management.conf.sample on first start
  • /etc/casaos/env — variables injected into every app
  • /var/lib/casaos/appstore — the downloaded catalogues
  • /var/lib/casaos/apps/<name>/docker-compose.yml — one directory per installed app; this is the file the settings page and the compose editor write
  • /var/log/casaos/app-management.log
  • casaos-app-management.service, started after docker.service and casaos-message-bus.service

There is no database. An installed app is its compose file plus whatever the Docker daemon reports about it.

Install

Components are not installed on their own. The distribution is installed and upgraded with one command:

curl -fsSL https://github.com/ReCasaOS/CasaOS-Install/releases/latest/download/install.sh | sudo bash

What a release contains, and how it is built, is described in CasaOS-Install.

What this fork changed

From alvins82:

  • Docker 26 and later. The SDKs were pinned to docker/cli and docker/docker v24, compose/v2 v2.23 and compose-go v1, which is why CasaOS stopped working against a current daemon. They are now v26.1.0, v2.27.0 and compose-go/v2 v2.1.0; the client already negotiated the API version with the daemon, and pkg/docker/api_negotiation_test.go now asserts it still does. This is the change that made the fork necessary. Offered upstream as #217, still unmerged.
  • Apps abandoned at boot. Docker gives up on a container whose bind mount does not exist yet, which happens on every reboot when apps live on a disk mounted after docker.service. A recovery sweep starts those apps once their storage appears, and leaves alone the ones the user stopped.

Here:

  • An app can keep its secrets in a .env. An installed app may carry a .env next to its docker-compose.yml, edited from the dashboard through GET/PUT /v2/app_management/compose/{id}/env: PUT replaces the whole file (an empty body removes it) and re-creates the app so the new values apply. A reference to one of its keys (${KEY}, $KEY, ${KEY:-default}), or to a key the runtime defines ($AppID, ${TZ}, $PUID, ${PGID}), now survives every settings round trip and the App Store update as written, where before the first save or update baked the resolved value into the compose file and every later .env edit was a no-op; the key has to be in .env when the compose is saved, or the reference is baked as a literal. It is kept in environment and every other free-text field (image, command, labels, env_file, x-casaos...) and in the host side of ports and volumes, which come back in the long syntax; a typed field such as cpus, mem_limit or privileged cannot hold one, and the editing load (GET /compose/{id} as YAML) fails with a 500 naming that field instead of serving the resolved value. A .env that defines a key the runtime sets itself (TZ, PUID, PGID, AppID, the environment of the CasaOS process) is refused with a 400 naming the key, since the runtime's value wins over the file anyway. When the compose file does not load, the pull fails or the app fails to start after a .env change, the previous .env is put back together with the previous docker-compose.yml and the app is started from them again.
  • A $ no longer doubles on every save. The settings handler parsed the incoming YAML without interpolation and then re-escaped every $, so a value it had produced itself came back doubled: $2a$12$… became $$2a$$12$$…, then $$$$2a$$$$12$$$$…, and the container received a broken password hash. Parsing with interpolation on makes the round trip idempotent. Fixes CasaOS#1988.
  • Architecture filtering. An app declaring architectures: [] was hidden on every host, because an explicit empty list decodes to an empty slice rather than nil and only nil was treated as "runs anywhere" — which is what the dashboard already assumed. Category counts were computed from the unfiltered catalogue, so on arm hosts they were larger than the number of cards listed under them. Both now agree with the list. Supersedes the draft in #202, which dereferenced that empty list and hardcoded amd64.
  • Releases. The upstream workflow needed IceWhale's secrets and is gone. .github/workflows/release.yml runs the tests and publishes with GoReleaser on a v*.*.* tag using the default GITHUB_TOKEN. Our change to .goreleaser.yaml is one line, release.github.owner, now ReCasaOS, so the archive layout the installer consumes is unchanged.
  • No geo-IP at install time. build/scripts/migration/script.d ran __get_download_domain at top level, curling ipconfig.io/country and then ifconfig.io/country_code to pick a download mirror by country. install.sh runs every script in that directory on every install and every upgrade, so both services were contacted each time, before the script had even decided whether a migration was due. On a current box it is not, though this repository is the one whose list still carries a reachable v0.4.5 entry. The migration tools now come from GitHub unconditionally, and the domain is a constant: it is not an environment knob either, because what it points at is downloaded and run as root without verification.
  • The compose lifecycle test is opt-in. It skipped itself only when no Docker daemon was reachable, which is the wrong question: a CI runner has a daemon and no CasaOS behind it, so the test ran and failed on the missing app store. It now requires CASAOS_INTEGRATION.
  • The module path is github.com/ReCasaOS/CasaOS-AppManagement. The Go module and every import of it moved off github.com/IceWhaleTech, and the shared library is now github.com/ReCasaOS/CasaOS-Common v0.4.22, so logs, stack traces and go version -m on the shipped binary name this distribution rather than upstream; App Store catalogue and CDN icon URLs still point at IceWhale's repositories and are unchanged.

The compose editor in an app's settings is a dashboard feature. The endpoint it saves through, PUT /v2/app_management/compose/{id}, is upstream; what this fork changed behind it is the $ handling and the .env references above.

Development

go generate ./...
go build ./...
go test ./route/v2/ ./service/ -count=1

Go 1.21 or later, per go.mod. codegen/ is generated and not committed, so go generate comes first; it fetches oapi-codegen and the MessageBus spec, so the first run needs network access.

go test ./... also runs ./pkg/docker, which drives a real Docker daemon and pulls images from Docker Hub. On a Windows workstation those tests fail on a goroutine-leak assertion against a go-winio worker; CI runs them on Linux. TestComposeAppLifecycle in ./service stays skipped unless CASAOS_INTEGRATION is set — it needs a live CasaOS host, not just a daemon.

Licence

Apache License 2.0 — see LICENSE; the upstream copyright notices are kept in the source. The service is the work of IceWhale and its contributors. The Docker SDK bump and the boot recovery sweep are alvins82's.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
appfile2compose command
migration-tool command
validator command
@Author: link a624669980@163.com
@Author: link a624669980@163.com
pkg
docker
credit: https://github.com/containrrr/watchtower
credit: https://github.com/containrrr/watchtower
v1
v2
@Author: LinkLeong link@icewhale.com
@Author: LinkLeong link@icewhale.com
v1

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL