From 04cfc00d2681a7bdc5745843e208703919645a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Pavl=C3=AD=C4=8Dek?= Date: Mon, 17 Aug 2026 15:51:55 +0200 Subject: [PATCH 1/3] z0 - add local storage, deprecate shared storage --- .../alpine/how-to/customize-runtime.mdx | 2 +- .../content/deno/how-to/customize-runtime.mdx | 2 +- apps/docs/content/features/backup.mdx | 2 +- apps/docs/content/features/coding-agents.mdx | 2 +- apps/docs/content/features/pipeline.mdx | 2 +- apps/docs/content/features/scaling.mdx | 6 +- apps/docs/content/guides/backup.mdx | 3 +- apps/docs/content/guides/choose-storage.mdx | 33 + .../content/guides/deployment-lifecycle.mdx | 5 +- .../guides/object-storage-integration.mdx | 2 +- .../content/guides/production-checklist.mdx | 2 + .../guides/shared-storage-integration.mdx | 8 +- apps/docs/content/homepage.mdx | 5 +- .../content/local-storage/how-to/connect.mdx | 76 + .../content/local-storage/how-to/create.mdx | 43 + .../content/local-storage/how-to/manage.mdx | 55 + apps/docs/content/local-storage/overview.mdx | 170 + .../content/local-storage/tech-details.mdx | 55 + .../nginx/how-to/customize-runtime.mdx | 2 +- .../references/import-yaml/type-list.mdx | 6 +- apps/docs/content/references/import.mdx | 6 +- .../content/shared-storage/how-to/connect.mdx | 4 + .../content/shared-storage/how-to/create.mdx | 4 + .../content/shared-storage/how-to/manage.mdx | 4 + apps/docs/content/shared-storage/overview.mdx | 11 +- .../content/shared-storage/tech-details.mdx | 4 + .../ubuntu/how-to/customize-runtime.mdx | 2 +- .../content/zerops-yaml/specification.mdx | 27 + apps/docs/sidebars.js | 68 +- .../components/content/customize-runtime.mdx | 2 +- .../src/components/content/shared-storage.mdx | 4 + .../src/theme/Icon/ServersConnected/index.tsx | 30 + apps/docs/src/theme/Icon/index.tsx | 2 + apps/docs/static/data.json | 3 + apps/docs/static/llms-full.txt | 57486 ++++++++-------- apps/docs/static/llms-small.txt | 45752 ++++++------ apps/docs/static/llms.txt | 700 +- 37 files changed, 53052 insertions(+), 51538 deletions(-) create mode 100644 apps/docs/content/guides/choose-storage.mdx create mode 100644 apps/docs/content/local-storage/how-to/connect.mdx create mode 100644 apps/docs/content/local-storage/how-to/create.mdx create mode 100644 apps/docs/content/local-storage/how-to/manage.mdx create mode 100644 apps/docs/content/local-storage/overview.mdx create mode 100644 apps/docs/content/local-storage/tech-details.mdx create mode 100644 apps/docs/src/theme/Icon/ServersConnected/index.tsx diff --git a/apps/docs/content/alpine/how-to/customize-runtime.mdx b/apps/docs/content/alpine/how-to/customize-runtime.mdx index 23e9d8dbc..c0d28ae4d 100644 --- a/apps/docs/content/alpine/how-to/customize-runtime.mdx +++ b/apps/docs/content/alpine/how-to/customize-runtime.mdx @@ -90,7 +90,7 @@ Zerops caches custom runtime images to optimize deployment times. Learn about [c For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). :::warning -Shared storage mounts are not available during the runtime prepare phase. +Shared storage mounts and Local Storage volumes are not available during the runtime prepare phase. ::: ## Troubleshooting diff --git a/apps/docs/content/deno/how-to/customize-runtime.mdx b/apps/docs/content/deno/how-to/customize-runtime.mdx index fbae815f8..8bbbd99f6 100644 --- a/apps/docs/content/deno/how-to/customize-runtime.mdx +++ b/apps/docs/content/deno/how-to/customize-runtime.mdx @@ -75,7 +75,7 @@ Zerops caches custom runtime images to optimize deployment times. Learn about [c For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). :::warning -Shared storage mounts are not available during the runtime prepare phase. +Shared storage mounts and Local Storage volumes are not available during the runtime prepare phase. ::: ## Troubleshooting diff --git a/apps/docs/content/features/backup.mdx b/apps/docs/content/features/backup.mdx index 0a2331c63..1a7df48b3 100644 --- a/apps/docs/content/features/backup.mdx +++ b/apps/docs/content/features/backup.mdx @@ -7,7 +7,7 @@ Zerops provides an automated, secure backup system for supported services. This ## Supported Services -Zerops provides automated backup functionality for the following services. For specific backup format details and restore instructions, visit each service's documentation: [MariaDB](/mariadb/how-to/backup), [PostgreSQL](/postgresql/how-to/manage#backups), [Qdrant](/qdrant/overview), [Elasticsearch](/elasticsearch/overview), [NATS](/nats/overview), [Meilisearch](/meilisearch/overview), and [Shared Storage](/shared-storage/how-to/manage#backups). +Zerops provides automated backup functionality for the following services. For specific backup format details and restore instructions, visit each service's documentation: [MariaDB](/mariadb/how-to/backup), [PostgreSQL](/postgresql/how-to/manage#backups), [Qdrant](/qdrant/overview), [Elasticsearch](/elasticsearch/overview), [NATS](/nats/overview), [Meilisearch](/meilisearch/overview), [Local Storage](/local-storage/how-to/manage#backups), and [Shared Storage](/shared-storage/how-to/manage#backups). ## Managing Backups in the UI diff --git a/apps/docs/content/features/coding-agents.mdx b/apps/docs/content/features/coding-agents.mdx index 4f581d3bc..05d278630 100644 --- a/apps/docs/content/features/coding-agents.mdx +++ b/apps/docs/content/features/coding-agents.mdx @@ -54,7 +54,7 @@ ZCP supports multiple coding agents including Claude Code (Anthropic), Codex (Op ### An ordinary Zerops project underneath -The agent operates inside a normal Zerops project — same shape as production. Managed databases (PostgreSQL, MariaDB, ClickHouse), key-value stores (KeyDB, Valkey), search (Elasticsearch, Meilisearch, Typesense), vector store (Qdrant), message queues (NATS, Kafka), object and shared storage, managed Nginx — all on a private network, addressable by hostname. The same pipeline that deploys here can deploy to a separate HA production project with no `zcp` service attached. Not a sandbox the work outgrows. +The agent operates inside a normal Zerops project — same shape as production. Managed databases (PostgreSQL, MariaDB, ClickHouse), key-value stores (KeyDB, Valkey), search (Elasticsearch, Meilisearch, Typesense), vector store (Qdrant), message queues (NATS, Kafka), object, local and shared storage, managed Nginx — all on a private network, addressable by hostname. The same pipeline that deploys here can deploy to a separate HA production project with no `zcp` service attached. Not a sandbox the work outgrows. ### Human ↔ agent handover diff --git a/apps/docs/content/features/pipeline.mdx b/apps/docs/content/features/pipeline.mdx index 6c86f18bf..78c82fe33 100644 --- a/apps/docs/content/features/pipeline.mdx +++ b/apps/docs/content/features/pipeline.mdx @@ -308,7 +308,7 @@ Learn more about building custom runtime images: :::warning Do not include your application code in the custom runtime image, as your built application code is deployed automatically into fresh containers. -Shared storage mounts are also not available during the runtime prepare phase. +Shared storage mounts and Local Storage volumes are also not available during the runtime prepare phase. ::: ## Deploy phase diff --git a/apps/docs/content/features/scaling.mdx b/apps/docs/content/features/scaling.mdx index ad0a96201..fba86207c 100644 --- a/apps/docs/content/features/scaling.mdx +++ b/apps/docs/content/features/scaling.mdx @@ -22,7 +22,7 @@ Unlike traditional hosting where resources must be predicted and pre-provisioned Zerops uses two fundamentally different approaches for optimizing infrastructure: #### **Resource Management (Vertical Scaling)** -- **Applies to:** Runtime services, databases, shared storage, and Linux containers (Alpine and Ubuntu) +- **Applies to:** Runtime services, databases, local and shared storage, and Linux containers (Alpine and Ubuntu) - **What it does:** Adjusts CPU, RAM, and disk resources within individual containers - **Management:** Automated by Zerops, but customizable by users @@ -306,6 +306,10 @@ For databases and shared storage services, Zerops offers two deployment modes fo Deployment mode cannot be changed after creation. ::: +:::note +[Local Storage](/local-storage/overview) is available in single container mode only — its volume lives on a single physical machine by design. See its [technical details](/local-storage/tech-details) for how availability and scaling work there. +::: + #### Single Container Mode Single Container Mode provides one container with vertical scaling only. This is suitable for development environments or non-critical data storage. diff --git a/apps/docs/content/guides/backup.mdx b/apps/docs/content/guides/backup.mdx index b72afee17..16e9d4b85 100644 --- a/apps/docs/content/guides/backup.mdx +++ b/apps/docs/content/guides/backup.mdx @@ -6,7 +6,7 @@ description: "Zerops auto-backs up databases and storage daily (00:00-01:00 UTC) Zerops auto-backs up databases and storage daily (00:00-01:00 UTC) with X25519 encryption; backups are retained for 7 days minimum after service/project deletion. ## Supported Services -MariaDB, PostgreSQL, Qdrant, Elasticsearch, NATS, Meilisearch, Shared Storage. +MariaDB, PostgreSQL, Qdrant, Elasticsearch, NATS, Meilisearch, Local Storage, Shared Storage. **ClickHouse**: not on the standard auto-backup path — back it up with the native `BACKUP ALL ...` SQL command (super user), stored as `.tar.gz`. @@ -50,6 +50,7 @@ End-to-end with X25519 per-project keys. Decrypted only on download. | Meilisearch | `.dump` | | Qdrant | `.snapshot` | | NATS | `.tar.gz` | +| Local Storage | tar → `.tar.gz` (archive of the live volume — pause database writes or use an application-level backup for guaranteed consistency) | | Shared Storage | tar → `.tar.gz` | ## Gotchas diff --git a/apps/docs/content/guides/choose-storage.mdx b/apps/docs/content/guides/choose-storage.mdx new file mode 100644 index 000000000..a3ddc880c --- /dev/null +++ b/apps/docs/content/guides/choose-storage.mdx @@ -0,0 +1,33 @@ +--- +title: "Choosing Storage on Zerops" +description: "**Use Object Storage** for uploads, media, and backups; **use Local Storage** for anything that needs a real filesystem (SQLite, Prometheus, Gitea, shared certs). Shared Storage is deprecated." +--- + +**Use Object Storage** (S3) for uploads, media, and backups. **Use Local Storage** (`run.volume`) for anything that needs a real filesystem — SQLite and other embedded databases, single-node stateful apps, filesystem state shared between services. **Shared Storage is deprecated** — don't use it in new projects. + +## Decision Matrix + +| Need | Choice | Why | +|------|--------|-----| +| User uploads, media, backups, logs | **Object Storage** (default) | S3 API, HA, cheapest per GB, survives independent of any service | +| SQLite / Prometheus / filesystem-based databases | **Local Storage** | Single-kernel POSIX: locking and mmap are correct — the only Zerops storage where these workloads are safe | +| Single-node stateful app (Gitea, etc.) | **Local Storage** | Persistent volume survives deploys and container replacement | +| Filesystem state shared between services (certs, caches) | **Local Storage** | One volume mountable by multiple runtime services, writes visible immediately | +| Temp/scratch files | Container disk | Fine as-is; lost on deploy | +| Existing `mount:`-based setups | Shared Storage (deprecated) | Keeps working; migrate to Local Storage or Object Storage | + +## Local Storage + +- Service type `local-storage:single`; runtime services mount it via `run.volume` in zerops.yaml: `volume: {hostname: , mountPath: /path (default /mnt/{hostname}), readOnly: false}`. One volume per runtime service; multiple services can mount the same volume. +- The volume is local to one physical machine: **all containers of all connected services are co-located on the volume's machine**. Not HA — on hardware failure or maintenance, Zerops moves the volume to a healthy server and every connected service goes through a small outage (stop, move, start); volume recovery is not guaranteed, so backups are strongly recommended. Horizontal scaling of connected services is capped by that machine's capacity. +- The volume survives deploys: new containers get the same volume attached. Mounted in runtime containers only (not build/prepare). +- Capacity = the service's max disk in `verticalAutoscaling`. Usage is billed as the service's disk usage. +- The service's own container has the volume at `/data` with SSH/web-shell access for direct inspection. Daily `.tar.gz` backups of the live volume are on by default — pause database writes or use application-level backups (e.g. `sqlite3 .backup`) for guaranteed-consistent archives. + +## Object Storage + +See the [object-storage integration guide](/guides/object-storage-integration): S3-compatible (MinIO), `objectStorageSize` quota, `AWS_USE_PATH_STYLE_ENDPOINT: true`, `${storage_*}` env var references. Not a filesystem — no locking, no partial writes, no mmap. + +## Shared Storage (deprecated) + +A managed SeaweedFS cluster mounted at `/mnt/` via the import-level `mount:` field. Deprecated: it will be replaced by a standalone SeaweedFS managed service mounted with `zsc shared-storage mount` in `initCommands`. Its per-mount-only locks make databases unsafe on it — that workload belongs on Local Storage. Existing services keep working. diff --git a/apps/docs/content/guides/deployment-lifecycle.mdx b/apps/docs/content/guides/deployment-lifecycle.mdx index e2aef15ec..3e446911b 100644 --- a/apps/docs/content/guides/deployment-lifecycle.mdx +++ b/apps/docs/content/guides/deployment-lifecycle.mdx @@ -136,6 +136,7 @@ When using SSHFS (`zerops_mount`) for dev workflows, deploy replaces the contain 2. **SSHFS mount auto-reconnects only while the service is running.** Usually no remount is needed, but if the mount goes stale after a deploy (stat/ls returns empty, writes hang), recover it explicitly with `zerops_mount action="mount"`. A stopped service has no live mount until it starts again. 3. **zerops.yml must be in deployFiles** for dev self-deploy lifecycle. Without it, subsequent deploys from the container fail because zerops.yml is missing. -**Two kinds of "mount" (disambiguation):** +**Three kinds of "mount" (disambiguation):** - `zerops_mount` -- SSHFS tool, mounts service `/var/www` locally for development. This is a dev workflow tool. -- Shared storage mount -- platform feature, attaches a shared-storage volume at `/mnt/{hostname}` via the service-level `mount:` parameter in import.yml. There is no `mount` field in zerops.yml (a `run.mount` is silently ignored). These are completely unrelated features. +- Shared storage mount (deprecated) -- platform feature, attaches a shared-storage volume at `/mnt/{hostname}` via the service-level `mount:` parameter in import.yml. There is no `mount` field in zerops.yml (a `run.mount` is silently ignored). These are completely unrelated features. +- Local Storage volume -- platform feature, mounts a Local Storage service's persistent volume via the `run.volume` field in zerops.yml (`volume: {hostname, mountPath, readOnly}`). The volume survives deploys: new containers get the same volume attached at the configured `mountPath`. diff --git a/apps/docs/content/guides/object-storage-integration.mdx b/apps/docs/content/guides/object-storage-integration.mdx index ea2fba360..c6f9218d3 100644 --- a/apps/docs/content/guides/object-storage-integration.mdx +++ b/apps/docs/content/guides/object-storage-integration.mdx @@ -82,7 +82,7 @@ Each service = one bucket (auto-named, immutable). Need multiple buckets? Create ## Gotchas 1. **`forcePathStyle: true` / `AWS_USE_PATH_STYLE_ENDPOINT: true` is REQUIRED**: Zerops uses MinIO which doesn't support virtual-hosted style -2. **Container filesystem is replaced on deploy**: Files on disk survive restarts but are lost when a new container is created (deploy, scale-up). Always use Object Storage for persistent data +2. **Container filesystem is replaced on deploy**: Files on disk survive restarts but are lost when a new container is created (deploy, scale-up). Use Object Storage for persistent data, or a Local Storage volume (`run.volume`) when the workload needs a real filesystem (SQLite, Prometheus, Gitea) 3. **Region is required but ignored**: Set `us-east-1` — MinIO ignores it but SDKs require it 4. **Public URL format**: `{apiUrl}/{bucketName}/path/to/file` 5. **Independent infrastructure**: Object Storage runs on separate infra from other services — accessible from Zerops and remotely over internet diff --git a/apps/docs/content/guides/production-checklist.mdx b/apps/docs/content/guides/production-checklist.mdx index 9f4faf559..599c726ef 100644 --- a/apps/docs/content/guides/production-checklist.mdx +++ b/apps/docs/content/guides/production-checklist.mdx @@ -70,6 +70,8 @@ Remove entirely or disable `enableSubdomainAccess`. Use VPN + pgAdmin/DBeaver lo |----------|----------| | User uploads | Object Storage (S3) | | Media files | Object Storage (S3) | +| SQLite / single-node stateful apps (Prometheus, Gitea) | Local Storage (persistent volume, survives deploys) | +| Shared filesystem state between services (certs, caches) | Local Storage | | Temp files | Container disk (OK) | | Build artifacts | Deploy via zerops.yaml | diff --git a/apps/docs/content/guides/shared-storage-integration.mdx b/apps/docs/content/guides/shared-storage-integration.mdx index 93196e161..5688d29d7 100644 --- a/apps/docs/content/guides/shared-storage-integration.mdx +++ b/apps/docs/content/guides/shared-storage-integration.mdx @@ -3,7 +3,9 @@ title: Shared Storage Integration on Zerops description: "Guide: Shared Storage Integration on Zerops" --- -Shared storage is a managed SeaweedFS volume mounted as a POSIX filesystem at `/mnt/` into one or more runtime services — for files that must be shared *between containers/services* (shared config, plugin directories, a common working set). It is mounted via the import.yaml `mount:` field; there is **no `zerops.yaml` mount**. For high-write workloads or user uploads, prefer Object Storage (S3) instead — shared storage is POSIX/NFS-style and not built for high-throughput churn. +**DEPRECATED**: Shared Storage is deprecated and will be replaced by a standalone SeaweedFS managed service mounted with `zsc shared-storage mount` in `initCommands`. For new projects, prefer **[Local Storage](/local-storage/overview)** (`run.volume` in zerops.yaml) for a persistent shared filesystem, or **Object Storage** for large or highly available data. Existing Shared Storage services keep working. + +Shared storage is a managed SeaweedFS volume mounted as a POSIX filesystem at `/mnt/` into one or more runtime services — for files that must be shared *between containers/services* (shared config, plugin directories, a common working set). It is mounted via the import.yaml `mount:` field; there is **no `zerops.yaml` mount** (do not confuse it with `run.volume`, which mounts a Local Storage volume). For high-write workloads or user uploads, prefer Object Storage (S3) instead — shared storage is POSIX/NFS-style and not built for high-throughput churn. ## Mounting — import.yaml `mount:` is the only config-file mechanism @@ -43,6 +45,6 @@ This registers the connection, but the FUSE mount materializes **only on the nex - **POSIX**: standard filesystem ops (with minor permission-setting limits). Filesystem operations are logged to runtime logs tagged `zerops-mount-`. `df` can report misleading numbers — use the Zerops GUI for accurate storage metrics. - **No env vars**: shared storage exposes no connection variables — it's a filesystem, not a networked service. -## Shared storage vs object storage +## Shared storage vs local storage vs object storage -Use **shared storage** when you need a POSIX filesystem shared across services (shared config, plugin/extension directories, a common scratch area). Use **object storage** (S3/MinIO) for user uploads, media, and any high-throughput or write-heavy file operations — and for anything that must survive independent of any single service. Don't reach for shared storage as a generic uploads bucket. +Use **local storage** (`run.volume`) when you need a persistent POSIX filesystem — it is a real single-node local filesystem with correct locking and mmap semantics, so it also covers SQLite and other filesystem-based databases that are unsafe on shared storage. Use **shared storage** (deprecated) only for existing setups that need the filesystem replicated across nodes. Use **object storage** (S3/MinIO) for user uploads, media, and any high-throughput or write-heavy file operations — and for anything that must survive independent of any single service. Don't reach for shared storage as a generic uploads bucket. diff --git a/apps/docs/content/homepage.mdx b/apps/docs/content/homepage.mdx index 7fa5613a9..b37ed6c6d 100644 --- a/apps/docs/content/homepage.mdx +++ b/apps/docs/content/homepage.mdx @@ -58,7 +58,8 @@ export const databases = [ export const storages = [ { name: "Object storage", link: "/object-storage/overview", icon: }, - { name: "Shared storage", link: "/shared-storage/overview", icon: }, + { name: "Local storage", link: "/local-storage/overview", icon: }, + { name: "Shared storage", link: "/shared-storage/overview", icon: }, ]
@@ -90,7 +91,7 @@ items={databases} /> ### Storages -Fully managed S3 compatible storage running on a separate infrastructure and persistent disk that can be mounted to multiple services. +Fully managed S3 compatible storage running on a separate infrastructure and persistent disk volumes that can be mounted to multiple services. diff --git a/apps/docs/content/local-storage/how-to/connect.mdx b/apps/docs/content/local-storage/how-to/connect.mdx new file mode 100644 index 000000000..482541a3d --- /dev/null +++ b/apps/docs/content/local-storage/how-to/connect.mdx @@ -0,0 +1,76 @@ +--- +title: Mount Local Storage to a service +description: Learn how to mount a Local Storage volume into runtime services with the zerops.yaml volume field and how the mount behaves. +--- + +Runtime services mount a Local Storage volume through the `volume` field in `zerops.yaml`. The mount is part of the service's runtime configuration, so it is applied by a deploy. + +## The volume field + +```yaml title="zerops.yaml" +zerops: + - setup: app + run: + base: nodejs@22 + volume: + hostname: vol # hostname of the Local Storage service + mountPath: /srv/data # optional, defaults to /mnt/{hostname} + readOnly: false # optional, defaults to false +``` + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldRequiredDescription
hostnameyesHostname of the Local Storage service in the same project.
mountPathnoAbsolute path the volume is mounted to inside the runtime containers. Defaults to /mnt/{hostname}. System directories (/etc, /var, /var/www, /tmp, ...) are rejected; their subdirectories are allowed.
readOnlynoMounts the volume read-only. Defaults to false. Use it for the "one writer, many readers" pattern and to protect data from accidental writes.
+ +The minimal configuration is just the hostname: + +```yaml +run: + volume: + hostname: vol +``` + +The referenced service must exist in the project and must be a Local Storage service, otherwise the deploy fails with a validation error. + +## How the mount behaves + +- The content is shared among **all containers** of the connected runtime service, and among all other runtime services that mount the same volume +- The mount point is owned by the `zerops` user and group, so your application can read and write without sudo +- Writes are immediately visible to every other container — a real local filesystem, not a network mount (see [filesystem semantics](/local-storage/tech-details#filesystem-semantics)) +- The volume is mounted in runtime containers only, not during build and prepare phases +- A runtime service mounts at most **one** Local Storage volume + +:::caution All connected containers share one machine +Every container of every connected runtime service is placed on the same physical machine that holds the volume. This is what makes the shared local filesystem possible, but it ties all connected services to a single machine: a hardware failure affects them all at once, and horizontal scaling is limited by that machine's capacity. See [co-location and scheduling](/local-storage/tech-details#co-location-and-scheduling). +::: + +## Change or remove the mount + +The `volume` field is applied by a deploy. To change the mount path, toggle `readOnly`, or disconnect from the volume, edit or remove the `volume` field in `zerops.yaml` and deploy again. + +:::caution +A Local Storage service cannot be deleted while runtime services still mount its volume. Remove the `volume` field from their `zerops.yaml` and deploy them first. +::: diff --git a/apps/docs/content/local-storage/how-to/create.mdx b/apps/docs/content/local-storage/how-to/create.mdx new file mode 100644 index 000000000..a116fe2a5 --- /dev/null +++ b/apps/docs/content/local-storage/how-to/create.mdx @@ -0,0 +1,43 @@ +--- +title: Create Local Storage service +description: Learn how to create a Local Storage service you can mount into your runtime services in Zerops. +--- + +## Create Using Import YAML + +```yaml title="zerops-import.yaml" +services: + - # Local Storage service + hostname: vol + type: local-storage:single +``` + +Import the file with the [zCLI](/references/cli): + +```sh +zcli project service-import zerops-import.yaml +``` + +Local Storage runs in a single container mode only — there is no highly available mode. Read the [availability trade-offs](/local-storage/tech-details#availability-and-failure-behavior) before you store critical data on it; automated [backups](/local-storage/how-to/manage#backups) are enabled by default and strongly recommended. + +To mount the volume into a runtime service, add the `volume` field to the runtime service's `zerops.yaml`. See [Mount to a service](/local-storage/how-to/connect). + +## Create Using Zerops GUI + +Go to your project dashboard and choose **Add new service** in the left menu in the **Services** block, then add a new **Local Storage** service. + +### Set a Hostname + +Enter a unique service identifier like "vol", "data" etc. Runtime services reference the volume by this hostname in their `zerops.yaml`. + +- Maximum 25 characters +- Must contain only lowercase ASCII letters (a-z) or numbers (0-9) +- Must be unique within the project + +:::note +The hostname is fixed after the service is created. It can't be changed later. +::: + +### Set Auto Scaling Configuration + +Configure vertical auto scaling parameters to control resource allocation and costs. The **maximum disk size is the capacity of the volume**: the volume can grow up to the configured disk maximum, and what you actually store is billed as the service's disk usage. diff --git a/apps/docs/content/local-storage/how-to/manage.mdx b/apps/docs/content/local-storage/how-to/manage.mdx new file mode 100644 index 000000000..e27d4d9d4 --- /dev/null +++ b/apps/docs/content/local-storage/how-to/manage.mdx @@ -0,0 +1,55 @@ +--- +title: Manage and back up Local Storage +description: Learn how to inspect a Local Storage volume over SSH and web shell, and how to back up and restore your data in Zerops. +--- + +Unlike other managed services, Local Storage is meant to be worked with directly: you can open a shell in the service's own container to inspect and modify the volume contents, and Zerops backs the volume up automatically. + +## Access the volume directly + +The Local Storage service runs one maintenance container with the volume mounted at `/data`, owned by the `zerops` user and group. You can access it like a runtime container: + +- **Web shell and file browser**: open the service detail page in the Zerops GUI and use the built-in terminal or file browser +- **SSH**: connect through the [Zerops VPN](/references/networking/vpn) and [SSH](/references/networking/ssh) into the container + +Everything you change under `/data` is immediately visible to all runtime services that [mount the volume](/local-storage/how-to/connect) — the maintenance container is just another view of the same filesystem. + +:::note +`/data` is the mount path inside the Local Storage container itself. Runtime services see the volume at their own configured `mountPath` (default `/mnt/{hostname}`). +::: + +## Backups + +Zerops provides automated data backup for Local Storage services with full encryption. Backups are enabled by default and strongly recommended: the volume is [not replicated](/local-storage/tech-details#availability-and-failure-behavior), so on a hardware failure they may be the only copy of your data. + +For general backup information including configuration, scheduling, retention, tagging, quotas, and CLI tools, see the [Zerops Backups](/features/backup) documentation. + +### Backup format + +- **Format**: `.tar.gz` (archive of the volume contents) +- **Content**: the entire volume (`/data` in the maintenance container) +- **Storage**: encrypted and stored in isolated object storage + +:::caution Backups are taken from the live filesystem +The archive is created while the volume stays mounted and writable, so files that are being written at that moment can be captured mid-write. For databases like SQLite this can produce an archive that does not restore cleanly. For guaranteed-consistent backups of a database, pause writes during the backup or use the database's own backup mechanism (e.g. `sqlite3 .backup` / `VACUUM INTO`) to produce a snapshot file the archive can pick up. +::: + +### Restoring backups + +1. Download the backup file (`.tar.gz`) from the Zerops UI. +2. Transfer the archive into the Local Storage container (or any runtime service that mounts the volume), for example over the [Zerops VPN](/references/networking/vpn). +3. Extract the archive into the volume: + +```sh +# in the Local Storage container +tar -xzf backup.tar.gz -C /data + +# or in a connected runtime container +tar -xzf backup.tar.gz -C /mnt/ +``` + +### Best practices + +- Regularly clean up unnecessary files to reduce backup size +- Create manual backups with protected tags before major file operations or migrations +- Test your restore process periodically to ensure data integrity diff --git a/apps/docs/content/local-storage/overview.mdx b/apps/docs/content/local-storage/overview.mdx new file mode 100644 index 000000000..bda613076 --- /dev/null +++ b/apps/docs/content/local-storage/overview.mdx @@ -0,0 +1,170 @@ +--- +title: Local Storage on Zerops +description: Managed persistent disk volume on Zerops. A single-machine POSIX filesystem with full locking and mmap semantics, mounted into your runtime services. +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +Zerops **Local Storage** is a managed service that owns a persistent, locally-attached disk volume. Runtime services in the same project mount the volume to a directory of their choosing, and every container sees the same files through a real local filesystem — no network filesystem in between. + +Because all connected containers run on the same physical machine and share one kernel, the volume behaves like a single local disk: file locking (`flock`, `fcntl`) works correctly across containers, memory-mapped files stay coherent, and a write in one container is immediately visible everywhere else. This is what makes SQLite (including WAL mode), Prometheus TSDB, and other filesystem-based databases safe on Local Storage — workloads that must never run on a network filesystem. See [Technical details](/local-storage/tech-details) for the full semantics. + +## Quick start + +Add a Local Storage service to your project: + +```yaml title="zerops-import.yaml" +services: + - hostname: vol + type: local-storage:single + + - hostname: app + type: nodejs@22 + buildFromGit: https://github.com/myorg/myapp +``` + +Then mount it in the runtime service's `zerops.yaml`: + +```yaml title="zerops.yaml" +zerops: + - setup: app + run: + base: nodejs@22 + volume: + hostname: vol +``` + +After the next deploy, the volume is mounted at `/mnt/vol` in all containers of the `app` service. See [Mount to a service](/local-storage/how-to/connect) for the full `volume` configuration including a custom mount path and read-only mounts. + +## Use cases + +Local Storage is a good fit for: + +- **SQLite and other embedded databases**: full locking and mmap coherence make SQLite safe, including WAL mode with multiple connecting containers (a single writer is still recommended) +- **Single-node stateful apps**: Prometheus, Gitea, and similar applications that keep their state in a local data directory +- **Sharing filesystem state**: certificates, caches, and other files shared across containers and services within a project, with immediate visibility of writes +- **Anything that needs a real local filesystem**: workloads that break on network filesystems because they rely on locking, mmap, inotify, or atomic renames + +:::caution Not highly available +The volume lives on a single physical machine, together with every runtime service that mounts it. If that hardware fails, or when maintenance requires moving workloads elsewhere, Zerops moves the volume to a healthy server and every connected runtime service goes through a small outage — stop, move, start. Recovering the volume and its data is not guaranteed. + +Automated [backups](/local-storage/how-to/manage#backups) are enabled by default and strongly recommended. +::: + +## Choosing a storage type + +The first word of each storage type names its access model: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ServiceAccess modelSemanticsHA
Object StorageS3 API over the networkObject semantics; best price and durability for uploads, media, and backupsYes
Shared Storage (deprecated)Network filesystemPOSIX-like with network filesystem caveats (per-mount locks, write amplification)Yes
Local StorageLocally attached disk, single machineFull single-kernel POSIX: locking, mmap, inotify across all connected containersNo
+ +Local Storage trades high availability for correctness and speed: it is the only storage type where lock-dependent workloads like databases are safe. + +## Key trade-offs + +- **Co-location**: all containers of every connected runtime service are placed on the same physical machine as the volume. Connecting a volume therefore ties the runtime service itself to that machine — a hardware failure affects all connected services at once, and horizontal scaling is limited by the capacity of that machine. +- **One volume per runtime service**: a runtime service mounts at most one Local Storage volume. Multiple runtime services can mount the same volume. +- The volume is mounted in runtime containers only — it is not available during build and prepare phases. +- Single container mode only; there is no HA mode. + +## Next steps + + + +## Need help? + +Stuck, or want to share what you built? Our core team and community are on Discord. + + diff --git a/apps/docs/content/local-storage/tech-details.mdx b/apps/docs/content/local-storage/tech-details.mdx new file mode 100644 index 000000000..2ee877200 --- /dev/null +++ b/apps/docs/content/local-storage/tech-details.mdx @@ -0,0 +1,55 @@ +--- +title: Local Storage Technical Details +description: Explore the filesystem semantics, co-location model, and failure behavior of Zerops Local Storage. +--- + +Zerops Local Storage is a persistent filesystem volume managed by the platform on a single physical machine, attached natively into every connected container. There is no network filesystem layer and no FUSE process — the containers see the volume as a local disk. + +## Architecture + +A Local Storage service consists of: + +- **A persistent volume**: a filesystem volume that holds your data. It exists independently of any container and survives container replacement. +- **A maintenance container**: a small always-on container with the volume mounted at `/data`. It gives the service its hostname, carries [SSH and web shell access](/local-storage/how-to/manage#access-the-volume-directly), and is the source of [backups](/local-storage/how-to/manage#backups). It never runs user code. + +Runtime services that [mount the volume](/local-storage/how-to/connect) get it attached directly into their containers at their configured mount path. + +## Inside the Container + +The volume appears as a regular kernel mount of a local filesystem. There is no FUSE daemon and no network client involved, so no extra process consumes the container's memory and no file operation pays a network round trip. + +- **`df` is accurate**: the reported size is the volume's capacity and the reported usage is what is actually stored +- **Ownership is consistent across containers**: the `zerops` user in one container is the `zerops` user in every other, so permissions behave exactly as they would for processes on a single machine +- **Extended attributes and POSIX ACLs** are supported; filenames are case-sensitive + +## Filesystem Semantics + +All connected containers run on the same physical machine and share one kernel, so every mount is a view of the same local filesystem. This gives you full single-kernel POSIX semantics across containers — the properties that network filesystems cannot provide: + +- **Advisory locking works across containers**: `flock` and `fcntl` locks are enforced by the shared kernel, so a lock held in one container is visible in all others +- **mmap coherence**: memory-mapped files stay coherent across containers. This is what makes SQLite in WAL mode safe with multiple connecting containers — WAL coordinates through an mmap'd shared-memory file, which is why [SQLite's own documentation ↗](https://sqlite.org/wal.html) states that "WAL does not work over a network filesystem". All containers mounting a Local Storage volume share one kernel, so they count as the same host +- **Unified page cache**: a write in one container is immediately visible to reads in another, with no close-to-open consistency window +- **Atomic rename and `O_APPEND`** behave exactly as on a local disk +- **inotify propagates across containers**: file watchers in one container see events triggered from another + +This is why filesystem-based databases (SQLite, Prometheus TSDB) are safe on Local Storage while they are explicitly unsafe on [Shared Storage](/shared-storage/overview#use-cases) or any other network filesystem. + +:::note +Even though locking is fully correct, a single-writer setup remains the most robust pattern for SQLite and similar databases. Use the [`readOnly` mount option](/local-storage/how-to/connect#the-volume-field) to enforce it. +::: + +## Co-location and Scheduling + +The volume is locally attached, so every container that mounts it must run on the machine that holds it. Zerops enforces this automatically: + +- All containers of all connected runtime services are scheduled onto the volume's machine +- Horizontal scaling of connected runtime services keeps working, but is limited by the free capacity of that machine +- Connecting a volume ties the runtime service itself to a single machine: you trade away the runtime's resilience to hardware failure, not just the volume's + +## Availability and Failure Behavior + +Local Storage is **not highly available** — the volume exists once, on one machine, with no replication. + +The volume lives on a single physical machine, together with every runtime service that mounts it. If that hardware fails, or when maintenance requires moving workloads elsewhere, Zerops moves the volume to a healthy server and every connected runtime service goes through a small outage — stop, move, start. Recovering the volume and its data is not guaranteed. + +[Backups](/local-storage/how-to/manage#backups) are enabled by default and strongly recommended. diff --git a/apps/docs/content/nginx/how-to/customize-runtime.mdx b/apps/docs/content/nginx/how-to/customize-runtime.mdx index af1066cac..15d00e479 100644 --- a/apps/docs/content/nginx/how-to/customize-runtime.mdx +++ b/apps/docs/content/nginx/how-to/customize-runtime.mdx @@ -55,7 +55,7 @@ Zerops caches custom runtime images to optimize deployment times. Learn about [c For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). :::warning -Shared storage mounts are not available during the runtime prepare phase. +Shared storage mounts and Local Storage volumes are not available during the runtime prepare phase. ::: ## Troubleshooting diff --git a/apps/docs/content/references/import-yaml/type-list.mdx b/apps/docs/content/references/import-yaml/type-list.mdx index 09c1b4bd8..905fd7529 100644 --- a/apps/docs/content/references/import-yaml/type-list.mdx +++ b/apps/docs/content/references/import-yaml/type-list.mdx @@ -215,7 +215,11 @@ Versions listed on the same line are aliases of the same underlying version. - Shared storage + Local storage + + + + Shared storage (deprecated) diff --git a/apps/docs/content/references/import.mdx b/apps/docs/content/references/import.mdx index e2d9d5259..8aaae0813 100644 --- a/apps/docs/content/references/import.mdx +++ b/apps/docs/content/references/import.mdx @@ -283,7 +283,7 @@ services: minContainers: 2 # Minimum number of containers (default: 1, max: 10) maxContainers: 6 # Maximum number of containers (max: 10) - # Shared storage + # Shared storage (deprecated, see Local Storage) mount: # List of shared storage services to mount - teststorage1 @@ -665,6 +665,10 @@ The `minContainers` and `maxContainers` parameters allow you to define the minim ### Service Mount Shared Storage +:::warning Deprecated +[Shared Storage](/shared-storage/overview) is deprecated, and the `mount:` field with it. For a persistent filesystem shared between services, use a [Local Storage](/local-storage/overview) service, mounted through the [`volume` field in zerops.yaml](/zerops-yaml/specification#volume-) instead of an import-level field. +::: + The mount shared storage configuration defines which shared storage services should be mounted to the service. diff --git a/apps/docs/content/shared-storage/how-to/connect.mdx b/apps/docs/content/shared-storage/how-to/connect.mdx index faf05110b..7c79e2e9e 100644 --- a/apps/docs/content/shared-storage/how-to/connect.mdx +++ b/apps/docs/content/shared-storage/how-to/connect.mdx @@ -3,6 +3,10 @@ title: Connect & mount shared storage description: Learn how to connect shared storage to runtime services in Zerops and how the mount behaves. --- +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: + This page covers how to connect an existing shared storage to runtime services, how to disconnect it, and how the mount behaves inside your containers. ## How the mount behaves diff --git a/apps/docs/content/shared-storage/how-to/create.mdx b/apps/docs/content/shared-storage/how-to/create.mdx index 921aafdca..30b704cfe 100644 --- a/apps/docs/content/shared-storage/how-to/create.mdx +++ b/apps/docs/content/shared-storage/how-to/create.mdx @@ -6,6 +6,10 @@ description: Learn how to create shared storage which you can use with your othe import GroupCards from '@site/src/components/GroupCards'; import Video from '@site/src/components/Video'; +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: + ## Create Using Zerops GUI Go to your project dashboard and choose **Add new service** in the left menu in the **Services** block. Then add a new Shared Storage service: diff --git a/apps/docs/content/shared-storage/how-to/manage.mdx b/apps/docs/content/shared-storage/how-to/manage.mdx index c160ae3b0..0c426d1a8 100644 --- a/apps/docs/content/shared-storage/how-to/manage.mdx +++ b/apps/docs/content/shared-storage/how-to/manage.mdx @@ -3,6 +3,10 @@ title: Manage and back up Shared Storage description: Learn how to manage, monitor, back up, and restore your Shared Storage in Zerops. --- +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: + Zerops Shared Storage provides several web interfaces to manage, monitor, and troubleshoot your storage, and automated encrypted backups of your data. ## Web interfaces diff --git a/apps/docs/content/shared-storage/overview.mdx b/apps/docs/content/shared-storage/overview.mdx index f12cfdde0..9fc926049 100644 --- a/apps/docs/content/shared-storage/overview.mdx +++ b/apps/docs/content/shared-storage/overview.mdx @@ -6,6 +6,15 @@ description: Managed shared disk storage on Zerops. A POSIX-compatible filesyste import DocCardList from '@theme/DocCardList'; import Icons from '@theme/Icon'; +:::warning Shared Storage is deprecated +Shared Storage in its current form — a managed SeaweedFS cluster connected through the import-level `mount:` field — is deprecated. It will be replaced by a standalone SeaweedFS managed service that runtime services mount themselves with [`zsc shared-storage mount`](/references/zsc#shared-storage) in their `initCommands`. Existing Shared Storage services keep working for now, but don't build new projects on it. + +For new projects, choose by workload: + +- A **persistent filesystem shared between services** — use [Local Storage](/local-storage/overview). It is a real local filesystem with correct locking, so it also covers the workloads Shared Storage was never safe for (SQLite and other filesystem-based databases). +- **Large or highly available data** — use [Object Storage](/object-storage/overview). +::: + Zerops **Shared Storage** is a managed disk volume that mounts as a POSIX-compatible filesystem into your runtime services. Files written by one container are immediately visible to every other container that mounts the same storage, whether they belong to the same service or to different services in the project. Under the hood it runs [SeaweedFS ↗](https://github.com/seaweedfs/seaweedfs), a distributed filesystem optimized for high-volume storage. See [Technical details](/shared-storage/tech-details) for the architecture. @@ -44,7 +53,7 @@ Do **not** run databases on Shared Storage. This includes SQLite, Prometheus TSD - File locks are enforced **per mount only**: a lock held in one container does not prevent another container from writing to the same file, which leads to data corruption. - The underlying storage engine is an append-only chunk store: every modification writes new chunks, so the frequent small writes typical for databases cause heavy write amplification. -Use [managed databases](/postgresql/overview) instead. For storing database *backups*, prefer [object storage](/object-storage/overview): it is cheaper and better suited for write-once files. +Use [managed databases](/postgresql/overview) instead. For SQLite and other filesystem-based databases, use [Local Storage](/local-storage/overview) — a local filesystem with correct locking where these workloads are safe. For storing database *backups*, prefer [object storage](/object-storage/overview): it is cheaper and better suited for write-once files. ::: ## Deployment modes diff --git a/apps/docs/content/shared-storage/tech-details.mdx b/apps/docs/content/shared-storage/tech-details.mdx index 0736a4706..d7f256e84 100644 --- a/apps/docs/content/shared-storage/tech-details.mdx +++ b/apps/docs/content/shared-storage/tech-details.mdx @@ -5,6 +5,10 @@ description: Explore the technical architecture, storage engine behavior, limits import ResourceTable from '/src/components/ResourceTable'; +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: + Zerops Shared Storage is built on [SeaweedFS ↗](https://github.com/seaweedfs/seaweedfs), a distributed filesystem optimized for high-volume storage with efficient retrieval. ## Architecture diff --git a/apps/docs/content/ubuntu/how-to/customize-runtime.mdx b/apps/docs/content/ubuntu/how-to/customize-runtime.mdx index ff7aea29b..dd40c5815 100644 --- a/apps/docs/content/ubuntu/how-to/customize-runtime.mdx +++ b/apps/docs/content/ubuntu/how-to/customize-runtime.mdx @@ -91,7 +91,7 @@ Zerops caches custom runtime images to optimize deployment times. Learn about [c For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). :::warning -Shared storage mounts are not available during the runtime prepare phase. +Shared storage mounts and Local Storage volumes are not available during the runtime prepare phase. ::: ## Troubleshooting diff --git a/apps/docs/content/zerops-yaml/specification.mdx b/apps/docs/content/zerops-yaml/specification.mdx index 93c1909ef..b7a041a6a 100644 --- a/apps/docs/content/zerops-yaml/specification.mdx +++ b/apps/docs/content/zerops-yaml/specification.mdx @@ -661,6 +661,33 @@ run: Setup cron jobs. See [examples](/zerops-yaml/cron). +### volume + +Mounts a [Local Storage](/local-storage/overview) service's volume into the runtime containers. + +```yaml +run: + volume: + hostname: vol # hostname of the Local Storage service + mountPath: /srv/data # optional, defaults to /mnt/{hostname} + readOnly: false # optional, defaults to false +``` + +Available parameters: + +#### hostname +Hostname of the Local Storage service in the same project. + +#### mountPath +Absolute path the volume is mounted to inside the runtime containers. Defaults to `/mnt/{hostname}`. System directories (`/etc`, `/var`, `/var/www`, `/tmp`, ...) are rejected; their subdirectories are allowed. + +#### readOnly +Mounts the volume read-only. Defaults to `false`. + +:::caution +All containers of a service that mounts a volume are placed on the physical machine holding the volume, together with the containers of every other service mounting it. A service can mount at most one volume. See [Mount Local Storage to a service](/local-storage/how-to/connect) for details. +::: + :::note For more detailed information on specific configurations, refer to the runtime-specific guides linked at the beginning of this document. ::: diff --git a/apps/docs/sidebars.js b/apps/docs/sidebars.js index 9df069104..0ada3e269 100644 --- a/apps/docs/sidebars.js +++ b/apps/docs/sidebars.js @@ -501,12 +501,21 @@ module.exports = { }, className: 'homepage-sidebar-item service-sidebar-item', }, + { + type: 'ref', + id: 'local-storage/overview', + label: 'Local Storage', + customProps: { + sidebar_icon: 'circle-stack', + }, + className: 'homepage-sidebar-item service-sidebar-item', + }, { type: 'ref', id: 'shared-storage/overview', label: 'Shared Storage', customProps: { - sidebar_icon: 'server', + sidebar_icon: 'servers-connected', }, className: 'homepage-sidebar-item service-sidebar-item', }, @@ -2736,6 +2745,61 @@ module.exports = { }, }, ], + localstorage: [ + { + type: 'ref', + id: 'homepage', + label: 'Back to home', + customProps: { + sidebar_is_back_link: true, + sidebar_icon: 'back-arrow', + }, + }, + { + type: 'doc', + id: 'local-storage/overview', + label: 'Local Storage overview', + customProps: { + sidebar_is_title: true, + sidebar_icon: 'circle-stack', + }, + }, + { + type: 'category', + label: 'How-to', + collapsible: false, + customProps: { + sidebar_is_group_headline: true, + sidebar_icon: 'academic-cap-solid', + }, + items: [ + { + type: 'doc', + id: 'local-storage/how-to/create', + label: 'Create Local Storage', + }, + { + type: 'doc', + id: 'local-storage/how-to/connect', + label: 'Mount to a service', + }, + { + type: 'doc', + id: 'local-storage/how-to/manage', + label: 'Manage & backups', + }, + ], + }, + { + type: 'doc', + id: 'local-storage/tech-details', + label: 'Technical details', + customProps: { + sidebar_is_title: true, + sidebar_icon: 'document-text', + }, + }, + ], sharedstorage: [ { type: 'ref', @@ -2752,7 +2816,7 @@ module.exports = { label: 'Shared storage overview', customProps: { sidebar_is_title: true, - sidebar_icon: 'server', + sidebar_icon: 'servers-connected', }, }, { diff --git a/apps/docs/src/components/content/customize-runtime.mdx b/apps/docs/src/components/content/customize-runtime.mdx index 5be234862..092c41b81 100644 --- a/apps/docs/src/components/content/customize-runtime.mdx +++ b/apps/docs/src/components/content/customize-runtime.mdx @@ -50,7 +50,7 @@ Zerops caches custom runtime images to optimize deployment times. Learn about [c For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). :::warning -Shared storage mounts are not available during the runtime prepare phase. +Shared storage mounts and Local Storage volumes are not available during the runtime prepare phase. ::: ## Troubleshooting diff --git a/apps/docs/src/components/content/shared-storage.mdx b/apps/docs/src/components/content/shared-storage.mdx index 2b2062c1f..3ab3aa9d1 100644 --- a/apps/docs/src/components/content/shared-storage.mdx +++ b/apps/docs/src/components/content/shared-storage.mdx @@ -25,6 +25,10 @@ services: mount: - teststorage`} /> +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, mount a [Local Storage](/local-storage/overview) volume through the [`volume` field in zerops.yaml](/zerops-yaml/specification#volume-) instead, or use [Object Storage](/object-storage/overview) for large or highly available data. +::: + Zerops provides [shared storage service](/shared-storage/overview) that can be connected to runtime services. Shared storage enables your service to share files between all containers of the same service or even among containers of different runtime services. ## Connect shared storage in Zerops GUI diff --git a/apps/docs/src/theme/Icon/ServersConnected/index.tsx b/apps/docs/src/theme/Icon/ServersConnected/index.tsx new file mode 100644 index 000000000..33a6adfc2 --- /dev/null +++ b/apps/docs/src/theme/Icon/ServersConnected/index.tsx @@ -0,0 +1,30 @@ +import { IconProps } from '@medusajs/icons/dist/types'; +import React from 'react'; + +const IconServersConnected = ({ color = 'currentColor', ...props }: IconProps) => { + return ( + + + + + + + + + + + + ); +}; + +export default IconServersConnected; diff --git a/apps/docs/src/theme/Icon/index.tsx b/apps/docs/src/theme/Icon/index.tsx index d69ec8adc..3718574ed 100644 --- a/apps/docs/src/theme/Icon/index.tsx +++ b/apps/docs/src/theme/Icon/index.tsx @@ -165,6 +165,7 @@ import IconVPN from './Vpn'; import IconBalancer from './Balancer'; import IconDns from './Dns'; import IconInternalAccess from './InternalAccess'; +import IconServersConnected from './ServersConnected'; export default { 'academic-cap-solid': AcademicCapSolid, @@ -263,6 +264,7 @@ export default { 'server-solid': ServerSolid, 'server-stack': ServerStack, 'server-stack-solid': ServerStackSolid, + 'servers-connected': IconServersConnected, 'shopping-cart': ShoppingCart, 'shopping-cart-solid': ShoppingCartSolid, sidebar: SidebarLeft, diff --git a/apps/docs/static/data.json b/apps/docs/static/data.json index a1e48e871..4900ca92b 100644 --- a/apps/docs/static/data.json +++ b/apps/docs/static/data.json @@ -327,6 +327,9 @@ "sharedstorage": { "import": [["shared-storage:single", "shared-storage:ha"]] }, + "localstorage": { + "import": [["local-storage:single"]] + }, "objectstorage": { "import": [["object-storage"]] } diff --git a/apps/docs/static/llms-full.txt b/apps/docs/static/llms-full.txt index 907b0080d..bb158072c 100644 --- a/apps/docs/static/llms-full.txt +++ b/apps/docs/static/llms-full.txt @@ -1,327 +1,351 @@ ---------------------------------------- -# Alpine > How To > Build Pipeline +# Homepage -Zerops provides a customizable build and runtime environment for your Alpine application. +export const runtimes = [ + { name: "Node.js", link: "/nodejs/overview", icon: }, + { name: "PHP", link: "/php/overview", icon: }, + { name: "Python", link: "/python/overview", icon: }, + { name: "Go", link: "/go/overview", icon: }, + { name: ".NET", link: "/dotnet/overview", icon: }, + { name: "Rust", link: "/rust/overview", icon: }, + { name: "Java", link: "/java/overview", icon: }, + { name: "Deno", link: "/deno/overview", icon: }, + { name: "Bun", link: "/bun/overview", icon: }, + { name: "Elixir", link: "/elixir/overview", icon: }, + { name: "Gleam", link: "/gleam/overview", icon: }, + { name: "Ruby", link: "/ruby/overview", icon: }, + { name: "Nginx", link: "/nginx/overview", icon: }, + { name: "Static", link: "/static/overview", icon: }, +] -## Add zerops.yaml to your repository +export const containers = [ + { name: "Ubuntu", link: "/ubuntu/overview", icon: }, + { name: "Alpine", link: "/alpine/overview", icon: }, + { name: "Docker", link: "/docker/overview", icon: }, +] -Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: +export const databases = [ + { name: "PostgreSQL", link: "/postgresql/overview", icon: }, + { name: "MariaDB", link: "/mariadb/overview", icon: }, + { name: "Valkey", link: "/valkey/overview", icon: }, + { name: "Elasticsearch", link: "/elasticsearch/overview", icon: }, + { name: "Typesense", link: "/typesense/overview", icon: }, + { name: "Meilisearch", link: "/meilisearch/overview", icon: }, + { name: "Qdrant", link: "/qdrant/overview", icon: }, + { name: "NATS", link: "/nats/overview", icon: }, + { name: "Kafka", link: "/kafka/overview", icon: }, + { name: "ClickHouse", link: "/clickhouse/overview", icon: }, + { name: "KeyDB", link: "/keydb/overview", icon: }, +] -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: alpine@3.20 +export const storages = [ + { name: "Object storage", link: "/object-storage/overview", icon: }, + { name: "Local storage", link: "/local-storage/overview", icon: }, + { name: "Shared storage", link: "/shared-storage/overview", icon: }, +] - # OPTIONAL. Customize the build environment by installing additional packages - # or tools to the base build environment. - prepareCommands: - - sudo apk add --no-cache something - - curl something else +
- # OPTIONAL. Build your application - buildCommands: - - +Zerops is a **developer-first Platform-as-a-Service**, running on bare metal, with every part built from scratch. Zerops aims to be the perfect mix of **developer experience**, **flexibility**, **scalability** and **affordability**, making it a great fit for applications of any size, complexity and traffic. - # REQUIRED. Select which files / folders to deploy after - # the build has successfully finished - deployFiles: app +## Natively supported services - # OPTIONAL. Which files / folders you want to cache for the next build. - # Next builds will be faster when the cache is used. - cache: some_file +### Runtimes & web servers - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: alpine@3.20 +For these services Zerops provides pre-prepared build and runtime images and flexible pipeline that allows you to modify them and build your applications. - # OPTIONAL. Sets the internal port(s) your app listens on: - ports: - # port number - - port: 8080 +### Linux containers & VMs - # OPTIONAL. Customize the runtime Alpine environment by installing additional - # dependencies to the base Alpine runtime environment. - prepareCommands: - - sudo apk add --no-cache something - - curl something else +These services can be deployed either as plain Linux containers or using Docker images, giving you flexibility to run any application or service. - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Alpine application is started. - initCommands: - - rm -rf ./cache +### Databases, search engines & message brokers - # OPTIONAL. Your Alpine application start command - start: ./app -``` +These services are fully managed by Zerops and offered in highly available and single container modes. -The top-level element is always `zerops`. +### Storages -### Setup +Fully managed S3 compatible storage running on a separate infrastructure and persistent disk volumes that can be mounted to multiple services. -The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. -Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: +## Quicklinks -```yaml -zerops: - # definition for app service - - setup: app - # optional - build: ... - # optional - deploy: ... - # required - run: ... +- [zCLI](/references/cli) +- [zerops.yaml](/zerops-yaml/specification) +- [Import YAML](/references/import) - # definition for api service - - setup: api - # optional - build: ... - # optional - deploy: ... - # required - run: ... -``` +## Feature highlights -Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. +Four concepts that play together to make Zerops developer-first and live up to the claim "no matter the size or environment". -## Build pipeline configuration +### ➡️ Custom dedicated infrastructure deployed with each project -### base +Zerops is made of three levels: **project** -> **service** -> **container**. For each project Zerops deploys dedicated **core services**, these consist of: -_REQUIRED._ Sets the base technology for the build environment. +- **L3 balancer** with a firewall and unique IP addresses assigned to it, this serves as the main entry point from the internet, +- **Logger** and **Statistics** containers that gather logs and resource metrics from all services inside the project and allow for log forwarding +- **L7 load balancer** that handles and routes http traffic, SSL termination and SSL certificates -Following options are available for Alpine builds: +User services (which consist of one or more containers) inside the project share a private network created with VXLAN, have resources isolated with cgroups and can securely communicate with each other simply by using the hostname and ports and read and reference each other's environment variables. -- `alpine@3.23`, `alpine@latest` -- `alpine@3.22` -- `alpine@3.21` -- `alpine@3.20` -- `alpine@3.19` -- `alpine@3.18` -- `alpine@3.17` +:::tip[**What does this mean for you?**] -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: alpine@3.20 - ... -``` +You get a fully managed, professional infrastructure setup that will scale no matter how much traffic you get and deals with all the networking, balancing and security stuff, so you can just focus on your actual applications. -

- The base build environment contains {data.alpine.default}, [Zerops command line tool](/references/cli), `git` and `wget`. -

+[Read more about the project infrastructure](/features/infrastructure) -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. ::: -If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: +### ➡️ Granular resource configuration, autoscaling and high availability of services -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: - - alpine@3.20 - prepareCommands: - - zsc add nodejs@latest - ... -``` +Zerops has fully automatic horizontal and vertical scaling with configuration steps as small as 0.125 GB RAM and 1 CPU core. Your runtime services can go from a single container with 0.25 RAM and 1 CPU core to 10 containers each with 32 GB RAM and 10 CPU cores and then back in a matter of minutes. At the same time, all database and storage services are offered in well-crafted setups that go through performance optimizations while scaling and are available in both non-HA (single container) and high availability (multiple containers and balancers) modes. -See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). +:::tip[**What does this mean for you?**] -To customize your build environment use the [prepareCommands](#preparecommands) attribute. +You won't ever overprovision or underprovision your resources and your services will always have the exact resources they need. There won't be any cutting corners like sharing too few CPU cores between too many services. You will be able to rely on professional, reliable and highly available database setups with auto-repairing abilities that will scale along with your applications. + +[Read more about autoscaling and high availability](/features/scaling) -:::note -Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. ::: -### prepareCommands +### ➡️ Full Linux OS containers with a powerful, flexible build and deploy pipeline -_OPTIONAL._ Customizes the build environment by installing additional dependencies or tools to the base build environment. +Zerops uses Incus to create containers, which means that you get a full Linux OS, either Ubuntu or Alpine, depending on your choices. This provides the perfect middle ground between a containerized process (Docker) and a full-fledged VM (Proxmox). Zerops provides build and runtime bases for all the popular runtime technologies and a powerful and flexible pipeline that allows you to modify and cache both the build and runtime images. This circumvents the need for Docker registries. The pipeline can be triggered either automatically, by connecting the service with GitHub or GitLab repositories, or manually using our CLI - either for triggering from your machine, or from any existing CI/CD process. -The base build environment contains: +:::tip[**What does this mean for you?**] -- {data.alpine.default} -- [Zerops command line tool](/references/cli) -- `git` and `wget` +You get a built-in powerful and flexible pipeline to modify build and runtime images and deploy your code, without any downtime. It can be used standalone or easily plugged into any existing CI/CD process. -To install additional packages or tools add one or more prepare commands: +[Read more about the build and deploy pipeline](/features/pipeline) -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: alpine@3.20 +::: - # OPTIONAL. Customize the build environment by installing additional packages - # or tools to the base build environment. - prepareCommands: - - sudo apk add --no-cache something - - curl something else - ... -``` +### ➡️ Pricing model that doesn't get in the way of good development practices -When the first build is triggered, Zerops will +"Simple and predictable pricing"... is what others say and what we actually do. In Zerops, cost per hardware resource (CPU, RAM, Disk) is 3-5x cheaper than with popular alternatives. And there are no plans, no feature tiers, no fees for seats. PaaS is just hardware with a cherry and bow on top, so why would we charge you for anything else but hardware resources? -1. create a build container -2. download your application code from your repository -3. run the prepare commands in the defined order +:::tip[**What does this mean for you?**] -The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. +You get a powerful managed platform with all the best features unlocked for a price that's nearly on par with VPS. You can create as many environments as you need, even one for each developer working on a project, all with the same infrastructure as production, so they can utilize Zerops for their local development. No more "but it works on my machine". -:::note -These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. ::: +
-#### Command exit code -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/alpine/how-to/logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. +---------------------------------------- -#### Single or separated shell instances +# Zerops Yaml > Specification -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). -### buildCommands +export const languages = [ + { name: "Node.js", link: "/nodejs/how-to/build-pipeline" }, + { name: "PHP", link: "/php/how-to/build-pipeline" }, + { name: "Python", link: "/python/how-to/build-pipeline" }, + { name: "Go", link: "/go/how-to/build-pipeline" }, + { name: ".NET", link: "/dotnet/how-to/build-pipeline" }, + { name: "Rust", link: "/rust/how-to/build-pipeline" }, + { name: "Java", link: "/java/how-to/build-pipeline" }, + { name: "Deno", link: "/deno/how-to/build-pipeline" }, + { name: "Bun", link: "/bun/how-to/build-pipeline" }, + { name: "Elixir", link: "/elixir/how-to/build-pipeline" }, + { name: "Gleam", link: "/gleam/how-to/build-pipeline" }, + { name: "Nginx", link: "/nginx/how-to/build-pipeline" } +] -_OPTIONAL._ Defines build commands. +The `zerops.yaml` file is crucial for defining how Zerops should [build and deploy](/features/pipeline) your application. +Add the `zerops.yaml` file to the **root of your repository** and customize it to suit your application's needs. -```yaml +:::note Parameter Availability +Not all parameters are available for every service type. Most parameters work across different runtime services, but some are specific to certain service types (e.g., documentRoot for webserver services, routing for Static services). This documentation covers zerops.yaml configuration for runtime services. +::: + +--- + +## Basic Structure + +```yaml title="zerops.yaml" zerops: - # hostname of your service - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: alpine@3.20 - - # OPTIONAL. Build your application - buildCommands: - - - ... + # optional + build: ... + # optional + deploy: ... + # required + run: ... ``` -Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. +Multiple services can be defined in a single `zerops.yaml` (useful for monorepos): -Before the build commands are triggered the build container contains: +```yaml +zerops: + - setup: app + # optional + build: ... + # optional + deploy: ... + # required + run: ... -1. base environment defined by the [base](#base) attribute -2. optional customisation of the base environment defined in the [prepareCommands](#preparecommands) attribute -3. your application code + - setup: api + # optional + build: ... + # optional + deploy: ... + # required + run: ... +``` -For detailed information about build commands, refer to the documentation for your specific technology (e.g., [Node.js](/nodejs/how-to/build-pipeline), [Go](/go/how-to/build-pipeline), [Python](/python/how-to/build-pipeline), etc.). +Each service configuration requires a `run` section. Optional `build` and `deploy` sections can be added to further customize your process. -#### Run build commands as a single shell instance +## Service Configuration -Use following syntax to run all commands in the same environment context. For example, if one command changes the current directory, the next command continues in that directory. When one command creates an environment variable, the next command can access it. +### setup *[Required]* + +Contains the hostname of your service (must exist in Zerops). ```yaml -buildCommands: - - | - cd src - ./build.sh +setup: app ``` -#### Run build commands as separate shell instances +### extends *[Optional]* -When the following syntax is used, each command is triggered in a separate environment context. For example, each shell instance starts in the home directory again. When one command creates an environment variable, it won't be available for the next command. +The `extends` key allows you to inherit configuration from another service defined in the same `zerops.yaml` file. This is useful for creating environment-specific configurations while maintaining a common base. ```yaml -buildCommands: - - cd src - - ./build.sh +zerops: + - setup: base + build: + buildCommands: + - npm run build + deployFiles: ./dist + run: + start: npm start + + - setup: prod + extends: base + run: + envVariables: + NODE_ENV: production + + - setup: dev + extends: base + run: + envVariables: + NODE_ENV: development ``` -#### Command exit code +When using `extends`: +- The `extends` value must refer to another service's `setup` value in the same file +- The child service inherits all configuration from the base service +- Configuration is merged at the section level (`build`, `run`, `deploy`) +- You can override specific sections by redefining them -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/alpine/how-to/logs#build-log) to troubleshoot the error. +:::tip +Create a base service with common configuration and extend it for environment-specific services to keep your `zerops.yaml` file DRY (Don't Repeat Yourself). +::: -If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `buildCommands` are finished, the application build is completed and ready for the deploy phase. +## Build Configuration *[Optional]* -### deployFiles +### base *[Required]* -_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. +Sets the base technology for the build environment. [See available options](/zerops-yaml/base-list). ```yaml -# REQUIRED. Select which files / folders to deploy after -# the build has successfully finished -deployFiles: - - app +build: + base: nodejs@latest ``` -Determines files or folders produced by your build, which should be deployed to your runtime service containers. +You can specify multiple technologies: -The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. +```yaml +build: + base: + - nodejs@latest + prepareCommands: + - zsc add python@3.9 +``` -The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. +### os *[Optional]* -#### Examples +Sets the operating system for the build environment. Options: -Deploys a folder, and a file from the project root directory: +- `alpine` (default) +- `ubuntu` (default for ubuntu service) + +Current versions: + +- {data.alpine.default} +- {data.ubuntu.default} ```yaml -deployFiles: - - app - - file.txt +build: + os: ubuntu ``` -Deploys the whole content of the build container: +### prepareCommands *[Optional]* + +Customizes the build environment by installing additional dependencies or tools. ```yaml -deployFiles: . +build: + prepareCommands: + - sudo apt-get update + - sudo apt-get install -y some-package ``` -Deploys a folder, and a file in a defined path: +:::note +`build.prepareCommands` run in the `/home/zerops` directory. +::: + +### buildCommands *[Optional]* + +Defines the commands to build your application. ```yaml -deployFiles: - - ./path/to/file.txt - - ./path/to/dir/ +build: + buildCommands: + - npm install + - npm run build ``` -#### How to use a wildcard in the path - -Zerops supports the `~` character as a wildcard for one or more folders in the path. +:::note +`build.buildCommands` run in the `/build/source` directory. +::: -Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` +#### Running commands in a single shell instance: ```yaml -deployFiles: ./path/~/to/file.txt +buildCommands: + - | + npm install + npm run build ``` -Deploys all folders that are located in any path that begins with `/path/to/` +### deployFiles *[Required]* + +Specifies which files or folders to deploy after a successful build. ```yaml -deployFiles: ./path/to/~/ +build: + deployFiles: + - dist + - package.json + - node_modules ``` -Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` +The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. + +#### Using wildcards: + +Zerops supports the `~` character as a wildcard for one or more folders in the path. + +Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/`. ```yaml -deployFiles: ./path/~/to/ +deployFiles: ./path/~/to/file.txt ``` -:::note Example By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` -::: #### .deployignore @@ -358,4284 +382,3338 @@ This example above ignores `file.txt` in ANY directory named `src`, such as: `.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. ::: -### cache +### cache *[Optional]* -_OPTIONAL._ Defines which files or folders will be cached for the next build. +Defines which files or folders to cache for subsequent builds. ```yaml -# OPTIONAL. Which files / folders you want to cache for the next build. -# Next builds will be faster when the cache is used. -cache: file.txt +build: + cache: node_modules ``` -The cache attribute helps optimize build times by preserving specified files between builds. - -The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). +For more information, see our detailed [guide on build cache](/features/build-cache), complete with extensive examples. -Learn more about the [build cache system](/features/build-cache) in Zerops. +### addToRunPrepare *[Optional]* -### envVariables +Defines files or folders to be copied from the build container to the prepare runtime container. -_OPTIONAL._ Defines the environment variables for the build environment. +### envVariables *[Optional]* -Enter one or more env variables in following format: +Sets environment variables for the build environment. ```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - base: alpine@3.20 - … - - # OPTIONAL. Defines the env variables for the build environment: - envVariables: - MODE: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} +build: + envVariables: + DB_NAME: db + DB_HOST: db + DB_USER: db + DB_PASS: ${db_password} ``` -Read more about [environment variables](/alpine/how-to/env-variables) in Zerops. - -## Runtime configuration - -### base +:::info +The `yamlPreprocessor` option in your project & service import YAML allows you to generate random secret values, passwords, and public/private key pairs. For more information, see the [yamlPreprocessor](/references/import-yaml/pre-processor) page. +::: -_OPTIONAL._ Sets the base technology for the runtime environment. -If you don't specify the `run.base` attribute, Zerops keeps the current Alpine version for your runtime. +## Deploy Configuration *[Optional]* -Following options are available for Alpine builds: +### temporaryShutdown *[Optional]* -- `alpine@3.23`, `alpine@latest` -- `alpine@3.22` -- `alpine@3.21` -- `alpine@3.20` -- `alpine@3.19` -- `alpine@3.18` -- `alpine@3.17` +Controls the container replacement order during deployment. ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: alpine@3.20 - ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: alpine@3.20 - ... +deploy: + temporaryShutdown: true ``` -

- The base runtime environment contains {data.alpine.default}, Zerops command line tool, `git` and `wget`. -

+- Type: `boolean` +- Default: `false` -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. -::: +**When `false` (default):** New containers are started before old containers are removed, ensuring zero-downtime deployment. -If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: +**When `true`:** Old containers are removed before new containers are started, causing temporary downtime but using fewer resources during deployment. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: alpine@3.20 - ... +### readinessCheck *[Optional]* - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: - - alpine@3.20 - prepareCommands: - - zsc add nodejs@latest - ... -``` +Defines a readiness check for your application. Requires either `httpGet` object or `exec` object. -See the full list of supported [run base environments](/zerops-yaml/base-list). +```yaml +deploy: + readinessCheck: + # HTTP GET method example + httpGet: + port: 80 + path: /status + host: my-host.zerops + scheme: https -To customise your build environment use the `prepareCommands` attribute. + # Common parameters + failureTimeout: 60 + retryPeriod: 10 +``` -### ports +Readiness checks work similarly to [health checks](#healthcheck-) but are specifically for deployment. They verify if a new deployment is ready to receive traffic. -_OPTIONAL._ Specifies one or more internal ports on which your application will listen. +Available parameters: -Projects in Zerops represent a group of one or more services. Services can be of different types (runtime services, databases, message brokers, object storage, etc.). All services of the same project share a **dedicated private network**. To connect to a service within the same project, just use the service hostname and its internal port. +#### httpGet and exec +The `httpGet` and `exec` options work the same way as in [health checks](#healthcheck-). See that section for detailed parameter descriptions. -For example, to connect to an Alpine service with hostname = "app" and port = 8080 from another service of the same project, simply use `app:8080`. Read more about [how to access an Alpine service](/references/networking/internal-access#basic-service-communication). +#### Common parameters *[Optional]* +The following parameters can be used with either `httpGet` or `exec` readiness checks: -Each port has following attributes: +- **failureTimeout** - Time in seconds until container is marked as failed. +- **retryPeriod** - Time interval in seconds between readiness check attempts (equivalent to `execPeriod` in health checks). -
- - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port number. You can set any port number between 10 and 65435. Ports outside this interval are reserved for internal Zerops systems.
protocolOptional. Defines the protocol. Allowed values are TCP or UDP. Default value is TCP.
httpSupportOptional. httpSupport = true is the default setting for TCP protocol. Set httpSupport = false if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). httpSupport = true is available only in combination with the TCP protocol.
+:::tip +Unlike health checks which run continuously, readiness checks only run during deployments to determine when your application is ready to accept traffic. +::: -### prepareCommands +## Runtime Configuration *[Required]* -_OPTIONAL._ Customises the Alpine runtime environment by installing additional dependencies or tools to the runtime base environment. +### base *[Optional]* -

- The base Alpine environment contains {data.alpine.default}, [Zerops command line tool](/references/cli) and `git` and `wget`. To install additional packages or tools add one or more prepare commands: -

+Sets the base technology for the runtime environment. If not specified, the current version is maintained. ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Alpine runtime environment. - prepareCommands: - - sudo apk add --no-cache something - - curl something else - ... +run: + base: nodejs@latest ``` -When the first deploy with a defined prepare attribute is triggered, Zerops will - -1. create a prepare runtime container -2. optionally: [copy selected folders or files from your build container](#copy-folders-or-files-from-your-build-container) -3. run the `prepareCommands` commands in the defined order +### os *[Optional]* -:::note -`run.prepareCommands` run in the `/home/zerops` directory. -::: +Sets the operating system for the runtime environment. Options and versions are the same as for the build environment. -#### Command exit code +### ports *[Optional]* -If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](/alpine/how-to/logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. +Specifies the internal ports on which your application will listen. -#### Cache of your custom runtime environment +```yaml +run: + ports: + - port: 8080 + protocol: TCP # Optional + httpSupport: true # Optional + - port: 8081 + ... +``` -Some packages or tools can take a long time to install. Therefore, Zerops caches your custom runtime environment after the installation of your custom packages or tools is completed. When the second or following deploy is triggered, Zerops will use the custom runtime cache from the previous deploy if following conditions are met: +Available parameters: -1. Content of the [build.addToRunPrepare](#copy-folders-or-files-from-your-build-container) and `run.prepareCommands` attributes didn't change from the previous deploy -2. The custom runtime cache wasn't invalidated in the Zerops GUI. +#### port *[Required]* +Defines the port number on which your application listens. Must be between *10* and *65435*, as ports outside this range are reserved for internal Zerops systems. -To invalidate the Zerops runtime cache go to your service detail in Zerops GUI, choose **Service dashboard & runtime containers** from the left menu and click on the **Open pipeline detail** button. Then click on the **Clear runtime prepare cache** button. +#### protocol *[Optional]* +Specifies the network protocol to use: +- Allowed values: `TCP` *(default)* or `UDP` -When the prepare cache is used, Zerops doesn't create a prepare runtime container and executes the deployment of your application directly. +#### httpSupport *[Optional]* +Indicates whether the port is running a web server: +- Default value: `false` +- Set to `true` if a web server is running on the port +- Only available with TCP protocol +- Used by Zerops for [public access](/features/access) configuration -#### Single or separated shell instances +### prepareCommands *[Optional]* -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +Customizes the runtime environment by installing additional dependencies or tools. -### Copy folders or files from your build container +:::note +`run.prepareCommands` run in the `/home/zerops` directory. +::: -

- The prepare runtime container contains {data.alpine.default}, [Zerops command line tool](/references/cli) and `git` and `wget`. -

+### initCommands *[Optional]* -The prepare runtime container does not contain your application code nor the built application. If you need to copy some folders or files from the build container to the runtime container (e.g. a configuration file) use the `addToRunPrepare` attribute in the [build section](#build-pipeline-configuration). +Defines commands to run each time a new runtime container starts or restarts. ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... - addToRunPrepare: ./runtime-config.yaml - - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Alpine runtime environment. - prepareCommands: - - sudo apk add --no-cache something - - curl something else - ... +run: + initCommands: + - rm -rf ./cache ``` -In the example above Zerops will copy the `runtime-config.yaml` file from your build container **after the build has finished** into the new **prepare runtime** container. The copied files and folders will be available in the `/home/zerops` folder in the new prepare runtime container before the prepare commands are triggered. +:::note +`run.initCommands` run in the `/var/www` directory. +::: -### initCommands +### start *[Required for some runtimes]* -_OPTIONAL._ Defines one or more commands to be run each time a new runtime container is started or a container is restarted. +Defines the start command for your application. ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Alpine application is started. - initCommands: - - rm -rf ./cache +run: + start: npm start ``` -These commands are triggered in the runtime container before your Alpine application is started via the [start command](#start). - -:::note -`run.initCommands` run in the `/var/www` directory. -::: +### startCommands *[Optional]* -Use init commands to clean or initialise your application cache or similar operations. +Defines start commands. -:::caution -The init commands will delay the start of your application each time a new runtime container is started (including the horizontal [scaling](/alpine/how-to/scaling) or when a runtime container is restarted). +Unlike `start`, you can define multiple commands that starts their own processes. -Do not use the init commands for customising your runtime environment. Use the [run:prepareCommands](#preparecommands-1) attribute instead. -::: +```yaml +run: + startCommands: + # start the application + - command: npm run start:prod + name: server + # start the replication + - command: litestream replicate -config=litestream.yaml + name: replication + # restore the database on container init + initCommands: + - litestream restore -if-replica-exists -if-db-not-exists -config=litestream.yaml $DB_NAME +``` -#### Command exit code +See [start-commands-example](https://github.com/zeropsio/start-commands-example) -If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](/alpine/how-to/logs#runtime-log) to troubleshoot the error. +### documentRoot *[Optional]* -#### Single or separated shell instances +Customizes the root folder for publicly accessible web server content (available only for webserver runtimes). -You can configure your `initCommands` to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +### siteConfigPath *[Optional]* -### envVariables +Sets the custom webserver configuration (available only for webserver runtimes). -_OPTIONAL._ Defines the environment variables for the runtime environment. +### envVariables *[Optional]* -Enter one or more env variables in following format: +Defines environment variables for the runtime environment. ```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to run your application ==== run: - # OPTIONAL. Defines the env variables for the runtime environment: + base: nodejs@20 envVariables: - MODE: production DB_NAME: db DB_HOST: db DB_USER: db DB_PASS: ${db_password} ``` -Read more about [environment variables](/alpine/how-to/env-variables) in Zerops. - -### start +### envReplace *[Optional]* -_OPTIONAL._ Defines the start command for your Alpine application. +Automatically replaces environment variable placeholders in your static files with their actual values during deployment. ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Your Alpine application start command - start: ./app +run: + envReplace: + delimiter: "%%" + target: + - config/jwt/public.pem + - config/jwt/private.pem + - ./config/ ``` -### health check - -_OPTIONAL._ Defines a health check. - -`healthCheck` requires either one `httpGet` object or one `exec` object. +Available parameters: -#### httpGet +#### delimiter *[Required]* +Characters that wrap your variable names in placeholders (e.g., `%%` means placeholders look like `%%VARIABLE%%`). +- Type: `string` or `array of strings` +- Supports multiple delimiters simultaneously -Configures the health check to request a local URL using a HTTP GET method. +#### target *[Required]* +Files or directories to process for variable replacement. +- Type: `string` or `array of strings` +- Can be specific files or directories -Following attributes are available: +:::warning +Directory targets only process files directly in the specified directory, not subdirectories for performance reasons. To process files in subdirectories, specify each subdirectory explicitly in the target array. For example, ./config/ processes only files in the config directory itself, not files in ./config/jwt/ or other subdirectories. +::: - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
+**How it works:** +1. Define placeholders in your files using the specified delimiters +2. Set environment variables with matching names +3. During deployment, Zerops finds and replaces placeholders with actual values -**Example:** +**Example usage:** ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Your Alpine application start command - start: ./app - - # OPTIONAL. Define a health check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - healthCheck: - httpGet: - port: 80 - path: /status +run: + envReplace: + delimiter: "%%" + target: + - ./config/ + - ./templates/ + - ./ # Only processes files in root, not subdirectories ``` -#### exec - -Configures the health check to run a local command. -Following attributes are available: +File content before replacement: +``` +# config/jwt/public.pem +%%JWT_PUBLIC_KEY_CONTENT%% +``` - - - - - - - - - - - - - -
ParameterDescription
command - Defines a local command to be run. +Environment variable: +``` +JWT_PUBLIC_KEY_CONTENT=-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... +-----END PUBLIC KEY----- +``` - The command has access to the same [environment variables](/alpine/how-to/create#set-secret-environment-variables) as your Alpine application. +The placeholder gets replaced with the actual JWT public key during deployment. - A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. -
+### routing *[Optional]* -**Example:** +Configures URL routing, redirects, and HTTP headers (only for Static services). ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +run: + routing: + root: /custom/root + cors: "'*' always" + redirects: + - from: /old-path + to: /new-path + status: 301 + headers: + - for: "/*" + values: + X-Frame-Options: "'DENY'" +``` - # ==== how to run your application ==== - run: - # REQUIRED. Your Alpine application start command - start: ./app +Available parameters: - # OPTIONAL. Define a health check with a shell command. - healthCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user -``` +#### root *[Optional]* +Sets a custom root directory for the service. +- Type: `string` -### crontab +#### cors *[Optional]* +Enables CORS headers for cross-origin requests. +- Type: `string` +- Sets `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`, and `Access-Control-Expose-Headers` +- Special case: `"*"` is automatically converted to `'*'` -_OPTIONAL._ Defines cron jobs. +#### redirects *[Optional]* +Defines URL redirects and rewrites. +- Type: `array of objects` +- Each redirect object supports: + - **from** *[Required]* - Source path to match ([supports wildcards](/static/overview#wildcard-matching) with `*`) + - **to** *[Required]* - Destination path + - **status** *[Optional]* - HTTP status code (required for absolute URLs) + - **preservePath** *[Optional]* - Preserve path after wildcard match + - **preserveQuery** *[Optional]* - Preserve query parameters -Setup cron jobs in the following format: +#### headers *[Optional]* +Sets custom HTTP headers for specific paths. +- Type: `array of objects` +- Each header object supports: + - **for** *[Required]* - Path pattern to match + - **values** *[Required]* - Object with header name/value pairs -```yaml -zerops: - # define hostname of your service - - setup: app +**Example usage:** - # ==== how to run your application ==== - run: - crontab: - # REQUIRED. Sets the command to execute: - - command: "" - # REQUIRED. Sets the interval time to execute: - timing: "0 * * * *" +```yaml +run: + routing: + cors: "'*' always" + redirects: + # Permanent redirect + - from: /old-page + to: /new-page + status: 301 + # Wildcard redirect with path preservation + - from: /blog/* + to: /articles/ + preservePath: true + status: 302 + headers: + - for: "/*" + values: + X-Frame-Options: "'DENY'" + Content-Security-Policy: '"default-src ''self''"' ``` -Read more about setting up [cron](/zerops-yaml/cron) in Zerops. +### healthCheck *[Optional]* -## Deploy configuration +Defines a health check for your application. -### readiness check +```yaml +run: + healthCheck: + # HTTP GET method example + httpGet: + port: 80 + path: /status + host: my-host.zerops + scheme: https + # OR command-based example + exec: + command: | + curl -s http://localhost:8080/status > /tmp/status + grep -q "OK" /tmp/status -_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](/alpine/how-to/deploy-process#readiness-checks) in Zerops. - -`readinessCheck` requires either one `httpGet` object or one `exec` object. - -#### httpGet - -Configures the readiness check to request a local URL using a http GET method. - -Following attributes are available: - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
- -**Example:** - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... + # Common parameters + failureTimeout: 60 + disconnectTimeout: 30 + recoveryTimeout: 30 + execPeriod: 10 +``` - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - httpGet: - port: 80 - path: /status +Available parameters: - # ==== how to run your application ==== - run: ... -``` +#### httpGet *[Optional]* +Configures the health check to request a local URL using a HTTP GET method. -Read more about how the [readiness check works](/alpine/how-to/deploy-process#readiness-checks) in Zerops. +- **port** *[Required]* - Defines the port of the HTTP GET request. +- **path** *[Required]* - Defines the URL path of the HTTP GET request. +- **host** *[Optional]* - The health check is triggered from inside of your runtime container so it uses the localhost (127.0.0.1). If you need to add a host to the request header, specify it in the host attribute. +- **scheme** *[Optional]* - The health check is triggered from inside of your runtime container so no https is required. If your application requires a https request, set scheme: `https`. -#### exec +#### exec *[Optional]* +Configures the health check to run a local command. -Configures the readiness check to run a local command. -Following attributes are available: +- **command** *[Required]* - Defines a local command to be run. The command has access to the same environment variables. A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example above. - - - - - - - - - - - - - -
ParameterDescription
command - Defines a local command to be run. +#### Common parameters *[Optional]* +The following parameters can be used with either `httpGet` or `exec` health checks: +- **failureTimeout** - Time in seconds until container fails after consecutive health check failures (reset by success). +- **disconnectTimeout** - Time in seconds until container is disconnected and becomes publicly unavailable. +- **recoveryTimeout** - Time in seconds until container is connected and becomes publicly available. +- **execPeriod** - Time interval in seconds between health check attempts. - The command has access to the same [environment variables](/alpine/how-to/create#set-secret-environment-variables) as your Alpine application. +:::tip +Health checks continuously monitor your running application, while readiness checks verify if a new deployment is ready to receive traffic. For readiness checks, see the [readinessCheck section](#readinesscheck-). +::: - A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. -
+### crontab *[Optional]* -**Example:** +Defines scheduled commands to run as cron jobs within a service. ```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user +run: + crontab: + - command: "date >> /var/log/cron.log" + timing: "0 * * * *" + allContainers: false ``` -Read more about how the [readiness check works](/alpine/how-to/deploy-process#readiness-checks) in Zerops. - ----------------------------------------- - -# Alpine > How To > Build Process - - -## Build process overview - -Zerops starts a temporary build container and performs the following actions: - -1. **Installs the build environment** - Sets up base system and runtime -2. **Downloads your application source code** - From [GitHub ↗](https://www.github.com), [GitLab ↗](https://www.gitlab.com) or via [Zerops CLI](/references/cli) -3. **Optionally customizes the build environment** - Runs prepare commands if configured -4. **Runs the build commands** - Executes your build process -5. **Uploads the application artifact** - Stores build output to internal Zerops storage -6. **Caches selected files** - Preserves specified files for faster future builds - -The build container is automatically deleted after the build has finished or failed. - -## Build configuration - -Configure your build process in your `zerops.yaml` file according to the pipeline guide. - -## Build environment - -### Default build environment - -The default build environment contains: - -- {data.alpine.default} -- [zCLI](/references/cli), Zerops command line tool -- - -### Customize build environment - -To install additional packages or tools, add one or more to your `zerops.yaml`. +Setup cron jobs. See [examples](/zerops-yaml/cron). -:::info -The application code is available in the `/build/source` folder in your build container before the prepare commands are triggered. This allows you to use any file from your application code in your prepare commands (e.g. a configuration file). -::: +### volume *[Optional]* -### Build hardware resources +Mounts a [Local Storage](/local-storage/overview) service's volume into the runtime containers. -All runtime services use the same hardware resources for build containers: +```yaml +run: + volume: + hostname: vol # hostname of the Local Storage service + mountPath: /srv/data # optional, defaults to /mnt/{hostname} + readOnly: false # optional, defaults to false +``` - - - - - - - - - - - - - - - - - - - - - - - - - -
HW resourceMinimumMaximum
CPU cores15
RAM8 GB8 GB
Disk1 GB100 GB
+Available parameters: -Build containers start with minimum resources and scale vertically up to maximum capacity as needed. +#### hostname *[Required]* +Hostname of the Local Storage service in the same project. -### Build time limit +#### mountPath *[Optional]* +Absolute path the volume is mounted to inside the runtime containers. Defaults to `/mnt/{hostname}`. System directories (`/etc`, `/var`, `/var/www`, `/tmp`, ...) are rejected; their subdirectories are allowed. -The time limit for the whole build pipeline is **1 hour**. After 1 hour, Zerops will terminate the build pipeline and delete the build container. +#### readOnly *[Optional]* +Mounts the volume read-only. Defaults to `false`. -:::info -Build container resources are not charged separately. Limited build time is included in your [project core plan](/company/pricing#project-core-plans), with additional build time available if needed. +:::caution +All containers of a service that mounts a volume are placed on the physical machine holding the volume, together with the containers of every other service mounting it. A service can mount at most one volume. See [Mount Local Storage to a service](/local-storage/how-to/connect) for details. ::: -## Troubleshooting builds - -:::tip Advanced troubleshooting -For complex build issues that require investigation, you can enable [debug mode](/features/debug-mode) to pause the build process at specific points and inspect the build container state interactively. +:::note +For more detailed information on specific configurations, refer to the runtime-specific guides linked at the beginning of this document. ::: -### Build and prepare command failures - -If any or fails (returns non-zero exit code), the build is canceled. Check the to troubleshoot the error. +*Need help? Join our [Discord community](https://discord.gg/zeropsio).* -### Build cache issues +## Editor support (JSON Schema) -If you encounter unexpected build behavior or dependency issues, the problem might be related to cached build data. While Zerops maintains the build cache to speed up deployments, sometimes you may need to start fresh. +Zerops publishes an official [JSON Schema ↗](https://json-schema.org/) for `zerops.yaml`: -To invalidate the build cache: +``` +https://api.app-prg1.zerops.io/api/rest/public/settings/zerops-yml-json-schema.json +``` -1. Go to your service detail in Zerops GUI -2. Choose **Pipelines & CI/CD Settings** from the left menu -3. Click on the **Invalidate build cache** button +With the schema attached, your editor gives you: -This will force Zerops to run the next build clean, including all prepare commands. +- **Autocomplete** for every key and nested field +- **Inline documentation** on hover +- **Validation** — typos, wrong types, and missing required fields are flagged as you type +- **Enum suggestions** for fields like `base` or `cache` -Learn more about [build cache behavior](/features/build-cache). +### Auto-detection via SchemaStore -## More resources +The schema is registered with [SchemaStore ↗](https://www.schemastore.org/), so most YAML-aware editors apply it automatically — no setup required — when the file is named: -For more details about the build and deploy pipeline, including how to cancel builds and manage application versions, see the [general pipeline documentation](/features/pipeline). +- `zerops.yml` +- `zerops.yaml` -## Next steps +This covers VS Code (with the [YAML extension by Red Hat ↗](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)), all JetBrains IDEs, and any editor backed by [`yaml-language-server` ↗](https://github.com/redhat-developer/yaml-language-server) (Neovim, Helix, Sublime LSP, …). -- Understand the -- Learn how to -- Explore +### Manual attachment ----------------------------------------- +If your file is named differently, add a modeline at the top: -# Alpine > How To > Controls +```yaml +# yaml-language-server: $schema=https://api.app-prg1.zerops.io/api/rest/public/settings/zerops-yml-json-schema.json +zerops: + - setup: app + # ... +``` +The same URL works in any editor that lets you map a schema to a file pattern manually (e.g., `yaml.schemas` in VS Code `settings.json`, or JetBrains' **JSON Schema Mappings** panel). ---------------------------------------- -# Alpine > How To > Create - - -Zerops provides a Alpine runtime service with extensive build support. Alpine runtime is highly scalable and customisable to suit both development and production. - -## Create Alpine service using Zerops GUI - -First, set up a project in Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu in the **Services** block. Then add a new Alpine service: - -[Video: /vids/services/golang.webm](/vids/services/golang.webm) - -### Choose Alpine version - -Following Alpine versions are currently supported: - -:::info -You can [change](/alpine/how-to/upgrade) the major version at any time later. -::: +# Zerops Yaml > Cron -### Set a hostname -Enter a unique service identifier like "app","cache", "gui" etc. Duplicate services with the same name in the same project are forbidden. +Cron jobs are scheduled commands that execute automatically inside a service's containers based on defined timing rules. -#### Limitations: +In Zerops, these jobs are configured in the `run` section of `zerops.yaml` file under the `crontab` key. -- maximum 25 characters -- must contain only lowercase ASCII letters (a-z) or numbers (0-9) +## Parameters -:::caution -The hostname is fixed after the service is created. It can't be changed later. -::: +### command +*string, REQUIRED* -### Set secret environment variables +The shell command to execute at the scheduled time. This can be any valid command. -Add environment variables with sensitive data, such as password, tokens, salts, certificates etc. These will be securely saved inside Zerops and added to your runtime service upon start. +### timing +*string, REQUIRED* -Setting the secret environment variables is optional. You can set them later in Zerops GUI. +The schedule for when the task should run, specified in standard cron format using five space-separated fields: + - Minute (0–59) + - Hour (0–23) + - Day of the month (1–31) + - Month (1–12) + - Day of the week (0–7; both 0 and 7 represent Sunday) -Read more about [different types of env variables](/alpine/how-to/env-variables#service-env-variables) in Zerops. +#### Examples + - `"0 5 * * *"` – Runs daily at 5:00 AM. + - `"*/10 * * * *"` – Runs every 10 minutes. -## Create Alpine service using zCLI +### allContainers +*boolean, REQUIRED* -zCLI is the Zerops command-line tool. To create a new Alpine service via the command-line, follow these steps: +**Options:** +- `true` – Command runs on all containers. +- `false` – Command runs on only one container. -1. [Install & setup zCLI](/references/cli) -2. [Create a project description file](/alpine/how-to/create#create-a-project-description-file) -3. [Create a project with a Alpine and PostgreSQL service](#full-example) +### workingDir +*string, REQUIRED* -### Create a project description file +Specifies the directory where the command will be executed. If not set, it defaults to `/var/www`. -Zerops uses a yaml format to describe the project infrastructure. +## Example Configurations +Here’s a basic example of how to set up a cron job in your service's `zerops.yaml`: -#### Basic example: +```yaml +run: + crontab: + - command: "date >> /var/log/cron.log" + timing: "0 * * * *" +``` +This configuration logs the current date to `/var/log/cron.log` every hour. -Create a directory `my-project`. Create an `description.yaml` file inside the `my-project` directory with following content: +### Running on Multiple Containers +By default, cron jobs run on a single container, even if multiple containers exist for the service. To execute a command across all containers, you can use the `allContainers` parameter: ```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in alpine@{version} format - type: alpine@3.20 - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' +run: + crontab: + - command: "rm -rf /tmp/*" + timing: "0 0 * * *" + allContainers: true ``` +This example removes temporary files from all containers every day at midnight. -The yaml file describes your future project infrastructure. The project will contain one Alpine service with default [auto scaling](/alpine/how-to/scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](/alpine/how-to/build-pipeline#ports). Following secret env variables will be configured: +### Custom Working Directory +You can also specify a custom working directory for your commands using the `workingDir` parameter: -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" +```yaml +run: + crontab: + - command: "php artisan schedule:run" + timing: "* * * * *" + workingDir: /var/www/html ``` +In this case, the command runs every minute in the `/var/www/html` directory. -#### Full example: - -Create a directory my-project. Create an description.yaml file inside the my-project directory with following content: +### Multiple Cronjobs +It is possible to define multiple cron jobs as a YAML object list under the `crontab` key. ```yaml -# basic project data -project: - # project name - name: my-project - # optional: project description - description: A project with a Alpine and PostgreSQL database - # optional: project tags - tags: - - DEMO - - ZEROPS -# array of project services -services: - - # service name - hostname: app - # service type and version number in alpine@{version} format - type: alpine@3.20 - # optional: vertical auto scaling customization - verticalAutoscaling: - cpuMode: DEDICATED - minCpu: 2 - maxCpu: 5 - minRam: 2 - maxRam: 24 - minDisk: 6 - maxDisk: 50 - startCpuCoreCount: 3 - minFreeRamGB: 0.5 - minFreeRamPercent: 20 - # defines the minimum number of containers for horizontal autoscaling. Max value = 6. - minContainers: 2 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 4 - # optional: create secret env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' - - # second service hostname - hostname: db - # service type and version number in postgresql@{version} format - type: postgresql@12 - # mode of operation "HA"/"non_HA" - mode: NON_HA +run: + crontab: + - command: ... + ... + - command: ... + ... ``` -The yaml file describes your future project infrastructure. The project will contain an Alpine service and a [PostgreSQL](/postgresql/overview) service. -Alpine service with "app" hostname, the internal port(s) the service listens on will be defined later in the zerops.yaml. Alpine service will run with a custom vertical and horizontal scaling. Following secret env variables will be configured: +---------------------------------------- -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` +# Zerops Yaml > Base List -The hostname of the PostgreSQL service will be set to "db". The [single container](/features/scaling#single-container-mode)(/features/scaling#deployment-modes-databases-and-shared-storage) mode will be chosen and the default auto [scaling configuration](/postgresql/how-to/scale#configure-scaling) will be set. -#### Description of description.yaml parameters +This is a list of all currently supported versions of technologies that can be used for [build.base](/zerops-yaml/specification#base-required) and [run.base](/zerops-yaml/specification#base) sections in `zerops.yaml`. -The `project:` section is required. Only one project can be defined. +:::note +Versions listed on the same line are aliases of the same underlying version. +::: - +## Runtime services + +
- - + + + - + + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +- `php@8.5`, `php@latest` +- `php@8.4` +- `php@8.3` +- `php@8.1` + + - + + + + + +
ParameterDescriptionService TypeSupported OSVersions
Build / Runtime
hostname - The unique service identifier. - - The hostname of the new database will be set to the `hostname` value. - - Limitations: -
    -
  • duplicate services with the same name in the same project are forbidden
  • -
  • maximum 25 characters
  • -
  • must contain only lowercase ASCII letters (a-z) or numbers (0-9)
  • -
-
Bun`ubuntu` / `alpine` +- `bun@1.3.9`, `bun@1.3`, `bun@latest` +- `bun@1.2.2`, `bun@1.2` +- `bun@nightly` +- `bun@canary` +- `bun@1.1.34`, `bun@1.1(Ubuntu only)` +
type - Specifies the service type and version. - - See what [Alpine service types](/references/import-yaml/type-list#runtime-services) are currently supported. - Deno`ubuntu` +- `deno@2.0.0`, `deno@2`, `deno@latest` +- `deno@1.45.5`, `deno@1` +
verticalAutoscaling - Optional. Defines [custom vertical auto scaling parameters](/alpine/how-to/create#set-auto-scaling-configuration). - - All verticalAutoscaling attributes are optional. Not specified attributes will be set to their default values. - .NET`ubuntu` / `alpine` +- `dotnet@10`, `dotnet@latest` +- `dotnet@9` +- `dotnet@8` +- `dotnet@7` +- `dotnet@6` +
- cpuMode - Optional. Accepts `SHARED`, `DEDICATED` values. Default is `SHARED` - Elixir`ubuntu` / `alpine` +- `elixir@1.16`, `elixir@1`, `elixir@latest` +
- minCpu/maxCpu - Optional. Set the minCpu or maxCpu in CPU cores (integer). - Gleam`ubuntu` +- `gleam@1.5`, `gleam@1`, `gleam@latest` +
- minRam/maxRam - Optional. Set the minRam or maxRam in GB (float). - Go`ubuntu` / `alpine` +- `go@1.22`, `go@1`, `golang@1`, `go@latest`, `golang@latest` +
- minDisk/maxDiskJava`ubuntu` / `alpine` +- `java@21`, `java@latest` +- `java@17` +
Node.js`ubuntu` / `alpine` +- `nodejs@24`, `nodejs@latest` +- `nodejs@22` +- `nodejs@20` +- `nodejs@18` +
Python`ubuntu` / `alpine` +- `python@3.14 (Ubuntu only)`, `python@latest` +- `python@3.12` +- `python@3.11` +
Rust`ubuntu` / `alpine` +- `rust@1`, `rust@latest`, `rust@stable` +- `rust@1.86` +- `rust@1.80` +- `rust@1.78` +- `rust@nightly` +
  BuildRuntime
PHP + Apache`ubuntu` / `alpine` - Optional. Set the minDisk or maxDisk in GB (float). - +- `php-apache@8.5`, `php-apache@latest` +- `php-apache@8.4` +- `php-apache@8.3` +- `php-apache@8.1` +
minContainersPHP + nginx`ubuntu` / `alpine` - Optional. Default = 1. Defines the minimum number of containers for [horizontal autoscaling](/alpine/how-to/create#horizontal-auto-scaling). +- `php@8.5`, `php@latest` +- `php@8.4` +- `php@8.3` +- `php@8.1` + +- `php-nginx@8.5`, `php-nginx@latest` +- `php-nginx@8.4` +- `php-nginx@8.3` +- `php-nginx@8.1` +
- Limitations: +## Static services - Current maximum value = 10. - + + + + + + + + + + + + + + + + + + - + + + + + +
Service TypeSupported OSVersions
BuildRuntime
nginx`ubuntu`/`alpine`- +- `nginx@1.22`, `nginx@latest` +
maxContainersstatic`ubuntu`/`alpine`- - Defines the maximum number of containers for [horizontal autoscaling](/alpine/how-to/create#horizontal-auto-scaling). +- `static`, `static@1.0`, `static@latest` +
- Limitations: +## Containers and virtual machines - Current maximum value = 10. - + + + + + + + + + + + + - + + + +- `docker@26.1`, `docker@latest` + + + + + + + + + + +
Service TypeSupported OSVersions
BuildRuntime
envSecretsDocker`alpine`- - Optional. Defines one or more secret env variables as a key value map. See env variable [restrictions](/alpine/how-to/env-variables#env-variable-restrictions). -
Alpine`alpine` +- `alpine@3.23`, `alpine@latest` +- `alpine@3.22` +- `alpine@3.21` +- `alpine@3.20` +- `alpine@3.19` +- `alpine@3.18` +- `alpine@3.17` +
Ubuntu`ubuntu` +- `ubuntu@24.04` +- `ubuntu@22.04`, `ubuntu@latest` +
-### Create a project based on the description.yaml +---------------------------------------- -When you have your `description.yaml` ready, use the `zcli project project-import` command to create a new project and the service infrastructure. +# Zcp > Quickstart -```sh -Usage: - zcli project project-import importYamlPath [flags] -Flags: - -h, --help Help for the project import command. - --org-id string If you have access to more than one organization, you must specify the org ID for which the - project is to be created. - --working-dir string Sets a custom working directory. Default working directory is the current directory. (default "./") -``` +Use this when you want the fastest hands-on ZCP loop: deploy an **AI Agent** recipe, authorize your coding agent, open Browser VS Code, and ask for one product change. -Zerops will create a project and one or more services based on the `description.yaml` content. +ZCP supports multiple coding agents including Claude Code (Anthropic), Codex (OpenAI), Antigravity, and Grok Build. The screenshots below use Claude Code as the walkthrough example. -Maximum size of the `description.yaml` file is 100 kB. +Some [Zerops recipes](https://app.zerops.io/recipes) include an **AI Agent** environment. That preset creates app services, managed services, the `zcp@1` workspace, Browser VS Code, and bundled agent wiring in one deploy. -You don't specify the project name in the `zcli project project-import` command, because the project name is defined in the `description.yaml`. +This quickstart uses [Laravel showcase](https://app.zerops.io/recipes/laravel-showcase?environment=ai-agent) because it includes real managed services. The same flow works for other recipes that offer AI Agent (local variants exist too). -If you have access to more than one client, you must specify the client ID for which the project is to be created. The `clientID` is located in the Zerops GUI under the client name on the project dashboard page. +## Prerequisites -### Add Alpine service to an existing project +- A Zerops account with permission to create a project. +- A subscription login or API credentials for your chosen coding agent (Claude Code, Codex, Antigravity, or Grok Build). Zerops wires the agent to ZCP, but your agent subscription or model credentials stay yours. -#### Example: +## 1. Choose the AI Agent recipe -Create a directory `my-project` if it doesn't exist. Create an `import.yaml` file inside the `my-project` directory with following content: +1. Open the [Zerops recipes catalog](https://app.zerops.io/recipes). +2. Open a recipe with an **AI Agent** environment. For example, open [Laravel showcase](https://app.zerops.io/recipes/laravel-showcase?environment=ai-agent). +3. Select **AI Agent**. +4. Keep **Coding Agent** and **Cloud IDE** enabled. +5. Deploy the recipe. -```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in alpine@{version} format - type: alpine@3.20 - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' +The deploy creates app runtimes, managed dependencies, and a `zcp@1` workspace. In this recipe it appears as the `zcp` service. The agent, terminal, and browser IDE run there. App code still deploys to the app runtimes, not to `zcp`. + +## 2. Authorize your coding agent + +When provisioning finishes, the dashboard opens the authentication flow for your bundled agent. If you are using Claude Code (as in the screenshots below), use your own Claude Code subscription login or API credentials. + +This is separate from `ZCP_API_KEY`, the Zerops token used by ZCP. Your agent login or API key is used only by the bundled agent. + +If you close the prompt, open the `zcp` service in the dashboard. Its panel shows the browser workspace, web terminal, SSH access, desktop editor access, and agent authorization state. + +## 3. Open the workspace + +After authentication, continue into **Browser VS Code**. The workspace opens with files, ZCP configuration, terminal access, and your coding agent panel (the Claude Code panel in the screenshots below). + +You are now inside the remote workspace. The agent can read live state, use the MCP tools, reach private services, and deploy app changes to the runtimes created by the recipe. + +## 4. Ask for a product outcome + +In your coding agent, ask for the app behavior in natural language. A good first prompt is intentionally short: + +```text +Build a task board for my team. +Tasks should stay saved after refresh. ``` -The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one Alpine service version 1 with default [auto scaling](/alpine/how-to/scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: +The agent should deploy, verify, read evidence, and return proof for the app task. Add detail only when it changes the work. -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" +Add details when they change the product, stack, runtime layout, acceptance criteria, or delivery preference: + +```text +In this Laravel app, add a task board backed by the existing PostgreSQL service. +A user can create a task, refresh the page, and still see it. ``` -The content of the `services:` section of `import.yaml` is identical to the project description file. The `import.yaml` never contains the `project:` section because the project already exists. +:::note Prompt shape -When you have your `import.yaml` ready, use the `zcli project service-import` command to add one or more services to your existing Zerops project. +Quickstart prompts are short so you can see what ZCP carries behind the request. Longer, detailed prompts are fine for larger engineering work, especially when they change product behavior, stack, runtime layout, acceptance criteria, delivery preference, credentials, or safety approvals. +::: -```sh -Usage: - zcli project service-import importYamlPath [flags] +## 5. Read the proof -Flags: - -h, --help Help for the project service import command. - -P, --project-id string If you have access to more than one project, you must specify the project ID for which the - command is to be executed. -``` +The final answer should give you a real URL, endpoint, UI state, stored result, or blocker. Open the URL and try the behavior the agent says it verified. -zCLI commands are interactive, when you press enter after `zcli project service-import importYamlPath`, you will be given a list of your projects to choose from. +For the task-board prompt, create a task, refresh the page, and confirm the task is still there. If it disappears, the app is not done; ask the agent to verify that exact behavior again and continue from current evidence rather than starting over. -Maximum size of the import.yaml file is 100 kB. +If the agent cannot finish, useful output names the blocker: missing credential, missing decision, unsupported runtime choice, or repeated failure it could not recover from. + +## Next steps + +- [Build and ship](/zcp/workflows/build-with-zcp) — Runtime layout, development work, delivery, packaging, and production release. +- [How it works](/zcp/concept/how-it-works) — Live state, runtime fit, app wiring, deploy evidence, behavior proof, and blockers. +- [Trust model](/zcp/security/trust-model) — What the project-scoped token lets the agent do, and where the safety boundary sits. ---------------------------------------- -# Alpine > How To > Customize Runtime +# Zcp > Overview -## Build Custom Runtime Images +This section covers, in order: -Zerops allows you to build custom runtime images (CRI) when the default base runtime images don't meet your application's requirements. This is an optional phase in the [build and deploy pipeline](/features/pipeline#runtime-prepare-phase-optional). +
-Alpine is a versatile base for running anything not explicitly offered as a dedicated Zerops runtime. You can install any packages and tools you need, treating it as a clean OS to customize however you want. +
-It is also a great option when you need a specific version of a technology (like Go, Node.js, or PHP) that Zerops doesn't support by default—whether it's an older version for legacy projects or a newer release not yet available. +GET STARTED -## Configuration +

Quickstart and concept

-### Default Runtime Environment +[Quickstart](/zcp/quickstart) for hands-on; [How it works](/zcp/concept/how-it-works) for the work loop. -The default runtime environment contains: +
-- {data.alpine.default} -- [zCLI](/references/cli) -- +
-### When You Need a Custom Runtime Image +SETUP -Since Alpine serves as a general-purpose base, you'll likely want to customize it for your specific use case. Common scenarios include: +

Remote or local workspace

-:::important -You should not include your application code in the custom runtime image, as your built/packaged code is deployed automatically into fresh containers. -::: +[Remote or local setup](/zcp/setup/choose-workspace), [Trust model](/zcp/security/trust-model), and [Production boundary](/zcp/security/production-policy). -Here are examples of configuring custom runtime images in your `zerops.yml`: +
-### Basic Setup +
-### Using Build Files in Runtime Preparation +WORKFLOWS -For complete configuration details, see the [runtime prepare phase configuration guide](/features/pipeline#configuration). +

Build, package, promote

-## Process and Caching +[Build and ship](/zcp/workflows/build-with-zcp), [Package a running service](/zcp/workflows/package-running-service), [Promote to production](/zcp/workflows/promote-to-production). -### How Runtime Prepare Works -The runtime prepare process follows the same steps for all runtimes. See [how runtime prepare works](/features/pipeline#how-it-works) for the complete process details. +
-### Caching Behavior -Zerops caches custom runtime images to optimize deployment times. Learn about [custom runtime image caching](/features/pipeline#custom-runtime-image-caching) including when images are cached and reused. +
-### Build Management -For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). +REFERENCE -:::warning -Shared storage mounts are not available during the runtime prepare phase. -::: +

Troubleshooting and lookup

-## Troubleshooting +[Workflows in depth](/zcp/reference/agent-workflow), [ZCP MCP tools](/zcp/reference/mcp-operations), [Troubleshooting](/zcp/reference/troubleshooting), [Glossary](/zcp/glossary). -If your `prepareCommands` fail, check the for specific error messages. +
----------------------------------------- +
-# Alpine > How To > Deploy Process +For the broader feature concept — why coding agents need real project infrastructure rather than a sandbox or generated artifact — start with [Infrastructure for Coding Agents](/features/coding-agents). +With the generated workflow instructions enabled, an app task ends in proof or a blocker. **Proof** is a deployed runtime plus the URL, endpoint response, UI state, worker result, or stored data that shows the requested behavior works. A **blocker** is the agent reading the relevant Zerops evidence and naming the missing credential, decision, unsupported fit, or repeated failure. +Your prompt can stay about the product. Name the stack, runtime layout, acceptance criteria, delivery path, external credentials, or risky approval only when those decisions matter. ----------------------------------------- +## What the agent gets -# Alpine > How To > Env Variables +
+
+STATE ----------------------------------------- +### Current state -# Alpine > How To > Filebrowser +Services, runtime layout, managed dependencies, env-var keys and references, logs, events, deploy history, verification state, and saved work state. +
+
----------------------------------------- +CONTROLS -# Alpine > How To > Logs +### Zerops operations +Project-scoped tools for discovering services, changing env vars, managing runtimes, deploying, verifying, scaling, public access, and delivery setup. +
----------------------------------------- +
-# Alpine > How To > Scaling +INSTRUCTIONS +### Workflow +The generated instructions combine service setup and app development: inspect state, choose the runtime target, use or create services, wire code and `zerops.yaml`, deploy, verify, and choose delivery. The Zerops work stays behind the product task instead of becoming another checklist. ----------------------------------------- +
-# Alpine > How To > Shared Storage +
+EVIDENCE +### Evidence-based completion ----------------------------------------- +A build or deploy is not the finish line. A completed app task should end with a working URL, endpoint result, UI proof, or a blocker backed by logs, events, and verification evidence. -# Alpine > How To > Trigger Pipeline +
+
+## What you no longer have to script ----------------------------------------- +Without this layer, an app prompt often turns into an operations runbook. With MCP tools and workflow instructions enabled, you should not need to paste: -# Alpine > How To > Upgrade +- the service map, runtime target, dev/stage state, or managed-service inventory, +- database credentials, private hostnames, env-var references, or generated connection strings, +- build logs, runtime logs, event timelines, or a guess about why the last deploy failed, +- a deploy/verify/recovery script for every task, +- a recap after the chat loses context; the agent can read current workflow status. +**You still own the decisions that need human judgment:** product intent, technology constraints, acceptance criteria, external credentials, repository policy, and approval for destructive actions. +## Where it runs ----------------------------------------- +The **same `zcp` binary** runs in both setups. In [remote setup](/zcp/setup/hosted-workspace), Zerops packages it as a `zcp@1` service with Browser VS Code and bundled agent wiring. In [local setup](/zcp/setup/local-agent-bridge), you install it on your machine and connect your own editor or CLI agent. The project surface is the same; the workspace, network access, deploy source, and safety profile differ. -# Alpine > Overview +To start, add remote setup in Zerops or initialize local setup beside your editor or CLI agent. The [Quickstart](/zcp/quickstart) uses remote setup because it needs no local install. +## Your agent, credentials, and workspace -[Alpine Linux ↗](https://alpinelinux.org/) is a lightweight, security-oriented Linux distribution based on musl libc and busybox, known for its small footprint and efficiency. +**Agent account.** ZCP supports multiple coding agents including Claude Code (Anthropic), Codex (OpenAI), Antigravity, and Grok Build. Remote setup can bundle one of these, already configured for MCP. Zerops wires the agent to the tools; you still authenticate with your own subscription login or API credentials. -Alpine services in Zerops provide a minimal base environment for running applications built with technologies that aren't officially supported by Zerops, or for custom setups requiring full control over the runtime environment while keeping resource usage low. +**Zerops token.** The MCP server connects through `ZCP_API_KEY`, a Zerops token limited to one project. Remote setup gets it from the platform; local setup reads it from `.mcp.json`. Token details live in [Tokens and credentials](/zcp/security/tokens-and-project-access). -:::tip -Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. +**Workspace freedom.** The `zcp@1` service is still a normal Zerops service. You can install another agent CLI, add private MCP servers or helper tools, edit `CLAUDE.md`, add team dotfiles, and adapt the workspace. Details live in [What remote workspace gives you](/zcp/setup/hosted-workspace). + +:::caution Production boundary +Use this setup for development or staging work. Production should stay in a separate Zerops project and receive released work through your CI or release process; see [Promote to production](/zcp/workflows/promote-to-production) for the practical flow and [Production boundary](/zcp/security/production-policy) for the policy. ::: -## Feature Highlights +## What stays outside -- [Create Alpine service](/alpine/how-to/create) — Start with creating an Alpine service using GUI or zCLI. -- [zerops.yaml](/alpine/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to configure your own app. -- [Scaling configuration](/alpine/how-to/scaling) — Set up scaling of your Alpine service so that it runs smoothly while using only necessary resources. +This section is not a replacement for Zerops platform references. The Zerops [build and deploy pipeline](/features/pipeline), [permissions](/features/rbac), networking, scaling, and service references remain canonical for platform behavior. -{" "} -- [Customize build environment](/alpine/how-to/build-process#customize-build-environment) -- [Customize runtime environment](/alpine/how-to/customize-runtime) +---------------------------------------- -## When in doubt, reach out +# Zcp > Glossary -Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. -In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. +Use these definitions when a page, workflow status, agent handoff, or policy needs exact wording. In normal prompts, describe the outcome you want. -Have you built something that others might find useful? Don't hesitate to share your knowledge! +## Core names -- [FAQ](/alpine/faq) — Most common questions in one place. -- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. +**ZCP MCP** - Zerops Control Plane MCP: the MCP tool surface that exposes project-scoped Zerops operations to coding agents. -## Popular Guides +**MCP server** - the Model Context Protocol server exposed by the `zcp` binary. -- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. -- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. +**ZCP MCP tools** - the project-scoped Zerops operations exposed to an agent or MCP-capable client. In MCP clients, this usually appears as the `zerops` server. +**`zcp` binary** - the executable that can run inside remote setup or on your machine in local setup. ----------------------------------------- +**`zcp` service** - the service instance in a Zerops project that hosts remote setup. -# Bun > How To > Build Pipeline +**`zcp@1` service** - the Zerops service type used for remote setup. +**zCLI** - the Zerops command-line client for humans, scripts, VPN, and CI. It is separate from ZCP MCP. -Zerops provides a customizable build and runtime environment for your Bun application. +**zsc** - the in-container Zerops Setup Control utility used from `zerops.yaml`. -## Add zerops.yaml to your repository +## Setup and workspace -Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: +**Remote setup** - the `zcp` binary running inside a Zerops `zcp@1` service. -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: bun@latest +**Include Coding Agent** - remote setup option that adds a bundled agent CLI (Claude Code, Codex, Antigravity, or Grok Build) and preconfigures it to use ZCP MCP tools. - # OPTIONAL. Set the operating system for the build environment. - # os: ubuntu +**Cloud IDE** - browser-based VS Code served by remote setup. - # OPTIONAL. Customise the build environment by installing additional packages - # or tools to the base build environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else +**Browser VS Code** - dashboard entry point into the Cloud IDE. - # OPTIONAL. Build your application - buildCommands: - - bun i - - bun run build +**AI Agent environment** - recipe environment preset that creates app services plus remote setup with **Include Coding Agent** enabled. - # REQUIRED. Select which files / folders to deploy after - # the build has successfully finished - deployFiles: - - dist - - package.json - - node_modules +**Local setup** - the `zcp` binary running on your machine after `zcp init`, while your local editor or CLI agent talks to it. - # OPTIONAL. Which files / folders you want to cache for the next build. - # Next builds will be faster when the cache is used. - cache: node_modules +**Env bridge** - local setup behavior that writes a local `.env` snapshot from Zerops env vars and references so local app code can reach managed services over VPN. - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: bun@latest +**Agent client** - the editor, CLI, hosted agent runtime, or custom MCP client that connects to ZCP MCP. - # OPTIONAL. Sets the internal port(s) your app listens on: - ports: - # port number - - port: 3000 +## Generated files and state - # OPTIONAL. Customise the runtime Bun environment by installing additional - # dependencies to the base Bun runtime environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else +**Generated workflow block** - the managed section in `CLAUDE.md` between `` and ``. Durable project instructions belong outside it. - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Bun application is started. - # initCommands: - # - rm -rf ./cache +**`.mcp.json`** - local MCP server config. It points the local agent client at `zcp serve` and stores `ZCP_API_KEY`; keep it out of git. - # REQUIRED. Your Bun application start command - start: bun start -``` +**`.zcp/state/`** - local workflow metadata for a project directory: known runtimes, pairing, delivery choice, sessions, deploy attempts, verify attempts, and coordination locks. It is not source code. -The top-level element is always `zerops`. +**Workflow state** - saved metadata that lets the agent resume, audit, or close a guided run after interruption. -### Setup +## Workflow -The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. -Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: +**Bootstrap** - workflow phase that reads the current project and settles which runtime services and managed services the app should use before app code work starts. -```yaml -zerops: - # definition for app service - - setup: app - # optional - build: ... - # optional - deploy: ... - # required - run: ... +**Service setup** - the phase that decides which runtime services and managed services the app should use before app code work starts. - # definition for api service - - setup: api - # optional - build: ... - # optional - deploy: ... - # required - run: ... -``` +**Develop** - workflow phase that changes app code/config, deploys, verifies reachability and behavior, and fixes failures from evidence. -Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. +**Runtime target** - the app runtime selected for the current change, such as `appdev`, `appstage`, `app`, or a linked local target. -## Build pipeline configuration +**Runtime layout** - which app runtime services the workflow should use: -### base +- `standard` - dev runtime plus explicit stage runtime. +- `dev` - one mutable development runtime. +- `simple` - one runtime with no dev/stage split. +- `local-stage` - local source directory linked to one Zerops runtime as deploy target. +- `local-only` - local source directory with no linked runtime yet. -_REQUIRED._ Sets the base technology for the build environment. +**Managed service** - database, cache, queue, search, storage, mail, or similar dependency. It provides connection details; it is not an app deploy target. -Following options are available for Bun builds: +**Direct deploy** - deploy from the current source to the scoped runtime through ZCP MCP. The first verified running result uses direct deploy before delivery setup is applied. -- `bun@1.3.9`, `bun@1.3`, `bun@latest` -- `bun@1.2.2`, `bun@1.2` -- `bun@nightly` -- `bun@canary` -- `bun@1.1.34`, `bun@1.1(Ubuntu only)` +**Reachability verification** - checks that the runtime exists, is running, has no recent blocking errors, and can answer an HTTP probe when it is an HTTP service. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: bun@latest - ... -``` +**Behavior verification** - checks that the requested app behavior works on the real URL, endpoint, worker result, or stored state. -

- The base build environment contains {data.alpine.default}, the selected - major version of Bun, - [Zerops command line tool](/references/cli), `npm`, - `yarn`, `git` and `npx` tools. -

+**Proof** - user-inspectable completion evidence, such as a URL, endpoint result, UI state, processed job, or stored result. -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. -::: +**Blocker** - a clear stop state with evidence: failure category, runtime in scope, what was tried, and what decision or credential is needed. -If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: +## Delivery and production -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: - - bun@latest - prepareCommands: - - zsc add go@latest - ... -``` +**Delivery choice** - what happens after a verified deploy: keep direct deploy, push to git, or hand off to CI/release/human process. -See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). +**Delivery mode** - exact reference label for delivery choice: -To customise your build environment use the [prepareCommands](build-pipeline#preparecommands) attribute. +- `auto` - keep direct deploy for future changes. +- `git-push` - commit and push to a configured remote, then observe/verify any tracked build. +- `manual` - external CI, release process, or a human owns future delivery. -:::note -Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. -::: +**Git-push capability** - whether remote setup has enough remote URL and credential setup to push from remote setup. It can exist even when the current delivery mode is `auto`. -### os +**Build integration** - repository-triggered build/deploy path that ZCP MCP may configure or observe, such as a Zerops dashboard webhook or GitHub Actions. It is separate from git-push capability and delivery mode. -_OPTIONAL._ Sets the operating system for the build environment. +**Package a running service** - workflow that turns one verified runtime and its managed dependencies into a re-importable, git-backed Zerops bundle. -Following options are available: +**Production release** - the release operation that moves verified dev or stage work into a separate production Zerops project. It is set up once per project (production infrastructure) and once per runtime (production deploy trigger), then runs every release. -- `alpine` -- `ubuntu` +**Production boundary** - policy that production should live in a separate Zerops project without a `zcp` service and receive promoted work through CI, release process, or human action. -Default value is `alpine`. +## Platform and failure terms -We are currently using following os version: +**Service scaling mode** - Zerops scaling setting such as `HA` or `NON_HA`. Different from runtime layout. -- {data.alpine.default} -- {data.ubuntu.default} +**Public subdomain access** - Zerops `.zerops.app` URL access for an eligible HTTP runtime. Workers and non-HTTP services do not get useful public URLs. -:::caution -The os version is fixed and cannot be customised. -::: +**Failure category** - label that points to the first useful evidence surface: -:::note -Changing the OS setting will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache behavior. -::: +- `build` - build phase failed. +- `start` - build passed, but runtime start or prepare failed. +- `verify` - runtime exists, but reachability or behavior failed. +- `network` - transport, DNS, VPN, SSH, or service-to-service reach failed. +- `config` - `zerops.yaml`, env vars, setup block, or service settings mismatch. +- `credential` - Zerops, git, SSH, managed-service, or external API credential failed. +- `other` - no known category matched. -### prepareCommands +**Confirmation gate** - an operation that pauses until the user explicitly confirms the named target or consequence. -_OPTIONAL._ Customises the build environment by installing additional dependencies or tools to the base build environment. +**Destructive import override** - import action that would replace an existing service stack. ZCP MCP refuses first, names affected services, and requires a matching acknowledgement before proceeding. -The base build environment contains: +## Credentials -- {data.alpine.default} -- selected version of Bun defined in the [base](build-pipeline#base) attribute -- [Zerops command line tool](/references/cli) -- `npm`, `yarn`, `git` and `npx` tools +**Single-project token** - Zerops token that can access exactly one project. ZCP MCP expects this shape. -To install additional packages or tools add one or more prepare commands: +**`ZCP_API_KEY`** - single-project Zerops token used by ZCP MCP. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: bun@latest +**`GIT_TOKEN`** - git provider credential used by remote git-push delivery when needed. - # OPTIONAL. Customise the build environment by installing additional packages - # or tools to the base build environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +**`ZEROPS_TOKEN`** - Zerops token commonly used by GitHub Actions or external CI that runs `zcli`. -When the first build is triggered, Zerops will +**External secret** - third-party credential such as Stripe, OpenAI, Mailgun, or GitHub API access. The agent can wire placeholders and env vars, but the secret value remains your responsibility. -1. create a build container -2. download your application code from your repository -3. run the prepare commands in the defined order -The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. +---------------------------------------- -:::note -These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. -::: +# Zcp > Workflows > Promote To Production -#### Command exit code -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. +Use this after the agent has proved work in development or stage. The production release is the point where authority changes: the agent can prepare proof, source changes, and setup notes, but production execution belongs to Zerops project settings, CI, release tooling, or a deliberate human action with production credentials. -#### Single or separated shell instances +Production should be a separate Zerops project without a `zcp` service. That keeps the development agent out of the production blast radius while still letting verified work reach production. -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +## The simple production path -### buildCommands +There are three different jobs. Two are setup work; one is the repeatable release operation. -_OPTIONAL._ Defines build commands. +| Job | How often | Simplest path | +| --- | --- | --- | +| **Create production infrastructure** | Once per production project | Export the verified Zerops project as YAML in the GUI, edit it for production, then import it as a new project. | +| **Connect the production deploy trigger** | Once per production runtime | In the production project, connect the git repository in the Zerops GUI and trigger builds from release tags. | +| **Release an app change** | Every release | Verify in dev/stage, push source to git, then create the release tag or use your team's release process. | +| **Release an app change** | Every release | Verify in dev/stage, push source to git, then create the release tag or use your team's release process. | -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: bun@latest +This page uses the GUI path because it is the clearest path available today. More customized teams can replace the GUI trigger with GitHub Actions or another CI system later. - # OPTIONAL. Build your application - buildCommands: - - bun i - - bun run build - ... -``` +## 1. Create production infrastructure -Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. +Do this once when you need a production project for a verified app. -Before the build commands are triggered the build container contains: +1. Open the development or staging project that contains the verified runtime. +2. Use **Export project as yaml**. +3. Edit the exported YAML for production. +4. Import the edited YAML as a new Zerops project. -1. base environment defined by the [base](build-pipeline#base) attribute -2. optional customisation of the base environment defined in the [prepareCommands](build-pipeline#preparecommands) attribute -3. your application code +Before import, review the YAML as production infrastructure, not as a blind copy of the development project: -#### Run build commands as a single shell instance +- remove the `zcp` service, +- remove dev-only runtimes and tools such as Mailpit or Adminer, +- keep the runtime and managed services that production actually needs, +- choose production `mode` values before creation, especially `HA` for databases that need it, +- set production `minContainers`, autoscaling, and core package, +- replace development secrets with production secrets or placeholders, +- plan managed-service data restore or migrations, +- configure production domains, DNS, public access, SMTP, object storage, backups, queues, search, and cache as needed. -Use following syntax to run all commands in the same environment context. For example, if one command changes the current directory, the next command continues in that directory. When one command creates an environment variable, the next command can access it. +Before opening production traffic, get familiar with the deeper Zerops production surface: service modes, scaling, deploy pipeline, health checks, backups, public access, and domains. If the app should use a real domain, follow [Public Access Configuration](/references/networking/public-access). -```yaml -buildCommands: - - | - bun i - bun run build -``` +Project export/import creates the production infrastructure. Do not rely on it as the code delivery mechanism. The app source should be in git, and the first production code deploy should come through the production deploy trigger. -#### Run build commands as a separate shell instances +## 2. Connect the production deploy trigger -When the following syntax is used, each command is triggered in a separate environment context. For example, each shell instance starts in the home directory again. When one command creates an environment variable, it won't be available for the next command. +Do this once for each production runtime that should build from git. -```yaml -buildCommands: - - bun i - - bun run build -``` +The simplest path is the Zerops GitHub or GitLab integration in the production project: -#### Command exit code +1. Open the production runtime service. +2. Connect the git repository. +3. Choose **New tag** as the production trigger. +4. Add a tag filter if your team uses one, for example `v*`. +5. Keep production env vars and secrets in the production Zerops project. -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](logs#build-log) to troubleshoot the error. If the error log doesn't contain any specific error message, try to run your build with the --verbose option. +For stage, a branch trigger can be convenient. For production, a tag trigger is easier to reason about: a normal source push can update stage, while a deliberate release tag updates production. -```yaml -buildCommands: - - bun i --verbose - - bun run build -``` +If your team needs approvals, custom tests, generated artifacts, or stricter audit, use GitHub Actions or another CI system instead. In that setup, store a production-scoped `ZEROPS_TOKEN` in the CI secret store and run the production deploy from CI. -If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `buildCommands` are finished, the application build is completed and ready for the deploy phase. +## 3. Release an app change -### deployFiles +This is the repeatable operation after production infrastructure and the deploy trigger exist. The exact release command is yours: define it in your repository instructions, agent skill, CI guide, or team release checklist. -_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. +For example, if production deploys from release tags, the user instruction can be as direct as: -```yaml -# REQUIRED. Select which files / folders to deploy after -# the build has successfully finished -deployFiles: - - dist - - package.json - - node_modules +```text +Create the release tag for production and push it to git. ``` -Determines files or folders produced by your build, which should be deployed to your runtime service containers. - -The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. - -The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. - -#### Examples - -Deploys a folder, and a file from the project root directory: - -```yaml -deployFiles: - - dist - - package.json -``` +Use the wording that matches your CI/CD. The release step can be a manual CLI action, a `git push`, a tag push, a pull request, a protected branch merge, or a CI job. That part is your team preference and production setup, not a rule from these docs. -Deploys the whole content of the build container: +The important rule is that the agent should name what it pushed and whether that push triggers stage, production, both, or neither. If production release requires a tag, the final answer should say the tag name or the exact tag command. -```yaml -deployFiles: . -``` +## What not to carry into production -Deploys a folder, and a file in a defined path: +Do not copy these from the development project into production: -```yaml -deployFiles: - - ./path/to/file.txt - - ./path/to/dir/ -``` +- the `zcp` service, +- development `ZCP_API_KEY`, +- local `.mcp.json`, +- development secrets, +- test data unless it is intentionally migrated, +- dev-only utilities such as Mailpit or Adminer, +- `.zerops.app` preview routing as the final public entry point. -#### How to use a wildcard in the path +Use production-specific domains, secrets, backup policy, scaling, and release credentials. -Zerops supports the `~` character as a wildcard for one or more folders in the path. +## What the agent should hand you -Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` +A useful release handoff from the agent contains: -```yaml -deployFiles: ./path/~/to/file.txt -``` +- runtime and project where the change was verified, +- URL, endpoint, UI state, job result, or stored data that proves the requested behavior, +- commit, branch, PR, or suggested release tag, +- whether the git push triggers stage, production, both, or neither, +- services to keep, remove, or change before importing production infrastructure, +- env vars, managed services, migrations, or delivery settings touched, +- external secrets still needed, +- managed-service data that must be restored or migrated, +- production blockers that need a human decision. -Deploys all folders that are located in any path that begins with `/path/to/` +If the answer only says that files were changed, the release handoff is incomplete. Ask for the verification evidence and the exact release artifact. -```yaml -deployFiles: ./path/to/~/ -``` +Production hardening belongs in your team's production checklist. This page only defines the handoff from verified dev or stage work into production authority. -Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` +## Related production references -```yaml -deployFiles: ./path/~/to/ -``` +- [Production boundary](/zcp/security/production-policy) — Why production stays outside the agent loop. +- [Import & Export YAML Configuration](/references/import) — Project export and import reference. +- [Public Access Configuration](/references/networking/public-access) — Custom domains, DNS, SSL, and production public access. -:::note Example -By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` -::: -#### .deployignore -Add a `.deployignore` file to the root of your project to specify which files and folders Zerops should ignore during deploy. The syntax follows the same pattern format as [`.gitignore`](https://git-scm.com/docs/gitignore#_pattern_format). +---------------------------------------- -To ignore a specific file or directory path, start the pattern with a forward slash (`/`). Without the leading slash, the pattern will match files with that name in any directory. +# Zcp > Workflows > Package Running Service -:::tip -For consistency, it's recommended to configure both your `.gitignore` and `.deployignore` files with the same patterns. -::: -Examples: +Use packaging when a verified runtime should become a re-importable Zerops bundle. It is a handoff or reuse task after the app already works, not the normal way to deploy the next change. -```yaml title="zerops.yaml" -zerops: - - setup: app - build: - deployFiles: ./ -``` +You can ask for it directly: -```text title=".deployignore" -/src/file.txt -``` -The example above ignores `file.txt` only in the root src directory. -```text title=".deployignore" -src/file.txt +```text +Package appstage as a buildFromGit import bundle. +Commit it and push it to git. ``` -This example above ignores `file.txt` in ANY directory named `src`, such as: -- `/src/file.txt` -- `/folder2/folder3/src/file.txt` -- `/src/src/file.txt` - -:::note -`.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. -::: -### cache +The result is a single git repo that contains the app source, [`zerops.yaml`](/zerops-yaml/specification), and a project [import file](/references/import) named `zerops-project-import.yaml`. The import file uses `buildFromGit:` so a fresh Zerops project can rebuild the app from the repo instead of carrying source code inside YAML. -_OPTIONAL._ Defines which files or folders will be cached for the next build. +Packaging starts from a deployed Zerops runtime. If important source changes exist only on your laptop, deploy or push them first so the runtime and git repo match what you want to package. -```yaml -# OPTIONAL. Which files / folders you want to cache for the next build. -# Next builds will be faster when the cache is used. -cache: file.txt -``` +## When to package -The cache attribute helps optimize build times by preserving specified files between builds. +Package a runtime when you need: -The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). +- a running runtime and its managed dependencies reproduced in another Zerops project, +- a reusable starter, demo, handoff, customer project, or clean staging baseline, +- a repo commit that carries the Zerops import shape next to the app source, +- the destination project to build from git. -Learn more about the [build cache system](/features/build-cache) in Zerops. +Do not use packaging for: -### envVariables +- the next app deploy; use the normal build, deploy, and verify loop, +- the production release; production needs its own infrastructure, credentials, domains, and release trigger, +- moving managed-service data; backups and restores are separate. -_OPTIONAL._ Defines the environment variables for the build environment. +For production setup, follow [Promote to production](/zcp/workflows/promote-to-production). Packaging can help create a reusable app bundle, but it does not decide production infrastructure or release policy. -Enter one or more env variables in following format: +## What the agent prepares -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - base: bun@latest - … +The agent packages **one** runtime. If the project has dev and stage runtimes, it asks which one to use because they can have different env values, start commands, or `setup:` blocks. - # OPTIONAL. Defines the env variables for the build environment: - envVariables: - NODE_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` +Managed services come along as dependencies when the runtime's `zerops.yaml` needs their env references. You do not pick databases, caches, queues, or search services one by one. -Read more about [environment variables](env-variables) in Zerops. +The workflow then prepares: -## Runtime configuration +- `zerops-project-import.yaml` - the project and service shape for the destination project, +- `zerops.yaml` - the runtime build and run configuration, +- a git commit and push when git delivery is configured or explicitly requested. -### base +If the runtime has no usable `zerops.yaml` or git remote, the agent has to fix that first. A bundle is only useful when the destination project can pull source and build it from git. -_OPTIONAL._ Sets the base technology for the runtime environment. -If you don't specify the `run.base` attribute, Zerops keeps the current Bun version for your runtime. +## Env vars need review -Following options are available for Bun runtimes: +Project env vars are the main place where the agent may ask you to decide. Each value gets one bucket: -- `bun@1.3.9`, `bun@1.3`, `bun@latest` -- `bun@1.2.2`, `bun@1.2` -- `bun@nightly` -- `bun@canary` -- `bun@1.1.34`, `bun@1.1(Ubuntu only)` +| Bucket | Use for | Bundle result | +| --- | --- | --- | +| `infrastructure` | Values derived from managed services, such as database or cache references. | Omitted from project envs; the new managed service provides fresh values. | +| `auto-secret` | App-owned signing or encryption keys that can be regenerated. | Fresh generated secret on import. | +| `external-secret` | Third-party credentials such as Stripe, OpenAI, Mailgun, or GitHub. | `REPLACE_ME` placeholder. | +| `plain-config` | Literal non-secret config such as log level, feature flags, or public app settings. | Copied as-is. | +| `plain-config` | Literal non-secret config such as log level, feature flags, or public app settings. | Copied as-is. | -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: bun@latest - ... +Do not treat this as a key-name guessing game. The agent should inspect source code and ask when classification changes behavior. For example, regenerating a Laravel `APP_KEY`, Django `SECRET_KEY`, or session secret can break existing encrypted state. If state continuity matters, carry the existing value instead of generating a new one. - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: bun@latest - ... -``` +## What is not included -

- The base runtime environment contains {data.alpine.default}, the - selected major version of Bun, Zerops command line tool, `npm`, `yarn`, `git` and `npx` tools. -

+| Not included | What to do instead | +| --- | --- | +| Managed-service data | Restore from [Backup](/features/backup) or another migration path. | +| Real third-party secrets | Fill placeholders in the destination project before deploying. | +| Production domains, scaling, backups, and release triggers | Configure them in the destination project. | +| A repeatable production release process | Use your CI or release workflow; see [Promote to production](/zcp/workflows/promote-to-production). | +| A repeatable production release process | Use your CI or release workflow; see [Promote to production](/zcp/workflows/promote-to-production). | -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. -::: +## Use the bundle -If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: +After the bundle is pushed, import `zerops-project-import.yaml` in the destination project through the dashboard or with `zcli project project-import zerops-project-import.yaml`. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: bun@latest - ... +Before opening the new project to users: - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: - - bun@latest - prepareCommands: - - zsc add go@latest - ... -``` +- fill `REPLACE_ME` values, +- restore or seed data when needed, +- review service scaling and public access, +- run a normal deploy and verification pass in the destination project. -See the full list of supported [run base environments](/zerops-yaml/base-list). -To customise your build environment use the `prepareCommands` attribute. +---------------------------------------- -### os +# Zcp > Workflows > Build With Zcp -_OPTIONAL._ Sets the operating system for the runtime environment. -Following options are available: +Use Build and ship for the decisions that shape normal app work. ZCP MCP gives the agent Zerops project state, platform guidance, project-scoped operations, deploy evidence, and recovery rules. You still decide what should be built, where it should run, how strict the acceptance criteria are, and what happens after proof. -- `alpine` -- `ubuntu` +```text +Build a task board. +Tasks should stay saved after refresh. +``` -Default value is `alpine`. +A prompt can be that short when the outcome is enough. Add detail when it changes behavior, architecture, stack, runtime layout, acceptance criteria, credentials, delivery, packaging, or the production release. -We are currently using following os version: +The expected output is a verified running change, not only generated files. The agent should prove the request against a real runtime, real managed services when used, and the logs, events, and checks that explain what happened. -- {data.alpine.default} -- {data.ubuntu.default} +## The decisions -:::caution -The os version is fixed and cannot be customised. -::: +
+
+ Product prompt + Build a task board... +
+ -### ports +You do not run these steps by hand. They are the parts where your intent changes what the agent should do. If you do not specify a choice, the agent should infer from current project state and ask only when the decision changes cost, credentials, runtime layout, delivery, production risk, or destructive behavior. -_OPTIONAL._ Specifies one or more internal ports on which your application will listen. +## 1. Choose the runtime layout {#choose-the-runtime-layout} -Projects in Zerops represent a group of one or more services. Services can be of different types (runtime services, databases, message brokers, object storage, etc.). All services of the same project share a **dedicated private network**. To connect to a service within the same project, just use the service hostname and its internal port. +When the app runtime and dependencies are unclear, the workflow prepares the layout before feature work starts. It reads current state, uses existing services when they fit, creates missing runtimes or managed services when needed, and stops when the agent knows where app code belongs. -For example, to connect to a Bun service with hostname = "app" and port = 3000 from another service of the same project, simply use `app:3000`. Read more about [how to access a Bun service](/features/access). +The main user-facing choice is runtime layout. Let the agent infer it from the project, or name it in the prompt when it matters. -Each port has following attributes: +| Runtime layout | Use when | What to tell the agent | +| ------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------- | +| **Dev** | You want one mutable runtime for fast iteration, experiments, or early app work. | `Build a small Node.js API on dev.` | +| **Dev + stage** | You want a development runtime plus a separate runtime for review or release rehearsal. | `Build a Node.js API with PostgreSQL on dev+stage.` | +| **Stage / linked target** | You work from local files or a single target runtime and want the workflow to use that target. | `Use appstage as the deploy target for this local app.` | +| **Stage / linked target** | You work from local files or a single target runtime and want the workflow to use that target. | `Use appstage as the deploy target for this local app.` | -| parameter | description | -| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| port | Defines the port number. You can set any port number between _10_ and _65435_. Ports outside this interval are reserved for internal Zerops systems. | -| protocol | **Optional.** Defines the protocol. Allowed values are `TCP` or `UDP`. Default value is `TCP`. | -| httpSupport | **Optional.** `httpSupport = true` is the default setting for TCP protocol. Set `httpSupport = false` if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). `httpSupport = true` is available only in combination with the TCP protocol. | -| httpSupport | **Optional.** `httpSupport = true` is the default setting for TCP protocol. Set `httpSupport = false` if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). `httpSupport = true` is available only in combination with the TCP protocol. | +The layout is about app runtimes, not where the `zcp` binary runs. Remote setup can use any of these layouts from the `zcp@1` workspace. Local setup usually works from local files into a linked stage or app runtime. -### prepareCommands +Managed services such as PostgreSQL, Valkey, queues, search, storage, or mail are dependencies. The agent gets their state and wiring patterns, but app code deploys to runtime services. -_OPTIONAL._ Customises the Bun runtime environment by installing additional dependencies or tools to the runtime base environment. +## 2. Development {#develop-with-live-project-context} -

- The base Bun environment contains {data.alpine.default} the selected - major version of Bun, [Zerops command line tool](/references/cli) and `npm`, `yarn`, `git` and `npx` tools. To install - additional packages or tools add one or more prepare commands: -

+Development is still a normal coding conversation with the agent. You describe the product behavior, stack constraints, acceptance criteria, and anything the agent must not guess. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... +MCP adds the Zerops side of that conversation: current project state, platform knowledge, project-scoped operations, deploy/log evidence, verification checks, recovery rules, and saved work state. Because of that, you usually do not paste service inventory, env wiring, deploy logs, or a "deploy and verify" checklist into the prompt. - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Bun runtime environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +The useful things to name are: -When the first deploy with a defined prepare attribute is triggered, Zerops will +- the behavior you want and how it should be verified, +- stack, framework, managed-service, or runtime target preferences, +- whether the agent should inspect or continue existing work first, +- approval boundaries for cost, credentials, data, production, or destructive actions. -1. create a prepare runtime container -2. optionally: [copy selected folders or files from your build container](build-pipeline#copy-folders-or-files-from-your-build-container) -3. run the `prepareCommands` commands in the defined order +Expect the agent to ask when one of those choices is missing. Otherwise, it should use project context while it works and finish with proof or a blocker. -:::note -`run.prepareCommands` run in the `/home/zerops` directory. -::: +## 3. Choose delivery after proof {#choose-delivery-after-proof} -#### Command exit code +Delivery preference is how app work closes after there is a verified result. Include it in the original prompt or set it later. -If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. +The first functional deploy is still direct so the agent can prove the app runs. Delivery preference decides what happens after that proof and how later sessions should finish similar work. -#### Cache of your custom runtime environment +| Delivery preference | What it means | What to tell the agent | +| ---------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| **Keep direct deploy** | The agent keeps deploying directly to the target runtime for fast dev/stage iteration. | `Keep direct deploy for now.` | +| **Push to git** | The agent commits and pushes working changes to the configured repository. | `When the app works, push changes to git@github.com:my-org/task-board.git.` | +| **CI / handoff** | A repository integration, GitHub Actions workflow, release process, or human owns the next deploy. | `Set up GitHub Actions delivery for future deploys after the app works.` | +| **CI / handoff** | A repository integration, GitHub Actions workflow, release process, or human owns the next deploy. | `Set up GitHub Actions delivery for future deploys after the app works.` | -Some packages or tools can take a long time to install. Therefore, Zerops caches your custom runtime environment after the installation of your custom packages or tools is completed. When the second or following deploy is triggered, Zerops will use the custom runtime cache from the previous deploy if following conditions are met: +The workflow records the delivery choice so later work can follow it. Git credentials, CI secrets, and production credentials are separate from `ZCP_API_KEY`; see [Tokens and credentials](/zcp/security/tokens-and-project-access). -1. Content of the [build.addToRunPrepare](#copy-folders-or-files-from-your-build-container) and `run.prepareCommands` attributes didn't change from the previous deploy -2. The custom runtime cache wasn't invalidated in the Zerops GUI. +## 4. Package a verified runtime {#package-a-verified-runtime} -To invalidate the custom runtime cache go to `yyy` +After a runtime is verified, you can ask the agent to prepare it as a re-importable Zerops project bundle. Use this when the app should become a reusable starter, customer handoff, demo project, or clean staging project. -When the custom runtime cache is used, Zerops doesn't create a prepare runtime container and executes the deployment of your application directly. +The prompt can be one sentence: -#### Single or separated shell instances +```text +Package appstage as a buildFromGit import bundle, commit it, and push it to git so I can import it into a fresh Zerops project. +``` -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +The export workflow prepares `zerops-project-import.yaml` and `zerops.yaml` in the same git repo as the app. The import file contains one runtime with `buildFromGit:` pointing back to that repo, plus managed services needed for Zerops env references to resolve when the bundle is imported into a fresh project. -### Copy folders or files from your build container +The agent may still ask which runtime to package, which half of a dev+stage pair to use, how to classify project env vars, or how to configure git push. Once pushed, the target project can import the bundle from the dashboard or with `zcli project project-import zerops-project-import.yaml`. -

- The prepare runtime container contains {data.alpine.default}, the selected major version of Bun, [Zerops command line tool](/references/cli) and `npm`, - `yarn`, `git` and `npx` tools. -

+Packaging is not the next deploy of the same app. For the next app change, keep using the normal build/deploy/verify loop. Use packaging when the output you want is a git-backed import bundle; see [Package a running service](/zcp/workflows/package-running-service). -The prepare runtime container does not contain your application code nor the built application. If you need to copy some folders or files from the build container to the runtime container (e.g. a configuration file) use the `addToRunPrepare` attribute in the [build section](#build-pipeline-configuration). +## 5. Prepare the production release {#prepare-production-release} -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... - addToRunPrepare: ./runtime-config.yaml +The production release is where authority changes. The agent prepares verified work and release evidence; production execution belongs to Zerops project settings, CI, release tooling, or a deliberate human action with production credentials. - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Bun runtime environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +The useful split is: -In the example above Zerops will copy the `runtime-config.yaml` file from your build container **after the build has finished** into the new **prepare runtime** container. The copied files and folders will be available in the `/home/zerops` folder in the new prepare runtime container before the prepare commands are triggered. +| Job | How often | What happens | +| --- | --- | --- | +| **Production infrastructure** | Once per production project | Export the verified project as YAML in the GUI, edit it for production, then import it as a new project. | +| **Production deploy trigger** | Once per production runtime | Connect the production runtime to git, usually with a tag trigger. | +| **Production release** | Every release | Verify in dev/stage, push source to git, then trigger production through your tag or release process. | +| **Production release** | Every release | Verify in dev/stage, push source to git, then trigger production through your tag or release process. | -### initCommands +Production should be a separate Zerops project without a `zcp` service. Production credentials are not `ZCP_API_KEY`; keep them in CI or release tooling. For the full release guide, see [Promote to production](/zcp/workflows/promote-to-production). -_OPTIONAL._ Defines one or more commands to be run each time a new runtime container is started or a container is restarted. +## What the final answer should contain -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +For a completed app task, the agent should report: - # ==== how to run your application ==== - run: - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Bun application is started. - initCommands: - - rm -rf ./cache -``` +- the runtime service it changed, +- the deploy or verification target, +- the URL, endpoint, UI state, job result, or stored data that proves the requested behavior, +- managed services, env vars, or delivery settings it touched, +- the delivery preference, packaging output, or production release state that now applies. -These commands are triggered in the runtime container before your Bun application is started via the [start command](build-pipeline#start). +If the task is incomplete, the final answer should name the blocker, the evidence read, what was tried, and the decision or credential needed from you. -:::note -`run.initCommands` run in the `/var/www` directory. -::: -Use init commands to clean or initialise your application cache or similar operations. +---------------------------------------- -:::caution -The init commands will delay the start of your application each time a new runtime container is started (including the [horizontal scaling](scaling) or when a runtime container is restarted). +# Zcp > Setup > Local Agent Bridge -Do not use the init commands for customising your runtime environment. Use the [run:prepareCommands](build-pipeline#preparecommands-1) attribute instead. + +Local setup installs the `zcp` binary on your machine and runs it from the app directory where your agent works. + +Use it when the agent should work next to local files, local data, your desktop editor, terminal tools, and git credentials. The MCP server limits Zerops operations to one project, but the agent client runs as your local user, so local approvals and filesystem allowlists matter. + +[Remote setup](/zcp/setup/hosted-workspace) is the safer default when the agent does not need local files or tools. Use local setup when local control is the point. + +:::warning Local setup maturity +Local setup has more moving parts than remote setup and may change faster. The binary install path, `.mcp.json` shape, and files written by `zcp init` are still settling between releases. ::: -#### Command exit code +## Choose a local starting point -If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](logs#runtime-log) to troubleshoot the error. +Pick the folder that should own app work: -#### Single or separated shell instances +- **Empty local directory.** Start with no app code yet. The agent can create the app structure and use the MCP tools to select or create Zerops services. +- **Existing app directory.** Use this when app code, local data, editor setup, test fixtures, and git credentials already live on your machine. +- **Recipe prepared for local setup.** Use a recipe to create the Zerops service baseline, then run the agent locally from the directory that should own source changes. -You can configure your `initCommands` to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +After that choice, the mechanics are the same: install `zcp`, run `zcp init`, add `ZCP_API_KEY`, start VPN when private service access is needed, and link a runtime when the agent should deploy. -### envVariables +## What local setup gives the agent -_OPTIONAL._ Defines the environment variables for the runtime environment. +- **Local files as source.** The agent edits the directory on your machine, and deploys use that working directory. +- **Your editor and terminal.** Framework CLIs, test runners, local data, and local feedback stay under your normal tools. +- **Your git credentials.** Pushes use your local git CLI, SSH agent, or credential helper. +- **Zerops operations.** The MCP tools let the agent discover services, generate env snapshots, deploy to linked runtimes, read logs, and verify. +- **Private service access through VPN.** Your local app and shell reach private service hostnames through `zcli vpn up`. -Enter one or more env variables in following format: +Security note: local setup cannot protect your laptop from the agent client. Configure approvals as you would for any local coding agent. -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to run your application ==== - run: - # OPTIONAL. Defines the env variables for the runtime environment: - envVariables: - NODE_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` +## Prerequisites -Read more about [environment variables](env-variables) in Zerops. +- A Zerops project. Create one from the [Zerops dashboard](https://app.zerops.io/dashboard/project-add), from a [recipe](https://app.zerops.io/recipes), or use an existing development/staging setup. +- [zCLI](/references/cli) installed and authenticated on your machine. +- A compatible local agent client installed and logged in. +- A **single-project Zerops token**. Multi-project tokens are refused at startup. +- A local directory where the agent should run. -### start +You do not need MCP just to develop locally against Zerops services as a human. `zcli vpn up` plus your editor is enough. Add MCP when a local coding agent should also understand and operate Zerops. -_REQUIRED._ Defines the start command for your Bun application. +## 1. Get `ZCP_API_KEY` -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +The MCP server needs a Zerops API token that reaches exactly one project. For normal agent work, use a full-access token; read-only tokens can authenticate but fail on deploys, env changes, lifecycle actions, and other mutations. Token generation, rejected shapes, and rotation are covered in [Tokens and credentials](/zcp/security/tokens-and-project-access). - # ==== how to run your application ==== - run: - # REQUIRED. Your Bun application start command - start: bun start +## 2. Install `zcp` + +```bash +curl -sSfL https://raw.githubusercontent.com/zeropsio/zcp/main/install.sh | sh ``` -We recommend starting your Bun application using `bun start`. +The installer downloads the latest release for your platform into `~/.local/bin`, or `/usr/local/bin` when run as root. Verify the install: -### health check +```bash +zcp version +``` -_OPTIONAL._ Defines a health check. +If your shell cannot find `zcp`, add the install directory to `PATH` and reload the shell. -`healthCheck` requires either one `httpGet` object or one `exec` object. +## 3. Run `zcp init` -#### httpGet +From the local directory the agent should operate: -Configures the health check to request a local URL using a HTTP GET method. +```bash +zcp init +``` -Following attributes are available: +`zcp init` writes local MCP config and agent instructions: - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
+- `.mcp.json` - MCP server config for this directory. +- `CLAUDE.md` - agent instructions for Zerops work. +- `.claude/settings.local.json` - Claude Code per-project settings when that client is used. +- `~/.config/zerops/aliases` plus a shell-rc sourcing line - helper aliases for launching the agent here. +- `.zcp/state/` - workflow state created when MCP first writes local state. -**Example:** +Re-running `zcp init` may refresh generated config. `CLAUDE.md` preserves edits outside managed markers, but `.mcp.json` is regenerated from the token-less template. If you rerun it, re-check the `ZCP_API_KEY` block before launching the agent. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +## 4. Add `ZCP_API_KEY` - # ==== how to run your application ==== - run: - # REQUIRED. Your Bun application start command - start: bun start +`zcp init` writes a token-less `.mcp.json`. Add the project token under the `env` block: - # OPTIONAL. Define a health check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - healthCheck: - httpGet: - port: 80 - path: /status +```json +{ + "mcpServers": { + "zerops": { + "command": "zcp", + "args": ["serve"], + "env": { + "ZCP_API_KEY": "" + } + } + } +} ``` -#### exec - -Configures the health check to run a local command. -Following attributes are available: +Add `.mcp.json` to `.gitignore`. It contains a live Zerops credential and should not leave the machine. Each app directory should have its own `.mcp.json` and token. -| Parameter | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **command** | Defines a local command to be run. -The command has access to the same [environment variables](create#set-secret-environment-variables) as your Bun application. -A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. | +The server name `zerops` is intentional. Do not rename it unless your agent client requires a different name and you understand the prompt/instruction changes. -**Example:** +## 5. Launch the agent from the app directory -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +Start the agent from the directory that contains `.mcp.json`. The client should list `zerops` as an available MCP server. - # ==== how to run your application ==== - run: - # REQUIRED. Your Bun application start command - start: bun start +Sanity check: - # OPTIONAL. Define a health check with a shell command. - healthCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user +```text +List the Zerops services through MCP. ``` -### crontab - -_OPTIONAL._ Defines cron jobs. +A working connection answers with the runtime and managed services. If not, check the launch directory, token scope, and whether the client loaded `.mcp.json`. -Setup cron jobs in the following format: +## 6. Bring up VPN when private services are needed -```yaml -zerops: - # define hostname of your service - - setup: app +The MCP server can talk to the Zerops API without VPN. Your local app, shell, tests, database clients, and framework commands need VPN to reach private hostnames such as `db` or `cache`. - # ==== how to run your application ==== - run: - crontab: - # REQUIRED. Sets the command to execute: - - command: "" - # REQUIRED. Sets the interval time to execute: - timing: "0 * * * *" +```bash +zcli vpn up ``` -Read more about setting up [cron](/zerops-yaml/cron) in Zerops. +VPN setup needs admin or root approval on macOS and Linux. The tools can tell the agent which command is needed, but they cannot approve or start it for you. After the tunnel is up, service hostnames resolve from your machine; rerun the command when local service connections fail. -## Deploy configuration +## 7. Generate local env when needed -### readiness check +When the local app needs service credentials, ask the agent for the app work and let the tools generate the env bridge. For a standalone check: -_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](deploy-process#readiness-checks) in Zerops. +```text +Generate a .env file for my local app from Zerops env references. +``` -`readinessCheck` requires either one `httpGet` object or one `exec` object. +Env generation needs `zerops.yaml` in the working directory, the runtime or setup the local app should use, a matching `setup:` entry, and non-empty `run.envVariables` under that setup. -#### httpGet +The tools read `run.envVariables`, resolve Zerops references such as `${db_user}`, `${db_password}`, and `${db_hostname}`, and write the resulting values into `.env`. Cross-service references resolve recursively, so a `DATABASE_URL` can land as a complete local connection string. -Configures the readiness check to request a local URL using a http GET method. +If those inputs are missing, the agent should fix `zerops.yaml` or ask for the target runtime/setup. It should not invent env values from service names or dashboard memory. -Following attributes are available: +The file is a snapshot, not a live sync. Regenerate it after changing env variables in Zerops. VPN is still required for your local app to use private service hostnames from that `.env`. - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
+Keep `.env` out of git. It contains real connection values. -**Example:** +## 8. Link a deploy target -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +Local setup needs a Zerops runtime when the agent should deploy from your working directory. A stage runtime is the usual target because it lets local work prove itself before the production release. - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - httpGet: - port: 80 - path: /status +If there is exactly one runtime, the agent can use it automatically. If multiple runtimes exist, it should ask which one to link: - # ==== how to run your application ==== - run: ... +```text +Link this local directory to appstage for deploys. ``` -Read more about how the [readiness check works](deploy-process#readiness-checks) in Zerops. +Without a linked runtime, the tools can still inspect services and generate env snapshots, but local deploys need a target first. -#### exec +## What stays outside -Configures the readiness check to run a local command. -Following attributes are available: +MCP does not replace your local feedback loop. Vite, Valet, Docker Compose, your IDE runner, framework CLIs, local fixtures, and test data stay under your normal tooling. -| Parameter | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **command** | Defines a local command to be run. -The command has access to the same [environment variables](create#set-secret-environment-variables) as your Bun application. -A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. | +Local setup does not mount Zerops runtime filesystems on your laptop. Remote setup can mount runtime files into the workspace; local setup works from files on your machine. To inspect runtime files from your machine, use [SSH](/references/networking/ssh) directly. -**Example:** +The MCP server does not own your git credentials. In local setup, your local git CLI, SSH agent, or credential helper handles pushes. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +## Local setup checks - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user -``` +- **Launch directory matters.** Start the agent from the folder that contains `.mcp.json`. +- **`zcp init` can remove the token from `.mcp.json`.** Re-add `ZCP_API_KEY` after rerunning init. +- **VPN is separate from MCP auth.** MCP may work while your app still cannot reach `db`. +- **`.env` generation depends on `run.envVariables`.** If generation fails, check that the working directory has `zerops.yaml`, the selected `setup:` exists, and env entries live under `run.envVariables`. +- **`.env` is a credential snapshot.** Regenerate after env changes and keep it out of git. -Read more about how the [readiness check works](deploy-process#readiness-checks) in Zerops. +## Next steps + +- [Build and ship](/zcp/workflows/build-with-zcp) - normal app work after setup. +- [Tokens and credentials](/zcp/security/tokens-and-project-access) - token scope, storage, rotation, and destructive confirmations. ---------------------------------------- -# Bun > How To > Build Process +# Zcp > Setup > Hosted Workspace +A remote workspace puts the agent, terminal, and optional browser IDE inside Zerops, next to private networking and ZCP access. ----------------------------------------- +The `zcp@1` service runs the same `zcp` binary used by local setup, but broad shell permissions and private service access stay in a clean Zerops service instead of on your laptop. -# Bun > How To > Controls +Use remote setup when you want the default workspace, a safer boundary for broad agent permissions, or a preconfigured environment with a bundled coding agent and Browser VS Code. +App code still deploys to your app runtime services. The `zcp` service is the workspace and control surface; it is not the application runtime. +Taking over is straightforward in this setup. You open the same workspace, terminal, files, and workflow status the agent used, then continue, inspect, or stop the work from there. ----------------------------------------- +## What it includes -# Bun > How To > Create +- **`zcp@1` workspace service.** Runs ZCP inside Zerops and gives the agent project-scoped operations. +- **Platform-injected `ZCP_API_KEY`.** Zerops injects the token into the workspace; you normally do not set it by hand. +- **Bundled coding agent when enabled.** The **Include Coding Agent** option installs and preconfigures one of the supported agents: Claude Code (Anthropic), Codex (OpenAI), Antigravity, or Grok Build. You authenticate with your own subscription login or API credentials. +- **Browser VS Code when enabled.** The **Cloud IDE** option gives you a browser editor, terminal, and a place to supervise or take over the agent session. +- **Private networking.** The workspace can reach managed services by hostname without laptop VPN. +- **Open workspace model.** You can add other agent CLIs, private MCP servers, helper processes, dotfiles, package installs, or a derived team image. +For the local alternative, see [Run locally](/zcp/setup/local-agent-bridge). For the tradeoffs, see [Remote or local setup](/zcp/setup/choose-workspace). -Zerops provides a powerful Bun runtime service with extensive build support. The Bun runtime is highly scalable and customizable to suit your development and production needs. With just a few clicks or commands, you can have a production-ready Bun environment up and running in no time. +## Choose a starting point -## Create a Bun service using Zerops GUI +### First-time trial -First, set up a project in the Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu under the **Services** section. From there, you can add a new Bun service: +Use the [Quickstart](/zcp/quickstart) when you want the guided recipe route. It covers the recipe catalog, **AI Agent** environment, coding agent authentication, Browser VS Code, first product prompt, and proof. -[Video: /vids/services/bun.webm](/vids/services/bun.webm) +After provisioning, continue with a product prompt in [Build and ship](/zcp/workflows/build-with-zcp). -### Choose a Bun version +### Recipe with AI Agent environment -Zerops supports the following Bun versions: +Use this when you want a guided stack baseline for development or staging. A recipe with an **AI Agent** environment creates app services, managed services, and the `zcp@1` workspace together. -:::info -You can easily [upgrade](upgrade) the major version at any time later. -::: +Keep **Coding Agent** enabled when you want a bundled coding agent. Keep **Cloud IDE** enabled when you want Browser VS Code. -### Set a hostname +### New Zerops setup with remote setup enabled -Enter a unique service identifier like "app", "cache", "gui", etc. Duplicate services with the same name within the same project are not allowed. +Use this when you want blank services or a custom stack. -#### Limitations: +1. Open [Add new project](https://app.zerops.io/dashboard/project-add). +2. Enter the project name, region, and tags. +3. Enable the `zcp@1` remote setup service. +4. Keep **Include Coding Agent** enabled if you want a bundled coding agent. +5. Keep **Cloud IDE** enabled if you want browser VS Code. +6. Create the project. -- Maximum 25 characters -- Must contain only lowercase ASCII letters (a-z) or numbers (0-9) +This gives you the `zcp@1` workspace. App runtimes and managed services may still be created later by normal ZCP app work. -:::caution -The hostname is fixed after the service is created and cannot be changed later. -::: +### Existing development or staging setup -### Set secret environment variables +Use this when runtime or managed services already exist in development or staging. Do not add `zcp` to production; promote verified work through your release process. -Add environment variables with sensitive data, such as passwords, tokens, salts, certificates, etc. These will be securely saved inside Zerops and added to your runtime service upon start. +Add a `zcp` service from the dashboard the same way you add another Zerops service. The workspace appears next to the existing services and receives ZCP access from the platform. -Setting secret environment variables is optional. You can always set them later in the Zerops GUI. +The agent should still read current state before changing anything. Existing services are context, not instructions for the next task. -Read more about the [different types of environment variables](env-variables#service-env-variables) in Zerops. +## Open the workspace -## Create a Bun service using zCLI +For a returning remote workspace, open the existing `zcp` service: -zCLI is the Zerops command-line tool. To create a new Bun service via the command line, follow these steps: +1. Open the project in the [Zerops dashboard](https://app.zerops.io/). +2. Open the `zcp` service. +3. Use **Browser VS Code** when **Cloud IDE** is enabled. +4. Complete your coding agent login or API-token flow if prompted (Claude Code, Codex, Antigravity, or Grok Build). -1. [Install & setup zCLI](/references/cli) -2. [Create a project description file](create#create-a-project-description-file) -3. [Create a project with a Bun and PostgreSQL service](#full-example) +After authentication, your coding agent is connected to ZCP and ready to work from the Browser VS Code terminal. If the workspace was already authorized, use the same route to resume, supervise, or take over work. -### Create a project description file +First load can take a minute while the image, Cloud IDE, and bundled agent finish starting. If the page opens before the service is ready, wait until the service is running and reload. -Zerops uses a YAML format to describe the project infrastructure. +## Use your own editor or tools -#### Basic example: +Browser VS Code is the quickest entry point, not the only one. -Create a directory called `my-project`. Inside the `my-project` directory, create a `description.yaml` file with the following content: -```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in Bun@{version} format - type: bun@latest - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' -``` +Editors that support remote development can connect to the workspace or runtime services over SSH, depending on how your team wants to work. Common options include VS Code Remote SSH, JetBrains Gateway, Cursor, Zed, and plain SSH. -The yaml file describes your future project infrastructure. The project will contain one Bun service with default [auto scaling](scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](build-pipeline#ports). Following secret env variables will be configured: +This keeps the agent and private network inside Zerops while letting you use a desktop editor UI. Broader editor patterns live in [Local & Remote Development](/features/local-remote-development#native-ide-over-ssh). -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` +You can also install another agent CLI or additional MCP servers inside the `zcp` service. The bundled agent flow is a convenience, not a closed product boundary. -#### Full example: +## Advanced customization guardrails -Create a directory my-project. Create an description.yaml file inside the my-project directory with following content: +Tools installed inside the `zcp` service may see workspace environment variables, private networking, and any runtime files mounted into the workspace. Use trusted and pinned tools. Keep model credentials, git delivery tokens, external API keys, and production credentials out of the workspace unless the current task explicitly needs them. -```yaml -# basic project data -project: - # project name - name: my-project - # optional: project description - description: A project with a Bun and PostgreSQL database - # optional: project tags - tags: - - DEMO - - ZEROPS -# array of project services -services: - - # service name - hostname: app - # service type and version number in Bun@{version} format - type: bun@latest - # optional: vertical auto scaling customization - verticalAutoscaling: - cpuMode: DEDICATED - minCpu: 2 - maxCpu: 5 - minRam: 2 - maxRam: 24 - minDisk: 6 - maxDisk: 50 - startCpuCoreCount: 3 - minFreeRamGB: 0.5 - minFreeRamPercent: 20 - # defines the minimum number of containers for horizontal autoscaling. Max value = 6. - minContainers: 2 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 4 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' - - # second service hostname - hostname: db - # service type and version number in postgresql@{version} format - type: postgresql@12 - # mode of operation "HA"/"non_HA" - mode: NON_HA -``` +## What belongs where -The yaml file describes your future project infrastructure. The project will contain a Bun service and a [PostgreSQL](/postgresql/overview) service. +| Concern | Where it belongs | +| -------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| Agent workspace | The `zcp@1` service: agent CLI, browser VS Code, shell tools, MCP servers, helper processes, dotfiles. | +| App code deploys | Your app runtime services; not the `zcp` workspace service. | +| `ZCP_API_KEY` | Injected by Zerops into the `zcp` workspace. | +| Agent account | Your agent subscription login or model API credential. Zerops wires the agent to ZCP, but the agent account remains yours. | +| Git credentials | Configured inside the workspace when the agent should commit or push from remote setup. | +| Production release | A separate production project and release process. | +| Production release | A separate production project and release process. | -Bun service with "app" hostname, the internal port(s) the service listens on will be defined later in the [zerops.yaml](build-pipeline#ports). Bun service will run with custom vertical and horizontal scaling. Following secret env variables will be configured: +## Runtime file access -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` +Remote setup can mount runtime service filesystems into the `zcp` workspace after the first setup pass. Each mounted runtime appears as its own folder. Editing a mounted file changes the file inside that runtime service, with no upload step from your laptop. -The hostname of the PostgreSQL service will be set to "db". The [single container](/features/scaling#single-container-mode)(/features/scaling#deployment-modes-databases-and-shared-storage) mode will be chosen and the default auto [scaling configuration](/postgresql/how-to/scale#configure-scaling) will be set. +Filesystem reach is narrower than network reach. The workspace can reach services over the private network, but it only sees runtime files mounted into it. -#### Description of description.yaml parameters +## Make customization persistent -The `project:` section is required. Only one project can be defined. +The `zcp@1` service is a normal Zerops service. One-off shell installs disappear when the service is rebuilt unless you make them part of the service setup. -| Parameter | Description | Limitations | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -| **name** | The name of the new project. Duplicates are allowed. | | -| **description** | **Optional.** Description of the new project. | Maximum 255 characters. | -| **tags** | **Optional.** One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects. | -| **tags** | **Optional.** One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects. | +Use these patterns: -At least one service in `services:` section is required. You can create a project with multiple services. The example above contains Bun and PostgreSQL services but you can create a `description.yaml` with your own combination of [services](/features/infrastructure). +- **Small additions:** put package installs, dotfiles, or bootstrap scripts into service init commands. +- **Team-standard workspace:** build a derived image based on `zcp@1` with required tools already present. +- **Helper processes:** run private helpers next to the agent and editor workspace when your team needs internal integrations. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
- hostname - - The unique service identifier. -
    -
  • duplicate services with the same name in the same project are forbidden
  • -
  • maximum 25 characters
  • -
  • must contain only lowercase ASCII letters (a-z) or numbers (0-9)
  • -
-
- type - - Specifies the service type and version. +Keep app runtime build steps with the runtime services. The remote workspace carries the agent, tools, and ZCP access; runtime services own app builds and deploys. - See what [Bun service types](/references/import-yaml/type-list#runtime-services) are currently supported. -
- verticalAutoscaling - - Optional. Defines [custom vertical auto scaling parameters](/bun/how-to/scaling#configure-scaling). +## Next steps - All verticalAutoscaling attributes are optional. Not specified attributes will be set to their default values. -
- - cpuMode - - Optional. Accepts `SHARED`, `DEDICATED` values. Default is `SHARED` -
- - minCpu/maxCpu - - Optional. Set the minCpu or maxCpu in CPU cores (integer). -
- - minRam/maxRam - - Optional. Set the minRam or maxRam in GB (float). -
- - minDisk/maxDisk - - Optional. Set the minDisk or maxDisk in GB (float). -
- minContainers - - Optional. Default = 1. Defines the minimum number of containers - for [horizontal autoscaling](/bun/how-to/scaling#configure-scaling). +- [Build and ship](/zcp/workflows/build-with-zcp) - normal app work after setup. +- [Tokens and credentials](/zcp/security/tokens-and-project-access) - how `ZCP_API_KEY`, git credentials, and CI secrets differ. - Limitations: - Current maximum value = 10. -
- maxContainers - - Defines the maximum number of containers for [horizontal autoscaling](/bun/how-to/scaling#configure-scaling). +---------------------------------------- - Limitations: +# Zcp > Setup > Choose Workspace - Current maximum value = 10. -
- envSecrets - - Optional. Defines one or more secret env variables as a key value - map. See env variable [restrictions](env-variables#env-variable-restrictions). -
-### Create a project based on the description.yaml +Use this page to decide where the agent workspace lives: inside Zerops, or on your machine beside the local app directory. -When you have your `description.yaml` ready, use the `zcli project project-import` command to create a new project and the service infrastructure. +Both setups connect the agent to one Zerops project and the same project-scoped operations. The tradeoff is where the agent works: filesystem ownership, private-service access, credential location, bundled tooling, and shell blast radius. The runtime layout is a separate app-work decision. -```sh -Usage: - zcli project project-import importYamlPath [flags] +## What you are choosing -Flags: - -h, --help Help for the project import command. - --org-id string If you have access to more than one organization, you must specify the org ID for which the - project is to be created. - --working-dir string Sets a custom working directory. Default working directory is the current directory. (default "./") -``` +**Remote setup** always includes the `zcp@1` workspace service. If the chosen **runtime layout** has a development runtime, the agent works with that service too. -Zerops will create a project and one or more services based on the `description.yaml` content. +**Local setup** does not need the workspace service or a separate development runtime. It runs beside your **local source tree** and deploys to the Zerops runtime you choose to link. -Maximum size of the `description.yaml` file is 100 kB. +Remote setup is the **safer default** for broader agent autonomy because the agent shell, private networking, and workspace files stay **inside Zerops** instead of on your machine. Use local setup when local files, data, desktop tools, git credentials, or a **local-only agent client** need to stay local. -You don't specify the project name in the `zcli project project-import` command, because the project name is defined in the `description.yaml`. +## Setup comparison -If you have access to more than one client, you must specify the client ID for which the project is to be created. The `clientID` is located in the Zerops GUI under the client name on the project dashboard page. +| | Remote setup | Local setup | +| ----------------------- | ------------------------------------------------- | -------------------------------------------- | +| Workspace service | Always has `zcp@1`. | Not required. | +| Development runtime | Only if the runtime layout includes one. | Not required for local work. | +| `zcp` process | Runs in Zerops. | Runs on your machine. | +| Agent process | Runs in the remote workspace. | Runs in your local editor or CLI. | +| Files the agent edits | Workspace files and mounted runtime files. | Files on your machine. | +| Private service access | Private Zerops network from the workspace. | Zerops VPN from your machine. | +| Token storage | Injected into the workspace service. | `.mcp.json` in the local app directory. | +| Git credentials | Configured inside the workspace service. | Your local git credentials. | +| Safety posture | Broad agent shell permissions stay in Zerops. | Agent shell permissions affect your machine. | +| Safety posture | Broad agent shell permissions stay in Zerops. | Agent shell permissions affect your machine. | -### Add Bun service to an existing project +## Starting points -#### Example: +Remote setup can start from: -Create a directory `my-project` if it doesn't exist. Create an `import.yaml` file inside the `my-project` directory with following content: +- **Recipe with AI Agent environment.** A guided path for a known stack. A recipe creates app services, managed services, and the `zcp@1` workspace together. +- **New Zerops setup with remote setup enabled.** Start from blank services or a custom stack and add the `zcp@1` service during creation. +- **Existing development or staging setup.** Add the `zcp` workspace next to services that already exist. Do not add ZCP to production; promote verified work through your release process instead. -```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in Bun@{version} format - type: bun@latest - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' -``` +Local setup can start from: -The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one Bun service with default [auto scaling](scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: +- **Empty local directory.** The agent creates the app structure from a product request and uses ZCP to select or create Zerops services. +- **Existing app directory.** The app code, editor setup, local data, and git credentials already live on your machine. +- **Recipe prepared for local setup.** The recipe creates the Zerops service baseline, while the agent and files stay local. -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` +## Runtime layout is separate -The content of the `services:` section of `import.yaml` is identical to the project description file. The `import.yaml` never contains the `project:` section because the project already exists. +Remote or local only answers where the agent and `zcp` process run. The project can still use: -When you have your `import.yaml` ready, use the `zcli project service-import` command to add one or more services to your existing Zerops project. +- one mutable dev runtime, +- a dev + stage pair, +- a single app runtime, +- local files linked to a stage target. -```sh -Usage: - zcli project service-import importYamlPath [flags] +That choice belongs to app work: [Build and ship](/zcp/workflows/build-with-zcp#choose-the-runtime-layout). -Flags: - -h, --help Help for the project service import command. - -P, --project-id string If you have access to more than one project, you must specify the project ID for which the - command is to be executed. -``` +Stage is not production. Keep production in a separate Zerops project and promote work through your release process; see [Production boundary](/zcp/security/production-policy). -zCLI commands are interactive, when you press enter after `zcli project service-import importYamlPath`, you will be given a list of your projects to choose from. +## Switching later -Maximum size of the import.yaml file is 100 kB. +Remote and local setup are not permanent, but switching is a handoff between workspaces, not a sync operation. Before switching, make the handoff explicit: ----------------------------------------- +- Preserve the current source tree through git or another explicit copy path. +- Choose one deploy source for the next task: the remote workspace, mounted runtime files, or the local app directory. +- Do not edit mounted runtime files and a local repo in parallel unless you have a merge plan. +- Regenerate local `.env` snapshots after Zerops env changes. +- If the local deploy target changed, have the agent inspect the current local link before deploying. -# Bun > How To > Customize Runtime +## Next steps +- [What remote workspace gives you](/zcp/setup/hosted-workspace) - remote setup, Browser VS Code, bundled agent CLI, and workspace persistence. +- [Run locally](/zcp/setup/local-agent-bridge) - local install, `zcp init`, `.mcp.json`, VPN, env snapshots, and deploy target linking. +- [Trust model](/zcp/security/trust-model) - how the safety boundary changes between remote setup and local setup. ---------------------------------------- -# Bun > How To > Deploy Process +# Zcp > Security > Trust Model +The trust model starts with one rule: one ZCP process operates one Zerops project. `ZCP_API_KEY` decides that boundary at startup, and ZCP refuses tokens that resolve to no project or multiple projects. ----------------------------------------- +That boundary is strong on the Zerops side. It does not make the agent harmless. A valid token can still deploy, change env vars, restart services, read logs, scale services, and change public access when Zerops permissions allow it. Treat it like an operations credential. -# Bun > How To > Env Variables +## Boundary summary +| Question | Answer | +| ------------------------------------ | ------------------------------------------------------------------------------------------- | +| What project can ZCP see? | Exactly one project resolved from `ZCP_API_KEY` at startup. | +| What can ZCP change? | Whatever Zerops RBAC grants that token inside the project. | +| What is outside reach? | Other projects, organization-wide settings, billing, and any operation Zerops RBAC rejects. | +| What network can remote setup reach? | Private services from inside the `zcp` service. | +| What network can local setup reach? | The Zerops API directly, plus private services only when your laptop VPN is up. | +| Who owns the agent login? | You. The agent subscription or model API key is separate from `ZCP_API_KEY`. | +| Who owns the agent login? | You. The agent subscription or model API key is separate from `ZCP_API_KEY`. | +Zerops [RBAC](/features/rbac) remains the authority. ZCP does not bypass platform permissions; it exposes project operations to the agent only through the token it was given. ----------------------------------------- +## Remote and local blast radius -# Bun > How To > Filebrowser +Remote setup and local setup share the same Zerops boundary, but not the same surroundings. +| Area | Remote setup | Local setup | +| -------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------- | +| Agent location | Inside the `zcp@1` service when **Include Coding Agent** is enabled | On your machine through your editor or CLI agent | +| Files visible to the agent | Workspace files and mounted runtime files | Local files and anything your client permits | +| Private service access | Private network without laptop VPN | `zcli vpn up ` from your machine | +| Local machine exposure | No direct access to your laptop | Agent client runs as your local user | +| Best safety posture | Keep ZCP in a development/staging project and avoid mounting unrelated files | Restrict client permissions, shell access, and filesystem scope | +| Best safety posture | Keep ZCP in a development/staging project and avoid mounting unrelated files | Restrict client permissions, shell access, and filesystem scope | +Remote setup is contained inside Zerops by design. Local setup is supervise-the-client by design. Either can be right, but local setup requires more attention to your agent client's local permissions. ----------------------------------------- +## Credential ownership -# Bun > How To > Logs +There are three separate credential surfaces people often mix together: +| Credential | Owner | Purpose | +| ----------------------------------- | ---------------------------- | ------------------------------------------------------ | +| `ZCP_API_KEY` | Zerops token | Lets ZCP operate one Zerops project. | +| Agent subscription or model API key | You / the agent provider | Lets the coding agent run. Zerops does not provide it. | +| Git or CI credentials | You / your repository system | Lets finished work push to git or deploy through CI. | +| Git or CI credentials | You / your repository system | Lets finished work push to git or deploy through CI. | +In both setups, the agent account is still authenticated through the agent's own login flow. For where each credential lives (remote injection vs `.mcp.json`), rotation, rejected token shapes, and `GIT_TOKEN` / `ZEROPS_TOKEN`, see [Tokens and credentials](/zcp/security/tokens-and-project-access). ----------------------------------------- +## What the token lets the agent do -# Bun > How To > Scaling +The agent can perform normal operational work when the token has permission: +- discover runtime and managed services, +- create or adjust services when the task requires it, +- read and write service env vars, +- deploy app code to runtime services, +- read build logs, runtime logs, and service events, +- restart, reload, stop, start, or scale services, +- enable or disable public access, +- prepare delivery such as git push or CI handoff. +This is why development and staging projects are the right place for ZCP. Production should be a separate project without a `zcp` service; see [Production boundary](/zcp/security/production-policy). ----------------------------------------- +## Remote setup specifics -# Bun > How To > Shared Storage +- **`zcp` service is not the app.** It is the workspace and control surface. Deploys target app runtimes, not the `zcp` service. +- **The service has operational reach.** A terminal in the `zcp` service can use the same ZCP access as the agent. Review the dashboard's additional changes before deploying the service; they are what give the workspace its operating surface. +- **Network reach is broader than file reach.** The workspace can reach private services, but it only sees runtime files that are mounted into it. +- **Do not hand-edit `ZCP_API_KEY`.** Remote setup gets the value from Zerops. Manual replacement can break the intended one-project boundary. +## Local setup specifics +- **The agent inherits local reach.** ZCP MCP is limited to one project, but the local agent client can read files, run commands, and use credentials allowed by your client settings. +- **Each local directory has its own config.** `.mcp.json` and `.zcp/state/` belong to one app directory. Launching from the wrong directory can connect the wrong token or no token. +- **VPN is outside MCP authority.** Bringing up Zerops VPN needs your operating-system approval. The tools cannot grant that for the agent. +- **`.env` files are snapshots.** They contain real project credentials and should stay out of git. ----------------------------------------- +## Human confirmation gates -# Bun > How To > Trigger Pipeline +Most project operations do not get an extra ZCP-specific confirmation prompt. Deploys, env changes, restarts, scaling, and public-access changes are normal project operations and are audited through platform evidence. +ZCP MCP adds hard gates where the loss is not safely reversible from the conversation: **service deletion** (explicit same-conversation approval by service name; remote setup also blocks deleting the `zcp` service it is running in) and **wholesale service replacement after failed deploy history** (refuse-then-acknowledge with failure evidence first). Approval from an old chat does not carry forward. The full enforcement rules are in [Tokens and credentials → What ZCP enforces for destructive actions](/zcp/security/tokens-and-project-access#what-zcp-enforces-for-destructive-actions). +## Audit evidence ----------------------------------------- +Zerops records platform-side evidence. It does not record the agent's private reasoning, every shell edit, browser-helper action, or prompt history outside your agent client. -# Bun > How To > Upgrade +When taking over from an agent, read evidence in this order: +1. service-scoped events, +2. build logs, +3. runtime logs, +4. deploy and verification output, +5. git history when delivery uses git-push. +| Surface | What it proves | What it does not prove | +| -------------- | ------------------------------------------------------------------------- | -------------------------------------------- | +| Service events | Deploy lifecycle, failures, restarts, scaling, and public-access changes. | The exact source edit that caused the event. | +| Build logs | Dependency install, build commands, compile/package failures. | Runtime request behavior after deploy. | +| Runtime logs | Start crashes, port binding, request-time app errors. | Why the build failed. | +| Verify output | Whether reachability and requested behavior passed. | That unrelated app flows work. | +| Git history | Source changes pushed during git-push delivery. | Uncommitted shell edits. | +| Git history | Source changes pushed during git-push delivery. | Uncommitted shell edits. | ----------------------------------------- +Filter by service hostname when possible. Project-level timelines can include unrelated services and older failures. -# Bun > Overview +## Related security +- [Tokens and credentials](/zcp/security/tokens-and-project-access) - token scope, storage, rotation, and confirmation gates. +- [Remote or local setup](/zcp/setup/choose-workspace) - compare blast radius before setup. +- [Production boundary](/zcp/security/production-policy) - keep production outside the agent loop. -[Bun ↗](https:/bun.org/en) is an asynchronous event-driven JavaScript runtime, which is designed to build scalable network applications. -As said, there is no need for coding yet, we have created a [Github repository ↗](https://github.com/zeropsio/recipe-bun), a **_recipe_**, containing the most simple Bun web application. The repo will be used as a source from which the app will be built. +---------------------------------------- -### 🚀 Feel free to deploy the recipe yourself +# Zcp > Security > Tokens And Project Access -This is the most bare-bones example of Bun app running in Zerops — as few libraries as possible, - just a simple endpoint with connect, read and write to a Zerops PostgreSQL database. - [Deploy "bun" recipe on Zerops](https://app.zerops.io/recipe/?lf=bun) +ZCP uses a Zerops API token to operate exactly one project. The important rule is simple: `ZCP_API_KEY` is the Zerops credential for ZCP, not an agent login, not a git token, and not a general account token. -1. Log in/sign up to [Zerops GUI ↗](https://app.zerops.io) +Remote setup gets `ZCP_API_KEY` from Zerops. Local setup reads it from `.mcp.json`. In both setups, ZCP validates the token at startup and refuses tokens that resolve to no project or multiple projects. -2. In the **Projects** box click on **Import a project** and paste in the following YAML config ([source ↗](https://github.com/zeropsio/recipe-bun/blob/main/zerops-project-import.yaml)): +## Credential map -```yaml -project: - name: recipe-bun - tags: - - zerops-recipe +| Name | What it authorizes | Where it belongs | +| ---------------------------- | -------------------------------------------- | --------------------------------------------------------------------------- | +| `ZCP_API_KEY` | ZCP against one Zerops project | Remote: `zcp` service env injected by Zerops. Local: `.mcp.json` env block. | +| Agent login or model API key | The coding agent itself | The bundled agent in remote setup, or your local agent client. | +| `GIT_TOKEN` | Git push from remote setup to a git provider | Secret env var on the `zcp` service when remote git-push delivery needs it. | +| `ZEROPS_TOKEN` | `zcli` in GitHub Actions or external CI | Separate Zerops delivery token stored in the CI/release secret store. | +| `ZEROPS_TOKEN` | `zcli` in GitHub Actions or external CI | Separate Zerops delivery token stored in the CI/release secret store. | -services: - - hostname: api - type: bun@1.1 - enableSubdomainAccess: true - buildFromGit: https://github.com/zeropsio/recipe-bun +Keeping these names separate prevents most setup and delivery failures. - - hostname: db - type: postgresql@16 - mode: NON_HA - priority: 1 -``` +## Recommended `ZCP_API_KEY` shape -3. Click on **Import project** and wait until all pipelines have finished. +Use a Zerops API token with **Custom access per project**, exactly one selected project, and **Full access** for normal agent work. -**That's it, your application is now up and running! :star: Let's check it works:** +Read-only tokens can authenticate, but they fail as soon as the agent needs to deploy, write env vars, restart services, scale, or change public access. Account-wide or multi-project tokens are refused before the agent can operate. -1. A _subdomain_ should have been enabled and visible in the project's **IP addressed & Public Routing Overview** box. Its format should look similar to this `https://api-806-3000.prg1.zerops.app`. -2. Click or the `subdomain` URL to open it in a browser and you should see +To generate the token: -``` -{"message":"This is a simple, basic Bun application running in Zerops.io,\n each request adds an entry to the PostgreSQL database and returns a count.\n See the source repository (https://github.com/zeropsio/recipe-bun) for more information.","newEntry":"dfd1e873-bfc8-4f36-af07-e32561820b93","count":"1"} -``` +1. Open [Settings -> Access Tokens Management](https://app.zerops.io/settings/token-management). +2. Create a token and name it for the project, for example `zcp-`. +3. Choose **Custom access per project**. +4. Add exactly one project. +5. Set that project to **Full access** for normal ZCP MCP work. +6. Create the token and copy the value. Zerops shows it only at creation time. -:::tip -Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. -::: +The token's blast radius equals the project and its granted permissions. Other projects, organization settings, and billing stay out of reach. Zerops [Roles & Permissions](/features/rbac#integration-tokens) remain the platform authority. -## How to start +## Rejected token shapes -It doesn't matter whether it's your first curious introduction to Zerops, you have already mastered the basics and are looking for a tiny detail or inspiration. Below, choose a section that fits your needs: +ZCP validates token shape at startup. -- [Care for details?](/bun/how-to/create) — Dive in all Zerops has to offer for your Bun application. -- [Bun recipes](https://github.com/zeropsio?q=Bun&type=all&language=&sort=) — Get inspired by already existing repositories, ready to be imported to Zerops. +| Token shape | What happens | Fix | +| ----------------------------------- | ------------------------------------------- | -------------------------------------------------------------------- | +| Account-wide or multi-project token | ZCP refuses to start. | Generate a token scoped to exactly one project. | +| Token with no project access | ZCP refuses to start. | Grant one project or create a new single-project token. | +| Expired or revoked token | ZCP refuses to start or receives HTTP 401. | Replace the token and restart the agent or ZCP process. | +| Read-only project token | Startup may pass, but mutations fail later. | Use full access for normal agent work, or expect read-only behavior. | +| Read-only project token | Startup may pass, but mutations fail later. | Use full access for normal agent work, or expect read-only behavior. | -## Feature Highlights +Common messages: -- [Create Bun service](/bun/how-to/create) — Start with creating a Bun service using GUI or zCLI. -- [Zerops.yaml](/bun/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to create your own app. -- [Scaling configuration](/bun/how-to/scaling) — Set up scaling of your Bun application so that it runs smoothly while using only necessary resources. +| Message | Meaning | +| -------------------------------------------------------------- | ------------------------------------------------- | +| `Token accesses N projects; use project-scoped token` | The token can see more than one project. | +| `Token has no project access` | The token authenticates but reaches no project. | +| `No authentication found: set ZCP_API_KEY or log in with zcli` | The `zcp` process did not receive a usable token. | +| `AUTH_TOKEN_EXPIRED` or HTTP 401 | The token expired, was revoked, or is invalid. | +| `AUTH_TOKEN_EXPIRED` or HTTP 401 | The token expired, was revoked, or is invalid. | -{" "} +For ZCP MCP setup, provide `ZCP_API_KEY`. `zcli` login is a diagnostic fallback, not the normal agent setup. -- [Customize build environment](/bun/how-to/build-process#customize-build-environment) -- [Customize runtime environment](/bun/how-to/customize-runtime) +## Where the token lives - remote vs local {#where-the-token-lives--remote-vs-local} -## When in doubt, reach out +ZCP reads `ZCP_API_KEY` from its process environment at startup. It does not write the token somewhere else or exchange it for a derived credential. -Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. +| Setup | Where `ZCP_API_KEY` comes from | Who provisions it | +| -------------------------------------------- | ------------------------------------------------------- | -------------------------------------------------------- | +| [Remote setup](/zcp/setup/hosted-workspace) | The `zcp` service environment | Zerops injects it automatically when the service starts. | +| [Local setup](/zcp/setup/local-agent-bridge) | The `env` block of `.mcp.json` in the app directory | You add it after `zcp init`. | +| [Local setup](/zcp/setup/local-agent-bridge) | The `env` block of `.mcp.json` in the app directory | You add it after `zcp init`. | -In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. +In remote setup, do not hand-edit `ZCP_API_KEY`. Replace or rotate it through the Zerops-managed surface so the service keeps the intended project boundary. -Have you build something that others might find useful? Don't hesitate to share your knowledge! +In local setup, `zcp init` writes a token-less `.mcp.json`. Add the token manually: -- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. +```json +{ + "mcpServers": { + "zerops": { + "command": "zcp", + "args": ["serve"], + "env": { + "ZCP_API_KEY": "" + } + } + } +} +``` -## Popular Guides +Add `.mcp.json` to `.gitignore`. Each app directory should have its own file and token. Switching projects means switching directories, not editing one shared credential. -- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. -- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. +## Agent credentials are separate +The bundled agent in remote setup may ask you to sign in or provide a model API key. That is not `ZCP_API_KEY`. ----------------------------------------- +Zerops wires the agent to ZCP. It does not provide your model subscription, store your agent login, or rotate your agent provider credentials. Treat the agent account exactly as you would outside Zerops. -# Clickhouse > Overview +## Git and CI credentials +`GIT_TOKEN` matters only when remote setup pushes to a git remote. It authorizes git provider access from the `zcp` service. In local setup, your local git CLI uses your normal SSH key or credential helper, so ZCP does not need `GIT_TOKEN`. -Zerops provides a fully managed [ClickHouse](https://clickhouse.com/) columnar database optimized for blazing-fast analytical queries on massive datasets, making it ideal for data warehousing and real-time analytics applications. +`ZEROPS_TOKEN` is a Zerops API token used by GitHub Actions or another CI system when that system runs `zcli` against Zerops. It is not a GitHub token. Use a separate delivery token so ZCP sessions and CI/release workflows can be named, rotated, and audited independently. -## Supported Versions +For production delivery, `ZEROPS_TOKEN` should reach production only and live only in the production CI or release secret store. -Currently supported ClickHouse version: +With GitHub CLI, the secret shape is: -Import configuration version: +```bash +gh secret set ZEROPS_TOKEN -b "$ZEROPS_DELIVERY_TOKEN" +``` -- `clickhouse@25.3` +Use the GitHub UI or your CI secret manager instead if your team does not allow local CLI secret writes. -## Service Configuration +## Rotation -Our ClickHouse implementation features optimized default settings designed for analytical workloads and data warehousing use cases. +Rotate in the Zerops dashboard, then update the surface that consumes the token. -### Resource Allocation +| Surface | Rotation step | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Remote `ZCP_API_KEY` | Reconfigure or redeploy the remote workspace through the dashboard-managed flow, then restart the `zcp` service so the process gets the new value. | +| Local `ZCP_API_KEY` | Paste the new token into `.mcp.json`, then restart the local agent client. | +| `ZEROPS_TOKEN` in CI | Replace the repository or CI secret. The next workflow run uses the new value. | +| `GIT_TOKEN` | Replace the git-provider credential stored for remote setup. | +| `GIT_TOKEN` | Replace the git-provider credential stored for remote setup. | -Zerops automatically allocates resources to your ClickHouse service based on demand within the limits defined in your [automatic scaling configuration](/features/scaling). +Rotation is picked up on the next process start or CI run, not in the middle of a live agent session. -## High Availability and Deployment Modes +## What ZCP enforces for destructive actions -:::important -Deployment mode is selected during service creation and cannot be changed later. -::: +A valid token does not remove every guardrail. ZCP MCP adds explicit confirmation for operations where the loss is not safely reversible from inside the conversation. -### High-Availability (HA) Setup +| Operation | Gate | +| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Service deletion | Requires explicit approval in the same conversation, including the service name. Remote setup also blocks deleting the `zcp` service it is running in. | +| Wholesale service replacement after failed deploy history | The first request refuses, surfaces what would be replaced, and requires the agent to read failure evidence before asking you to confirm. | +| Wholesale service replacement after failed deploy history | The first request refuses, surfaces what would be replaced, and requires the agent to read failure evidence before asking you to confirm. | -The recommended solution for production workloads and mission-critical analytics: +Deploys, env changes, lifecycle actions, restarts, scaling, and public-access changes do not get an additional ZCP-specific confirmation gate. They are normal operations for a full-access token and should be reviewed through service events, logs, verification output, and team policy. -* **3 data nodes** with automatic monitoring, repairs, and replication factor of 3 -* **Default cluster name:** `zerops` (currently 1 shard with 3 replicas) +Approval from a previous chat does not carry forward. A new conversation needs a new approval. -#### Replication Configuration +## Evidence before destructive recovery -The `Replicated` database engine handles replication automatically, but there are specific requirements you need to follow: +When a service has recent failure history, ZCP enforces one recovery rule: read the platform evidence before destroying or replacing the service. -**For Database Operations** -Use this configuration when creating/managing databases: +The agent should inspect service events, build logs, runtime logs, and failure summaries, then either fix the cause or show you the evidence before asking for destructive confirmation. The point is to preserve the failure context the next session needs. -```sql -CREATE DATABASE uk ON CLUSTER '{cluster}' -ENGINE = Replicated('/clickhouse/databases/{uuid}', '{shard}', '{replica}'); -``` +A service waiting for first code deploy is not the same thing as a failed service. The gate is about recorded failure history, not idle state. -**For Table Operations** -Use `ENGINE = ReplicatedMergeTree` when creating tables (without the `ON CLUSTER '{cluster}'` clause): +Threat model and boundaries: [Trust model](/zcp/security/trust-model). -```sql -CREATE TABLE uk.uk_price_paid -( - price UInt32, - date Date, - postcode1 LowCardinality(String), - postcode2 LowCardinality(String), - type Enum8('terraced' = 1, 'semi-detached' = 2, 'detached' = 3, 'flat' = 4, 'other' = 0), - is_new UInt8, - duration Enum8('freehold' = 1, 'leasehold' = 2, 'unknown' = 0), - addr1 String, - addr2 String, - street LowCardinality(String), - locality LowCardinality(String), - town LowCardinality(String), - district LowCardinality(String), - county LowCardinality(String) -) ENGINE = ReplicatedMergeTree ORDER BY (postcode1, postcode2, addr1, addr2); -``` +## Credential checks -For more details see: -- https://clickhouse.com/docs/engines/database-engines/replicated -- https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication -- https://clickhouse.com/docs/sql-reference/distributed-ddl +- **Account-wide full-access tokens are refused.** ZCP needs one project, not a broad account credential. +- **`zcp init` regenerates `.mcp.json`.** Re-add `ZCP_API_KEY` after rerunning it. +- **`GIT_TOKEN` is not `ZCP_API_KEY`.** One authorizes git provider access; the other authorizes Zerops operations. +- **`ZEROPS_TOKEN` in GitHub Actions is not a GitHub PAT.** It is a Zerops API token for `zcli`. +- **A rotated token needs a restart.** The live ZCP process keeps the old environment value until it starts again. +- **A successful confirmation is still destructive.** Backups, git history, and service events are your recovery evidence; ZCP does not auto-rollback a confirmed deletion or replacement. -You can use other `Replicated*` engines from the MergeTree family. Replication is only supported for tables in the MergeTree family: +## Related pages -* `ReplicatedMergeTree` -* `ReplicatedSummingMergeTree` -* `ReplicatedReplacingMergeTree` -* `ReplicatedAggregatingMergeTree` -* `ReplicatedCollapsingMergeTree` -* `ReplicatedVersionedCollapsingMergeTree` -* `ReplicatedGraphiteMergeTree` +- [Trust model](/zcp/security/trust-model) - the access boundary this page enforces. +- [What remote workspace gives you](/zcp/setup/hosted-workspace) - automatic token injection. +- [Run locally](/zcp/setup/local-agent-bridge) - local `.mcp.json` token setup. +- [Production boundary](/zcp/security/production-policy) - why production gets separate credentials. +- [GitHub integration](/references/github-integration) - CI secret usage with Zerops. -User management (users, grants, etc.) is replicated by Keeper by default. The `ON CLUSTER '{cluster}'` clause is not needed when creating/deleting users or changing grants. -The default `` database follows these practices. If you don't follow these recommendations, it is possible you will face issues in case of fail and repair scenario. +---------------------------------------- -### Single Container Installation +# Zcp > Security > Production Policy -Suitable for development and testing environments: -* Consists of 1 ClickHouse node -* Lower resource requirements -* No automatic replication +Use the MCP setup in development or staging. Keep production in a separate Zerops project without a `zcp` service. Production deploys should come from CI, a release pipeline, or a deliberate human `zcli` push using production credentials. -:::warning -Use for development purposes or non-critical data only. **Make sure to have backups enabled** if using in production, as you can lose your data due to container volatility. -::: +Zerops does not prevent you from adding `zcp` to production. The policy exists because ZCP MCP gives a coding agent operational access. In production, that is the wrong blast radius for normal app development. -## Network Access & Protocols +The production boundary does not make ZCP output disposable. The intended path is production-shaped dev or stage infrastructure, verified behavior, and then a controlled production release outside the agent loop. -Zerops automatically configures secure authentication for your ClickHouse service. +## Recommended project layout -### Default Database -Zerops creates a default database with the same name as your service hostname (``) during service creation. +| Project | Contains | Who operates it | +| ----------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------ | +| Development / staging project | `zcp` service, agent workspace, dev runtime, optional stage runtime, non-production managed services | Agent plus humans | +| Production project | Production runtimes, production managed services, production env values, production backups and scaling | CI/release process plus humans | +| Production project | Production runtimes, production managed services, production env values, production backups and scaling | CI/release process plus humans | -### Default Users +The two projects use different Zerops tokens. A development token cannot reach production. A production token should not be placed in the development `zcp` service or a local `.mcp.json` used by the agent. -#### `zerops` User -* Created automatically upon service creation -* Has privileges for the default database -* Password available as environment variable `password` +## Why production is a separate project -#### `super` User -* Administrative user for cluster management -* Can create new databases, users, and manage permissions -* Password available as environment variable `superUserPassword` +- **The Zerops project is the security boundary.** ZCP binds to one project at startup. Keeping production separate prevents a development agent from touching it by accident. +- **Secrets stay clean.** Production env values, database credentials, object-storage keys, and third-party secrets stay in the production project. +- **Operational policies can differ.** Production often needs HA services, stronger backup retention, stricter scaling, alerts, and release approvals. Development can stay cheaper and more flexible. +- **Audit trails stay readable.** Development experiments and agent retries do not mix with production deploy evidence. -### Access Methods +This separation matters even when the same source repository deploys to both projects. -Services within the same project can access ClickHouse directly using: -``` -: -``` +## What stage proves -For HA cluster setups, you can also access specific data nodes: -``` -node-stable-<1..3>.db..zerops: -``` +Stage is the production-like rehearsal inside development or staging. It is where the agent proves the change before the release leaves the ZCP loop. -For external access, use `zcli` VPN to connect using the same connection strings. +Use stage to match production where it matters: -ClickHouse offers multiple interfaces for different use cases: +- same runtime family and version, +- same managed service types, +- same build and start command pattern, +- same deploy route, +- behavior checks against a real running service. -#### Native TCP Protocol -**Port:** `9000` (Environment variable: `port` or `portNative`) +Stage is not production. It should use non-production data and non-production secrets. A green stage means the change is ready for release, not that the agent should deploy to production itself. -Optimal for high-performance applications and ClickHouse-native clients. +## The release -More about it in [official ClickHouse docs](https://clickhouse.com/docs/interfaces/tcp). +After stage verifies, ZCP's job is done for that change. The production release happens outside the agent loop: -#### HTTP/HTTPS Interface -**Port:** `8123` (Environment variable: `portHttp`) +- CI deploys a merged commit or release tag to the production project. +- A release pipeline runs `zcli push` with a production-scoped `ZEROPS_TOKEN`. +- A human runs `zcli push` against the production project with production credentials. -Ideal for web applications and REST API integrations. +The agent can prepare the handoff by pushing code, summarizing verification evidence, and naming the runtime and URL it verified. It should not bridge development to production. -It is also possible to setup HTTPS domain access or enable subdomain for access from outside the project. Then you can access the database using following URL: -- `https://clickhouse.my-awesome-domain.tld` -- JDBC connection string example (use `ssl=true&sslmode=NONE` options): -`jdbc:clickhouse:https://clickhouse.my-awesome-domain.tld:443/?ssl=true&sslmode=NONE` +For the practical workflow, see [Promote to production](/zcp/workflows/promote-to-production). -More about it in [official ClickHouse docs](https://clickhouse.com/docs/interfaces/http). +## Credential rules -#### MySQL Protocol -**Port:** `9004` (Environment variable: `portMysql`) +| Credential | Production policy | +| ----------------------------------- | -------------------------------------------------------------------------------------------------------- | +| Development `ZCP_API_KEY` | Never grants production access. Keep it scoped to the development/staging project. | +| Production `ZEROPS_TOKEN` | Store only in the production CI/release secret store. Do not place it in the development `zcp` service. | +| Agent subscription or model API key | May be used by the agent, but it does not grant Zerops production access by itself. | +| Git credentials | May push source changes, but production deploy authority should stay with the release process. | +| Git credentials | May push source changes, but production deploy authority should stay with the release process. | -Enables connectivity from MySQL-compatible tools and applications. +If a production deploy fails, investigate in the production project with production logs, events, backups, and CI output. Do not attach the development agent directly to production as a shortcut. -More about it in [official ClickHouse docs](https://clickhouse.com/docs/interfaces/mysql). +## Production separation rules -#### PostgreSQL Protocol -**Port:** `9005` (Environment variable: `portPostgresql`) +| Rule | Why it matters | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| Keep the production project without a `zcp` service | Production should not host an agent workspace with operational access. | +| Keep production tokens out of local `.mcp.json` | Local agents should operate development or staging projects, not production. | +| Keep production `ZEROPS_TOKEN` in the release secret store | Development tooling should not deploy to production outside the release process. | +| Treat stage proof as release evidence, not production approval | Stage is the rehearsal; production approval is a separate release decision. | +| Promote through CI, release tooling, or a deliberate human action | Production execution should use production credentials. | +| Promote through CI, release tooling, or a deliberate human action | Production execution should use production credentials. | -Allows integration with PostgreSQL-compatible clients and ORMs. +## Acceptable agent involvement -More about it in [official ClickHouse docs](https://clickhouse.com/docs/interfaces/postgresql). +The agent can still help before the production release: -## Backup and Recovery +- make the code change in development, +- deploy and verify dev/stage runtimes, +- produce the URL, endpoint result, or UI proof it verified, +- push or prepare the branch your team uses for review, +- summarize release notes and known blockers for the human or CI handoff. -Zerops provides comprehensive backup functionality using ClickHouse's native backup capabilities. +ZCP's involvement stops at the handoff. Production execution belongs to the release process. -### Backup Process +## Related security -* Backups are performed using ClickHouse SQL command `BACKUP ALL ...` with `super` user permissions -* All databases are backed up (excluding system databases) -* Backup files are stored as `tar.gz` archives -* Contains the complete folder structure produced by the SQL backup command +- [Promote to production](/zcp/workflows/promote-to-production) - practical production release paths after ZCP proof. +- [Trust model](/zcp/security/trust-model) - the boundary that makes this policy enforceable. +- [Tokens and credentials](/zcp/security/tokens-and-project-access) - production and development credentials stay separate. -### Restore Options -#### Option 1: Custom S3 Bucket Restore +---------------------------------------- -1. Download backup from Zerops GUI or via API -2. Extract the tar.gz archive and upload to your S3 bucket -3. Restore using ClickHouse SQL commands: +# Zcp > Reference > Troubleshooting -```sql --- Restore specific table -RESTORE TABLE mydb.mytable AS mydb.mytable2 -FROM S3('https://storage-prg1.zerops.io/mybucket/path/to/dir/with/untarred/backup', - 'my-access-key-id', 'my-secret-key'); --- Restore all data -RESTORE ALL FROM S3('https://storage-prg1.zerops.io/mybucket/path/to/backup', - 'my-access-key-id', 'my-secret-key'); +Use troubleshooting when the agent is confused, a session was interrupted, deploy keeps failing, verification does not match the final answer, or you are taking over manually. --- see https://clickhouse.com/docs/operations/backup#configuring-backuprestore-to-use-an-s3-endpoint -``` +Start from current state, not chat memory: -#### Option 2: Support-Assisted Restore +```text +Read current project status and tell me where things stand before changing anything. +``` -Contact Zerops support on Discord, and we'll place the backup on the container's filesystem for restoration using the `File` driver (see [ClickHouse documentation](https://clickhouse.com/docs/operations/backup) for further info). +That should make the agent read live services, saved workflow state, recent deploys, logs, events, and verification output before it edits anything else. -:::note -A simple GUI/API action for backup restoration is on our roadmap for future releases. -::: +## Find where the run is stuck -## Troubleshooting +| Stuck point | Ask for | What you should get | +| ----------- | ------- | ------------------- | +| Agent lost context | Current project status and services in scope. | Runtime target, managed services, last deploy, last verify result, and any saved workflow state. | +| Service setup is unclear | Runtime target and dependency plan. | Which existing services will be used, which missing services are needed, and what needs human approval. | +| Deploy failed | Failure category plus build logs, runtime logs, and recent service events. | A cause or next diagnostic step, not another blind deploy. | +| Runtime is reachable but app behavior fails | The failing behavior check and request-time runtime logs. | Endpoint/UI/job/data evidence tied to the product request. | +| Local app cannot reach services | VPN state, generated `.env`, and selected runtime/setup. | Whether MCP auth works separately from private service access. | +| Delivery is ambiguous | Delivery mode, git-push state, build integration, or handoff note. | What will happen after proof: direct deploy, git push, CI, package, or production handoff. | +| Delivery is ambiguous | Delivery mode, git-push state, build integration, or handoff note. | What will happen after proof: direct deploy, git push, CI, package, or production handoff. | -### Common Issues +Useful prompt: -#### Connection Problems -* Verify you're using the correct port for your chosen protocol -* Check that your service is running and healthy in the Zerops dashboard -* For HA clusters, try connecting to specific nodes if the main endpoint fails -* Ensure authentication credentials are correct +```text +Show me the runtime in scope, failure category, evidence read, fixes tried, and the next decision needed. +``` -#### Replication Issues -* Verify you're using `ON CLUSTER '{cluster}'` for database operations -* Confirm tables use `ReplicatedMergeTree` engines +## Evidence order -## Learn More +The useful evidence depends on the failure category surfaced by deploy or verify tools. -- [Official ClickHouse Documentation](https://clickhouse.com/docs) - Comprehensive guide to ClickHouse features and SQL syntax -- [ClickHouse Replication Guide](https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication) - Detailed replication concepts -- [Distributed DDL Reference](https://clickhouse.com/docs/sql-reference/distributed-ddl) - Cluster operations documentation +| Category | Read first | Avoid | +| -------- | ---------- | ----- | +| `build` | Build logs, build commands, dependency manifests, deploy file list. | Runtime logs; the runtime did not start yet. | +| `start` | Prepare/runtime logs, start command, ports, env references. | Rebuilding without checking why the process exited. | +| `verify` | Failing check detail, HTTP response, request-time runtime logs, stored state. | Calling a green deploy "done" before behavior passes. | +| `network` | VPN, SSH, DNS, subdomain readiness, service status, transport error. | Editing app code before proving connectivity. | +| `config` | Field-level rejection, `zerops.yaml`, setup name, env references, service settings. | Guessing from service names or dashboard memory. | +| `credential` | The named credential surface: `ZCP_API_KEY`, git, SSH, managed-service, CI, or external API. | Rotating unrelated secrets. | +| `other` | Raw events/logs and the exact phase that failed. | Repeating the same attempt after the same unknown reason. | +| `other` | Raw events/logs and the exact phase that failed. | Repeating the same attempt after the same unknown reason. | -## Support +Failure categories come from the deploy/verify evidence surface. They are not a verdict; they tell the agent where the next useful signal is. -For advanced configurations or custom requirements: -- Join our [Discord community](https://discord.gg/zerops) -- Contact support via [email](mailto:support@zerops.io) +## Local setup checks ----------------------------------------- +Local setup has two separate connections: -# Company > About +- MCP uses `ZCP_API_KEY` to talk to the Zerops API. +- Your local app and shell use `zcli vpn up` to reach private service hostnames such as `db` or `cache`. +That means MCP can work while the app cannot reach the database. -## Our Story +| Symptom | Check | +| ------- | ----- | +| Agent does not list the `zerops` MCP server. | Relaunch the agent from the directory containing `.mcp.json`. | +| MCP startup says the token reaches multiple projects. | Replace `ZCP_API_KEY` with a single-project token. | +| Re-running `zcp init` made MCP disappear. | Re-add the `ZCP_API_KEY` env block to `.mcp.json` and restart the agent. | +| Local app cannot reach `db`, `cache`, or storage hostnames. | Run `zcli vpn up ` again. | +| Local app reads stale credentials. | Regenerate `.env`; it is a snapshot, not a live sync. | +| `zcp` is not found after install. | Add `~/.local/bin` or the install target to `PATH`, then restart the shell/agent. | +| `zcp` is not found after install. | Add `~/.local/bin` or the install target to `PATH`, then restart the shell/agent. | -Zerops, originally founded in 2018, began as an internal project at [vshosting.eu](https://vshosting.eu), one of the largest providers of managed hosting solutions in Central Europe. In June 2024, after a period when the project had been shut down following corporate restructuring, Zerops was re-launched as an independent startup. Now headed by the original development team and backed by strong partners, Zerops continues its mission with renewed focus and independence. +For local setup details, use [Run locally](/zcp/setup/local-agent-bridge). -## Technology & Infrastructure +## Manual takeover -Zerops runs on bare metal, with the platform built from the ground up using Golang and [Incus](https://linuxcontainers.org/incus/) containerization. Our servers are currently located in Prague, Czech Republic, leveraging vshosting's state-of-the-art datacenter facilities. +If you take over from the agent, read evidence in this order: -## Financial Backing & Partners +1. Service list and runtime target. +2. Service-scoped events for the runtime in question. +3. Build logs for build failures, runtime logs for start or request failures. +4. Verify output for reachability and requested behavior. +5. Git history only when delivery uses git-push or CI. -Zerops is financially backed by established venture capital firms: -- [Presto Ventures](https://www.prestoventures.com/) - A leading Central European venture capital firm -- [Gi21 Capital](https://gi21capital.com/) - A technology-focused investment firm +Do not inspect every service first. Start with the runtime in scope and expand only when the evidence points to a dependency. -Our primary infrastructure partner is [vshosting.eu](https://vshosting.eu), which itself is part of [Contabo](https://contabo.com/en/), owned by global investment firm [KKR](https://www.kkr.com/). This strategic partnership provides Zerops with enterprise-grade infrastructure stability. +## When to stop -## Looking Ahead +Stop the loop when: -We're committed to continually improving the Zerops platform with a focus on: +- the same failure repeats without new evidence, +- the agent needs an external credential, +- the target runtime or stage choice is ambiguous, +- a destructive action would delete or replace a service, +- production release authority is needed, +- the request no longer fits the current project layout. -- **Multiregional Deployment**: Beginning with built-in CDN capabilities, followed by the ability to run entire projects in different regions -- **Enhanced Performance**: Ongoing optimization of our container orchestration and resource management -- **Developer Experience**: Continuous improvement of our UI, CLI, and API interfaces +A blocker is acceptable only when it names the runtime in scope, failure category, evidence read, fixes attempted, and the human decision or credential still needed. -## Connect With Us +Before destructive recovery, read service-scoped events, logs, deploy/verify result, and git history when delivery uses git-push. Token scope and destructive confirmations are covered in [Tokens and credentials](/zcp/security/tokens-and-project-access). -- [Discord](https://discord.com/invite/WDvCZ54) -- [X.com](https://x.com/zeropsio) -- [LinkedIn](https://www.linkedin.com/company/zerops) -- [Contact Us](mailto:team@zerops.io) ---------------------------------------- -# Company > Branding +# Zcp > Reference > Mcp Operations -# Zerops Brand Assets +Most app work should be phrased as an outcome: build this, fix that, deploy and prove it. Operation names matter when you configure agent-client policy, debug an MCP integration, build a custom client, or use ZCP MCP pragmatically as a set of project-scoped Zerops tools. -Here you can find and download our official logos and badges in various formats. Please follow our brand guidelines when using these assets. +ZCP MCP is the MCP server exposed by the `zcp` binary. Any MCP-capable client can connect to it and call tools such as `zerops_discover`, `zerops_logs`, `zerops_events`, `zerops_deploy`, or `zerops_verify`. -## Download Assets +## Tool-only use -Below you'll find our official assets available in various formats. Click the download buttons to get the assets in your preferred format. +The MCP server exposes operations. It does not, by itself, decide the whole app lifecycle. -## Brand Guidelines +Claude Code with the generated workflow uses its instructions to decide sequencing: inspect state before changing things, choose the runtime target, use existing services or create missing ones, deploy, read failure evidence, verify requested behavior, and stop with proof or a blocker. -When using Zerops brand assets, please: +Tool-only use is valid when you want a custom MCP client, script, dashboard, policy-gated agent, or narrow operational task. In that setup, your integration owns the sequencing: -- Don't modify the logos or badges in any way -- Maintain adequate spacing around the assets -- Use the provided color versions (light/dark) as appropriate -- Don't use the Zerops logo or badges in a way that suggests partnership or endorsement without permission -- Don't use the assets as your own branding or as part of your logo +- which project services are in scope, +- when a deploy is allowed, +- what counts as verification, +- which logs or events should be read after failure, +- when to ask a human, +- when to stop. +Tool-level gates still apply. Service deletion requires explicit named approval, and destructive import override requires an acknowledgement of the exact targets. ----------------------------------------- +If you use Claude Code but do not want the generated workflow guidance, keep the MCP connection and remove the ZCP-managed workflow block from `CLAUDE.md`, or keep your own policy outside the ZCP markers. What you lose is the generated instruction layer that makes the agent plan around live state, deploy with bounded retries, verify behavior, and report proof or a concrete blocker. -# Company > Payment +Generated files and workflow state are documented in [Workflows in depth](/zcp/reference/agent-workflow#generated-files-and-state). +## What the tools can do -Zerops provides a transparent credit-based payment system that makes managing your account finances straightforward. You can easily add funds to your account through manual or automatic top-ups, track all your transactions, and download invoices for your records. +| Area | Tools | Typical use | +| ---- | ----- | ----------- | +| Discover | `zerops_discover` | Read services, service metadata, env-var keys, and project topology. | +| Observe | `zerops_logs`, `zerops_events`, `zerops_verify`, `zerops_process` | Diagnose deploys, read runtime/build evidence, run health checks, and watch async processes. | +| Deploy | `zerops_deploy` | Push source through Zerops build/deploy pipeline and return build/deploy evidence. | +| Configure | `zerops_env`, `zerops_subdomain`, `zerops_scale`, `zerops_manage` | Change env vars, public subdomain access, scaling, lifecycle, reload/restart, and storage attachment. | +| Import/export | `zerops_import`, `zerops_export`, `zerops_preprocess` | Import project/service YAML, read export YAML, and expand Zerops preprocessor expressions. | +| Workspace | `zerops_mount` | Mount or unmount runtime filesystems in remote setup. | +| Workflow | `zerops_workflow` | Track, recover, or configure workflow sessions and packaging/export flow. | +| Destructive | `zerops_delete` | Delete one named service after explicit user approval. | +| Destructive | `zerops_delete` | Delete one named service after explicit user approval. | -This page explains how to manage your account balance, set up payment preferences, and access your complete billing history to help you maintain uninterrupted service while keeping your finances organized. +Recipe-authoring and ZCP-internal maintenance operations are intentionally out of scope for this public reference. -## Manual Top-up +## Read-only operations -Manual top-ups give you direct control over your account funding. To add credits to your account immediately: +| Operation | Purpose | +| --------- | ------- | +| `zerops_discover` | Read services, ports, env-var keys, and current state. | +| `zerops_export` | Read platform project/service export YAML and service metadata. | +| `zerops_logs` | Read runtime/build logs filtered by service, severity, time, or search. | +| `zerops_events` | Read service activity, deploys, builds, scaling, and failures. | +| `zerops_verify` | Run service health, recent error log, and HTTP-readiness checks. | +| `zerops_knowledge` | Fetch ZCP MCP guidance or platform knowledge for the current state. | +| `zerops_process` | Check a known async process; cancel is a mutating action. | +| `zerops_process` | Check a known async process; cancel is a mutating action. | -1. Navigate to **Credit & Spend Overview** in the Organization section of the main menu -2. Click on **Top up credit** and fill in the [billing information](#billing-information) -3. Enter your desired top-up amount (minimum $10 VAT excl.) -3. Complete payment using your saved or new payment method +## Mutating operations -## Automatic Top-ups +| Operation | Purpose | +| --------- | ------- | +| `zerops_deploy` | Ship code through the Zerops build and deploy pipeline. | +| `zerops_env` | Read, set, delete, or generate env vars and local `.env` files. | +| `zerops_manage` | Start, stop, restart, reload, or connect storage. | +| `zerops_scale` | Change CPU, RAM, disk, CPU mode, or container autoscaling where supported. `HA`/`NON_HA` is set at service creation. | +| `zerops_subdomain` | Enable or disable public subdomain access. | +| `zerops_delete` | Delete a service. Explicit named approval is required. | +| `zerops_delete` | Delete a service. Explicit named approval is required. | -Automatic top-up ensures your projects continue running without interruption by replenishing your credits when they run low. +## Operational setup -:::note Prerequisites -Automatic top-ups are available once you have made at least one manual top-up, saved a payment method, and provided your [billing information](#billing-information). The saved card is charged off-session, so a valid payment method must stay on file. -::: +| Operation | Purpose | +| --------- | ------- | +| `zerops_workflow` | Track, recover, or configure workflow sessions; also carries the package-running-service export flow. | +| `zerops_import` | Import project/service definitions. Destructive override is gated. | +| `zerops_mount` | Mount or unmount runtime filesystems in remote setup. | +| `zerops_preprocess` | Expand Zerops preprocessor expressions. | +| `zerops_preprocess` | Expand Zerops preprocessor expressions. | -To turn them on, navigate to **Credit & Spend Overview** in the Organization section of the main menu, open the automatic top-up settings, and configure the three values described below. +## Remote and local tool differences -### How Automatic Top-ups Work +The operation names are the same, but the filesystem and network boundary differ. -When enabled, Zerops periodically checks your balance and tops it up by a fixed amount whenever your credit drops below a threshold you choose, up to a limit you set for each calendar month. -Zerops initiates an automatic payment when: +| Area | Remote setup | Local setup | +| ---- | ------------ | ----------- | +| Files | Runtime files through SSHFS or remote containers. | Local working directory. | +| Deploy source | Remote service or batch deploy inside Zerops. | Local `workingDir`. | +| Dev server | Remote setup can run or inspect remote dev processes. | Your local tool owns the dev server. | +| Env bridge | Env vars are already available in Zerops. | `.env` generation resolves Zerops references for local use. | +| Git | Workspace-managed credentials. | User's local git credentials. | +| Git | Workspace-managed credentials. | User's local git credentials. | -- Your combined balance (credit + promo credit) drops **below your threshold** -- You have automatic top-ups enabled -- The top-up wouldn't exceed your **calendar-month limit** +## Confirmation gates -:::note Important notes -- Each top-up charges the **fixed amount** you configured, regardless of how fast you're spending -- Your balance is checked periodically (every few minutes), so a top-up can take a few minutes to appear after you drop below the threshold -- The final automatic top-up of the month is reduced so the month's total lands exactly on your calendar-month limit; after the limit is reached, automatic top-ups pause until the next calendar month -- To avoid repeatedly hitting your payment method (which can get a card flagged or blocked by the payment processor), top-ups are spaced out: after a **successful** top-up Zerops waits **1 hour** before the next one, and after a **failed** top-up it waits **1 day** before trying again -- If a charge fails, Zerops notifies you so you can check the validity and available funds of your saved card. After **3 failed attempts in a row**, automatic top-up is turned off and you're notified by email; re-enable it once your payment method is working again -- Auto top-up limits don't affect manual payments — add any amount manually regardless of automatic settings -::: +Two operations require explicit care: -### Configuration Options +- **Service deletion** requires explicit user approval in the current conversation, by service name. +- **Destructive import override** first refuses and names what would be replaced; a second call must acknowledge the same targets. -#### Threshold -When your combined balance (credit + promo credit) drops below this value, an automatic top-up is triggered. +See [Tokens and credentials](/zcp/security/tokens-and-project-access#what-zcp-enforces-for-destructive-actions) for the user-facing confirmation flow. -#### Top-up Amount -The fixed amount charged to your saved card on each automatic top-up. +## Related reference -- Minimum: $10 (matches the minimum manual payment) -- Maximum: $10,000 per top-up +- [Workflows in depth](/zcp/reference/agent-workflow) - how a generated-workflow run uses these tools. +- [Troubleshooting](/zcp/reference/troubleshooting) - evidence order when a run gets stuck. +- [Tokens and credentials](/zcp/security/tokens-and-project-access) - token scope, storage, and confirmation gates. -#### Calendar-Month Limit -The maximum total that can be automatically charged within a single calendar month (UTC). This safeguards against unexpected costs: once the limit is reached, automatic top-ups pause until the next calendar month. -- Must be at least the top-up amount (so at least one top-up can go through each month) +---------------------------------------- -#### Real-World Example +# Zcp > Reference > Index -**Scenario:** Application with ~$50 weekly operating costs and an initial manual top-up of $100 -**Your Settings:** -- Threshold = $50 -- Top-up amount = $200 -- Calendar-month limit = $500 +Reference pages exist for the moments when an exact label, tool name, or recovery step matters. For day-to-day app work, start in [Build and ship](/zcp/workflows/build-with-zcp); for the loop itself, [How it works](/zcp/concept/how-it-works). -**Expected behavior:** -- When your balance falls below $50, Zerops charges $200 to bring it back up -- Each top-up is exactly $200, no matter how fast you're spending, until you approach the calendar-month limit -- After two top-ups ($400), a full $200 would exceed the $500 limit, so the next top-up is reduced to $100, bringing the month's total to exactly $500 -- Automatic top-ups then pause until the limit resets at the start of the next calendar month (UTC) +- [Workflows in depth](/zcp/reference/agent-workflow) — Catalog of phases, routes, layouts, and labels behind a generated-workflow run. +- [ZCP MCP tools](/zcp/reference/mcp-operations) — Exact tool names and surface for custom MCP clients or agent policy. +- [Troubleshooting](/zcp/reference/troubleshooting) — When the agent is stuck, a session was interrupted, deploys keep failing, or you are taking over manually. +- [Glossary](/zcp/glossary) — Definitions for terms across pages and workflow status (`appdev`, `local-stage`, `delivery mode`, etc.). -## Billing Information +## Common scenarios -You are required to enter billing details for all transactions (manual and automatic top-ups), with one exception: +
-- EU-based users who are not VAT payers with transactions under $350 +
-You can save your billing details by navigating to **Invoices & Billing Settings** in the Organization section of the main menu. +SCENARIO -## Invoices +### Debugging a stuck deploy -Zerops provides easy access to all invoices generated for manual and automatic top-ups within your organization. +[Troubleshooting → Evidence order](/zcp/reference/troubleshooting#evidence-order) names what to read first; [Workflows in depth → Failure categories](/zcp/reference/agent-workflow#failure-categories) maps the labels. -To view and manage your invoices navigate to **Invoices & Billing Settings** in the Organization section of the main menu. +
-## Export Credit Consumption Records +
-Zerops allows you to download monthly reports of your credit consumption history for analysis and record-keeping. +SCENARIO -1. Navigate to **Credit & Spend Overview** in the Organization section -2. Find the **Export Credit Consumption Records** section -3. Click on any month button to download that period's report +### Building a custom MCP client -Reports are available for the past 12 months in TXT format and include: -- Client information and reporting period -- Starting and ending balances -- Itemized resource charges by project and service -- Credit transactions (top-ups, refunds, promotional credits) -- Clear distinction between common (paid) and promotional credits +[ZCP MCP tools](/zcp/reference/mcp-operations) for the tool surface; [Workflows in depth → What drives the workflow](/zcp/reference/agent-workflow#what-drives-the-workflow) for what the generated workflow adds on top of bare tools. ----------------------------------------- +
-# Company > Pricing +
+SCENARIO -Zerops provides a straightforward pricing structure based on your project type and resource usage. +### Auditing a finished run -The total cost of deploying an application includes your project's **core package cost** + the **cost of the resources** of the services inside a project. Additional charges may apply for optional features such as dedicated IPv4, extra egress, object storage, extra backup space and extra build time. +[Workflows in depth → Completion evidence](/zcp/reference/agent-workflow#completion-evidence) for what should be in the final answer; [Trust model → Audit evidence](/zcp/security/trust-model#audit-evidence) for what Zerops records platform-side. -:::note Fair Billing Model -Resources are allocated per service and billed by the minute, though credit is deducted hourly based on actual usage. You're only charged for what you use, calculated down to the minute. -::: +
-Need to add credits to your account? Visit our [Top-up & Billing page](/company/payment) for instructions. +
-## Project Core Plans -Zerops offers two core types to match different needs and budgets. For detailed information on both core types, visit our [Project & Services Structure](/features/infrastructure) page. +---------------------------------------- -### Lightweight Core - Free -Best for development, testing, and smaller workloads with limited redundancy. +# Zcp > Reference > Agent Workflow -**Included resources:** -- **Build Time**: 15 hours per month -- **Backup Storage**: 5 GB -- **Egress Traffic**: 100 GB per month -### Serious Core - $10 / 30 days -Optimized for production workloads with high availability and comprehensive failover protection. +Use this page when you want the process and exact labels behind a run that follows the generated workflow. Normal prompts should still describe outcomes. The workflow exists so the agent can read the project, prepare the right runtime and services, make the app change, deploy, verify, recover from evidence, and stop with proof or a concrete blocker. -**Included resources:** -- **Build Time**: 150 hours per month -- **Backup Storage**: 25 GB -- **Egress Traffic**: 3 TB per month +The useful mental split is: -:::note Storage Limits -All projects have a technical maximum backup storage limit of **1 TiB**. Usage beyond the free tier allocation (5GB or 25GB) is billed according to the [overage costs](#overage-costs) below. -::: +| Phase | What it settles | What should be true when it ends | +| ----- | --------------- | -------------------------------- | +| **Bootstrap** | Where the app should run and which services it depends on. | Runtime target and managed dependencies are known. | +| **Develop** | Code, `zerops.yaml`, env wiring, deploy, verification, recovery, and delivery choice. | The requested behavior is proved, or the blocker is concrete. | +| **Develop** | Code, `zerops.yaml`, env wiring, deploy, verification, recovery, and delivery choice. | The requested behavior is proved, or the blocker is concrete. | -## Resource Pricing +For the loop itself, see [How it works](/zcp/concept/how-it-works). This page catalogs the exact phases, routes, layouts, labels, and gates. -Services in Zerops require computing resources that are billed separately from your project core. These resources are allocated per service and billed by the minute based on actual usage, with credits deducted hourly. +## Session layers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ResourcePriceDescription
Shared CPU$0.60 per CPU / 30 daysEconomical option for most workloads with good performance
Dedicated CPU$6.00 per CPU / 30 daysReserved CPU cores for predictable performance
RAM$0.75 per 0.25 GB / 30 daysMemory allocated to your services
Disk Space$0.05 per 0.5 GB / 30 daysStorage space for your applications and data
+Most workflow mistakes come from confusing these layers: -:::note Daily Spending Control -You can set a daily spending limit in the GUI for your project to keep an eye on costs and avoid unexpected charges. This provides an alternative to configuring automatic resource scaling ranges while keeping your services running optimally. +| Layer | What it is | What changes here | +| ----- | ---------- | ----------------- | +| **Workspace** | Where `zcp` and the agent run: remote `zcp@1` service or local machine. | Agent config, tools, local workflow state. App code should not be deployed to the workspace itself. | +| **Target runtime service** | The app runtime in scope: `appdev`, `appstage`, `app`, or a linked local deploy target. | App files, `zerops.yaml`, deploys, runtime logs, verification target. | +| **Managed services** | Databases, caches, queues, search, storage, mail, and similar dependencies. | Schema/data operations and credentials, never app code deploys. | +| **Managed services** | Databases, caches, queues, search, storage, mail, and similar dependencies. | Schema/data operations and credentials, never app code deploys. | -Reaching the limit does not stop your project - your services keep running. When a project reaches its daily spending limit, Zerops sends you a warning notification (e-mail) so you can decide whether to raise the limit. The limit resets at midnight (UTC). -::: +The `zcp` service is the control surface, not the app runtime. -## Additional Services +## What drives the workflow -Enhance your deployment with these optional services to meet specific requirements for networking, storage, and data transfer. +The generated workflow is made from four pieces: - - - - - - - - - - - - - - - - - - - - -
ServicePriceDescription
Dedicated IPv4$3.00 per 30 daysExclusive IPv4 address for your project (instead of shared)
Object Storage$0.01 per GB / 30 daysScalable storage for files, backups, and static assets
+| Piece | Role | +| ----- | ---- | +| **MCP tools** | Project-scoped Zerops operations: discover, deploy, read logs/events, manage env vars, verify, import/export, and related actions. | +| **Generated instructions** | Agent policy for when to inspect, when to ask, when to deploy, what evidence to read, and what counts as done. | +| **Saved workflow state** | Local metadata about bootstrap sessions, runtime pairing, delivery choice, deploy attempts, verify attempts, and interrupted work. | +| **Live Zerops project** | Source of truth for services, status, env refs, logs, events, deploys, runtime files, and public access. | +| **Live Zerops project** | Source of truth for services, status, env refs, logs, events, deploys, runtime files, and public access. | -## Overage Costs +The workflow does not replace judgment from the user or the agent. It gives the agent a process and evidence surface so app work does not depend on stale chat memory or a pasted runbook. -When you exceed the resources included in your project core plan, the following charges apply: +## Bootstrap - - - - - - - - - - - - - - - - - - - - - - - - - -
ItemPriceDescription
Extra Egress$0.02 per GBData transfer out of your project beyond plan limits
Extra Backup Space$0.50 per 5 GBAdditional storage for automatic, encrypted backups
Extra Build Time$0.50 per 15 hoursAdditional time for building and deploying applications
+Bootstrap starts before app code changes when the workflow needs to understand or prepare the project layout. -## Pricing Calculator +```mermaid +flowchart TD + start(["Read live project state"]) + interrupted{"Interrupted bootstrap +to resume?"} + runtime{"Runtime services +already exist?"} + known{"Request matches +known recipe or stack?"} + resume(["resume"]) + adopt(["adopt"]) + recipe(["recipe"]) + classic(["classic"]) + done(["Runtime target and dependencies known"]) -Use our pricing calculator to estimate your monthly costs based on your specific needs: + start --> interrupted + interrupted -- yes --> resume --> done + interrupted -- no --> runtime + runtime -- yes --> adopt --> done + runtime -- no --> known + known -- yes --> recipe --> done + known -- no --> classic --> done +``` +| Route | Use when | Wrong signal | +| ----- | -------- | ------------ | +| `adopt` | Runtime services already exist, including recipe-created projects. | Recreating services that already fit, or targeting the `zcp` service as the app. | +| `recipe` | The project is empty or only has remote setup, and the request matches a known stack recipe. | Treating an unchanged starter as the finished requested product. | +| `classic` | The project is empty and needs a custom service plan. | Writing app code before service ownership and runtime target are known. | +| `resume` | A previous bootstrap was interrupted. | Starting from scratch without checking live services and saved state. | +| `resume` | A previous bootstrap was interrupted. | Starting from scratch without checking live services and saved state. | ----------------------------------------- +Bootstrap ends when the app runtime target and managed dependencies are known. It should also make visible any choice that needs human judgment: cost, credentials, data, runtime layout, production risk, or destructive behavior. -# Deno > How To > Build Pipeline +## Runtime layouts +Runtime layout describes which app runtime services the workflow should use. Exact layout labels (`standard`, `dev`, `simple`, `local-stage`, `local-only`) and the runtime names they map to live in the [Glossary](/zcp/glossary#runtime-layout). The user-facing three (dev, dev + stage, stage / linked target) are in [Build and ship → Choose the runtime layout](/zcp/workflows/build-with-zcp#choose-the-runtime-layout). Service scaling mode (`HA`/`NON_HA`) is a separate service setting. -Zerops provides a customizable build and runtime environment for your Deno application. +In `standard`, stage is explicit. Work scoped to `appdev` does not silently touch `appstage`; a release or stage verification happens when the user asks for it. -## Add zerops.yaml to your repository +## Develop -Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: +Develop is the main app-work loop. It begins after bootstrap has a runtime target and dependencies. It closes only when runtime reachability and requested behavior both pass, or when the agent has a blocker that needs a human decision. The loop itself is in [How it works → The work loop](/zcp/concept/how-it-works#the-work-loop). The labeled steps are: -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: deno@latest +1. **Name runtime target.** State which runtime is in scope: `appdev`, `appstage`, `app`, or a linked local target. +2. **Change code and config.** Edit app files, `zerops.yaml`, env references, migrations, seeds, framework config, or local `.env` bridge when needed. +3. **Deploy directly first.** The first verified runtime deploy goes through MCP tools. Git or CI handoff comes after proof. +4. **Start or restart if needed.** Dynamic dev runtimes may need an explicit start or restart after deploy. Built-in webserver runtimes do not need a separate dev-server step unless the framework requires one. +5. **Verify runtime reachability.** Check service status, recent error logs, and HTTP readiness when the runtime is an HTTP service. +6. **Verify requested behavior.** Check endpoint body, UI state, job result, persisted data, or another result tied to the user request. +7. **Fix from evidence.** Read failure category, logs, events, and check output. Repeating the same deploy without new evidence is not progress. - # OPTIONAL. Set the operating system for the build environment. - # os: ubuntu +Reachability and requested behavior are separate gates. A green deploy with a broken route is not done. - # OPTIONAL. Customise the build environment by installing additional packages - # or tools to the base build environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else +## Failure categories - # OPTIONAL. Build your application - buildCommands: - - deno task build +Failure categories (`build`, `start`, `verify`, `network`, `config`, `credential`, `other`) point the agent to the first useful evidence surface. The full read-first / avoid playbook is in [Troubleshooting → Evidence order](/zcp/reference/troubleshooting#evidence-order); the term definitions are in the [Glossary](/zcp/glossary#failure-category). - # REQUIRED. Select which files / folders to deploy after - # the build has successfully finished - deployFiles: - - dist - - deno.jsonc +Categorization is what turns retries into evidence-driven fixes. - # OPTIONAL. Which files / folders you want to cache for the next build. - # Next builds will be faster when the cache is used. - # cache: directory +## Delivery after proof - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: deno@latest +Delivery mode applies after a verified deploy. It does not replace the first proof. - # OPTIONAL. Sets the internal port(s) your app listens on: - ports: - # port number - - port: 3000 +| Exact mode | User-facing choice | Meaning | +| ---------- | ------------------ | ------- | +| `auto` | Keep direct deploy | The agent keeps deploying future changes directly to the target runtime. | +| `git-push` | Push to git | The agent commits and pushes to a configured remote; any resulting build still needs observation and verification. | +| `manual` | External handoff | CI, release process, or a human owns future delivery; the workflow records evidence but does not initiate the next deploy. | +| `manual` | External handoff | CI, release process, or a human owns future delivery; the workflow records evidence but does not initiate the next deploy. | - # OPTIONAL. Customise the runtime Deno environment by installing additional - # dependencies to the base Deno runtime environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else +Git-push capability, delivery mode, and build integration are separate. A project can have git-push configured while still using direct deploy for a given session. - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Deno application is started. - # initCommands: - # - rm -rf ./cache +Packaging and production release are deliberate handoffs after proof. Packaging turns a verified runtime into a git-backed import bundle. A production release moves verified work into a separate production project through GUI setup, git/CI triggers, or the team's release process. - # REQUIRED. Your Deno application start command - start: deno task start -``` +## Generated files and state -The top-level element is always `zerops`. +Remote setup and `zcp init` create configuration around the MCP server and workflow guidance. -### Setup +| File or directory | Created where | Purpose | +| ----------------- | ------------- | ------- | +| `CLAUDE.md` | Remote workspace or local project directory | Claude Code instruction surface. ZCP MCP writes a managed block between `` and ``. User content outside that block is preserved. | +| `.claude/settings.local.json` | Remote workspace or local project directory | Claude Code per-project settings and ZCP MCP tool permissions for that directory. | +| `.mcp.json` | Local project directory | Project-local MCP server config. It contains the local `zcp` command and the project-scoped `ZCP_API_KEY`; keep it out of git. | +| `~/.claude.json` and SSH config | Remote setup | Workspace-level Claude Code and SSH wiring used inside the Zerops-hosted workspace. | +| `.zcp/state/` | Working directory where the MCP server runs | Workflow state and service metadata for that project directory. | +| `.zcp/state/` | Working directory where the MCP server runs | Workflow state and service metadata for that project directory. | -The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. -Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: +The managed `CLAUDE.md` block is refreshed by `zcp init` and by the MCP server when the block already exists. Put durable project instructions outside the ZCP markers. Edits inside the managed block are treated as generated content. -```yaml -zerops: - # definition for app service - - setup: app - # optional - build: ... - # optional - deploy: ... - # required - run: ... +`.zcp/state/` is not application source code and should not be committed. It stores metadata such as known runtime services, local/stage pairing, delivery preference, git-push setup, build integration, first-deploy stamps, workflow sessions, deploy attempts, verify attempts, and local coordination locks. - # definition for api service - - setup: api - # optional - build: ... - # optional - deploy: ... - # required - run: ... -``` +ZCP MCP does not use `.zcp/state/` as a stale copy of the Zerops project. Service status, logs, events, runtime files, env-var values, and current platform configuration are read from Zerops or from the local filesystem when tools run. Local `.env` files are generated separately and may contain secrets. -Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. +Do not edit `.zcp/state/` by hand during normal work. Use workflow operations to reset, resume, iterate, or reconfigure state. Deleting it intentionally discards local memory of services and delivery setup for that directory; the tools can rediscover live Zerops state, but delivery preferences and workflow history may need to be set again. -## Build pipeline configuration +## Completion evidence -### base +A completed app task should answer: -_REQUIRED._ Sets the base technology for the build environment. +- which bootstrap route was used when setup was needed, +- which runtime target changed, +- which managed services were used or created, +- which deploy passed, +- which reachability check passed, +- which requested behavior passed, +- which URL, endpoint, UI state, worker result, or stored value proves it, +- which delivery choice applies next, +- or which blocker remains and what evidence supports it. -Following options are available for Deno builds: +A clear blocker is acceptable completion only when it names the runtime in scope, failure category, evidence read, fixes tried, and human decision or credential still needed. -- `deno@2.0.0`, `deno@2`, `deno@latest` -- `deno@1.45.5`, `deno@1` +## Confirmation gates -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: deno@latest - ... -``` +Two operations pause because the loss is not safely reversible from inside the conversation: **service deletion** (named approval) and **destructive import override** (refuse-then-acknowledge). See [Tokens and credentials → What ZCP enforces for destructive actions](/zcp/security/tokens-and-project-access#what-zcp-enforces-for-destructive-actions) for the user-facing confirmation flow. -

- The base build environment contains {data.alpine.default}, the selected - major version of Deno, [Zerops command line tool](/references/cli), `npm`, `yarn`, `git` and `npx` tools. -

+## Auditing a workflow -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. -::: +A workflow run is well-shaped if the evidence answers: -If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: +| Question | Evidence | +| -------- | -------- | +| Where did bootstrap start? | Live service list, saved workflow state, and bootstrap route. | +| Where did bootstrap end? | Runtime target, managed dependencies, and any human decisions. | +| Which runtime was developed and deployed? | Runtime target, deploy result, events, and logs. | +| What proved reachability? | Verify output, service status, public URL, or HTTP probe. | +| What proved behavior? | Endpoint, UI flow, job result, database/object state, or other requested proof. | +| What controls future delivery? | Delivery mode, git-push state, build integration, package bundle, or production release handoff note. | +| What controls future delivery? | Delivery mode, git-push state, build integration, package bundle, or production release handoff note. | -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: - - deno@latest - prepareCommands: - - zsc add go@latest - ... -``` +## Related reference -See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). +- [ZCP MCP tools](/zcp/reference/mcp-operations) — operation names and direct tool calls. +- [Troubleshooting](/zcp/reference/troubleshooting) — recovery order when a run gets stuck. +- [Glossary](/zcp/glossary) — exact terms used across the ZCP MCP reference. -To customise your build environment use the [prepareCommands](#preparecommands) attribute. -:::note -Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. -::: +---------------------------------------- -### os +# Zcp > Concept > How It Works -_OPTIONAL._ Sets the operating system for the build environment. -Following options are available: +The ZCP MCP setup gives a coding agent a **work loop** for Zerops app work. The agent reads live state, chooses the app runtime and dependencies, changes the app, deploys through Zerops, verifies real behavior, and returns proof or a blocker. -- `alpine` -- `ubuntu` +The loop is carried by project-scoped Zerops operations, Zerops-specific knowledge, and instructions for what to inspect, what to change, when to ask, and what counts as done. You describe the product outcome; the agent uses the loop to make its decisions visible while it works. -Default value is `alpine`. +The source of truth is the real project: runtimes, managed services, env references, logs, events, and deploy results. A separate preview sandbox is not the source of truth. -We are currently using following os version: +## The work loop -- {data.alpine.default} -- {data.ubuntu.default} +```mermaid +flowchart TD + intent["Product intent +Build a task board for my team."] + state["Live state +services, runtime layout, env vars, +logs, events, saved work state"] + scope["Runtime target +which app service changes"] + setup{"Missing or unsuitable +services?"} + provision["Service setup +use existing services or create +missing runtimes/dependencies"] + appwork["App work +code, zerops.yaml, env refs, +migrations, seeds, framework config"] + deploy["Direct deploy through Zerops"] + reachability{"Runtime reachable? +status, logs, HTTP probe"} + behavior{"Requested behavior works? +endpoint, UI flow, worker result, +persisted state"} + evidence["Evidence +build logs, runtime logs, +events, verify output"] + proof["Proof +URL, endpoint result, +UI state, or stored result"] + delivery["Delivery after proof +keep direct deploy, push to git, +or hand off"] + blocker["Blocker +credential, decision, +unsupported fit, +repeated failure"] -:::caution -The os version is fixed and cannot be customised. -::: + intent --> state --> scope --> setup + setup -->|yes| provision --> appwork + setup -->|no| appwork + appwork --> deploy --> reachability + reachability -->|no, fixable| evidence --> appwork + reachability -->|yes| behavior + behavior -->|no, fixable| evidence + behavior -->|yes| proof --> delivery + setup -->|needs decision| blocker + reachability -->|needs human| blocker + behavior -->|needs human| blocker -:::note -Changing the OS setting will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache behavior. -::: + classDef user stroke:#2d72d9,stroke-width:1.5px; + classDef zcpbox stroke:#32845a,stroke-width:1.5px; + classDef work stroke:#c47f17,stroke-width:1.5px; + classDef done stroke:#7157d9,stroke-width:1.5px; + classDef stop stroke:#d33f49,stroke-width:1.5px; -### prepareCommands + class intent user; + class state,scope zcpbox; + class setup,provision,appwork,deploy,reachability,behavior,evidence work; + class proof,delivery done; + class blocker stop; +``` -_OPTIONAL._ Customises the build environment by installing additional dependencies or tools to the base build environment. +The loop keeps the agent working from evidence instead of a guessed checklist: current state, Zerops wiring rules, deploy evidence, and the distinction between proof and blocker. -The base build environment contains: +## What "live state" means -- {data.alpine.default} -- selected version of Deno defined in the [base](#base) attribute -- [Zerops command line tool](/references/cli) -- `npm`, `yarn`, `git` and `npx` tools +The MCP tools read Zerops instead of asking you to paste a service inventory into the prompt. Useful state includes: -To install additional packages or tools add one or more prepare commands: +- runtime services and managed services, +- whether the app has one runtime, a dev+stage pair, or local files linked to a Zerops runtime, +- env-var keys and Zerops references, +- recent build/deploy events, +- build logs, runtime logs, and verification output, +- saved work state after an interrupted session. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: deno@latest +This is why a short prompt can be enough. The agent can ask what exists, which runtime was last deployed, which checks passed, and where a previous run stopped. - # OPTIONAL. Customise the build environment by installing additional packages - # or tools to the base build environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... +Chat history is not the source of truth. If the agent sounds confused, starts from an old assumption, or a session was interrupted, the recovery move is: + +```text +Read current project status and tell me where this project stands before changing anything. ``` -When the first build is triggered, Zerops will +## What the workflow handles -1. create a build container -2. download your application code from your repository -3. run the prepare commands in the defined order +The workflow handles the things an agent must resolve during app work so you do not have to name them in the prompt. The tools and instructions supply the state, guidance, operations, and verification surface so the agent can work from evidence. -The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. +| What the workflow handles | What the agent gets | What that means for you | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| Live state | Services, env-var keys, Zerops references, recent events, logs, verification output, and saved work state. | You do not have to paste a service inventory or reconstruct what happened. | +| Runtime target | Rules for choosing the app runtime that should receive code changes. | The agent can identify where app work belongs before editing or deploying. | +| Managed services | Knowledge and env wiring patterns for database, cache, queue, search, storage, mail, and similar services. | Product intent can imply real dependencies without a manual wiring checklist. | +| Service setup | Operations for using existing services or creating missing runtimes and dependencies. | Runtime layout and dependencies can be established before app work starts. | +| App wiring | Zerops-specific rules for `zerops.yaml`, env references, ports, commands, public access, and build/deploy behavior. | The app is wired for Zerops rather than for a generic cloud template. | +| Deploy evidence | Build logs, runtime logs, platform events, service status, HTTP checks, and structured verification output. | A failed deploy becomes a diagnosis surface instead of guesswork. | +| Behavior proof | The proof gate is the requested behavior, not only a successful build or reachable root URL. | The final answer can point to what was actually checked. | +| Delivery handoff | Direct proof first; then git push, CI, or human handoff when that is the chosen delivery choice. | Shipping setup follows a verified running result. | +| Delivery handoff | Direct proof first; then git push, CI, or human handoff when that is the chosen delivery choice. | Shipping setup follows a verified running result. | -:::note -These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. -::: +The exact labels for layouts, delivery modes, and setup routes live in the [Glossary](/zcp/glossary) and [Workflows in depth](/zcp/reference/agent-workflow). -#### Command exit code +## Service setup prepares the project layout -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/deno/how-to/logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. +Before app code work starts, the workflow makes three decisions visible: -#### Single or separated shell instances +- Which runtime service is the app target? +- Which managed services are dependencies? +- Does the existing project layout fit the request? -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +If the services already exist, the agent can use them. If a needed runtime or dependency is missing, the tools can create it. If the choice affects cost, product scope, credentials, a destructive action, or which stage/runtime should be used, the agent should stop and ask. -### buildCommands +Service setup is finished when the app runtime and dependencies are known. It is the layout that lets app work happen in the right place. -_OPTIONAL._ Defines build commands. +## App work changes code and platform wiring together -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: deno@latest +After the runtime target is known, the agent gets the platform knowledge needed to make the application change. In practice this often spans both source code and Zerops wiring: - # OPTIONAL. Build your application - buildCommands: - - deno task build - ... -``` +- app files, +- `zerops.yaml` build and run setup, +- env references to managed services, +- migrations, seeds, and framework config, +- start commands, ports, and public HTTP support, +- local `.env` generation when using local setup. -Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. +That guidance matters because Zerops is its own platform. Service references, build/deploy behavior, public access, scaling, and env resolution do not follow Docker Compose or Kubernetes conventions. -Before the build commands are triggered the build container contains: +The first functional deploy goes directly through MCP so the agent has a running result to verify. A repository push or CI handoff can follow, but it should not replace the first proof. -1. base environment defined by the [base](#base) attribute -2. optional customisation of the base environment defined in the [prepareCommands](#preparecommands) attribute -3. your application code +## Recovery is evidence-driven -#### Run build commands as a single shell instance +When something fails, the workflow puts the agent on the matching evidence surface — build logs for build failures, prepare/runtime logs for start failures, verify output and request-time logs for behavior failures, transport surfaces for network failures, field-level rejection for config, and the named credential surface for credential failures. The full categories, what to read first, and what to avoid live in [Troubleshooting](/zcp/reference/troubleshooting). -Use following syntax to run all commands in the same environment context. For example, if one command changes the current directory, the next command continues in that directory. When one command creates an environment variable, the next command can access it. +Retrying the same deploy without new evidence is not progress. The loop pushes toward one of three outcomes: fix from a cause, ask for the missing decision, or report a blocker with the category, evidence read, and attempts made. -```yaml -buildCommands: - - | - deno test - deno task build -``` +## Verification has two layers -#### Run build commands as a separate shell instances +A successful deploy proves that Zerops accepted the build and started the runtime. Reachability checks prove the service is running and reachable. They still do not prove the product request. -When the following syntax is used, each command is triggered in a separate environment context. For example, each shell instance starts in the home directory again. When one command creates an environment variable, it won't be available for the next command. +For a task-board app, useful behavior proof might be: -```yaml -buildCommands: - - deno task build -``` +- create a task, +- move it between columns, +- refresh the page, +- confirm the task is still there. -#### Command exit code +For an API task, proof might be a JSON response from the requested endpoint and stored data behind it. For a worker task, proof might be a processed job and the resulting database or object-storage state. For a staging request, proof belongs on the stage runtime, not only on dev. -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/deno/how-to/logs#build-log) to troubleshoot the error. If the error log doesn't contain any specific error message, try to run your build with the --verbose option. +The final answer should make proof inspectable: runtime name, URL or endpoint, behavior checked, and delivery choice if one was set. -```yaml -buildCommands: - - npm i --verbose - - npm run build -``` +## Delivery happens after proof -If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `buildCommands` are finished, the application build is completed and ready for the deploy phase. +Delivery choice controls how future changes ship after a verified runtime exists: keep direct deploy, push to git, or hand off to CI/release/human action. The user-facing version of this choice and what to tell the agent for each option lives in [Build and ship → Choose delivery after proof](/zcp/workflows/build-with-zcp#choose-delivery-after-proof). -### deployFiles +Packaging a running service turns a deployed runtime into a re-importable bundle for another Zerops project. It is useful for handoff or reuse after proof, not for deploying the next app change; see [Package a running service](/zcp/workflows/package-running-service). -_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. +## Remote and local setup use the same loop -```yaml -# REQUIRED. Select which files / folders to deploy after -# the build has successfully finished -deployFiles: - - dist - - package.json - - node_modules -``` +The same `zcp` binary can run in two places. The control loop stays the same; filesystem and network access change. A human can take over from the same evidence either way: files, runtime target, logs, events, verification result, and delivery state. -Determines files or folders produced by your build, which should be deployed to your runtime service containers. +| Setup | What runs where | Practical effect | +| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Remote setup | A `zcp@1` service runs the `zcp` binary inside Zerops. **Include Coding Agent** adds the bundled agent CLI; **Cloud IDE** adds Browser VS Code. | Work happens inside the remote workspace, with private networking and runtime file mounts. | +| Local setup | The `zcp` binary runs on your laptop after `zcp init`, and your local editor or CLI agent talks to it. | App files, deploy source, and git credentials stay local. Managed services are reached over Zerops VPN, and `.env` generation bridges credentials into your local app. | +| Local setup | The `zcp` binary runs on your laptop after `zcp init`, and your local editor or CLI agent talks to it. | App files, deploy source, and git credentials stay local. Managed services are reached over Zerops VPN, and `.env` generation bridges credentials into your local app. | -The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. +Choose setup by where the agent and filesystem should live: [Remote or local setup](/zcp/setup/choose-workspace). -The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. +## Signs of a healthy run -#### Examples +A well-shaped run should: -Deploys a folder, and a file from the project root directory: +- name the runtime target before editing or deploying, +- use existing services when they fit, +- create missing services only before app work starts, +- read logs, events, and verify output when failure occurs, +- distinguish runtime reachability from requested behavior, +- stop before destructive actions, ambiguous runtime/stage choices, or missing credentials, +- end with proof or a blocker. -```yaml -deployFiles: - - dist - - package.json -``` +That is the practical difference between "the agent wrote code" and "the app task is done". -Deploys the whole content of the build container: +## Next steps -```yaml -deployFiles: . -``` +- [Build and ship](/zcp/workflows/build-with-zcp) — normal app work after setup. +- [Workflows in depth](/zcp/reference/agent-workflow) — process gates, generated files, runtime layouts, delivery labels, and completion evidence. -Deploys a folder, and a file in a defined path: -```yaml -deployFiles: - - ./path/to/file.txt - - ./path/to/dir/ -``` +---------------------------------------- -#### How to use a wildcard in the path +# Valkey > Overview -Zerops supports the `~` character as a wildcard for one or more folders in the path. -Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` +Valkey is a powerful, open-source alternative to Redis, offering full compatibility with Redis clients while providing an independent development path focused on community-driven innovation. Deploy and manage Valkey in Zerops' fully managed infrastructure to get instant access to high-performance in-memory data storage. -```yaml -deployFiles: ./path/~/to/file.txt -``` +:::tip +Valkey is our recommended Redis alternative as KeyDB's development has slowed significantly in recent times. +::: -Deploys all folders that are located in any path that begins with `/path/to/` +## Supported Versions -```yaml -deployFiles: ./path/to/~/ -``` +Currently supported Valkey versions: -Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` +Import configuration version: -```yaml -deployFiles: ./path/~/to/ -``` +- `valkey@7.2` -:::note Example -By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` -::: -#### .deployignore +## Service Configuration -Add a `.deployignore` file to the root of your project to specify which files and folders Zerops should ignore during deploy. The syntax follows the same pattern format as [`.gitignore`](https://git-scm.com/docs/gitignore#_pattern_format). +Zerops offers Valkey in two deployment configurations to meet different availability requirements. -To ignore a specific file or directory path, start the pattern with a forward slash (`/`). Without the leading slash, the pattern will match files with that name in any directory. +### Single Setup +- Single node deployment on port `6379` (non-TLS) and `6380` (TLS) +- Suitable for development or non-critical workloads -:::tip -For consistency, it's recommended to configure both your `.gitignore` and `.deployignore` files with the same patterns. -::: +See [Persistence](#persistence) for how data is stored and recovered. -Examples: +### HA (High Availability) Setup -```yaml title="zerops.yaml" -zerops: - - setup: app - build: - deployFiles: ./ -``` +The HA deployment is a 3-node cluster with automatic failover, fronted by an HAProxy load balancer on every node. -```text title=".deployignore" -/src/file.txt -``` -The example above ignores `file.txt` only in the root src directory. -```text title=".deployignore" -src/file.txt -``` -This example above ignores `file.txt` in ANY directory named `src`, such as: -- `/src/file.txt` -- `/folder2/folder3/src/file.txt` -- `/src/src/file.txt` +- 3-node configuration: 1 primary + 2 replicas +- Client-facing ports (available on every node): + - `6379` — read/write (non-TLS), routed to the current primary + - `6380` — read/write over TLS, routed to the current primary + - `7000` — read-only (non-TLS), load-balanced across replicas + - `7001` — read-only over TLS, load-balanced across replicas +- Failover is handled by a built-in [Sentinel](https://valkey.io/topics/sentinel/) cluster. When the primary becomes unreachable, a replica is promoted automatically and HAProxy starts routing writes to it. +- TLS is terminated at HAProxy. +- Connect your application to the standard ports — the address never changes when the primary moves. :::note -`.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. +Replica reads (ports `7000`/`7001`) can lag slightly behind the primary due to asynchronous replication. ::: -### cache - -_OPTIONAL._ Defines which files or folders will be cached for the next build. +**Failover client impact:** expect roughly 10–15 seconds of write unavailability while a new primary is elected and HAProxy reconverges. Read traffic on surviving replicas is unaffected. -```yaml -# OPTIONAL. Which files / folders you want to cache for the next build. -# Next builds will be faster when the cache is used. -cache: file.txt -``` +:::tip Trusting the TLS certificate +The certificates served on the TLS ports (`6380` and `7001`) are signed by the Zerops Certificate Authority. To verify them from outside Zerops, download and trust the [Zerops CA](/references/networking/zerops-ca) — e.g. `redis-cli --tls --cacert ./zerops-ca.pem -h -p 6380 -a `. +::: -The cache attribute helps optimize build times by preserving specified files between builds. +## Connecting -The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). +Zerops generates the connection details as environment variables on the Valkey service. Reference them from another service in the same project as `${_}` — for a service named `db`, the connection string is `${db_connectionString}`. The examples below assume the hostname `db`. -Learn more about the [build cache system](/features/build-cache) in Zerops. +| Variable | Example value | Notes | +|---|---|---| +| `hostname` | `db` | Service hostname; reachable as `db.zerops` inside the project | +| `port` | `6379` | Plain (non-TLS) port | +| `portTls` | `6380` | TLS port | +| `password` | *(generated)* | Password for the `default` user (sensitive) | +| `connectionString` | `redis://default:@db.zerops:6379` | Ready-to-use non-TLS URL | +| `connectionTlsString` | `rediss://default:@db.zerops:6380` | Ready-to-use TLS URL | +| `connectionTlsString` | `rediss://default:@db.zerops:6380` | Ready-to-use TLS URL | -### envVariables +In **HA mode** four additional variables expose the read-only replica endpoints (load-balanced across replicas): -_OPTIONAL._ Defines the environment variables for the build environment. +| Variable | Example value | Notes | +|---|---|---| +| `portReplicas` | `7000` | Read-only plain port | +| `portTlsReplicas` | `7001` | Read-only TLS port | +| `connectionStringReplicas` | `redis://default:@db.zerops:7000` | Read-only non-TLS URL | +| `connectionTlsStringReplicas` | `rediss://default:@db.zerops:7001` | Read-only TLS URL | +| `connectionTlsStringReplicas` | `rediss://default:@db.zerops:7001` | Read-only TLS URL | -Enter one or more env variables in following format: +The connection string format is `redis://default:@.zerops:` (or `rediss://` for TLS). The username is always `default`. -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - base: deno@latest - … +:::note Authentication +Valkey requires a password. It is generated automatically, exposed as the sensitive `${db_password}` variable, and already embedded in the `connectionString` variables above. Connect with it directly — e.g. `redis-cli -h db.zerops -p 6379 -a "$db_password"`. - # OPTIONAL. Defines the env variables for the build environment: - envVariables: - NODE_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` +Services created **without** a `password` variable (older deployments) keep working without authentication and are unaffected. **All deployments created since this release require the password.** +::: -Read more about [environment variables](/deno/how-to/env-variables) in Zerops. +### Idle connection timeout -## Runtime configuration +Valkey closes connections that stay **idle for 5 minutes** (`timeout 300`). This is intentional on the managed instances — we avoid keeping infinite idle connections open. Older Valkey services ran with no timeout (`timeout 0`); if you connected before this change, your connections used to stay open indefinitely. -### base +"Idle" means **no commands sent on the connection** — the server resets the timer on every command, so a busy connection is never closed. The connections most likely to be affected are long-lived ones that sit waiting rather than sending commands, typically **pub/sub subscribers** and **blocking reads** (`BLPOP`, `XREAD`, …). Most clients reconnect automatically, so you may only see log lines such as `Redis subscriber socket closed; reconnecting if possible.` — but the reconnect churn can drop pub/sub messages published in the gap. -_OPTIONAL._ Sets the base technology for the runtime environment. -If you don't specify the `run.base` attribute, Zerops keeps the current Deno version for your runtime. +To keep idle connections open, send an application-level **`PING` on an interval shorter than 300s**. A TCP keep-alive alone is **not** enough — keepalive packets live below the application layer and don't count as Valkey commands, so they don't reset the idle timer. -Following options are available for Deno builds: +Many clients have a built-in option for this. For example, [node-redis](https://github.com/redis/node-redis): -- `2.0` -- `1.45` +```js +const redisClient = createClient({ + url: redisURL, + pingInterval: 10000, // send PING every 10s; keeps the connection under the 300s idle limit +}); +``` -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: deno@latest - ... +If your client has no equivalent option, run your own heartbeat on every long-lived connection: - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: deno@latest - ... +```js +const heartbeat = setInterval(() => { + publisher.ping().catch(() => {}); + subscriber.ping().catch(() => {}); +}, 60000); // any interval under 300s ``` -

- The base runtime environment contains {data.alpine.default}, the - selected major version of Deno, Zerops command line tool, `npm`, `yarn`, `git` and `npx` tools. -

+For ordinary request/response traffic, a [connection pool](https://valkey.io/topics/clients/) that recycles connections handles this transparently. -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. -::: +## Persistence -If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: +Valkey persists data to disk with **AOF (append-only file)**, so the dataset survives restarts and is rebuilt automatically on startup. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: deno@latest - ... +- **AOF is enabled** (`appendonly yes`) and synced to disk **every second** (`appendfsync everysec`). After an unclean crash you lose at most ~1 second of the most recent writes. +- **RDB snapshots are disabled** (`save ""`) — durability relies on AOF, not periodic snapshots. - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: - - deno@latest - prepareCommands: - - zsc add go@latest - ... -``` +**Durability by mode:** +- **Single:** the AOF lives on the node's local disk. Data survives service restarts but is lost if the underlying hardware node fails and no backup exists. +- **HA:** writes are additionally replicated to two replicas, so the dataset survives the loss of any single node via automatic failover. -See the full list of supported [run base environments](/zerops-yaml/base-list). +:::note Backups +Platform-managed encrypted backups are available for both Single and HA setups. They are **disabled by default** — enable them on the service if you need point-in-time recovery beyond AOF and replication. +::: -To customise your build environment use the `prepareCommands` attribute. +## Memory and Autoscaling -### os +You don't set `maxmemory` directly. Zerops sizes it at **80% of the container's available RAM** — precisely 80% of the *smaller* of your configured maximum RAM and the cgroup-allocated RAM. It is re-evaluated and adjusted automatically about every 30 seconds, so `maxmemory` tracks the container as it scales vertically. The remaining 20% covers Valkey's internal overhead (fork on AOF rewrite / replica sync, fragmentation) and the OS. -_OPTIONAL._ Sets the operating system for the runtime environment. +:::warning Keep minimum free RAM above 20% when customizing autoscaling +If you edit the autoscaling configuration, keep the **minimum free RAM above 20%**. Zerops caps `maxmemory` at 80% of available RAM, so the dataset alone can never push free RAM below 20%. If your minimum free RAM threshold is at or below 20%, the scale-up trigger may **never fire at all** — free RAM never crosses it, so the service stays stuck at its current size and starts evicting keys (or rejecting writes under `noeviction`) instead of scaling up. Setting the threshold above 20% lets the dataset's growth toward the 80% cap cross the trigger, so the service scales up in time and keeps headroom for the fork during an AOF rewrite or replica sync. The built-in profiles all keep this threshold above 20%. +::: -Following options are available: +:::note Check the logs for OOM events +Watch the service's runtime logs for out-of-memory events — typically the kernel OOM-killer terminating and restarting Valkey when a fork during an AOF rewrite or replica sync briefly inflates memory. Recurring OOMs mean the reserved headroom isn't enough for your workload's peaks. Raise the **minimum free RAM** (more headroom) or the **minimum RAM** (a higher floor) until they stop. +::: -- `alpine` -- `ubuntu` +## Tunable Parameters -Default value is `alpine`. +The `maxmemory-policy` Valkey setting is exposed as an **autoscaling profile override**. In the GUI, open the service's **Automatic scaling configuration**, click **Adjust scaling** and set them under **Overrides**. Zerops applies the change live — **no service restart**, no client reconnect. In HA mode the change is rolled out to every node. -We are currently using following os version: +To set the parameters at creation time, use `profileOverrides` in your import YAML (a `profile` must be selected to use overrides — available profiles are `hobby`, `staging` and `production`): -- {data.alpine.default} -- {data.ubuntu.default} +```yaml +services: + - hostname: redis + type: valkey:ha@7.2 + profile: staging + profileOverrides: + maxmemory-policy: noeviction +``` -:::caution -The os version is fixed and cannot be customised. +:::note Migrating from environment variables +Services created before profile overrides existed configure this setting via the `VALKEY_MAXMEMORY_POLICY` environment variable. It keeps working, but once a profile override is set it takes precedence over the environment variable. ::: -### ports +### `maxmemory-policy` -_OPTIONAL._ Specifies one or more internal ports on which your application will listen. +Default: `allkeys-lru`. Controls what Valkey does when the dataset reaches `maxmemory`. -Projects in Zerops represent a group of one or more services. Services can be of different types (runtime services, databases, message brokers, object storage, etc.). All services of the same project share a **dedicated private network**. To connect to a service within the same project, just use the service hostname and its internal port. +| Value | Behavior | When to use | +|---|---|---| +| `noeviction` | Reject writes with an OOM error | Datasets where every key must be preserved (session storage without TTL, job queues). Requires careful capacity planning. | +| `allkeys-lru` | Evict least-recently-used keys | General-purpose caching — the safe default | +| `allkeys-lfu` | Evict least-frequently-used keys | Hot/cold workloads where access frequency matters more than recency | +| `allkeys-random` | Evict random keys | Uniform access patterns (rare) | +| `volatile-lru` | Evict LRU keys *with a TTL set* | Mixed workloads: persistent keys without TTL are protected, cache keys with TTL are evictable | +| `volatile-lfu` | Evict LFU keys with a TTL | Same as `volatile-lru`, frequency-based | +| `volatile-random` | Evict random keys with a TTL | Rarely appropriate | +| `volatile-ttl` | Evict keys with the shortest remaining TTL | When TTL reflects priority | +| `volatile-ttl` | Evict keys with the shortest remaining TTL | When TTL reflects priority | -For example, to connect to a Deno service with hostname = "app" and port = 3000 from another service of the same project, simply use `app:3000`. Read more about [how to access a Deno service](/references/networking/internal-access#basic-service-communication). +:::warning `noeviction` and memory pressure +With `noeviction`, Valkey cannot free memory on its own — once the dataset reaches `maxmemory`, writes fail with OOM errors until the service scales up or keys are deleted. Make sure your autoscaling limits (maximum RAM) leave enough room for the dataset's growth. +::: -Each port has following attributes: - -| parameter | description | -| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| port | Defines the port number. You can set any port number between _10_ and _65435_. Ports outside this interval are reserved for internal Zerops systems. | -| protocol | **Optional.** Defines the protocol. Allowed values are `TCP` or `UDP`. Default value is `TCP`. | -| httpSupport | **Optional.** `httpSupport = true` is the default setting for TCP protocol. Set `httpSupport = false` if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). `httpSupport = true` is available only in combination with the TCP protocol. | -| httpSupport | **Optional.** `httpSupport = true` is the default setting for TCP protocol. Set `httpSupport = false` if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). `httpSupport = true` is available only in combination with the TCP protocol. | - -### prepareCommands - -_OPTIONAL._ Customises the Deno runtime environment by installing additional dependencies or tools to the runtime base environment. - -

- The base Deno environment contains {data.alpine.default} the selected - major version of Deno, [Zerops command line tool](/references/cli) and `npm`, `yarn`, `git` and `npx` tools. To install - additional packages or tools add one or more prepare commands: -

- -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... +## Metrics - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Deno runtime environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +Prometheus-compatible metrics are exported by default for scraping, on the port given by the `ZEROPS_PROMETHEUS_PORT` variable (`db:9121`). -When the first deploy with a defined prepare attribute is triggered, Zerops will +## Learn More -1. create a prepare runtime container -2. optionally: [copy selected folders or files from your build container](#copy-folders-or-files-from-your-build-container) -3. run the `prepareCommands` commands in the defined order +- [Official Valkey Documentation](https://valkey.io/docs) - Comprehensive guide to Valkey features -:::note -`run.prepareCommands` run in the `/home/zerops` directory. -::: +## Support -#### Command exit code +For advanced configurations or custom requirements: +- Join our [Discord community](https://discord.gg/zeropsio) +- Contact support via [email](mailto:support@zerops.io) -If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](/deno/how-to/logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. +---------------------------------------- -#### Cache of your custom runtime environment +# Ubuntu > Overview -Some packages or tools can take a long time to install. Therefore, Zerops caches your custom runtime environment after the installation of your custom packages or tools is completed. When the second or following deploy is triggered, Zerops will use the custom runtime cache from the previous deploy if following conditions are met: -1. Content of the [build.addToRunPrepare](#copy-folders-or-files-from-your-build-container) and `run.prepareCommands` attributes didn't change from the previous deploy -2. The custom runtime cache wasn't invalidated in the Zerops GUI. +[Ubuntu ↗](https://ubuntu.com/) is a popular Linux distribution based on Debian, widely used for servers, cloud computing, and containerized applications. -To invalidate the custom runtime cache go to `yyy` +Ubuntu services in Zerops provide a flexible base environment for running applications built with technologies that aren't officially supported by Zerops, or for custom setups requiring full control over the runtime environment. -When the custom runtime cache is used, Zerops doesn't create a prepare runtime container and executes the deployment of your application directly. +:::tip +Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. +::: -#### Single or separated shell instances +## Feature Highlights -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +- [Create Ubuntu service](/ubuntu/how-to/create) — Start with creating an Ubuntu service using GUI or zCLI. +- [zerops.yaml](/ubuntu/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to configure your own app. +- [Scaling configuration](/ubuntu/how-to/scaling) — Set up scaling of your Ubuntu service so that it runs smoothly while using only necessary resources. -### Copy folders or files from your build container +{" "} -

- The prepare runtime container contains {data.alpine.default}, the - selected major version of Deno, [Zerops command line tool](/references/cli) and `npm`, `yarn`, `git` and `npx` tools. -

+- [Customize build environment](/ubuntu/how-to/build-process#customize-build-environment) +- [Customize runtime environment](/ubuntu/how-to/customize-runtime) -The prepare runtime container does not contain your application code nor the built application. If you need to copy some folders or files from the build container to the runtime container (e.g. a configuration file) use the `addToRunPrepare` attribute in the [build section](#build-pipeline-configuration). +## When in doubt, reach out -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... - addToRunPrepare: ./runtime-config.yaml +Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Deno runtime environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. -In the example above Zerops will copy the `runtime-config.yaml` file from your build container **after the build has finished** into the new **prepare runtime** container. The copied files and folders will be available in the `/home/zerops` folder in the new prepare runtime container before the prepare commands are triggered. +Have you built something that others might find useful? Don't hesitate to share your knowledge! -### initCommands +- [FAQ](/ubuntu/faq) — Most common questions in one place. +- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. -_OPTIONAL._ Defines one or more commands to be run each time a new runtime container is started or a container is restarted. +## Popular Guides -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. +- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. - # ==== how to run your application ==== - run: - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Deno application is started. - initCommands: - - rm -rf ./cache -``` -These commands are triggered in the runtime container before your Deno application is started via the [start command](#start). +---------------------------------------- -:::note -`run.initCommands` run in the `/var/www` directory. -::: +# Ubuntu > How To > Upgrade -Use init commands to clean or initialise your application cache or similar operations. -:::caution -The init commands will delay the start of your application each time a new runtime container is started (including the horizontal [scaling](/deno/how-to/scaling) or when a runtime container is restarted). -Do not use the init commands for customising your runtime environment. Use the [run:prepareCommands](#preparecommands-1) attribute instead. -::: +---------------------------------------- -#### Command exit code +# Ubuntu > How To > Trigger Pipeline -If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](/deno/how-to/logs#runtime-log) to troubleshoot the error. -#### Single or separated shell instances -You can configure your `initCommands` to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +---------------------------------------- -### envVariables +# Ubuntu > How To > Shared Storage -_OPTIONAL._ Defines the environment variables for the runtime environment. -Enter one or more env variables in following format: -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to run your application ==== - run: - # OPTIONAL. Defines the env variables for the runtime environment: - envVariables: - NODE_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` +---------------------------------------- -Read more about [environment variables](/deno/how-to/env-variables) in Zerops. +# Ubuntu > How To > Scaling -### start -_REQUIRED._ Defines the start command for your Deno application. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +---------------------------------------- - # ==== how to run your application ==== - run: - # REQUIRED. Your Deno application start command - start: deno task start -``` +# Ubuntu > How To > Logs -We recommend starting your Deno application using `deno task start`. -### health check -_OPTIONAL._ Defines a health check. +---------------------------------------- -`healthCheck` requires either one `httpGet` object or one `exec` object. +# Ubuntu > How To > Filebrowser -#### httpGet -Configures the health check to request a local URL using a HTTP GET method. -Following attributes are available: +---------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
+# Ubuntu > How To > Env Variables -**Example:** -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - # ==== how to run your application ==== - run: - # REQUIRED. Your Deno application start command - start: deno task start +---------------------------------------- - # OPTIONAL. Define a health check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - healthCheck: - httpGet: - port: 80 - path: /status -``` +# Ubuntu > How To > Deploy Process -#### exec -Configures the health check to run a local command. -Following attributes are available: -| Parameter | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **command** | Defines a local command to be run. -The command has access to the same [environment variables](/deno/how-to/create#set-secret-environment-variables) as your Deno application. -A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. | +---------------------------------------- -**Example:** +# Ubuntu > How To > Customize Runtime -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - # ==== how to run your application ==== - run: - # REQUIRED. Your Deno application start command - start: deno task start +## Build Custom Runtime Images - # OPTIONAL. Define a health check with a shell command. - healthCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user -``` +Zerops allows you to build custom runtime images (CRI) when the default base runtime images don't meet your application's requirements. This is an optional phase in the [build and deploy pipeline](/features/pipeline#runtime-prepare-phase-optional). -### crontab +Ubuntu is a versatile base for running anything not explicitly offered as a dedicated Zerops runtime. You can install any packages and tools you need, treating it as a clean OS to customize however you want. -_OPTIONAL._ Defines cron jobs. +It is also a great option when you need a specific version of a technology (like Go, Node.js, or PHP) that Zerops doesn't support by default—whether it's an older version for legacy projects or a newer release not yet available. -Setup cron jobs in the following format: +## Configuration -```yaml -zerops: - # define hostname of your service - - setup: app +### Default Runtime Environment - # ==== how to run your application ==== - run: - crontab: - # REQUIRED. Sets the command to execute: - - command: "" - # REQUIRED. Sets the interval time to execute: - timing: "0 * * * *" -``` +The default runtime environment contains: -Read more about setting up [cron](/zerops-yaml/cron) in Zerops. +- {data.ubuntu.default} +- [zCLI](/references/cli) +- -## Deploy configuration +### When You Need a Custom Runtime Image -### readiness check +Since Ubuntu serves as a general-purpose base, you'll likely want to customize it for your specific use case. Common scenarios include: -_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](/deno/how-to/deploy-process#readiness-checks) in Zerops. +:::important +You should not include your application code in the custom runtime image, as your built/packaged code is deployed automatically into fresh containers. +::: -`readinessCheck` requires either one `httpGet` object or one `exec` object. +Here are examples of configuring custom runtime images in your `zerops.yml`: -#### httpGet +### Basic Setup -Configures the readiness check to request a local URL using a http GET method. +### Using Build Files in Runtime Preparation -Following attributes are available: +For complete configuration details, see the [runtime prepare phase configuration guide](/features/pipeline#configuration). - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
+## Process and Caching -**Example:** +### How Runtime Prepare Works +The runtime prepare process follows the same steps for all runtimes. See [how runtime prepare works](/features/pipeline#how-it-works) for the complete process details. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +### Caching Behavior +Zerops caches custom runtime images to optimize deployment times. Learn about [custom runtime image caching](/features/pipeline#custom-runtime-image-caching) including when images are cached and reused. - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - httpGet: - port: 80 - path: /status +### Build Management +For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). - # ==== how to run your application ==== - run: ... -``` +:::warning +Shared storage mounts and Local Storage volumes are not available during the runtime prepare phase. +::: -Read more about how the [readiness check works](/deno/how-to/deploy-process#readiness-checks) in Zerops. +## Troubleshooting -#### exec +If your `prepareCommands` fail, check the for specific error messages. -Configures the readiness check to run a local command. -Following attributes are available: +---------------------------------------- -| Parameter | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **command** | Defines a local command to be run. -The command has access to the same [environment variables](/deno/how-to/create#set-secret-environment-variables) as your Deno application. -A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. | +# Ubuntu > How To > Create -**Example:** -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +Zerops provides a Ubuntu runtime service with extensive build support. Ubuntu runtime is highly scalable and customisable to suit both development and production. - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user -``` +## Create Ubuntu service using Zerops GUI -Read more about how the [readiness check works](/deno/how-to/deploy-process#readiness-checks) in Zerops. +First, set up a project in Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu in the **Services** block. Then add a new Ubuntu service: +[Video: /vids/services/golang.webm](/vids/services/golang.webm) ----------------------------------------- +### Choose Ubuntu version -# Deno > How To > Build Process +Following Ubuntu versions are currently supported: +:::info +You can [change](/ubuntu/how-to/upgrade) the major version at any time later. +::: -## Build process overview +### Set a hostname -Zerops starts a temporary build container and performs the following actions: +Enter a unique service identifier like "app","cache", "gui" etc. Duplicate services with the same name in the same project are forbidden. -1. **Installs the build environment** - Sets up base system and Deno runtime -2. **Downloads your application source code** - From [GitHub ↗](https://www.github.com), [GitLab ↗](https://www.gitlab.com) or via [Zerops CLI](/references/cli) -3. **Optionally customizes the build environment** - Runs prepare commands if configured -4. **Runs the build commands** - Executes your build process -5. **Uploads the application artifact** - Stores build output to internal Zerops storage -6. **Caches selected files** - Preserves specified files for faster future builds +#### Limitations: -The build container is automatically deleted after the build has finished or failed. +- maximum 25 characters +- must contain only lowercase ASCII letters (a-z) or numbers (0-9) -## Build configuration +:::caution +The hostname is fixed after the service is created. It can't be changed later. +::: -Configure your Deno build process in your `zerops.yaml` file according to the [full build & deploy Deno pipeline guide](/deno/how-to/build-pipeline). +### Set secret environment variables -## Build environment +Add environment variables with sensitive data, such as password, tokens, salts, certificates etc. These will be securely saved inside Zerops and added to your runtime service upon start. -### Default Deno build environment +Setting the secret environment variables is optional. You can set them later in Zerops GUI. -The default Deno build environment contains: +Read more about [different types of env variables](/ubuntu/how-to/env-variables#service-env-variables) in Zerops. -- {data.ubuntu.default} -- Selected version of Deno defined in `zerops.yaml` [build.base](/deno/how-to/build-pipeline#base) parameter -- [zCLI](/references/cli), Zerops command line tool -- Deno and Git +## Create Ubuntu service using zCLI -### Customize build environment +zCLI is the Zerops command-line tool. To create a new Ubuntu service via the command-line, follow these steps: -To install additional packages or tools, add one or more [build.prepareCommands](/deno/how-to/build-pipeline#preparecommands) to your `zerops.yaml`. +1. [Install & setup zCLI](/references/cli) +2. [Create a project description file](/ubuntu/how-to/create#create-a-project-description-file) +3. [Create a project with a Ubuntu and PostgreSQL service](#full-example) -:::info -The application code is available in the `/build/source` folder in your build container before the prepare commands are triggered. This allows you to use any file from your application code in your prepare commands (e.g. a configuration file). -::: +### Create a project description file -### Build hardware resources +Zerops uses a yaml format to describe the project infrastructure. -All runtime services use the same hardware resources for build containers: +#### Basic example: - - - - - - - - - - - - - - - - - - - - - - - - - -
HW resourceMinimumMaximum
CPU cores15
RAM8 GB8 GB
Disk1 GB100 GB
+Create a directory `my-project`. Create an `description.yaml` file inside the `my-project` directory with following content: -Build containers start with minimum resources and scale vertically up to maximum capacity as needed. +```yaml +# basic project data +project: + # project name + name: my-project +# array of project services +services: + - # service name + hostname: app + # service type and version number in ubuntu@{version} format + type: ubuntu@24.04 + # defines the minimum number of containers for horizontal autoscaling + minContainers: 1 + # defines the maximum number of containers for horizontal autoscaling. Max value = 6. + maxContainers: 6 + # optional: create env variables + envSecrets: + S3_ACCESS_KEY_ID: 'P8cX1vVVb' + S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' +``` -:::info -Build container resources are not charged separately. Limited build time is included in your [project core plan](/company/pricing#project-core-plans), with additional build time available if needed. -::: +The yaml file describes your future project infrastructure. The project will contain one Ubuntu service with default [auto scaling](/ubuntu/how-to/scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](/ubuntu/how-to/build-pipeline#ports). Following secret env variables will be configured: -### Build time limit +```env +S3_ACCESS_KEY_ID="P8cX1vVVb" +S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" +``` -The time limit for the whole build pipeline is **1 hour**. After 1 hour, Zerops will terminate the build pipeline and delete the build container. +#### Full example: -## Troubleshooting Deno builds - -### Build command failures - -If any [build command](/deno/how-to/build-pipeline#buildcommands) fails (returns non-zero exit code), the build is canceled. Check the [build log](/deno/how-to/logs#build-log) to troubleshoot the error. - -For Deno, if the error log doesn't contain specific error messages, try running your build with verbose output: - -```yaml -buildCommands: - - deno cache main.ts - - deno compile --allow-net --allow-read main.ts -``` - -### Prepare command failures - -If any [prepare command](/deno/how-to/build-pipeline#preparecommands) fails, check the [build log](/deno/how-to/logs#build-log) for specific error messages. Common issues include: - -- Missing permissions in Deno commands (add --allow-net, --allow-read, etc.) -- Ubuntu package installation failures (use sudo apt-get update first) -- Deno cache directory permissions - -### Build cache issues - -If you encounter unexpected build behavior or dependency issues, the problem might be related to [cached build data](/features/build-cache). While Zerops maintains the build cache to speed up deployments, sometimes you may need to start fresh. - -To invalidate the build cache: - -1. Go to your service detail in Zerops GUI -2. Choose **Pipelines & CI/CD Settings** from the left menu -3. Click on the **Invalidate build cache** button - -This will force Zerops to run the next build clean, including all prepare commands. Learn more about [build cache behavior](/features/build-cache). - -:::tip Advanced troubleshooting -For complex build issues that require investigation, you can enable [debug mode](/features/debug-mode) to pause the build process at specific points and inspect the build container state interactively. -::: - -## More resources - -For more details about the build and deploy pipeline, including how to cancel builds and manage application versions, see the [general pipeline documentation](/features/pipeline). - -## Next steps - -- Understand the [deployment process](/deno/how-to/deploy-process) -- Learn how to [customize the runtime environment](/deno/how-to/customize-runtime) -- Explore [build and runtime logs](/deno/how-to/logs) - ----------------------------------------- - -# Deno > How To > Controls - - - ----------------------------------------- - -# Deno > How To > Create - - -Zerops provides a powerful Deno runtime service with extensive build support. The Deno runtime is highly scalable and customizable to suit your development and production needs. With just a few clicks or commands, you can have a production-ready Deno environment up and running in no time. - -## Create a Deno service using Zerops GUI - -First, set up a project in the Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu under the **Services** section. From there, you can add a new Deno service: - -[Video: /vids/services/deno.webm](/vids/services/deno.webm) - -### Choose a Deno version - -Zerops supports the following Deno versions: - -:::info -You can easily [upgrade](/deno/how-to/upgrade) the major version at any time later. -::: - -### Set a hostname - -Enter a unique service identifier like "app", "cache", "gui", etc. Duplicate services with the same name within the same project are not allowed. - -#### Limitations: - -- Maximum 25 characters -- Must contain only lowercase ASCII letters (a-z) or numbers (0-9) - -:::caution -The hostname is fixed after the service is created and cannot be changed later. -::: - -### Set secret environment variables - -Add environment variables with sensitive data, such as passwords, tokens, salts, certificates, etc. These will be securely saved inside Zerops and added to your runtime service upon start. - -Setting secret environment variables is optional. You can always set them later in the Zerops GUI. - -Read more about the [different types of environment variables](/deno/how-to/env-variables#service-env-variables) in Zerops. - -## Create a Deno service using zCLI - -zCLI is the Zerops command-line tool. To create a new Deno service via the command line, follow these steps: - -1. [Install & setup zCLI](/references/cli) -2. [Create a project description file](/deno/how-to/create#create-a-project-description-file) -3. [Create a project with a Deno and PostgreSQL service](#full-example) - -### Create a project description file - -Zerops uses a YAML format to describe the project infrastructure. - -#### Basic example: - -Create a directory called `my-project`. Inside the `my-project` directory, create a `description.yaml` file with the following content: -```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in deno@{version} format - type: deno@latest - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' -``` - -The yaml file describes your future project infrastructure. The project will contain one Deno version 20 service with default [auto scaling](/deno/how-to/scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](/deno/how-to/build-pipeline#ports). Following secret env variables will be configured: - -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` - -#### Full example: - -Create a directory my-project. Create an description.yaml file inside the my-project directory with following content: +Create a directory my-project. Create an description.yaml file inside the my-project directory with following content: ```yaml # basic project data @@ -4643,7 +3721,7 @@ project: # project name name: my-project # optional: project description - description: A project with a Deno and PostgreSQL database + description: A project with a Ubuntu and PostgreSQL database # optional: project tags tags: - DEMO @@ -4652,8 +3730,8 @@ project: services: - # service name hostname: app - # service type and version number in deno@{version} format - type: deno@latest + # service type and version number in ubuntu@{version} format + type: ubuntu@24.04 # optional: vertical auto scaling customization verticalAutoscaling: cpuMode: DEDICATED @@ -4670,7 +3748,7 @@ services: minContainers: 2 # defines the maximum number of containers for horizontal autoscaling. Max value = 6. maxContainers: 4 - # optional: create env variables + # optional: create secret env variables envSecrets: S3_ACCESS_KEY_ID: 'P8cX1vVVb' S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' @@ -4682,9 +3760,9 @@ services: mode: NON_HA ``` -The yaml file describes your future project infrastructure. The project will contain a Deno service and a [PostgreSQL](/postgresql/overview) service. +The yaml file describes your future project infrastructure. The project will contain a Ubuntu service and a [PostgreSQL](/postgresql/overview) service. -Deno service with "app" hostname, the internal port(s) the service listens on will be defined later in the [zerops.yaml](/deno/how-to/build-pipeline#ports). Deno service will run on version 20 with a custom vertical and horizontal scaling. Following secret env variables will be configured: +Ubuntu service with "app" hostname, the internal port(s) the service listens on will be defined later in the zerops.yaml. Ubuntu service will run with a custom vertical and horizontal scaling. Following secret env variables will be configured: ```env S3_ACCESS_KEY_ID="P8cX1vVVb" @@ -4697,29 +3775,22 @@ The hostname of the PostgreSQL service will be set to "db". The [single containe The `project:` section is required. Only one project can be defined. -| Parameter | Description | Limitations | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -| **name** | The name of the new project. Duplicates are allowed. | | -| **description** | **Optional.** Description of the new project. | Maximum 255 characters. | -| **tags** | **Optional.** One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects. | -| **tags** | **Optional.** One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects. | - -At least one service in `services:` section is required. You can create a project with multiple services. The example above contains Deno and PostgreSQL services but you can create a `description.yaml` with your own combination of [services](/features/infrastructure). - - - + + - + - + + - + - + - + - + - + - + - + - @@ -4840,7 +3890,7 @@ You don't specify the project name in the `zcli project project-import` command, If you have access to more than one client, you must specify the client ID for which the project is to be created. The `clientID` is located in the Zerops GUI under the client name on the project dashboard page. -### Add Deno service to an existing project +### Add Ubuntu service to an existing project #### Example: @@ -4855,8 +3905,8 @@ project: services: - # service name hostname: app - # service type and version number in deno@{version} format - type: deno@latest + # service type and version number in ubuntu@{version} format + type: ubuntu@24.04 # defines the minimum number of containers for horizontal autoscaling minContainers: 1 # defines the maximum number of containers for horizontal autoscaling. Max value = 6. @@ -4867,7 +3917,7 @@ services: S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' ``` -The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one Deno service version 20 with default [auto scaling](/deno/how-to/scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: +The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one Ubuntu service version 1 with default [auto scaling](/ubuntu/how-to/scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: ```env S3_ACCESS_KEY_ID="P8cX1vVVb" @@ -4895,499 +3945,473 @@ Maximum size of the import.yaml file is 100 kB. ---------------------------------------- -# Deno > How To > Customize Runtime +# Ubuntu > How To > Controls -## Build Custom Runtime Images -Zerops allows you to build custom runtime images (CRI) when the default base runtime images don't meet your Deno application's requirements. This is an optional phase in the [build and deploy pipeline](/features/pipeline#runtime-prepare-phase-optional). +---------------------------------------- -:::important -You should not include your application code in the custom runtime image, as your built/packaged code is deployed automatically into fresh containers. -::: +# Ubuntu > How To > Build Process -## Configuration -### Default Deno Runtime Environment +## Build process overview -The default Deno runtime environment contains: +Zerops starts a temporary build container and performs the following actions: -- {data.ubuntu.default} -- Selected version of Deno when the runtime service was created -- [zCLI](/references/cli) -- Deno and Git +1. **Installs the build environment** - Sets up base system and runtime +2. **Downloads your application source code** - From [GitHub ↗](https://www.github.com), [GitLab ↗](https://www.gitlab.com) or via [Zerops CLI](/references/cli) +3. **Optionally customizes the build environment** - Runs prepare commands if configured +4. **Runs the build commands** - Executes your build process +5. **Uploads the application artifact** - Stores build output to internal Zerops storage +6. **Caches selected files** - Preserves specified files for faster future builds -### When You Need a Custom Runtime Image +The build container is automatically deleted after the build has finished or failed. -If your Deno application needs more than what's included in the default environment, you'll need to build a custom runtime image. Common scenarios include: +## Build configuration -- **System packages for processing**: When your app processes images, videos, or files (requiring packages like `sudo apt-get install -y imagemagick`) -- **Global Deno tools**: When you need CLI tools or utilities available system-wide -- **Native dependencies**: When your Deno modules require system libraries that aren't in the default environment +Configure your build process in your `zerops.yaml` file according to the pipeline guide. -Here are Deno-specific examples of configuring custom runtime images in your `zerops.yml`: +## Build environment -### Basic Deno Setup +### Default build environment -### Using Build Files in Runtime Preparation +The default build environment contains: -```yaml -build: - addToRunPrepare: - - deno.json - - import_map.json -run: - prepareCommands: - - sudo apt-get update - - sudo apt-get install -y imagemagick - - deno cache deps.ts -``` +- {data.ubuntu.default} +- [zCLI](/references/cli), Zerops command line tool +- -For complete configuration details, see the [runtime prepare phase configuration guide](/features/pipeline#configuration). +### Customize build environment -## Process and Caching +To install additional packages or tools, add one or more to your `zerops.yaml`. -### How Runtime Prepare Works -The runtime prepare process follows the same steps for all runtimes. See [how runtime prepare works](/features/pipeline#how-it-works) for the complete process details. +:::info +The application code is available in the `/build/source` folder in your build container before the prepare commands are triggered. This allows you to use any file from your application code in your prepare commands (e.g. a configuration file). +::: -### Caching Behavior -Zerops caches custom runtime images to optimize deployment times. Learn about [custom runtime image caching](/features/pipeline#custom-runtime-image-caching) including when images are cached and reused. +### Build hardware resources -### Build Management -For information about managing builds and deployments, see [managing builds and deployments](/features/pipeline#manage-builds-and-deployments). +All runtime services use the same hardware resources for build containers: -:::warning -Shared storage mounts are not available during the runtime prepare phase. -::: +
ParameterDescriptionParameterDescription
- hostname - hostname The unique service identifier. + + The hostname of the new database will be set to the `hostname` value. + + Limitations:
  • duplicate services with the same name in the same project are forbidden
  • maximum 25 characters
  • @@ -4728,90 +3799,69 @@ At least one service in `services:` section is required. You can create a projec
- type - type Specifies the service type and version. - See what [Deno service types](/references/import-yaml/type-list#runtime-services) are currently supported. + See what [Ubuntu service types](/references/import-yaml/type-list#runtime-services) are currently supported.
verticalAutoscaling - verticalAutoscaling - - Optional. Defines [custom vertical auto scaling parameters](/deno/how-to/create#set-auto-scaling-configuration). + Optional. Defines [custom vertical auto scaling parameters](/ubuntu/how-to/create#set-auto-scaling-configuration). - All verticalAutoscaling attributes are optional. Not specified - attributes will be set to their default values. + All verticalAutoscaling attributes are optional. Not specified attributes will be set to their default values.
- cpuMode - - cpuMode - - Optional. Accepts `SHARED`, `DEDICATED` values. Default is `SHARED` + Optional. Accepts `SHARED`, `DEDICATED` values. Default is `SHARED`
- minCpu/maxCpu - - minCpu/maxCpu - - Optional. Set the minCpu or maxCpu in CPU cores (integer). + Optional. Set the minCpu or maxCpu in CPU cores (integer).
- minRam/maxRam - - minRam/maxRam - - Optional. Set the minRam or maxRam in GB (float). + Optional. Set the minRam or maxRam in GB (float).
- minDisk/maxDisk - - minDisk/maxDisk - - Optional. Set the minDisk or maxDisk in GB (float). + Optional. Set the minDisk or maxDisk in GB (float).
minContainers - minContainers - - Optional. Default = 1. Defines the minimum number of containers - for [horizontal autoscaling](/deno/how-to/create#horizontal-auto-scaling). + Optional. Default = 1. Defines the minimum number of containers for [horizontal autoscaling](/ubuntu/how-to/create#horizontal-auto-scaling). - Limitations: + Limitations: Current maximum value = 10.
maxContainers - maxContainers - - Defines the maximum number of containers for [horizontal autoscaling](/deno/how-to/create#horizontal-auto-scaling). + Defines the maximum number of containers for [horizontal autoscaling](/ubuntu/how-to/create#horizontal-auto-scaling). - Limitations: + Limitations: Current maximum value = 10.
envSecrets - envSecrets - - Optional. Defines one or more secret env variables as a key value - map. See env variable [restrictions](/deno/how-to/env-variables#env-variable-restrictions). + Optional. Defines one or more secret env variables as a key value map. See env variable [restrictions](/ubuntu/how-to/env-variables#env-variable-restrictions).
+ + + + + + + + + + + + + + + + + + + + + + + + +
HW resourceMinimumMaximum
CPU cores15
RAM8 GB8 GB
Disk1 GB100 GB
-## Troubleshooting +Build containers start with minimum resources and scale vertically up to maximum capacity as needed. -If your `prepareCommands` fail, check the [prepare runtime log](/deno/how-to/logs#prepare-runtime-log) for specific error messages. +### Build time limit ----------------------------------------- +The time limit for the whole build pipeline is **1 hour**. After 1 hour, Zerops will terminate the build pipeline and delete the build container. -# Deno > How To > Deploy Process +:::info +Build container resources are not charged separately. Limited build time is included in your [project core plan](/company/pricing#project-core-plans), with additional build time available if needed. +::: +## Troubleshooting builds +:::tip Advanced troubleshooting +For complex build issues that require investigation, you can enable [debug mode](/features/debug-mode) to pause the build process at specific points and inspect the build container state interactively. +::: ----------------------------------------- +### Build and prepare command failures -# Deno > How To > Env Variables +If any or fails (returns non-zero exit code), the build is canceled. Check the to troubleshoot the error. +### Build cache issues +If you encounter unexpected build behavior or dependency issues, the problem might be related to cached build data. While Zerops maintains the build cache to speed up deployments, sometimes you may need to start fresh. ----------------------------------------- +To invalidate the build cache: -# Deno > How To > Filebrowser +1. Go to your service detail in Zerops GUI +2. Choose **Pipelines & CI/CD Settings** from the left menu +3. Click on the **Invalidate build cache** button +This will force Zerops to run the next build clean, including all prepare commands. +Learn more about [build cache behavior](/features/build-cache). ----------------------------------------- +## More resources -# Deno > How To > Logs +For more details about the build and deploy pipeline, including how to cancel builds and manage application versions, see the [general pipeline documentation](/features/pipeline). +## Next steps +- Understand the +- Learn how to +- Explore ---------------------------------------- -# Deno > How To > Scaling - +# Ubuntu > How To > Build Pipeline ----------------------------------------- +Zerops provides a customizable build and runtime environment for your Ubuntu application. -# Deno > How To > Shared Storage +## Add zerops.yaml to your repository +Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: +```yaml +zerops: + # define hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Set the base technology for the build environment: + base: ubuntu@24.04 ----------------------------------------- + # OPTIONAL. Customize the build environment by installing additional packages + # or tools to the base build environment. + prepareCommands: + - sudo apt-get something + - curl something else -# Deno > How To > Trigger Pipeline + # OPTIONAL. Build your application, e.g. with not officially supported version of your favourite technology + buildCommands: + - go build -o app main.go + # REQUIRED. Select which files / folders to deploy after + # the build has successfully finished + deployFiles: app + # OPTIONAL. Which files / folders you want to cache for the next build. + # Next builds will be faster when the cache is used. + cache: some_file + # ==== how to run your application ==== + run: + # OPTIONAL. Sets the base technology for the runtime environment: + base: ubuntu@24.04 ----------------------------------------- + # OPTIONAL. Sets the internal port(s) your app listens on: + ports: + # port number + - port: 8080 -# Deno > How To > Upgrade + # OPTIONAL. Customize the runtime Ubuntu environment by installing additional + # dependencies to the base Ubuntu runtime environment. + prepareCommands: + - sudo apt-get something + - curl something else + # OPTIONAL. Run one or more commands each time a new runtime container + # is started or restarted. These commands are triggered before + # your Ubuntu application is started. + initCommands: + - rm -rf ./cache + # REQUIRED. Your Ubuntu application start command + start: ./app +``` ----------------------------------------- +The top-level element is always `zerops`. -# Deno > Overview +### Setup +The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. +Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: -[Deno ↗](https://deno.org/en) is an asynchronous event-driven JavaScript runtime, which is designed to build scalable network applications. +```yaml +zerops: + # definition for app service + - setup: app + # optional + build: ... + # optional + deploy: ... + # required + run: ... -:::tip -Have you got any additional question? Join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. -::: + # definition for api service + - setup: api + # optional + build: ... + # optional + deploy: ... + # required + run: ... +``` -As said, there is no need for coding yet, we have created a [Github repository ↗](https://github.com/zeropsio/recipe-deno), a **_recipe_**, containing the most simple Deno web application. The repo will be used as a source from which the app will be built. +Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. -### 🚀 No Fuss, Just Deploy with Speed! +## Build pipeline configuration -This is the most bare-bones example of Deno app running in Zerops — as few libraries as possible, - just a simple endpoint with connect, read and write to a Zerops PostgreSQL database. +### base - [Deploy "deno" recipe on Zerops](https://app.zerops.io/recipe/?lf=deno) +_REQUIRED._ Sets the base technology for the build environment. -1. Log in/sign up to [Zerops GUI ↗](https://app.zerops.io) +Following options are available for Ubuntu builds: -2. In the **Projects** box click on **Import a project** and paste in the following YAML config ([source ↗](https://github.com/zeropsio/recipe-deno/blob/main/zerops-project-import.yaml)): +- `ubuntu@24.04` +- `ubuntu@22.04`, `ubuntu@latest` ```yaml -project: - name: recipe-deno - tags: - - zerops-recipe - -services: - - hostname: api - type: deno@1 - buildFromGit: https://github.com/zeropsio/recipe-deno - enableSubdomainAccess: true - - - hostname: db - type: postgresql@16 - mode: NON_HA - priority: 1 +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Sets the base technology for the build environment: + base: ubuntu@24.04 + ... ``` -3. Click on **Import project** and wait until all pipelines have finished. - -**That's it, your application is now up and running! :star: Let's check it works:** +

+ The base build environment contains {data.ubuntu.default}, [Zerops command line tool](/references/cli), `git` and `wget`. +

-1. A _subdomain_ should have been enabled and visible in the project's **IP addressed & Public Routing Overview** box. Its format should look similar to this `https://api-7f6-8000.prg1.zerops.app`. -2. Click or the `subdomain` URL to open it in a browser and you should see +:::info +You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. +::: -``` -{"message":"This is a simple, basic Deno / Oak application running in Zerops.io,\n each request adds an entry to the PostgreSQL database and returns a count.\n See the source repository (https://github.com/zeropsio/recipe-deno) for more information.","newEntry":"274b0cc1-5b6d-4351-b8ec-53cf82bd9d0f","count":1} -``` +If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: -:::tip -Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. -::: - -## How to start - -It doesn't matter whether it's your first curious introduction to Zerops, you have already mastered the basics and are looking for a tiny detail or inspiration. Below, choose a section that fits your needs: - -- [Care for details?](/deno/how-to/create) — Dive in all Zerops has to offer for your Deno application. -- [Deno recipes](https://github.com/zeropsio?q=deno&type=all&language=&sort=) — Get inspired by already existing repositories, ready to be imported to Zerops. - -## Feature Highlights - -- [Create Deno service](/deno/how-to/create) — Start with creating a Deno service using GUI or zCLI. -- [Zerops.yaml](/deno/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to create your own app. -- [Scaling configuration](/deno/how-to/scaling) — Set up scaling of your Deno application so that it runs smoothly while using only necessary resources. - -{" "} +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Sets the base technology for the build environment: + base: + - ubuntu@24.04 + prepareCommands: + - zsc add nodejs@latest + ... +``` -- [Customize build environment](/deno/how-to/build-process#customize-build-environment) -- [Customize runtime environment](/deno/how-to/customize-runtime) +See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). -## When in doubt, reach out +To customize your build environment use the [prepareCommands](#preparecommands) attribute. -Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. +:::note +Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. +::: -In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. +### prepareCommands -Have you build something that others might find useful? Don't hesitate to share your knowledge! +_OPTIONAL._ Customizes the build environment by installing additional dependencies or tools to the base build environment. -- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. +The base build environment contains: -## Popular Guides +- {data.ubuntu.default} +- [Zerops command line tool](/references/cli) +- `git` and `wget` -- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. -- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. +To install additional packages or tools add one or more prepare commands: +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Set the base technology for the build environment: + base: ubuntu@24.04 ----------------------------------------- + # OPTIONAL. Customize the build environment by installing additional packages + # or tools to the base build environment. + prepareCommands: + - sudo apt-get something + - curl something else + ... +``` -# Docker > Overview +When the first build is triggered, Zerops will +1. create a build container +2. download your application code from your repository +3. run the prepare commands in the defined order -Zerops provides Docker support through dedicated Virtual Machine (VM) environments, ensuring maximum compatibility and isolation while maintaining integration with the broader Zerops ecosystem. This guide explains how to effectively use Docker services in Zerops, including best practices and important considerations. +The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. -## Why VMs +:::note +These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. +::: -While Zerops primarily uses native Linux containers for optimal performance, this VM-based approach allows you to run virtually any Docker container while maintaining Zerops' robust infrastructure management. +#### Command exit code -You can learn more about [differences](/features/container-vs-vm) between Containers and Virtual Machines in Zerops. +If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/ubuntu/how-to/logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. -Before using Docker services, consider these important aspects: +#### Single or separated shell instances -### Virtual Machine Environment +You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). -Docker services in Zerops operate in a full VM environment, which has several implications: +### buildCommands -- **Slower Boot Times**: VMs require more time to initialize due to full kernel boot -- **Higher Resource Usage**: VMs include additional system overhead compared to native containers -- **Scaling Limitations**: - - Vertical scaling requires VM restart - - Resources must be set as fixed values (no min-max ranges) - - Zerops automatically restarts the VM when resource values are changed in UI -- **Storage Management**: Disk space can only be increased, not decreased without recreation -- **Build Phase Limitations**: Build phase runs in containers, not in the VM environment +_OPTIONAL._ Defines build commands. -### Advantages +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Set the base technology for the build environment: + base: ubuntu@24.04 -Despite these limitations, Docker services offer some benefits: + # OPTIONAL. Build your application + buildCommands: + - + ... +``` -- **Broad Compatibility**: Run almost any Docker container with minimal modification -- **Familiar Environment**: Standard Docker runtime environment +Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. -## Configuration Guide +Before the build commands are triggered the build container contains: -### Supported Version +1. base environment defined by the [base](#base) attribute +2. optional customisation of the base environment defined in the [prepareCommands](#preparecommands) attribute +3. your application code -Currently supported Docker versions: +For detailed information about build commands, including how to run commands in single or separate shell instances and command exit code handling, refer to the documentation for your specific technology (e.g., [Node.js](/nodejs/how-to/build-pipeline), [Go](/ubuntu/how-to/build-pipeline), [Python](/python/how-to/build-pipeline), etc.). -### Basic Structure +### deployFiles -Docker services in Zerops are configured through the `zerops.yaml` file. Here's a typical configuration pattern: +_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. -```yaml title="zerops.yaml" -zerops: - - setup: app - run: - base: docker@latest - prepareCommands: - - docker image pull : # Always use specific version tags - start: docker run --network=host : - ports: - - port: - httpSupport: true +```yaml +# REQUIRED. Select which files / folders to deploy after +# the build has successfully finished +deployFiles: + - app ``` -:::important -Always use specific version tags (like `1.0.0`) instead of `:latest`. Zerops caches the `prepareCommands` output, which means a new `:latest` image won't be automatically pulled on subsequent deployments unless the cache is manually cleared or the commands change. -::: +Determines files or folders produced by your build, which should be deployed to your runtime service containers. -Refer to the [Docker recipe repository](https://github.com/zeropsio/recipe-docker) for an example configuration. +The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. -:::note -We are actively working on improving the speed of image caching after `run.prepareCommands` and reducing the startup time of runtime VMs. These improvements will be released in future updates. -::: +The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. -### Network Configuration +#### Examples -Docker services require the `--network=host` flag for proper integration with Zerops: +Deploys a folder, and a file from the project root directory: -- **Direct Port Management**: Ports are managed through `zerops.yaml` -- **Simplified Configuration**: Avoids double port exposure in Docker and Zerops -- **Native Performance**: Direct access to host networking +```yaml +deployFiles: + - app + - file.txt +``` -### Docker Compose Support +Deploys the whole content of the build container: -For projects using Docker Compose, additional configuration is required: +```yaml +deployFiles: . +``` -1. **File Deployment**: - ```yaml title="zerops.yaml" - build: - # base cannot be docker — build phase runs in containers, not VMs - deployFiles: ./docker-compose.yaml - addToRunPrepare: ./docker-compose.yaml - ``` +Deploys a folder, and a file in a defined path: -2. **Network Mode**: - ```yaml title="docker-compose.yaml" - services: - your-service: - image: your-image:1.0.0 - network_mode: host - ``` +```yaml +deployFiles: + - ./path/to/file.txt + - ./path/to/dir/ +``` -3. **Start Command**: - ```yaml title="zerops.yaml" - run: - start: docker compose up --force-recreate - ``` +#### How to use a wildcard in the path -### Environment Variables +Zerops supports the `~` character as a wildcard for one or more folders in the path. -When using Docker services, there's an additional layer to consider since environment variables defined in Zerops must be explicitly passed to your Docker containers. +Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` -#### 1. Defining Variables in Zerops +```yaml +deployFiles: ./path/~/to/file.txt +``` -Define your environment variables in the `run.envVariables` section of your `zerops.yaml` (example uses [referenced](/features/env-variables#referencing-variables) variables): +Deploys all folders that are located in any path that begins with `/path/to/` -```yaml title="zerops.yaml" -zerops: - - setup: app - run: - base: docker@latest - envVariables: - DB_HOST: ${db_hostname} - DB_PORT: ${db_port} +```yaml +deployFiles: ./path/to/~/ ``` -#### 2. Passing Variables to Docker Containers - -For single containers, pass variables using the `-e` flag: +Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` -```yaml title="zerops.yaml" -run: - base: docker@latest - prepareCommands: - - docker image pull my-application:1.0.0 # Use specific version tags, not :latest - start: docker run -e DB_HOST -e DB_PORT --network=host my-application:1.0.0 +```yaml +deployFiles: ./path/~/to/ ``` -:::important -Always use specific version tags (like `1.0.0`) instead of `:latest`. Zerops caches the `prepareCommands` output, which means a new `:latest` image won't be automatically pulled on subsequent deployments unless the cache is manually cleared or the commands change. +:::note Example +By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` ::: -For Docker Compose setups, pass environment variables in your `docker-compose.yaml`: - -```yaml title="docker-compose.yaml" -services: - api: - image: my-application:1.0.0 - network_mode: host - environment: - - DB_HOST - - DB_PORT -``` - -## Implementation Examples +#### .deployignore -### Single Container +Add a `.deployignore` file to the root of your project to specify which files and folders Zerops should ignore during deploy. The syntax follows the same pattern format as [`.gitignore`](https://git-scm.com/docs/gitignore#_pattern_format). -```yaml title="zerops.yaml" -zerops: - - setup: app - run: - base: docker@latest - prepareCommands: - - docker image pull crccheck/hello-world:1.0.0 # Always use specific version tags - start: docker run --network=host crccheck/hello-world:1.0.0 - ports: - - port: 8000 - httpSupport: true -``` +To ignore a specific file or directory path, start the pattern with a forward slash (`/`). Without the leading slash, the pattern will match files with that name in any directory. -:::important -Always use specific version tags (like `1.0.0`) instead of `:latest`. Zerops caches the `prepareCommands` output, which means a new `:latest` image won't be automatically pulled on subsequent deployments unless the cache is manually cleared or the commands change. +:::tip +For consistency, it's recommended to configure both your `.gitignore` and `.deployignore` files with the same patterns. ::: -### Single Service with Docker Compose +Examples: ```yaml title="zerops.yaml" zerops: - - setup: api + - setup: app build: - # base cannot be docker — build phase runs in containers, not VMs - deployFiles: ./docker-compose.yaml - addToRunPrepare: ./docker-compose.yaml - run: - base: docker@latest - prepareCommands: - - docker compose pull api - start: docker compose up api --force-recreate - ports: - - port: 8000 - httpSupport: true -``` - -```yaml title="docker-compose.yaml (excerpt)" -services: - api: - image: your-image:1.0.0 - network_mode: host - # other configuration... + deployFiles: ./ ``` -### Multiple Services with Docker Compose - -```yaml title="zerops.yaml" -zerops: - - setup: apps - build: - # base cannot be docker — build phase runs in containers, not VMs - deployFiles: ./docker-compose.yaml - addToRunPrepare: ./docker-compose.yaml - run: - base: docker@latest - prepareCommands: - - docker compose pull - start: docker compose up --force-recreate - ports: - - port: 8000 - httpSupport: true +```text title=".deployignore" +/src/file.txt ``` - -```yaml title="docker-compose.yaml (excerpt)" -services: - web: - image: web-image:1.0.0 - network_mode: host - # other configuration... - - api: - image: api-image:1.0.0 - network_mode: host - # other configuration... +The example above ignores `file.txt` only in the root src directory. +```text title=".deployignore" +src/file.txt ``` +This example above ignores `file.txt` in ANY directory named `src`, such as: +- `/src/file.txt` +- `/folder2/folder3/src/file.txt` +- `/src/src/file.txt` -## Best Practices - -#### Image Management -- **Always use specific version tags** instead of `:latest` - This prevents caching issues as Zerops caches `prepareCommands` output - -#### Resource Planning -- Account for VM overhead in resource allocation -- Plan for longer initialization times -- Consider the impact on scaling operations - -#### Migration Consideration -- Evaluate if your workload could run on native containers -- Consider gradual migration for complex applications -- Balance development effort against operational benefits - -## Limitations and Workarounds - -### Build Phase - -Since the build phase runs in containers rather than VMs: - -- Use `run.prepareCommands` for Docker-specific build steps -- Consider external CI/CD for complex Docker builds -- Leverage pre-built images when possible - -### Scaling Operations +:::note +`.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. +::: -Docker services in Zerops have specific scaling characteristics that differ from native containers: +### cache -#### Vertical Scaling -- Resources must be defined with **fixed** values instead of min-max ranges -- CPU, RAM, and disk are specified as single values: - ```yaml - verticalAutoscaling: - cpu: 3 - ram: 2 - disk: 20 - ``` -- Any change to these values through the UI triggers an automatic VM restart -- Plan your resource allocation carefully to minimize scaling operations +_OPTIONAL._ Defines which files or folders will be cached for the next build. -#### Horizontal Scaling -- Still supports multiple containers through `minContainers` and `maxContainers` -- Consider breaking large services into smaller components -- Implement proper health checks for reliable scaling -- Use horizontal scaling when possible to avoid VM restarts +```yaml +# OPTIONAL. Which files / folders you want to cache for the next build. +# Next builds will be faster when the cache is used. +cache: file.txt +``` ----------------------------------------- +The cache attribute helps optimize build times by preserving specified files between builds. -# Dotnet > How To > Build Pipeline +The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). +Learn more about the [build cache system](/features/build-cache) in Zerops. -Zerops provides a customizable build and runtime environment for your .NET application. +### envVariables -## Add zerops.yaml to your repository +_OPTIONAL._ Defines the environment variables for the build environment. -Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: +Enter one or more env variables in following format: ```yaml zerops: @@ -5395,103 +4419,31 @@ zerops: - setup: app # ==== how to build your application ==== build: - # REQUIRED. Set the base technology for the build environment: - base: dotnet@6 - - # OPTIONAL. Set the operating system for the build environment. - # os: ubuntu - - # OPTIONAL. Customize the build environment by installing additional packages - # or tools to the base build environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else - - # OPTIONAL. Build your application - buildCommands: - - npm i - - npm run build - - # REQUIRED. Select which files / folders to deploy after - # the build has successfully finished - deployFiles: - - dist - - package.json - - node_modules - - # OPTIONAL. Which files / folders you want to cache for the next build. - # Next builds will be faster when the cache is used. - cache: node_modules - - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: dotnet@latest - - # OPTIONAL. Sets the internal port(s) your app listens on: - ports: - # port number - - port: 5000 - - # OPTIONAL. Customize the runtime .NET environment by installing additional - # dependencies to the base .NET runtime environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else - - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your .NET application is started. - # initCommands: - # - rm -rf ./cache - - # REQUIRED. Your .NET application start command - start: npm start -``` - -The top-level element is always `zerops`. - -### Setup - -The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. -Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: - -```yaml -zerops: - # definition for app service - - setup: app - # optional - build: ... - # optional - deploy: ... - # required - run: ... + base: ubuntu@24.04 + … - # definition for api service - - setup: api - # optional - build: ... - # optional - deploy: ... - # required - run: ... + # OPTIONAL. Defines the env variables for the build environment: + envVariables: + MODE: production + DB_NAME: db + DB_HOST: db + DB_USER: db + DB_PASS: ${db_password} ``` -Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. +Read more about [environment variables](/ubuntu/how-to/env-variables) in Zerops. -## Build pipeline configuration +## Runtime configuration ### base -_REQUIRED._ Sets the base technology for the build environment. +_OPTIONAL._ Sets the base technology for the runtime environment. +If you don't specify the `run.base` attribute, Zerops keeps the current Ubuntu version for your runtime. -Following options are available for .NET builds: +Following options are available for Ubuntu builds: -- `dotnet@10`, `dotnet@latest` -- `dotnet@9` -- `dotnet@8` -- `dotnet@7` -- `dotnet@6` +- `ubuntu@24.04` +- `ubuntu@22.04`, `ubuntu@latest` ```yaml zerops: @@ -5500,20 +4452,25 @@ zerops: # ==== how to build your application ==== build: # REQUIRED. Sets the base technology for the build environment: - base: dotnet@6 + base: ubuntu@24.04 + ... + + # ==== how to run your application ==== + run: + # OPTIONAL. Sets the base technology for the runtime environment: + base: ubuntu@24.04 ... ```

- The base build environment contains {data.alpine.default}, the selected - major version of .NET, [Zerops command line tool](/references/cli), `ASP .NET` and `git`. + The base runtime environment contains {data.ubuntu.default}, Zerops command line tool, `git` and `wget`.

:::info You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. ::: -If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: +If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: ```yaml zerops: @@ -5522,357 +4479,16 @@ zerops: # ==== how to build your application ==== build: # REQUIRED. Sets the base technology for the build environment: - base: - - dotnet@6 - prepareCommands: - - zsc add go@latest - ... -``` - -See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). - -To customize your build environment use the [prepareCommands](#preparecommands) attribute. - -:::note -Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. -::: - -### os - -_OPTIONAL._ Sets the operating system for the build environment. - -Following options are available: - -- `alpine` -- `ubuntu` - -Default value is `alpine`. - -We are currently using following os version: - -- {data.alpine.default} -- {data.ubuntu.default} - -:::caution -The os version is fixed and cannot be customized. -::: - -:::note -Changing the OS setting will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache behavior. -::: - -### prepareCommands - -_OPTIONAL._ Customizes the build environment by installing additional dependencies or tools to the base build environment. - -The base build environment contains: - -- {data.alpine.default} -- selected version of .NET defined in the [base](#base) attribute -- [Zerops command line tool](/references/cli) -- `ASP .NET` and `git` - -To install additional packages or tools add one or more prepare commands: - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: dotnet@6 - - # OPTIONAL. Customize the build environment by installing additional packages - # or tools to the base build environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` - -When the first build is triggered, Zerops will - -1. create a build container -2. download your application code from your repository -3. run the prepare commands in the defined order - -The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. - -:::note -These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. -::: - -#### Command exit code - -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/dotnet/how-to/logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. - -#### Single or separated shell instances - -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). - -### buildCommands - -_OPTIONAL._ Defines build commands. - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: dotnet@6 - - # OPTIONAL. Build your application - buildCommands: - - dotnet build -o app - ... -``` - -Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. - -Before the build commands are triggered the build container contains: - -1. base environment defined by the [base](#base) attribute -2. optional customisation of the base environment defined in the [prepareCommands](#preparecommands) attribute -3. your application code - -#### Run build commands as a single shell instance - -Use following syntax to run all commands in the same environment context. For example, if one command changes the current directory, the next command continues in that directory. When one command creates an environment variable, the next command can access it. - -```yaml -buildCommands: - - | - sudo apt-get -y install dotnet-runtime-6.0 aspnetcore-runtime-6.0 dotnet-sdk-6.0 # already installed for .NET service - dotnet build -o app -``` - -#### Run build commands as a separate shell instances - -When the following syntax is used, each command is triggered in a separate environment context. For example, each shell instance starts in the home directory again. When one command creates an environment variable, it won't be available for the next command. - -```yaml -buildCommands: - - sudo apt-get -y install dotnet-runtime-6.0 aspnetcore-runtime-6.0 dotnet-sdk-6.0 # already installed for .NET service - - dotnet build -o app -``` - -#### Command exit code - -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/dotnet/how-to/logs#build-log) to troubleshoot the error. If the error log doesn't contain any specific error message, try to run your build with the `--verbosity ` option. - -```yaml -buildCommands: - - dotnet build --verbosity detailed -``` - -If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `buildCommands` are finished, the application build is completed and ready for the deploy phase. - -### deployFiles - -_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. - -```yaml -# REQUIRED. Select which files / folders to deploy after -# the build has successfully finished -deployFiles: - - app -``` - -Determines files or folders produced by your build, which should be deployed to your runtime service containers. - -The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. - -The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. - -#### Examples - -Deploys a folder, and a file from the project root directory: - -```yaml -deployFiles: - - app - - file.txt -``` - -Deploys the whole content of the build container: - -```yaml -deployFiles: . -``` - -Deploys a folder, and a file in a defined path: - -```yaml -deployFiles: - - ./path/to/file.txt - - ./path/to/dir/ -``` - -#### How to use a wildcard in the path - -Zerops supports the `~` character as a wildcard for one or more folders in the path. - -Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` - -```yaml -deployFiles: ./path/~/to/file.txt -``` - -Deploys all folders that are located in any path that begins with `/path/to/` - -```yaml -deployFiles: ./path/to/~/ -``` - -Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` - -```yaml -deployFiles: ./path/~/to/ -``` - -:::note Example -By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` -::: -#### .deployignore - -Add a `.deployignore` file to the root of your project to specify which files and folders Zerops should ignore during deploy. The syntax follows the same pattern format as [`.gitignore`](https://git-scm.com/docs/gitignore#_pattern_format). - -To ignore a specific file or directory path, start the pattern with a forward slash (`/`). Without the leading slash, the pattern will match files with that name in any directory. - -:::tip -For consistency, it's recommended to configure both your `.gitignore` and `.deployignore` files with the same patterns. -::: - -Examples: - -```yaml title="zerops.yaml" -zerops: - - setup: app - build: - deployFiles: ./ -``` - -```text title=".deployignore" -/src/file.txt -``` -The example above ignores `file.txt` only in the root src directory. -```text title=".deployignore" -src/file.txt -``` -This example above ignores `file.txt` in ANY directory named `src`, such as: -- `/src/file.txt` -- `/folder2/folder3/src/file.txt` -- `/src/src/file.txt` - -:::note -`.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. -::: - -### cache - -_OPTIONAL._ Defines which files or folders will be cached for the next build. - -```yaml -# OPTIONAL. Which files / folders you want to cache for the next build. -# Next builds will be faster when the cache is used. -cache: file.txt -``` - -The cache attribute helps optimize build times by preserving specified files between builds. - -The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). - -Learn more about the [build cache system](/features/build-cache) in Zerops. - -### envVariables - -_OPTIONAL._ Defines the environment variables for the build environment. - -Enter one or more env variables in following format: - -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - base: dotnet@6 - … - - # OPTIONAL. Defines the env variables for the build environment: - envVariables: - DOTNET_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` - -Read more about [environment variables](/dotnet/how-to/env-variables) in Zerops. - -## Runtime configuration - -### base - -_OPTIONAL._ Sets the base technology for the runtime environment. -If you don't specify the `run.base` attribute, Zerops keeps the current .NET version for your runtime. - -Following options are available for .NET builds: - -- `dotnet@10`, `dotnet@latest` -- `dotnet@9` -- `dotnet@8` -- `dotnet@7` -- `dotnet@6` - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: dotnet@6 - ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: dotnet@6 - ... -``` - -

- The base runtime environment contains {data.alpine.default}, the - selected major version of .NET, [Zerops command line tool](/references/cli) and `ASP .NET` and `git`. -

- -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. -::: - -If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: dotnet@6 + base: ubuntu@24.04 ... # ==== how to run your application ==== run: # OPTIONAL. Sets the base technology for the runtime environment: base: - - dotnet@6 + - ubuntu@24.04 prepareCommands: - - zsc add go@latest + - zsc add nodejs@latest ... ``` @@ -5880,33 +4496,13 @@ See the full list of supported [run base environments](/zerops-yaml/base-list). To customise your build environment use the `prepareCommands` attribute. -### os - -_OPTIONAL._ Sets the operating system for the runtime environment. - -Following options are available: - -- `alpine` -- `ubuntu` - -Default value is `alpine`. - -We are currently using following os version: - -- {data.alpine.default} -- {data.ubuntu.default} - -:::caution -The os version is fixed and cannot be customised. -::: - ### ports _OPTIONAL._ Specifies one or more internal ports on which your application will listen. Projects in Zerops represent a group of one or more services. Services can be of different types (runtime services, databases, message brokers, object storage, etc.). All services of the same project share a **dedicated private network**. To connect to a service within the same project, just use the service hostname and its internal port. -For example, to connect to a .NET service with hostname = "app" and port = 5000 from another service of the same project, simply use `app:5000`. Read more about [how to access a .NET service](/references/networking/internal-access#basic-service-communication). +For example, to connect to a Ubuntu service with hostname = "app" and port = 8080 from another service of the same project, simply use `app:8080`. Read more about [how to access a Ubuntu service](/references/networking/internal-access#basic-service-communication). Each port has following attributes: @@ -5935,12 +4531,10 @@ Each port has following attributes: ### prepareCommands -_OPTIONAL._ Customises the .NET runtime environment by installing additional dependencies or tools to the runtime base environment. +_OPTIONAL._ Customises the Ubuntu runtime environment by installing additional dependencies or tools to the runtime base environment.

- The base .NET environment contains {data.alpine.default}, the selected - major version of .NET, [Zerops command line tool](/references/cli) and `ASP .NET` and `git`. To install additional packages - or tools add one or more prepare commands: + The base Ubuntu environment contains {data.ubuntu.default}, [Zerops command line tool](/references/cli) and `git` and `wget`. To install additional packages or tools add one or more prepare commands:

```yaml @@ -5954,7 +4548,7 @@ zerops: # ==== how to run your application ==== run: # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base .NET runtime environment. + # or tools to the base Ubuntu runtime environment. prepareCommands: - sudo apt-get something - curl something else @@ -5973,7 +4567,7 @@ When the first deploy with a defined prepare attribute is triggered, Zerops will #### Command exit code -If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](/dotnet/how-to/logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. +If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](/ubuntu/how-to/logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. #### Cache of your custom runtime environment @@ -5993,10 +4587,7 @@ You can configure your prepare commands to be run in a single shell instance or ### Copy folders or files from your build container

- The prepare runtime container contains {data.alpine.default}, the - selected major version of .NET, - [Zerops command line tool](/references/cli) and - `ASP .NET` and `git`. + The prepare runtime container contains {data.ubuntu.default}, [Zerops command line tool](/references/cli) and `git` and `wget`.

The prepare runtime container does not contain your application code nor the built application. If you need to copy some folders or files from the build container to the runtime container (e.g. a configuration file) use the `addToRunPrepare` attribute in the [build section](#build-pipeline-configuration). @@ -6013,7 +4604,7 @@ zerops: # ==== how to run your application ==== run: # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base .NET runtime environment. + # or tools to the base Ubuntu runtime environment. prepareCommands: - sudo apt-get something - curl something else @@ -6037,12 +4628,12 @@ zerops: run: # OPTIONAL. Run one or more commands each time a new runtime container # is started or restarted. These commands are triggered before - # your .NET application is started. + # your Ubuntu application is started. initCommands: - rm -rf ./cache ``` -These commands are triggered in the runtime container before your .NET application is started via the [start command](#start). +These commands are triggered in the runtime container before your Ubuntu application is started via the [start command](#start). :::note `run.initCommands` run in the `/var/www` directory. @@ -6051,14 +4642,14 @@ These commands are triggered in the runtime container before your .NET applicati Use init commands to clean or initialise your application cache or similar operations. :::caution -The init commands will delay the start of your application each time a new runtime container is started (including the horizontal [scaling](/dotnet/how-to/scaling) or when a runtime container is restarted). +The init commands will delay the start of your application each time a new runtime container is started (including the horizontal [scaling](/ubuntu/how-to/scaling) or when a runtime container is restarted). Do not use the init commands for customising your runtime environment. Use the [run:prepareCommands](#preparecommands-1) attribute instead. ::: #### Command exit code -If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](/dotnet/how-to/logs#runtime-log) to troubleshoot the error. +If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](/ubuntu/how-to/logs#runtime-log) to troubleshoot the error. #### Single or separated shell instances @@ -6078,18 +4669,18 @@ zerops: run: # OPTIONAL. Defines the env variables for the runtime environment: envVariables: - DOTNET_ENV: production + MODE: production DB_NAME: db DB_HOST: db DB_USER: db DB_PASS: ${db_password} ``` -Read more about [environment variables](/dotnet/how-to/env-variables) in Zerops. +Read more about [environment variables](/ubuntu/how-to/env-variables) in Zerops. ### start -_REQUIRED._ Defines the start command for your .NET application. +_OPTIONAL._ Defines the start command for your Ubuntu application. ```yaml zerops: @@ -6100,8 +4691,8 @@ zerops: # ==== how to run your application ==== run: - # REQUIRED. Your .NET application start command - start: cd app && dotnet dnet.dll + # OPTIONAL. Your Ubuntu application start command + start: ./app ``` ### health check @@ -6157,8 +4748,8 @@ zerops: # ==== how to run your application ==== run: - # REQUIRED. Your .NET application start command - start: cd app && dotnet dnet.dll + # OPTIONAL. Your Ubuntu application start command + start: ./app # OPTIONAL. Define a health check with a HTTP GET request option. # Configures the check on http://127.0.0.1:80/status @@ -6186,7 +4777,7 @@ Following attributes are available: Defines a local command to be run. - The command has access to the same [environment variables](/dotnet/how-to/create#set-secret-environment-variables) as your .NET application. + The command has access to the same [environment variables](/ubuntu/how-to/create#set-secret-environment-variables) as your Ubuntu application. A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. @@ -6205,8 +4796,8 @@ zerops: # ==== how to run your application ==== run: - # REQUIRED. Your .NET application start command - start: cd app && dotnet dnet.dll + # REQUIRED. Your Ubuntu application start command + start: ./app # OPTIONAL. Define a health check with a shell command. healthCheck: @@ -6243,7 +4834,7 @@ Read more about setting up [cron](/zerops-yaml/cron) in Zerops. ### readiness check -_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](/dotnet/how-to/deploy-process#readiness-checks) in Zerops. +_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](/ubuntu/how-to/deploy-process#readiness-checks) in Zerops. `readinessCheck` requires either one `httpGet` object or one `exec` object. @@ -6305,7 +4896,7 @@ zerops: run: ... ``` -Read more about how the [readiness check works](/dotnet/how-to/deploy-process#readiness-checks) in Zerops. +Read more about how the [readiness check works](/ubuntu/how-to/deploy-process#readiness-checks) in Zerops. #### exec @@ -6325,7 +4916,7 @@ Following attributes are available: Defines a local command to be run. - The command has access to the same [environment variables](/dotnet/how-to/create#set-secret-environment-variables) as your .NET application. + The command has access to the same [environment variables](/ubuntu/how-to/create#set-secret-environment-variables) as your Ubuntu application. A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. @@ -6354,1602 +4945,1244 @@ zerops: mv /outside/user /home/user ``` -Read more about how the [readiness check works](/dotnet/how-to/deploy-process#readiness-checks) in Zerops. +Read more about how the [readiness check works](/ubuntu/how-to/deploy-process#readiness-checks) in Zerops. ---------------------------------------- -# Dotnet > How To > Build Process +# Typesense > Overview +Zerops provides a fully managed [Typesense search engine](https://typesense.org/) service that combines developer productivity with enterprise-grade reliability. The platform handles infrastructure complexity through automated deployment, scaling, and maintenance while providing developers full access to Typesense's native capabilities. ----------------------------------------- +## Supported Versions -# Dotnet > How To > Controls +Currently supported Typesense version: +Import configuration version: +- `typesense@27.1` ----------------------------------------- +## Service Configuration -# Dotnet > How To > Create +Our Typesense implementation comes with carefully tuned defaults that diverge from the [standard Typesense configuration](https://typesense.org/docs/27.1/api/server-configuration.html#using-command-line-arguments) in the following ways: +```yaml +thread-pool-size: 16 +num-collections-parallel-load: 8 +``` -Zerops provides a .NET runtime service with extensive build support. .NET runtime is highly scalable and customisable to suit both development and production. +These defaults are optimized for most common use cases and managed by the platform. If you need to adjust these settings, please contact us through our [support channels](#support). -## Create .NET service using Zerops GUI +### Data Persistence -First, set up a project in Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu in the **Services** block. Then add a new .NET service: +Typesense data is automatically persisted to disk at `/var/lib/typesense`. -[Video: /vids/services/dotnet.webm](/vids/services/dotnet.webm) +This ensures that data remains intact during service restarts (Typesense automatically reloads the persisted data into memory upon startup). -### Choose .NET version +This persistence mechanism works in both HA and non-HA deployment modes, though with different reliability guarantees as detailed below. -Following .NET versions are currently supported: +### Deployment Modes -:::info -You can [change](/dotnet/how-to/upgrade) the major version at any time later. +:::warning +The choice between HA and non-HA mode must be made during service creation and cannot be changed later. Make sure to carefully consider your requirements before deploying. ::: -### Set a hostname +#### Non-HA Mode +- Suitable for development and testing +- Data persistence not guaranteed during node failures +- Lower resource requirements -Enter a unique service identifier like "app","cache", "gui" etc. Duplicate services with the same name in the same project are forbidden. +#### HA Mode +- Implements Typesense's native [**Raft consensus**](https://typesense.org/docs/guide/high-availability.html) mechanism for data replication +- Deploys as a **3-node cluster by default** for optimal reliability + - Scaling configuration of 3-5 or 3-7 nodes for higher workloads is possible upon request (contact [support](#support) to configure custom node ranges) +- Includes **built-in data synchronization** across all nodes +- Features **automatic leader election** to maintain cluster availability + - Recovery typically takes up to 1 minute during node failures or leader transitions + - During these periods, requests may temporarily receive `503 Not Ready or Lagging` or `500 Could not find a leader` responses + - These states automatically resolve once consensus is reestablished -#### Limitations: +### API Key Management -- maximum 25 characters -- must contain only lowercase ASCII letters (a-z) or numbers (0-9) +The master API key is automatically generated and managed by the platform. You can access it through: +- The service access details in the Zerops GUI +- The `apiKey` environment variable in your service configuration -:::caution -The hostname is fixed after the service is created. It can't be changed later. +:::warning +Currently, as a security-focused design decision, the master API key cannot be modified after generation. ::: -### Set secret environment variables - -Add environment variables with sensitive data, such as password, tokens, salts, certificates etc. These will be securely saved inside Zerops and added to your runtime service upon start. - -Setting the secret environment variables is optional. You can set them later in Zerops GUI. +### CORS Configuration -Read more about [different types of env variables](/dotnet/how-to/env-variables#service-env-variables) in Zerops. +Your Typesense instance comes with CORS enabled by default, ensuring seamless integration with frontend applications. Browser-based clients can directly access the instance by providing the `X-Typesense-Api-Key` header, maintaining security while enabling straightforward client-side implementation. -## Create .NET service using zCLI +## Network Architecture & Access Patterns -zCLI is the Zerops command-line tool. To create a new .NET service via the command-line, follow these steps: +### Access Methods -1. [Install & setup zCLI](/references/cli) -2. [Create a project description file](/dotnet/how-to/create#create-a-project-description-file) -3. [Create a project with a .NET and PostgreSQL service](#full-example) +#### HTTPS Access -### Create a project description file +When using HTTPS access (either through Zerops subdomain or custom domain), traffic is distributed across nodes via our integrated Nginx proxy layer. This provides a single access point that handles load balancing automatically. -Zerops uses a yaml format to describe the project infrastructure. +For enabling HTTPS access: +1. Configure through the [Zerops access documentation](/features/access) +2. Or use `enableSubdomainAccess: true` when [importing](/references/import#service-configuration) a Typesense service -#### Basic example: +#### Direct Node Access -Create a directory `my-project`. Create an `description.yaml` file inside the `my-project` directory with following content: +Allows to access individual nodes using internal DNS: +1. **Via [Zerops VPN](/references/networking/vpn)** +2. **Internal Project Access** - services within the same project can reach nodes directly -```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in dotnet@6 format - type: dotnet@6 - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' -``` - -The yaml file describes your future project infrastructure. The project will contain one .NET version 6 service with default [auto scaling](/dotnet/how-to/scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](/dotnet/how-to/build-pipeline#ports). Following secret env variables will be configured: - -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` +Node addressing patterns: +##### Standard format +**Format:**```node{n}.db.{hostname}.zerops``` +- e.g. `node1.db.typesenseha.zerops`, `node2.db.typesenseha.zerops` +##### Stable DNS records +**Format:**```node-stable-{n}.db.{hostname}.zerops``` +- **maintain consistent IP mapping** until node retirement (scaling down or failure events) +- e.g. `node-stable-1.db.typesenseha.zerops`, `node-stable-2.db.typesenseha.zerops` -#### Full example: +## Quick Start Example -Create a directory my-project. Create an description.yaml file inside the my-project directory with following content: +Here's a simple example of using Typesense with the JavaScript client: -```yaml -# basic project data -project: - # project name - name: my-project - # optional: project description - description: A project with a .NET and PostgreSQL database - # optional: project tags - tags: - - DEMO - - ZEROPS -# array of project services -services: - - # service name - hostname: app - # service type and version number in dotnet@6 format - type: dotnet@6 - # optional: vertical auto scaling customization - verticalAutoscaling: - cpuMode: DEDICATED - minCpu: 2 - maxCpu: 5 - minRam: 2 - maxRam: 24 - minDisk: 6 - maxDisk: 50 - startCpuCoreCount: 3 - minFreeRamGB: 0.5 - minFreeRamPercent: 20 - # defines the minimum number of containers for horizontal autoscaling. Max value = 6. - minContainers: 2 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 4 - # optional: create secret env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' - - # second service hostname - hostname: db - # service type and version number in postgresql@{version} format - type: postgresql@12 - # mode of operation "HA"/"non_HA" - mode: NON_HA -``` +```javascript -The yaml file describes your future project infrastructure. The project will contain a .NET service and a [PostgreSQL](/postgresql/overview) service. +const client = new TypesenseClient({ + nodes: [{ + host: 'your-service.zerops.dev', // Your Zerops subdomain + port: '443', + protocol: 'https' + }], + apiKey: process.env.TYPESENSE_API_KEY, + connectionTimeoutSeconds: 2 +}) -.NET service with "app" hostname, the internal port(s) the service listens on will be defined later in the [zerops.yaml](/dotnet/how-to/build-pipeline#ports). .NET service will run on version 6 with a custom vertical and horizontal scaling. Following secret env variables will be configured: +// Create a collection +await client.collections().create({ + name: 'companies', + fields: [ + { name: 'company_name', type: 'string' }, + { name: 'num_employees', type: 'int32' }, + { name: 'country', type: 'string', facet: true } + ], + default_sorting_field: 'num_employees' +}) -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" +// Example search query +const searchResults = await client.collections('companies') + .documents() + .search({ + q: 'tech', + query_by: 'company_name', + filter_by: 'country:=USA', + sort_by: 'num_employees:desc' + }) ``` -The hostname of the PostgreSQL service will be set to "db". The [single container](/features/scaling#single-container-mode)(/features/scaling#deployment-modes-databases-and-shared-storage) mode will be chosen and the default auto [scaling configuration](/postgresql/how-to/scale#configure-scaling) will be set. - -#### Description of description.yaml parameters - -The `project:` section is required. Only one project can be defined. +## Best Practices - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescriptionLimitations
nameThe name of the new project. Duplicates are allowed.
descriptionOptional. Description of the new project.Maximum 255 characters.
tagsOptional. One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects.
+#### API Key Security +- Never expose the master API key in client-side code +- Generate scoped search-only API keys for frontend applications +- Rotate API keys periodically through your service configuration -At least one service in `services:` section is required. You can create a project with multiple services. The example above contains .NET and PostgreSQL services but you can create a `description.yaml` with your own combination of [services](/features/infrastructure). +#### High Availability +- Implement retry logic in clients for handling temporary unavailability +- Use stable DNS records for direct node access when needed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
hostname - The unique service identifier. +#### Performance Optimization +- Utilize batch operations for bulk updates +- Configure appropriate timeout values based on your use case +- Consider data volume when designing collection schemas - The hostname of the new database will be set to the `hostname` value. +## Support - Limitations: -
    -
  • duplicate services with the same name in the same project are forbidden
  • -
  • maximum 25 characters
  • -
  • must contain only lowercase ASCII letters (a-z) or numbers (0-9)
  • -
-
type - Specifies the service type and version. +For advanced configurations or custom requirements: +- Join our [Discord community](https://discord.gg/zeropsio) +- Contact support via [email](mailto:support@zerops.io) - See what [.NET service types](/references/import-yaml/type-list#runtime-services) are currently supported. -
verticalAutoscaling - Optional. Defines [custom vertical auto scaling parameters](/dotnet/how-to/create#set-auto-scaling-configuration). +---------------------------------------- - All verticalAutoscaling attributes are optional. Not specified attributes will be set to their default values. -
- cpuMode - Optional. Accepts `SHARED`, `DEDICATED` values. Default is `SHARED` -
- minCpu/maxCpu - Optional. Set the minCpu or maxCpu in CPU cores (integer). -
- minRam/maxRam - Optional. Set the minRam or maxRam in GB (float). -
- minDisk/maxDisk - Optional. Set the minDisk or maxDisk in GB (float). -
minContainers - Optional. Default = 1. Defines the minimum number of containers for [horizontal autoscaling](/dotnet/how-to/create#horizontal-auto-scaling). +# Static > Overview - Limitations: - Current maximum value = 10. -
maxContainers - Defines the maximum number of containers for [horizontal autoscaling](/dotnet/how-to/create#horizontal-auto-scaling). +The Static service provides a way to serve static content through a pre-configured Nginx setup. It balances simplicity with the flexibility needed for modern web applications. - Limitations: +### Experience the simplicity of Zerops - Current maximum value = 10. -
envSecrets - Optional. Defines one or more secret env variables as a key value map. See env variable [restrictions](/dotnet/how-to/env-variables#env-variable-restrictions). -
+Deploy an Analog app with static hosting in seconds. All you need is a Zerops account. -### Create a project based on the description.yaml + [Deploy "analog" recipe on Zerops](https://app.zerops.io/recipe/?lf=analog) -When you have your `description.yaml` ready, use the `zcli project project-import` command to create a new project and the service infrastructure. +## Quick Start -```sh -Usage: - zcli project project-import importYamlPath [flags] +Add a Static service to your project by including this in your `zerops.yaml`: -Flags: - -h, --help Help for the project import command. - --org-id string If you have access to more than one organization, you must specify the org ID for which the - project is to be created. - --working-dir string Sets a custom working directory. Default working directory is the current directory. (default "./") +```yaml title="zerops.yaml" +zerops: + - setup: app + run: + os: alpine + base: static ``` -Zerops will create a project and one or more services based on the `description.yaml` content. +## Routing & Configuration -Maximum size of the `description.yaml` file is 100 kB. +### Default Behavior -You don't specify the project name in the `zcli project project-import` command, because the project name is defined in the `description.yaml`. +Every Static service in Zerops comes with built-in defaults optimized for modern web applications, including Single Page Applications. By default, for any incoming request, the service will: +1. Try to serve the exact path (`$uri`) +2. Try with .html extension (`$uri.html`) +3. Look for an index.html in the directory (`$uri/index.html`) +4. Fall back to `/index.html` (suitable for SPAs) +5. Return 404 if none of the above exist -If you have access to more than one client, you must specify the client ID for which the project is to be created. The `clientID` is located in the Zerops GUI under the client name on the project dashboard page. +:::important SPAs +Single Page Applications work out of the box without any additional configuration. The built-in fallback to `/index.html` ensures that client-side routing functions properly. +::: -### Add .NET service to an existing project +### Custom Routing Configuration -#### Example: +The Static service allows you to configure additional URL routing and redirects through simple YAML configuration, abstracting away the complexity of Nginx configuration. -Create a directory `my-project` if it doesn't exist. Create an `import.yaml` file inside the `my-project` directory with following content: +Configure custom routing beyond the default behavior in the `run.routing` section of your `zerops.yaml`: -```yaml -# basic project data -project: - # project name - name: my-project -# array of project services -services: - - # service name - hostname: app - # service type and version number in dotnet@6 format - type: dotnet@6 - # defines the minimum number of containers for horizontal autoscaling - minContainers: 1 - # defines the maximum number of containers for horizontal autoscaling. Max value = 6. - maxContainers: 6 - # optional: create env variables - envSecrets: - S3_ACCESS_KEY_ID: 'P8cX1vVVb' - S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' +```yaml title="zerops.yaml" +run: + routing: + redirects: + # Only needed for custom redirect scenarios + - from: /special-path/* + to: /specific-landing-page + status: 302 ``` -The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one .NET service version 6 with default [auto scaling](/dotnet/how-to/scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: - -```env -S3_ACCESS_KEY_ID="P8cX1vVVb" -S3_ACCESS_SECRET="ogFthuiLYki8XoL73opSCQ" -``` +### Redirects -The content of the `services:` section of `import.yaml` is identical to the project description file. The `import.yaml` never contains the `project:` section because the project already exists. +#### Relative Redirects -When you have your `import.yaml` ready, use the `zcli project service-import` command to add one or more services to your existing Zerops project. +:::note +Remember that SPA routing is already built into the default behavior. You don't need to add any custom redirects for client-side routing to work. +::: -```sh -Usage: - zcli project service-import importYamlPath [flags] +Use relative redirects to route paths within your application. When both `from` and `to` are relative paths, you can omit the `status` code to create a masked redirect that shows the content of the target page while preserving the original URL: -Flags: - -h, --help Help for the project service import command. - -P, --project-id string If you have access to more than one project, you must specify the project ID for which the - command is to be executed. -``` +```yaml title="zerops.yaml" +routing: + redirects: + # Masked redirect - URL stays the same but shows content from about-us + - from: /about + to: /about-us -zCLI commands are interactive, when you press enter after `zcli project service-import importYamlPath`, you will be given a list of your projects to choose from. + # Standard redirect with status code + - from: /old-page + to: /new-page + status: 301 -Maximum size of the import.yaml file is 100 kB. + # Preserve the path when redirecting between directories + - from: /blog/* + to: /articles/ + preservePath: true + status: 302 + # Preserve both path and query parameters + - from: /posts/* + to: /blog/ + preservePath: true + preserveQuery: true + status: 302 +``` ----------------------------------------- +:::caution Important +When using `preservePath` with wildcards, ensure the `to` path ends with a `/` to maintain proper path concatenation. For example, `/blog/*` to `/new-blog/` will correctly redirect `/blog/hello.html` to `/new-blog/hello.html`, while `/new-blog` would result in `/new-bloghello.html`. +::: -# Dotnet > How To > Customize Runtime +#### Absolute Redirects +For redirecting between domains or to external URLs, use absolute redirects by including `http://` or `https://`. When using absolute URLs in either `from` or `to`, you must specify a `status` code: +```yaml title="zerops.yaml" +routing: + redirects: + # Redirect an old domain to a new one + - from: https://old-domain.com/* + to: https://new-domain.com + status: 301 + preserveQuery: true # Optional: maintain query parameters ----------------------------------------- + # Redirect with path preservation + - from: https://old-site.com/* + to: https://new-site.com/ + status: 301 + preservePath: true +``` -# Dotnet > How To > Deploy Process +#### Wildcard Matching +Use `*` as a wildcard in your paths: +- **At the end of a path**: Matches any subsequent content +- **At the start of a domain** (after `https://`): Enables regex matching for subdomains +Example of domain management: ----------------------------------------- +```yaml title="zerops.yaml" +run: + routing: + redirects: + # Redirect a specific domain to an article + - from: https://promo-domain.com/* + to: https://main-site.com/special-offer + status: 302 -# Dotnet > How To > Env Variables + # Redirect all subdomains to main site + - from: https://*.old-domain.com/* + to: https://main-site.com + status: 302 +``` +#### Matching Priority +When multiple redirects are configured, they follow Nginx's matching priority system: ----------------------------------------- +1. Exact matches are checked first +2. Simple path matches (without wildcards) are checked next +3. Pattern matches (with wildcards) are checked last -# Dotnet > How To > Filebrowser +For example: +```yaml title="zerops.yaml" +routing: + redirects: + # Exact match for homepage - standard redirect + - from: / + to: /home + status: 302 + # Simple path match - masked redirect + - from: /about + to: /about-us ----------------------------------------- + # Pattern match with path preservation + - from: /blog/* + to: /articles/ + preservePath: true + status: 302 +``` -# Dotnet > How To > Logs +In this configuration: +- `/` will redirect to `/home` with a 302 status +- `/about` will show content from `/about-us` but keep the URL as `/about` +- `/blog/post-123.html` will redirect to `/articles/post-123.html` +- Any other path will use the [default behavior](#default-behavior) +#### Common Redirect Patterns +**Domain Migration** +```yaml title="zerops.yaml" +routing: + redirects: + - from: https://old-domain.com/* + to: https://new-domain.com + status: 301 +``` +Use permanent (301) redirects when permanently moving content to maintain SEO value. ----------------------------------------- +**Multiple Domain Management** +```yaml title="zerops.yaml" +run: + routing: + redirects: + # Product-specific domain + - from: https://product-promo.com/* + to: https://main-site.com/products + status: 302 -# Dotnet > How To > Scaling + # Campaign domain + - from: https://special-offer.com/* + to: https://main-site.com/campaign + status: 302 + # Legacy domains and subdomains + - from: https://*.legacy-domain.com/* + to: https://main-site.com + status: 302 +``` +### CORS Configuration ----------------------------------------- +You can enable CORS for your static service by adding a `cors` directive: -# Dotnet > How To > Shared Storage +```yaml title="zerops.yaml" +run: + routing: + # Simple case - automatically converted to '*' + cors: "*" + # Full syntax with proper quoting + cors: "'*' always" +``` +The `cors` directive sets the following headers: +- `Access-Control-Allow-Origin` +- `Access-Control-Allow-Methods` +- `Access-Control-Allow-Headers` +- `Access-Control-Expose-Headers` ----------------------------------------- +:::note +The `cors` directive has a special case: if you specify just `"*"`, it's automatically converted to `'*'`. For any other values, you need to include the proper Nginx syntax including quotes. +::: -# Dotnet > How To > Trigger Pipeline +### Custom Headers +For more control over HTTP headers, use the `headers` directive: +```yaml title="zerops.yaml" +run: + routing: + headers: + - for: "/" + values: + # All values need proper quoting since they're inserted directly into Nginx + X-Frame-Options: "'DENY'" ----------------------------------------- + # Values with internal quotes need proper YAML escaping + Content-Security-Policy: '"default-src ''self''"' +``` -# Dotnet > How To > Upgrade +:::important +Header values are inserted directly into the Nginx configuration **without** additional quotes, which means: +1. **All values must include their own quotes** (typically single quotes) +2. If you need single quotes inside your header value, you must escape them in YAML (using double single quotes) +3. To include the `always` directive, add it after your quoted value +4. For complex values, you can use YAML's block scalar notation (`>-`) for better readability +::: +Here are examples for different header scenarios: ----------------------------------------- - -# Dotnet > Overview - - -[.NET ↗](https://dotnet.microsoft.com/en-us/) is the free, open-source, cross-platform framework for building modern apps and powerful cloud services.. - -As said, there is no need for coding yet, we have created a [Github repository ↗](https://github.com/zeropsio/recipe-dotnet-hello-world), a **_recipe_**, containing the most simple .NET web application. The repo will be used as a source from which the app will be built. +```yaml title="zerops.yaml" +headers: + - for: "/" + values: + # Simple header with proper quoting + X-Frame-Options: "'DENY'" -### 🚀 Feel free to deploy the recipe yourself + # Header with 'always' directive + X-XSS-Protection: "'1; mode=block' always" -This is the most bare-bones example of .NET running in Zerops — as few libraries as possible, - just a simple endpoint with connect, read and write to a Zerops PostgreSQL database. + # Header with internal single quotes - need double single quotes for escaping + Content-Security-Policy: '"default-src ''self'' https://cdn.example.com"' - [Deploy "dotnet" recipe on Zerops](https://app.zerops.io/recipe/?lf=dotnet) + # Complex header with block scalar notation for better readability + Content-Security-Policy: >- + "default-src 'self' https://cdn.example.com; + script-src 'self' 'unsafe-inline'; + img-src * data:" always +``` -1. Log in/sign up to [Zerops GUI ↗](https://app.zerops.io) -2. In the **Projects** box click on **Import a project** and paste in the following YAML config ([source ↗](https://github.com/zeropsio/recipe-dotnet-hello-world/blob/main/import-project/description.yaml)): +When this configuration is processed, it translates to the following Nginx directives: -```yaml -project: - name: my-first-project -services: - - hostname: helloworld - type: dotnet@latest - minContainers: 1 - maxContainers: 3 - buildFromGit: https://github.com/zeropsio/recipe-dotnet-hello-world@main - enableSubdomainAccess: true +``` +add_header X-Frame-Options 'DENY'; +add_header X-XSS-Protection '1; mode=block' always; +add_header Content-Security-Policy "default-src 'self' https://cdn.example.com"; +add_header Content-Security-Policy "default-src 'self' https://cdn.example.com; script-src 'self' 'unsafe-inline'; img-src * data:" always; ``` -3. Click on **Import project** and wait until all pipelines have finished. +:::important Path Handling +When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same [default behavior](#default-behavior) as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). -**That's it, your application is now up and running! :star: Let's check it works:** +If you add headers for a path that already has a location block, your headers will be merged with the existing configuration. +::: -1. A _subdomain_ should have been enabled and visible in the project's **IP addressed & Public Routing Overview** box. Its format should look similar to this `https://helloworld-24-8080.prg1.zerops.app`. -2. Click or the `subdomain` URL to open it in a browser and you should see +### Combining CORS and Custom Headers -``` -Hello, World! +You can use both CORS and custom headers together: + +```yaml title="zerops.yaml" +run: + routing: + cors: "'*' always" + headers: + - for: "/" + values: + X-Frame-Options: "'DENY'" ``` -:::tip -Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. +The `cors` directive sets default Access-Control headers for all routes, while the `headers` directive allows you to set additional headers for specific paths. + +:::important +If you specify Access-Control headers in the `headers` directive, they will override the ones set by `cors` for that specific path. ::: -## How to start +## SEO with Prerender -- [Care for details?](/dotnet/how-to/create) — Dive in all Zerops has to offer for your .NET application. +Single Page Applications render content with JavaScript, which most crawlers can't process—they see an empty page instead of your content. This affects traditional search engines, social media platforms, and AI tools like ChatGPT, Perplexity, and Claude. -## Feature Highlights +The Static service includes built-in support for Prerender.io, which automatically detects crawlers and serves them pre-rendered HTML while your users get the full interactive experience. -- [Create .NET service](/dotnet/how-to/create) — Start with creating a .NET service using GUI or zCLI. -- [zerops.yaml](/dotnet/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to create your own app. -- [Scaling configuration](/dotnet/how-to/scaling) — Set up scaling of your .NET application so that it runs smoothly while using only necessary resources. +### Setup -{" "} +1. Set the `PRERENDER_TOKEN` secret variable with your Prerender.io token +2. The service automatically configures necessary rewrites based on user agents -- [Customize build environment](/dotnet/how-to/build-process#customize-build-environment) -- [Customize runtime environment](/dotnet/how-to/customize-runtime) +### Custom Prerender Host -## When in doubt, reach out +If you're using a custom Prerender host, add it to environment variables in `zerops.yaml`: -Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. +```yaml title="zerops.yaml" +run: + envVariables: + - PRERENDER_HOST=your.prerender.host +``` -In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. +:::note Default +The default host is `service.prerender.io` if not specified. +::: -Have you build something that others might find useful? Don't hesitate to share your knowledge! +## Framework Integration -- [FAQ](/dotnet/faq) — Most common questions in one place. -- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. +The Static service handles static builds from any modern framework. Here's the typical deployment pattern: -## Popular Guides +```yaml title="zerops.yaml" +zerops: + - setup: app + build: + base: nodejs@20 + buildCommands: + - npm install + - npm run build + deployFiles: + - dist/~ # Your framework's output directory + run: + base: static +``` -- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. -- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. +The key is pointing `deployFiles` to wherever your framework outputs its built files (`dist/`, `build/`, `.output/public/`, etc.). +This configuration: +1. Uses Node.js for building the application +2. Installs dependencies and builds the application +3. Deploys the resulting static files to the Static service ----------------------------------------- +You can enhance this basic setup with: +- Custom redirects for URL management +- Prerender.io integration for SEO +- Additional routing rules as needed -# Elasticsearch > Overview +For framework-specific examples, check out our [recipe collection](https://github.com/zeropsio/recipe-analog-static). +## Advanced Topics -Deploy [Elasticsearch](https://www.elastic.co/elasticsearch/) instances in Zerops with flexible scaling options, from standalone nodes to highly available clusters. +### Switching to Full Nginx -## Supported Versions +If you need more control over your Nginx configuration: -Currently supported Elasticsearch versions: +1. Go to your Static service overview in the UI +2. Click the three vertical dots in the left panel +3. Select **Need to switch to full Nginx service?** +4. Copy the generated Nginx configuration +5. Use this configuration as a starting point for a full Nginx service -Import configuration version: +:::tip +This allows you to move to a more customizable setup while maintaining your existing routing logic. +::: -- `elasticsearch@9.2` -- `elasticsearch@8.16` +### Complex Multi-Domain Setups -## Connection Details +For advanced scenarios involving multiple domains and complex routing: -- **Port**: 9200 -- **Protocol**: HTTP only -- **Internal Access**: `http://{hostname}:9200` -- **Basic auth security** - - **User**: `elastic` - - **Password**: randomly generated during service creation, find under **Access Details** in service detail +```yaml title="zerops.yaml" +run: + routing: + redirects: + # Product-specific domain + - from: https://product-promo.com/* + to: https://main-site.com/products + status: 302 -#### Example -```sh -curl -u elastic:generatedpassword http://elasticsearch:9200 + # Campaign domain + - from: https://special-offer.com/* + to: https://main-site.com/campaign + status: 302 + + # Legacy domains and subdomains + - from: https://*.legacy-domain.com/* + to: https://main-site.com + status: 302 ``` -## Configuration Options +## Complete Examples -### Plugin Management +### Development Setup -You can configure Elasticsearch plugins using a comma-separated list in your environment secrets: +Configuration for local development with CORS and API proxying: -```yaml -envSecrets: - PLUGINS: "analysis-icu,ingest-attachment" +```yaml title="zerops.yaml" +run: + routing: + # CORS with proper quoting + cors: "'*' always" + redirects: + # API requests + - from: /api/* + to: https://api.your-domain.com + status: 302 ``` -**Plugin Configuration Details:** -- Defines plugins to install at service startup -- **Format**: `plugin1,plugin2,...` -- Service automatically installs specified plugins during initialization -- Removing a plugin from this list triggers uninstallation on service restart - -### JVM Heap Allocation +### Production Setup with Security -Control the JVM heap size as a percentage of container memory: +Security-enhanced configuration for production environments: -```yaml -envSecrets: - HEAP_PERCENT: "75" +```yaml title="zerops.yaml" +run: + routing: + headers: + # Custom headers for default location + - for: "/*" + values: + X-Frame-Options: "'DENY' always" + X-Content-Type-Options: "'nosniff' always" + # Note the proper escaping of single quotes + Content-Security-Policy: '"default-src ''self''" always' ``` -**Heap Configuration Details:** -- Value represents the percentage of container memory allocated to JVM heap -- **Default**: 50% of available container memory -- **Valid range**: 1-100 -- To increase available memory, adjust the service's RAM allocation in scaling configuration +---------------------------------------- -:::note Requires Restart -Changes to HEAP_PERCENT require a service restart to take effect. -::: +# Shared Storage > Tech Details -## Backup -Elasticsearch backups are created using `elasticdump`: +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: -- **Format**: `.gz` (per index/component dump) -- **Tooling**: `elasticdump` -- **Compression**: Gzip compressed JSON data +Zerops Shared Storage is built on [SeaweedFS ↗](https://github.com/seaweedfs/seaweedfs), a distributed filesystem optimized for high-volume storage with efficient retrieval. -For backup configuration, scheduling, retention policies, and management options, see the [Zerops Backups](/features/backup) documentation. +## Architecture -### Restoring Backups +Shared Storage consists of three main components: -To restore an Elasticsearch backup: +- **Master Server**: manages metadata and coordinates volume servers +- **Volume Servers**: store the actual file data +- **Filer**: provides a POSIX-compatible interface for file operations -1. **Download** the backup file (`.gz`) from the Zerops UI -2. **Extract** the compressed files to access the JSON data -3. **Prepare** your target environment (clean existing indices or use a new instance) -4. **Restore** using either: - - **elasticdump tool**: Use the same tool that created the backup for restoration via Zerops VPN or during deployment - - **Elasticsearch API**: Import the data through REST API [calls](https://www.elastic.co/docs/deploy-manage/tools/snapshot-and-restore/restore-snapshot) +### Storage Engine Behavior -For assistance with the restoration process, contact Zerops support. +SeaweedFS stores file data in append-only volumes. Files are split into chunks, and when a file is modified, new chunks are written while the old ones remain on disk until they are reclaimed. Frequent small modifications of existing files therefore cause significant write amplification, which is one of the reasons Shared Storage is [not suitable for databases](/shared-storage/overview#use-cases). -## Example Configuration +An **automatic vacuum process** reclaims the space occupied by deleted and superseded chunks. This process is triggered when the size of deleted content exceeds 15% (reduced from the SeaweedFS default of 30%). -```yaml -services: - - hostname: elasticsearch - type: elasticsearch@8.16 - mode: HA - envSecrets: - PLUGINS: "analysis-icu,ingest-attachment" - HEAP_PERCENT: "75" -``` +## Deployment Modes -## Related Resources +Zerops provides Shared Storage in two deployment modes: -- [Elasticsearch Official Documentation](https://www.elastic.co/guide/index.html) -- [Available Elasticsearch Plugins](https://www.elastic.co/guide/en/elasticsearch/plugins/current/index.html) +### Highly Available ----------------------------------------- +Recommended for production environments where data reliability is critical. -# Elixir > How To > Build Pipeline +- **Architecture**: Two containers, each running its own filer and volume server; the master server runs on the first container +- **Data Durability**: Data and filer metadata are replicated 1:1 across both containers +- **Fault Tolerance**: + - If a node fails, an automatic repair process begins + - A new container replaces the failed one + - Data is automatically replicated to the new container (duration depends on data size) + - During master node failure, mounted directories become temporarily unavailable until the new master initializes (~30s) +### Single Container -Zerops provides a customizable build and runtime environment for your Elixir application. +Suitable for development environments or non-critical data storage. -## Add zerops.yaml to your repository +- **Architecture**: Master, volume, and filer server all located on a single container +- **Data Durability**: All data is lost if the container fails -Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: +:::warning +The deployment mode is fixed after the service is created and cannot be changed later. +::: -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: elixir@latest +## Filesystem Capabilities - # OPTIONAL. Set the operating system for the build environment. - # os: ubuntu +Shared Storage supports standard POSIX filesystem operations: - # OPTIONAL. Customise the build environment by installing additional packages - # or tools to the base build environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else +- Create, read, update, and delete files and directories +- Set permissions (with some limitations) +- File locking (per mount only, see the warning below) +- Hard and symbolic links +- Directory listing and traversal - # OPTIONAL. Build your application - buildCommands: - - mix deps.get --only prod - - mix compile - - mix release +For a complete list of supported features, see the [SeaweedFS FUSE documentation ↗](https://github.com/seaweedfs/seaweedfs/wiki/FUSE-Mount#supported-features). - # REQUIRED. Select which files / folders to deploy after - # the build has successfully finished - deployFiles: _build/prod/rel/app/ +:::caution File locks are per-mount only +File locks (`flock`, POSIX locks) are enforced only within a single container's mount. A process in another container can freely write to a file you hold locked. Do not rely on file locking for coordination between containers, and do not run [lock-dependent workloads such as databases](/shared-storage/overview#use-cases) on Shared Storage. +::: - # OPTIONAL. Which files / folders you want to cache for the next build. - # Next builds will be faster when the cache is used. - cache: node_modules +## Storage Capacity - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: elixir@latest +:::caution The 60GB data limit is independent of disk scaling +A Shared Storage service holds at most **60GB of data**, no matter how much disk the service scales to. The disk resource (up to 250GB) provides headroom for the vacuum process and filesystem metadata; raising the disk limits in autoscaling does **not** increase the amount of data you can store. - # OPTIONAL. Sets the internal port(s) your app listens on: - ports: - # port number - - port: 3000 +If you need more than 60GB, contact support. +::: - # OPTIONAL. Customise the runtime Elixir environment by installing additional - # dependencies to the base Elixir runtime environment. - # prepareCommands: - # - sudo apt-get something - # - curl something else +- Maximum storage space: 60GB (can be increased via support request) +- Maximum file size: no fixed limit through the mount (files are stored in chunks), up to the available storage space +- Maximum upload size via Filer UI: 64MB per file - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Elixir application is started. - # initCommands: - # - rm -rf ./cache +## Performance Considerations - # REQUIRED. Your Elixir application start command - start: npm start -``` +- **Latency**: higher latency compared to local storage due to the network-based distributed architecture +- **Write performance**: for write-heavy workloads, batch operations where possible +- **Small files**: minimize operations with many small files for better performance +- **Mount process memory**: the mount process runs inside each connected runtime container and consumes its memory, roughly 60MB when idle and around 150MB under higher filesystem loads; it is optimized for low RAM usage, which may trade off some performance -The top-level element is always `zerops`. +## Auto Scaling Configuration -### Setup +Zerops scales Shared Storage services automatically by raising or lowering the hardware resources of each container. -The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. -Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: +Vertical auto scaling has the following default configuration: -```yaml -zerops: - # definition for app service - - setup: app - # optional - build: ... - # optional - deploy: ... - # required - run: ... +:::note +Disk size only gives the storage engine working space; the usable data capacity stays capped at 60GB. See [Storage Capacity](#storage-capacity). +::: - # definition for api service - - setup: api - # optional - build: ... - # optional - deploy: ... - # required - run: ... -``` +For most cases, the default parameters will work without issues. If you need to limit the cost of the Shared Storage service, lower the maximal resources. Zerops will never scale above the selected maximums. -Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. +When you are experiencing problems with insufficient Shared Storage performance, increase the minimal resources. Zerops will never scale below the selected minimums. -## Build pipeline configuration +You can change the auto scaling parameters at any time. -### base -_REQUIRED._ Sets the base technology for the build environment. +---------------------------------------- -Following options are available for Elixir builds: +# Shared Storage > Overview -- `1.16` -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: elixir@latest - ... -``` +:::warning Shared Storage is deprecated +Shared Storage in its current form — a managed SeaweedFS cluster connected through the import-level `mount:` field — is deprecated. It will be replaced by a standalone SeaweedFS managed service that runtime services mount themselves with [`zsc shared-storage mount`](/references/zsc#shared-storage) in their `initCommands`. Existing Shared Storage services keep working for now, but don't build new projects on it. -

- The base build environment contains {data.alpine.default}, the selected - major version of Elixir, [Zerops command line tool](/references/cli), `npm`, `yarn`, `git` and `npx` tools. -

+For new projects, choose by workload: -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. +- A **persistent filesystem shared between services** — use [Local Storage](/local-storage/overview). It is a real local filesystem with correct locking, so it also covers the workloads Shared Storage was never safe for (SQLite and other filesystem-based databases). +- **Large or highly available data** — use [Object Storage](/object-storage/overview). ::: -If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: - - elixir@latest - prepareCommands: - - zsc add go@latest - ... -``` +Zerops **Shared Storage** is a managed disk volume that mounts as a POSIX-compatible filesystem into your runtime services. Files written by one container are immediately visible to every other container that mounts the same storage, whether they belong to the same service or to different services in the project. -See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). +Under the hood it runs [SeaweedFS ↗](https://github.com/seaweedfs/seaweedfs), a distributed filesystem optimized for high-volume storage. See [Technical details](/shared-storage/tech-details) for the architecture. -To customise your build environment use the [prepareCommands](#preparecommands) attribute. +## Quick start -:::note -Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. -::: +Add a shared storage to your project and mount it into a runtime service with a `zerops-import.yaml`: -### os +```yaml title="zerops-import.yaml" +services: + - hostname: teststorage + # type is shared-storage:{mode} + type: shared-storage:ha -_OPTIONAL._ Sets the operating system for the build environment. + - hostname: app + type: nodejs@22 + buildFromGit: https://github.com/myorg/myapp + # mount the storage into /mnt/teststorage + mount: + - teststorage +``` -Following options are available: +The storage appears in the runtime containers at `/mnt/teststorage`. See [Create shared storage](/shared-storage/how-to/create) for the GUI flow and configuration details, and [Connect & mount](/shared-storage/how-to/connect) for how the mount behaves. -- `alpine` -- `ubuntu` +## Use cases -Default value is `alpine`. +Shared Storage is a good fit for: -We are currently using following os version: +- **Configuration sharing**: deploy configuration once and share it across services (e.g. Apache Airflow configuration and DAG files shared with all worker nodes) +- **Application data**: user uploads, images, documents, and other assets shared between containers (avoid huge trees of tiny files, see [performance considerations](/shared-storage/tech-details#performance-considerations)) +- **Fallback to object storage**: applications that strictly require filesystem semantics and cannot work with [object storage](/object-storage/overview) -- {data.alpine.default} -- {data.ubuntu.default} +:::caution Not suitable for databases +Do **not** run databases on Shared Storage. This includes SQLite, Prometheus TSDB, and other filesystem-based databases. -:::caution -The os version is fixed and cannot be customised. -::: +- File locks are enforced **per mount only**: a lock held in one container does not prevent another container from writing to the same file, which leads to data corruption. +- The underlying storage engine is an append-only chunk store: every modification writes new chunks, so the frequent small writes typical for databases cause heavy write amplification. -:::note -Changing the OS setting will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache behavior. +Use [managed databases](/postgresql/overview) instead. For SQLite and other filesystem-based databases, use [Local Storage](/local-storage/overview) — a local filesystem with correct locking where these workloads are safe. For storing database *backups*, prefer [object storage](/object-storage/overview): it is cheaper and better suited for write-once files. ::: -### prepareCommands +## Deployment modes -_OPTIONAL._ Customises the build environment by installing additional dependencies or tools to the base build environment. +Choose the reliability model when you create the service. It is set through the service `type` and is **fixed for the life of the service**. -The base build environment contains: + + + + + + + + + + + + + + + + + + + + +
ModetypeWhat it is
Highly Availableshared-storage:haTwo containers with data and metadata replicated 1:1 across both, with automatic repair when a node fails. Recommended for production.
Single containershared-storage:singleOne container, so lower cost but no redundancy. All data is lost if the container fails. Good for development and non-critical data.
-- {data.alpine.default} -- selected version of Elixir defined in the [base](#base) attribute -- [Zerops command line tool](/references/cli) -- `npm`, `yarn`, `git` and `npx` tools +## Key limits -To install additional packages or tools add one or more prepare commands: +- The storage holds at most **60GB of data**, regardless of the disk resource in autoscaling. See [storage capacity](/shared-storage/tech-details#storage-capacity). +- File locks work **only within a single container's mount**, not across containers. See [filesystem capabilities](/shared-storage/tech-details#filesystem-capabilities). +- The mount is available only in runtime containers, not during build and prepare phases. -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: elixir@latest +## Next steps - # OPTIONAL. Customise the build environment by installing additional packages - # or tools to the base build environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +- [Create shared storage](/shared-storage/how-to/create) — Create a service in the GUI or with zerops-import.yaml. +- [Connect & mount](/shared-storage/how-to/connect) — Connect runtime services and understand how the mount behaves. +- [Manage & backups](/shared-storage/how-to/manage) — Web interfaces, monitoring, backups, and restore. +- [Technical details](/shared-storage/tech-details) — Architecture, storage engine behavior, limits, and autoscaling. -When the first build is triggered, Zerops will +## Need help? -1. create a build container -2. download your application code from your repository -3. run the prepare commands in the defined order +Stuck, or want to share what you built? Our core team and community are on Discord. -The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. +- [Discord](https://discord.com/invite/WDvCZ54) — Join the Zerops community on Discord. Ask questions and share your tips. +- [zCLI](/references/cli) — Get more out of Zerops with the command-line tool. -:::note -These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. + +---------------------------------------- + +# Shared Storage > How To > Manage + + +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. ::: -#### Command exit code +Zerops Shared Storage provides several web interfaces to manage, monitor, and troubleshoot your storage, and automated encrypted backups of your data. -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/elixir/how-to/logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. +## Web interfaces -#### Single or separated shell instances +The web interfaces are accessible through the [Zerops VPN](/references/networking/vpn). -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +### Filer UI -### buildCommands +* `http://.zerops:8888` -_OPTIONAL._ Defines build commands. +A web-based interface for managing files and directories: +- Browse the directory structure and create new directories +- Upload new files (up to 64MB per file) and download existing files +- Rename and delete files and directories -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Set the base technology for the build environment: - base: elixir@latest +### Master UI - # OPTIONAL. Build your application - buildCommands: - - npm i - - npm run build - ... -``` +* `http://node-stable-1.db..zerops:9333` -Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. +System status and monitoring information: +- View cluster topology +- Monitor volume servers +- Check system status and health +- View statistics and metrics -Before the build commands are triggered the build container contains: +### Volume UI -1. base environment defined by the [base](#base) attribute -2. optional customisation of the base environment defined in the [prepareCommands](#preparecommands) attribute -3. your application code +* `http://node-stable-.db..zerops:8080/ui/index.html` -#### Run build commands as a single shell instance +Monitoring of individual storage volumes: +- View volume status +- Check disk usage +- Monitor I/O operations +- View volume statistics -Use following syntax to run all commands in the same environment context. For example, if one command changes the current directory, the next command continues in that directory. When one command creates an environment variable, the next command can access it. +## Monitoring -```yaml -buildCommands: - - | - npm i - npm run build -``` +Several options are available to help you monitor your Shared Storage: -#### Run build commands as a separate shell instances +- **Runtime service logs**: navigate to your runtime service detail page, open the **Runtime Logs** section, and filter using the tag `zerops-mount-` (standard output and error of the mount process) +- **Shared Storage logs**: access from the Shared Storage service detail page, **Runtime Logs** tab +- **System and volume status**: monitor replication status, disk usage, and performance metrics through the Master UI and Volume UI -When the following syntax is used, each command is triggered in a separate environment context. For example, each shell instance starts in the home directory again. When one command creates an environment variable, it won't be available for the next command. +## Backups -```yaml -buildCommands: - - npm i - - npm run build -``` +Zerops provides automated data backup for Shared Storage services with full encryption. -#### Command exit code +For general backup information including configuration, scheduling, retention, tagging, quotas, and CLI tools, see the [Zerops Backups](/features/backup) documentation. -If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/elixir/how-to/logs#build-log) to troubleshoot the error. If the error log doesn't contain any specific error message, try to run your build with the --verbose option. +### Backup format -```yaml -buildCommands: - - npm i --verbose - - npm run build -``` +Shared Storage backups are created using tar archival: -If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `buildCommands` are finished, the application build is completed and ready for the deploy phase. +- **Format**: `.tar.gz` (archive of the directory contents) +- **Content**: the entire shared volume (`/mnt/`) +- **Storage**: encrypted and stored in isolated object storage -### deployFiles +### Restoring backups -_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. +To restore a Shared Storage backup: -```yaml -# REQUIRED. Select which files / folders to deploy after -# the build has successfully finished -deployFiles: - - dist - - package.json - - node_modules +1. Download the backup file (`.tar.gz`) from the Zerops UI. +2. Transfer the archive into a runtime service that has the shared storage [connected](/shared-storage/how-to/connect), for example over the [Zerops VPN](/references/networking/vpn). +3. Extract the archive into the mount directory from within the runtime container: + +```sh +tar -xzf backup.tar.gz -C /mnt/ ``` -Determines files or folders produced by your build, which should be deployed to your runtime service containers. +:::note +Do not restore by uploading files through the Filer UI. Uploads there are limited to 64MB per file, so extracting the archive directly into the mounted directory is the reliable path. +::: -The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. +### Best practices -The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. +- Regularly clean up unnecessary files from your Shared Storage to reduce backup size +- Create manual backups with protected tags before major file operations or migrations +- Test your restore process periodically to ensure data integrity -#### Examples -Deploys a folder, and a file from the project root directory: +---------------------------------------- -```yaml -deployFiles: - - dist - - package.json -``` +# Shared Storage > How To > Create -Deploys the whole content of the build container: -```yaml -deployFiles: . -``` +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: -Deploys a folder, and a file in a defined path: +## Create Using Zerops GUI -```yaml -deployFiles: - - ./path/to/file.txt - - ./path/to/dir/ -``` +Go to your project dashboard and choose **Add new service** in the left menu in the **Services** block. Then add a new Shared Storage service: -#### How to use a wildcard in the path +[Video: /vids/services/shared-storage.webm](/vids/services/shared-storage.webm) -Zerops supports the `~` character as a wildcard for one or more folders in the path. +### Set a Hostname -Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` +Enter a unique service identifier like "storage", "files" etc. -```yaml -deployFiles: ./path/~/to/file.txt -``` +- Maximum 25 characters +- Must contain only lowercase ASCII letters (a-z) or numbers (0-9) +- Must be unique within the project -Deploys all folders that are located in any path that begins with `/path/to/` +:::note +The hostname is fixed after the service is created. It can't be changed later. +::: -```yaml -deployFiles: ./path/to/~/ -``` +### Connect to Services -Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` +Select one or more of the project's runtime services in the **Share with Services** block: -```yaml -deployFiles: ./path/~/to/ -``` +Runtime services can be [connected and disconnected](/shared-storage/how-to/connect) at any time, even after the shared storage is created. -:::note Example -By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` +### Choose Deployment Mode + +Choose between **Highly Available** (recommended for production) and **Single Container** (suitable for development). See the [mode comparison](/shared-storage/overview#deployment-modes) and [technical details](/shared-storage/tech-details#deployment-modes). + +:::warning +The deployment mode is fixed after the service is created. It can't be changed later. ::: -#### .deployignore -Add a `.deployignore` file to the root of your project to specify which files and folders Zerops should ignore during deploy. The syntax follows the same pattern format as [`.gitignore`](https://git-scm.com/docs/gitignore#_pattern_format). +### Set Auto Scaling Configuration -To ignore a specific file or directory path, start the pattern with a forward slash (`/`). Without the leading slash, the pattern will match files with that name in any directory. +Configure vertical auto scaling parameters to control resource allocation and costs: -:::tip -For consistency, it's recommended to configure both your `.gitignore` and `.deployignore` files with the same patterns. +:::note +Raising the disk limits does not raise the usable data capacity, which is capped at 60GB. See [Storage Capacity](/shared-storage/tech-details#storage-capacity) and [Auto Scaling Configuration](/shared-storage/tech-details#auto-scaling-configuration). ::: -Examples: +## Create Using Import YAML -```yaml title="zerops.yaml" -zerops: - - setup: app - build: - deployFiles: ./ -``` +The deployment mode is part of the service type: -```text title=".deployignore" -/src/file.txt -``` -The example above ignores `file.txt` only in the root src directory. -```text title=".deployignore" -src/file.txt +```yaml title="zerops-import.yaml" +services: + - # Shared storage service in highly available mode + hostname: teststorage + type: shared-storage:ha ``` -This example above ignores `file.txt` in ANY directory named `src`, such as: -- `/src/file.txt` -- `/folder2/folder3/src/file.txt` -- `/src/src/file.txt` + +Use `shared-storage:single` for the single container mode. :::note -`.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. +You can also pin the underlying engine version directly with `seaweedfs:ha@3` or `seaweedfs:single@3`. ::: -### cache - -_OPTIONAL._ Defines which files or folders will be cached for the next build. +Import the file with the [zCLI](/references/cli): -```yaml -# OPTIONAL. Which files / folders you want to cache for the next build. -# Next builds will be faster when the cache is used. -cache: file.txt +```sh +zcli project service-import zerops-import.yaml ``` -The cache attribute helps optimize build times by preserving specified files between builds. +To mount the storage into a runtime service in the same import, add the `mount:` parameter to the runtime service. See the [import reference](/references/import#service-mount-shared-storage) for details and requirements. -The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). +### Runtime-Specific Guides -Learn more about the [build cache system](/features/build-cache) in Zerops. +export const languages = [ + { name: "Node.js", link: "/nodejs/how-to/shared-storage#create-nodejs-service-with-a-shared-storage-using-zcli" }, + { name: "PHP", link: "/php/how-to/shared-storage#create-php-service-with-a-shared-storage-using-zcli" }, + { name: "Python", link: "/python/how-to/shared-storage#create-python-service-with-a-shared-storage-using-zcli" }, + { name: "Go", link: "/go/how-to/shared-storage#create-go-service-with-a-shared-storage-using-zcli" }, + { name: ".NET", link: "/dotnet/how-to/shared-storage#create-dotnet-service-with-a-shared-storage-using-zcli" }, + { name: "Rust", link: "/rust/how-to/shared-storage#create-rust-service-with-a-shared-storage-using-zcli" } +] -### envVariables -_OPTIONAL._ Defines the environment variables for the build environment. +---------------------------------------- -Enter one or more env variables in following format: +# Shared Storage > How To > Connect -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to build your application ==== - build: - base: elixir@latest - … - # OPTIONAL. Defines the env variables for the build environment: - envVariables: - NODE_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` +:::warning Deprecated +Shared Storage is [deprecated](/shared-storage/overview). For new projects, use [Local Storage](/local-storage/overview) or [Object Storage](/object-storage/overview) instead. +::: -Read more about [environment variables](/elixir/how-to/env-variables) in Zerops. +This page covers how to connect an existing shared storage to runtime services, how to disconnect it, and how the mount behaves inside your containers. -## Runtime configuration +## How the mount behaves -### base +Once a shared storage is connected to a runtime service, Zerops mounts it at `/mnt/` in the runtime containers. For example, `/mnt/teststorage` for a `teststorage` shared storage: -_OPTIONAL._ Sets the base technology for the runtime environment. -If you don't specify the `run.base` attribute, Zerops keeps the current Elixir version for your runtime. +- The content is shared among **all containers** of the connected runtime service; if you connect multiple runtime services, they all see the same content +- Multiple storages can be mounted to a single service (e.g. `/mnt/files1`, `/mnt/files2`) +- The mount point is owned by the `zerops` user and group (no sudo required) +- Mounting removes any existing content of the mount directory +- The mount is only available in runtime containers, not during build and prepare runtime phases +- The mount process logs its standard output and error to the runtime service logs (tagged `zerops-mount-`); individual file operations are not logged -Following options are available for Elixir builds: +:::note +The `df` command may show incorrect or misleading information for shared storage mounts. Refer to the Zerops GUI for accurate storage metrics. +::: -- `1.16` +## Connect in Zerops GUI -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: elixir@latest - ... +When creating a new shared storage service, you can directly select which runtime services it should be connected to. See [Create shared storage](/shared-storage/how-to/create) for the creation process. - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: elixir@latest - ... -``` +For existing storage, go to the shared storage service detail page and select **Shared storage connections**. Toggle ON any runtime services you wish to connect to this storage. -

- The base runtime environment contains {data.alpine.default}, the - selected major version of Elixir, Zerops command line tool, `npm`, `yarn`, `git` and `npx` tools. -

+To disconnect storage, toggle OFF the desired runtime service in the same place. -:::info -You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. +:::note +Connecting and disconnecting a shared storage is applied live; the runtime containers are not restarted. ::: -If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - # REQUIRED. Sets the base technology for the build environment: - base: elixir@latest - ... +## Mount and unmount using zsc - # ==== how to run your application ==== - run: - # OPTIONAL. Sets the base technology for the runtime environment: - base: - - elixir@latest - prepareCommands: - - zsc add go@latest - ... -``` +You can also mount and unmount a shared storage from within a runtime container using the `zsc` command: -See the full list of supported [run base environments](/zerops-yaml/base-list). +```sh +# Mount a shared storage +zsc shared-storage mount -To customise your build environment use the `prepareCommands` attribute. +# Unmount a shared storage +zsc shared-storage unmount -### os +# Wait until the storage mount is ready +zsc shared-storage wait +``` -_OPTIONAL._ Sets the operating system for the runtime environment. +Run these commands from your runtime container via web terminal or SSH, or as part of your `zerops.yaml` commands. For more details, see the [zsc reference](/references/zsc#shared-storage). -Following options are available: +:::caution +The shared storage must be mounted (through the GUI connection toggle or via `zsc shared-storage mount`) before your application can access the `/mnt/` directory. -- `alpine` -- `ubuntu` +Before stopping or deleting a shared storage service, you must first disconnect (unmount) it from all runtime services. +::: -Default value is `alpine`. -We are currently using following os version: +---------------------------------------- -- {data.alpine.default} -- {data.ubuntu.default} +# Rust > Overview -:::caution -The os version is fixed and cannot be customised. -::: -### ports +[Rust ↗](https://www.rust-lang.org/) - a language empowering everyone to build reliable and efficient software. -_OPTIONAL._ Specifies one or more internal ports on which your application will listen. +As said, there is no need for coding yet, we have created a [Github repository ↗](https://github.com/zeropsio/recipe-rust-hello-world), a **_recipe_**, containing the most simple Rust web application. The repo will be used as a source from which the app will be built. -Projects in Zerops represent a group of one or more services. Services can be of different types (runtime services, databases, message brokers, object storage, etc.). All services of the same project share a **dedicated private network**. To connect to a service within the same project, just use the service hostname and its internal port. +### 🚀 Feel free to deploy the recipe yourself -For example, to connect to a Elixir service with hostname = "app" and port = 3000 from another service of the same project, simply use `app:3000`. Read more about [how to access a Elixir service](/references/networking/internal-access#basic-service-communication). +This is the most bare-bones example of Rust running in Zerops — as few libraries as possible, + just a simple endpoint with connect, read and write to a Zerops PostgreSQL database. -Each port has following attributes: + [Deploy "rust" recipe on Zerops](https://app.zerops.io/recipe/?lf=rust) -| parameter | description | -| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| port | Defines the port number. You can set any port number between _10_ and _65435_. Ports outside this interval are reserved for internal Zerops systems. | -| protocol | **Optional.** Defines the protocol. Allowed values are `TCP` or `UDP`. Default value is `TCP`. | -| httpSupport | **Optional.** `httpSupport = true` is the default setting for TCP protocol. Set `httpSupport = false` if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). `httpSupport = true` is available only in combination with the TCP protocol. | -| httpSupport | **Optional.** `httpSupport = true` is the default setting for TCP protocol. Set `httpSupport = false` if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). `httpSupport = true` is available only in combination with the TCP protocol. | +1. Log in/sign up to [Zerops GUI ↗](https://app.zerops.io) +2. In the **Projects** box click on **Import a project** and paste in the following YAML config ([source ↗](https://github.com/zeropsio/recipe-rust-hello-world/blob/main/import-project/description.yaml)): -### prepareCommands +```yaml +project: + name: my-first-project +services: + - hostname: helloworld + type: rust@latest + minContainers: 1 + maxContainers: 3 + buildFromGit: https://github.com/zeropsio/recipe-rust-hello-world@main + enableSubdomainAccess: true +``` -_OPTIONAL._ Customises the Elixir runtime environment by installing additional dependencies or tools to the runtime base environment. +3. Click on **Import project** and wait until all pipelines have finished. -

- The base Elixir environment contains {data.alpine.default} the selected - major version of Elixir, [Zerops command line tool](/references/cli) and `npm`, `yarn`, `git` and `npx` tools. To install - additional packages or tools add one or more prepare commands: -

+**That's it, your application is now up and running! :star: Let's check it works:** -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... +1. A _subdomain_ should have been enabled and visible in the project's **IP addressed & Public Routing Overview** box. Its format should look similar to this `https://helloworld-24-8080.prg1.zerops.app`. +2. Click or the `subdomain` URL to open it in a browser and you should see - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Elixir runtime environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... +``` +Hello, World! ``` -When the first deploy with a defined prepare attribute is triggered, Zerops will +:::tip +Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. +::: -1. create a prepare runtime container -2. optionally: [copy selected folders or files from your build container](#copy-folders-or-files-from-your-build-container) -3. run the `prepareCommands` commands in the defined order +## How to start -:::note -`run.prepareCommands` run in the `/home/zerops` directory. -::: +- [Care for details?](/rust/how-to/create) — Dive in all Zerops has to offer for your Rust application. -#### Command exit code +## Feature Highlights -If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](/elixir/how-to/logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. +- [Create Rust service](/rust/how-to/create) — Start with creating a Rust service using GUI or zCLI. +- [zerops.yaml](/rust/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to create your own app. +- [Scaling configuration](/rust/how-to/scaling) — Set up scaling of your Rust application so that it runs smoothly while using only necessary resources. -#### Cache of your custom runtime environment +{" "} -Some packages or tools can take a long time to install. Therefore, Zerops caches your custom runtime environment after the installation of your custom packages or tools is completed. When the second or following deploy is triggered, Zerops will use the custom runtime cache from the previous deploy if following conditions are met: +- [Customize build environment](/rust/how-to/build-process#customize-build-environment) +- [Customize runtime environment](/rust/how-to/customize-runtime) -1. Content of the [build.addToRunPrepare](#copy-folders-or-files-from-your-build-container) and `run.prepareCommands` attributes didn't change from the previous deploy -2. The custom runtime cache wasn't invalidated in the Zerops GUI. +## When in doubt, reach out -To invalidate the custom runtime cache go to `yyy` +Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. -When the custom runtime cache is used, Zerops doesn't create a prepare runtime container and executes the deployment of your application directly. +In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. -#### Single or separated shell instances +Have you build something that others might find useful? Don't hesitate to share your knowledge! -You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). +- [FAQ](/rust/faq) — Most common questions in one place. +- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. -### Copy folders or files from your build container +## Popular Guides -

- The prepare runtime container contains {data.alpine.default}, the - selected major version of Elixir, [Zerops command line tool](/references/cli) and `npm`, `yarn`, `git` and `npx` tools. -

+- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. +- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. -The prepare runtime container does not contain your application code nor the built application. If you need to copy some folders or files from the build container to the runtime container (e.g. a configuration file) use the `addToRunPrepare` attribute in the [build section](#build-pipeline-configuration). -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: - ... - addToRunPrepare: ./runtime-config.yaml +---------------------------------------- - # ==== how to run your application ==== - run: - # OPTIONAL. Customise the runtime environment by installing additional packages - # or tools to the base Elixir runtime environment. - prepareCommands: - - sudo apt-get something - - curl something else - ... -``` +# Rust > How To > Upgrade -In the example above Zerops will copy the `runtime-config.yaml` file from your build container **after the build has finished** into the new **prepare runtime** container. The copied files and folders will be available in the `/home/zerops` folder in the new prepare runtime container before the prepare commands are triggered. -### initCommands -_OPTIONAL._ Defines one or more commands to be run each time a new runtime container is started or a container is restarted. +---------------------------------------- -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # OPTIONAL. Run one or more commands each time a new runtime container - # is started or restarted. These commands are triggered before - # your Elixir application is started. - initCommands: - - rm -rf ./cache -``` - -These commands are triggered in the runtime container before your Elixir application is started via the [start command](#start). - -:::note -`run.initCommands` run in the `/var/www` directory. -::: - -Use init commands to clean or initialise your application cache or similar operations. - -:::caution -The init commands will delay the start of your application each time a new runtime container is started (including the horizontal [scaling](/elixir/how-to/scaling) or when a runtime container is restarted). - -Do not use the init commands for customising your runtime environment. Use the [run:prepareCommands](#preparecommands-1) attribute instead. -::: - -#### Command exit code - -If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](/elixir/how-to/logs#runtime-log) to troubleshoot the error. - -#### Single or separated shell instances - -You can configure your `initCommands` to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). - -### envVariables - -_OPTIONAL._ Defines the environment variables for the runtime environment. - -Enter one or more env variables in following format: - -```yaml -zerops: - # define hostname of your service - - setup: app - # ==== how to run your application ==== - run: - # OPTIONAL. Defines the env variables for the runtime environment: - envVariables: - NODE_ENV: production - DB_NAME: db - DB_HOST: db - DB_USER: db - DB_PASS: ${db_password} -``` - -Read more about [environment variables](/elixir/how-to/env-variables) in Zerops. - -### start - -_REQUIRED._ Defines the start command for your Elixir application. - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # REQUIRED. Your Elixir application start command - start: npm start -``` - -We recommend starting your Elixir application using `npm start`. - -### health check - -_OPTIONAL._ Defines a health check. - -`healthCheck` requires either one `httpGet` object or one `exec` object. - -#### httpGet - -Configures the health check to request a local URL using a HTTP GET method. - -Following attributes are available: - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
- -**Example:** - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # REQUIRED. Your Elixir application start command - start: npm start - - # OPTIONAL. Define a health check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - healthCheck: - httpGet: - port: 80 - path: /status -``` - -#### exec - -Configures the health check to run a local command. -Following attributes are available: - -| Parameter | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **command** | Defines a local command to be run. -The command has access to the same [environment variables](/elixir/how-to/create#set-secret-environment-variables) as your Elixir application. -A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. | - -**Example:** - -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... - - # ==== how to run your application ==== - run: - # REQUIRED. Your Elixir application start command - start: npm start - - # OPTIONAL. Define a health check with a shell command. - healthCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user -``` - -### crontab - -_OPTIONAL._ Defines cron jobs. - -Setup cron jobs in the following format: - -```yaml -zerops: - # define hostname of your service - - setup: app - - # ==== how to run your application ==== - run: - crontab: - # REQUIRED. Sets the command to execute: - - command: "" - # REQUIRED. Sets the interval time to execute: - timing: "0 * * * *" -``` +# Rust > How To > Trigger Pipeline -Read more about setting up [cron](/zerops-yaml/cron) in Zerops. -## Deploy configuration -### readiness check +---------------------------------------- -_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](/elixir/how-to/deploy-process#readiness-checks) in Zerops. +# Rust > How To > Shared Storage -`readinessCheck` requires either one `httpGet` object or one `exec` object. -#### httpGet -Configures the readiness check to request a local URL using a http GET method. +---------------------------------------- -Following attributes are available: +# Rust > How To > Scaling - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
portDefines the port of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. -The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. -If your application requires a https request, set scheme: https
-**Example:** -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +---------------------------------------- - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - httpGet: - port: 80 - path: /status +# Rust > How To > Logs - # ==== how to run your application ==== - run: ... -``` -Read more about how the [readiness check works](/elixir/how-to/deploy-process#readiness-checks) in Zerops. -#### exec +---------------------------------------- -Configures the readiness check to run a local command. -Following attributes are available: +# Rust > How To > Filebrowser -| Parameter | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **command** | Defines a local command to be run. -The command has access to the same [environment variables](/elixir/how-to/create#set-secret-environment-variables) as your Elixir application. -A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. | -**Example:** -```yaml -zerops: - # hostname of your service - - setup: app - # ==== how to build your application ==== - build: ... +---------------------------------------- - # ==== how to deploy your application ==== - deploy: - # OPTIONAL. Define a readiness check with a HTTP GET request option. - # Configures the check on http://127.0.0.1:80/status - readinessCheck: - exec: - command: | - touch grass - rm -rf life - mv /outside/user /home/user -``` +# Rust > How To > Env Variables -Read more about how the [readiness check works](/elixir/how-to/deploy-process#readiness-checks) in Zerops. ---------------------------------------- -# Elixir > How To > Build Process +# Rust > How To > Deploy Process ---------------------------------------- -# Elixir > How To > Controls +# Rust > How To > Customize Runtime ---------------------------------------- -# Elixir > How To > Create +# Rust > How To > Create -Zerops provides a powerful Elixir runtime service with extensive build support. The Elixir runtime is highly scalable and customizable to suit your development and production needs. With just a few clicks or commands, you can have a production-ready Elixir environment up and running in no time. +Zerops provides a Rust runtime service with extensive build support. Rust runtime is highly scalable and customisable to suit both development and production. -## Create a Elixir service using Zerops GUI +## Create Rust service using Zerops GUI -First, set up a project in the Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu under the **Services** section. From there, you can add a new Elixir service: +First, set up a project in Zerops GUI. Then go to the project dashboard page and choose **Add new service** in the left menu in the **Services** block. Then add a new Rust service: -[Video: /vids/services/elixir.webm](/vids/services/elixir.webm) +[Video: /vids/services/rust.webm](/vids/services/rust.webm) -### Choose a Elixir version +### Choose Rust version -Zerops supports the following Elixir versions: +Following Rust versions are currently supported: :::info -You can easily [upgrade](/elixir/how-to/upgrade) the major version at any time later. +You can [change](/rust/how-to/upgrade) the major version at any time later. ::: ### Set a hostname -Enter a unique service identifier like "app", "cache", "gui", etc. Duplicate services with the same name within the same project are not allowed. +Enter a unique service identifier like "app","cache", "gui" etc. Duplicate services with the same name in the same project are forbidden. #### Limitations: -- Maximum 25 characters -- Must contain only lowercase ASCII letters (a-z) or numbers (0-9) +- maximum 25 characters +- must contain only lowercase ASCII letters (a-z) or numbers (0-9) :::caution -The hostname is fixed after the service is created and cannot be changed later. +The hostname is fixed after the service is created. It can't be changed later. ::: ### Set secret environment variables -Add environment variables with sensitive data, such as passwords, tokens, salts, certificates, etc. These will be securely saved inside Zerops and added to your runtime service upon start. +Add environment variables with sensitive data, such as password, tokens, salts, certificates etc. These will be securely saved inside Zerops and added to your runtime service upon start. -Setting secret environment variables is optional. You can always set them later in the Zerops GUI. +Setting the secret environment variables is optional. You can set them later in Zerops GUI. -Read more about the [different types of environment variables](/elixir/how-to/env-variables#service-env-variables) in Zerops. +Read more about [different types of env variables](/rust/how-to/env-variables#service-env-variables) in Zerops. -## Create a Elixir service using zCLI +## Create Rust service using zCLI -zCLI is the Zerops command-line tool. To create a new Elixir service via the command line, follow these steps: +zCLI is the Zerops command-line tool. To create a new Rust service via the command-line, follow these steps: 1. [Install & setup zCLI](/references/cli) -2. [Create a project description file](/elixir/how-to/create#create-a-project-description-file) -3. [Create a project with a Elixir and PostgreSQL service](#full-example) +2. [Create a project description file](/rust/how-to/create#create-a-project-description-file) +3. [Create a project with a Rust and PostgreSQL service](#full-example) ### Create a project description file -Zerops uses a YAML format to describe the project infrastructure. +Zerops uses a yaml format to describe the project infrastructure. #### Basic example: -Create a directory called `my-project`. Inside the `my-project` directory, create a `description.yaml` file with the following content: +Create a directory `my-project`. Create an `description.yaml` file inside the `my-project` directory with following content: + ```yaml # basic project data project: @@ -7959,8 +6192,8 @@ project: services: - # service name hostname: app - # service type and version number in elixir@{version} format - type: elixir@latest + # service type and version number in rust@{version} format + type: rust@latest # defines the minimum number of containers for horizontal autoscaling minContainers: 1 # defines the maximum number of containers for horizontal autoscaling. Max value = 6. @@ -7971,7 +6204,7 @@ services: S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' ``` -The yaml file describes your future project infrastructure. The project will contain one Elixir version 20 service with default [auto scaling](/elixir/how-to/scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](/elixir/how-to/build-pipeline#ports). Following secret env variables will be configured: +The yaml file describes your future project infrastructure. The project will contain one Rust version 18 service with default [auto scaling](/rust/how-to/scaling) configuration. Hostname will be set to "app", the internal port(s) the service listens on will be defined later in the [zerops.yaml](/rust/how-to/build-pipeline#ports). Following secret env variables will be configured: ```env S3_ACCESS_KEY_ID="P8cX1vVVb" @@ -7988,7 +6221,7 @@ project: # project name name: my-project # optional: project description - description: A project with a Elixir and PostgreSQL database + description: A project with a Rust and PostgreSQL database # optional: project tags tags: - DEMO @@ -7997,8 +6230,8 @@ project: services: - # service name hostname: app - # service type and version number in elixir@{version} format - type: elixir@latest + # service type and version number in rust@{version} format + type: rust@latest # optional: vertical auto scaling customization verticalAutoscaling: cpuMode: DEDICATED @@ -8015,7 +6248,7 @@ services: minContainers: 2 # defines the maximum number of containers for horizontal autoscaling. Max value = 6. maxContainers: 4 - # optional: create env variables + # optional: create secret env variables envSecrets: S3_ACCESS_KEY_ID: 'P8cX1vVVb' S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' @@ -8027,9 +6260,9 @@ services: mode: NON_HA ``` -The yaml file describes your future project infrastructure. The project will contain a Elixir service and a [PostgreSQL](/postgresql/overview) service. +The yaml file describes your future project infrastructure. The project will contain a Rust service and a [PostgreSQL](/postgresql/overview) service. -Elixir service with "app" hostname, the internal port(s) the service listens on will be defined later in the [zerops.yaml](/elixir/how-to/build-pipeline#ports). Elixir service will run on version 20 with a custom vertical and horizontal scaling. Following secret env variables will be configured: +Rust service with "app" hostname, the internal port(s) the service listens on will be defined later in the [zerops.yaml](/rust/how-to/build-pipeline#ports). Rust service will run on version 18 with a custom vertical and horizontal scaling. Following secret env variables will be configured: ```env S3_ACCESS_KEY_ID="P8cX1vVVb" @@ -8042,14 +6275,34 @@ The hostname of the PostgreSQL service will be set to "db". The [single containe The `project:` section is required. Only one project can be defined. -| Parameter | Description | Limitations | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -| **name** | The name of the new project. Duplicates are allowed. | | -| **description** | **Optional.** Description of the new project. | Maximum 255 characters. | -| **tags** | **Optional.** One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects. | -| **tags** | **Optional.** One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects. | + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescriptionLimitations
nameThe name of the new project. Duplicates are allowed.
descriptionOptional. Description of the new project.Maximum 255 characters.
tagsOptional. One or more string tags. Tags do not have a functional meaning, they only provide better orientation in projects.
-At least one service in `services:` section is required. You can create a project with multiple services. The example above contains Elixir and PostgreSQL services but you can create a `description.yaml` with your own combination of [services](/features/infrastructure). +At least one service in `services:` section is required. You can create a project with multiple services. The example above contains Rust and PostgreSQL services but you can create a `description.yaml` with your own combination of [services](/features/infrastructure). @@ -8079,7 +6332,7 @@ At least one service in `services:` section is required. You can create a projec @@ -8087,7 +6340,7 @@ At least one service in `services:` section is required. You can create a projec verticalAutoscaling @@ -8185,7 +6438,7 @@ You don't specify the project name in the `zcli project project-import` command, If you have access to more than one client, you must specify the client ID for which the project is to be created. The `clientID` is located in the Zerops GUI under the client name on the project dashboard page. -### Add Elixir service to an existing project +### Add Rust service to an existing project #### Example: @@ -8200,8 +6453,8 @@ project: services: - # service name hostname: app - # service type and version number in elixir@{version} format - type: elixir@latest + # service type and version number in rust@{version} format + type: rust@latest # defines the minimum number of containers for horizontal autoscaling minContainers: 1 # defines the maximum number of containers for horizontal autoscaling. Max value = 6. @@ -8212,7 +6465,7 @@ services: S3_ACCESS_SECRET: 'ogFthuiLYki8XoL73opSCQ' ``` -The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one Elixir service version 20 with default [auto scaling](/elixir/how-to/scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: +The yaml file describes the list of one or more services that you want to add to your existing project. In the example above, one Rust service version 18 with default [auto scaling](/rust/how-to/scaling) configuration will be added to your project. Hostname of the new service will be set to `app`. Following secret env variables will be configured: ```env S3_ACCESS_KEY_ID="P8cX1vVVb" @@ -8240,8988 +6493,10194 @@ Maximum size of the import.yaml file is 100 kB. ---------------------------------------- -# Elixir > How To > Customize Runtime +# Rust > How To > Controls ---------------------------------------- -# Elixir > How To > Deploy Process +# Rust > How To > Build Process ---------------------------------------- -# Elixir > How To > Env Variables - - - ----------------------------------------- +# Rust > How To > Build Pipeline -# Elixir > How To > Filebrowser +Zerops provides a customizable build and runtime environment for your Rust application. +## Add zerops.yaml to your repository ----------------------------------------- +Start by adding `zerops.yaml` file to the **root of your repository** and modify it to fit your application: -# Elixir > How To > Logs +```yaml +zerops: + # define hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Set the base technology for the build environment: + base: rust@latest + # OPTIONAL. Set the operating system for the build environment. + # os: ubuntu + # OPTIONAL. Customize the build environment by installing additional packages + # or tools to the base build environment. + # prepareCommands: + # - sudo apt-get something + # - curl something else ----------------------------------------- + # OPTIONAL. Build your application + buildCommands: + - cargo b --release -# Elixir > How To > Scaling + # REQUIRED. Select which files / folders to deploy after + # the build has successfully finished + deployFiles: + - target/release/~app + # OPTIONAL. Which files / folders you want to cache for the next build. + # Next builds will be faster when the cache is used. + # cache: file.txt + # ==== how to run your application ==== + run: + # OPTIONAL. Sets the base technology for the runtime environment: + base: rust@latest ----------------------------------------- + # OPTIONAL. Sets the internal port(s) your app listens on: + ports: + # port number + - port: 8080 -# Elixir > How To > Shared Storage + # OPTIONAL. Customize the runtime Rust environment by installing additional + # dependencies to the base Rust runtime environment. + # prepareCommands: + # - sudo apt-get something + # - curl something else + # OPTIONAL. Run one or more commands each time a new runtime container + # is started or restarted. These commands are triggered before + # your Rust application is started. + # initCommands: + # - rm -rf ./cache + # REQUIRED. Your Rust application start command + start: ./app +``` ----------------------------------------- +The top-level element is always `zerops`. -# Elixir > How To > Trigger Pipeline +### Setup +The first element `setup` contains the **hostname** of your service. A runtime service with the same hostname must exist in Zerops. +Zerops supports the definition of multiple runtime services in a single `zerops.yaml`. This is useful when you use a monorepo. Just add multiple setup elements in your `zerops.yaml`: +```yaml +zerops: + # definition for app service + - setup: app + # optional + build: ... + # optional + deploy: ... + # required + run: ... ----------------------------------------- + # definition for api service + - setup: api + # optional + build: ... + # optional + deploy: ... + # required + run: ... +``` -# Elixir > How To > Upgrade +Each service configuration contains at least the `run` section. Optional `build` and `deploy` sections can be added to further customize your process. +## Build pipeline configuration +### base ----------------------------------------- +_REQUIRED._ Sets the base technology for the build environment. -# Elixir > Overview +Following options are available for Rust builds: +- `rust@1`, `rust@latest`, `rust@stable` +- `rust@1.86` +- `rust@1.80` +- `rust@1.78` +- `rust@nightly` -[Elixir ↗](https://elixir.org/en) is an asynchronous event-driven JavaScript runtime, which is designed to build scalable network applications. - -As said, there is no need for coding yet, we have created a [Github repository ↗](https://github.com/zeropsio/recipe-elixir), a **_recipe_**, containing the most simple Elixir web application. The repo will be used as a source from which the app will be built. - -### 🚀 Feel free to deploy the recipe yourself - -This is the most bare-bones example of Elixir app running in Zerops — as few libraries as possible, - just a simple endpoint with connect, read and write to a Zerops PostgreSQL database. +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Sets the base technology for the build environment: + base: rust@latest + ... +``` - [Deploy "elixir" recipe on Zerops](https://app.zerops.io/recipe/?lf=elixir) +

+ The base build environment contains {data.alpine.default}, the selected + major version of Rust, [Zerops command line tool](/references/cli), `npm` , `yarn`, `git` and `npx` tools. +

-1. Log in/sign up to [Zerops GUI ↗](https://app.zerops.io) +:::info +You can change the base environment when you need to. Just simply modify the `zerops.yaml` in your repository. +::: -2. In the **Projects** box click on **Import a project** and paste in the following YAML config ([source ↗](https://github.com/zeropsio/recipe-elixir/blob/main/zerops-project-import.yaml)): +If you need to install more technologies to the build environment, set multiple values as a yaml array. For example: ```yaml -project: - name: recipe-elixir - tags: - - zerops-recipe - -services: - - hostname: api - type: elixir@1.16 - enableSubdomainAccess: true - buildFromGit: https://github.com/zeropsio/recipe-elixir - - - hostname: db - type: postgresql@16 - mode: NON_HA - priority: 1 +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Sets the base technology for the build environment: + base: + - rust@latest + prepareCommands: + - zsc add go@latest + ... ``` -3. Click on **Import project** and wait until all pipelines have finished. - -**That's it, your application is now up and running! :star: Let's check it works:** - -1. A _subdomain_ should have been enabled and visible in the project's **IP addressed & Public Routing Overview** box. Its format should look similar to this `https://api-808-4000.prg1.zerops.app`. -2. Click or the `subdomain` URL to open it in a browser and you should see +See the full list of supported [build base environments](/zerops-yaml/base-list#runtime-services). -``` -{"message":"This is a simple Elixir application running in Zerops.io, each request adds an entry to the PostgreSQL database and returns a count. See the source repository (https://github.com/zeropsio/recipe-elixir) for more information.","newEntry":"e64be640-d6c2-4be8-93ac-d1e40e56fa06","count":1} -``` +To customize your build environment use the [prepareCommands](#preparecommands) attribute. -:::tip -Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. +:::note +Modifying the base technology will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. ::: -## How to start +### os -It doesn't matter whether it's your first curious introduction to Zerops, you have already mastered the basics and are looking for a tiny detail or inspiration. Below, choose a section that fits your needs: +_OPTIONAL._ Sets the operating system for the build environment. -- [Care for details?](/elixir/how-to/create) — Dive in all Zerops has to offer for your Elixir application. -- [Elixir recipes](https://github.com/zeropsio?q=elixir&type=all&language=&sort=) — Get inspired by already existing repositories, ready to be imported to Zerops. +Following options are available: -## Feature Highlights +- `alpine` +- `ubuntu` -- [Create Elixir service](/elixir/how-to/create) — Start with creating a Elixir service using GUI or zCLI. -- [Zerops.yaml](/elixir/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to create your own app. -- [Scaling configuration](/elixir/how-to/scaling) — Set up scaling of your Elixir application so that it runs smoothly while using only necessary resources. +Default value is `alpine`. -{" "} +We are currently using following os version: -- [Customize build environment](/elixir/how-to/build-process#customize-build-environment) -- [Customize runtime environment](/elixir/how-to/customize-runtime) +- {data.alpine.default} +- {data.ubuntu.default} -## When in doubt, reach out +:::caution +The os version is fixed and cannot be customized. +::: -Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. +:::note +Modifying the OS will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for more details about cache invalidation. +::: -In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. +### prepareCommands -Have you build something that others might find useful? Don't hesitate to share your knowledge! +_OPTIONAL._ Customizes the build environment by installing additional dependencies or tools to the base build environment. -- [FAQ](/elixir/faq) — Most common questions in one place. -- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. +The base build environment contains: -## Popular Guides +- {data.alpine.default} +- selected version of Rust defined in the [base](#base) attribute +- [Zerops command line tool](/references/cli) +- `npm`, `yarn`, `git` and `npx` tools -- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. -- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. +To install additional packages or tools add one or more prepare commands: +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Set the base technology for the build environment: + base: rust@latest ----------------------------------------- + # OPTIONAL. Customize the build environment by installing additional packages + # or tools to the base build environment. + prepareCommands: + - cargo b --release + ... +``` -# Features > Access +When the first build is triggered, Zerops will +1. create a build container +2. download your application code from your repository +3. run the prepare commands in the defined order -Zerops provides multiple ways to access your services, whether you need internal communication between services, secure access from your development machine, or public access from the internet. +The application code is available in `/build/source` before the prepare commands are triggered, so you can use any file from your repository in your prepare commands (e.g. a configuration file). The commands themselves run in the `/home/zerops` directory. :::note -By default, your services are not publicly accessible until you configure external access. Internal communication between services within the same project works automatically. +These commands are skipped when using cached environment. Modifying `prepareCommands` will invalidate your build cache. See our [Build Cache Documentation](/features/build-cache) for details about cache invalidation. ::: -## How Zerops Networking Works - -Every Zerops project includes a **shared networking infrastructure** that handles all access methods: +#### Command exit code -**Private Project Network:** -- All services within a project share a dedicated private network -- Services communicate directly using hostnames and internal ports -- Traffic stays isolated within your project +If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/rust/how-to/logs#build-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all prepare commands are finished, your custom build environment is ready for the build phase. -**Public Access Infrastructure:** -- **Core (L3) Balancer** manages IP addresses and direct port access -- **L7 HTTP Balancer** handles domain routing and SSL termination - - Can be extensively configured for advanced routing, performance optimization, and custom behaviors - - See the [L7 Balancer Configuration Guide](/references/networking/l7-balancer-config) for detailed options -- Both are shared across all services in your project +#### Single or separated shell instances -**Secure External Access:** -- **Built-in VPN** provides secure tunnel access to your project's private network -- Useful for development, debugging, and administration +You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). -## Internal Access +### buildCommands -:::tip Complete Internal Access Setup -See the [Internal access reference guide](/references/networking/internal-access). -::: +_OPTIONAL._ Defines build commands. -Services within the same project can communicate directly using hostnames and internal ports. No additional configuration required. +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Set the base technology for the build environment: + base: rust@latest -**Example:** Connect to your `api` service on port 3000: -``` -http://api:3000 + # OPTIONAL. Build your application + buildCommands: + - cargo b --release + ... ``` -**Key points:** -- Use service hostname as the address -- Use HTTP (not HTTPS) for internal communication -- Access internal ports defined in your service configuration -- Communication is automatically isolated from other projects - -### Environment Variables - -Zerops automatically creates environment variables to help with internal connections between services. +Build commands are optional. Zerops triggers each command in the defined order in a dedicated build container, running from the `/build/source` directory. -## VPN Access -:::tip Complete VPN Setup -See the [VPN reference guide](/references/networking/vpn). -::: +Before the build commands are triggered the build container contains: -Connect securely to your project's internal network from your local machine: +1. base environment defined by the [base](#base) attribute +2. optional customisation of the base environment defined in the [prepareCommands](#preparecommands) attribute +3. your application code -```bash -# Connect to your project -zcli vpn up +#### Run build commands as a single shell instance -# Access services using internal hostnames -curl http://api:3000/health +Use following syntax to run all commands in the same environment context. For example, if one command changes the current directory, the next command continues in that directory. When one command creates an environment variable, the next command can access it. -# Disconnect when done -zcli vpn down +```yaml +buildCommands: + - | + cargo b --release ``` -## Public Access +#### Run build commands as a separate shell instances -:::tip Complete Public Access Setup -See the [Public access reference guide](/references/networking/public-access). -::: +When the following syntax is used, each command is triggered in a separate environment context. For example, each shell instance starts in the home directory again. When one command creates an environment variable, it won't be available for the next command. -Make your services accessible from the internet using one of three methods: +```yaml +buildCommands: + - cargo b --release +``` -### Zerops Subdomain -**Best for:** Development and testing +#### Command exit code -- Quick setup with automatic `.zerops.app` subdomains -- Each service gets its own unique subdomain -- Automatic SSL certificate management -- Shared infrastructure (has limitations for production use) +If any command fails, it returns an exit code other than 0 and the build is canceled. Read the [build log](/rust/how-to/logs#build-log) to troubleshoot the error. If the error log doesn't contain any specific error message, try to run your build with the --verbose option. -### Custom Domain -**Best for:** Production deployments +```yaml +buildCommands: + - cargo b --release +``` -- Use your own domain names -- Better performance with dedicated balancer -- Full control over SSL and routing -- Requires DNS configuration +If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `buildCommands` are finished, the application build is completed and ready for the deploy phase. -### Direct Port Access -**Best for:** Non-HTTP protocols and specialized use cases +### deployFiles -- Direct access to specific ports on your services -- Supports any protocol (TCP/UDP) -- Optional firewall configuration -- Uses your project's IP addresses +_REQUIRED._ Selects which files or folders will be deployed after the build has successfully finished. To filter out specific files or folders, use [`.deployignore`](#deployignore) file. -## Next Steps +```yaml +# REQUIRED. Select which files / folders to deploy after +# the build has successfully finished +deployFiles: + - target/release/~app +``` -- **Internal access setup:** [Internal Access Reference Guide](/references/networking/internal-access) -- **Public access configuration:** [Public Access Reference Guide](/references/networking/public-access) -- **VPN setup and troubleshooting:** [VPN Reference Guide](/references/networking/vpn) -- **Advanced routing and SSL:** [L7 Balancer Configuration Guide](/references/networking/l7-balancer-config) +Determines files or folders produced by your build, which should be deployed to your runtime service containers. ----------------------------------------- +The path starts from the **root directory** of your project (the location of `zerops.yaml`). You must enclose the name in quotes if the folder or the file name contains a space. -# Features > Backup +The files/folders will be placed into `/var/www` folder in runtime, e.g. `./src/assets/fonts` would result in `/var/www/src/assets/fonts`. +#### Examples -Zerops provides an automated, secure backup system for supported services. This guide covers how to configure, manage, and restore your backups. +Deploys a folder, and a file from the project root directory: -## Supported Services +```yaml +deployFiles: + - target/release/~app +``` -Zerops provides automated backup functionality for the following services. For specific backup format details and restore instructions, visit each service's documentation: [MariaDB](/mariadb/how-to/backup), [PostgreSQL](/postgresql/how-to/manage#backups), [Qdrant](/qdrant/overview), [Elasticsearch](/elasticsearch/overview), [NATS](/nats/overview), [Meilisearch](/meilisearch/overview), and [Shared Storage](/shared-storage/how-to/manage#backups). +Deploys the whole content of the build container: -## Managing Backups in the UI +```yaml +deployFiles: . +``` -By default, your data is backed up automatically **every day** between 00:00:00 UTC and 01:00:00 UTC, unless you update your settings. +Deploys a folder, and a file in a defined path: -To manage backups, go to the service detail and choose **Backups List & Configuration** in the left menu. +```yaml +deployFiles: + - ./path/to/file.txt + - ./path/to/dir/ +``` -From this section, you can: -- Create a one-time backup -- Change the frequency/disable of automatic backups -- Configure retention policies and limits +#### How to use a wildcard in the path -### Backup Frequency Options +Zerops supports the `~` character as a wildcard for one or more folders in the path. -Available schedules: -- **No backups**: Disable automatic backups (not recommended) -- **Once a day**: Daily backups at a specified time -- **Once a week**: Weekly backups on a specific day and time -- **Once a month**: Monthly backups on a specific day and time -- **Custom CRON**: Define a custom schedule using CRON syntax +Deploys all `file.txt` files that are located in any path that begins with `/path/` and ends with `/to/` -For the Custom CRON option, you can use the following syntax: +```yaml +deployFiles: ./path/~/to/file.txt +``` -
Specifies the service type and version. - See what [Elixir service types](/references/import-yaml/type-list#runtime-services) are currently supported. + See what [Rust service types](/references/import-yaml/type-list#runtime-services) are currently supported.
- Optional. Defines [custom vertical auto scaling parameters](/elixir/how-to/create#set-auto-scaling-configuration). + Optional. Defines [custom vertical auto scaling parameters](/rust/how-to/create#set-auto-scaling-configuration). All verticalAutoscaling attributes are optional. Not specified attributes will be set to their default values. @@ -8131,7 +6384,7 @@ At least one service in `services:` section is required. You can create a projec Optional. Default = 1. Defines the minimum number of containers - for [horizontal autoscaling](/elixir/how-to/create#horizontal-auto-scaling). + for [horizontal autoscaling](/rust/how-to/create#horizontal-auto-scaling). Limitations: @@ -8143,7 +6396,7 @@ At least one service in `services:` section is required. You can create a projec maxContainers - Defines the maximum number of containers for [horizontal autoscaling](/elixir/how-to/create#horizontal-auto-scaling). + Defines the maximum number of containers for [horizontal autoscaling](/rust/how-to/create#horizontal-auto-scaling). Limitations: @@ -8156,7 +6409,7 @@ At least one service in `services:` section is required. You can create a projec Optional. Defines one or more secret env variables as a key value - map. See env variable [restrictions](/elixir/how-to/env-variables#env-variable-restrictions). + map. See env variable [restrictions](/rust/how-to/env-variables#env-variable-restrictions).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Field nameAllowed values
Minute0-59
Hour0-23
Day1-31
Month1-12
Week Day0–7; both 0 and 7 represent Sunday
+Deploys all folders that are located in any path that begins with `/path/to/` -Examples: -- `0 2 * * *` - Every day at 2:00 AM -- `0 4 * * 0` - Every Sunday at 4:00 AM -- `0 0 1 * *` - First day of every month at midnight -- `0 */6 * * *` - Every 6 hours +```yaml +deployFiles: ./path/to/~/ +``` -### Backup Tagging +Deploys all folders that are located in any path that begins with `/path/` and ends with `/to/` -Zerops uses tags to categorize and manage backups: +```yaml +deployFiles: ./path/~/to/ +``` +:::note Example +By default, `./src/assets/fonts` deploys to `/var/www/src/assets/fonts`, keeping the full path. Adding `~`, like `./src/assets/~fonts`, shortens it to `/var/www/fonts` +::: -**Time-Based Tags** (assigned automatically): -- `daily`: Every automatic backup -- `weekly`: First backup of each week (Monday UTC) -- `monthly`: First backup of each month (1st UTC) +#### .deployignore -**User Tags** (custom labels you create): -- Used for organization and identification (e.g., `v2.1-release`, `before-migration`, `monthly-snapshot`) -- Add when creating manual backups - up to 24 characters (letters, numbers, `:-_`) +Add a `.deployignore` file to the root of your project to specify which files and folders Zerops should ignore during deploy. The syntax follows the same pattern format as [`.gitignore`](https://git-scm.com/docs/gitignore#_pattern_format). -**Protected Tags** (configured in retention policy): -- Backups with these tag names are exempt from automatic deletion, regardless of storage limits -- Define in the backup retention configuration section of the UI and add when creating manual backups +To ignore a specific file or directory path, start the pattern with a forward slash (`/`). Without the leading slash, the pattern will match files with that name in any directory. -:::important -Manual backups don't get automatic time-based tags. Always add a protected tag to preserve critical manual backups. +:::tip +For consistency, it's recommended to configure both your `.gitignore` and `.deployignore` files with the same patterns. ::: -### View and Manage Backup Files +Examples: -In this section, you can: -- Create manual backups -- View all backups with their timestamps and sizes -- Download backups -- Delete backups +```yaml title="zerops.yaml" +zerops: + - setup: app + build: + deployFiles: ./ +``` + +```text title=".deployignore" +/src/file.txt +``` +The example above ignores `file.txt` only in the root src directory. +```text title=".deployignore" +src/file.txt +``` +This example above ignores `file.txt` in ANY directory named `src`, such as: +- `/src/file.txt` +- `/folder2/folder3/src/file.txt` +- `/src/src/file.txt` :::note -When creating manual backups via the UI, you'll see immediate feedback. If the backup takes longer than 10 seconds, the process continues in the background. You can verify completion by refreshing the backup list or checking service logs. +`.deployignore` file also works with [`zcli service deploy`](/references/zcli/commands#deploy) command. ::: -## Storage and Limits +### cache -### Project Storage Quotas +_OPTIONAL._ Defines which files or folders will be cached for the next build. -Each Zerops project has a **technical maximum backup storage limit of 1 TiB**: -- Only full backups are stored -- If a backup would exceed the storage limit, it will not be stored -- This quota is shared across all service backups within the project +```yaml +# OPTIONAL. Which files / folders you want to cache for the next build. +# Next builds will be faster when the cache is used. +cache: file.txt +``` -### Billing -- **Lightweight Project Core**: 5 GB backup storage and 100 GB egress included -- **Serious Project Core**: 25 GB backup storage and 3 TB egress included +The cache attribute helps optimize build times by preserving specified files between builds. -When you exceed your plan's free limits, **additional charges apply** according to our [pricing](/company/pricing#overage-costs). +The cache attribute supports the [~ wildcard character](#how-to-use-a-wildcard-in-the-path). -### Retention Policy and Configuration +Learn more about the [build cache system](/features/build-cache) in Zerops. -Zerops manages which backups are kept using a retention policy that you can customize through the UI: +### envVariables -**Default Time-Based Retention** (minimums): -- At least 7 daily backups -- At least 4 weekly backups -- At least 3 monthly backups +_OPTIONAL._ Defines the environment variables for the build environment. -**Default Resource Limits** (maximums): -- Max 50 total backups per service -- Storage limited to your project's 1 TiB technical maximum (with billing for usage beyond free tier) +Enter one or more env variables in following format: -**Customization Options:** -You can modify these defaults in the backup retention configuration interface: -- **Set Protected Tags**: Define tag names that prevent automatic deletion of backups -- **Configure Maximum Limits**: Adjust total number of backups and storage size limits per service -- **Customize Minimum Retention**: Change how many daily, weekly, and monthly backups to keep -- **Set Type-Specific Limits**: Control maximum backups for each type (0 means unlimited, subject to total limits) +```yaml +zerops: + # define hostname of your service + - setup: app + # ==== how to build your application ==== + build: + base: rust@latest + … -:::important -Backups with [protected tags](#backup-tagging) and the minimum required time-based backups will always be kept, even if they exceed the limits above. This ensures your critical recovery points are preserved. -::: + # OPTIONAL. Defines the env variables for the build environment: + envVariables: + RUST_ENV: production + DB_NAME: db + DB_HOST: db + DB_USER: db + DB_PASS: ${db_password} +``` -If you need more storage space, contact our support team. +Read more about [environment variables](/rust/how-to/env-variables) in Zerops. -### When Deleting Services or Projects +## Runtime configuration -Deleted services/projects have their backups kept for a 7-day grace period before final removal. +### base -## Command Line Interface +_OPTIONAL._ Sets the base technology for the runtime environment. +If you don't specify the `run.base` attribute, Zerops keeps the current Rust version for your runtime. -You can also manage backups using the Zerops CLI (zCLI): +Following options are available for Rust builds: -```bash -# Create a backup -zcli backup create myServiceName +- `rust@1`, `rust@latest`, `rust@stable` +- `rust@1.86` +- `rust@1.80` +- `rust@1.78` +- `rust@nightly` -# Create a backup with tags (including protection) -zcli backup create myServiceName --tags pre-deploy,protected +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Sets the base technology for the build environment: + base: rust@latest + ... + + # ==== how to run your application ==== + run: + # OPTIONAL. Sets the base technology for the runtime environment: + base: rust@latest + ... ``` -Check `zcli backup --help` for current commands. +

+ The base runtime environment contains {data.alpine.default}, the + selected major version of Rust, Zerops command line tool, npm, yarn, git and + npx tools. +

-:::note -zCLI currently focuses on creation; listing/deletion/tag management is primarily via UI. +:::info +You can change the base environment when you need to. Just simply modify the zerops.yaml in your repository. ::: -## Restoring Backups +If you need to install more technologies to the runtime environment, set multiple values as a yaml array. For example: -Restoration involves downloading backups and using service-specific methods. Zerops facilitates the backup creation and download; the restore action uses service-specific tools and APIs. +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + # REQUIRED. Sets the base technology for the build environment: + base: rust@latest + ... -1. **Download**: Find the backup in the UI (by date/tag) and download it -2. **Prepare**: Set up your target environment (clean existing data or use a new instance) -3. **Restore**: Use service-specific tools via Zerops VPN, run the restore during deployment, or use the service API if available. For service-specific restore instructions, see each service's documentation linked in the [Supported Services](#supported-services) section above. - -:::info Continuous Improvement -We're working on enhancing the restore experience, potentially including more automated options in the future. -::: - -For assistance with restoration, contact Zerops support. - -## High Availability (HA) - -For multi-node HA services: -- **Automatic Backups**: Run on a randomly selected healthy node -- **Manual Backups**: Typically run on the primary/designated node (check logs) -- **Cluster State**: Other nodes stay operational - -## Security + # ==== how to run your application ==== + run: + # OPTIONAL. Sets the base technology for the runtime environment: + base: + - rust@latest + prepareCommands: + - zsc add go@latest + ... +``` -Backups are protected with end-to-end encryption: +See the full list of supported [run base environments](/zerops-yaml/base-list). -- **Unique Encryption**: Each project gets its own encryption key (X25519) -- **Secure Process**: Data is encrypted immediately as backups are created -- **Zero-Trust**: Even Zerops staff cannot access your raw backup data -- **Isolated Storage**: Backups are stored separately from your regular data -- **Secure Download**: Backups are only decrypted when you download them +To customize your build environment use the `prepareCommands` attribute. -:::important -When a project is deleted, the encryption key is permanently destroyed after 7 days, making the backup data unrecoverable. -::: +### os -## Best Practices +_OPTIONAL._ Sets the operating system for the runtime environment. -1. **Create backups before major changes**: - - Always create a manual backup with a protected tag before database migrations, deployments, or large data operations - - Use descriptive tags like `pre-migration` or `pre-release-v2` +Following options are available: -2. **Manage storage efficiently**: - - Regularly check usage in the Project Overview & Service Backup tabs to monitor free tier usage and stay within the 1 TiB technical limit - - Remove unnecessary backups, especially those with [protected tags](#backup-tagging) - - Adjust [retention policies](#retention-policy-and-configuration) based on your recovery needs - - Regularly review and clean up old backups to optimize storage usage and minimize overage costs +- `alpine` +- `ubuntu` -3. **Test your restore process** periodically in a non-production environment to ensure you can recover when needed +Default value is `alpine`. -## Troubleshooting +We are currently using following os version: -### Storage Quota Issues -**Cause**: High backup frequency, long retention periods, or many protected tags can lead to exceeding free tier limits or approaching technical maximums. +- {data.alpine.default} +- {data.ubuntu.default} -**Solutions**: -1. **Review & Prune**: Delete unnecessary manual backups or remove protected status from older backups -2. **Adjust Retention Policy**: Reduce minimum retention counts if your recovery requirements allow -3. **Optimize Schedule**: Reduce backup frequency if daily backups aren't essential -4. **Monitor Costs**: Check usage against your free tier (5GB/25GB) to avoid unexpected overage charges -5. **Contact Support**: If you need assistance managing storage +:::caution +The os version is fixed and cannot be customised. +::: -### Backup Failures -**Cause**: Service health issues, resource exhaustion, or platform problems. +### ports -**Solutions**: -1. **Check Service Logs**: Look for error messages around the scheduled backup time -2. **Verify Service Health**: Ensure the service is running properly with adequate resources -3. **Check Platform Status**: Visit status.zerops.io for any ongoing incidents -4. **Contact Support**: If issues persist, reach out with service name, failure time, and relevant logs +_OPTIONAL._ Specifies one or more internal ports on which your application will listen. ----------------------------------------- +Projects in Zerops represent a group of one or more services. Services can be of different types (runtime services, databases, message brokers, object storage, etc.). All services of the same project share a **dedicated private network**. To connect to a service within the same project, just use the service hostname and its internal port. -# Features > Build Cache +For example, to connect to a Rust service with hostname = "app" and port = 8080 from another service of the same project, simply use `app:8080`. Read more about [how to access a Rust service](/references/networking/internal-access#basic-service-communication). +Each port has following attributes: -> Zerops implements a sophisticated two-layer caching strategy that optimizes build times while maintaining complete control over the build environment. This documentation explores the architecture, configuration patterns, and practical implementation of the build cache system. + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
portDefines the port number. You can set any port number between 10 and 65435. Ports outside this interval are reserved for internal Zerops systems.
protocolOptional. Defines the protocol. Allowed values are TCP or UDP. Default value is TCP.
httpSupportOptional. httpSupport = true is the default setting for TCP protocol. Set httpSupport = false if a web server isn't running on the port. Zerops uses this information for the configuration of [public access](/features/access). httpSupport = true is available only in combination with the TCP protocol.
-## Architecture Overview +### prepareCommands -The build cache operates through two distinct layers: +_OPTIONAL._ Customises the Rust runtime environment by installing additional dependencies or tools to the runtime base environment. -1. **Base Layer**: Comprises the OS, installed dependencies, and prepare commands -2. **Build Layer**: Contains the state after executing build commands +

+ The base Rust environment contains {data.alpine.default}, the selected + major version of Rust, [Zerops command line tool](/references/cli) and `npm` , `yarn`, `git` and `npx` tools. To install additional packages or tools add one or + more prepare commands: +

-The layers work together to create an efficient and predictable build environment, though they are currently coupled in their cache invalidation behavior (invalidating one layer affects the other). +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + ... -### Cache Implementation + # ==== how to run your application ==== + run: + # OPTIONAL. Customise the runtime environment by installing additional packages + # or tools to the base Rust runtime environment. + prepareCommands: + - sudo apt-get something + - curl something else + ... +``` -The caching mechanism is implemented through an efficient file movement strategy. This approach ensures near-instantaneous cache operations through simple directory relocation within the container, implementing the following characteristics: +When the first deploy with a defined prepare attribute is triggered, Zerops will -- Files are moved between `/build/source` and `/build/cache` using container-level rename operations -- No packaging, compression, or network transfer is involved -- Cache preservation is achieved through simple directory relocation within the container -- Files maintain their original state and permissions throughout the process +1. create a prepare runtime container +2. optionally: [copy selected folders or files from your build container](#copy-folders-or-files-from-your-build-container) +3. run the `prepareCommands` commands in the defined order :::note -See detailed [build process lifecycle](#build-process-lifecycle). +`run.prepareCommands` run in the `/home/zerops` directory. ::: -## Configuration Guide +#### Command exit code -### Essential zerops.yaml Fields +If any command fails, it returns an exit code other than 0 and the deploy is canceled. Read the [prepare runtime log](/rust/how-to/logs#prepare-runtime-log) to troubleshoot the error. If the command ends successfully, it returns the exit code 0 and Zerops triggers the following command. When all `prepareCommands` commands are finished, your custom runtime environment is ready for the deploy phase. -The following fields in `zerops.yaml` affect build cache behavior: +#### Cache of your custom runtime environment -**Direct Cache Configuration**: -- `build.cache`: Explicitly defines what should be cached through paths or patterns +Some packages or tools can take a long time to install. Therefore, Zerops caches your custom runtime environment after the installation of your custom packages or tools is completed. When the second or following deploy is triggered, Zerops will use the custom runtime cache from the previous deploy if following conditions are met: -**Cache Invalidation Triggers**: -These parameters trigger cache invalidation when modified: -- `build.os`: Base operating system selection -- `build.base`: Pre-installed software stacks and runtimes -- `build.prepareCommands`: System preparation and dependency installation -- `build.cache`: Changes to cache configuration +1. Content of the [build.addToRunPrepare](#copy-folders-or-files-from-your-build-container) and `run.prepareCommands` attributes didn't change from the previous deploy +2. The custom runtime cache wasn't invalidated in the Zerops GUI. -**Build Artifact Generation**: -- `build.buildCommands`: Generates the build artifact that will be deployed. +To invalidate the Zerops runtime cache go to your service detail in Zerops GUI, choose **Service dashboard & runtime containers** from the left menu and click on the **Open pipeline detail** button. Then click on the **Clear runtime prepare cache** button. -## Cache Configuration Patterns +When the prepare cache is used, Zerops doesn't create a prepare runtime container and executes the deployment of your application directly. -### Pattern 1: System-Wide Cache Control -```yaml -build: - cache: true # Cache everything - # OR - cache: false # Intended to disable all caching -``` +#### Single or separated shell instances -The boolean values provide system-wide cache control: +You can configure your prepare commands to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). -`cache: true`: -- Preserves the entire build container state -- Maintains system-level package installations -- Ideal for globally installed packages (Python/PHP packages, Go modules) +### Copy folders or files from your build container -`cache: false`: -- Intended to disable all caching -- Currently, due to layer coupling, only files within `/build/source` are not cached -- Everything outside `/build/source` remains cached (see [Common Pitfalls: Layer Coupling](#current-pitfalls)) +

+ The prepare runtime container contains {data.alpine.default}, the + selected major version of Rust, [Zerops command line tool](/references/cli) and `npm`, `yarn`, `git` and `npx` tools. +

+ +The prepare runtime container does not contain your application code nor the built application. If you need to copy some folders or files from the build container to the runtime container (e.g. a configuration file) use the `addToRunPrepare` attribute in the [build section](#build-pipeline-configuration). -### Pattern 2: Path-Specific Caching ```yaml -# Single path -build: - cache: node_modules +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: + ... + addToRunPrepare: ./runtime-config.yaml -# Multiple paths -build: - cache: - - node_modules - - package-lock.json - - .build + # ==== how to run your application ==== + run: + # OPTIONAL. Customise the runtime environment by installing additional packages + # or tools to the base Rust runtime environment. + prepareCommands: + - sudo apt-get something + - curl something else + ... ``` -Execution flow: -1. Source code extraction to `/build/source` -2. Build command execution -3. Specified path preservation in `/build/cache` -4. Cached content restoration (no-clobber mode - source files take precedence) +In the example above Zerops will copy the `runtime-config.yaml` file from your build container **after the build has finished** into the new **prepare runtime** container. The copied files and folders will be available in the `/home/zerops` folder in the new prepare runtime container before the prepare commands are triggered. -:::tip -Ideal for non-versioned dependencies in your working directory (e.g., `node_modules`, `vendor`, `.venv`). -::: +### initCommands -## Path Pattern Reference +_OPTIONAL._ Defines one or more commands to be run each time a new runtime container is started or a container is restarted. -Zerops supports [Go's filepath.Match](https://pkg.go.dev/path/filepath#Match) syntax. Consider this example structure: +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: ... -``` -├── node_modules/ -├── package.json -├── package-lock.json -└── subdir/ - ├── file1.txt - ├── file2.txt - └── file3.md + # ==== how to run your application ==== + run: + # OPTIONAL. Run one or more commands each time a new runtime container + # is started or restarted. These commands are triggered before + # your Rust application is started. + initCommands: + - rm -rf ./cache ``` -Pattern examples and matches: -```yaml -build: - cache: - - "subdir/*.txt" # Matches: subdir/file1.txt, subdir/file2.txt - - "package*" # Matches: package.json, package-lock.json - - "node_modules" # Matches: entire node_modules directory recursively -``` +These commands are triggered in the runtime container before your Rust application is started via the [start command](#start). :::note -All patterns resolve relative to `/build/source`. Path variations like `./node_modules`, `node_modules`, and `node_modules/` are treated identically. +`run.initCommands` run in the `/var/www` directory. ::: -## Build Process Lifecycle - -1. **Initialization Phase** - - Build container startup - - Builder process launch - - Source code loading into `/build/source` - -2. **Cache Restoration Phase** - - Cached file movement to `/build/source` (no-clobber mode) - - Source file precedence handling - - Conflict logging (no build interruption) - - Cache directory cleanup - -3. **Build Execution Phase** - - Build command processing - - Artifact packaging (`build.deployFiles`) - -4. **Cache Preservation Phase** - - Specific cache files movement outside `/build/source` - - `/build/source` directory cleanup - - Container termination - -## Cache Invalidation Reference - -The build cache invalidates under these conditions: - -1. **Manual Triggers** - - API call: `DELETE /service-stack/{id}/build-cache` - - GUI: Manual cache clear action +Use init commands to clean or initialise your application cache or similar operations. -2. **Version Management** - - Backup app version activation via `PUT /app-version/{id}/deploy` +:::caution +The init commands will delay the start of your application each time a new runtime container is started (including the horizontal [scaling](/rust/how-to/scaling) or when a runtime container is restarted). -3. **Configuration Changes** - Any modifications to: - ```yaml - build.os - build.base - build.prepareCommands - build.cache - ``` +Do not use the init commands for customising your runtime environment. Use the [run:prepareCommands](#preparecommands-1) attribute instead. +::: -### Current Pitfalls +#### Command exit code -The current implementation has some important characteristics: +If any of the `initCommands` fails, it returns an exit code other than 0, but deploy is **not** canceled. After all init commands are finished, regardless of the status code, the application is started. Read the [runtime log](/rust/how-to/logs#runtime-log) to troubleshoot the error. -1. **Layer Coupling** - ```yaml - build: - base: go@1 - prepareCommands: - - sudo apk update - - sudo apk add sqlite - buildCommands: - - go build -o app main.go - cache: false - ``` - Even with `cache: false`, Go modules outside `/build/source` remain cached. +#### Single or separated shell instances -2. **Cascade Invalidation** - ```yaml - build: - base: node@22 - prepareCommands: - - sudo apk update - - sudo apk add sqlite vim # Adding 'vim' invalidates everything - buildCommands: - - npm install - - npm build - cache: - - node_modules - ``` - Modifying `prepareCommands` invalidates both layers, including cached `node_modules`. +You can configure your `initCommands` to be run in a single shell instance or multiple shell instances. The format is identical to [build commands](#buildcommands). -## Real-World Implementation Examples +### envVariables -### Node.js Project with TypeScript -```yaml -build: - base: node@22 - buildCommands: - - npm ci - - npm run build - cache: - - node_modules - - .next - - .turbo - - package-lock.json -``` +_OPTIONAL._ Defines the environment variables for the runtime environment. -### Go Project with Multiple Dependencies -```yaml -build: - base: go@1 - prepareCommands: - - sudo apk add build-base - buildCommands: - - go mod download - - go build -o bin/app cmd/main.go - cache: true # Caches entire Go modules directory -``` +Enter one or more env variables in following format: -### PHP/Laravel Project ```yaml -build: - base: php@8.3 - buildCommands: - - composer install --no-dev - - php artisan optimize - cache: - - vendor - - composer.lock +zerops: + # define hostname of your service + - setup: app + # ==== how to run your application ==== + run: + # OPTIONAL. Defines the env variables for the runtime environment: + envVariables: + RUST_ENV: production + DB_NAME: db + DB_HOST: db + DB_USER: db + DB_PASS: ${db_password} ``` -## Debugging and Monitoring - -* **Build Logs** - - Cache operations are detailed in build logs - - File conflicts during restoration are logged - - Cache preservation status is visible - -## Implementation Best Practices - -### Cache Strategy Optimization - -1. **Layer Management** - - Maintain stable `prepareCommands` to prevent cache invalidation - - Group related prepare commands logically - -2. **Performance Optimization**: - - Cache package manager lock files alongside dependency directories - - Use system-wide caching (`cache: true`) for languages with global package managers - -3. **Performance Tuning** - - Leverage system-wide caching for complex builds - - Monitor build logs for cache operations and potential conflicts - - Use explicit patterns for precise control - - Don't over-optimize – the system handles large caches efficiently - -## Future Development +Read more about [environment variables](/rust/how-to/env-variables) in Zerops. -Planned system enhancements include: -- Layer independence implementation -- Granular cache control mechanisms -- Enhanced layer management capabilities -- Improved cache invalidation patterns +### start +_REQUIRED._ Defines the start command for your Rust application. ----------------------------------------- +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: ... -# Features > Cdn + # ==== how to run your application ==== + run: + # REQUIRED. Your Rust application start command + start: ./app +``` +### health check -Zerops CDN is a global content delivery network that brings your static content closer to your users, resulting in faster load times and improved user experience. Built on Nginx and Cloudflare geo-steering technology, our CDN automatically routes users to the nearest server location based on their DNS request. +_OPTIONAL._ Defines a health check. -## Key Benefits +`healthCheck` requires either one `httpGet` object or one `exec` object. -- **Global Reach**: Serve content from strategic locations across the world -- **Reduced Latency**: Content is delivered from the server closest to your users -- **Simple Integration**: No complex configuration required +#### httpGet -## Global CDN Infrastructure +Configures the health check to request a local URL using a HTTP GET method. -Zerops CDN operates across **6 strategic regions** to ensure your content is always delivered from a location close to your users: +Following attributes are available: - +
- - - + + - - - - - - - - - - - - - + + - - - + + - - - + + - - - + + - +
RegionLocationCoverage AreaParameterDescription
EUCZPrague, Czech RepublicPrimary European coverage + failover for all regions
DEFalkenstein, Germany
UKLondon, United KingdomUK and surrounding areasportDefines the port of the HTTP GET request. +The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
AUSydney, AustraliaAustralia and OceaniapathDefines the URL path of the HTTP GET request. +The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
SGSingapore, SingaporeSoutheast AsiahostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
CABeauharnois, CanadaNorth AmericaschemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. +If your application requires a https request, set scheme: https
-### Geo-Steering Technology -Zerops CDN's geo-steering technology automatically routes users to the server location closest to them. Here's how it works: - -* **Automatic routing**: Users are directed to the optimal CDN node based on their geographic location -* **Quick failover**: The DNS TTL is set to just 30 seconds, allowing fast recovery if a node fails -* **Redundancy**: If any node becomes unavailable, Cloudflare automatically redirects traffic to the next closest node -* **Reliable backup**: The EU region serves as the ultimate fallback - if all other nodes go down, EU will always be served in DNS - -## CDN Modes and Implementation +**Example:** -Zerops CDN currently supports two distinct usage modes (with a third mode coming soon), each designed for specific content delivery needs. +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: ... -### Object Storage Mode + # ==== how to run your application ==== + run: + # REQUIRED. Your Rust application start command + start: ./app -Perfect for efficiently delivering media files, documents, and other static assets stored in Zerops [Object Storage](/object-storage/overview) to users across different geographical regions. + # OPTIONAL. Define a health check with a HTTP GET request option. + # Configures the check on http://127.0.0.1:80/status + healthCheck: + httpGet: + port: 80 + path: /status +``` -**Setup process:** -1. Create an Object Storage service or select an existing one -2. Enable the CDN option for this service -3. Set appropriate public read access policies for objects you want to serve via CDN +#### exec -**Accessing content:** -```txt -https://storage.cdn.zerops.app/your-bucket/path/to/file +Configures the health check to run a local command. +Following attributes are available: + + + + + + + + + + + + + + +
ParameterDescription
command + Defines a local command to be run. + + The command has access to the same [environment variables](/rust/how-to/create#set-secret-environment-variables) as your Rust application. + + A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. +
+ +**Example:** + +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: ... + + # ==== how to run your application ==== + run: + # REQUIRED. Your Rust application start command + start: ./app + + # OPTIONAL. Define a health check with a shell command. + healthCheck: + exec: + command: | + touch grass + rm -rf life + mv /outside/user /home/user ``` -:::tip -Access the storage CDN URL via the `storageCdnUrl` **project** environment variable `${storageCdnUrl}/your-bucket/path/to/file`. -::: +### crontab -### Static Mode +_OPTIONAL._ Defines cron jobs. -Ideal for caching and delivering static website assets like HTML, CSS, JavaScript, and images served from your custom domains. +Setup cron jobs in the following format: -**Setup process:** -1. Configure domain access for your service through the L7 HTTP Balancer section -2. Access domain settings via the **three dots menu** or **gear icon** next to your domain entry -3. In the "Project Domain Access Modification" dialog, enable the **"Enable CDN for static files"** toggle -4. Optionally enable "Automatically install SSL Certificates" if not already configured +```yaml +zerops: + # define hostname of your service + - setup: app -**Accessing content:** -```txt -https://static.cdn.zerops.app/your-domain.com/path/to/file + # ==== how to run your application ==== + run: + crontab: + # REQUIRED. Sets the command to execute: + - command: "" + # REQUIRED. Sets the interval time to execute: + timing: "0 * * * *" ``` -:::tip -Access the static CDN URL via the `staticCdnUrl` **project** environment variable `${staticCdnUrl}/your-domain.com/path/to/file`. -::: +Read more about setting up [cron](/zerops-yaml/cron) in Zerops. -:::warning Wildcard Domains Not Supported -Static CDN cannot be activated for wildcard domains (e.g., *.example.com). You must use specific domain names. -::: +## Deploy configuration -### API Mode *(Coming Soon)* +### readiness check -Designed for caching API responses to reduce load on your backend services and deliver faster responses to clients. +_OPTIONAL._ Defines a readiness check. Read more about how the [readiness check works](/rust/how-to/deploy-process#readiness-checks) in Zerops. -**Environment variable:** Once available, you'll be able to access the API CDN URL via the `apiCdnUrl` **project** environment variable. +`readinessCheck` requires either one `httpGet` object or one `exec` object. -:::warning -API Mode is currently under development and will be available in a future release. -::: +#### httpGet -### HTML Implementation Examples +Configures the readiness check to request a local URL using a http GET method. -Here's how to integrate CDN URLs in your HTML code: +Following attributes are available: -```html - - + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
portDefines the port of the HTTP GET request. +The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
pathDefines the URL path of the HTTP GET request. +The readiness check will trigger a GET request on {'http://127.0.0.1:{port}/{path}'}
hostOptional. The readiness check is triggered from inside of your runtime container so it always uses the localhost 127.0.0.1. If you need to add a host to the request header, specify it in the host attribute.
schemeOptional. The readiness check is triggered from inside of your runtime container so no https is required. +If your application requires a https request, set scheme: https
- +**Example:** - +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: ... - - - + # ==== how to deploy your application ==== + deploy: + # OPTIONAL. Define a readiness check with a HTTP GET request option. + # Configures the check on http://127.0.0.1:80/status + readinessCheck: + httpGet: + port: 80 + path: /status - - + # ==== how to run your application ==== + run: ... ``` -### Testing Specific CDN Nodes +Read more about how the [readiness check works](/rust/how-to/deploy-process#readiness-checks) in Zerops. -For testing or debugging purposes, you can bypass the automatic geo-steering and access a specific CDN node directly: +#### exec -``` -https://{region}-{mode}.cdn.zerops.app/path/to/content +Configures the readiness check to run a local command. +Following attributes are available: + + + + + + + + + + + + + + +
ParameterDescription
command + Defines a local command to be run. + + The command has access to the same [environment variables](/rust/how-to/create#set-secret-environment-variables) as your Rust application. + + A single string is required. If you need to run multiple commands create a shell script or, use a multiline format as in the example below. +
+ +**Example:** + +```yaml +zerops: + # hostname of your service + - setup: app + # ==== how to build your application ==== + build: ... + + # ==== how to deploy your application ==== + deploy: + # OPTIONAL. Define a readiness check with a HTTP GET request option. + # Configures the check on http://127.0.0.1:80/status + readinessCheck: + exec: + command: | + touch grass + rm -rf life + mv /outside/user /home/user ``` -Available region prefixes: `cz`, `de`, `au`, `sg`, `uk`, and `ca` +Read more about how the [readiness check works](/rust/how-to/deploy-process#readiness-checks) in Zerops. -**Examples:** -- Test Australia node: `https://au-storage.cdn.zerops.app/my-bucket/test.jpg` -- Test UK node: `https://uk-static.cdn.zerops.app/my-domain.com/index.html` -## Managing CDN Content +---------------------------------------- -### Cache Lifecycle +# Ruby > Overview -Content served through Zerops CDN follows this lifecycle: -1. **First Request**: When a user requests content not yet in the CDN cache, the request goes to the origin server (your Zerops service), and the response is cached at the CDN node -2. **Subsequent Requests**: Further requests for the same content are served directly from the CDN cache, reducing latency and origin server load -3. **Cache Expiration**: By default, content remains cached for 30 days unless explicitly purged -4. **Automatic Management**: When CDN storage reaches capacity, the least recently used content is automatically removed +[Ruby ↗](https://www.ruby-lang.org/en/) is a dynamic, object-oriented programming language with a focus on simplicity and programmer happiness. -:::note Important Cache Behavior -Zerops CDN implements a fixed 30-day TTL policy. Currently, HTTP caching headers such as `Cache-Control`, `Expires`, `Pragma`, etc. do not influence CDN caching behavior. To refresh content sooner than the 30-day period, use the [purge API](#api-reference). +As said, there is no need for coding yet, we have created a [Github repository ↗](https://github.com/zerops-recipe-apps/ruby-hello-world-app), a **_recipe_**, containing a simple Ruby (Sinatra) web application served by Puma. The repo will be used as a source from which the app will be built. -Your `Cache-Control` headers will still affect browser caching behavior. +1. Log in/sign up to [Zerops GUI ↗](https://app.zerops.io) + +2. In the **Projects** box click on **Import a project** and paste in the following YAML config: + +```yaml +project: + name: recipe-ruby + tags: + - zerops-recipe + +services: + - hostname: app + type: ubuntu/ruby@4.0 + zeropsSetup: prod + enableSubdomainAccess: true + buildFromGit: https://github.com/zerops-recipe-apps/ruby-hello-world-app + + - hostname: db + type: postgresql@16 + mode: NON_HA + priority: 1 +``` + +3. Click on **Import project** and wait until all pipelines have finished. + +**That's it, your application is now up and running! :star: Let's check it works:** + +1. A _subdomain_ should have been enabled and visible in the project's **IP addressed & Public Routing Overview** box. Its format should look similar to this `https://app-808-8080.prg1.zerops.app`. +2. Click or the `subdomain` URL to open it in a browser and you should see + +``` +{"type":"ruby","greeting":"Hello from Zerops!","status":{"database":"OK"}} +``` + +:::tip +Do you have any questions? Check the step-by-step tutorial, browse the documentation and join our **[Discord](https://discord.com/invite/WDvCZ54)** community to get help from our team and other members. ::: -### When to Purge Cache +## How to start -You should consider purging cached content when: +It doesn't matter whether it's your first curious introduction to Zerops, you have already mastered the basics and are looking for a tiny detail or inspiration. Below, choose a section that fits your needs: -- **Content Updates**: You've updated content but kept the same URL (e.g., updated images, CSS files) -- **Deployment Rollouts**: You've deployed a new version of your application -- **Emergency Removal**: You need to immediately remove content that was accidentally made public -- **Testing Changes**: You want to ensure users see the latest version during testing +- [Care for details?](/ruby/how-to/create) — Dive in all Zerops has to offer for your Ruby application. +- [Ruby recipes](https://github.com/zeropsio?q=ruby&type=all&language=&sort=) — Get inspired by already existing repositories, ready to be imported to Zerops. -### Purging Cached Content +## Feature Highlights -Zerops provides multiple ways to manage and purge cached content before its normal expiration: +- [Create Ruby service](/ruby/how-to/create) — Start with creating a Ruby service using GUI or zCLI. +- [Zerops.yaml](/ruby/how-to/build-pipeline#add-zeropsyaml-to-your-repository) — See a full example of zerops.yaml file to create your own app. +- [Scaling configuration](/ruby/how-to/scaling) — Set up scaling of your Ruby application so that it runs smoothly while using only necessary resources. -- **Command Line**: Use the `zsc cdn purge` [command](/references/zsc#cdn) available in all Zerops containers: - ```sh - # Purge all content for a domain - zsc cdn purge example.com - # Purge all content (wildcard) - zsc cdn purge example.com "/*" - # Purge specific file - zsc cdn purge example.com "/path/to/my-file$" - ``` +{" "} - :::important - - This command must be executed in any container within the project that has the CDN-enabled domain active - - Currently only works for [Static Mode](#static-mode) CDN - ::: +- [Customize build environment](/ruby/how-to/build-process#customize-build-environment) +- [Customize runtime environment](/ruby/how-to/customize-runtime) -- **API Endpoints**: For programmatic control, use the [API endpoints](#api-reference). Here are ready-to-use curl examples for quickly purging content in your scripts: +## When in doubt, reach out - ```sh - # Static mode: Purge all content for a domain - curl --location --request PUT "https://api.app-prg1.zerops.io/api/rest/public/project/$PROJECT_ID/purge-cdn/static/$DOMAIN/*" \ - --header "Authorization: Bearer $USER_OR_ACCESS_TOKEN" - ``` +Don't know how to start or got stuck during the process? You might not be the first one, visit the FAQ section to find out. - ```sh - # Storage mode: Purge all content for object storage - curl --location --request PUT "https://api.app-prg1.zerops.io/api/rest/public/service-stack/$OBJECT_STORAGE_SERVICE_ID/purge-cdn/*" \ - --header "Authorization: Bearer $USER_OR_ACCESS_TOKEN" - ``` +In case you haven't found an answer (and also if you have), we and our community are looking forward to hearing from you on Discord. -#### Purge Pattern Examples +Have you build something that others might find useful? Don't hesitate to share your knowledge! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PatternDescriptionExample
`/*`Purges all contentUseful after major updates
`/images/*`Purges all content in a directoryClear all cached images
`/css/main.css$`Purges a specific fileUpdate a single CSS file
`/2023*`Purges content starting with patternClear content with date prefix
+- [FAQ](/ruby/faq) — Most common questions in one place. +- [Discord](https://discord.com/invite/WDvCZ54) — Join our core team and Zerops community on Discord. Ask questions and share your tips with other members. -:::warning Pattern Rules -- Wildcards (`*`) must be at the end of the pattern -- Specific files must include `$` at the end -- Nested wildcards (e.g., `/dir/*.jpg`) are not supported -::: +## Popular Guides -## API Reference +- [zCLI](/references/cli) — Get even more out of Zerops with the zCLI command line tool. +- [Zerops VPN](/references/networking/vpn) — Connect to your services easily with Zerops VPN. -Zerops provides a comprehensive set of API endpoints to manage your CDN configuration and content. For complete information about base URLs, authorization, and general API usage, please refer to our [API specification](/references/api). -The endpoint links below will take you to the Swagger documentation with detailed request/response schemas and examples: +---------------------------------------- -### CDN Management API +# Ruby > How To > Upgrade -- **[Enable CDN for Storage ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStack/EnableStorageCdn)** `PUT /api/rest/public/service-stack/{id}/cdn` -- **[Disable CDN for Storage ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStack/DisableStorageCdn)** `DELETE /api/rest/public/service-stack/{id}/cdn` -- **[Create Object Storage with CDN ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStackObjectStorage/CreateObjectStorageV1)** `POST /api/rest/public/service-stack/object_storage_v1` -- **[Create Domain Routing with CDN ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicPublicHttpRouting/CreatePublicHttpRouting)** `POST /api/public/public-http-routing` -- **[Update Domain Routing with CDN ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicPublicHttpRouting/UpdatePublicHttpRouting)** `PUT /api/public/public-http-routing/{id}` -### Cache Purge API -- **[Purge Storage Mode Cache ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStack/PurgeStorageCdn)** `PUT /api/rest/public/service-stack/{id}/purge-cdn/{path}` -- **[Purge Static Mode Cache ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicProject/PurgeStaticCdn)** `PUT /api/rest/public/project/{id}/purge-cdn/static/{domain}/{path}` -- **Purge Api Mode Cache *(Coming soon)*** +---------------------------------------- -## Troubleshooting +# Ruby > How To > Trigger Pipeline -Having issues with your CDN? Here are solutions to the most common problems: -#### Content Not Updated After Changes -* **Issue:** You've updated content, but users still see the old version. -* **Possible Cause:** The CDN cache is continuing to serve the previously cached version. -* **Solution:** - - Use the [purge API](#api-reference) with the specific content path - - For immediate changes, use versioned file names (e.g., `style.v2.css` instead of just `style.css`) -#### Content Not Being Cached -* **Issue:** Your content isn't being cached by the CDN. -* **Possible Cause:** Missing public read permissions on objects. -* **Solution:** - - For object storage: Check bucket and object access policies - - Verify the object is accessible directly before attempting CDN access +---------------------------------------- -:::note -Remember that only publicly accessible objects will be cached by the CDN. Private objects will always be fetched directly from the origin. -::: +# Ruby > How To > Shared Storage -#### Environment Variables Not Available -* **Issue:** You can't access the new CDN-related project level environment variables in your containers. -* **Possible Cause:** When new environment variables are created, existing services need to be restarted to access them. Services created before the CDN feature release require special handling. -* **Solution:** - - For services created after CDN release: Restart the service to apply the new environment variables - - For services created before CDN release: Add and then remove a dummy environment variable in the project settings adn restart the service -#### Unexpected 404 Errors -* **Issue:** Users receive 404 errors when accessing content via CDN. -* **Possible Cause:** Incorrect CDN URL formatting or missing content at origin. -* **Solution:** - - Double-check your [URL structure](#) (pay attention to domain names and paths) - - Verify content exists at the origin before attempting CDN access - - Test accessing the content directly from origin first -**Correct URL patterns:** -- Object Storage: `https://storage.cdn.zerops.app/your-bucket/path/to/file` -- Static Mode: `https://static.cdn.zerops.app/your-domain.com/path/to/file` +---------------------------------------- + +# Ruby > How To > Scaling ---- -*Need help implementing CDN in your project? Join our [Discord community](https://discord.gg/zeropsio) where our team and other Zerops users can assist you!* ---------------------------------------- -# Features > Coding Agents +# Ruby > How To > Logs -Zerops was built on the idea of **environment parity** — giving developers the full development lifecycle, from remote development to highly available production, with the observability and developer tools for maximum flexibility, and sensible defaults so the configs stay reasonable. Turns out that's **exactly what coding agents need** to produce and iterate on production-ready applications. -
-