Skip to main content
zenith-compose.yml is a Compose Specification file with a required top-level x-zenith block for Zenith listing and deployment metadata. Start with zenith init, check your project with zenith check, and use zenith up for temporary testing. When you are ready to submit for review, zenith publish can build your app from a pinned public GitHub commit. You do not need to publish your own app image first.
This page covers the fields most apps need. Use the complete zenith-compose.yml reference for the shared schema and published runtime behavior. For source-build constraints, see the preview policy.

Start with the CLI

Install and sign in using the quickstart, then work from your project root.
1

Initialize the project

Run zenith init to add missing Zenith files. Inspect the generated Dockerfile, command, port, and Compose services. Keep your existing app behavior.
2

Check preview compatibility

Run zenith check --upload-size. This checks the local preview policy and estimates the upload size. It works offline; it is not a general validator for every published runtime feature.
3

Test a temporary preview

Run zenith up to upload the project and build a temporary preview. Check the app at the returned URL, inspect zenith logs, and run zenith down when finished. A preview is temporary testing, not catalogue publication. See temporary previews.
4

Publish a pinned commit

Commit and push the manifest, Dockerfile, and app source to a public GitHub repository. With publishing authorization in place, run zenith publish to submit a pinned commit for review. See publishing.
For previews, define exactly one app service with build: . and a project-root Dockerfile, plus dependencies using public images. Expose the built HTTP app through a primary x-zenith.expose entry with web: true and no label. The Dockerfile can omit EXPOSE. Do not add an image alongside build on the preview app. Preview policy rejects alternate Dockerfiles, remote build contexts, build arguments, targets, and build platforms. Previews support x-zenith.env, x-zenith.storage, and x-zenith.configs. See the preview policy before adapting published examples.

Create the file

Keep zenith-compose.yml at the root of your app’s repository. If you already have a working Compose file, use it to guide the service definitions. The remaining examples describe the shared schema and published runtime. This image-based example packages PrivateBin with one public service and one persistent volume. It is not a zenith up project as written:
zenith-compose.yml
The schema requires services and x-zenith. Inside x-zenith, catalog requires name, description, authors, tags, source, and license; expose must contain at least one entry. The remaining catalogue fields and top-level x-zenith blocks are optional.

Configure the listing

Set the catalogue metadata in catalog. Include name, description, authors, tags, source, and license. Use accurate project details and the app’s actual license. See the catalog reference for optional fields.

Expose a service

expose maps a Compose service port to a public Zenith hostname. Follow Public URLs and domains to configure your app’s base URL, allowed hosts, and labelled endpoints.
Use an entry without label for the primary endpoint. Add a unique label for each additional endpoint. Set web explicitly, even when its value is false.

Add forward authentication

To require the deployment owner’s Zenith account before requests reach an endpoint, follow Protect an app with forward authentication. Configure app accounts separately if the app also has its own login.

Add deployment variables

Declare runtime values with x-zenith.env. Follow Environment variables and secrets for aliases, generated credentials, service scoping, and owner inputs.

Send email

Use Zenith’s outbound SMTP relay for verification emails, password resets, and notifications. Follow SMTP email to map credentials and configure STARTTLS.

Add Sign in with Zenith

Use x-zenith.sign_in to connect your app to Zenith through OpenID Connect. The dedicated guide covers callback paths, credential mappings, owner account linking, and access controls.

Add persistent storage

Mount named volumes for durable app data. Follow Persistent storage and files to configure storage and owner file-manager access.

Add static configuration

Mount static, non-secret files with inline Compose configs. Follow Static configuration files for a complete example and runtime behavior.

Expose editable configuration files

Use x-zenith.configs to give app owners an editor for a specific file in a named volume. The volume can stay private. Applying a change saves the file and requests an app restart. Follow Expose configuration files to create the file, make it editable, and keep changes across restarts.

Check the file locally

Parse the Compose model locally:
Then run the app:
These optional Docker Compose commands test the Compose model and the app locally. They do not reproduce Zenith’s environment resolution or replace zenith check and zenith up for preview-compatible projects. Image-only published manifests can be valid even when they fail the stricter preview check. Zenith validates the published app again during submission.
Continue when Compose parses the file without errors, required services reach their expected state, and each exposed service answers on its declared port.

Zenith runtime restrictions

Docker Compose accepts some settings that Zenith does not. Remove the unsupported settings listed below before you submit. Temporary previews have additional restrictions.
  • Bind mounts.
  • Top-level include.
  • Config sources other than inline content, including configs.<name>.file, external, and environment.
  • Config ownership overrides (uid or gid) or targets that collide with another mount.
  • secrets.<name>.file.
  • Service extends, env_file, or label_file.
  • privileged: true.
To let Zenith build your app image from the pinned public GitHub commit, use build: . for one service and keep a Dockerfile at the repository root. Give every other service a public image. See container requirements for both options. Avoid cap_add unless your app needs a specific Linux capability. Some capabilities weaken isolation or may be rejected by the cluster. Other Compose fields may parse without working on Zenith; use the supported fields.

Publish the file

Commit and push zenith-compose.yml at the repository root of a public GitHub repository. The file must be non-empty and no larger than 128 KiB. For build: ., include a root Dockerfile and the required app source. Image-only submissions do not require a Dockerfile. zenith publish selects local HEAD by default, or you can supply a full 40-character SHA with --commit. The selected commit must be available on GitHub. It does not need to be the current default-branch commit. After sign-in, GitHub connection, Developer Agreement acceptance, and explicit authorization to submit, run:
For build: ., Zenith reuses a successful preview image when its verified source matches the pinned commit. Otherwise, Zenith builds that commit. The CLI waits for the image before submitting for review. Apps that use public images can be submitted without this build. Submission enters review, not immediate publication. Later Git pushes do not automatically update the submission or an existing deployment. See publish your app for listing metadata, screenshots, and revision commands.

Next: publish your app

Submit a pinned public GitHub commit for review with the CLI.

Complete reference

Check every supported field, default, validation rule, and runtime behavior.