Use this reference when packaging Docker services as self-hosted apps for ZimaOS or another compatible NAS OS.
Each app lives under Apps/<folder>/docker-compose.yml.
Scope of this page
This page focuses on the top-level x-casaos block, which is the store-specific metadata contract used by the build pipeline.
For the rest of the Compose file:
- follow the official Docker Compose file reference: https://docs.docker.com/reference/compose-file/
- use the official
servicesreference for service definitions: https://docs.docker.com/reference/compose-file/services/ - use the official top-level
namereference: https://docs.docker.com/reference/compose-file/version-and-name/
In other words:
- standard container runtime configuration belongs to Docker Compose
- store-facing app metadata belongs to
x-casaos
Source model
You author one compose file per app. That file contains:
- standard Docker Compose content
- one top-level
x-casaosblock
The source directory name under Apps/ is not the protocol identity. The build process reads identity from the compose content itself, especially top-level name and x-casaos.id.
Minimal example
name: my-app |
Compose rules outside x-casaos
For all non-x-casaos content, this repository does not redefine Docker Compose semantics. Use the official documentation as the source of truth:
- Compose file reference: https://docs.docker.com/reference/compose-file/
- Services reference: https://docs.docker.com/reference/compose-file/services/
- Project
namereference: https://docs.docker.com/reference/compose-file/version-and-name/ - Project naming behavior: https://docs.docker.com/compose/how-tos/project-name/
Repo-specific expectations are limited to:
- compose must be valid YAML
- compose must pass
docker compose config -q - top-level
namemust satisfy repo validation expectations - service-level
services.<name>.x-casaosblocks are legacy and removed during v2 build processing
x-casaos overview
The top-level x-casaos block contains two kinds of fields:
- runtime/display entry fields that remain in built
docker-compose.yml - metadata fields that are extracted into built
meta.json
Field matrix
| Field | Type | Required | Localized in source | Built output location |
|---|---|---|---|---|
id |
string |
Yes | No | built compose + meta.json/index-derived outputs |
main |
string |
Yes | No | built compose |
index |
string |
Yes in practice | No | built compose |
port_map |
string |
Yes | No | built compose |
scheme |
string |
No | No | built compose |
icon |
string |
Yes | No | built compose, rewritten during build |
title |
object |
Yes | Yes | built compose, resolved per locale |
tagline |
object |
Recommended | Yes | meta.json, index listing |
description |
object |
Recommended | Yes | meta.json |
thumbnail |
string |
No | No | meta.json as built asset path |
screenshot_link |
string[] |
No | No | meta.json as built asset paths |
tips |
object |
No | Yes | meta.json |
author |
string |
Recommended | No | meta.json, index listing |
developer |
string |
Recommended | No | meta.json, index listing |
category |
string |
Yes | No | meta.json, index listing |
architectures |
string[] |
Recommended | No | meta.json, index listing |
version |
string |
Yes | No | meta.json, index listing |
update_at |
string |
No | No | meta.json |
release_notes |
object |
No | Yes | meta.json.release_note |
website |
string |
No | No | meta.json |
repo |
string |
No | No | meta.json |
support |
string |
No | No | meta.json |
docs |
string |
No | No | meta.json |
Runtime fields
id
Purpose:
Stable store-protocol application identity.
Rules:
- required in every source app compose
- must use reverse-domain style such as
com.example.myapp - only letters, digits,
.,_, and-are allowed - normalized to lowercase during build
- must contain at least two non-empty dot-separated segments
Build behavior:
- remains present in built compose
- also propagates into built metadata and listing data
Common mistakes:
- treating the app directory name as the identity
- using a short non-domain-style string
main
Purpose:
Names the service that provides the primary browser-facing UI.
Rules:
- required
- must match a service name under
services - should point to the user-facing web service, not a helper container
Build behavior:
- remains in built compose
Common mistakes:
- pointing
mainat a database container
index
Purpose:
Defines the path appended to the app entry URL when clients open the UI.
Rules:
- usually
/ - should reflect the app’s actual web entry path
Build behavior:
- remains in built compose
port_map
Purpose:
Defines the published web UI port exposed to users.
Rules:
- required
- must be a YAML string, for example
"8080" - should match the port users actually open in the browser
Build behavior:
- remains in built compose
Common mistakes:
- writing
port_map: 8080without quotes
scheme
Purpose:
Specifies whether the app should be opened with http or https.
Rules:
- optional
- should match the actual exposed protocol
Build behavior:
- remains in built compose
icon
Purpose:
Provides the installed-dashboard icon URL.
Rules:
- required
- source compose may use any reachable URL
- build output rewrites the field to the built asset URL under
--base-url
Build behavior:
- remains in built compose
- rewritten to point at
apps/{app-id}/assets/icon.*
Common mistakes:
- assuming this exact source value will remain unchanged after build
title
Purpose:
Provides the app display name.
Rules:
- required
- locale-keyed object in source
- should include
en_US
Build behavior:
- remains in built compose
- resolved to plain string text in each generated locale output
Common mistakes:
- writing a plain string instead of a locale-keyed object
Metadata fields
tagline
Purpose:
Short one-line summary used in app listing and detail contexts.
Rules:
- recommended
- locale-keyed object in source
Build behavior:
- extracted to built
meta.json - may also be emitted into listing data such as
index.json
description
Purpose:
Long-form app description.
Rules:
- recommended
- locale-keyed object in source
- may contain markdown text depending on client support
Build behavior:
- extracted to built
meta.json - resolved to plain string in each generated locale file
thumbnail
Purpose:
Provides a larger promotional image for richer app presentation.
Rules:
- optional
- usually references a file in the app directory
Build behavior:
- emitted into
meta.jsonas a built asset path - source file is transformed into output under
apps/{app-id}/assets/
screenshot_link
Purpose:
Provides one or more screenshots for the app detail view.
Rules:
- optional
- array of screenshot filenames in source
Build behavior:
- emitted into
meta.jsonas built asset paths
tips
Purpose:
Carries install-time or pre-install user guidance.
Rules:
- optional
- object whose values are locale-keyed text
Example:
tips: |
Build behavior:
- extracted to built
meta.json - locale values are resolved per generated locale
author
Purpose:
Identifies the store-side packager or maintainer of the app definition.
Rules:
- recommended
- plain string
Build behavior:
- emitted into
meta.json - commonly included in app listing data
developer
Purpose:
Identifies the upstream project or original developer.
Rules:
- recommended
- plain string
Build behavior:
- emitted into
meta.json - commonly included in app listing data
category
Purpose:
Assigns the app to a standardized ZimaOS store category.
Rules:
- required in practice for correct display
- must be one of:
MediaProductivityHomeNetworkingAIFinanceSocialDeveloperOthers
Build behavior:
- emitted into
meta.json - commonly included in app listing data
Common mistakes:
- using free-form category names
architectures
Purpose:
Declares which CPU architectures are supported by the app package.
Rules:
- recommended
- array of strings
- common values include
amd64andarm64
Build behavior:
- emitted into
meta.json - commonly included in app listing data
version
Purpose:
Application version shown to users and used to understand upgrades.
Rules:
- required for apps published to the new store
- plain string
- should change when the published app update changes in a way users should receive as a new version
- should use a semver-style value whenever possible, for example
1.2.3
Build behavior:
- emitted into
meta.json - may also appear in listing data
Why it matters:
- future app upgrade decisions rely on this field to determine what version users are moving to
- without it, users and clients must fall back to lower-level change signals such as
content_hash - missing or non-semver versions weaken update transparency and may be skipped from some listing-facing output
Common mistakes:
- treating
versionas a cosmetic field only - forgetting to update it when publishing a meaningful app update
- using ad-hoc strings that do not behave like a normal release version
update_at
Purpose:
Optional update date used to enrich store presentation.
Rules:
- optional
- recommended format:
YYYY-MM-DD
Build behavior:
- emitted into
meta.json
release_notes
Purpose:
Provides release notes or changelog summary.
Rules:
- optional
- locale-keyed object in source
- source field name remains
release_notes
Build behavior:
- extracted to built
meta.json - renamed to
release_note
Common mistakes:
- writing
release_notein source instead ofrelease_notes
website
Purpose:
Links to the official product or homepage.
Rules:
- optional
- plain string URL
Build behavior:
- emitted into
meta.json
repo
Purpose:
Links to the source repository or project repository.
Rules:
- optional
- plain string URL
Build behavior:
- emitted into
meta.json
support
Purpose:
Links to the support page, issue tracker, forum, or help center.
Rules:
- optional
- plain string URL
Build behavior:
- emitted into
meta.json
docs
Purpose:
Links to documentation for the packaged application.
Rules:
- optional
- plain string URL
Build behavior:
- emitted into
meta.json
What stays in built compose vs what moves to meta.json
Stays in built compose:
idmainindexport_mapschemeicontitle
Moves to built meta.json:
taglinedescriptionthumbnailscreenshot_linktipsauthordevelopercategoryarchitecturesversionupdate_atrelease_notewebsitereposupportdocs
Field placement rule
Use this split when authoring source compose:
- runtime and launch-entry information belongs in runtime
x-casaosfields - store presentation metadata belongs in metadata
x-casaosfields - container runtime details belong to standard Docker Compose sections such as
services,volumes,networks, andenvironment
Common mistakes summary
- using plain strings where locale-keyed objects are expected
- pointing
mainto a non-UI service - using an integer instead of a quoted string for
port_map - using unofficial category values
- forgetting that
titlestays in built compose whiletaglinemoves tometa.json