# Authorization (/docs/api/authorization) API Authorization [#api-authorization] Coolify authenticates protected API requests with Bearer tokens. Each token belongs to the user and active team that created it and includes the permissions selected during creation. Before you make a request [#before-you-make-a-request] Follow [API Tokens](/core/security/credentials/api-tokens) to: * create a token for the correct active team * choose permissions and an expiration period * copy the token into the caller's secret store Use a separate token for each integration and team. Do not place tokens in source code, query strings, or deployment logs. Coolify Cloud API access is already enabled, so Cloud users only need to create a token. On a self-hosted instance, an administrator must also [enable API access](/api/ip-allowlist#api-access-controls). *** Send a Bearer token [#send-a-bearer-token] Include the complete token in the `Authorization` header of every protected request: ```sh export COOLIFY_URL="https://coolify.shadowarcanist.com" export COOLIFY_TOKEN="" curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ "$COOLIFY_URL/api/v1/teams/current" ``` The header format is: ```txt Authorization: Bearer ``` The token includes an ID, a `|` separator, and the secret value. Send the complete value exactly as Coolify displayed it when the token was created. A successful request returns the team bound to the token. *** Authorization checks [#authorization-checks] A protected request passes through these checks: 1. The token exists, has not expired, and authenticates a user. 2. The user still belongs to the team recorded when the token was created. 3. On a self-hosted instance, [API Access](/api/ip-allowlist) is enabled and the caller matches the IP allowlist when one is set. 4. The token has the permission required by the endpoint, unless it has `root`. 5. A token using `write` or `root` still belongs to a team administrator or owner. | Status | Typical meaning | | :----- | :---------------------------------------------------------------------------------------------------------------------------------------- | | `401` | Unauthenticated. The token is missing, invalid, expired, revoked, or no longer belongs to a current team member. | | `403` | Forbidden. API access or the caller's IP is blocked, the token lacks the required permission, or the token owner lacks the required role. | See [API errors](/api/errors) for other status codes and response-handling guidance. *** Review [Permissions](/api/permissions) before choosing token abilities. Read the [API overview](/api/overview) for base URLs and the other API reference sections. # Errors (/docs/api/errors) API errors [#api-errors] Coolify uses HTTP status codes to distinguish successful requests from authentication, authorization, validation, conflict, and rate-limit failures. Check the response documented for the specific endpoint because available statuses and response fields vary by operation. Error responses [#error-responses] Most API errors return a JSON object with a `message` field: ```json { "message": "Unauthenticated." } ``` Validation failures can also include an `errors` object keyed by request field: ```json { "message": "Validation error.", "errors": { "name": ["The name field is required."] } } ``` Do not parse the human-readable message to decide whether a request succeeded. Use the HTTP status code, then log the message and field errors for diagnosis. *** Status codes [#status-codes] | Status | Meaning | Client action | | :-------------------------- | :---------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------ | | `200 OK` | The request succeeded. | Read the response body for the operation result. | | `201 Created` | Coolify created the requested resource. | Store the returned identifier and verify the resource state when required. | | `400 Bad Request` | The request or token is invalid for the operation. | Check the endpoint schema, parameters, and complete token value. | | `401 Unauthenticated` | Coolify could not authenticate the request. | Replace a missing, invalid, expired, or revoked token. | | `403 Forbidden` | The authenticated caller cannot perform the operation. | Check token permissions, team role, API access, and the source-IP allowlist. | | `404 Not Found` | The route or requested resource is unavailable to the caller. | Check the URL, resource identifier, and token team. | | `409 Conflict` | The requested change conflicts with existing state, such as an existing domain. | Read the response and resolve the conflicting state before retrying. | | `422 Unprocessable Content` | One or more request fields failed validation. | Correct the fields listed in `errors`, then send a new request. | | `429 Too Many Requests` | A request limit, deployment queue, or upstream provider rejected the request temporarily. | Follow `Retry-After` and the [rate-limit guidance](/api/rate-limits#handle-a-429-response). | Each operation page under **Endpoints** lists its documented responses. *** Diagnose authentication and authorization failures [#diagnose-authentication-and-authorization-failures] For `401 Unauthenticated`, confirm that: * the header uses `Authorization: Bearer ` * the complete token value, including the ID and `|` separator, is present * the token has not expired or been revoked * the token owner still belongs to the token's team A password change revokes that user's issued API tokens. Create a replacement token when this happens. For `403 Forbidden`, confirm that: * the token has the endpoint's required `read`, `write`, or `deploy` permission * the token owner still has an administrator or owner role when using `write` or `root` * **API Access** is enabled on a self-hosted instance * the caller matches **Allowed IPs for API Access** when an allowlist is configured Token permissions cannot be changed after creation. Create a replacement token with the required permissions and revoke the previous token. IP allowlist rejections [#ip-allowlist-rejections] On a self-hosted instance, a request from an address outside **Allowed IPs for API Access** returns `403 Forbidden`: ```json { "success": true, "message": "You are not allowed to access the API." } ``` Treat the HTTP `403` status as the failure signal even though this response contains `"success": true`. Add the caller's exact source IP address or network to the allowlist, then make the request again. Follow [Restrict API access by IP address](/api/ip-allowlist#restrict-api-access-by-ip-address) for supported values and configuration steps. *** Missing or redacted data [#missing-or-redacted-data] A successful request can still omit expected resources or redact sensitive values. * If a resource is missing, confirm that it belongs to the team recorded when the token was created. Create a separate token for another team. * If passwords, private keys, environment values, logs, or Compose content are redacted, use a token with `read:sensitive` in addition to the endpoint's required permission. Read [Authorization](/api/authorization) for the complete request and access-check flow. Database imports and log requests [#database-imports-and-log-requests] Concurrent database start, restart, or import operations can return `409`. Wait for the current operation and inspect its result before retrying. Database create requests return `422` for invalid input, accept numeric resource limits, and interpret `instant_deploy` as a boolean. `GET /applications/{uuid}/logs` supports `service_name` to select a Compose container and returns `404` when no running container matches. Server domain requests can filter an application with `GET /servers/{uuid}/domains?uuid=`. # IP Allowlist (/docs/api/ip-allowlist) API IP allowlist [#api-ip-allowlist] Self-hosted Coolify administrators can enable API access for the instance and restrict authenticated API endpoints to specific source addresses. Coolify Cloud does not use these self-hosted controls for customer requests. API access controls [#api-access-controls] Open **Settings > Advanced**. Under **API and MCP**, the page contains: * **API access**, which allows or blocks authenticated REST API requests * **Allowed API IPs**, which accepts exact IP addresses and networks in CIDR notation When **API access** is off, protected API requests return `403 Forbidden` even when the Bearer token is valid. *** Restrict API access by IP address [#restrict-api-access-by-ip-address] **Allowed API IPs** is an instance-wide allowlist. When the field contains one or more entries, Coolify rejects a request unless its source IP matches an exact address or one of the listed networks. Before changing the allowlist, identify the source address that Coolify receives from each API client. If a client connects through NAT, add its public outbound IP address rather than its private address. 1. Open **Settings > Advanced**. 2. Under **API and MCP**, set **API access** to **Enabled**. 3. Enter exact IPv4 or IPv6 addresses, or networks in CIDR notation, in **Allowed API IPs**. 4. Separate multiple entries with commas. 5. Select **Save changes**. For example: ```txt 203.0.113.10,198.51.100.0/24,2001:db8::/32 ``` This example allows one IPv4 address, one IPv4 network, and one IPv6 network. | Entry | Accepted value | | :--------------- | :------------------------------------ | | Exact address | A valid IPv4 or IPv6 address | | IPv4 network | CIDR prefix from `/0` through `/32` | | IPv6 network | CIDR prefix from `/0` through `/128` | | Multiple entries | Comma-separated addresses or networks | Leaving the field empty or setting it to `0.0.0.0` allows API requests from any source address. Use a restrictive list for production integrations with stable outbound addresses. *** Call the API from the Coolify Docker network [#call-the-api-from-the-coolify-docker-network] When an API client runs in a container connected to the `coolify` Docker network, send requests directly to the Coolify container: ```txt http://coolify:8080/api/v1 ``` Coolify receives the request from the client's container address rather than its public outbound address. Docker may use an IPv6 address for this connection, so add both the IPv4 and IPv6 subnets assigned to the `coolify` network. List the configured subnets on the Coolify server: ```sh docker network inspect coolify \ --format '{{range .IPAM.Config}}{{println .Subnet}}{{end}}' ``` Add every IPv4 and IPv6 subnet returned by the command to **Allowed API IPs**, separated by commas. Allowing an entire Docker subnet permits every container on that subnet to pass the IP check. API tokens and their permissions still apply, but you should connect only trusted containers to the `coolify` network. *** Verify the allowlist [#verify-the-allowlist] After saving, make an authenticated request from every allowed client. Confirm that each request reaches the endpoint successfully. A request from an address outside the allowlist returns `403 Forbidden` with the message `You are not allowed to access the API.` See [IP allowlist rejections](/api/errors#ip-allowlist-rejections) for the complete response. If an expected client is rejected, confirm the public source IP address it uses when connecting to Coolify. Add that exact address or its required network, save the setting, and try again. # Making Requests (/docs/api/making-requests) Make API requests [#make-api-requests] Each endpoint specifies an HTTP method, path, parameters, request body, and possible responses. Combine the documented path with the [base URL](/api/overview#base-urls) for your Coolify deployment. The examples on this page use the following sample values: * **Coolify URL:** `https://coolify.shadowarcanist.com` * **API token:** `67|abcthisisa123dummytoken` * **Project UUID:** `x0k4w8s4o0c8g4k4c0s4` * **Application UUID:** `g8k4s0w8c4o0k8w4s0c4` Replace these values with your Coolify URL, API token, and resource UUIDs before sending a request. Follow [API Tokens](/core/security/credentials/api-tokens) to create and securely store a token. Build the request URL [#build-the-request-url] Choose an operation under **Endpoints**, then use the HTTP method and path shown on that page. For example, an endpoint documented as: ```txt PATCH /projects/{uuid} ``` becomes the following URL after you replace `{uuid}` with your project's UUID: ```txt https://coolify.shadowarcanist.com/api/v1/projects/x0k4w8s4o0c8g4k4c0s4 ``` Some endpoints also document query parameters. For example: ```txt POST https://coolify.shadowarcanist.com/api/v1/deploy?uuid=g8k4s0w8c4o0k8w4s0c4&force=true ``` The UUIDs are examples. Replace them with the project or application UUID from your Coolify instance. *** Send request headers [#send-request-headers] Protected endpoints require the complete API token as a Bearer credential. Request JSON responses with `Accept: application/json`: ```sh export COOLIFY_URL="https://coolify.shadowarcanist.com" export COOLIFY_TOKEN="67|abcthisisa123dummytoken" curl --fail-with-body \ --request GET \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/teams/current" ``` Use `Content-Type: application/json` when the request includes a JSON body: ```sh curl --fail-with-body \ --request PATCH \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data '{"name":"production-platform"}' \ "$COOLIFY_URL/api/v1/projects/x0k4w8s4o0c8g4k4c0s4" ``` Replace the example project UUID before running the request. *** Send JSON request bodies [#send-json-request-bodies] For `POST` and `PATCH` requests, follow the request-body fields and value types shown on the endpoint page. Send the body as JSON and include `Content-Type: application/json`. *** Handle the response [#handle-the-response] Check the HTTP status before using the response body. Most API endpoints return JSON. The public `/api/health` and `/api/v1/health` endpoints are exceptions and return plain text `OK` without requiring a token. The `--fail-with-body` cURL option returns a nonzero exit status for HTTP errors while preserving the response body for diagnostics. Read [Errors](/api/errors) for common status codes and [Rate Limits](/api/rate-limits) for the limit headers returned with API responses. # Overview (/docs/api/overview) Coolify API [#coolify-api] The Coolify REST API lets integrations inspect and manage teams, projects, applications, databases, services, servers, deployments, and other Coolify resources. Base URLs [#base-urls] | Deployment | Base URL | | :------------------ | :------------------------------------- | | Coolify Cloud | `https://app.coolify.io/api/v1` | | Self-hosted Coolify | `https:///api/v1` | For example, a self-hosted instance at `https://coolify.shadowarcanist.com` uses: ```txt https://coolify.shadowarcanist.com/api/v1 ``` The public health check is available at `/api/health` and `/api/v1/health`. It does not require a Bearer token. *** Before sending a protected request [#before-sending-a-protected-request] 1. Create an [API token](/core/security/credentials/api-tokens) for the team and permissions the integration needs. 2. Follow [Authorization](/api/authorization) to send the token as a Bearer credential. 3. Follow [Making Requests](/api/making-requests) to build the URL, headers, parameters, and request body. 4. Choose an operation from **Endpoints** in the API sidebar. On a self-hosted instance, an administrator must also enable API access. Use [IP Allowlist](/api/ip-allowlist) to enable the API and optionally restrict requests by source address. *** API reference sections [#api-reference-sections] * [Making Requests](/api/making-requests) explains URLs, methods, headers, parameters, bodies, and responses. * [Authorization](/api/authorization) explains Bearer tokens and access checks. * [Permissions](/api/permissions) covers token abilities, team scope, roles, and sensitive data. * [IP Allowlist](/api/ip-allowlist) covers self-hosted API access and source-IP restrictions. * [Rate Limits](/api/rate-limits) documents request limits, response headers, and retries. * [Errors](/api/errors) explains status codes and common failure responses. * **Endpoints** contains the generated request and response schema for each API operation. # Permissions (/docs/api/permissions) API permissions [#api-permissions] Each API token belongs to the user and active team that created it. Its permissions determine which endpoints it can use and whether supported responses can include sensitive values. Choose the smallest permission set required by the integration. Permission levels [#permission-levels] | Permission | Allows | Important restrictions | | :--------------- | :-------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | | `read` | List and inspect resources. | Sensitive response values remain redacted. | | `read:sensitive` | Read secrets, logs, passwords, private keys, environment values, and Compose content returned by supported endpoints. | Coolify also adds `read`. The token owner must be a team administrator or owner. | | `write` | Create, update, and delete resources through write endpoints. | The token owner must remain a team administrator or owner when the request runs. | | `deploy` | Trigger deployments, restarts, stops, cancellations, and deploy webhooks. | Selecting it in the dashboard creates a deploy-only token. The token owner must be a team administrator or owner. | | `root` | Bypass the `read`, `write`, and `deploy` checks on API endpoints. | It remains team-bound and does not bypass instance-wide API access or the IP allowlist. The token owner must be a team administrator or owner. | Selecting `root` in the dashboard removes the other permissions because they are unnecessary. It does not provide access to resources owned by another team. *** Team and role scope [#team-and-role-scope] Coolify records the active team when the token is created. Switching teams later does not change an issued token. * Create a separate token for each team an integration must access. * Removing the token owner from the team makes the token invalid. * A token that performs privileged operations requires its owner to remain a team administrator or owner. * Instance-wide [API access and IP allowlist controls](/api/ip-allowlist) still apply to every self-hosted token, including `root`. *** Sensitive response data [#sensitive-response-data] Endpoint access and sensitive-data access are separate checks. A request with `read` may succeed while passwords, private keys, environment values, logs, or Compose content remain redacted. Add `read:sensitive` only when the integration needs supported sensitive fields. The token must have that permission, and its owner must be a team administrator or owner. A `root` token can also receive supported sensitive data, but it should be reserved for integrations that need full API access. *** Choose the least privilege [#choose-the-least-privilege] * Use `read` for inventory, monitoring, and status checks. * Use `deploy` for a deployment-only CI or automation workflow. * Use `write` only when the integration must change resource configuration. * Add `read:sensitive` only when redacted responses are insufficient. * Use `root` only when the integration must call endpoints across permission levels or manage instance-wide API functions. Follow [API Tokens](/core/security/credentials/api-tokens) to create, store, rotate, and revoke credentials. Each endpoint under **Endpoints** identifies the permission required for that operation. Operation-specific checks [#operation-specific-checks] * Container log endpoints and scheduled-task output require `read:sensitive` or `root`, rather than ordinary `read`. * Saved proxy configuration and server validation logs are returned only with `read:sensitive` or `root`. * Database import uploads and starts require `write`; server-path imports also require `deploy`. * Creating a resource with `instant_deploy` requires `deploy` in addition to its creation permission. * API mounts outside the resource directory require `deploy`. Only recognized token permissions are accepted. Resource and credential ownership is checked against the resource's team, even if the user switches teams in another browser tab. # Rate Limits (/docs/api/rate-limits) API rate limits [#api-rate-limits] Coolify limits API request frequency to protect the instance from excessive traffic. Clients should read the rate-limit response headers instead of assuming that every instance uses the default. Default limits [#default-limits] | Requests | Default limit | Window | | :------------------- | :------------- | :------- | | General API requests | 200 requests | 1 minute | | `/api/health` | 1,000 requests | 1 minute | Coolify Cloud uses these default limits. Self-hosted instances use the same defaults unless an administrator changes the general limit with `API_RATE_LIMIT`. The health endpoint keeps its separate 1,000-request limit. Coolify identifies a rate-limit bucket by the authenticated user when one is available. Requests without an authenticated user are grouped by source IP address. *** Rate-limit headers [#rate-limit-headers] API responses include headers that describe the current request bucket: | Header | When present | Meaning | | :---------------------- | :---------------------- | :------------------------------------------------------------------ | | `X-RateLimit-Limit` | API responses | Maximum requests allowed in the current window. | | `X-RateLimit-Remaining` | API responses | Requests remaining in the current window after the current request. | | `Retry-After` | A rate-limited response | Seconds to wait before trying again. | | `X-RateLimit-Reset` | A rate-limited response | Unix timestamp in seconds when another request can be attempted. | Inspect the headers without downloading the response body: ```sh export COOLIFY_URL="https://coolify.shadowarcanist.com" export COOLIFY_TOKEN="67|abcthisisa123dummytoken" curl --head \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ "$COOLIFY_URL/api/v1/teams/current" ``` Some endpoints can also return `429 Too Many Requests` because a deployment queue or an upstream cloud provider is busy. Use `Retry-After` whenever the response provides it, even when `X-RateLimit-Remaining` shows capacity in Coolify's general API limit. *** Handle a 429 response [#handle-a-429-response] When Coolify returns `429 Too Many Requests`: 1. Stop sending requests for the affected operation. 2. Read `Retry-After` as a number of seconds. 3. Wait for that interval before retrying. 4. Add exponential backoff and random jitter if repeated attempts still fail. 5. Avoid retrying unsafe write requests unless the endpoint and client can prevent duplicate changes. Do not send parallel retries for the same failed request. Parallel retries consume the remaining capacity faster and can repeat a write operation. *** Change the instance-wide rate limit [#change-the-instance-wide-rate-limit] Set `API_RATE_LIMIT` in `/data/coolify/source/.env` to change the number of general API requests allowed per minute: ```dotenv API_RATE_LIMIT=400 ``` The running container does not pick up this change from a normal restart. Run the Coolify installation script to recreate the Coolify containers with the updated environment: ```sh curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` The installation script also updates Coolify to the latest release. Follow [Update Coolify](/core/instance-management/update#manual-update-via-terminal) if you need to install a specific version. After the containers are recreated, make a request and confirm that `X-RateLimit-Limit` reports the new limit. Increasing this value does not increase the capacity of the Coolify instance, deployment queues, or upstream providers. Prefer client-side caching, request batching, and backoff before raising it. Coolify Cloud users cannot change the instance environment. To request a higher limit, [contact Coolify support](/support) and explain why the integration needs more than 200 general API requests per minute. Include the endpoints being called and the expected sustained and peak request rates so the request can be evaluated. See [API errors](/api/errors) for the difference between a general rate-limit response and other API failures. # Custom Docker Options (/docs/applications/builds/custom-docker-options) Custom Docker options [#custom-docker-options] Use **General > Custom Docker Options** to add supported arguments to the command that starts an application container. Use this field only when the option belongs to the container runtime. Put image construction in a Dockerfile and use the dedicated Coolify settings for CPU, memory, GPU, ports, storage, and environment variables when available. Supported options [#supported-options] Coolify accepts these options: * `--ip` * `--ip6` * `--shm-size` * `--dns` * `--cap-add` * `--cap-drop` * `--security-opt` * `--sysctl` * `--device` * `--ulimit` * `--init` * `--privileged` * `--gpus` * `--hostname` * `--entrypoint` Coolify converts only the listed options into the generated container configuration. Other Docker run options are not applied because they can conflict with the network, storage, or lifecycle configuration Coolify manages. Add an option [#add-an-option] Enter one or more arguments: ```sh --shm-size 1g --init ``` Save the application, redeploy it, then inspect the deployment log and container behavior. Override the entrypoint [#override-the-entrypoint] Use `--entrypoint` when the image contains the required executable but its default entrypoint is not correct for this application: ```sh --entrypoint /app/start-worker.sh ``` Coolify accepts these entrypoint forms: ```sh --entrypoint /bin/sh --entrypoint="/app/start-worker.sh" --entrypoint "sh -c 'php artisan horizon'" ``` Use the quoted form when the entrypoint contains spaces or arguments. Coolify converts the value to the Compose `entrypoint` field used by the generated deployment configuration. The entrypoint executable must exist inside the image. If it starts a process that exits, Docker treats the application container as stopped. An entrypoint override can run a different process from the same image, such as a queue worker instead of the web server: ```sh --entrypoint "sh -c 'npm run worker'" ``` It can also run an image-owned initialization script: ```sh --entrypoint /app/custom-init.sh ``` Use one `--entrypoint` value. Put multiple command arguments inside the quoted value instead of repeating the option. Options such as `--privileged`, `--device`, and added Linux capabilities weaken the container isolation boundary. Grant only the access the application requires and verify the image is trusted. # Docker Compose (/docs/applications/builds/docker-compose) Docker Compose [#docker-compose] Coolify supports Docker Compose from a Git repository or from a definition pasted directly into Coolify. These paths create different resource types: | Path | Resource created | Compose definition | Git automation | | :---------------------------------------------------- | :------------------- | :--------------------------------- | :--------------------------------------------------------- | | Git repository with the **Docker Compose** build pack | Application | Stored in the repository. | Supports branch-based deployments, webhooks, and previews. | | **Docker Compose Empty** | User-defined Service | Pasted into and stored by Coolify. | Has no Git source, branch, or pull-request events. | In both paths, the Compose definition controls service images, builds, commands, environment references, volumes, health checks, dependencies, and Compose networking. Coolify parses the definition and adds the configuration required to manage the resource. Create the Docker Compose resource [#create-the-docker-compose-resource] Use this path when the Compose definition belongs in version control and deployments should follow repository changes. Choose the source [#choose-the-source] Open the target project and environment, then select **+ New**. Choose a public repository, deploy key, or supported Git App. The repository must contain the Compose file. For a public repository, paste its HTTPS URL and select **Check Repository**. Select Docker Compose [#select-docker-compose] Under **General > Build pipeline**, select **Compose** as the **Build strategy**. Set: * **Base Directory** to the repository directory that contains the application * **Docker Compose Location** to the Compose file path relative to the base directory Coolify combines both values when locating the file. Load and review the definition [#load-and-review-the-definition] Save the configuration and review **Docker Compose Content**. For Git-based applications, edit the source file in the repository and reload the application configuration instead of treating the rendered content as the primary copy. Confirm every service has the required image or build definition, environment references, volumes, and health check. Configure public services [#configure-public-services] Open **Domains**, select **Add domain**, choose the receiving **Service**, and enter the protocol, hostname, internal port, and optional path for each HTTP service that should be public. If the service listens on port `3000`, include that internal port in the value: ```sh https://app.example.com:3000 ``` The public request still uses normal HTTP or HTTPS ports. The suffix tells the Coolify proxy which container port receives the request. Deploy and verify [#deploy-and-verify] Select **Deploy**. Open **Deployment Logs** and wait for the operation to complete. Verify each public domain and inspect **Runtime Logs** for services that do not start or become healthy. Use this path to create a user-defined Service from a Compose definition without connecting a Git repository. Select Docker Compose Empty [#select-docker-compose-empty] Open the target project and environment, select **+ New**, then select **Docker Compose Empty**. Choose the deployment server and destination when Coolify asks for them. Enter the Compose definition [#enter-the-compose-definition] Paste the complete YAML definition into **Docker Compose file**. The definition must include every service, image or build instruction, environment reference, volume, health check, and dependency required by the stack. Create the Service [#create-the-service] Select **Save**. Coolify validates and parses the definition, creates a user-defined Service, and opens its configuration. Review the detected services, generated environment variables, domains, and storage before deploying. Deploy and verify [#deploy-and-verify-1] Select **Deploy**, then inspect the deployment logs for each service in the definition. Confirm that the required containers are running and healthy. Open every configured public domain and verify communication between dependent services. To change the definition later, open the Service configuration and select **Edit Compose File**. Save the change, then redeploy the Service. Because this resource has no Git source, repository webhooks and pull-request previews do not apply. Read [Services](/services) for the user-defined Service lifecycle. Configure the Compose definition [#configure-the-compose-definition] For a Git-based Application, edit the Compose file in the repository and redeploy the selected commit. For **Docker Compose Empty**, use **Edit Compose File** in the Service configuration. Environment variables [#environment-variables] Values under a Compose service's `environment:` section can come directly from the Compose file or from Coolify. ```yaml services: api: environment: APP_ENV: production DATABASE_URL: ${DATABASE_URL} ``` `APP_ENV` is fixed to `production` in the Compose definition. It is passed to the container, but Coolify does not create an editable variable for it. `${DATABASE_URL}` tells Coolify to create **DATABASE\_URL** under the resource's **Environment Variables**. Enter the connection string there instead of committing it to the Compose file. Both the list and mapping forms work: ```yaml services: api: environment: - DATABASE_URL=${DATABASE_URL} - LOG_LEVEL=${LOG_LEVEL:-info} ``` Defaults and required values [#defaults-and-required-values] Compose variable operators control what happens when a value has not been entered: | Syntax | Behavior | Typical use | | :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- | | `${VARIABLE}` | Creates an empty, editable variable in Coolify. | A value that can be empty or will be supplied later. | | `${VARIABLE:-text}` | Creates the variable with `text` as its initial value. Compose uses the fallback when the variable is unset or empty. | An optional setting with a safe default. | | `${VARIABLE-text}` | Creates the variable with `text` as its initial value. Compose uses the fallback only when the variable is unset. | A setting where an intentionally empty value must be preserved. | | `${VARIABLE:?}` | Marks the variable as required. Coolify highlights it when empty and prevents deployment until a value is entered. | A credential or connection value the stack cannot start without. | | `${VARIABLE?}` | Also marks the variable as required in Coolify. In Compose interpolation, the non-colon form distinguishes an unset value from an empty value. | Prefer `${VARIABLE:?}` unless the Compose distinction is intentional. | For example: ```yaml services: api: environment: DATABASE_URL: ${DATABASE_URL} LOG_LEVEL: ${LOG_LEVEL:-info} API_KEY: ${API_KEY:?} ``` After Coolify loads the definition, **LOG\_LEVEL** starts with `info`, while **DATABASE\_URL** and **API\_KEY** wait for values. **API\_KEY** must have a value before the resource can deploy. Coolify keeps an existing value when the Compose definition is loaded again. Changing `LOG_LEVEL` from `info` to `debug` in the dashboard is not overwritten merely because the Compose file still contains `${LOG_LEVEL:-info}`. Defaults can reference another Compose or generated variable: ```yaml services: api: environment: PUBLIC_API_URL: ${PUBLIC_API_URL:-${SERVICE_URL_API}/v1} ``` Coolify creates **PUBLIC\_API\_URL** and retains the nested `SERVICE_URL_API` reference used by its default. Keep the braces balanced when nesting expressions. Reuse one variable [#reuse-one-variable] Reference the same key anywhere in the definition when several services or fields need one value: ```yaml services: api: environment: DATABASE_URL: ${DATABASE_URL} worker: environment: DATABASE_URL: ${DATABASE_URL} ``` Both containers receive the value saved as **DATABASE\_URL** in Coolify. The same substitution works in other Compose fields, including a bind-mount source: ```yaml services: api: volumes: - /data/${TENANT_NAME}:/app/data ``` Use a shared variable [#use-a-shared-variable] Shared variables can be assigned to the corresponding application variable with reference syntax such as `{{environment.DATABASE_URL}}`. First declare `${DATABASE_URL}` in the Compose definition. Then open **Environment Variables** and set its value to the shared-variable reference: ```dotenv DATABASE_URL={{environment.DATABASE_URL}} ``` Read [Environment variables](/applications/configuration/environment-variables) for build/runtime scope and secret handling. Generated stack values [#generated-stack-values] Coolify can generate a domain, username, password, or random value when the Compose definition contains a variable named `SERVICE__`. `` identifies what the value belongs to. For `SERVICE_URL` and `SERVICE_FQDN`, use the Compose service name so Coolify can assign the generated domain to that service. Replace hyphens or dots in the service name with underscores in the variable. Reusing the same complete variable name returns the same stored value to every service in the resource. | Pattern | Generated value | Size | | :-------------------------------------------------------- | :------------------------------------------------------------------------------ | :------------------------------- | | `SERVICE_URL_` | URL based on the configured wildcard domain. | Not applicable | | `SERVICE_FQDN_` | Domain name from the generated URL, without the scheme. | Not applicable | | `SERVICE_USER_` | Random alphanumeric username. | 16 characters | | `SERVICE_LOWERCASEUSER_` | Random lowercase alphanumeric username. | 16 characters | | `SERVICE_PASSWORD_` | Random password without symbols. | 32 characters | | `SERVICE_PASSWORD_64_` | Random password without symbols. | 64 characters | | `SERVICE_PASSWORDWITHSYMBOLS_` | Random password with symbols. | 32 characters | | `SERVICE_PASSWORDWITHSYMBOLS_64_` | Random password with symbols. | 64 characters | | `SERVICE_BASE64_` or `SERVICE_BASE64_32_` | Random alphanumeric string. Despite its name, this value is not Base64-encoded. | 32 characters | | `SERVICE_BASE64_64_` | Random alphanumeric string, not Base64-encoded. | 64 characters | | `SERVICE_BASE64_128_` | Random alphanumeric string, not Base64-encoded. | 128 characters | | `SERVICE_REALBASE64_` or `SERVICE_REALBASE64_32_` | Base64 encoding of random bytes. | 32 random bytes before encoding | | `SERVICE_REALBASE64_64_` | Base64 encoding of random bytes. | 64 random bytes before encoding | | `SERVICE_REALBASE64_128_` | Base64 encoding of random bytes. | 128 random bytes before encoding | | `SERVICE_HEX_32_` | Random hexadecimal string. | 32 characters | | `SERVICE_HEX_64_` | Random hexadecimal string. | 64 characters | | `SERVICE_HEX_128_` | Random hexadecimal string. | 128 characters | Naming generated variables [#naming-generated-variables] Underscores are allowed in ordinary environment variable names, such as `DATABASE_PASSWORD`. In Coolify's magic variables, some underscores separate parts that the parser uses to choose what to generate: ```text SERVICE_PASSWORD_64_DB │ │ │ └─ Identifier: DB │ │ └──── Size: 64 characters │ └───────────── Type: PASSWORD └───────────────────── Coolify magic-variable prefix SERVICE_URL_API_3000 │ │ │ └───── Internal port: 3000 │ │ └───────── Compose service: api │ └───────────── Type: URL └───────────────────── Coolify magic-variable prefix ``` For generated usernames, passwords, and random values, keep `` as a single token without underscores. Use `DBPASSWORD`, for example, rather than `DB_PASSWORD`. Adding an underscore can change the parsed type or size instead of extending the identifier. | Example | Meaning | | :------------------------------- | :-------------------------------------------------------------------------------------------- | | `DATABASE_PASSWORD` | Ordinary variable. Underscores are allowed; Coolify does not generate a value from this name. | | `SERVICE_PASSWORD_DBPASSWORD` | Generates a password for identifier `DBPASSWORD`. | | `SERVICE_PASSWORD_64_DBPASSWORD` | Generates a 64-character password for that identifier. | | `SERVICE_PASSWORD_DB_PASSWORD` | Incorrect password-generator name: `DB_PASSWORD` is not a single identifier token. | | `SERVICE_URL_API_3000` | Generates a URL for Compose service `api`, routed to internal port `3000`. | URL and FQDN names follow service-name normalization instead: a Compose service named `my-api` or `my.api` is represented as `MY_API` in the variable name. This is separate from the identifier rule for generated credentials. A final numeric segment in a URL/FQDN name is interpreted as a port. Generate and reuse credentials by referencing the generated names: ```yaml services: database: image: postgres:17 environment: POSTGRES_USER: ${SERVICE_USER_POSTGRES} POSTGRES_PASSWORD: ${SERVICE_PASSWORD_64_POSTGRES} api: image: example/api:latest environment: DATABASE_USER: ${SERVICE_USER_POSTGRES} DATABASE_PASSWORD: ${SERVICE_PASSWORD_64_POSTGRES} SESSION_SECRET: ${SERVICE_REALBASE64_64_API} ``` Coolify generates one PostgreSQL username and password, then supplies the same pair to both services. The API receives a separate Base64-encoded session secret. Generate domains for services [#generate-domains-for-services] `SERVICE_URL_` includes the scheme. `SERVICE_FQDN_` contains the domain name without the scheme. Add a numeric suffix when the proxy should route to a specific internal container port, and assign a path as the variable value when the generated URL needs a path: ```yaml services: api: environment: SERVICE_URL_API_3000: /v1 PUBLIC_API_URL: ${SERVICE_URL_API_3000} PUBLIC_API_HOST: ${SERVICE_FQDN_API_3000} ``` With a configured wildcard domain, Coolify generates the URL for the resource, appends `/v1`, and configures routing to port `3000` inside the `api` container. The public URL still uses the normal HTTP or HTTPS port. Use the matching service name in each generated domain variable: ```yaml services: frontend: environment: SERVICE_URL_FRONTEND: / api: environment: SERVICE_URL_API_8080: /v1 ``` Generated values persist between deployments and appear under **Environment Variables**. Passwords and random values can be edited there. Coolify manages the generated URL and FQDN values from the resource's domain configuration. Storage [#storage] Define Compose-owned volumes in the Compose file: ```yaml services: app: image: example/app:latest volumes: - app-data:/app/data volumes: app-data: ``` Coolify displays parsed storage under **Persistent Storage**, but Compose-owned fields are read-only there. Change them in the Compose definition. Volumes marked `external: true` use their declared Docker names. Existing resources retain previously renamed volumes; review the deployment log and storage page before migrating data to the external volume. Preview deployments retain their own volume. Coolify preserves `driver`, `driver_opts`, and `labels` when renaming managed volumes. Relative bind sources resolve from the resource directory, including supported `../` sources. Storage paths are validated; managed file paths must remain within the resource directory. Preview deletion removes only networks and volumes Coolify created for that preview. Coolify also supports `is_directory: true` and `content:` extensions for repository-relative bind sources. Use these only when the deployment must create the directory or file. For a file bind mount, create the source file before deployment or use `content:` so Coolify creates it. When the file comes from the Git repository, enable **Preserve repository during deployment** under **General > Build pipeline** so it remains available in the deployment directory. If Docker receives a missing file source, it can create a directory at that path. The container then fails to start with an error such as `not a directory: unknown`. Create a repository-relative directory before the container starts: ```yaml services: filebrowser: image: filebrowser/filebrowser:latest volumes: - type: bind source: ./srv target: /srv is_directory: true ``` Create a repository-relative file with predefined content: ```yaml services: database: image: postgres:17 volumes: - type: bind source: ./init/99-roles.sql target: /docker-entrypoint-initdb.d/99-roles.sql content: | CREATE ROLE app; ``` Read [Persistent storage](/core/persistent-storage/storage-mounts/overview) before choosing paths or backup behavior. If a file bind mount fails with `not a directory: unknown`, inspect the source path on the deployment server. Confirm that it exists as a file rather than a directory, then redeploy the resource. Health checks [#health-checks] Define health checks in the image Dockerfile or Compose service. Git-based Docker Compose Applications do not use the standard Application **Healthcheck** page, and user-defined Services also use the checks from their Compose definition. ```yaml services: api: image: example/api:latest healthcheck: test: ["CMD", "curl", "--fail", "http://localhost:3000/health"] interval: 30s timeout: 5s retries: 3 ``` Use `exclude_from_hc: true` for a one-time service, such as a migration container, that should not determine the overall application health. Compose networking [#compose-networking] Coolify creates a resource-specific network for the Compose resource. Services in the definition can reach one another by service name and internal port. Under **Advanced > Docker compose > Predefined network**, choose **Connect to predefined network** only when the Compose services must communicate with resources on the selected Coolify destination. Names can be prefixed to prevent collisions, so verify the generated container or service name before using it as a hostname. Do not publish a service with `ports:` unless it must be reachable directly on a server interface. A published host port bypasses domain-based proxy routing and can expose an internal service. Raw Compose deployment for an Application [#raw-compose-deployment-for-an-application] For a Git-based Docker Compose Application, choosing **Raw (deploy file as-is)** under **Advanced > Docker compose > Compose deployment** applies the definition without most Coolify modifications. You must provide the proxy labels, networking, and other behavior that the normal deployment path generates. Enable raw mode only when the Compose definition already contains everything required to expose and operate the application. Coolify cannot repair missing proxy or networking configuration in an as-is deployment. Application labels [#application-labels] For a normal Git-based Docker Compose Application, Coolify adds these management labels when they are absent: ```yaml labels: - coolify.managed=true - coolify.applicationId= - coolify.type=application ``` Coolify also generates the proxy labels needed for domains configured in the application. Define and maintain proxy labels yourself only when **Compose deployment** is **Raw (deploy file as-is)**. Application build arguments [#application-build-arguments] For a Git-based Docker Compose Application, Coolify can inject application build variables as Docker build arguments for services that use `build:`. Under **Advanced > Build**, set **Build arguments** to **Managed manually in Dockerfile** when the service Dockerfiles declare and consume every required `ARG` themselves. `SOURCE_COMMIT` is excluded from the build by default so commits with unchanged layers can reuse cache. Under **Advanced > Build**, set **Source commit availability** to **Available during build** only when the image contents need the commit value. Application Compose commands [#application-compose-commands] For a Git-based Docker Compose Application, the **Custom Build Command** and **Custom Start Command** fields replace the normal Compose commands. Coolify injects the Compose file and environment-file flags unless the custom command supplies its own. Keep paths relative to **Base Directory** and use the same Compose definition that Coolify parsed. Otherwise, generated domains, labels, and variables may not match the deployed services. Troubleshoot an unavailable domain [#troubleshoot-an-unavailable-domain] If a domain shows **No Available Server**: 1. inspect the deployment and service logs 2. confirm the target service is running and healthy 3. confirm the domain includes the service's internal listening port when it is not `80` 4. confirm the process listens on `0.0.0.0`, not only `127.0.0.1` 5. follow [No available server](/troubleshoot/applications/no-available-server) for proxy checks Variables in network names [#variables-in-network-names] Compose network names support interpolation such as `${NETWORK:-coolify}` and `${COMPOSE_PROJECT_NAME}_default`, including service `networks:` entries. A network name consisting of a single variable is added as an editable environment variable. # Docker Registries (/docs/applications/builds/docker-registries) Docker registries [#docker-registries] Coolify can pull an existing image for a Docker Image application or push an image created from application source. Registry authentication is stored by Docker for the server user Coolify uses to run Docker commands. Pull an existing image [#pull-an-existing-image] Create a [Docker Image application](/applications/deployments/docker-image) and enter an image reference: ```sh ghcr.io/example/api:1.4.0 ``` You can also use a SHA256 digest: ```sh ghcr.io/example/api@sha256: ``` A digest identifies fixed image content. A tag can resolve to different content after the registry publishes another image with the same tag. Push an image built by Coolify [#push-an-image-built-by-coolify] Open **General > Docker Registry**. | Field | Purpose | | :------------------- | :--------------------------------------------------------------------------------------------------------------------------- | | **Docker Image** | Registry and repository name, such as `ghcr.io/example/api`. Leaving it empty prevents Coolify from pushing the built image. | | **Docker Image Tag** | Optional additional tag. Coolify also tags the image with the source commit for Git-based builds. | Deploy the application and confirm the registry contains the expected image and tags. Authenticate a private registry [#authenticate-a-private-registry] Open **Registries** in the main sidebar, or **Servers > \[server] > Registries**. The page lists saved server logins and registries required by applications. 1. Select **Log in** and choose the target server or servers when using the global page. 2. Choose a provider preset: Docker Hub, GHCR, GitLab, Google Artifact Registry, Azure ACR, AWS ECR, or a custom registry. 3. Enter the registry, username, and password or token. Google Artifact Registry can use a service-account JSON key. 4. Select **Log in**. Coolify runs `docker login` for the configured server user. 5. Check the login before deploying. Use **Update login** to replace credentials or **Log out** to remove a login. Coolify does not store the token in its database. Docker stores the server login in `~/.docker/config.json`; those credentials are encoded, not encrypted. Authenticate every deployment and build server that needs the image. The API provides `GET /servers/{uuid}/registries`, `POST /servers/{uuid}/registries`, `POST /servers/{uuid}/registries/{registry}/check`, and `DELETE /servers/{uuid}/registries/{registry}`. Listing registry logins requires `read:sensitive`. Authenticate through SSH [#authenticate-through-ssh] You can also connect through SSH as the configured server user and authenticate: ```bash docker login ``` For token-based authentication: ```bash printf '%s' "$REGISTRY_TOKEN" | docker login --username --password-stdin ``` Docker stores the credentials for that server user. Repeat the authentication on every machine that must push or pull the private image. A build server cannot run the completed application. Configure a registry image name and authenticate both the build server and deployment server so the first can push the image and the second can pull it. Use a registry with Docker Swarm [#use-a-registry-with-docker-swarm] Every manager and worker that can run the application must be able to resolve, reach, and authenticate with the registry. Coolify passes registry authentication to `docker stack deploy`, but the image still has to be available from the registry to every Swarm node. Test an image pull from each node before relying on the deployment. Host a registry in Coolify [#host-a-registry-in-coolify] Coolify includes a [Docker Registry one-click service](/services/docker-registry). The current template: * runs `registry:3` * creates a registry username and password through Coolify service variables * generates the htpasswd file when the service starts * stores images in the persistent `registry-data` volume Create the service, configure a public domain, then use the generated credentials with `docker login ` on each server that must push or pull images. Registry storage grows as images and tags are added. Include the `registry-data` volume in backups, configure retention outside Coolify, and review the upstream [storage-driver documentation](https://distribution.github.io/distribution/storage-drivers/) when the registry should use an external storage backend. # Dockerfile (/docs/applications/builds/dockerfile) Dockerfile [#dockerfile] Use a Dockerfile when you need exact control over the base image, installed packages, copied files, build stages, runtime user, and default container command. Coolify can read the Dockerfile from a Git repository or store one directly without Git. During deployment, Coolify builds an image from its instructions, then creates a container with the application's domains, environment variables, storage, networks, health checks, and runtime settings. Choose where the Dockerfile is stored [#choose-where-the-dockerfile-is-stored] | Path | Use it when | Dockerfile location | | :--------------------- | :------------------------------------------------------------------------- | :----------------------------------------------------------------- | | Git repository | The build needs application source or other repository files. | The path formed by **Base Directory** and **Dockerfile Location**. | | Dockerfile without Git | The instructions can build an image without checking out repository files. | Stored in Coolify under **General > Dockerfile**. | A Dockerfile entered without Git has no repository build context. Its `COPY` and `ADD` instructions cannot read application files from a repository. Deploy from a Dockerfile [#deploy-from-a-dockerfile] Choose the path that matches where the Dockerfile and its build context are stored. A repository-owned Dockerfile can copy application files from the repository and can use Git-based automatic deployments. Connect the repository [#connect-the-repository] Open the target project and environment, then select **+ New**. Choose a public repository, deploy key, or supported Git App. For a public repository, paste its HTTPS URL and select **Check Repository**. Select Dockerfile [#select-dockerfile] Choose **Dockerfile** in **Build pack** during creation. After creation, this choice is **Build strategy** under **General > Build pipeline**. Configure the build context [#configure-the-build-context] Set **Base Directory** to the repository directory Docker should use as the build context. Set **Dockerfile Location** to the Dockerfile path relative to that directory. Configure the runtime [#configure-the-runtime] Continue to the application and set **Ports Exposes** to the internal port used by the process. The process must listen on `0.0.0.0`, not only `127.0.0.1`, for the Coolify proxy to reach it. Add the required domain, environment variables, and persistent storage. Do not copy production secrets into the Dockerfile or image layers. Deploy and verify [#deploy-and-verify] Select **Deploy** and inspect the Docker build stages in the deployment log. After the container starts, verify the application logs, internal port, health, and public domain. Use this path when the complete image can be built from Dockerfile instructions without application files from a repository. Select Dockerfile [#select-dockerfile-1] Open the target project and environment, select **+ New**, then select **Dockerfile**. Enter the Dockerfile [#enter-the-dockerfile] Paste the complete Dockerfile into the editor. For example: ```dockerfile FROM nginx:alpine RUN printf '

Hello from Coolify

' > /usr/share/nginx/html/index.html EXPOSE 80 ``` Select **Save**. Coolify creates an Application and opens its configuration. Coolify uses the first `EXPOSE` instruction as the initial **Ports Exposes** value. When the Dockerfile has no `EXPOSE` instruction, the initial port is `80`.
Configure the application [#configure-the-application] Open **General** to edit the stored **Dockerfile** or correct **Ports Exposes**. Add the required domain, runtime environment variables, storage, health check, and resource limits. These runtime settings are not added to the image. Deploy and verify [#deploy-and-verify-1] Select **Deploy** and inspect the Docker build stages in the deployment log. Confirm that the container starts, then verify the application logs, internal port, health, and public domain.
This application has no Git source, so Git push events and pull-request previews do not apply. Edit the stored Dockerfile and redeploy when its image instructions change.
Build arguments [#build-arguments] Coolify can inject configured build variables as Docker build arguments. Under **Advanced > Build**, set **Build arguments** to **Managed manually in Dockerfile** when the Dockerfile declares and consumes every required `ARG` itself. For Git-based Dockerfile applications, `SOURCE_COMMIT` is excluded from the build by default so commits with unchanged layers can reuse cache. Under **Advanced > Build**, set **Source commit availability** to **Available during build** only when the image contents need the commit value. Use **Build secrets > Docker BuildKit secrets** for sensitive build-time values when Docker BuildKit is available. Read [Environment variables](/applications/configuration/environment-variables#build-and-runtime-scope) before passing credentials to a build. Image health checks [#image-health-checks] A Dockerfile can define: ```dockerfile HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD curl --fail http://localhost:3000/health || exit 1 ``` The image must contain the command used by the check. Alternatively, configure the application under **Healthcheck**. Read [Health checks](/applications/configuration/health-checks) for precedence and routing behavior. Deployment commands [#deployment-commands] **Pre-deployment** runs in the current application container before replacement. **Post-deployment** runs in the newly deployed container. Coolify skips the pre-deployment command when no current container exists, including the first deployment. A failing pre-deployment command stops the deployment. Coolify marks the deployment complete before running the post-deployment command. A failing post-deployment command is recorded in the deployment log but does not change the successful deployment status. Use commands that can be run more than once, and test database migrations and other stateful operations against a non-production environment first. Node.js multi-core scaling [#nodejs-multi-core-scaling] A plain Node.js process uses one CPU core. Read [Node.js multi-core scaling](/knowledge-base/nodejs-multi-core-scaling) when a Node.js or Bun application should use multiple cores from one Dockerfile deployment. Troubleshoot the runtime [#troubleshoot-the-runtime] If the build succeeds but the domain fails: 1. inspect **Runtime Logs** for a process exit or bind error 2. confirm the process listens on `0.0.0.0` 3. confirm **Ports Exposes** contains the internal listening port 4. verify the health-check request inside **Terminal** 5. follow [No available server](/troubleshoot/applications/no-available-server) when the proxy has no healthy target # Deploy with Nixpacks (/docs/applications/builds/nixpacks/deploy) Deploy with Nixpacks [#deploy-with-nixpacks] Use this guide to connect a Git repository, let Nixpacks detect the application, and deploy the generated image with Coolify. Read the [Nixpacks overview](/applications/builds/nixpacks/overview) first when you need to decide whether automatic detection fits the codebase. Deploy the application [#deploy-the-application] Create a resource [#create-a-resource] Open the target project and environment, then select **+ New**. Connect the repository [#connect-the-repository] Create an application from a [public repository](/applications/sources/public-repositories), [deploy key](/applications/sources/deploy-keys), or supported Git App. For a public repository, paste its HTTPS URL and select **Check Repository**. Select the repository and branch. Select Nixpacks [#select-nixpacks] Choose **Nixpacks** in **Build pack** during creation. After creation, this choice is **Build strategy** under **General > Build pipeline**. Set **Base Directory** to the directory Nixpacks should inspect. Use `/` for the repository root or a path such as `/apps/api` for an application in a monorepo. Choose the application type [#choose-the-application-type] After creation, use **General > Build pipeline > Site type** to choose **Dynamic**, **Static**, or **SPA (single-page application)**. For static output: * choose **Static site** in **Output type** during creation * enter **Publish Directory**, such as `/dist` * keep the generated Nginx port `80` For a server application: * choose **Web application** in **Output type** during creation * enter the internal port where the process listens Add environment variables [#add-environment-variables] Continue to the application and open **Environment Variables**. Add the values required by the application. Choose **Available during build** in **Build time** for values that the build command must read. Review the detected commands [#review-the-detected-commands] Open **General** and review the detected **Install Command**, **Build Command**, and **Start Command**. Override a command only when detection is incorrect or the codebase requires a custom command. Deploy and verify [#deploy-and-verify] Configure a domain when the application should be public, then select **Deploy**. Inspect the deployment log to confirm which providers, packages, and commands Nixpacks selected. For a server application, open the application logs and confirm the process listens on the configured internal port. For a static application, open the domain and verify the generated assets and a client-side route. Configure static output [#configure-static-output] Coolify uses Nginx to serve a static Nixpacks build. Use **General > Build pipeline > Custom Nginx configuration** only when the site needs behavior such as single-page application fallback, custom headers, or caching rules. Save the change and redeploy the application. Coolify copies the Nginx configuration into the final static image during the image build, so a restart that reuses the existing image cannot apply the change. # Node.js Versioning (/docs/applications/builds/nixpacks/node-versioning) Node.js versioning in Nixpacks [#nodejs-versioning-in-nixpacks] Nixpacks supports selecting a Node.js major version. The Nix package archive used by the build determines the exact minor and patch version. Select a major version [#select-a-major-version] Use one repository source of truth: ```json { "engines": { "node": "22" } } ``` Nixpacks can also read `.nvmrc` or `.node-version`. Alternatively, add a build variable in Coolify: ```dotenv NIXPACKS_NODE_VERSION=22 ``` Keep **Build time** set to **Available during build**, then redeploy and inspect the build log to confirm the resolved version. Why a range does not pin a patch release [#why-a-range-does-not-pin-a-patch-release] Values such as `22`, `22.x`, or `>=22` select a compatible major version. They do not tell Nixpacks which nixpkgs archive to use. The selected archive contains a particular Node.js package. A build can therefore resolve Node.js `22.13.1`, `22.14.0`, or another `22.x` release even when the application version setting has not changed. Pin a nixpkgs archive [#pin-a-nixpkgs-archive] When the application must stay on the package set from one nixpkgs commit, add `nixpacks.toml` to the application source directory: ```toml [phases.setup] nixpkgsArchive = '51ad838b03a05b1de6f9f2a0fffecee64a9788ee' ``` The value is a complete commit SHA from the [NixOS/nixpkgs repository](https://github.com/NixOS/nixpkgs?utm_source=coolify.io). The example commit contains Node.js `22.13.1`. Redeploy and inspect the Nixpacks build log to confirm the Node.js version selected from the pinned archive. A nixpkgs commit controls more than Node.js. The pin can also change system libraries and other packages used by the build. Test the image and application before moving an archive change to production. Use a [Dockerfile](/applications/builds/dockerfile) with an exact base-image tag or digest when exact runtime reproducibility is a deployment requirement. Find an archive commit [#find-an-archive-commit] To locate a nixpkgs commit for a required Node.js release: 1. Open the [NixOS/nixpkgs repository](https://github.com/NixOS/nixpkgs?utm_source=coolify.io). 2. Find the Node.js version definition, such as `pkgs/development/web/nodejs/v22.nix`. 3. Open the file history and find the commit that introduced the required version. 4. Confirm the `version` and source hash in that revision. 5. Copy the complete commit SHA into `nixpacks.toml`. 6. Deploy in a non-production environment and verify the resolved Node.js version in the build log. For example, commit [`51ad838b03a05b1de6f9f2a0fffecee64a9788ee`](https://github.com/NixOS/nixpkgs/commit/51ad838b03a05b1de6f9f2a0fffecee64a9788ee) updates the Node.js 22 package from `22.12.0` to `22.13.1`. Read the upstream [nixpkgs archive configuration](https://nixpacks.com/docs/configuration/file#nixpkgs-archive?utm_source=coolify.io) for the Nixpacks setting. Node.js source-hash reference [#nodejs-source-hash-reference] The following values were collected from Node.js package definitions in nixpkgs history. Use them to compare the package definition in a candidate archive commit with the Node.js release you expect. These hashes are not nixpkgs archive commit IDs, and they do not pin a version by themselves. The values have not been independently verified for every platform or archive state. Confirm the version and hash in the candidate nixpkgs commit before using it. | Version | SHA256 | | :------ | :----------------------------------------------------------------- | | 20.0.0 | `sha256-dFDnV5Vo99HLOYGFz85HLaKDeyqjbFliCyLOS5d7XLU=` | | 20.1.0 | `sha256-YA+eEYYJlYFLkSKxrFMY9q1WQnR4Te7ZjYqSBmSUNrU=` | | 20.2.0 | `sha256-IlI98jFsNVaXFP8fabBTwuKGztRgiYQX3uRpRe/N+Yk=` | | 20.3.0 | `sha256-G6jUlCPtOnVykGa7PqJkk+6ct9ZWjvlIWX/J70VPdDU=` | | 20.3.1 | `sha256-EqgtswZpeVm0OJs1Gl+XhImGsTE/mQGw4LPYz08/mZE=` | | 20.4.0 | `sha256-Cb0Lc8UmtjwCnV3f2IXRCWLnrYfJdblFg8H4zpDuU0g=` | | 20.5.0 | `sha256-yzJ1aVje8cBOBpp5txtSymHtFZDBfyz6HuOvZB9y4Fg=` | | 20.5.1 | `sha256-Q5xxqi84woYWV7+lOOmRkaVxJYBmy/1FSFhgScgTQZA=` | | 20.6.0 | `sha256-nvtcunqPSxjTiw19N6mzDe1zOQyE44DPTeianTCn1vo=` | | 20.6.1 | `sha256-Ouxeco2qOIAMNDsSkiHTSIBkolKaObtUZ7xVviJsais=` | | 20.7.0 | `sha256-P8/c0FxGFRdIBZZZZnTfhbNc/OWX3QrjP1QW/E3xK+o=` | | 20.8.0 | `sha256-QSvoR65t9hAQup2jzD5r5bZ6oALjVOkZ9Z7INgNxcEw=` | | 20.8.1 | `sha256-95nGb2pjhruKwsdaN490DEVel/H+lkOT3TnJ+fbvvHA=` | | 20.9.0 | `sha256-oj2WgQq/BFVCazSdR85TEPMwlbe8BXG5zFEPSBw6RRk=` | | 20.10.0 | `sha256-MuslbuvYys1VdOZjHlS0K+fsjr4lrUeoymhUA7rRVTU=` | | 20.11.0 | `sha256-MYB+vu6wScU/F2XkqVrtaUdqS2lt0QDLU5q2aNeVC0A=` | | 20.11.1 | `sha256-d4E+2/P38W0tNdM1NEPe5OYdXuhNnjE4x1OKPAylIJ4=` | | 20.12.0 | `sha256-duU0bOv9WBUo9pn3ZPTRpuh8uBi2lnCPI13ctiWg940=` | | 20.12.1 | `sha256-aEDUkLpNHVFlXg++EgmVahXbQFUQ1+oWa62YqMnTek4=` | | 20.12.2 | `sha256-18vMX7+zHpAB8/AVC77aWavl3XE3qqYnOVjNWc41ztc=` | | 20.14.0 | `sha256-CGVQKPDYQ26IFj+RhgRNY10/Nqhe5Sjza9BbbF5Gwbs=` | | 20.15.0 | `sha256-D0p6BRw12V65BejLKqQ8XUArExIDkI/mM+s8+gUO+Qc=` | | 20.15.1 | `sha256-/dU6VynZNmkaKhFRBG+0iXchy4sPyir5V4I6m0D+DDQ=` | | 20.16.0 | `cd6c8fc3ff2606aadbc7155db6f7e77247d2d0065ac18e2f7f049095584b8b46` | | 20.17.0 | `9abf03ac23362c60387ebb633a516303637145cb3c177be3348b16880fd8b28c` | | 20.18.0 | `7d9433e91fd88d82ba8de86e711ec41907638e227993d22e95126b02f6cd714a` | | 20.18.1 | `91df43f8ab6c3f7be81522d73313dbdd5634bbca228ef0e6d9369fe0ab8cccd0` | | 20.18.2 | `69bf81b70f3a95ae0763459f02860c282d7e3a47567c8afaf126cc778176a882` | | 20.18.3 | `0674f16f3bc284c11724cd3f7c2a43f7c2c13d2eb7a872dd0db198f3d588c5f2` | | 20.19.0 | `5ac2516fc905b6a0bc1a33e7302937eac664a820b887cc86bd48c035fba392d7` | | 20.19.1 | `5587b23e907d0c7af2ea8a8deb33ec50010453b46dbb3df5987c5678eee5ed51` | | 20.19.2 | `4a7ff611d5180f4e420204fa6f22f9f9deb2ac5e98619dd9a4de87edf5b03b6e` | | 20.19.3 | `99be7b9d268d48b93be568a23240398ceacb0782dc7055b9972305c000b0e292` | | 20.19.4 | `b87fd7106013d3906706913ffc63a4403715fbb272c4f83ff4338527353eec0f` | | 20.19.5 | `230c899f4e2489c4b8d2232edd6cc02f384fb2397c2a246a22e415837ee5da51` | | 20.19.6 | `2026f9ff52c286d7c7d99932b21be313d1736aea524c5aff1748d41ab0bd9a20` | | Version | SHA256 | | :------ | :----------------------------------------------------------------- | | 22.0.0 | `sha256-IuKPv/MfaQc7gCTLQnReUQX4QEHzR1smC5fVoUEDnRo=` | | 22.1.0 | `sha256-nX1fQNnb1iYMmbXklLX5vHVejw/6xw4SGtzl+0QvI8s=` | | 22.2.0 | `sha256-iJkIqIKNFISRDX5lm2qlet6NUo/w45Dpp372WadihHQ=` | | 22.3.0 | `0k0h4s9s2y0ms3g6xhynsqsrkl9hz001dmj6j0gpc5x5vk8mpf5z` | | 22.4.0 | `sha256-KStDAITy8ykT3H2k6y+8iWklJ3Kp0b/ormxLSpjKOtM=` | | 22.4.1 | `sha256-ZfyFf1qoJWqvyQCzRMARXJrq4loCVB/Vzg29Tf0cX7k=` | | 22.5.1 | `924f381a32cf26b6bedbe95feedde348450f4fd321283d3bf3f7965aa45ce831` | | 22.6.0 | `37259d618d5565ca55acc2585045c7e1c5b9965a3d4eb44c0a237fdae84b9d44` | | 22.7.0 | `1e0b6f2f2ca4fb0b4644a11363169daf4b7c42f00e5a53d2c65a9fdc463e7d88` | | 22.8.0 | `f130e82176d1ee0702d99afc1995d0061bf8ed357c38834a32a08c9ef74f1ac7` | | 22.9.0 | `a55aeb368dee93432f610127cf94ce682aac07b93dcbbaadd856df122c9239df` | | 22.10.0 | `3180710d3130ad9df01466abf010e408d41b374be54301d1480d10eca73558e0` | | 22.11.0 | `bbf0297761d53aefda9d7855c57c7d2c272b83a7b5bad4fea9cb29006d8e1d35` | | 22.12.0 | `fe1bc4be004dc12721ea2cb671b08a21de01c6976960ef8a1248798589679e16` | | 22.13.1 | `cfce282119390f7e0c2220410924428e90dadcb2df1744c0c4a0e7baae387cc2` | | 22.14.0 | `c609946bf793b55c7954c26582760808d54c16185d79cb2fb88065e52de21914` | | 22.15.0 | `e7c4226d1d92f33ad854d6da4f7e519e77690b8e73f93496881f8c539174d9df` | | 22.15.1 | `c19f0177d21c621746625e5f37590bd0d79a72043b77b53784cba5f145e7263e` | | 22.16.0 | `720894f323e5c1ac24968eb2676660c90730d715cb7f090be71a668662a17c37` | | 22.17.0 | `7a3ef2aedb905ea7926e5209157266e2376a5db619d9ac0cba3c967f6f5db4f9` | | 22.17.1 | `327415fd76fcebb98133bf56e2d90e3ac048b038fac2676f03b6db91074575b9` | | 22.18.0 | `120e0f74419097a9fafae1fd80b9de7791a587e6f1c48c22b193239ccd0f7084` | | 22.19.0 | `0272acfce50ce9ad060288321b1092719a7f19966f81419835410c59c09daa46` | | 22.20.0 | `ff7a6a6e8a1312af5875e40058351c4f890d28ab64c32f12b2cc199afa22002d` | | 22.21.1 | `487d73fd4db00dc2420d659a8221b181a7937fbc5bc73f31c30b1680ad6ded6a` | | Version | SHA256 | | :---------- | :----------------------------------------------------------------- | | 24.0.0-rc.2 | `729fca42bb7266031dd020f3935423ea8d4b4e2d119b34b608f1d079e5c1621a` | | 24.0.0-rc.3 | `9bbca08fba05f075a20f734ea80b195a4a39218476b60b32db79e1d393fda20b` | | 24.0.0 | `914f3f1b03f84a0994d7357f190ff13c038800c693b6c06da2290eb588c82761` | | 24.0.1 | `70271026971808409a7ed6444360d5fe3ef4146c1ca53f2ca290c60d214be84e` | | 24.0.2 | `1597075afc06e5c6145d0bfbd77e2072c2ec0ab71ac4950cf008b2641374cd71` | | 24.1.0 | `c8171b2aeccb28c8c5347f273a25adae172fb2a65bc8c975bc22ec58949d0eaf` | | 24.2.0 | `40143d43efbdeeb9537995f532126c494d63a31da332acb5022f76f00afc62ab` | | 24.3.0 | `eb688ef8a63fda9ebc0b5f907609a46e26db6d9aceefc0832009a98371e992ed` | | 24.4.0 | `42fa8079da25a926013cd89b9d3467d09110e4fbb0c439342ebe4dd6ecc26bbb` | | 24.4.1 | `adb79ca0987486ed66136213da19ff17ef6724dcb340c320e010c9442101652f` | | 24.5.0 | `f1ba96204724bd1c6de7758e08b3718ba0b45d87fb3bebd7e30097874ccc8130` | | 24.6.0 | `8ad5c387b5d55d8f3b783b0f1b21bae03a3b3b10ac89a25d266cffa7b795e842` | | 24.7.0 | `cf74a77753b629ffebd2e38fb153a21001b2b7a3c365c0ec7332b120b98c7251` | | 24.8.0 | `1c03b362ebf4740d4758b9a3d3087e3de989f54823650ec80b47090ef414b2e0` | | 24.9.0 | `f17bc4cb01f59098c34a288c1bb109a778867c14eeb0ebbd608d0617b1193bbf` | | 24.10.0 | `f17e36cb2cc8c34a9215ba57b55ce791b102e293432ed47ad63cbaf15f78678f` | | 24.11.0 | `cf9c906d46446471f955b1f2c6ace8a461501d82d27e1ae8595dcb3b0e2c312a` | | 24.11.1 | `ea4da35f1c9ca376ec6837e1e30cee30d491847fe152a3f0378dc1156d954bbd` | | 24.12.0 | `6d3e891a016b90f6c6a19ea5cbc9c90c57eef9198670ba93f04fa82af02574ae` | | Version | SHA256 | | :------ | :----------------------------------------------------------------- | | 25.2.1 | `aa7c4ac1076dc299a8949b8d834263659b2408ec0e5bba484673a8ce0766c8b9` | Read the [Nixpacks Node provider](https://nixpacks.com/docs/providers/node?utm_source=coolify.io) for upstream version-selection behavior. # Overview (/docs/applications/builds/nixpacks/overview) Nixpacks [#nixpacks] Nixpacks detects the application's language and framework from its codebase and generates a Dockerfile. Coolify builds the application image from those generated instructions. Use Nixpacks when the codebase follows a supported convention and does not need a custom Dockerfile. Nixpacks is available for Git-based applications. Railway states that [Nixpacks](https://github.com/railwayapp/nixpacks) is not under active development and recommends [Railpack](https://github.com/railwayapp/railpack) as its successor. Coolify still supports Nixpacks. For a new application, evaluate Railpack first, but note that Coolify currently labels Railpack as **Beta**. Test the generated image before switching an existing application because the two builders use different configuration files and can produce different results. When to use Nixpacks [#when-to-use-nixpacks] Nixpacks is a good fit when: * the application uses a language or framework supported by Nixpacks * its manifest and lockfile are available inside the configured **Base Directory** * automatic install, build, and start command detection is sufficient * the build needs only small command, package, or phase overrides Use [Dockerfile](/applications/builds/dockerfile) when the image needs exact base images, operating-system configuration, copy instructions, users, or build stages. Follow [Deploy with Nixpacks](/applications/builds/nixpacks/deploy) for the complete setup procedure. How Coolify uses Nixpacks [#how-coolify-uses-nixpacks] For each deployment, Coolify gives Nixpacks the application source directory and build configuration. Nixpacks detects providers, packages, and commands, then generates the Dockerfile used to build the image. For a server application, Coolify starts a container from that image and routes requests to the configured internal port. For a static application, Nixpacks builds the frontend and Coolify copies the selected **Publish Directory** into an Nginx image. Configure Nixpacks [#configure-nixpacks] Coolify shows the detected **Install Command**, **Build Command**, and **Start Command** under **General**. Override only the command the application needs to change. Nixpacks can also read `nixpacks.toml` or `nixpacks.json` from the application source directory. Use a configuration file when the build needs packages, phases, or behavior that cannot be expressed through the Coolify command fields. Nixpacks environment variables use the `NIXPACKS_` prefix. Add build configuration under **Environment Variables** and keep **Build time** set to **Available during build**. Refer to the [Nixpacks configuration documentation](https://nixpacks.com/docs/configuration/file?utm_source=coolify.io) for the supported file schema. Static applications [#static-applications] When **Site type** is **Static** or **SPA (single-page application)**, Coolify serves the selected publish directory through Nginx. Use **General > Build pipeline > Custom Nginx configuration** only when the default static-server configuration is insufficient. Redeploy after saving a change because Coolify copies the configuration into the final static image during the image build. Node.js versions [#nodejs-versions] Nixpacks selects Node.js from repository configuration such as `engines.node`, `.nvmrc`, or `.node-version`, or from `NIXPACKS_NODE_VERSION`. Read [Node.js versioning](/applications/builds/nixpacks/node-versioning) before depending on a specific minor or patch version. Use multiple CPU cores with Node.js [#use-multiple-cpu-cores-with-nodejs] A plain Node.js process uses one CPU core. Read [Node.js multi-core scaling](/knowledge-base/nodejs-multi-core-scaling) when a Node.js or Bun application should use multiple cores from one Nixpacks deployment. Troubleshoot detection [#troubleshoot-detection] If the build uses the wrong provider or command: 1. confirm **Base Directory** contains the application manifest 2. inspect the generated plan in the deployment log 3. remove conflicting lockfiles or manifests from that source directory 4. add a Nixpacks configuration file or override the affected command 5. use [Dockerfile](/applications/builds/dockerfile) when the build needs complete image control Nixpacks resolves an older package [#nixpacks-resolves-an-older-package] Nixpacks can resolve an older package from its selected nixpkgs archive. For Node.js, read [Node.js versioning](/applications/builds/nixpacks/node-versioning). For other packages, refer to the upstream [nixpkgs archive setting](https://nixpacks.com/docs/configuration/file#nixpkgs-archive?utm_source=coolify.io) and test an archive change before using it in production. # Overview (/docs/applications/builds/overview) Build applications [#build-applications] Every application container starts from a Docker image. For Git source, the selected **Build strategy** determines how Coolify prepares the required images. Nixpacks, Railpack, Static, and Dockerfile build one application image; Docker Compose can build or pull an image for each service. [Docker Image applications](/applications/deployments/docker-image) skip this build stage because the image already exists in a registry. Use Nixpacks or Railpack for automatic detection, Static for files that are already built, Dockerfile for one custom image, and Docker Compose for a multi-service definition. *** Compare build methods [#compare-build-methods] The creation form labels these choices **Build pack**; after creation, use **Build strategy** under **General > Build pipeline**. Nixpacks, Railpack, Static, and Dockerfile each produce one application image. Docker Compose is broader: each service can build an image from source or pull an image from a registry. | Method | Use it when | Guide | | :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------- | | Nixpacks | The codebase follows a supported language or framework convention. Configure it through detection, command overrides, or `nixpacks.toml`. | [Deploy with Nixpacks](/applications/builds/nixpacks/deploy) | | Railpack (Beta) | The repository is supported by Railway's newer automatic build system. Configure it through detection, command overrides, or `railpack.json`. | [Configure Railpack](/applications/builds/railpack) | | Static | The repository contains the finished website files. Configure their directory and optional web-server settings in Coolify. | [Configure a static build](/applications/builds/static) | | Dockerfile | The repository contains one custom image definition used with Coolify runtime settings. | [Use a Dockerfile](/applications/builds/dockerfile) | | Docker Compose | The application needs a Compose definition with one or more services. | [Use Docker Compose](/applications/builds/docker-compose) | Choose [Nixpacks](/applications/builds/nixpacks/overview) or [Railpack](/applications/builds/railpack) when automatic detection is sufficient. Choose [Dockerfile](/applications/builds/dockerfile) or [Docker Compose](/applications/builds/docker-compose) when the repository must define the image or service topology explicitly. Where builds run [#where-builds-run] Coolify runs image builds on the deployment server by default. A [build server](/core/infrastructure/servers/build-servers) separates build CPU, memory, and disk use from the server running the application. A build server cannot run deployed resources. The completed image must be available to the deployment server through the configured registry path. Build and runtime configuration [#build-and-runtime-configuration] Build-time variables and commands affect the image. Runtime variables, domains, storage, and container settings affect the container created from that image. A runtime-only change can reuse an existing image. Changes to the Dockerfile, Compose build definition, source commit, build command, or build-time variables can require another build. Build cache [#build-cache] Docker reuses unchanged build layers when caching is available. Under **Advanced**, **Disable Build Cache** forces every build step to run again. Coolify excludes `SOURCE_COMMIT` from the build by default so different commits can reuse unchanged layers. Under **Advanced > Build**, set **Source commit availability** to **Available during build** only when the build itself requires the commit value. Use **Force deploy (without cache)** for one deployment that must run a Coolify-generated build without cached layers. A custom Docker Compose build command controls its own cache flags. Push built images to a registry [#push-built-images-to-a-registry] Configure **Docker Image** and **Docker Image Tag** under **General** when a built image must be pushed to a registry. Read [Docker registries](/applications/builds/docker-registries) for image names, tags, authentication, and build-server requirements. *** Choose the next build guide [#choose-the-next-build-guide] # Railpack (/docs/applications/builds/railpack) Railpack [#railpack] Railpack is Railway's successor to Nixpacks. It detects the application's language and framework from its codebase, installs dependencies, and creates an application image with Docker BuildKit. Railpack can build server applications and frontend applications that produce static files. Coolify supports Railpack only for Git-based applications. Coolify labels Railpack as **Beta**. Test the generated image and application behavior before replacing an existing production build. Deploy with Railpack [#deploy-with-railpack] Connect the repository [#connect-the-repository] Create an application from a [public repository](/applications/sources/public-repositories), [deploy key](/applications/sources/deploy-keys), or supported Git App. Select the repository and branch. Select Railpack [#select-railpack] Choose **Railpack** in **Build pack** during creation. After creation, this choice is **Build strategy** under **General > Build pipeline**. Set **Base Directory** to the directory Railpack should inspect. Use `/` for the repository root or a path such as `/apps/api` for an application in a monorepo. Configure the application type [#configure-the-application-type] After creation, use **General > Build pipeline > Site type** to choose **Dynamic**, **Static**, or **SPA (single-page application)**. For a server application: * choose **Web application** in **Output type** during creation * enter the internal port where the process listens For a static output: * choose **Static site** in **Output type** during creation * enter **Publish Directory**, such as `/dist` * keep the generated Nginx port `80` Review detected commands [#review-detected-commands] Continue to **General** and review the detected **Install Command**, **Build Command**, and **Start Command**. Override a command only when detection is incorrect or the codebase requires a custom command. Deploy and verify [#deploy-and-verify] Configure the required environment variables and domain, then select **Deploy**. Inspect the deployment log to confirm the generated plan and commands before using the application in production. The server that runs the build and the Coolify helper container must have the Docker Buildx CLI plugin. A Railpack deployment stops with an error when either copy of Buildx is unavailable. Command overrides [#command-overrides] Coolify can pass install, build, and start command overrides to Railpack. Use the **Install Command**, **Build Command**, and **Start Command** fields under **General** for a direct override. Use `railpack.json` when the build needs additional packages, multiple commands, or other repository-owned configuration. Railpack environment variables [#railpack-environment-variables] Railpack build variables use the `RAILPACK_` prefix. Add them under **Environment Variables** with **Build time** set to **Available during build**. | Variable | Purpose | | :----------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | | `RAILPACK_BUILD_CMD` | Override the detected build command. | | `RAILPACK_INSTALL_CMD` | Override the detected install command. | | `RAILPACK_START_CMD` | Override the container start command. | | `RAILPACK_PACKAGES` | Install additional [Mise](https://mise.jdx.dev?utm_source=coolify.io) packages as space-separated `package[@version]` values. | | `RAILPACK_BUILD_APT_PACKAGES` | Install additional space-separated APT packages in the build environment. | | `RAILPACK_DEPLOY_APT_PACKAGES` | Install additional space-separated APT packages in the final image. Coolify also adds `curl` and `wget`. | | `RAILPACK_DISABLE_CACHES` | Disable named BuildKit cache keys, or use `*` to disable all Railpack caches. | | `RAILPACK_VERBOSE` | Enable verbose Railpack output. | Use the Coolify command fields instead of defining the three command variables when the application only needs an install, build, or start override. Refer to the upstream [Railpack environment variables](https://railpack.com/config/environment-variables/?utm_source=coolify.io) for accepted values and additional variables. `railpack.json` [#railpackjson] Add `railpack.json` to the application source directory selected by **Base Directory**: ```json { "$schema": "https://schema.railpack.com", "packages": { "node": "22" }, "steps": { "install": { "commands": ["npm install"] }, "build": { "commands": ["npm run build"] } }, "deploy": { "startCommand": "node dist/index.js" } } ``` The `$schema` value enables editor validation and completion. During deployment, Coolify reads this file and passes the resulting configuration to `railpack prepare`. Refer to the [Railpack configuration-file reference](https://railpack.com/config/file/?utm_source=coolify.io) for the supported schema. Static output [#static-output] When **Site type** is **Static** or **SPA (single-page application)**, Railpack builds the application and Coolify copies the selected publish directory into an Nginx image. Use **General > Build pipeline > Custom Nginx configuration** only when the default static-server configuration is insufficient. Redeploy after saving a change because Coolify copies the configuration into the final static image during the image build. Choose Railpack or Nixpacks [#choose-railpack-or-nixpacks] Both methods detect supported codebases, create an image, support static output, and allow command overrides. | Difference | Railpack | Nixpacks | | :----------------------- | :------------------------------------------------- | :--------------------------------------------- | | Repository configuration | `railpack.json` | `nixpacks.toml` or `nixpacks.json` | | Image build | Docker BuildKit frontend through Docker Buildx | Generated Dockerfile built by Docker | | Package versions | [Mise](https://mise.jdx.dev?utm_source=coolify.io) | Nix | | Build-variable prefix | `RAILPACK_` | `NIXPACKS_` | | Upstream development | Actively developed successor | Maintenance mode; not under active development | | Status in Coolify | **Beta** | Supported | Use [Dockerfile](/applications/builds/dockerfile) when the repository needs deterministic image instructions beyond either automatic builder. # Static (/docs/applications/builds/static) Static [#static] The **Static** build pack packages files already present in the Git repository into an Nginx image. Use it when the repository contains the final HTML, CSS, JavaScript, and other assets that should be served. It does not run a framework build command. Use Nixpacks, Railpack, or a Dockerfile when the repository must run `npm run build` or another compilation step before the static files exist. Deploy static files [#deploy-static-files] Prepare the repository [#prepare-the-repository] Commit the final static files to the repository. If they are in a subdirectory such as `dist`, identify that path before creating the application. Create a resource [#create-a-resource] Open the project and environment that should contain the application, then select **+ New**. Choose the repository source [#choose-the-repository-source] Connect a public repository, deploy key, or supported Git App. For a public repository, paste its HTTPS URL and select **Check Repository**. Select Static [#select-static] Select **Static** in **Build pack** during creation. After creation, this choice is **Build strategy** under **General > Build pipeline**. Set the base directory [#set-the-base-directory] Set **Base Directory** to the directory containing the finished website files. Use `/` when the files are at the repository root, or a path such as `/dist` when they are in a subdirectory. Select **Continue**. Review the web server [#review-the-web-server] Coolify uses Nginx to serve the static files. Configure the domain [#configure-the-domain] Open **Domains**, select **Add domain**, and enter the protocol, hostname, and any target port or path. Add each additional hostname separately. See [Domains](/core/networking/domains). Deploy and verify [#deploy-and-verify] Select **Deploy**. Open the domain and verify a document, asset, and client-side route used by the site. Nginx configuration [#nginx-configuration] Coolify provides a default Nginx configuration for the static image. Open **General**, generate the configuration, and edit it only when the site needs behavior such as single-page application fallback, custom headers, or caching rules. Save the change and redeploy the application. Coolify copies the Nginx configuration into the static image during the image build, so a restart that reuses the existing image cannot apply the change. If the repository contains source files rather than final assets, [deploy with Nixpacks](/applications/builds/nixpacks/deploy) or use [Railpack](/applications/builds/railpack), choose **Static** in **Site type**, and set the build output as **Publish Directory**. # Choose a Deployment Method (/docs/applications/choose-deployment-method) Choose a deployment method [#choose-a-deployment-method] Choose the method that matches the input you already maintain. The deployment method determines what Coolify receives; the build method determines how Coolify creates images from Git source. Choose what you provide [#choose-what-you-provide] | You have | What Coolify does | Guide | | :----------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- | | A Git repository | Coolify checks out the selected commit and prepares the required images. | [Compare build methods](/applications/builds/overview) | | A Dockerfile without a Git repository | Coolify stores the Dockerfile, builds an image from its instructions, and creates the application container from that image. | [Use a Dockerfile](/applications/builds/dockerfile) | | A Git repository containing a Compose file | Coolify reads the definition, builds images for services with `build:`, pulls images for services with `image:`, and applies the definition with Docker Compose. | [Use Docker Compose](/applications/builds/docker-compose) | | An image already published to a registry | Coolify pulls the image, applies the saved runtime configuration, and creates a container from it. | [Deploy a Docker image](/applications/deployments/docker-image) | Use a Git repository [#use-a-git-repository] Connect the repository through a public URL, deploy key, or supported Git App, then select its **Build strategy**. * Use [Nixpacks](/applications/builds/nixpacks/overview) or [Railpack](/applications/builds/railpack) when automatic framework and command detection is sufficient. * Use [Static](/applications/builds/static) when the repository already contains the finished website files. * Use [Dockerfile](/applications/builds/dockerfile) when the repository defines one custom image. * Use [Docker Compose](/applications/builds/docker-compose) when the repository defines multiple services or Compose-owned runtime configuration. Read [Compare build methods](/applications/builds/overview) for the differences between these choices. Use a Dockerfile without Git [#use-a-dockerfile-without-git] Select **+ New > Dockerfile** when you want to paste a Dockerfile directly into Coolify without connecting a repository. This path stores the Dockerfile in Coolify and does not check out application source. A `COPY` instruction therefore cannot read files from a repository. Use the Git repository path when the image build needs project files. Use Docker Compose from Git [#use-docker-compose-from-git] Select **Docker Compose** as the **Build strategy** when a Git repository contains the Compose definition for an Application. The Compose file becomes the source of truth for the services it defines. Do not expect every standard application setting to override Compose-owned configuration. Selecting **+ New > Docker Compose Empty** creates a user-defined Service, not an Application. Use [Services](/services) when the Compose definition is not stored in Git. Use an existing Docker image [#use-an-existing-docker-image] Use a [Docker Image application](/applications/deployments/docker-image) when CI or another build system already publishes the image. Enter an image with a tag such as `ghcr.io/example/api:1.4.0` or a SHA256 digest. A digest identifies immutable image content; a mutable tag such as `latest` can resolve to different content during a later deployment. Verify the choice [#verify-the-choice] After creating the application: 1. Under **General**, confirm the repository and build method, stored Dockerfile, Compose location, or image reference used by the selected path. 2. For a non-Compose Application, set **Ports Exposes** to the port where the process listens. For Docker Compose, configure the domain and internal port on each public service. 3. Deploy the application. 4. Open **Deployment Logs** and confirm the operation succeeds. 5. Open the configured domain or test the exposed service. # Coming from Managed Platforms (/docs/applications/coming-from-managed-platforms) Coming from managed platforms [#coming-from-managed-platforms] Managed platforms such as Vercel combine a deployment control plane, build infrastructure, runtime infrastructure, networking, and platform defaults. Coolify provides the deployment control plane and coordinates Docker on servers you connect. This gives you more infrastructure control, but it also makes server capacity, networking, data persistence, and recovery explicit responsibilities. Map familiar concepts [#map-familiar-concepts] | Managed-platform concept | Coolify equivalent | | :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Project or application | A resource inside a Coolify project and environment | | Git integration | A [Git source](/applications/sources/overview), [deploy key](/applications/sources/deploy-keys), or [public repository](/applications/sources/public-repositories) | | Framework preset | [Nixpacks](/applications/builds/nixpacks/overview) or [Railpack](/applications/builds/railpack) detection, or explicit build commands | | Build image | A [Docker image](/core/docker-and-containers#images-and-containers) created on the deployment server or a [build server](/core/infrastructure/servers/build-servers) | | Serverless or managed runtime | A [Docker container](/applications/how-applications-work) running on a server connected to Coolify | | Production domain | A [resource domain](/core/networking/domains) routed by the Coolify Proxy on the deployment server | | Preview URL | A [preview deployment](/applications/deployments/preview-deployments) with its own generated or configured domain | | Environment variables | [Resource variables](/applications/configuration/environment-variables) with build-time, runtime, and preview scopes | | Persistent data | A [volume or bind mount](/core/persistent-storage/storage-mounts/overview), database, or external storage service | | Platform logs | [Deployment logs and runtime container logs](/applications/operations/overview#logs-and-terminal) | | Instant rollback | A [rollback](/applications/deployments/rollbacks) to an image still retained on the deployment server | What you must decide [#what-you-must-decide] Use this order to plan the Coolify deployment before moving production traffic. Choose where the application runs [#choose-where-the-application-runs] Select a [server](/core/infrastructure/servers/overview) with enough CPU, memory, disk, and network capacity. A self-hosted installation starts with a **localhost** server that can run both Coolify and deployed resources. Coolify Cloud requires a connected or provisioned server for deployed resources. Choose what Coolify deploys [#choose-what-coolify-deploys] [Choose a deployment method](/applications/choose-deployment-method) that matches what you want to deploy. For a Git repository, use Nixpacks or Railpack for automatic framework detection, or choose Static, Dockerfile, or Docker Compose. Use Docker Image when another system already publishes the image. Plan where data persists [#plan-where-data-persists] Identify uploads, generated files, and application state that must survive a deployment. Configure [persistent storage](/core/persistent-storage/storage-mounts/overview) or use an external data service instead of the writable container filesystem. Plan how traffic reaches the application [#plan-how-traffic-reaches-the-application] Identify the domain, DNS record, and internal port the application needs. The Coolify Proxy on the deployment server handles HTTP and HTTPS routing to that port. Plan how the application recovers [#plan-how-the-application-recovers] Decide how you will recover from a bad release, data loss, or server failure. A [rollback](/applications/deployments/rollbacks) can redeploy a retained application image, but it does not restore databases or persistent files. Keep separate backups for persistent data and document how to restore external dependencies. A safe migration sequence [#a-safe-migration-sequence] 1. Deploy the application to Coolify without changing production DNS. 2. Configure environment variables and external dependencies. 3. Add persistent storage where the application writes important files. 4. If the application provides a health endpoint, configure and verify a health check. 5. Test the Coolify deployment through a temporary or generated domain. 6. Point production DNS to the Coolify deployment server. 7. Monitor runtime logs and keep the previous platform available until the Coolify deployment is confirmed stable. Stop writes or use the database or storage system's supported migration process before transferring persistent data. Copying a live data directory can produce an inconsistent result. # Advanced (/docs/applications/configuration/advanced) Advanced settings [#advanced-settings] Open an application, then select **Advanced** in the application settings sidebar. These controls change build caching, deployment triggers, container names, proxy behavior, restart handling, logging, and GPU access. The available controls depend on the application's source and build method. A setting that does not apply is hidden. Settings available by application type [#settings-available-by-application-type] | Application type | Additional settings shown | | :------------------------- | :------------------------------------------------------------------------------------------------------------ | | Git-based application | Automatic deployments, submodules, Git LFS, and clone depth. Preview controls are on **Preview Deployments**. | | Docker Compose application | **Compose deployment** and **Predefined network**. GPU controls are hidden. | | Non-Compose application | GPU controls. | | Every application | Build, container name, proxy, shutdown, restart, and log-drain controls. | Build controls cache reuse, Docker build arguments, and commit metadata. Build cache [#build-cache] Under **Build cache**, choose **Rebuild from scratch every time** to prevent Coolify-generated builds from reusing Docker build cache on every deployment. Choose **Use Docker build cache** for normal deployments. Select **Force deploy (without cache)** instead when only the next deployment needs a clean generated build. A custom Docker Compose build command controls its own cache flags, so this setting cannot add or remove cache arguments from that command. *** Build arguments [#build-arguments] **Build arguments** defaults to **Inject build args automatically**. Coolify adds `ARG` instructions for application variables that are available during the build. Choose **Managed manually in Dockerfile** when the Dockerfile declares and manages every required `ARG` itself. This avoids duplicate injected instructions and gives the Dockerfile complete control over cache boundaries. *** Source commit availability [#source-commit-availability] Under **Source commit availability**, choose **Available during build** when the image build needs `SOURCE_COMMIT`, the selected Git commit hash. The default is **Runtime only (preserves cache)** so commits with otherwise identical inputs can reuse cached image layers. `SOURCE_COMMIT` remains available to the running container when it is excluded from the build. Read [Build cache](/applications/builds/overview#build-cache) before enabling it for every deployment. These settings appear only for applications connected to a Git repository. Auto Deploy [#auto-deploy] Under **Deployment**, **Auto deploy** set to **Deploy on push (webhooks)** allows supported Git webhook events to start a deployment. It is enabled by default, but the repository connection must still have a working webhook or provider integration. Choose **Manual deployments only** when deployments should start only from the Coolify dashboard, API, deploy webhook, or an external workflow. *** Preview deployments [#preview-deployments] Preview enablement and pull-request access are configured on **Preview Deployments** in the application settings sidebar. Select **Enable preview deployments**, then choose **Repository members only** or **Public (fork PRs allowed)** in **PR deployment access**. Public previews can run contributor-controlled code. Read [Preview deployments](/applications/deployments/preview-deployments) before changing access. *** Submodules [#submodules] Under **Git > Submodules**, choose **Clone submodules** when the selected repository commit depends on Git submodules. Coolify includes them during source checkout. The connected source or deploy key must be able to access every private submodule. For private submodules in the same GitHub user or organization, prefer a relative URL in `.gitmodules`: ```ini [submodule "prisma"] path = prisma url = ../prisma.git ``` The relative URL uses the authenticated parent-repository remote instead of starting a separate unauthenticated HTTPS clone. If checkout still fails, confirm that the GitHub App installation or deploy key can access both repositories. Changing only the submodule repository does not update the commit recorded by the parent repository. Commit the new submodule pointer in the parent repository before deploying it. *** LFS [#lfs] Under **Git LFS**, choose **Enabled** when the repository stores required files with Git Large File Storage. Coolify downloads the LFS-managed content during source checkout. Leave it disabled when the build does not need LFS objects. *** Shallow Clone [#shallow-clone] Under **Clone depth**, choose **Shallow clone (latest commit only)** to check out only the latest commit history with `--depth=1`. This can reduce clone time and transferred history for large repositories. Choose **Full history** when the build needs earlier commits, complete tags, or history-based versioning. Read [Automatic deployments](/applications/deployments/automatic-deployments) for provider webhook setup. Compose deployment [#compose-deployment] This setting appears only for Docker Compose applications. Coolify normally parses the Compose definition and adds the networking, labels, and other configuration it needs to manage the deployment. With **Compose deployment** set to **Raw (deploy file as-is)**, Coolify deploys the Compose definition as written. The definition must provide its own proxy labels, networking, and other required runtime configuration. Read [Raw Compose deployment](/applications/builds/docker-compose#raw-compose-deployment-for-an-application) before enabling it. *** Predefined network [#predefined-network] This setting appears only for Docker Compose applications. Under **Docker compose > Predefined network**, choose **Connect to predefined network** when services in the Compose application must communicate with resources attached to the selected Coolify destination network. Docker Compose services already receive a private network for communication within their own definition. Joining the predefined network is only needed for communication across Coolify resources, and service DNS names can change after joining it. Read [Compose networking](/applications/builds/docker-compose#compose-networking) before configuring another resource's hostname. Container settings control the runtime name assigned to a non-preview application container. Container naming [#container-naming] Under **Container > Container naming**, choose **Consistent name (no rolling updates)** to use the application UUID as the container name on every deployment. Docker cannot run the current and replacement containers with the same name. Enabling this setting prevents Coolify from starting the replacement beside the running container. Choose **Generated name (rolling updates)** when the application depends on [rolling updates](/applications/deployments/rolling-updates). *** Custom Container Name [#custom-container-name] **Custom container name** appears when consistent naming is selected. Enter a recognizable fixed name when another system must address the container by that exact runtime name. Coolify converts the value to slug format when you save it. The name must be unique among applications on the same deployment server. A custom name also disables rolling updates because the current and replacement containers cannot use it simultaneously. Choose generated naming to use deployment-specific names. Container name prefix [#container-name-prefix] With consistent naming disabled, set an optional **Container Name Prefix** to make generated names readable while retaining rolling updates. Coolify slugifies the prefix, limits it to 30 characters, and requires it to be unique per server. | Application | Generated name with prefix `shop-api` | | :-------------------- | :------------------------------------ | | Single container | `shop-api-20260908T141530` | | Compose service `web` | `web-shop-api-20260908T141530` | Without a prefix, generated names use the application UUID followed by the timestamp. Old timestamp suffixes remain recognized. In consistent mode, a custom name produces `shop-api` for a single container or `web-shop-api` for the Compose service. The API field is `custom_container_name_prefix`. Setting `custom_internal_name` enables consistent naming; combining it with `is_consistent_container_name_enabled: false` returns `422`. Applications whose stored custom names were previously applied despite consistent naming being disabled are migrated to consistent mode to preserve their names. Proxy settings change labels generated by Coolify Proxy for the application's configured domains. HTTPS redirection [#https-redirection] Open **Domains** and choose **Enabled** in **Redirect HTTP to HTTPS**. This control appears when an HTTPS domain is configured and labels are managed by Coolify. The domain, DNS, and certificate must already support HTTPS. Selecting this option does not convert an HTTP-only domain into an HTTPS domain. *** Gzip compression [#gzip-compression] Choosing **Enabled** in **Gzip compression** allows Coolify Proxy to compress supported responses. Choose **Disabled** when the application already compresses responses or when a streaming or binary workload should not be compressed by the proxy. *** Path prefixes [#path-prefixes] Under **Path prefixes**, choose **Strip prefixes** when the application is exposed under a path but should receive the request without that routing prefix. For example, a request to `/api/users` can be forwarded to the container as `/users`. Test application routes after changing this setting because the application may generate links or redirects that still include the original prefix. Proxy controls are unavailable when **General > Container labels > Label management** is set to **Managed manually (edit labels yourself)**. In manual-label mode, change the equivalent proxy labels yourself. Operations controls graceful shutdown, crash restart limits, log forwarding, and when changes reach the running container. Stop Grace Period (seconds) [#stop-grace-period-seconds] Coolify waits for the application process to stop gracefully during rolling updates, manual stops, and restarts. **Accepted values:** * Leave the field empty to use the 30-second default. * Enter a whole number from `1` to `3600` seconds. Give the process enough time to finish in-flight work after receiving its shutdown signal. Increasing the value does not fix a process that ignores the signal. *** Max Restart Count [#max-restart-count] **Max Restart Count** limits how many times Coolify automatically restarts a crashing application before stopping it and sending a notification. **Accepted values:** * The default is `10` restarts. * Enter `0` to disable the limit. * Enter a positive whole number to set another limit. *** Apply changes [#apply-changes] Most dropdowns, **Stop grace period (seconds)**, and **Max restart count** save immediately. Edited container-name fields and GPU configuration use **Save changes**. Redeploy or restart the application after changing a setting that affects the image, container name, proxy labels, network, shutdown behavior, logging, or GPU access. Log drain [#log-drain] Under **Logs > Log drain**, choose **Send logs to the log drain endpoint** to forward application logs to the log-drain endpoint configured on the deployment server. Coolify rejects the setting when log draining is not enabled on that server. Follow [Log drains](/core/observability/log-drains/overview) before enabling it for the application. GPU controls appear only for non-Compose applications. The deployment server must already have working GPU drivers and a container runtime configured for GPU access. GPU access [#gpu-access] Under **GPU > GPU access**, choose **Enabled** to add GPU access to the application container. Additional GPU fields appear after it is enabled. *** GPU Driver [#gpu-driver] **GPU driver** selects the container runtime's GPU driver. Enter the driver configured on the deployment server. *** GPU Count and device IDs [#gpu-count-and-device-ids] Use **GPU count** to request a number of GPUs. Leave it empty to make all available GPUs accessible to the container. Use **GPU device ids** to select specific devices as a comma-separated list, such as `0,2`. Do not set **GPU count** and **GPU device ids** together. Coolify rejects the configuration and clears both values when both are provided. *** GPU Options [#gpu-options] **GPU options** accepts additional driver-specific runtime options. Add only options supported by the GPU driver and container runtime installed on the deployment server. Select **Save changes**, then redeploy or restart the application and verify GPU access from inside the container. # Environment Variables (/docs/applications/configuration/environment-variables) Environment variables [#environment-variables] Application environment variables pass configuration to the image build, the running container, or both. Open the application, then select **Environment Variables**. Production and preview variables appear in separate labelled sections. Use the preview section for values that should differ, such as a preview database or callback URL. Add variables [#add-variables] Use **Normal view** to configure one variable at a time. Select **Add**, enter **Name** and **Value**, choose its scope and value settings, then select **Add variable**. Select a variable name or its edit icon to change it, then select **Update variable**. Use **Developer view** to paste or edit multiple values in `.env` format: ```dotenv NODE_ENV=production LOG_LEVEL=info API_URL=https://api.example.com ``` Lines beginning with `#` are ignored. Saving Developer view creates, updates, and removes entries to match its contents. Locked secrets and multiline values cannot be edited in Developer view. Change those entries in Normal view. Build and runtime scope [#build-and-runtime-scope] **Build time** and **Runtime** are independent dropdowns. New variables default to **Available during build** and **Available in the container**. | Setting | Image build | Running container | | :---------------- | :-----------: | :---------------: | | Build and runtime | Available | Available | | Build only | Available | Not available | | Runtime only | Not available | Available | Set **Build time** to **Not available during build** for a secret that the application only reads after the container starts. Traditional Docker build arguments can appear in image metadata. Set **Build secrets** to **Docker BuildKit secrets** for sensitive build-time values when the build server supports Docker BuildKit. If BuildKit is unavailable, Coolify falls back to build arguments. Example: private npm registry [#example-private-npm-registry] Authenticate to a private npm registry during the build with a build variable instead of committing a token to the repository. 1. Add an `.npmrc` file to your project root: ```ini //registry.npmjs.org/:_authToken=${NPM_TOKEN} ``` 2. Add `NPM_TOKEN` with **Build time** set to **Available during build** (the token is only needed during `npm install`), and set its value to your registry token. 3. Deploy the application. The build reads `NPM_TOKEN` and authenticates to the registry. Multiline and literal values [#multiline-and-literal-values] Set **Value type** to **Multiline** when a value contains line breaks, such as a private key, certificate, or configuration file. Set **Interpolation** to **Literal (keep $ characters as-is)** when characters such as `$` must remain unchanged. Without it, Coolify can expand references contained in the value. Multiline values are already treated literally. Shared variables [#shared-variables] Reference a team, project, environment, or server variable instead of copying the same value into every resource: ```sh {{environment.DATABASE_URL}} ``` Follow [Shared variables](/core/team/shared-variables) to create a value at the correct scope and assign it to an application variable. External secret managers [#external-secret-managers] Link Doppler, Infisical, or HashiCorp Vault and reference a remote value with `{{vault.KEY}}`. Follow [Use a secret manager](/integrations/security/using-secret-managers). Predefined application variables [#predefined-application-variables] Coolify makes deployment information available through predefined values. | Variable | Value | | :----------------------- | :------------------------------------------------- | | `COOLIFY_FQDN` | Application domain names. | | `COOLIFY_URL` | Application URLs. | | `COOLIFY_BRANCH` | Selected Git branch. | | `COOLIFY_RESOURCE_UUID` | Coolify resource identifier. | | `COOLIFY_CONTAINER_NAME` | Generated container name. | | `SOURCE_COMMIT` | Deployed Git commit. | | `PORT` | First exposed port when `PORT` is not already set. | | `HOST` | `0.0.0.0` when `HOST` is not already set. | Coolify excludes `SOURCE_COMMIT` from Docker builds by default to preserve cache reuse. Set **Advanced > Build > Source commit availability** to **Available during build** when the build needs it. Assign a predefined value to your own key when the application expects another name: ```dotenv APP_REVISION=$SOURCE_COMMIT ``` Docker Compose variables [#docker-compose-variables] Coolify detects variable references in a Compose definition and displays them as application variables: ```yaml services: api: environment: DATABASE_URL: ${DATABASE_URL} LOG_LEVEL: ${LOG_LEVEL:-info} API_KEY: ${API_KEY:?} ``` `${API_KEY:?}` marks the variable as required. Coolify blocks deployment while its value is empty. For generated stack values such as URLs, users, passwords, and random strings, read [Docker Compose](/applications/builds/docker-compose). Apply changes [#apply-changes] Save the variables, then redeploy or restart the application so Coolify recreates the runtime environment. Use a new deployment when build-time values changed. Use **Restart** when only runtime values changed. Source-based paths reuse an existing image when eligible; Docker Image pulls the saved image reference again. Names and copying values [#names-and-copying-values] New environment variable names must match `[A-Za-z_][A-Za-z0-9_.]*`: begin with a letter or underscore, then use letters, numbers, underscores, or dots. Existing invalid runtime-only names, such as `my-var`, deploy with a warning and suggested name. Invalid build-time names stop the image build. Use the copy button to copy a resolved value. Shared-variable and `$SERVICE_*` references resolve to their actual values. Locked variables have no copy button, and references to locked shared variables remain references rather than exposing the secret. # General (/docs/applications/configuration/general) General settings [#general-settings] Open an application, then select **General** in the application settings sidebar. This page contains the settings that determine what Coolify builds or pulls, where it finds source files, which container ports receive traffic, and how the resulting container starts. The controls change according to the application's source, **Build strategy**, and deployment destination. A setting that does not apply to the selected method is hidden rather than disabled. Settings available by deployment method [#settings-available-by-deployment-method] Use this table to identify which part of **General** applies to the application: | Deployment method | Main settings shown | | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Nixpacks or Railpack | Build commands, repository paths, static-site controls, publish directory, domains, registry output, network settings, and container labels. | | Static | Static server image, repository root, custom Nginx configuration, domains, registry output, network settings, and container labels. | | Dockerfile from Git | Repository root, Dockerfile path, optional build stage, domains, registry output, network settings, and container labels. | | Dockerfile without Git | The Dockerfile stored in Coolify, optional build stage, domains, registry output, network settings, and container labels. The **Build strategy** selector is not shown. | | Docker Compose from Git | Compose file paths, per-service domains, parsed Compose content, repository preservation, optional Compose commands, and label escaping. | | Docker Image | Image name, tag or hash, container options, domains, network settings, and container labels. The **Build strategy** selector is not shown. | Docker Compose applications do not use the single-container **Network**, **HTTP Basic Authentication**, or editable **Active labels** controls on this page. Configure ports, health checks, service environment entries, volumes, and labels in the Compose definition. General contains the application's identity and an **Access** summary linking to its domain configuration. Application details [#application-details] **Name** identifies the application throughout the Coolify dashboard. It is required. **Description** is optional and can record the workload's purpose, owner, or other team context. Use the resource menu in the top bar to navigate between applications in the active environment. *** Domains [#domains] Select **Domains** in the application settings sidebar, or use the domain-management action in **Access**. Add and edit individual domains there rather than entering a comma-separated list on General. Choose **Add domain**, then enter **Protocol**, **Domain**, optional internal **Port**, and optional **Path**. For Docker Compose applications, also choose the receiving **Service**. A domain port selects a port inside the container; it does not publish that port on the server. For example, HTTPS with domain `example.com` and port `3000` serves visitors at `https://example.com` while forwarding to container port `3000`. Edit a domain to set **www redirect** and **Search engine indexing**. The Domains page also provides **Redirect HTTP to HTTPS** when an HTTPS domain is configured. When labels are managed manually, configure routing in the labels instead. Read [Domains](/core/networking/domains) before changing production routing. Build contains the source, image, repository, and registry settings used to prepare the application. Build strategy [#build-strategy] **Build strategy** selects how Coolify prepares an application from Git source: * [Nixpacks](/applications/builds/nixpacks/overview) detects the codebase and generates an image build plan. * [Railpack](/applications/builds/railpack) detects the codebase and builds an image with Railpack. * [Static](/applications/builds/static) serves repository content through a static web server image. * [Dockerfile](/applications/builds/dockerfile) builds an image using a Dockerfile. * [Docker Compose](/applications/builds/docker-compose) builds or pulls the images required by the Compose services. The selector is unavailable for Docker Image applications and applications created from a Dockerfile stored directly in Coolify. Create another application when the deployment must use a different method. Coolify detects **Install Command**, **Build Command**, and **Start Command** from the codebase. Enter an override only when the detected command is unsuitable. When overriding a command, keep the corresponding Nixpacks or Railpack configuration consistent with the value entered in Coolify. The deployment log shows the generated build plan and the command that ran. **Base Directory** selects the repository directory Coolify treats as the application root. Use `/` for the repository root or a path such as `/apps/api` for a monorepo application. Under **Build pipeline**, choose **Static** in **Site type** when the build creates files that a web server should serve instead of starting a long-running application process. Then configure: * Choose **SPA (single-page application)** in **Site type** when client-side routes must fall back to the entry page. * **Publish Directory** with the build-output directory, such as `/dist` or `/build`. This field is required when static-site mode is enabled. * **Custom Nginx configuration** when the generated static-site configuration does not meet the application's routing or header requirements. The **Static** build pack serves repository files without running a framework build command. **Web server** selects the container image used to serve the files. The currently selectable image is `nginx:alpine`. **Base Directory** selects the repository directory that contains the files to serve. **Custom Nginx configuration** replaces the generated server configuration. **Generate default** overwrites the current custom value with the configuration Coolify generates for the selected static-site behavior. For a Git-based application, Coolify combines **Base Directory** and **Dockerfile Location** to find the Dockerfile: ```plaintext Base Directory: /apps/api Dockerfile Location: /docker/Dockerfile Resolved file: /apps/api/docker/Dockerfile ``` Both paths begin with `/`. **Base Directory** also defines the build context available to `COPY` and `ADD` instructions. **Docker Build Stage Target** selects a named stage from a multi-stage Dockerfile. Leave it empty to build the Dockerfile's final stage. For an application created with **Dockerfile** without Git, the editable **Dockerfile** field contains the definition stored by Coolify. Repository path controls do not appear because no repository is connected. Read [Dockerfile deployments](/applications/builds/dockerfile) for build-context examples and the complete deployment flow. Coolify combines **Base Directory** and **Docker Compose Location** to locate the Compose file. Both paths begin with `/`: ```plaintext Base Directory: /deploy Docker Compose Location: /compose.yaml Resolved file: /deploy/compose.yaml ``` **Load Compose File** parses the repository file. After it has been loaded, **Reload Compose File** reads it again. Coolify then shows: * **Docker Compose Content (raw)** for the definition read from the repository. * **Docker Compose Content** for the deployable definition after Coolify adds its managed configuration. * **Show Raw Compose** or **Show Deployable Compose** to switch between them. These fields are read-only. Edit the Compose file in the Git repository, then reload it in Coolify. Enable **Preserve repository during deployment** when the repository content under **Base Directory** must also be copied into the deployment directory. This is useful when the Compose definition uses repository-relative files at runtime rather than only during an image build. **Custom Build Command** and **Custom Start Command** replace the generated Compose commands. Coolify adds the Compose-file and environment-file flags unless the command already supplies its own `-f` or `--env-file` flag. When an override is entered, **Final Build Command (Preview)** or **Final Start Command (Preview)** shows the command Coolify will execute. Keep custom command paths relative to **Base Directory** and use the same Compose file that Coolify parsed. Otherwise, generated domains, labels, and variables may not match the deployed services. Read [Docker Compose deployments](/applications/builds/docker-compose) for environment-variable patterns, storage, service networking, and raw deployments. **Image** contains the registry image name, such as `nginx` or `ghcr.io/example/api`. **Tag** accepts a tag such as `latest` or `v1.2.3`, or an image hash in the format shown by Coolify. Pin a version or digest when deployments must use an immutable image instead of whatever a moving tag references. **Custom Docker Options** adds supported options to the command used to start the container. Use [Custom Docker options](/applications/builds/custom-docker-options) to check supported flags before adding capabilities, devices, mounts, or runtime settings. *** Build servers and container options [#build-servers-and-container-options] **Builder selection** appears for non-Compose source builds. Choose a dedicated builder only after configuring another server as a [build server](/core/infrastructure/servers/build-servers). Coolify builds the image there, pushes it to the configured registry, and the deployment server pulls it. A registry image name is required for this path. **Custom Docker Options** also appears for Nixpacks, Railpack, Static, Dockerfile, and Docker Image applications. The options affect how Coolify starts the container; they do not change the image build. Docker Compose applications define equivalent runtime configuration in the Compose file. *** Git repository settings [#git-repository-settings] **Watch Paths** is available when you select a repository through a GitHub App or GitLab source integration. It is not available for applications created from a public repository URL or a deploy key. The setting filters which changed paths can start a webhook deployment. Patterns are evaluated in order, support `*`, `**`, `?`, and `!`, and use the last matching pattern. Read [Limit deployments by changed paths](/applications/deployments/automatic-deployments#limit-deployments-by-changed-paths) before adding exclusions. *** Docker registry [#docker-registry] The **Container image** section does not appear for Docker Compose applications because each service's `image:` or `build:` configuration belongs in the Compose definition. For a Docker Image application, **Image** and **Tag** identify the image Coolify pulls. For a source build, **Image** names an image Coolify can push after building it. Include the registry hostname for a private registry, for example `ghcr.io/example/api`. If **Tag** is set, Coolify pushes that tag in addition to the commit-based tag. An output image name is required when the application uses Docker Swarm, additional deployment servers, or a separate build server. Those destinations must be able to pull the built image from a registry. Read [Docker registries](/applications/builds/docker-registries) for authentication and image naming. Network controls how Coolify Proxy and other containers reach a non-Compose application. Docker Compose applications define ports and service networking in the Compose file instead. Ports Exposes [#ports-exposes] **Ports Exposes** is a comma-separated list of ports used inside the container: ```plaintext 3000 3000,3001 ``` Coolify uses the first port for proxy routing when the domain does not specify another internal port. The first port also becomes the default health-check port when the health check does not configure one. If a `PORT` environment variable exists, Coolify reports whether its value is present in **Ports Exposes**. A domain cannot reach an HTTP application when no listening port is exposed. Leaving the field empty is valid for a worker, bot, or scheduled process that does not receive HTTP traffic. The field is read-only for static applications because Coolify selects the static server port. It also becomes read-only when manual container-label editing is enabled. *** Port Mappings [#port-mappings] **Port Mappings** publishes a container port directly on an interface of the deployment server. Use `host:container` entries separated by commas: ```plaintext 3000:3000,3002:3002 ``` Anyone who can reach the mapped server port can connect without going through the domain's proxy rules. A fixed host port also prevents Coolify from starting a replacement container beside the current container, so rolling updates are unavailable. **Port Mappings** is not shown for Docker Swarm destinations. *** Network Aliases [#network-aliases] **Network Aliases** gives the application container additional hostnames on its Docker network. Another container attached to the same network can use an alias instead of the generated container name. Use an alias when a dependent container expects a stable hostname that should not change between deployments. For example, set **Network Aliases** to `api.internal`, then configure a worker on the same Docker network to connect to: ```plaintext http://api.internal:3000 ``` Enter multiple aliases as a comma-separated list, such as `api.internal,api.local`. Keep each alias unique on the Docker network so it resolves to the intended container. An alias is private container networking. It does not create a public DNS record, configure a domain, or make the application reachable from a browser outside the Docker network. This field is not shown for Docker Swarm destinations. Read [Networking in Coolify](/core/networking-in-coolify) before depending on container DNS names across resources. Labels contains proxy authentication and the container metadata Coolify uses for routing and management. HTTP Basic Authentication [#http-basic-authentication] Under **Security**, choose **HTTP Basic Authentication** in **Authentication** to place a proxy username and password in front of a non-Compose application. Enter **Username** and **Password**, then redeploy or restart the application so the proxy configuration is refreshed. For Docker Compose, define the required proxy middleware through the Compose labels instead of this control. *** Container labels [#container-labels] Coolify normally generates **Active labels** for domain routing and other managed container behavior. With **Label management** set to **Managed by Coolify (auto-generated)**: * the label editor is read-only * **Domains**, **www redirect**, and **Ports Exposes** remain the primary controls * Coolify regenerates the corresponding labels when configuration changes Choose **Managed manually (edit labels yourself)** in **Label management** only when you need to own the complete label configuration. In manual mode: * **Active labels** becomes editable * **Domains**, **www redirect**, and **Ports Exposes** become read-only * Coolify does not repair incomplete proxy labels when the container is recreated Before switching to manual label management, copy the generated labels and understand the proxy configuration they implement. Missing or invalid routing labels can make the application unreachable after a restart or deployment. Choosing **Managed by Coolify (auto-generated)** restores Coolify's generated labels. **Reset to defaults** also replaces all custom proxy labels with the current Coolify defaults. Choose **Escape special characters ($ becomes $$)** in **Special characters** to convert characters such as `$` to their escaped form before the labels are stored. Choose **Keep unescaped (allow env variables)** when a label intentionally contains an environment-variable reference that the container platform must expand. Docker Compose applications do not show the standalone label editor. Define their labels in the Compose file; the **Escape special characters in labels?** setting still controls escaping. Deployment contains commands that run around a deployment and explains when saved changes reach the running container. Pre-deployment command [#pre-deployment-command] **Pre-deployment** runs through `sh -c` inside the currently running application container. Coolify runs it after preparing the deployment workspace and before building or starting the replacement application container. The pre-deployment phase ends when the command exits. Coolify continues when the command succeeds. A failure stops the deployment. On the first deployment, no application container exists yet, so Coolify skips the command. For Docker Compose applications, the adjacent **Container Name** selects the existing service container in which the command runs. Leave it empty only when the Compose application has one container. Use this command for work that must finish against the currently running version before it is replaced. It runs inside the container, not directly on the deployment server. *** Post-deployment command [#post-deployment-command] **Post-deployment** runs through `sh -c` inside the newly deployed application container after Coolify marks the deployment complete. The post-deployment phase ends when the command exits. A failure is written to the deployment log, but the deployment remains marked as successful because the new container has already been deployed. For Docker Compose applications, the adjacent **Container Name** selects the newly deployed service container in which the command runs. Leave it empty only when the Compose application has one container. Use this command for work that depends on the newly deployed version, such as warming an application cache. It runs inside the container, not directly on the deployment server. *** Apply changes [#apply-changes] Select **Save changes** for edited fields. Dropdowns that save immediately do not need this action. Redeploy after changing the build method, build commands, source paths, image, Dockerfile, Compose location, build-time values, or registry output. Restart or redeploy after changing runtime ports, labels, authentication, or deployment commands so Coolify recreates the container and its proxy configuration. Read [Build and deployment model](/core/build-deployment-model) for the image and container lifecycle. # Health Checks (/docs/applications/configuration/health-checks) Health checks [#health-checks] A health check tells Docker and Coolify whether an application container is ready. Health checks are optional, but they provide a readiness signal for deployments and rolling replacement. This routing behavior applies only when Coolify Proxy uses Traefik. When application health checks are enabled, Traefik removes unhealthy containers from routing. If every application container is unhealthy, Traefik can return `404 Not Found` or `No available server` instead of forwarding the request. Choose where to define the check [#choose-where-to-define-the-check] | Location | Use it for | Availability | | :--------------------------- | :---------------------------------------------------------------------------- | :--------------------------------------------------------------------- | | **Healthcheck** | Configure an HTTP request or a command without changing the image definition. | Nixpacks, Railpack, Static, Dockerfile, and Docker Image applications. | | Dockerfile `HEALTHCHECK` | Keep the check with the image and use it anywhere the image runs. | Any image built from a Dockerfile. | | Docker Compose `healthcheck` | Configure a separate check for each service in a Compose application. | Docker Compose applications and user-defined Services. | Docker Compose applications do not use the standard application **Healthcheck** page. Define the check in each service's Dockerfile or in the Compose definition. For a non-Compose Dockerfile application, Coolify detects the image's `HEALTHCHECK` and uses it instead of adding the health check configured in the dashboard. Remove the Dockerfile instruction and redeploy before switching that application to a Coolify-managed check. Configure a health check in Coolify [#configure-a-health-check-in-coolify] Open the application, select **Healthcheck**, then choose **HTTP** or **CMD** under **Check type**. Coolify runs dashboard-configured HTTP checks from inside the application container. The final application image must contain `curl` or `wget`; installing either command only on the deployment server is not enough. Without one of them, the HTTP check fails and Docker marks the container unhealthy. Choose HTTP when the application exposes an endpoint that reports whether it is ready to receive requests. Create a readiness endpoint [#create-a-readiness-endpoint] Add an endpoint such as `/health` to the application. It should return success only when the process is ready, remain lightweight, and avoid changing application data. Configure the request [#configure-the-request] Enter: * **Method**: `GET` or `POST` * **Scheme**: `http` or `https` * **Host**: normally `localhost` * **Port**: the port used inside the container; when empty, Coolify uses the first value from **Ports Exposes** * **Path**: the readiness path, such as `/health` For a static application, Coolify uses port `80`. Verify the container has an HTTP client [#verify-the-container-has-an-http-client] Open the application's **Terminal** and confirm that the running container contains at least one supported client: ```sh command -v curl || command -v wget ``` Use `curl` when the check depends on the selected HTTP method. The generated `wget` fallback performs its normal request behavior. Test the endpoint [#test-the-endpoint] Open the application's **Terminal** and run the same internal request: ```sh curl --fail http://localhost:3000/health ``` Replace `3000` and `/health` with the values entered in the health-check form. The command should exit with code `0`. The generated HTTP check currently uses the `curl` or `wget` exit status to determine health. Although **Expected code** and **Expected response text** appear in the form, the generated check does not compare the response against those two fields. Choose CMD when a local process, file, socket, or dependency can provide a better readiness signal than an HTTP endpoint. Choose a command [#choose-a-command] Use a command that exists inside the application container and exits with code `0` only when the application is ready. For PostgreSQL tooling: ```sh pg_isready -U postgres ``` For a Node.js application with a health-check script included in the image: ```sh node healthcheck.js ``` Enter the command [#enter-the-command] Select **CMD**, then enter the command under **Command**. The command can contain letters, numbers, spaces, and safe argument characters. Shell operators and substitutions such as `;`, `|`, `&`, `$()`, `>`, and `<` are not allowed. Put multi-step logic in a script inside the image, then run that script from **Command**. Test the command [#test-the-command] Open the application's **Terminal**, run the exact command, then check its exit code: ```sh pg_isready -U postgres echo $? ``` The result must be `0` when the application is ready and non-zero when it is not ready. Configure timing [#configure-timing] These settings apply to both HTTP and CMD checks: | Setting | Behavior | | :------------------------- | :------------------------------------------------------------------------------------------------------ | | **Interval (seconds)** | Time between health-check attempts. Must be at least one second. | | **Timeout (seconds)** | Maximum time allowed for one attempt. Must be at least one second. | | **Retries** | Consecutive failed attempts required before Docker marks the container unhealthy. Must be at least one. | | **Start period (seconds)** | Startup period before failures count toward the retry limit. | Give slow-starting applications enough **Start period (seconds)** to complete migrations, cache loading, or other required initialization. Save and enable the check [#save-and-enable-the-check] Select **Save changes**, then select **Enable** and confirm **Enable healthcheck**. If the application is already running, restart or redeploy it so Coolify recreates the container with the health-check configuration. Disabling a check also requires the container configuration to be recreated before Docker stops running it. Define the check with the application [#define-the-check-with-the-application] Keep a health check in the Docker configuration when it should travel with the image or Compose service instead of being owned by one Coolify application. Add a `HEALTHCHECK` instruction after installing the command used by the check: ```dockerfile FROM node:22-alpine RUN apk add --no-cache curl WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY . . EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD curl --fail http://localhost:3000/health || exit 1 CMD ["npm", "start"] ``` The command runs inside containers created from the image. It must use the internal listening port, and every binary referenced by `HEALTHCHECK` must be installed in the final image stage. For a non-Compose Dockerfile application, Coolify detects this instruction and does not add its dashboard-configured health check to the generated container definition. Add `healthcheck` to each service that needs a readiness signal: ```yaml services: api: build: . expose: - "3000" healthcheck: test: ["CMD", "curl", "--fail", "http://localhost:3000/health"] interval: 30s timeout: 5s retries: 3 start_period: 20s worker: build: ./worker healthcheck: test: ["CMD", "node", "healthcheck.js"] interval: 30s timeout: 5s retries: 3 start_period: 10s ``` Each command runs inside its own service container. The `api` image must contain `curl`, and the `worker` image must contain `healthcheck.js` at the working-directory path used by the command. A Compose `healthcheck` overrides the image's Dockerfile `HEALTHCHECK` for that service. Omit the Compose block when the service should inherit the check from its image. Read [Docker Compose health checks](/applications/builds/docker-compose#health-checks) for Compose-specific behavior, including one-time services. Health checks and rolling updates [#health-checks-and-rolling-updates] During an application-level rolling update, a health check lets Coolify wait for the new container before removing the currently running container. If the replacement fails its check, Coolify can remove it and keep the healthy version running. Rolling replacement also depends on container naming, networking, and port settings. Read [Rolling updates](/applications/deployments/rolling-updates) before depending on zero-downtime replacement. Troubleshoot a failed check [#troubleshoot-a-failed-check] 1. Open the application's **Terminal**. 2. Run the same request or command used by the health check. 3. Confirm the binary exists inside the container. 4. Confirm the check uses the internal container port rather than a public or host-mapped port. 5. Inspect **Runtime Logs** for startup or dependency failures. Follow [No available server](/troubleshoot/applications/no-available-server) when Traefik has no healthy target. # Overview (/docs/applications/configuration/overview) Configure an application [#configure-an-application] Open an application and use its settings sidebar to change how Coolify prepares its images, starts its containers, exposes traffic, and operates the workload. The available pages depend on the application type and destination. For example, **Git Source** appears only for Git-based applications, **Swarm** appears only for a Docker Swarm destination, and the application **Healthcheck** page is not used for Docker Compose. Use **General** for build, image, and port settings, and **Domains** for public routing. Use the remaining configuration pages for environment variables, storage, source authentication, automation, health, limits, and operations. *** Configuration pages [#configuration-pages] | Configuration page | What it controls | Guide | | :------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | **General** | Application identity, build strategy, access summary, image settings, ports, container labels, and deployment commands. | [Review General settings](/applications/configuration/general) | | **Domains** | Public domains, target ports, paths, redirects, and indexing. | [Configure domains](/core/networking/domains) | | **Advanced** | Build cache, container naming, automatic deployments, Git clone options, proxy behavior, restart limits, log drains, and GPU access. | [Review Advanced settings](/applications/configuration/advanced) | | **Swarm** | Docker Swarm service settings for applications deployed to a Swarm destination. | [Configure Docker Swarm](/core/infrastructure/scaling/docker-swarm) | | **Environment Variables** | Build-time and runtime values passed to the application. | [Configure environment variables](/applications/configuration/environment-variables) | | **Persistent Storage** | Volume, directory, and file mounts attached outside the replaceable container filesystem. | [Configure application persistent storage](/applications/configuration/persistent-storage) | | **Deployment Logs** | Build and deployment history and output. | [Deployment overview](/applications/deployments/overview) | | **Runtime Logs** | Output from the running application containers. | [Observability overview](/core/observability/monitoring/overview) | | **Git Source** | The connected Git source or deploy key for a Git-based application. | [Configure a source](/applications/sources/overview) | | **Servers** | The servers selected to run the application. | [Configure multi-server deployments](/core/infrastructure/scaling/multi-server-deployments) | | **Scheduled Tasks** | Commands that Coolify runs inside the application container on a schedule. | [Configure application scheduled tasks](/applications/operations/scheduled-tasks) | | **Webhooks** | Authenticated deployment webhooks and manual Git-provider webhooks. | [Use deploy webhooks](/core/automation/deploy-webhooks)
[Configure manual Git webhooks](/applications/deployments/manual-webhooks) | | **Preview Deployments** | Pull-request or merge-request environments and manual preview deployments. | [Configure preview deployments](/applications/deployments/preview-deployments) | | **Healthcheck** | HTTP or command checks used to determine whether a non-Compose application is healthy. | [Configure health checks](/applications/configuration/health-checks) | | **Rollback** | Previously built images that are still available for deployment. | [Roll back an application](/applications/deployments/rollbacks) | | **Resource Limits** | CPU and memory limits applied to the application containers. | [Configure resource limits](/applications/configuration/resource-limits) | | **Resource Operations** | Clone the application to another destination or move it between projects and environments. | [Clone or move an application](/applications/operations/resource-operations) | | **Metrics** | Container metrics collection and display. | [Monitor resource metrics](/core/observability/monitoring/metrics) | | **Tags** | Team-level labels used to organize resources. | [Organize resources with tags](/core/automation/tags/overview) | | **Danger Zone** | Destructive actions, including deleting the application. | [Delete an application](/applications/operations/danger-zone) | Apply configuration changes [#apply-configuration-changes] Saving a setting updates the stored configuration. It does not necessarily replace the running container immediately. Deploy or restart the application after changing settings that affect its container, including environment variables, storage, health checks, ports, networks, and resource limits. Build configuration changes require a deployment that creates or reuses an image. Use: * **Deploy** for the first deployment * **Redeploy** to run the deployment flow again * **Restart** to recreate the runtime through the deployment queue; source-based paths reuse an existing image when eligible, while Docker Image pulls the saved image reference again * **Force deploy (without cache)** to disable cache for a Coolify-generated source build; custom Docker Compose build commands control their own cache flags Read [Build and deployment model](/core/build-deployment-model) for the difference between image preparation and container replacement. Related configuration guides [#related-configuration-guides] Use the application settings filter to find pages, including nested settings such as **Advanced > Proxy**. Sidebar groups collapse, with the active page’s group open. # Persistent Storage (/docs/applications/configuration/persistent-storage) Configure persistent storage [#configure-persistent-storage] Application containers are replaceable. Data written only to a container filesystem can disappear when Coolify redeploys or removes that container. Use **Persistent Storage** to mount application data outside the container at the path where the application expects it. This page covers the application workflow. The [Persistent storage section in Core](/core/persistent-storage/storage-mounts/overview) explains volume, bind, directory, file, host-file, permissions, and backup behavior in detail. Understand the two paths [#understand-the-two-paths] Every mount connects: * a storage location on the deployment server * a **Destination Path** inside the application container For example, if the application writes uploads to `/app/uploads`, the mount's **Destination Path** must be `/app/uploads`. Only data written under that destination path is persistent. | Coolify choice | Use it when | | :------------------ | :--------------------------------------------------------------------------------------------------------------------- | | **Volume Mount** | Docker should manage the storage location. Add a **Source Path** only when the volume must use a specific server path. | | **Directory Mount** | The application needs a specific directory on the deployment server. | | **File Mount** | The container needs one file whose contents Coolify manages. | | **Host File Mount** | The container needs an existing file at an exact path on the deployment server. | Read [Storage mount types](/core/persistent-storage/storage-mounts/overview#choose-a-storage-mount) before choosing a mount. Add a mount to an application [#add-a-mount-to-an-application] Open Persistent Storage [#open-persistent-storage] Open the application in its project and environment, select **Persistent Storage** in the resource sidebar. Choose the mount type [#choose-the-mount-type] Select **Add**, then choose **Volume Mount**, **Directory Mount**, **File Mount**, or **Host File Mount**. If you are not sure which type to use, read [Storage mount types](/core/persistent-storage/storage-mounts/overview#choose-a-storage-mount) to compare how each one works. Enter the source and destination [#enter-the-source-and-destination] Enter the source location or file content required by the selected mount. Enter the exact **Destination Path** used by the application inside the container. For a volume or directory that must be copied between servers, record the source name or path. You will need it for a [migration](/applications/operations/migrate-between-instances) or backup restore. Save and apply the mount [#save-and-apply-the-mount] Save the mount, then redeploy or restart the application so the container starts with the new mount. Verify that the application can read and write the expected data before relying on the mount. Compose applications [#compose-applications] For a Docker Compose application, the Compose file is the source of truth for volume and bind-mount definitions. Define or change the mount in the Compose file, then reload the Compose configuration. Coolify displays parsed mounts but does not provide the same mount editor for Compose services. Important boundaries [#important-boundaries] * A mount does not recover data that was already written to a removed container. * Storage is local to the deployment server; connecting another server to Coolify does not make the mount shared. * The container user must have permission to read and write the mounted destination. * Do not share a writable directory between containers unless the application supports concurrent access and file locking. * Persistent storage is not a backup. Use [Storage mount backups](/core/persistent-storage/storage-mounts/backups) for eligible volume and directory mounts, and test the restore procedure separately. Continue with the Core guides [#continue-with-the-core-guides] * [Volume mounts](/core/persistent-storage/storage-mounts/volume-mounts) * [Bind mounts](/core/persistent-storage/storage-mounts/bind-mounts) * [File mounts](/core/persistent-storage/storage-mounts/file-mounts) * [Storage mount backups](/core/persistent-storage/storage-mounts/backups) # Resource Limits (/docs/applications/configuration/resource-limits) Resource limits [#resource-limits] Open an application, then select **Resource Limits** to restrict the CPU and memory available to its containers. **CPU limit** and the memory-limit fields use `0` for no configured limit. Other fields have their own defaults. Start with measured application usage rather than choosing the lowest possible value. CPU limits [#cpu-limits] | Setting | Accepted value | Default | Behavior | | :------------- | :----------------------------------------------- | :------ | :------------------------------------------------------------------------------- | | **CPU limit** | A whole or decimal number, such as `2` or `0.5`. | `0` | Sets the maximum CPU capacity. `0` allows the container to use all CPUs. | | **CPU set** | CPU numbers or ranges, such as `0-2` or `0,1,3`. | Empty | Restricts the container to selected CPU cores. Empty allows all CPU cores. | | **CPU weight** | A whole number of `0` or greater. | `1024` | Sets the container's relative CPU priority when containers compete for CPU time. | **CPU weight** does not reserve CPU capacity. It changes how Docker shares available CPU time during contention. Memory limits [#memory-limits] Memory fields accept `0` or a whole number followed by `b`, `k`, `m`, or `g`. The unit is case-insensitive: ```plaintext 256m 1g ``` | Setting | Accepted value | Default | Behavior | | :------------------------ | :-------------------------------- | :------ | :------------------------------------------------------------------------------------- | | **Memory reservation** | A memory value. | `0` | Sets the memory reservation Docker considers when the server is under memory pressure. | | **Swappiness** | A whole number from `0` to `100`. | `60` | Controls how readily the container's anonymous memory pages can be swapped. | | **Memory limit** | A memory value. | `0` | Sets the hard memory limit for the container. | | **Memory and swap limit** | A memory value. | `0` | Sets the total memory and swap available to the container. | A hard memory limit that is lower than the application's working set can cause Docker to terminate the process for running out of memory. A low CPU limit can make health checks time out during load. Apply and verify [#apply-and-verify] Select **Save changes**, then redeploy or restart the application so Coolify recreates its containers with the new limits. After the application starts: 1. Open **Metrics** and confirm CPU and memory usage stays below the configured limits. 2. Open **Runtime Logs** and check for out-of-memory exits, repeated restarts, or health-check failures. 3. Send representative traffic to the application and confirm response times remain acceptable. Read [Resource metrics](/core/observability/monitoring/metrics) to enable and inspect container metrics. # Automatic Deployments (/docs/applications/deployments/automatic-deployments) Automatic deployments [#automatic-deployments] Coolify can start a deployment when a Git provider reports a repository change or when an external workflow sends an authenticated deployment request. Choose the trigger that matches how the application source is connected: Use this method when the application was created by selecting a repository through a [GitHub App](/applications/sources/github/app) or [GitLab source integration](/applications/sources/gitlab). The integration receives provider events for Coolify, so you do not need to copy a manual Git webhook URL. Enable automatic deployments [#enable-automatic-deployments] Open the application, select **Advanced > Deployment**, then choose **Deploy on push (webhooks)** in **Auto deploy**. Push to the configured branch [#push-to-the-configured-branch] Push a commit to the branch selected for the application. A push to another branch does not update the production application unless that branch is configured for a preview or another application. Verify the deployment [#verify-the-deployment] Open **Deployment Logs** and confirm a webhook deployment appears for the pushed commit. If no deployment appears, inspect the provider integration and confirm the application still has access to the repository. Use this method for an application created from a public repository URL or **Private Repository (with deploy key)**. These source types can clone the repository but do not automatically configure provider events. Add a manual Git webhook so the provider can notify Coolify. Copy the provider webhook URL [#copy-the-provider-webhook-url] Open the application, select **Webhooks**, then copy the URL for the repository provider under **Manual Git webhooks**. Configure the secret [#configure-the-secret] Enter a long random value in the matching **Webhook secret** field and select **Save changes**. Create the webhook in the repository provider with the copied Coolify URL and the same secret. Do not reuse an account password, API token, or deploy key. Select repository events [#select-repository-events] Enable the provider's push event. Add pull-request or merge-request events only when the application also uses preview deployments. Follow [Manual Git webhooks](/applications/deployments/manual-webhooks) for provider-specific event names and delivery settings. Enable and verify automatic deployments [#enable-and-verify-automatic-deployments] Open **Advanced > Deployment**, choose **Deploy on push (webhooks)** in **Auto deploy**, then push a commit to the configured branch. Open **Deployment Logs** and confirm a webhook deployment appears. Use this method when CI should run tests, approvals, or an external image build before it tells Coolify to deploy. The authenticated **Deploy Webhook** starts a deployment directly. **Auto deploy** does not need to be set to deploy on push for this method. Create an API token [#create-an-api-token] Create a Coolify [API token](/core/security/credentials/api-tokens) with permission to deploy the application. Copy the deploy webhook [#copy-the-deploy-webhook] Open the application, select **Webhooks**, then copy **Deploy webhook URL**. Store the webhook URL and API token as secrets in the external CI system. Call Coolify after CI succeeds [#call-coolify-after-ci-succeeds] Add the request after the workflow's tests, build, or approval steps: ```sh curl --fail --request POST "$COOLIFY_WEBHOOK" \ --header "Authorization: Bearer $COOLIFY_TOKEN" ``` The [GitHub Actions workflow](/applications/sources/github/actions#add-the-github-actions-workflow) shows the same authentication pattern in a complete example. Verify the deployment [#verify-the-deployment-1] Run the workflow, then open **Deployment Logs** and confirm Coolify received the authenticated request. If the request fails, inspect the CI response and confirm that the webhook URL and token were stored without extra whitespace. Limit deployments by changed paths [#limit-deployments-by-changed-paths] Use **Watch Paths** under **General > Build** when a monorepo should deploy only after matching files change. Patterns are evaluated in order and support `*`, `**`, `?`, and negation with `!`. The last matching pattern wins. For example: ```sh apps/api/** packages/shared/** !apps/api/**/*.md ``` Watch paths filter Git provider webhook events that include changed-file information. They do not block deployments started manually from the dashboard or through the authenticated **Deploy Webhook**. Test the patterns with a documentation-only commit before relying on them for production automation. Disable automatic Git deployments [#disable-automatic-git-deployments] Choose **Manual deployments only** under **Advanced > Deployment > Auto deploy** to keep the source connection while ignoring automatic commit deployments from Git provider events. You can still select **Deploy** or **Redeploy**, or call the authenticated **Deploy Webhook** from an external workflow. # Docker Image (/docs/applications/deployments/docker-image) Deploy a Docker image [#deploy-a-docker-image] Use **Docker Image** when a registry already contains the application image you want to deploy. Coolify pulls the selected image on the deployment server, applies the application's runtime configuration, and starts the container. It does not clone a repository or build an image for this deployment type. When to use Docker Image [#when-to-use-docker-image] Choose Docker Image when: * a CI system already builds and publishes the application image * you want to deploy a public image from Docker Hub or another registry * you have a versioned image from which Coolify should create the application container * you want to deploy by tag or immutable SHA256 digest Use [Dockerfile](/applications/builds/dockerfile) when Coolify should build an image from instructions you control. Use [Docker Compose](/applications/builds/docker-compose) when one definition must manage several services. Before you start [#before-you-start] Make sure you have: * the complete image name, such as `ghcr.io/example/api` * a tag or SHA256 digest from the registry or image publisher * the internal port where the image's process listens * registry credentials on the deployment server when the image is private Follow [Docker registry authentication](/applications/builds/docker-registries#authenticate-a-private-registry) before deploying a private image. Authenticate every server that must pull the image. Choose a tag or digest [#choose-a-tag-or-digest] | Reference | Example | Use it when | | :------------ | :------------------------------------------------- | :------------------------------------------------------------------------------- | | Tag | `ghcr.io/example/api:1.4.0` | The registry publishes recognizable release versions. | | Mutable tag | `ghcr.io/example/api:latest` | You accept that another image can later replace the content behind the same tag. | | SHA256 digest | `ghcr.io/example/api@sha256:<64-character-digest>` | The deployment must identify fixed image content. | If you leave both **Tag** and **SHA256 Digest** empty, Coolify uses `latest`. A mutable tag can resolve to different image content during a later deployment. Use a version tag when your registry does not rewrite release tags. Use a digest when the deployment must always pull the same image content. Deploy a Docker image [#deploy-a-docker-image-1] Select Docker Image [#select-docker-image] Open a project and environment, select **+ New**, then select **Docker Image**. Enter the image reference [#enter-the-image-reference] Enter the image repository under **Image Name**. You can paste a complete reference such as: ```sh ghcr.io/example/api:1.4.0 ``` Coolify separates a pasted tag or digest into the matching field. Alternatively, enter the repository name and complete either **Tag (optional)** or **SHA256 Digest (optional)**. Do not enter both. When using the separate digest field, enter only the 64-character hexadecimal value without the `sha256:` prefix. Select **Save** to create the application. Configure the runtime [#configure-the-runtime] Open **General** and set **Ports Exposes** to the internal port where the image's process listens. Docker Image applications start with port `80`; replace it when the image listens on another port. Add the required domain, runtime environment variables, persistent storage, health check, and resource limits. These settings apply when Coolify starts the container; they do not change the image. Deploy and verify [#deploy-and-verify] Select **Deploy**, then open **Deployment Logs** and inspect the operation log. Confirm that Coolify pulls the intended image reference, starts the container, and reports a successful deployment. Open the application logs and configured domain to verify that the process listens on the expected port. Change the deployed image [#change-the-deployed-image] Open **General > Docker Registry**. * **Docker Image** contains the registry and repository name. * **Docker Image Tag or Hash** contains the selected tag or a digest stored as `sha256-<64-character-digest>`. Save the new value, then select **Redeploy**. Coolify pulls the selected image before applying the replacement. Redeploying the same mutable tag pulls the image currently published under that tag. A digest continues to identify the same image content. **Restart** also pulls the saved image reference again. If the application uses a mutable tag, a restart can deploy different image content even when only runtime configuration changed. What Docker Image skips [#what-docker-image-skips] A Docker Image application does not use: * a Git source or deploy key * Nixpacks, Railpack, Static, Dockerfile, or Docker Compose builds * install, build, or start command detection * automatic Git deployments The image supplies its filesystem and default process. Coolify still manages runtime environment variables, storage, networks, domains, health checks, logs, deployment history, previews created from image tags, and supported replacement behavior. Continue with [Docker registries](/applications/builds/docker-registries) for private registry access, [Preview deployments](/applications/deployments/preview-deployments) for tag-based previews, and [Rolling updates](/applications/deployments/rolling-updates) for replacement requirements. # Manual Git Webhooks (/docs/applications/deployments/manual-webhooks) Manual Git webhooks [#manual-git-webhooks] A manual Git webhook lets GitHub, GitLab, Bitbucket, or Gitea notify Coolify when a repository changes. Use one for an application created from a public repository URL or **Private Repository (with deploy key)**. Applications connected through an official Git App receive provider events through that integration and do not need a manual Git webhook. **Deploy webhook URL** starts a deployment when an external workflow calls Coolify with an API token. It is not a repository webhook. Follow [Automatic deployments](/applications/deployments/automatic-deployments) and choose **External workflow** when CI should call Coolify directly. Choose the repository provider [#choose-the-repository-provider] Each provider uses its own URL and secret from **Webhooks > Manual Git Webhooks**. Configure only the provider that hosts the repository. New or changed secrets must contain at least 16 characters. Use the generator beside the secret field to create a random value, then save the same value at the Git provider. For production deployments, select the provider's push event and choose **Deploy on push (webhooks)** under **Advanced > Deployment > Auto deploy**. For [preview deployments](/applications/deployments/preview-deployments), also select the pull-request or merge-request events shown below. Enable automatic branch deployments [#enable-automatic-branch-deployments] Open the application, select **Advanced > Deployment**, then choose **Deploy on push (webhooks)** in **Auto deploy** if pushes to the configured branch should deploy automatically. Copy the GitHub webhook details [#copy-the-github-webhook-details] Open **Webhooks**. Enter a long random value in **Webhook secret** in the **GitHub** section, select **Save changes**, then copy the **GitHub** URL under **Manual Git webhooks**. Keep the secret private. GitHub must use the same value when it signs webhook deliveries. Add the webhook on GitHub [#add-the-webhook-on-github] Open the GitHub repository, select **Settings > Webhooks > Add webhook**, then enter: * **Payload URL:** the GitHub URL copied from Coolify * **Content type:** `application/json` or `application/x-www-form-urlencoded` * **Secret:** the value saved in Coolify Keep **Enable SSL verification** selected. Select the events [#select-the-events] Choose **Just the push event** for automatic deployments from the configured branch. If the application also uses previews, choose **Let me select individual events**, then select **Pushes** and **Pull requests**. Keep **Active** selected and select **Add webhook**. Verify the webhook [#verify-the-webhook] Push a commit to the application's configured branch. Open **Deployment Logs** in Coolify and confirm a webhook deployment appears. GitHub also shows the webhook and its recent deliveries under **Settings > Webhooks**. Copy the GitLab webhook details [#copy-the-gitlab-webhook-details] Open **Webhooks** in Coolify. Enter a long random value in **Webhook secret** in the **GitLab** section, select **Save changes**, then copy the **GitLab** URL. Add the webhook on GitLab [#add-the-webhook-on-gitlab] Open the GitLab project and select **Settings > Webhooks**. Paste the Coolify URL into **URL** and enter the same value in **Secret token**. Select the events [#select-the-events-1] Select **Push events** for automatic branch deployments. Also select **Merge request events** when the application uses preview deployments, then add the webhook. Enable and verify deployments [#enable-and-verify-deployments] Open **Advanced > Deployment** and choose **Deploy on push (webhooks)** in **Auto deploy** in Coolify, then push to the configured branch. Open **Deployment Logs** and confirm a webhook deployment appears. Copy the Bitbucket webhook details [#copy-the-bitbucket-webhook-details] Open **Webhooks** in Coolify. Enter a long random value in **Webhook secret** in the **Bitbucket** section, select **Save changes**, then copy the **Bitbucket** URL. Add the webhook on Bitbucket [#add-the-webhook-on-bitbucket] Open the Bitbucket repository and select **Repository settings > Webhooks > Add webhook**. Paste the Coolify URL and enter the same secret. Select the events [#select-the-events-2] Select **Repository push** for automatic branch deployments. For previews, also select these pull-request events: * **Created** * **Updated** * **Merged** * **Declined** Save the webhook. Enable and verify deployments [#enable-and-verify-deployments-1] Open **Advanced > Deployment** and choose **Deploy on push (webhooks)** in **Auto deploy** in Coolify, then push to the configured branch. Open **Deployment Logs** and confirm a webhook deployment appears. Copy the Gitea webhook details [#copy-the-gitea-webhook-details] Open **Webhooks** in Coolify. Enter a long random value in **Webhook secret** in the **Gitea** section, select **Save changes**, then copy the **Gitea** URL. Add the webhook on Gitea [#add-the-webhook-on-gitea] Open the Gitea repository and select **Settings > Webhooks > Add Webhook > Gitea**. Paste the Coolify URL into **Target URL** and enter the same secret. Select the events [#select-the-events-3] Select the **Push** event for automatic branch deployments. Also select the **Pull Request** event when the application uses preview deployments, then add the webhook. Enable and verify deployments [#enable-and-verify-deployments-2] Open **Advanced > Deployment** and choose **Deploy on push (webhooks)** in **Auto deploy** in Coolify, then push to the configured branch. Open **Deployment Logs** and confirm a webhook deployment appears. Troubleshoot a missing deployment [#troubleshoot-a-missing-deployment] Open the webhook's recent deliveries in the repository provider, then check: 1. the provider sent an event supported by Coolify 2. the delivery received a successful HTTP response 3. the provider secret exactly matches the saved Coolify secret 4. the Coolify webhook URL is reachable from the internet 5. **Auto deploy** under **Advanced > Deployment** is set to **Deploy on push (webhooks)** for a push event 6. the pushed branch matches the branch configured for the application A pull-request or merge-request event creates a preview only when **Preview Deployments** is enabled. Repeated distinct signature failures are throttled per client address, repository, and branch. Correctly signed deliveries remain accepted. Webhook responses do not reveal matching applications; verify deployment history instead. # Overview (/docs/applications/deployments/overview) Deploy applications [#deploy-applications] A deployment is a queued operation that prepares the required images and applies the application's runtime configuration on the selected server. The deployment can build images from source, [pull existing images](/applications/deployments/docker-image), or build and pull the images required by services in a Docker Compose definition. Docker creates and runs the resulting containers on your infrastructure. Read [Build and deployment model](/core/build-deployment-model) for the complete path from source to running containers. Start a deployment manually, from a Git event, or through automation. Use **Deployment Logs** to follow the queue, inspect the exact operation log, and verify the result. *** Start a deployment [#start-a-deployment] | Action | When to use it | | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Deploy** | Start the first deployment of a configured application. | | **Redeploy** | Run the normal deployment flow again for an existing application. | | **Restart** | Recreate the runtime through the deployment queue. Source-based paths reuse an existing image when eligible and can build when required. Docker Image pulls the saved image reference again. | | **Force deploy (without cache)** | Disable cache for a Coolify-generated source build. A custom Docker Compose build command controls its own cache flags. | | Git webhook | Deploy a new commit received from the connected repository. | | Deploy webhook or API | Start a deployment from an external CI system or automation. | A deployment request enters the queue. Coolify records whether it is queued, in progress, successful, failed, or cancelled. Inspect deployment history [#inspect-deployment-history] Open **Deployment Logs** on the application to see previous and active operations. Open one deployment to inspect its log. The log shows the selected source revision, image build or pull, generated configuration, and container actions. Use the first failing command as the starting point when a deployment does not complete. A failed source build does not replace the running application. Failures after the build can depend on the replacement path and health-check configuration. Choose the next deployment guide [#choose-the-next-deployment-guide] # Preview Deployments (/docs/applications/deployments/preview-deployments) Preview deployments [#preview-deployments] A preview deployment runs the code from a pull request or merge request separately from the production application. Each preview can use its own domain and environment variables without replacing the production deployment. Coolify deletes an automatically created preview after its pull request or merge request is closed or merged. Before enabling previews [#before-enabling-previews] Confirm that the application deploys successfully from its configured branch and that the deployment server has enough capacity to run production and preview containers at the same time. A pull request can run code on the deployment server. Do not expose production credentials to preview deployments, and keep **PR deployment access** set to **Repository members only** unless you accept the risk of running code from public contributors. Enable preview deployments [#enable-preview-deployments] Open the application, select **Preview Deployments** in its settings sidebar, then select **Enable preview deployments**. With **PR deployment access** set to **Repository members only**, Coolify blocks pull requests from forks unless the author is a repository owner, member, or collaborator. Choose **Public (fork PRs allowed)** only when anyone should be allowed to trigger a preview. GitLab, Gitea, and Bitbucket pull requests from other repositories require public preview deployments to be enabled. Connect pull-request events [#connect-pull-request-events] Choose how Coolify receives pull-request or merge-request events for the application. Follow [Set up a GitHub App](/applications/sources/github/app) first. Its repository installation must include the repository used by the application. Enable preview permissions in Coolify [#enable-preview-permissions-in-coolify] During automated GitHub App setup, set **Preview deployment access** to **Read and update pull requests** before selecting **Register with GitHub**. Coolify requests read-and-write access to pull requests and subscribes the app to pull-request events. Finish the GitHub App installation [#finish-the-github-app-installation] Complete the registration and install the GitHub App for the required account and repositories. Verify the event connection [#verify-the-event-connection] Open or update a pull request. Open **Preview Deployments** in Coolify and confirm that the pull request appears. Grant pull-request permission [#grant-pull-request-permission] While creating the GitHub App, open **Repository permissions** and set **Pull requests** to **Read and write**. Subscribe to pull-request events [#subscribe-to-pull-request-events] Under **Subscribe to events**, select **Pull request**, then finish creating and installing the GitHub App. Verify the event connection [#verify-the-event-connection-1] Open or update a pull request. Open **Preview Deployments** in Coolify and confirm that the pull request appears. Update an existing GitHub App [#update-an-existing-github-app] If the GitHub App was created without preview permissions, update it before testing previews. Open the GitHub App permissions [#open-the-github-app-permissions] Open **Sources** in Coolify, select the GitHub App, open **Permissions**, then select **Update**. Update GitHub permissions [#update-github-permissions] On GitHub, set **Pull requests** to **Read and write** under **Repository permissions** and subscribe to the **Pull request** event. Accept and verify the update [#accept-and-verify-the-update] Accept the permission update, then open or update a pull request. Confirm that it appears under **Preview Deployments**. Use this path for an application created from a public repository URL or **Private Repository (with deploy key)**. Copy the provider webhook details [#copy-the-provider-webhook-details] Open **Webhooks**. Enter a long random value in the matching **Webhook secret** field, select **Save changes**, then copy the URL for the repository provider under **Manual Git webhooks**. For GitHub, the fields look like this: Add the repository webhook [#add-the-repository-webhook] Add the copied URL and the same secret to the repository's webhook settings. Follow [Manual Git webhooks](/applications/deployments/manual-webhooks#choose-the-repository-provider) for the exact provider navigation and event names. For GitHub, open **Settings > Webhooks > Add webhook**. Select pull-request events [#select-pull-request-events] For GitHub, paste the Coolify URL into **Payload URL**, enter the same secret, keep **Enable SSL verification** selected, and choose **Let me select individual events**. Select **Pull requests**, keep **Active** selected, then select **Add webhook**. Verify the webhook [#verify-the-webhook] Open or update a pull request. Confirm that the provider reports a successful delivery and that Coolify creates a preview. Configure preview domains [#configure-preview-domains] Open **Preview Deployments**. Under **Preview URL template**, **URL template** controls the generated domain: * `{{pr_id}}` inserts the pull-request or merge-request number. * `{{random}}` inserts a random value. * `{{domain}}` inserts the production application's domain name. The default template is `{{pr_id}}.{{domain}}`. For example, `{{pr_id}}.preview.example.com` produces `123.preview.example.com` for pull request 123. To use domains such as `123.preview.example.com`, create an `A` or `AAAA` record for `*.preview.example.com` that points to the deployment server. You can also enter a domain for an individual preview. Docker Compose previews can have a separate domain for each service. Separate preview variables from production [#separate-preview-variables-from-production] Coolify keeps production and preview environment variables in separate groups. * **Production Environment Variables** apply to the main deployment. * **Preview Deployment Environment Variables** apply to pull-request and merge-request deployments. Use non-production credentials for preview databases, storage, and external services. A preview container is temporary, but data written to an external service can remain after Coolify deletes the preview. Follow [Environment variables](/applications/configuration/environment-variables) for variable scopes and build-time values. Load pull requests that were already open [#load-pull-requests-that-were-already-open] Coolify does not automatically deploy pull requests that were open before previews were enabled. For a GitHub-based application, open **Preview Deployments** and select **Load Pull Requests**. In the **Pull requests** dialog, select **Deploy preview** beside each request that needs a preview. Use **Configure** to prepare a preview without deploying it. GitHub pull-request comments [#github-pull-request-comments] A GitHub App can add the preview deployment status and domain to the pull request, then update the comment when the deployment state changes. Manual repository webhooks can trigger previews, but automated pull-request comments require a GitHub App with the required permissions. Deploy a Docker Image preview manually [#deploy-a-docker-image-preview-manually] For a [Docker Image application](/applications/deployments/docker-image), open **Preview Deployments** and use **Manual preview**. Enter: * **Preview ID:** an identifier used in the preview name, domain, logs, and cleanup * **Docker Tag:** the image tag to deploy, for example `pr_1234` Select **Deploy Preview**. This path is useful when an external CI system builds one image tag for each pull request. Manage a preview [#manage-a-preview] Open **Preview Deployments** to view each preview. Use **Preview links** to open its domain or Git request, **Preview logs** for deployment and runtime logs, and **Preview actions** for lifecycle actions. Depending on the preview state, you can: * select **Deploy** or **Redeploy** * select **Force deploy (without cache)** * select **Stop** to remove its containers and other non-persistent runtime resources * select **Delete** to permanently remove the preview deployment Verify the preview lifecycle [#verify-the-preview-lifecycle] 1. Open or update a pull request or merge request. 2. Confirm that Coolify creates a separate preview deployment. 3. Open the preview domain and test the proposed change. 4. Close or merge the request. 5. Confirm that Coolify removes the automatically created preview. Manage previews through the API [#manage-previews-through-the-api] Use `GET /applications/{uuid}/previews` to list previews and `GET /applications/{uuid}/previews/{pull_request_id}` to inspect one. Creating or redeploying a preview requires `deploy`: ```sh curl --request POST "https://coolify.example.com/api/v1/applications//previews" \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Content-Type: application/json" \ --data '{"pull_request_id":42,"git_type":"github","force":false}' ``` Use the provider that hosts the request. Bitbucket also requires a `commit` SHA. Pull request IDs must be positive integers no greater than `2147483647`; invalid IDs return a validation error, including in the MCP deploy tool. `POST /deploy` with `pull_request_id` also deploys the pull-request ref for deploy-key and public-repository applications. Gitea previews use the pull request's head commit. The UI's pull-request listing and status updates are available for GitHub App sources. Inspect deployment history after the request is accepted. Closing or deleting a preview removes only its own containers and Coolify-created networks and volumes. # Rollbacks (/docs/applications/deployments/rollbacks) Rollbacks [#rollbacks] A rollback deploys an older application image retained on the server. It does not reverse database migrations, restore persistent storage, or change external services. Open the application and select **Rollback** to see the images Coolify can still use. Before rolling back [#before-rolling-back] Confirm: * the image for the version you want to restore appears under **Rollback** * the current environment variables and runtime settings are compatible with that image * any database schema changes are backward compatible * persistent data has a separate restore plan when the release changed it Deploy an older image [#deploy-an-older-image] 1. Open **Rollback**. 2. Under **Available images**, identify the previous working deployment. Select **Reload images** if the list needs refreshing. 3. Select **Roll back to this image**. Only commit and pull-request image tags support rollback; the running image cannot be selected. 4. Open **Deployment Logs** and follow the new operation. 5. Verify the application domain, logs, health check, and critical user flow. The rollback uses current Coolify runtime configuration with the selected older image. If a variable or mount changed after that image was built, review it before starting. Image retention [#image-retention] Rollback availability depends on image retention. Set **Images to keep** under **Image retention** and select **Save changes**. A server-level setting can disable retention and override the application value. An image removed by cleanup no longer appears as a rollback target. A registry may retain another copy, but restoring it requires deploying an available image reference rather than using a missing local rollback entry. Image rollback only changes application code and image contents. Use persistent-storage and database backups for state that must be restored. # Rolling Updates (/docs/applications/deployments/rolling-updates) Rolling updates [#rolling-updates] For Nixpacks, Railpack, Static, Dockerfile, and Docker Image applications, Coolify can start a replacement container while the current container remains running. **Rolling updates are not supported for Docker Compose applications.** Docker Compose uses its own service reconciliation process instead of Coolify's application-level rolling update sequence. Coolify can overlap the old and new containers, wait for a health check, and allow time for the old container to stop. The application must still report readiness accurately, handle shutdown gracefully, and remain compatible while both versions run. If the application does not cooperate with that process, requests can still fail during a rolling update. We will publish a detailed guide for preparing applications for near-zero-downtime deployments in the near future. How a rolling update works [#how-a-rolling-update-works] For an eligible application deployment, Coolify: 1. starts the replacement container without stopping the current container 2. waits for the replacement container's health check to pass, when a health check is configured in Coolify or the image 3. keeps the current container when the replacement becomes unhealthy 4. stops and removes the current container after the replacement is considered ready Without a health check, Coolify treats a successfully started container as ready. It cannot determine whether the application has finished initialization or can serve requests correctly before stopping the current container. What the application must handle [#what-the-application-must-handle] Coolify controls the containers, but the application controls whether the transition is safe for users. | Application responsibility | Why it matters | | :------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Report readiness accurately | The health check must fail until the application can handle real requests and its required dependencies are available. | | Shut down gracefully | Docker asks the old container to stop. The application should stop accepting new requests, finish or safely abandon in-flight requests, and exit within the configured grace period. | | Keep releases compatible | The old and new versions run at the same time. Database migrations, APIs, queues, caches, and shared files must work with both versions during that overlap. | | Support parallel instances | Sessions and required state should not exist only in one container. Schedulers, queue consumers, and other background work must tolerate two versions running briefly. | A health check proves only what its command or endpoint tests. For example, an endpoint that always returns `200` can mark the container healthy before the application is actually ready. Follow [Health checks](/applications/configuration/health-checks) to configure an HTTP or command check that represents application readiness. Configure graceful shutdown [#configure-graceful-shutdown] Open **Advanced > Operations** and set **Stop Grace Period (seconds)** to the maximum time the application should need after receiving its termination signal. The default is 30 seconds. Coolify accepts values from 1 to 3600 seconds. Increasing the grace period gives the old container more time to finish in-flight work, but it does not add graceful-shutdown behavior to the application. The application itself must handle the termination signal and exit correctly. Settings that prevent a rolling update [#settings-that-prevent-a-rolling-update] The old and replacement containers must be able to run at the same time. Coolify stops the current container first when any of these conditions applies: | Condition | Why the containers cannot overlap | | :-------------------------------------------------------------------- | :-------------------------------------------------------------------------------------- | | A port is published on the host | Both containers cannot bind the same host port. | | **Container naming** is **Consistent name (no rolling updates)** | Both containers would use the same Docker container name. | | A **Custom Container Name** is configured | Both containers would use the same custom name. | | `--ip` or `--ip6` assigns a custom IP | Both containers would require the same network address. | | The deployment is a pull-request preview | Coolify does not use its application-level rolling update path for preview deployments. | An optional generated **Container Name Prefix** retains a deployment-specific timestamp and does not disable rolling updates. See [Container naming](/applications/configuration/advanced#container-name-prefix). When Coolify detects one of these conditions, the deployment log explains why rolling updates are not supported. Stopping the current container before starting its replacement causes an interruption while the replacement starts. Docker Compose and Docker Swarm [#docker-compose-and-docker-swarm] A Docker Compose application does not use Coolify's application-level rolling update sequence. Coolify runs `docker compose up` and Docker Compose reconciles the services defined in the Compose file. A Docker Swarm application uses `docker stack deploy` with a start-first service update. Docker Swarm controls replica replacement and routing, so its behavior depends on the stack configuration and the application in each replica. Neither deployment method guarantees zero downtime by itself. The application and its health, shutdown, state, and compatibility behavior still matter. Test the complete transition [#test-the-complete-transition] Test rolling updates with production-like traffic before relying on them for availability: 1. configure a health check that fails during application startup and passes only when the application can serve requests 2. confirm the application handles its termination signal and finishes requests within **Stop Grace Period (seconds)** 3. deploy a backward-compatible change while repeatedly requesting a critical application endpoint 4. open the deployment log and confirm **Rolling update started**, **New container is healthy**, and **Rolling update completed** appear 5. confirm the test requests succeeded throughout the deployment 6. verify background jobs, sessions, database writes, and persistent data remained correct Container overlap is working when the new container becomes healthy before Coolify removes the old one. Zero downtime is confirmed only when user requests and application work also remain successful during the transition. Troubleshoot an interrupted update [#troubleshoot-an-interrupted-update] If the current container stops before its replacement starts, inspect the deployment log for a host port mapping, consistent or custom container name, custom IP, or preview deployment. If the replacement starts but the deployment fails: 1. inspect the reported health-check status and logs 2. confirm the health-check command exists inside the image and reaches the correct port or path 3. confirm the application finishes startup before the health-check retries are exhausted 4. verify that the old and new versions can use the same database, queues, storage, and external dependencies at the same time If requests fail after the replacement becomes healthy, make the readiness check stricter and verify the application's graceful-shutdown handling. A passing container health check does not by itself prove a zero-downtime transition. # Phoenix (/docs/applications/framework-examples/elixir/phoenix) Phoenix [#phoenix] Phoenix is a productive web framework that does not compromise speed and maintainability written in Elixir/Erlang. Requirements [#requirements] * Set **Build strategy** to `nixpacks` * Set `MIX_ENV` to `prod` * It should be a `Build time` environment variable * Set `SECRET_KEY_BASE` to a random string ([https://hexdocs.pm/phoenix/deployment.html#handling-of-your-application-secrets](https://hexdocs.pm/phoenix/deployment.html#handling-of-your-application-secrets)) * It should be a `Build time` environment variable * Set `DATABASE_URL` to your database connection string * It should be a `Build time` environment variable * Set `Ports Exposes` to `4000` (default) # NextJS (/docs/applications/framework-examples/javascript/nextjs) NextJS [#nextjs] NextJS is a React framework that enables functionality such as server-side rendering and generating static websites. [Example repository.](https://github.com/coollabsio/coolify-examples/tree/main/javascript/frameworks/nextjs) Deploy with Nixpacks [#deploy-with-nixpacks] Server build (NodeJS) [#server-build-nodejs] * Set **Build strategy** to `nixpacks`. Static build (SPA) [#static-build-spa] * Set **Build strategy** to `nixpacks`. * Choose **Static** in **Site type**. * Set `Output Directory` to `out`. Deploy with Dockerfile [#deploy-with-dockerfile] If you are having problems with Nixpacks or want more control over the building stage, you can use a Dockerfile to deploy your NextJS application. Prerequisites [#prerequisites] 1. Set `Ports Exposes` field to `3000`. 2. Create a `Dockerfile` in the root of your project and copy the content from the official [NextJS Repository](https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile). 3. Set the **Build strategy** to `Dockerfile`. # Nuxt (/docs/applications/framework-examples/javascript/nuxt) Nuxt [#nuxt] Nuxt is an open source framework that makes web development intuitive and powerful. Create performant and production-grade full-stack web apps and websites with confidence. [Example repository.](https://github.com/coollabsio/coolify-examples/tree/main/javascript/frameworks/nuxt) Server build (Nuxt, using `nuxt build`) [#server-build-nuxt-using-nuxt-build] * Set **Build strategy** to `nixpacks`. * Set Start Command to `node .output/server/index.mjs` Alternatively, you can set the `start` script inside package.json to `node .output/server/index.mjs`. Then Nixpacks will automatically use it as the start command. Static build (Nuxt, using `nuxt generate`) [#static-build-nuxt-using-nuxt-generate] * Set **Build strategy** to `nixpacks`. * Choose **Static** in **Site type**. * Set `Output Directory` to `dist`. Nitro server build (Nitro, using `nitro build`) [#nitro-server-build-nitro-using-nitro-build] * Set **Build strategy** to `nixpacks`. * Set Start Command to `node .output/server/index.mjs` Alternatively, you can set the `start` script inside package.json to `node .output/server/index.mjs`. Then Nixpacks will automatically use it as the start command. # SvelteKit (/docs/applications/framework-examples/javascript/svelte-kit) SvelteKit [#sveltekit] Svelte Kit is a framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing. Static build (`adapter-static`) [#static-build-adapter-static] You need to use `@sveltejs/adapter-static` ([docs](https://kit.svelte.dev/docs/adapter-static)) adapter to build a static site. 1. Under **General > Build pipeline**, choose **Static** in **Site type**. 2. Set your `Publish Directory` to `/build` Node server (`adapter-node`) [#node-server-adapter-node] You need to use `@sveltejs/adapter-node` ([docs](https://kit.svelte.dev/docs/adapter-node)) adapter to build a node server based SvelteKit app. 1. Under **General > Build pipeline**, choose **Dynamic** in **Site type**. 2. Set your `Install Command` to `npm install`. 3. Set your `Build Command` to `npm run build`. 4. Set your `Start Command` to `node build`. 5. Select **Save changes**. 6. In your Environment Variables tab, check the current Node version supported by Nix. In the example screenshot below, it's `version 22`. 7. Add `engines` to your `package.json` with the Node version from your environment variables. For example ```json "engines": { "node": ">=22" } ``` 8. Git Commit 9. Click Deploy from your Coolify Dashboard 10. Add an Environment Variable ORIGIN with your app's actual domain. For example: 11. Optional, but recommended: open **Healthcheck**, select **Enable**, and confirm **Enable healthcheck** # Vite (/docs/applications/framework-examples/javascript/vite) Vite [#vite] Vite is a build tool that aims to provide a faster and leaner development experience for modern web projects. [Example repository.](https://github.com/coollabsio/coolify-examples/tree/main/javascript/build-tools/vite) Vanilla TypeScript build (Static) [#vanilla-typescript-build-static] * Set **Build strategy** to `nixpacks`. * Choose **Static** in **Site type**. * Set `Publish Directory` to `dist`. Vanilla JavaScript build (Static) [#vanilla-javascript-build-static] * Set **Build strategy** to `nixpacks`. * Choose **Static** in **Site type**. * Set `Publish Directory` to `dist`. # Vue (/docs/applications/framework-examples/javascript/vuejs) Vue [#vue] Vue.js is an approachable, performant and versatile framework for building web user interfaces. [Example repository.](https://github.com/coollabsio/coolify-examples/tree/main/javascript/frameworks/vue) Server build (NodeJS|Express) [#server-build-nodejsexpress] * Set **Build strategy** to `nixpacks`. * Set 'Start Command' to `node server.js`. Static build (SPA) [#static-build-spa] * Set **Build strategy** to `nixpacks`. * Choose **Static** in **Site type**. * Set `Output Directory` to `dist`. Static build with Router (SPA) [#static-build-with-router-spa] * Set **Build strategy** to `nixpacks`. * Choose **Static** in **Site type**. * Set `Output Directory` to `dist`. # Laravel (/docs/applications/framework-examples/php/laravel) Laravel [#laravel] Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Example repository [here](https://github.com/coollabsio/coolify-examples/tree/main/php/laravel). Deploy with Nixpacks [#deploy-with-nixpacks] Requirements [#requirements] * Set **Build strategy** to `nixpacks` * Set the required [environment variables](#environment-variables) * Add `nixpacks.toml` with the following [configuration](#all-in-one-container) * Set `Ports Exposes` to `80` Environment Variables [#environment-variables] If your application needs a database or Redis, you can simply create them beforehand in the Coolify dashboard. You will receive the connection strings which you can use in your application and set them as environment variables: ```bash DB_CONNECTION=mysql DB_HOST= DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=root DB_PASSWORD= REDIS_HOST= REDIS_PASSWORD=null REDIS_PORT=6379 ``` All-in-one container [#all-in-one-container] If you would like to start queue worker, scheduler, etc within one container (recommended), then you can place a `nixpacks.toml` inside your repository with the following value. ```toml [phases.setup] nixPkgs = ["...", "python311Packages.supervisor"] [phases.build] cmds = [ "mkdir -p /etc/supervisor/conf.d/", "cp /assets/worker-*.conf /etc/supervisor/conf.d/", "cp /assets/supervisord.conf /etc/supervisord.conf", "chmod +x /assets/start.sh", "..." ] [start] cmd = '/assets/start.sh' [staticAssets] "start.sh" = ''' #!/bin/bash # Ensure storage and bootstrap cache are writable by www-data chown -R www-data:www-data /app/storage /app/bootstrap/cache chmod -R 775 /app/storage /app/bootstrap/cache # Transform the nginx configuration node /assets/scripts/prestart.mjs /assets/nginx.template.conf /etc/nginx.conf # Start supervisor supervisord -c /etc/supervisord.conf -n ''' "supervisord.conf" = ''' [unix_http_server] file=/assets/supervisor.sock [supervisord] logfile=/var/log/supervisord.log logfile_maxbytes=50MB logfile_backups=10 loglevel=info pidfile=/assets/supervisord.pid nodaemon=false silent=false minfds=1024 minprocs=200 [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl=unix:///assets/supervisor.sock [include] files = /etc/supervisor/conf.d/*.conf ''' "worker-nginx.conf" = ''' [program:worker-nginx] process_name=%(program_name)s_%(process_num)02d command=nginx -c /etc/nginx.conf autostart=true autorestart=true stdout_logfile=/var/log/worker-nginx.log stderr_logfile=/var/log/worker-nginx.log ''' "worker-phpfpm.conf" = ''' [program:worker-phpfpm] process_name=%(program_name)s_%(process_num)02d command=php-fpm -y /assets/php-fpm.conf -F autostart=true autorestart=true stdout_logfile=/var/log/worker-phpfpm.log stderr_logfile=/var/log/worker-phpfpm.log ''' "worker-laravel.conf" = ''' [program:worker-laravel] process_name=%(program_name)s_%(process_num)02d command=bash -c 'exec php /app/artisan queue:work --sleep=3 --tries=3 --max-time=3600' user=www-data autostart=true autorestart=true stopasgroup=true killasgroup=true numprocs=12 # To reduce memory/CPU usage, change to 2. startsecs=0 stopwaitsecs=3600 stdout_logfile=/var/log/worker-laravel.log stderr_logfile=/var/log/worker-laravel.log ''' "php-fpm.conf" = ''' [www] listen = 127.0.0.1:9000 user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = dynamic pm.max_children = 50 pm.min_spare_servers = 4 pm.max_spare_servers = 32 pm.start_servers = 18 clear_env = no php_admin_value[post_max_size] = 35M php_admin_value[upload_max_filesize] = 30M ''' "nginx.template.conf" = ''' user www-data www-data; worker_processes 5; daemon off; worker_rlimit_nofile 8192; events { worker_connections 4096; # Default: 1024 } http { include $!{nginx}/conf/mime.types; index index.html index.htm index.php; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx-access.log; error_log /var/log/nginx-error.log; sendfile on; tcp_nopush on; server_names_hash_bucket_size 128; # this seems to be required for some vhosts server { listen ${PORT}; listen [::]:${PORT}; server_name localhost; $if(NIXPACKS_PHP_ROOT_DIR) ( root ${NIXPACKS_PHP_ROOT_DIR}; ) else ( root /app; ) add_header X-Content-Type-Options "nosniff"; client_max_body_size 35M; index index.php; charset utf-8; $if(NIXPACKS_PHP_FALLBACK_PATH) ( location / { try_files $uri $uri/ ${NIXPACKS_PHP_FALLBACK_PATH}?$query_string; } ) else ( location / { try_files $uri $uri/ /index.php?$query_string; } ) location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } $if(IS_LARAVEL) ( error_page 404 /index.php; ) else () location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include $!{nginx}/conf/fastcgi_params; include $!{nginx}/conf/fastcgi.conf; } location ~ /\.(?!well-known).* { deny all; } } } ''' ``` With Inertia.js [#with-inertiajs] When using Laravel with [Inertia.js](https://inertiajs.com/), you may need to specify some additional configuration in your `nixpacks.toml` file. Increasing the NGINX buffer size for Inertia requests [#increasing-the-nginx-buffer-size-for-inertia-requests] Because of a [known issue](https://github.com/inertiajs/inertia-laravel/issues/529) with Inertia.js and default NGINX configuration, you may need to increase the buffer size for NGINX to handle Inertia requests. ```sh # ... http { # ... server { # ... location ~ \.php$ { fastcgi_buffer_size 8k; # [!code ++][!code focus] fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include $!{nginx}/conf/fastcgi_params; include $!{nginx}/conf/fastcgi.conf; # ... } } } ``` Inertia SSR [#inertia-ssr] If you are using Inertia.js with [server-side rendering](https://inertiajs.com/server-side-rendering), you should add another worker in your `nixpacks.toml` file to automatically start your SSR server. ```toml "worker-inertia-ssr.conf" = ''' [program:inertia-ssr] process_name=%(program_name)s_%(process_num)02d command=bash -c 'exec php /app/artisan inertia:start-ssr' autostart=true autorestart=true stderr_logfile=/var/log/worker-inertia-ssr.log stdout_logfile=/var/log/worker-inertia-ssr.log ''' ``` By default, Nixpacks runs the command `npm run build` to build your application during the deployment. Ensure that your `build` script in `package.json` contains the necessary build commands for server-side rendering. If you use one of the official starter kits including Inertia.js, change your scripts like this: ```yaml "scripts": { "build": "vite build", # [!code --] "build": "vite build && vite build --ssr", # [!code ++] "build:ssr": "vite build && vite build --ssr", } ``` Alternatively, if you don't want to adapt your default `build` script in `package.json`, you can add the correct build command for server-side rendering directly in your `nixpacks.toml` configuration file. ```yaml [phases.build] cmds = [ "npm run build:ssr", # [!code ++] "mkdir -p /etc/supervisor/conf.d/", "cp /assets/worker-*.conf /etc/supervisor/conf.d/", "cp /assets/supervisord.conf /etc/supervisord.conf", "chmod +x /assets/start.sh", "..." ] ``` Persistent php.ini customizations [#persistent-phpini-customizations] If you want to customize settings from your php.ini file, you can easily do so by using the `php_admin_value` directive and appending them to your `php-fpm.conf` file like this: ```toml "php-fpm.conf" = ''' [www] listen = 127.0.0.1:9000 user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = dynamic pm.max_children = 50 pm.min_spare_servers = 4 pm.max_spare_servers = 32 pm.start_servers = 18 clear_env = no php_admin_value[memory_limit] = 512M php_admin_value[max_execution_time] = 60 php_admin_value[max_input_time] = 60 php_admin_value[post_max_size] = 256M ''' ``` Using pnpm [#using-pnpm] If your project uses `pnpm` as the package manager, you may encounter a license collision during the Nix build, since `pnpm` and `composer` both pull in overlapping packages. To resolve this, give `composer` a higher priority in `nixPkgs` using `lib.hiPrio`, matching the PHP version your project uses: ```toml [phases.setup] nixPkgs = ["...", "python311Packages.supervisor", "(lib.hiPrio php84Packages.composer)"] ``` Swap `php84Packages` for the package set that matches your project's PHP version (e.g. `php81Packages`, `php82Packages`, `php83Packages`, `php84Packages`) so it stays consistent with the rest of your `nixpacks.toml` configuration. Deploy with Dockerfile and Nginx Unit [#deploy-with-dockerfile-and-nginx-unit] Prerequisites [#prerequisites] 1. Create a new resource from a private or public repository. 2. Set the `Ports Exposes` field to `8000`, for example. 3. Set default environment variables using `Developer view` in `Environment Variables`: ```bash APP_DEBUG=false APP_ENV=staging APP_KEY= #YourAppKey APP_MAINTENANCE_DRIVER=file APP_NAME=Laravel CACHE_STORE=file DB_CONNECTION= #YourDbConnection DB_DATABASE= #YourDb DB_HOST= #YourDbHost DB_PASSWORD= #YourDbPassword DB_PORT= #YourDbPort DB_USERNAME= #YourDbUsername FILESYSTEM_DISK=public MAIL_MAILER=log SESSION_DRIVER=file ``` 4. Create a `Dockerfile` in the root of your project with the following content: ```dockerfile FROM unit:1.34.1-php8.3 RUN apt update && apt install -y \ curl unzip git libicu-dev libzip-dev libpng-dev libjpeg-dev libfreetype6-dev libssl-dev \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) pcntl opcache pdo pdo_mysql intl zip gd exif ftp bcmath \ && pecl install redis \ && docker-php-ext-enable redis RUN echo "opcache.enable=1" > /usr/local/etc/php/conf.d/custom.ini \ && echo "opcache.jit=tracing" >> /usr/local/etc/php/conf.d/custom.ini \ && echo "opcache.jit_buffer_size=256M" >> /usr/local/etc/php/conf.d/custom.ini \ && echo "memory_limit=512M" > /usr/local/etc/php/conf.d/custom.ini \ && echo "upload_max_filesize=64M" >> /usr/local/etc/php/conf.d/custom.ini \ && echo "post_max_size=64M" >> /usr/local/etc/php/conf.d/custom.ini COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer WORKDIR /var/www/html RUN mkdir -p /var/www/html/storage /var/www/html/bootstrap/cache RUN chown -R unit:unit /var/www/html/storage bootstrap/cache && chmod -R 775 /var/www/html/storage COPY . . RUN chown -R unit:unit storage bootstrap/cache && chmod -R 775 storage bootstrap/cache RUN composer install --prefer-dist --optimize-autoloader --no-interaction COPY unit.json /docker-entrypoint.d/unit.json EXPOSE 8000 CMD ["unitd", "--no-daemon"] ``` 3. Create a `unit.json` file (lowercase) at the root of your project with the following content. ```json { "listeners": { "*:8000": { "pass": "routes", "forwarded": { "protocol": "X-Forwarded-Proto", "source": [""] } } }, "routes": [ { "match": { "uri": "!/index.php" }, "action": { "share": "/var/www/html/public$uri", "fallback": { "pass": "applications/laravel" } } } ], "applications": { "laravel": { "type": "php", "root": "/var/www/html/public/", "script": "index.php" } } } ``` When using docker-compose for deployment, then there might be an issue with `Mixed content error` when some of the assets are requested via `http://` instead of `https://`. To avoid that, find your load balancer/proxy subnet or IP address and add it to the unit.config to explicitly tell unit to forward the correct headers to Laravel. Laravel also has to be configured trust proxies. More on that [here](https://laravel.com/docs/12.x/requests#configuring-trusted-proxies). ```json "listeners": { "*:8000": { "pass": "routes", "forwarded": { "protocol": "X-Forwarded-Proto", "source": [""] } } }, ``` 4. Set Post-deployment to: ```bash php artisan optimize:clear && php artisan config:clear && php artisan route:clear && php artisan view:clear && php artisan optimize ``` # Symfony (/docs/applications/framework-examples/php/symfony) Symfony [#symfony] Symfony is the leading PHP framework to create websites and web applications. Built on top of the Symfony Components. Requirements [#requirements] * Set **Build strategy** to `nixpacks` * Set `APP_ENV` * Set `APP_SECRET` * Set `NIXPACKS_PHP_FALLBACK_PATH` to `/index.php` * Set `NIXPACKS_PHP_ROOT_DIR` to `/app/public` * Set `Ports Exposes` to `80` Database migrations [#database-migrations] If you use Doctrine, you can add the following `Post-deployment script` : `php bin/console doctrine:migrations:migrate --all-or-nothing --no-interaction` Other components [#other-components] If your application needs a database or Redis, you can simply create them beforehand in the Coolify dashboard. You will receive the connection strings which you can use in your application and set them as environment variables: ```bash DATABASE_URL=postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8 REDIS_HOST= REDIS_PASSWORD=null REDIS_PORT=6379 ``` Trusted proxy [#trusted-proxy] You might need to configure the [trusted proxy](https://symfony.com/doc/current/deployment/proxies.html) : * Set the environment variable `TRUSTED_PROXIES` with the IP of your server * Add the following Symfony configuration : ```yaml # config/packages/framework.yaml framework: trusted_proxies: "%env(TRUSTED_PROXIES)%" trusted_headers: ['x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix'] ``` Persistent php.ini customizations [#persistent-phpini-customizations] If you want to customize settings from your php.ini file, you can easily do so by using the `php_admin_value` directive and appending them to your `php-fpm.conf` file like this: ```toml "php-fpm.conf" = ''' [www] listen = 127.0.0.1:9000 user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = dynamic pm.max_children = 50 pm.min_spare_servers = 4 pm.max_spare_servers = 32 pm.start_servers = 18 clear_env = no php_admin_value[memory_limit] = 512M php_admin_value[max_execution_time] = 60 php_admin_value[max_input_time] = 60 php_admin_value[post_max_size] = 256M ''' ``` # Django (/docs/applications/framework-examples/python/django) Django [#django] Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Requirements [#requirements] 1. Set the base directory where your `requirements.txt` and `manage.py` files are located. > In the example repository, it is `/coolify`. 2. Add `gunicorn` to the `requirements.txt` file, [official docs](https://gunicorn.org/install/). 3. Add `localhost` and your `domain` to `ALLOWED_HOSTS` in `settings.py` file, [ official docs](https://docs.djangoproject.com/en/4.2/ref/settings/#allowed-hosts). > `Localhost` is required for health checks to work properly. # Jekyll (/docs/applications/framework-examples/ruby/jekyll) Jekyll [#jekyll] Jekyll is a simple, blog-aware, static site generator for personal, project, or organization sites. Deploy with Nixpacks [#deploy-with-nixpacks] Nixpacks needs a few prerequisites in your source code to deploy your Jekyll application. More info [here](https://nixpacks.com/docs/providers/ruby). Deploy with Dockerfile [#deploy-with-dockerfile] If you want simplicity, you can use a Dockerfile to deploy your Jekyll application. Prerequisites [#prerequisites] 1. Set `Ports Exposes` field to `80`. 2. Create a `Dockerfile` in the root of your project with the following content: ```dockerfile FROM ruby:3.1.1 AS builder RUN apt-get update -qq && apt-get install -y build-essential nodejs WORKDIR /srv/jekyll COPY Gemfile Gemfile.lock ./ RUN bundle install COPY . . RUN chown 1000:1000 -R /srv/jekyll RUN bundle exec jekyll build -d /srv/jekyll/_site FROM nginx:alpine COPY --from=builder /srv/jekyll/_site /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` 3. Make sure you have a `Gemfile` and `Gemfile.lock` in the root of your project. 4. Set the buildpack to `Dockerfile`. # Ruby on Rails (/docs/applications/framework-examples/ruby/rails) Ruby on Rails [#ruby-on-rails] Ruby on Rails is a web-application framework that includes everything needed to create database-backend web applications according to the Model-View-Controller (MVC) pattern. Requirements [#requirements] If you would like to migrate the database during the deployment with `NIXPACKS` build pack, you need to set the following `Start Command`: ```bash bundle exec rake db:migrate && bundle exec bin/rails server -b 0.0.0.0 -p ${PORT:-3000} -e $RAILS_ENV ``` # How Applications Work (/docs/applications/how-applications-work) How applications work [#how-applications-work] Coolify combines an application definition stored in the control plane with Docker resources on a connected server. The application definition contains the source or image reference, build method, runtime settings, deployment destination, and operational settings. Docker stores the prepared images and runs containers created from them. From source to a running application [#from-source-to-a-running-application] 1. A deployment starts from the dashboard, a Git webhook, a deploy webhook, or an API request. 2. Coolify queues the deployment. 3. Coolify checks out source code, reads Docker configuration, or resolves the saved image reference. 4. Docker builds or pulls the required images. 5. Coolify applies environment variables, networks, storage, ports, domains, and health-check settings. 6. Docker starts the application containers, including containers for Compose services. 7. The Coolify proxy routes configured domains to healthy HTTP containers. Read [Build and deployment model](/core/build-deployment-model) for the complete lifecycle and replacement paths. Control plane and workload server [#control-plane-and-workload-server] The Coolify instance is the control plane. It provides the dashboard, stores configuration, and coordinates deployments. The connected server is the workload machine. It stores the application's Docker resources and runs its containers. Those resources include: * Docker images * application containers * Docker networks * volumes and bind-mounted files * proxy configuration and certificate data If the Coolify instance becomes unavailable, already-running containers can continue serving traffic while Docker, the proxy, the server, and the network remain healthy. You cannot start new Coolify operations until the control plane is available again. Containers are replaceable [#containers-are-replaceable] A deployment can replace the current container with another container created from a new image or configuration. Data written only to the container filesystem can disappear when Docker removes that container. Store required data in a [persistent storage mount](/core/persistent-storage/storage-mounts/overview) or an external data service. A volume or bind mount survives normal container replacement, but it does not protect against deletion, disk failure, corruption, or server loss. Configure [storage mount backups](/core/persistent-storage/storage-mounts/backups) when the application stores important files locally. Networking [#networking] For an HTTP application, the configured domain points to the server. The Coolify proxy receives the request and forwards it to the application port inside the container. A host port mapping bypasses this domain-based proxy path and publishes a container port directly on the server. Host port mappings also prevent Coolify from using its normal [rolling replacement path](/applications/deployments/rolling-updates) because two containers cannot bind the same host port at the same time. Read [Networking in Coolify](/core/networking-in-coolify) for domains, proxy routing, Docker networks, and communication between resources. Builds and deployments are different [#builds-and-deployments-are-different] A build creates an image. A deployment prepares the required images and runtime configuration, then creates or updates the application containers. [Nixpacks](/applications/builds/nixpacks/overview), [Railpack](/applications/builds/railpack), [Static](/applications/builds/static), [Dockerfile](/applications/builds/dockerfile), and [Docker Compose](/applications/builds/docker-compose) can build images from source. [Docker Image applications](/applications/deployments/docker-image) skip the source build and pull an existing image. The same image can be redeployed with different runtime variables or container settings. A build-time change requires another image build. # Applications (/docs/applications) Applications [#applications] Coolify deploys applications as Docker containers on a connected server. Create an Application from a Git repository, a Dockerfile entered without Git, or an existing Docker image. A Git-based Application can also use a Docker Compose definition from its repository. Start with **Understand Applications** if you are new to self-hosting or are moving from a managed deployment platform. The section explains which infrastructure Coolify manages, what remains your responsibility, and how to choose a deployment method. Use [Services](/services) for software distributed as a ready-made Coolify service template. Use Applications when you control the source code, Docker configuration, or image reference. Find the right section [#find-the-right-section] | If you want to | Start here | | :--------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------- | | Learn what an application is and where it runs | [What is an application](/applications/what-is-an-application) | | Choose between Git source, a Dockerfile without Git, Git-based Docker Compose, and an existing image | [Choose a deployment method](/applications/choose-deployment-method) | | Connect GitHub, GitLab, Bitbucket, Gitea, or another Git provider | [Source code](/applications/sources/overview) | | Configure how Coolify builds source code | [Builds](/applications/builds/overview) | | Manage domains, ports, variables, health checks, and advanced settings | [Configuration](/applications/configuration/overview) | | Inspect deployments, previews, rolling updates, and rollbacks | [Deployments](/applications/deployments/overview) | | Use logs, the terminal, backups, or resource operations | [Operations](/applications/operations/overview) | Start with your first application [#start-with-your-first-application] If you have not deployed an application before, follow [Deploy your first app](/deploy-your-first-app). The guide uses `nginx:alpine` so you can verify the server, Docker, proxy, and generated domain before connecting source code. After the first deployment, choose the path that matches the application you want to run. # Danger Zone (/docs/applications/operations/danger-zone) Delete an application [#delete-an-application] Deleting an application removes it from Coolify, stops its production and preview containers, and removes its environment variables. The deletion cannot be undone. Open the application, then select **Danger Zone**. Before deletion [#before-deletion] * Back up every persistent volume that contains required data. * Record the source, domains, environment variables, storage mounts, and deployment settings needed to recreate the application. * Move production traffic before deletion when the application must remain available. * Confirm that you have permission to delete the application. Otherwise, Coolify shows **Insufficient Permissions**. Application rollback images are not backups of persistent volumes. Verify a volume backup outside the affected volume before continuing. Deleting the application also deletes its scheduled volume-backup configuration and the backup archives created by those schedules from local and S3 storage. This happens regardless of which optional deletion actions you select. Delete the application [#delete-the-application] Review the deletion actions [#review-the-deletion-actions] Select **Delete** and review the actions in the confirmation modal. Coolify selects all four optional actions by default: | Action | Result | | :-------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | | **Permanently delete all volumes associated with this resource.** | Deletes the application's Docker volumes and their Coolify storage records. | | **Permanently delete all non-predefined networks associated with this resource.** | Deletes application networks that were not defined as shared networks. | | **Permanently delete all configuration files from the server.** | Deletes Coolify-generated configuration files for the application from its server. | | **Run Docker Cleanup (remove unused images and builder cache).** | Starts Docker cleanup on the application server after deletion. | The application record, environment variables, file-mount records, scheduled volume-backup configuration and archives, and application containers are removed even when optional actions are cleared. Confirm the application name [#confirm-the-application-name] Enter the exact application name shown in the confirmation modal. Coolify skips this step when the instance-wide two-step confirmation setting is disabled. Confirm your password [#confirm-your-password] Enter your Coolify account password, then confirm the deletion. Coolify skips password confirmation for OAuth accounts without a password and when the instance-wide two-step confirmation setting is disabled. Coolify returns to the project environment while the deletion job removes the selected Docker resources. Verify deletion [#verify-deletion] Confirm that: 1. The application no longer appears in the project environment. 2. Its production and preview containers no longer appear on the server. 3. Any domain that should remain in use now routes to its replacement. Coolify does not manage DNS records at your DNS provider. Remove or update obsolete records separately. Recreate a deleted application [#recreate-a-deleted-application] Coolify cannot restore a deleted application record from the Danger Zone. Create a new application, configure its source and environment variables, attach new or restored storage, and deploy it. Use [Persistent storage backups](/core/persistent-storage/storage-mounts/backups) to restore data from a backup created before deletion. When the server is unreachable, resource deletion warns that Docker resources remain on the server. The team is notified afterwards. Clean those resources up when server access returns. # Migrate an Application (/docs/applications/operations/migrate-between-instances) Migrate an application [#migrate-an-application] This guide moves one application from a source Coolify instance to a destination Coolify instance. It does not migrate the Coolify control plane, team members, servers, projects, or instance settings. Coolify does not provide a single export and import operation for an application. Recreate the application on the destination instance, verify it with a temporary domain, move every stateful dependency, then transfer production traffic. Data can change while the source application is running. Stop writes or stop the source application before the final database dump or file copy. Keep the source unchanged until the destination is confirmed stable. Before you start [#before-you-start] Make sure you can access: * both Coolify instances * the source and destination deployment servers over SSH when files or Docker volumes must be transferred * the Git repository or image registry used by the application * DNS for the production domain * credentials for databases, object storage, email, OAuth, and other external services Record the configuration from the source application: | Source page | Record | | :------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------- | | **General** | Source or image reference, branch, build pack, base directory, build-file locations, commands, domains, internal ports, and host port mappings | | **Environment Variables** | Production variables, build-time settings, preview variables, and shared-variable references | | **Persistent Storage** | Mount type, volume or source path, destination path, file content, and read-only setting | | **Advanced** | Deployment, Git, proxy, container, and operational settings that differ from the defaults | | Other configuration pages | Health check, resource limits, scheduled tasks, webhooks, servers, tags, and preview settings | Also list every database, cache, queue, storage bucket, callback URL, and third-party dependency used by the application. Coolify cannot discover all state held outside the container. Choose how each type of state moves [#choose-how-each-type-of-state-moves] One application can use several of these paths. | State | Migration path | | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | | No persistent application data | Recreate the configuration and deploy from the same source or image. | | Database | Create a logical backup with the database engine's supported tool, transfer it, then restore it into the destination database. | | Docker volume | Stop writes, archive the named volume, transfer the archive, and extract it into the destination volume. | | Directory or bind mount | Copy the exact source directory to the destination server while preserving ownership and permissions. | | Coolify-managed File Mount | Recreate the file and its destination path in the destination application. | | Host File Mount | Copy or independently recreate the host file at the required destination-server path. | | External object storage or managed service | Keep the existing dependency or migrate it with that provider's supported process, then update the destination variables. | Do not copy a running database's Docker volume as a substitute for a database-aware backup. Live database files can produce an inconsistent or unusable copy. Recreate and test the application [#recreate-and-test-the-application] Prepare the destination [#prepare-the-destination] Add and validate the destination deployment server. Confirm that its proxy is running, it can reach required registries and external dependencies, and it has enough CPU, memory, and storage for the application. Create required private keys, Git integrations, registry authentication, S3 destinations, and shared variables on the destination instance. These instance and team resources are not copied with the application. Recreate the application [#recreate-the-application] Create a new application with the same deployment method and enter the recorded configuration. Use a temporary domain and non-production credentials for the first deployment. Do not assign the production domain or change production DNS yet. If the source application references shared variables, recreate those variables first or replace each reference with the intended destination value. Verify the application without production state [#verify-the-application-without-production-state] Deploy the destination application and confirm that Coolify builds or pulls the intended image, starts the container, and passes its health check. Open the temporary domain and verify the internal port, environment variables, outbound network access, and connection to non-production dependencies. Resolve build, proxy, or network failures before moving production data. Move application state [#move-application-state] Create destination mounts before restoring data. Then use each path that matches the application's state. One application can use several paths. Databases and external dependencies [#databases-and-external-dependencies] Create a logical database backup with the database engine's supported tool. Transfer and restore it into the destination database, then update the destination application variables with the new connection details. For a Coolify-managed database, create the recovery file with [Database backups](/databases/backups), then follow [Restore a database](/databases/restore) when the destination engine supports Coolify's import workflow. Verify required tables or records before the destination application uses the database. Move object storage, queues, caches, and other external state through the provider's supported process. A cache usually does not need migration unless the application treats it as durable data. Do not copy a running database's Docker volume as a substitute for a database-aware backup. Live database files can produce an inconsistent or unusable copy. Persistent files [#persistent-files] Use the subsection below that matches each mount, then confirm the destination container user can read and write the restored content. Cut over to the destination [#cut-over-to-the-destination] Perform the final synchronization [#perform-the-final-synchronization] Stop writes or stop the source application. Create a final database dump and copy any files changed since the test migration. Restore that final state on the destination, then redeploy or restart the destination application so it uses the final variables and mounts. Transfer production traffic [#transfer-production-traffic] Test the destination through its temporary domain first. Verify login, reads, writes, uploads, background jobs, email, OAuth, webhooks, and other critical integrations. Assign the production domain to the destination application and update DNS when the domain points to a different server. Confirm TLS issuance and routing before declaring the migration complete. Reconnect automation [#reconnect-automation] Update manual Git webhooks, authenticated deploy webhooks, CI secrets, scheduled tasks, registry credentials, monitoring, and external callback URLs that still reference the source instance or server. Trigger one test deployment and one scheduled or background operation. Move a Docker volume [#move-a-docker-volume] Use the scheduled [storage mount backup](/core/persistent-storage/storage-mounts/backups) workflow when it supports the source mount. Download the resulting `.tar.gz` archive before the migration because the dashboard does not restore storage archives. Backup and restore overview [#backup-and-restore-overview] The [Docker-recommended process](https://docs.docker.com/engine/storage/volumes/#back-up-restore-or-migrate-data-volumes) for volume migration looks like this: 1. **Mount** your volume into a temporary container. 2. **Archive** the volume’s contents into a tarball. 3. **Copy** the tarball from the container to your host and then delete the temporary container. 4. **Transfer** the tarball to the new server. 5. **Create** a fresh volume on the destination. 6. **Mount** the transferred tarball into a temporary container. 7. **Extract** the archive into the new volume. This series of steps ensures a consistent, safe backup and restore. Below, we’ll provide ready-to-use scripts and detailed instructions. *** The steps below include scripts to help you back up, transfer, and restore volumes easily and interactively. They also include checks to ensure volumes and backups exist, to prevent mistakes like restoring to the wrong volume. Backup the volume [#backup-the-volume] 1. **SSH into your server** where you have the Docker volume. 2. **Create a script** named `backup.sh`: ```bash touch backup.sh && chmod +x backup.sh ``` 3. **Open** `backup.sh` in your editor and paste the following: ```bash #!/bin/bash # === INPUT PROMPTS === # Prompt for the Docker volume name and set the variable read -p "[ Backup Agent ] [ INPUT ] Please enter the Docker volume name to back up: " VOLUME_NAME # Inform the user of the set volume name echo "[ Backup Agent ] [ INFO ] Backup Volume is set to $VOLUME_NAME" # Check if the entered volume exists if ! docker volume ls --quiet | grep -q "^$VOLUME_NAME$"; then echo "[ Backup Agent ] [ ERROR ] Volume '$VOLUME_NAME' doesn't exist, aborting backup." echo "[ Backup Agent ] [ ERROR ] Backup Failed!" exit 1 # Exit if volume doesn't exist else echo "[ Backup Agent ] [ INFO ] Volume '$VOLUME_NAME' exists, continuing backup..." fi # Prompt for the directory to save the backup read -p "[ Backup Agent ] [ INPUT ] Please enter the directory to save the backup (Optional: press enter to use ./volume-backup): " BACKUP_DIR # If no directory is entered, default to './volume-backup' BACKUP_DIR=${BACKUP_DIR:-./volume-backup} # Inform the user of the backup location echo "[ Backup Agent ] [ INFO ] Backup location is set to $BACKUP_DIR" # Set the backup file name based on the volume name BACKUP_FILE="${VOLUME_NAME}-backup.tar.gz" # Inform the user of the backup file name echo "[ Backup Agent ] [ INFO ] Backup file name is set to $BACKUP_FILE" # === SCRIPT START === # Check if the backup directory exists if [ -d "$BACKUP_DIR" ]; then echo "[ Backup Agent ] [ INFO ] Directory '$BACKUP_DIR' already exists, skipping directory creation." else echo "[ Backup Agent ] [ INFO ] Directory '$BACKUP_DIR' does not exist, creating directory." # Create the backup directory, exit if creation fails mkdir -p "$BACKUP_DIR" || { echo "[ Backup Agent ] [ ERROR ] Failed to create directory '$BACKUP_DIR', aborting backup." echo "[ Backup Agent ] [ ERROR ] Backup Failed!" exit 1 } fi # Perform the backup operation echo "[ Backup Agent ] [ INFO ] Backing up volume: $VOLUME_NAME to $BACKUP_DIR/$BACKUP_FILE" # Run the Docker container to create the backup docker run --rm \ -v "$VOLUME_NAME":/volume \ -v "$(pwd)/$BACKUP_DIR":/backup \ busybox \ tar czf /backup/"$BACKUP_FILE" -C /volume . || { # If the backup fails, print an error message and exit echo "[ Backup Agent ] [ ERROR ] Backup process failed, aborting." echo "[ Backup Agent ] [ ERROR ] Backup Failed!" exit 1 } # If everything succeeds, notify the user echo "[ Backup Agent ] [ SUCCESS ] Backup completed!" ``` 4. **Find the volume name** by running: ```bash docker volume ls ``` Or from Coolify’s **Persistent Storage** page (see below). 5. **Stop your application** to perform a clean backup. 6. **Run** the script: ```bash ./backup.sh ``` * When prompted, paste the volume name. * Press **Enter** to accept the default backup directory (`./volume-backup`), or type a custom path. 7. **Verify** that you now have a directory (e.g., `volume-backup`) containing `-backup.tar.gz`. *** Transfer the backup to the new server [#transfer-the-backup-to-the-new-server] If you already know how to manually transfer the backup file, feel free to move on to the next step. 1. **Create** a second script named `transfer.sh`: ```bash touch transfer.sh && chmod +x transfer.sh ``` 2. **Open** `transfer.sh` in your editor and paste the following: ```bash #!/bin/bash # =============== CONFIG VARIABLES =============== SSH_PORT=22 SSH_USER="root" SSH_IP="192.168.1.222" SSH_KEY="$HOME/.ssh/local-vm" SOURCE_PATH="./volume-backup" DESTINATION_PATH="/root/backups/volume-backup" MAX_RETRIES=3 # Max number of password attempts echo "[ Transfer Agent ] [ INFO ] Starting transfer..." echo "[ Transfer Agent ] [ INFO ] Trying SSH key: $SSH_KEY" echo "[ Transfer Agent ] [ INFO ] Transfer from: $SOURCE_PATH" echo "[ Transfer Agent ] [ INFO ] Transfer to: $SSH_USER@$SSH_IP:$DESTINATION_PATH" # If SSH key file doesn’t exist, fall back to password mode if [ ! -f "$SSH_KEY" ]; then echo "[ Transfer Agent ] [ WARN ] SSH key '$SSH_KEY' not found. Falling back to password authentication." SSH_KEY="" fi # If we need password-based auth, ensure Expect is installed if [ -z "$SSH_KEY" ] && ! command -v expect >/dev/null 2>&1; then echo "[ Transfer Agent ] [ ERROR ] The package expect is required for password authentication but not installed (Install it manually using sudo apt install expect and try again). Aborting." exit 1 fi # --------------------------------------------- # Helper: test whether $1 (the password) is valid by doing “ssh … exit” # Returns 0 if OK, 1 if “Permission denied” (or any other failure) test_password_with_expect() { local PW="$1" expect -c " log_user 0 set timeout 15 spawn ssh -o StrictHostKeyChecking=no -p $SSH_PORT $SSH_USER@$SSH_IP exit expect { \"*?assword:\" { send -- \"$PW\r\" expect { \"Permission denied\" { exit 1 } eof { exit [lindex [wait] 3] } } } eof { exit [lindex [wait] 3] } } " >/dev/null 2>&1 return $? } # Prompt up to $MAX_RETRIES times for a correct password get_password() { local retries=0 while [ $retries -lt $MAX_RETRIES ]; do read -s -p "[ Transfer Agent ] [ INPUT ] Please enter the SSH password for $SSH_USER@$SSH_IP: " SSHPASS echo "" test_password_with_expect "$SSHPASS" if [ $? -eq 0 ]; then # Password is correct return 0 else echo "[ Transfer Agent ] [ ERROR ] Invalid password. Please try again." retries=$((retries + 1)) fi done echo "[ Transfer Agent ] [ ERROR ] Maximum retries reached. Aborting." exit 1 } # --------------------------------------------- # STEP 0: Attempt SSH-key authentication (if a key is set) if [ -n "$SSH_KEY" ]; then # Use BatchMode to prevent falling back to password prompt ssh -i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=no -p "$SSH_PORT" \ "$SSH_USER@$SSH_IP" exit >/dev/null 2>&1 RC=$? if [ $RC -eq 0 ]; then echo "[ Transfer Agent ] [ INFO ] SSH key is valid!" USING_KEY=true else echo "[ Transfer Agent ] [ WARN ] SSH key authentication failed. Falling back to password authentication." SSH_KEY="" USING_KEY=false fi else USING_KEY=false fi # If key auth failed (or no key), prompt for password if [ "$USING_KEY" = false ]; then get_password echo "[ Transfer Agent ] [ INFO ] Password is valid!" fi # --------------------------------------------- # STEP 1: Ensure the full DESTINATION_PATH exists on the remote side. echo "[ Transfer Agent ] [ INFO ] Ensuring remote directory '$DESTINATION_PATH' exists..." if [ -n "$SSH_KEY" ]; then ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" \ "$SSH_USER@$SSH_IP" "mkdir -p $DESTINATION_PATH" >/dev/null 2>&1 MKRC=$? else expect -c " log_user 0 set timeout 5 spawn ssh -o StrictHostKeyChecking=no -p $SSH_PORT $SSH_USER@$SSH_IP mkdir -p $DESTINATION_PATH expect { \"*?assword:\" { send -- \"$SSHPASS\r\" exp_continue } eof { exit [lindex [wait] 3] } } " >/dev/null 2>&1 MKRC=$? fi if [ $MKRC -ne 0 ]; then echo "[ Transfer Agent ] [ ERROR ] Failed to create remote directory. Aborting." exit 1 fi # --------------------------------------------- # STEP 2: Copy only the contents of local “volume-backup” into that folder. echo "[ Transfer Agent ] [ INFO ] Initiating file transfer..." # Capture any SCP stderr in a temp file so we can surface it if something goes wrong SCP_LOG="$(mktemp)" if [ -n "$SSH_KEY" ]; then # Suppress stdout, capture only stderr scp -i "$SSH_KEY" -o StrictHostKeyChecking=no -P "$SSH_PORT" -r \ "$SOURCE_PATH"/. "$SSH_USER@$SSH_IP:$DESTINATION_PATH" > /dev/null 2> "$SCP_LOG" SCP_RC=$? else expect -c " log_user 0 set timeout -1 spawn scp -o StrictHostKeyChecking=no -P $SSH_PORT -r $SOURCE_PATH/. $SSH_USER@$SSH_IP:$DESTINATION_PATH expect { \"*?assword:\" { send -- \"$SSHPASS\r\" exp_continue } eof { exit [lindex [wait] 3] } } " 2> "$SCP_LOG" SCP_RC=$? fi if [ $SCP_RC -eq 0 ]; then echo "[ Transfer Agent ] [ SUCCESS ] Transfer completed." rm -f "$SCP_LOG" exit 0 else echo "[ Transfer Agent ] [ ERROR ] Transfer failed." while IFS= read -r line; do echo "[ Transfer Agent ] $line" done < "$SCP_LOG" rm -f "$SCP_LOG" exit 1 fi ``` 3. **Adjust** the variables at the top (`SSH_IP`, `SSH_USER`, `SSH_KEY`, `DESTINATION_PATH`) to match your new server. 4. **Run** the transfer: ```bash ./transfer.sh ``` * If key-based authentication succeeds, the backup folder copies over via SCP. * Otherwise, you’ll be prompted for the SSH password. *** Restore the backup on the new server [#restore-the-backup-on-the-new-server] In this example, we’ll use [Umami Analytics](https://umami.is/?utm_source=coolify.io) (PostgreSQL) to show how you restore a database-backed app. Adjust paths and volume names for your own database. 1. **Deploy your application** on the new server with Coolify, then **stop it** so volumes will be created but won't be in use. 2. **SSH into** the new server and **create** a script called `restore.sh`: ```bash touch restore.sh && chmod +x restore.sh ``` 3. **Paste** the following into `restore.sh`: ```bash #!/bin/bash # === VOLUME NAME INPUT === # Prompt for the target Docker volume name to restore into read -p "[ Restore Agent ] [ INPUT ] Enter the target Docker volume name to restore into: " TARGET_VOLUME # === VOLUME CHECK === # Check if the target volume exists if ! docker volume ls --quiet | grep -q "^$TARGET_VOLUME$"; then echo "[ Restore Agent ] [ ERROR ] Volume '$TARGET_VOLUME' doesn't exist." # Ask if the user wants to create the volume read -p "[ Restore Agent ] [ INPUT ] Do you want to create a new volume with the name '$TARGET_VOLUME'? (y/N): " create_volume if [[ "$create_volume" == "y" ]]; then echo "[ Restore Agent ] [ INFO ] Creating volume '$TARGET_VOLUME'..." docker volume create "$TARGET_VOLUME" || { echo "[ Restore Agent ] [ ERROR ] Failed to create volume '$TARGET_VOLUME', aborting restore." echo "[ Restore Agent ] [ ERROR ] Restore Failed!" exit 1 } echo "[ Restore Agent ] [ INFO ] Volume '$TARGET_VOLUME' created successfully." else echo "[ Restore Agent ] [ INFO ] Volume '$TARGET_VOLUME' doesn't exist and user opted not to create it. Aborting restore." echo "[ Restore Agent ] [ ERROR ] Restore Failed!" exit 1 fi else echo "[ Restore Agent ] [ INFO ] Volume '$TARGET_VOLUME' exists, continuing..." fi # === BACKUP DIRECTORY INPUT === # Prompt for the backup directory (default: ./volume-backup) read -p "[ Restore Agent ] [ INPUT ] Enter the backup directory (default: ./volume-backup): " BACKUP_DIR BACKUP_DIR=${BACKUP_DIR:-./volume-backup} # === BACKUP DIRECTORY CHECK === # Check if the backup directory exists if [[ ! -d "$BACKUP_DIR" ]]; then echo "[ Restore Agent ] [ ERROR ] Backup directory not found: $BACKUP_DIR" echo "[ Restore Agent ] [ ERROR ] Restore Failed!" exit 1 fi echo "[ Restore Agent ] [ INFO ] Backup directory '$BACKUP_DIR' found, continuing..." # === BACKUP FILE INPUT === # Prompt for the backup file name read -p "[ Restore Agent ] [ INPUT ] Enter the backup file name (e.g., abc123_postgresql.tar.gz): " BACKUP_FILE # === BACKUP FILE CHECK === # Check if the backup file exists if [[ ! -f "$BACKUP_DIR/$BACKUP_FILE" ]]; then echo "[ Restore Agent ] [ ERROR ] Backup file not found: $BACKUP_DIR/$BACKUP_FILE" echo "[ Restore Agent ] [ ERROR ] Restore Failed!" exit 1 fi echo "[ Restore Agent ] [ INFO ] Backup file '$BACKUP_FILE' found, continuing..." # === SAFETY CONFIRMATION === echo "[ Restore Agent ] [ INFO ] Make sure containers using '$TARGET_VOLUME' are stopped!" read -p "[ Restore Agent ] [ INPUT ] Proceed with restore? (y/N): " confirm if [[ "$confirm" != "y" ]]; then echo "[ Restore Agent ] [ ERROR ] Restore Failed: cancelled by user." exit 1 fi # === RESTORE START === # Inform the user that restore is starting echo "[ Restore Agent ] [ INFO ] Restoring $BACKUP_FILE into volume: $TARGET_VOLUME" # Run the Docker container to restore the backup docker run --rm \ -v "$TARGET_VOLUME":/volume \ -v "$(pwd)/$BACKUP_DIR":/backup \ busybox \ sh -c "cd /volume && tar xzf /backup/$BACKUP_FILE" || { # If the restore process fails, print an error message and exit echo "[ Restore Agent ] [ ERROR ] Docker restore process failed, aborting." echo "[ Restore Agent ] [ ERROR ] Restore Failed!" exit 1 } # If everything succeeds, notify the user echo "[ Restore Agent ] [ SUCCESS ] Restore completed!" ``` 4. **Run** the script: ```bash ./restore.sh ``` * Enter the **volume name** (from `docker volume ls` command or Coolify's Persistent Storage page). * Press **Enter** to accept `./volume-backup`, or type a custom backup path. * Enter the backup filename (e.g., `umami_postgresql-backup.tar.gz`). * Confirm you want to proceed by typing `y`. *** Start your application [#start-your-application] Once the restore finishes, go to Coolify’s dashboard and click **Deploy**. Your application should now use the migrated data. If it does not, or if logs show errors then repeat the restore step to ensure all files copied correctly. If the database credentials (username, database name or password) are different on the new server, update them in Coolify’s dashboard to match those from the old server. Move a directory, bind mount, or host file [#move-a-directory-bind-mount-or-host-file] Find the exact source-server path under **Persistent Storage**. Stop writes, then copy the contents while preserving ownership and permissions. For a directory, run from the source server: ```sh rsync -a --numeric-ids -e "ssh -p " \ / \ @:/ ``` The trailing `/` on `/` copies the directory contents into `/`. Create the same mount in the destination application with the destination server's source path and the container's original **Destination Path**. For one Host File Mount, copy the file instead of the directory and confirm its destination-server path before starting the application. For a Coolify-managed File Mount, recreate its content in the destination dashboard rather than copying a generated internal path. Verify the migration [#verify-the-migration] Confirm all of the following on the destination: * the production domain serves the destination application with valid TLS * the intended source revision or image is running * health checks and application logs show a stable runtime * login, reads, writes, uploads, and downloads work * databases contain the expected final records * scheduled tasks, queues, webhooks, email, OAuth, and external callbacks work * backups run and create a usable destination copy Monitor the destination until it is confirmed stable. Keep the source application stopped but unchanged, and retain the final backups for the rollback period you selected. Roll back the cutover [#roll-back-the-cutover] If the destination fails after traffic moves: 1. stop writes to the destination 2. determine whether production data changed on the destination after cutover 3. restore or synchronize those changes back to the source dependencies when required 4. return the production domain or DNS record to the source application 5. start the source application and verify its critical user flow Do not send traffic back to an older source database without accounting for writes accepted by the destination. DNS rollback changes routing; it does not merge data. # Overview (/docs/applications/operations/overview) Operate applications [#operate-applications] After an application is deployed, Coolify provides separate views for deployment activity, container output, terminal access, backups, and runtime metrics. Start with the page that matches what you are trying to understand or change. Deployment logs and application logs answer different questions. Know where to look [#know-where-to-look] | Page | Use it to | | :-------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | **Settings pages** | Use the application sidebar to change the source, build, runtime, storage, health, resource limits, and other application settings. | | **Deployment Logs** | Follow current and previous deployment operations, including source checkout, image build or pull, and container replacement. | | **Backups** | Configure and inspect scheduled archives for eligible application volume and directory mounts. | | **Runtime Logs** | Read stdout and stderr from the application's current containers. | | **Terminal** | Open an interactive shell in a selected running container. | **Runtime Logs** can show containers across the application's functional deployment servers, including preview containers. **Terminal** appears only when terminal access is enabled, your team role can use it, and the application has an eligible running container. It is not available from an application deployed to Docker Swarm. Choose a lifecycle action [#choose-a-lifecycle-action] | Goal | Action | What Coolify does | | :-------------------------------------------------------------- | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Deploy the application for the first time | **Deploy** | Starts the configured deployment flow. | | Apply source, image, build-time, or deployment changes | **Redeploy** | Runs the normal deployment flow again and uses a [rolling update](/applications/deployments/rolling-updates) when supported. | | Recreate the runtime without intentionally rebuilding | **Restart** | Runs the restart path through the deployment queue. A Docker Image application pulls its saved image reference again. | | Rebuild a Coolify-generated source image without build cache | **Force deploy (without cache)** | Starts a deployment with the generated build cache disabled. A custom Docker Compose build command controls its own cache behavior. | | Take the application offline without deleting its configuration | **Stop** | Stops its containers and removes non-persistent container data. Persistent mounts and the Coolify resource remain. | Use **Restart** after a runtime-only change when a rebuild is unnecessary. Use **Redeploy** when source code, the selected image, build arguments, or build-time variables changed. Follow [Deploy applications](/applications/deployments/overview) for deployment history and action details. Diagnose an application problem [#diagnose-an-application-problem] Check the application status [#check-the-application-status] Confirm whether the application is running, stopped, unhealthy, or repeatedly restarting. A restart indicator beside **Runtime Logs** shows when Coolify has recorded container restarts. Inspect the latest deployment [#inspect-the-latest-deployment] Open **Deployment Logs** when the problem began during a deploy, redeploy, or restart. Start with the first failing command rather than the final failure summary. A build or image-pull failure is visible here, not in the runtime application logs. Read the container output [#read-the-container-output] Open **Runtime Logs**, find the affected server and container, then inspect the output around the failure time. Use these logs for application exceptions, crashes, failed startup, connection errors, and process output. When no containers are listed, confirm that the deployment server is functional and the application has a running container. Inspect the running container when necessary [#inspect-the-running-container-when-necessary] Open **Terminal**, select the container, and connect. Use it to check files, environment variables, DNS resolution, network connections, processes, or a health-check command from inside the container. Do not treat terminal changes as configuration. Files installed or edited only inside the container can disappear after a restart or deployment. Put lasting changes in the source, image, environment variables, or persistent storage. Check resource usage [#check-resource-usage] Open **Metrics** when the application is slow, being terminated for resource use, or behaving differently under load. Application metrics require Sentinel and are not available for Docker Compose applications. Follow [Metrics](/core/observability/monitoring/metrics) for enablement, sampling, and retention. Protect application state [#protect-application-state] Data written outside a persistent mount can disappear when Coolify replaces or removes the container. Store uploads, generated files, and other required state in persistent storage, a database, or an external object store. Persistent storage keeps data outside a replaceable container, but it is not a backup. Use the path that matches the data: * [Persistent storage](/core/persistent-storage/storage-mounts/overview) explains volume, directory, and file mounts. * [Storage mount backups](/core/persistent-storage/storage-mounts/backups) covers scheduled archives for eligible application mounts. * [Database backups](/databases/backups) covers database-aware backup commands and schedules. Keep at least one tested backup outside the deployment server. A local backup on the same server does not protect against losing that server. Run recurring work [#run-recurring-work] Use **Scheduled Tasks** for commands that must run inside an application container on a schedule, such as a framework scheduler, queue maintenance, or cache cleanup. A disabled task does not start scheduled executions. An enabled execution fails when the application has no running container or the deployment server is not functional. Follow [Application scheduled tasks](/applications/operations/scheduled-tasks) to configure the command, frequency, timeout, and target container. Use [Tags](/core/automation/tags/overview) to group related resources across projects and environments. Remove or move an application [#remove-or-move-an-application] Use **Stop** when the application should remain configured but offline. Use **Danger Zone** only when you intend to permanently remove the resource; review [Danger Zone](/applications/operations/danger-zone) before deleting it. Use [Resource Operations](/applications/operations/resource-operations) to clone an application to another destination or move it between projects and environments on the same Coolify instance. To move the application and its state to another Coolify control plane, follow [Migrate an application](/applications/operations/migrate-between-instances). Continue operating the application [#continue-operating-the-application] Resource action buttons [#resource-action-buttons] The primary resource action is a one-click button. Use the adjacent dropdown for secondary actions. Confirm destructive actions in the Coolify modal and review the listed effects before continuing. Follow a running operation [#follow-a-running-operation] Use **Deploying… View log** to reopen a running deployment or startup log. Selecting Deploy, Start, or Restart while an operation runs reopens its log. The running-deployments indicator appears in the sidebar, in the top bar on mobile, and on the dashboard. The container log viewer separates **Time**, **Type**, and **Message**. Expand a row to view pretty-printed JSON. If containers cannot be loaded, read the displayed error instead of treating it as proof that none are running. Viewing container logs requires permission to update the resource. API log requests require `read:sensitive` or `root`. # Resource Operations (/docs/applications/operations/resource-operations) Clone or move an application [#clone-or-move-an-application] **Resource Operations** provides these placement actions: * **Clone to another destination** creates another application on a selected server and network destination. * **Clone to another environment** copies the application into another project environment on the current server and network. * **Move resource** changes which project and environment contain the existing application. Neither action moves an application to another Coolify instance. Follow [Migrate an application](/applications/operations/migrate-between-instances) for that process. A clone copies the application configuration into a new, stopped application. The source application continues running and is not changed. Coolify copies storage definitions, but it does not copy the files inside Docker volumes, bind mounts, or directories through this application workflow. Databases and other external state also remain separate. Plan how to copy required state before deploying the clone. The cloned configuration includes application settings, environment variables, preview variables, storage definitions, scheduled tasks, tags, and preview records. Review every copied value before deployment, especially domains, secrets, server paths, and external dependency addresses. Prepare the destination [#prepare-the-destination] Confirm that the destination server is validated, can host resources, and has the required network destination. Build servers cannot be selected because they do not host running resources. Configure any repository, registry, proxy, DNS, and external-service access required by the application on that server. Open Clone Resource [#open-clone-resource] Open the application and select **Resource Operations**. Under **Clone to another destination**, choose **Server**. Select the network destination [#select-the-network-destination] Choose **Network destination** for the selected server, then select **Clone resource**. Coolify creates a stopped application in the current project and environment with a name beginning with `clone-of-`. Review the clone [#review-the-clone] Before deploying, review: * the domain and proxy labels, so the clone does not compete with the source application * production and preview environment variables * source or registry access from the destination server * persistent-storage names and source paths * scheduled tasks, so the clone does not run duplicate recurring work unexpectedly * database, cache, queue, storage, and callback addresses Copy or restore required persistent data separately. A bind-mount path copied from the source configuration must exist on the destination server with the expected files and permissions. Deploy and verify the clone [#deploy-and-verify-the-clone] Deploy the cloned application with a temporary domain. Verify the image, health check, logs, storage, dependencies, and critical application flow before assigning production traffic. Clone into another environment [#clone-into-another-environment] Under **Clone to another environment**, select **Project** and **Environment**, then select **Clone resource**. This keeps the current server and network destination. Review the copied configuration and persistent-storage requirements before deploying the clone. Move the application when it belongs in another project or environment on the same Coolify instance. The application keeps its server, network destination, configuration, domain, and running containers. Use **Clone resource** instead when the application must run on another server or network destination. Choose the target location [#choose-the-target-location] Open **Resource Operations**. Under **Move resource**, choose **Project**. Select **Environment**. Coolify excludes the application's current environment from the available targets. Move the resource [#move-the-resource] Select **Move resource**. Coolify changes the application's project and environment without stopping the running application. Verify the new location [#verify-the-new-location] Confirm that the application appears in the selected project and environment. Open its domain and logs to confirm that the existing runtime remains available. Review project- or environment-level expectations outside the application, such as team conventions, related resources, and automation that uses the old dashboard path. # Scheduled Tasks (/docs/applications/operations/scheduled-tasks) Run scheduled application tasks [#run-scheduled-application-tasks] Scheduled tasks let Coolify run a command inside an application container on a recurring schedule. Use them for framework schedulers, queue maintenance, cleanup commands, imports, and other work that belongs inside the deployed application. Coolify runs the command in a shell inside a running container. The schedule uses the timezone configured for the application's deployment server. This page covers the application workflow. The [Scheduled Tasks section in Core](/core/automation/scheduled-tasks/overview) explains task management, execution history, output downloads, cron behavior, and troubleshooting in more detail. Open Scheduled Tasks [#open-scheduled-tasks] Open the application page [#open-the-application-page] Open the application and select **Scheduled Tasks**. Choose the detailed guide [#choose-the-detailed-guide] Select **+ Add** to start a task, or select an existing task to manage it. Follow the Core guide for the complete field-by-field procedure. Run the first execution [#run-the-first-execution] Open the task and select **Execute now** while the application is running. Open the new record under **Recent executions**. Confirm that it finishes successfully and that its output or effect matches what the command should produce. Application-specific behavior [#application-specific-behavior] When the schedule is due, Coolify finds the application's running container and runs the saved command through `sh`. Before following the detailed guide, check these application-specific requirements: * Test commands that change or delete data through the application **Terminal** first. * Enter the command as it should run inside the container; do not include `docker exec`. * Set **Container** when the application has more than one container. * The schedule uses the timezone configured for the application's deployment server. * **Timeout (seconds)** accepts `60` to `36000` and defaults to `300`. An execution fails when no application container is running, the configured container cannot be found, the command exits with an error, or the command exceeds its timeout. Coolify records the status, timing, and captured output under **Recent executions**. A successful exit does not prove that the command produced the intended application result, so verify the affected records, files, or external system when necessary. Use the detailed Core guides [#use-the-detailed-core-guides] # Bitbucket (/docs/applications/sources/bitbucket) Bitbucket [#bitbucket] Use an HTTPS URL for a [public repository](/applications/sources/public-repositories) or an SSH URL for a [private repository with a deploy key](/applications/sources/deploy-keys). ```sh https://bitbucket.org/example/application.git git@bitbucket.org:example/application.git ``` Add the deploy key's public key under the repository's access-key settings. Configure automatic deployments [#configure-automatic-deployments] 1. Open **Webhooks** in the Coolify application. 2. Copy the **Bitbucket** URL. 3. Enter **Webhook secret** in the **Bitbucket** section, then select **Save changes**. 4. In Bitbucket, open the repository webhook settings. 5. Enter the URL and configure the same secret when supported by the provider flow. 6. Enable **Repository push**. 7. For previews, enable pull request **Created**, **Updated**, **Merged**, and **Declined**. 8. Open **Advanced > Deployment** and choose **Deploy on push (webhooks)** in **Auto deploy** in Coolify. Push to the configured branch and inspect **Deployment Logs**. Open or update a pull request to verify preview events separately. # Cursor Origin (/docs/applications/sources/cursor-origin) Cursor Origin [#cursor-origin] Coolify can deploy a private [Cursor Origin](https://cursor.com/origin) repository over SSH. Store the private key in Coolify, add the matching SSH key to Origin, and then create the application with the deploy-key source. Add a deploy key to Coolify [#add-a-deploy-key-to-coolify] 1. Open **Keys & Tokens** in the Coolify dashboard. 2. Select **Private Keys**, then **New private key**. 3. Choose **Generate ED25519** or **Generate RSA** to generate and save a key immediately. To use an existing key, choose **Add manually**, paste the complete private key, and select **Continue**. 4. Open the saved key's edit icon to inspect its public key or change its name. Select **Save changes** after editing. Keep the key available while configuring Origin. Origin must use the same key that you stored in Coolify. Add the key to Origin [#add-the-key-to-origin] From the repository directory, run: ```bash origin ssh-key add ``` Follow the Origin CLI prompts and add the SSH key that corresponds to the private key saved in Coolify. Create the application in Coolify [#create-the-application-in-coolify] 1. Open your project in Coolify and select **+ New**. 2. Select **Private Repository (with deploy key)**. 3. Choose the server that will run the application. 4. Select the private key that you saved in the first step. 5. Enter the repository's SSH clone URL and continue. 6. Configure the application, then deploy it. The deploy key authenticates an SSH connection. An HTTPS repository URL will not use it. For more information about this source type, see [Deploy keys](/applications/sources/deploy-keys). For build and application settings, see [Applications](/applications). # Deploy Keys (/docs/applications/sources/deploy-keys) Deploy keys [#deploy-keys] A deploy key grants one SSH key access to one private repository. Use it when you cannot install a Git App or when repository-specific access is preferred. Create a deploy key [#create-a-deploy-key] Generate a key in Coolify [#generate-a-key-in-coolify] Open **Keys & Tokens > Private Keys**, select **New private key**, then **Generate ED25519** or **Generate RSA**. Coolify saves the key immediately. Open the saved key's edit icon to give it a name that identifies the repository, select **Save changes**, and copy **Public key**. Add the public key to the repository [#add-the-public-key-to-the-repository] Open the repository's deploy-key or access-key settings and add the copied public key. Keep write access disabled. Coolify only needs to clone and fetch the repository. Copy the SSH repository URL [#copy-the-ssh-repository-url] Use the provider's SSH clone URL: ```sh git@github.com:coollabsio/coolify-examples.git ``` Do not use the HTTPS URL for **Private Repository (with deploy key)**. Create the application [#create-the-application] Open a project, select **+ New**, then **Private Repository (with deploy key)**. Choose the server, select the stored private key, paste the SSH URL, and configure the application. Deploy and verify [#deploy-and-verify] Select **Deploy**. Confirm the repository clone and requested branch succeed in the deployment log. Automatic deployments [#automatic-deployments] The SSH key only provides repository access. Choose how the deployment starts. Add a [manual Git webhook](/applications/deployments/manual-webhooks), then choose **Deploy on push (webhooks)** under **Advanced > Deployment > Auto deploy**. The provider can then notify Coolify when the configured branch changes. Use a [GitHub App](/applications/sources/github/app) instead when you want GitHub repository selection and webhook configuration through one integration. Call the authenticated **Deploy Webhook** from GitHub Actions or another CI system after its checks pass. The deployment step in the [GitHub Actions example](/applications/sources/github/actions#example-workflow) shows the authentication pattern. Key scope [#key-scope] Prefer a separate deploy key for each repository. If a key is exposed, remove it from the repository and Coolify, create a replacement, attach the new key under **Git Source**, and redeploy. # Gitea (/docs/applications/sources/gitea) Gitea [#gitea] Use an HTTPS URL for a [public repository](/applications/sources/public-repositories) or an SSH URL for a [private repository with a deploy key](/applications/sources/deploy-keys). ```sh https://gitea.example.com/example/application.git git@gitea.example.com:example/application.git ``` Add the deploy key's public key to the repository before creating the private application. Configure automatic deployments [#configure-automatic-deployments] 1. Open **Webhooks** in the Coolify application. 2. Copy the **Gitea** URL. 3. Enter **Webhook secret** in the **Gitea** section, then select **Save changes**. 4. In Gitea, open the repository webhook settings. 5. Enter the URL and the same secret. 6. Enable **Push**. 7. Enable pull-request events when using preview deployments. 8. Open **Advanced > Deployment** and choose **Deploy on push (webhooks)** in **Auto deploy** in Coolify. Verify a push deployment first. Then open or update a pull request and inspect **Preview Deployments**. # GitHub Actions (/docs/applications/sources/github/actions) GitHub Actions [#github-actions] GitHub Actions can run checks, build your application as a Docker image, publish it to a container registry, and trigger Coolify only after the preceding steps pass. For a working reference, review the [`github-actions`](https://github.com/coollabsio/coolify-examples/tree/main/github-actions) example and its [workflow file](https://github.com/coollabsio/coolify-examples/blob/main/github-actions/.github/workflows/build.yaml). Build and deploy [#build-and-deploy] This guide uses: * **Docker image:** `ghcr.io/shadowarcanist/tasklytics:latest` * **Registry:** `ghcr.io` * **Branch:** `main` Replace these values with your registry and image. Choose the deployment type [#choose-the-deployment-type] GitHub Actions builds the image, so Coolify must deploy the published image instead of rebuilding the same source. Choose one: * Create a [Docker Image application](/applications/deployments/docker-image) for one image. * Use [Docker Compose](/applications/builds/docker-compose) when the deployment contains multiple services. Reference the published image with `image:` instead of `build:`. ```yaml services: web: image: ghcr.io/shadowarcanist/tasklytics:latest ``` Authenticate the deployment server before using a private image. Enable Coolify API access [#enable-coolify-api-access] On a self-hosted Coolify instance: 1. Open **Settings**. 2. Select **Advanced**. 3. In **API and MCP**, set **API access** to **Enabled**. 4. Select **Save changes**. Coolify Cloud has API access enabled by default. Cloud users cannot access the self-hosted **API access** settings, so skip this step. Create a Coolify API token [#create-a-coolify-api-token] 1. Open **Keys & Tokens > API Tokens**. 2. Enter a **Description** that identifies the workflow. 3. Choose **Expires in** to set the token lifetime. 4. Open **Permissions** and select **Deploy**. 5. Select **Create token**. 6. Copy the token immediately. Store it in a password manager until it has been added to GitHub. Copy the deploy webhook [#copy-the-deploy-webhook] 1. Open the application. 2. Select **Webhooks**. 3. Copy **Deploy webhook URL**. The URL identifies the application. The API token authorizes the request. Add GitHub repository secrets [#add-github-repository-secrets] 1. Open the GitHub repository settings. 2. Select **Secrets and variables > Actions**. 3. Select **New repository secret**. 4. Create `COOLIFY_WEBHOOK` with the authenticated deploy webhook URL. 5. Select **New repository secret** again. 6. Create `COOLIFY_TOKEN` with the Coolify API token. Do not commit either value to the workflow file. Add the GitHub Actions workflow [#add-the-github-actions-workflow] Create `.github/workflows/build.yaml`: ```yaml name: Build and deploy on: push: branches: [main] env: REGISTRY: ghcr.io IMAGE_NAME: shadowarcanist/tasklytics jobs: build-and-deploy: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image uses: docker/build-push-action@v6 with: context: . file: Dockerfile platforms: linux/amd64 push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - name: Trigger Coolify deployment run: | curl --fail --request POST '${{ secrets.COOLIFY_WEBHOOK }}' \ --header 'Authorization: Bearer ${{ secrets.COOLIFY_TOKEN }}' ``` The workflow builds and publishes the image before asking Coolify to deploy it. Keep the Coolify request after tests, security checks, the image build, and the registry push. Otherwise, Coolify can pull the previous image or deploy a release that has not passed validation. For immutable releases, publish a commit-specific tag and update the deployed image reference as part of the release process instead of relying only on `latest`. Authenticate the deployment server [#authenticate-the-deployment-server] For a private registry, connect to every deployment server that must pull the image and authenticate Docker as the server user configured in Coolify. Create a GitHub token that can read packages, then run: ```bash echo "$GH_TOKEN" | docker login ghcr.io --username "$GITHUB_USERNAME" --password-stdin ``` Run: ```bash docker login ``` Use a Docker Hub access token instead of the account password when possible. Trigger the workflow and confirm: 1. GitHub Actions publishes the expected image. 2. The Coolify request succeeds. 3. Coolify pulls the new image. 4. The application container starts and becomes healthy. # Set Up a GitHub App (/docs/applications/sources/github/app) Set up a GitHub App [#set-up-a-github-app] A GitHub App gives Coolify access to one repository, selected repositories, or every repository in a personal account or organization. Use a GitHub App when you want repository selection, automatic deployments, and pull-request events through one integration. Use a [deploy key](/applications/sources/deploy-keys) when you cannot install a GitHub App or need read-only access to one repository. Choose an installation method [#choose-an-installation-method] * **Automated installation** uses GitHub's manifest flow to configure the required permissions, webhook, credentials, and callback. Use this method for GitHub.com. * **Manual installation** requires you to create the app, permissions, events, credentials, private key, and installation yourself. Use it for GitHub Enterprise or a custom permission setup. Automated installation is recommended because it reduces the number of credentials and settings you must transfer manually. The screenshots use these example values: * **GitHub App name in Coolify:** `GitHub App Tutorial` * **GitHub App name on GitHub:** `coolify-github-app-tutorial` * **Webhook endpoint:** `https://coolboxy.shadowarcanist.internal` Replace them with your own name and public Coolify URL. 1\. Create a GitHub App source in Coolify [#1-create-a-github-app-source-in-coolify] 1. Open **Sources** from the Coolify sidebar. 2. Select **New source > GitHub App**. 3. Enter a name for the source. 4. Enter the GitHub organization name when the app belongs to an organization. Leave **Organization** empty for a personal account. 5. Under **Use this App for**, select **Pull request previews** if you need preview deployments. Select **Continue**. For self-hosted GitHub Enterprise, expand **Self-hosted / Enterprise GitHub** and enter its HTML URL, API URL, Git user, and Git port. On self-hosted Coolify, **System wide** makes the GitHub App available to every team on the instance. Leave it disabled when only the current team should use the app. Coolify Cloud does not offer this setting because a source cannot be shared with other Cloud customers. 2\. Choose automated installation [#2-choose-automated-installation] Use the **Automated installation** section. In **Webhook endpoint**, choose **Use an instance endpoint** and select an **Instance endpoint**. Choose **Use a custom endpoint** and enter **Custom endpoint** when GitHub must call a different public URL, such as a domain exposed through a tunnel. Enter only the base URL, such as `https://coolify.example.com`. Do not append `/webhooks`. Repository access can work while automatic and preview deployments fail if GitHub cannot reach this endpoint. Set **Preview deployment access** to **Read and update pull requests** when Coolify should add deployment information to pull requests. This grants read-and-write access to pull requests. The mandatory permissions grant read access to repository contents, metadata, and email addresses. Select **Register with GitHub**. 3\. Register the app on GitHub [#3-register-the-app-on-github] 1. Enter a unique GitHub App name. 2. Select **Create GitHub App**. GitHub returns you to Coolify after creating the app. Coolify stores the generated App ID, client credentials, webhook secret, and private key. 4\. Install repository access [#4-install-repository-access] Select **Install repositories** in the repository-access prompt shown after registration. Choose **All repositories** or **Only select repositories**, then select **Install**. Use selected repositories when the app does not need account-wide access. After GitHub returns to Coolify, confirm that the source shows an installation and repository-management actions. 5\. Create an application [#5-create-an-application] 1. Open the required project and environment. 2. Select **+ New**. 3. Select **Private Repository (with GitHub App)**. 6\. Choose the deployment server [#6-choose-the-deployment-server] A self-hosted installation starts with a **localhost** server. Coolify selects it automatically when no other deployment server is available. Choose the server where the application should run. 7\. Choose the GitHub App [#7-choose-the-github-app] Select the GitHub App source you created. 8\. Configure and deploy the application [#8-configure-and-deploy-the-application] Choose a repository and select **Load Repository**. Choose the branch, **Build pack**, base directory, internal port, and any required build settings. Read [Build applications](/applications/builds/overview) when you need help choosing a build method. Select **Continue**, configure the application domain and variables, then deploy it. Open **Deployment Logs** and confirm that Coolify clones the selected repository and commit. Use manual installation for self-hosted GitHub Enterprise or when you must control the GitHub App configuration yourself. You will transfer these values to Coolify: * App ID * Installation ID * Client ID * Client Secret * Webhook Secret * GitHub App private key 1\. Create the source in Coolify [#1-create-the-source-in-coolify] Open **Sources** and select **New source > GitHub App**. Enter the source name and optional organization, then select **Continue**. The same **System wide** and self-hosted GitHub settings described in the automated path apply. In **Manual installation**, select **Continue manually**. Coolify opens the source fields where you will later enter the GitHub App credentials. 2\. Open GitHub App settings [#2-open-github-app-settings] GitHub places app creation under different account settings. 1. Open your GitHub account settings. 2. Select **Developer settings**. 3. Select **GitHub Apps**. 4. Select **New GitHub App**. 1. Open the GitHub organization settings. 2. Select **Developer settings**. 3. Select **GitHub Apps**. 4. Select **New GitHub App**. 3\. Configure the GitHub App [#3-configure-the-github-app] 1. Enter a unique **GitHub App name**. 2. Enter the public Coolify URL as the **Homepage URL**. Set the webhook URL to: ```txt https://coolify.example.com/webhooks/source/github/events ``` Replace `https://coolify.example.com` with the public URL of your Coolify instance. Generate a long random **Webhook secret**, save it in a password manager, and enable **SSL verification**. Under **Repository permissions**, grant: | Permission | Access | | :-------------- | :-------------------------------------------------------- | | Contents | Read-only | | Metadata | Read-only | | Email addresses | Read-only | | Pull requests | Read and write only when preview deployments are required | Under **Subscribe to events**: 1. Enable **Push**. 2. Enable **Pull request** when preview deployments are required. 3. Limit installation to the current account unless other accounts must install this app. 4. Select **Create GitHub App**. 4\. Collect the app credentials [#4-collect-the-app-credentials] Copy the **App ID** and **Client ID**. Select **Generate a new client secret**, then copy the generated **Client Secret**. Under **Private keys**, select **Generate a private key**. GitHub downloads a `.pem` file. Keep the Client Secret, Webhook Secret, and private key confidential. 5\. Install the app and find the Installation ID [#5-install-the-app-and-find-the-installation-id] Open **Install App**, then select **Install** for the required account or organization. Choose all repositories or selected repositories, then complete the installation. Open the installation settings. Copy the numeric Installation ID from the URL after `/installations/`. 6\. Add the private key and credentials to Coolify [#6-add-the-private-key-and-credentials-to-coolify] 1. Open **Keys & Tokens > Private Keys**. 2. Select **New private key > Add manually**. 3. Give the key a descriptive name. 4. Paste the complete contents of the `.pem` file. 5. Select **Continue** to save the private key. 6. Return to **Sources**, open the GitHub App, and select **General**. 7. Enter the App ID, Installation ID, Client ID, Client Secret, and the same Webhook Secret configured on GitHub. 8. Select the private key you added. 9. Select **Save changes**. 10. Select **Sync name**. A successful sync confirms that Coolify can authenticate as the GitHub App. 7\. Create and deploy an application [#7-create-and-deploy-an-application] Open a project and environment, then select **+ New**. Select **Private Repository (with GitHub App)**. Choose the deployment server. Select the manually created GitHub App. Choose the repository and select **Load Repository**. Choose the branch and build settings, then continue to the application configuration and deploy it. Confirm the repository clone and selected commit in **Deployment Logs**. *** Change repository access [#change-repository-access] Open **Sources**, select the GitHub App, open **General**, then select **Repositories**. Change the installation's repository access on GitHub and return to Coolify. Refresh the repository list before creating another application. Removing repository access prevents new clones and webhook deployments for applications that use that repository. # GitHub Auto Deploy (/docs/applications/sources/github/auto-deploy) GitHub Auto Deploy [#github-auto-deploy] Coolify can deploy a new version of your application whenever you push changes to its GitHub repository. Choose how GitHub starts the deployment. Deploy through a GitHub App [#deploy-through-a-github-app] Follow [Set up a GitHub App](/applications/sources/github/app) first. Coolify sets **Auto deploy** to **Deploy on push (webhooks)** for applications created through a GitHub App. If it is set to **Manual deployments only**: 1. Open the application. 2. Open **Advanced > Deployment**. 3. Choose **Deploy on push (webhooks)** in **Auto deploy**. 4. Push a commit to the configured branch and confirm that a deployment appears. Deploy through GitHub Actions [#deploy-through-github-actions] Use [GitHub Actions](/applications/sources/github/actions) when a workflow should run tests, build and publish an image, and then request a Coolify deployment. Deploy through a repository webhook [#deploy-through-a-repository-webhook] Use this path for a public repository or a private repository connected through a deploy key. Enable Auto Deploy [#enable-auto-deploy] 1. Open the application. 2. Open **Advanced > Deployment**. 3. Choose **Deploy on push (webhooks)** in **Auto deploy**. Configure the GitHub webhook secret [#configure-the-github-webhook-secret] 1. Open **Webhooks**. 2. Enter a random **Webhook secret** in the **GitHub** section. 3. Select **Save changes**. 4. Copy the GitHub URL under **Manual Git webhooks**. The secret authenticates webhook deliveries. Store it like a password and use the same value in Coolify and GitHub. Add the webhook on GitHub [#add-the-webhook-on-github] 1. Open the GitHub repository settings. 2. Select **Webhooks**. 3. Select **Add webhook**. 4. Paste the Coolify webhook URL into **Payload URL**. 5. Enter the same secret in **Secret**. 6. Keep **Enable SSL verification** selected. 7. Select **Just the push event**. 8. Keep **Active** selected. 9. Select **Add webhook**. Push a commit to the configured branch. Confirm that GitHub records a successful webhook delivery and Coolify starts a deployment. # GitHub Deploy Key (/docs/applications/sources/github/deploy-key) GitHub Deploy Key [#github-deploy-key] A deploy key gives Coolify read-only SSH access to one private GitHub repository without using a personal access token or an account-level SSH key. Use a deploy key when: * Coolify should access only one private repository * you cannot install a GitHub App in the organization * repository-specific read-only access is preferred Use a [GitHub App](/applications/sources/github/app) when Coolify needs integrated access to several repositories. This guide uses: * **Repository owner:** `ShadowArcanist` * **Repository name:** `coolify-dev` * **Key name:** `Deploy Key Tutorial` * **SSH URL:** `git@github.com:ShadowArcanist/coolify-dev.git` Create a private key in Coolify [#create-a-private-key-in-coolify] 1. Open **Keys & Tokens**. 2. Select **Private Keys**. 3. Open **New private key**. 4. Select **Generate RSA** or **Generate ED25519**. 5. Coolify saves the generated key immediately. Select its **Edit** icon. 6. Copy the **Public key**. Run: ```bash ssh-keygen -t rsa -b 4096 -C "coolify-deploy-key" ``` Paste the generated private key into Coolify and use the matching `.pub` file on GitHub. Add the deploy key on GitHub [#add-the-deploy-key-on-github] 1. Open the repository settings. 2. Select **Deploy keys**. 3. Select **Add deploy key**. The direct URL has this form: ```txt https://github.com/OWNER/REPOSITORY/settings/keys ``` 4. Enter a descriptive title. 5. Paste the public key copied from Coolify. 6. Keep **Allow write access** disabled. 7. Select **Add key**. Copy the repository SSH URL [#copy-the-repository-ssh-url] 1. Open the GitHub repository. 2. Select **Code > Local > SSH**. 3. Copy the SSH URL, such as `git@github.com:ShadowArcanist/coolify-dev.git`. Create a resource [#create-a-resource] Open the required project and environment, then select **+ New**. Select the deploy-key resource type [#select-the-deploy-key-resource-type] Select **Private Repository (with Deploy Key)**. Choose the server [#choose-the-server] A self-hosted installation starts with a **localhost** server. Coolify selects it automatically when no other deployment server is available. Choose the server where the application should run. Choose the deploy key [#choose-the-deploy-key] Select the private key created in Coolify. Configure and deploy [#configure-and-deploy] 1. Paste the GitHub SSH URL. 2. Choose the branch, **Build pack**, internal port, and other required settings. 3. Continue to the application configuration and deploy it. Open **Deployment Logs** and confirm that Coolify clones the private repository and requested commit. Follow [GitHub Auto Deploy](/applications/sources/github/auto-deploy) to deploy new commits through a repository webhook. # Overview (/docs/applications/sources/github/overview) GitHub [#github] Coolify can deploy a GitHub repository through a public HTTPS URL, a repository deploy key, or a GitHub App. | Method | Best for | Guide | | :---------------- | :------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------- | | Public repository | Public source that needs no authentication. | [Deploy a public GitHub repository](/applications/sources/github/public-repository) | | Deploy key | One private repository or an organization where you cannot install an app. | [Use a GitHub deploy key](/applications/sources/github/deploy-key) | | GitHub App | Selected public or private repositories with integrated push and pull-request events. | [Set up a GitHub App](/applications/sources/github/app) | | GitHub Actions | Build and publish an image in GitHub before Coolify deploys it. | [Build and deploy with GitHub Actions](/applications/sources/github/actions) | Use a [GitHub App](/applications/sources/github/app) for the most complete integration. Its repository installation controls which repositories Coolify can list and clone. Continue with [GitHub Auto Deploy](/applications/sources/github/auto-deploy) for push-triggered deployments or [GitHub Preview Deployments](/applications/sources/github/preview-deploy) for pull requests. GitHub Container Registry is independent from repository access. Read [Docker registries](/applications/builds/docker-registries) when the deployment pulls or pushes `ghcr.io` images. # GitHub Preview Deployments (/docs/applications/sources/github/preview-deploy) GitHub Preview Deployments [#github-preview-deployments] Preview deployments run pull requests separately from the production application. Coolify removes an automatic preview after its pull request is merged or closed. Features [#features] Preview domains [#preview-domains] **Preview URL Template** controls the generated domain: * `{{random}}` inserts a random value. * `{{pr_id}}` inserts the pull-request number. To use a domain such as `https://123.preview.example.com`, create an `A` or `AAAA` record for `*.preview.example.com` that points to the deployment server. **Load Pull Requests** fetches currently open pull requests. Coolify does not automatically deploy pull requests that were already open when preview deployments were enabled. Select **Load Pull Requests**, then select **Deploy** for each required pull request. Choose who can deploy previews [#choose-who-can-deploy-previews] Pull-request code can be untrusted. A public contributor could otherwise run code on your server. * **Preview Deployments** enables previews for trusted repository members, collaborators, and contributors. * **Allow Public PR Deployments** allows public contributors to trigger previews. Keep public pull-request deployments disabled unless you accept the risk of running contributor code. Scoped secrets [#scoped-secrets] Coolify keeps production and preview variables separate. * **Production Environment Variables** are used only by the main deployment and are not passed to pull-request previews. * **Preview Deployment Environment Variables** are used only by pull-request deployments. Do not copy production credentials into preview variables for untrusted pull requests. Use limited, non-production credentials. Automated comments [#automated-comments] Coolify can add deployment status and domain information to the pull request and update the comment when the deployment state changes. Manual repository webhooks can trigger previews, but automated pull-request comments require GitHub App permissions. *** Set up preview deployments [#set-up-preview-deployments] Choose how the application receives pull-request events. Follow [Set up a GitHub App](/applications/sources/github/app) first. Set **Preview deployment access** to **Read and update pull requests** before selecting **Register with GitHub**. Coolify requests read-and-write pull-request access and subscribes the app to pull-request events. When creating the app on GitHub: 1. Set **Pull requests** to **Read and write** under **Repository permissions**. 2. Subscribe to the **Pull request** event. Update an existing GitHub App [#update-an-existing-github-app] 1. Open **Sources** and select the GitHub App. 2. Open **Permissions**. 3. Select **Update**. 4. Set **Pull requests** to **Read and write**. 5. Subscribe to **Pull request** events. 6. Accept the permission update. 1. Open **Webhooks**. 2. Enter a random **Webhook secret** in the **GitHub** section and select **Save changes**. 3. Copy the GitHub URL under **Manual Git webhooks**. The secret authenticates webhook deliveries. Use the same value in Coolify and GitHub. 4. Open the repository settings on GitHub. 5. Select **Webhooks > Add webhook**. 6. Paste the Coolify URL into **Payload URL**. 7. Enter the same secret. 8. Keep **Enable SSL verification** selected. 9. Choose **Let me select individual events**. 10. Select **Pull requests**. 11. Keep **Active** selected. 12. Select **Add webhook**. *** Verify preview deployments [#verify-preview-deployments] 1. Open or update a pull request. 2. Confirm that Coolify creates a separate preview deployment. 3. Open the generated preview domain and test the changed behavior. 4. Close the pull request and confirm that Coolify removes the automatic preview. # Deploy a Public GitHub Repository (/docs/applications/sources/github/public-repository) Deploy a public GitHub repository [#deploy-a-public-github-repository] You can deploy any public GitHub repository without creating a GitHub App or deploy key. Create a resource [#create-a-resource] 1. Open the required project and environment. 2. Select **+ New**. Select Public Repository [#select-public-repository] Select **Public Repository**. Choose the server [#choose-the-server] A self-hosted installation starts with a **localhost** server. Coolify selects it automatically when no other deployment server is available. Choose the server where the application should run. Enter the repository URL [#enter-the-repository-url] Paste the public GitHub repository URL. Coolify selects `main` for: `https://github.com/coollabsio/coolify-examples` Coolify selects `next` for: `https://github.com/coollabsio/coolify-examples/tree/next` Configure and deploy [#configure-and-deploy] 1. Select **Check Repository**. 2. Choose the **Build pack**, internal port, base directory, and other required settings. 3. Continue to the application configuration. 4. Configure a domain and required variables. 5. Deploy the application. Read [Build applications](/applications/builds/overview) when you need help choosing the build method. Open **Deployment Logs** and confirm the repository, branch, and commit in the deployment log. # Switch GitHub Apps (/docs/applications/sources/github/switch-apps) Switch GitHub Apps [#switch-github-apps] Switch the GitHub App used by an application when a repository moves to another account or organization, or when you want a different access policy. The replacement GitHub App must have access to the repository before Coolify can clone from it. 1\. Move the repository when needed [#1-move-the-repository-when-needed] Transfer the repository on GitHub when it is moving to another account or organization. Skip this step when the repository stays in the same location and only its GitHub App access changes. 2\. Add the replacement GitHub App [#2-add-the-replacement-github-app] Follow [Set up a GitHub App](/applications/sources/github/app) and install it for the required repository. Keep the existing GitHub App installed until the application has deployed successfully through the replacement. 3\. Confirm repository access [#3-confirm-repository-access] 1. Open **Sources** and select the replacement GitHub App. 2. Open **General** and select **Repositories**. 3. Under **Repository access** on GitHub, confirm that the application repository is selected. 4. Return to Coolify and refresh the repository list. 4\. Change the application source [#4-change-the-application-source] 1. Open the application. 2. Select **Git Source**. 3. Under **Git source**, select the replacement GitHub App. 4. Confirm the change. 5\. Update the repository name when needed [#5-update-the-repository-name-when-needed] If the repository moved to another account or organization, update **Repository** from the previous `owner/repository` value to its new location. Skip this step when the repository owner and name did not change. 6\. Redeploy and verify [#6-redeploy-and-verify] 1. Select **Save changes** after editing the repository fields. 2. Select **Redeploy**. 3. Open **Deployment Logs** and confirm that Coolify clones the expected repository and commit. 4. Push a test commit to the configured branch. 5. Confirm that the replacement GitHub App delivers the webhook and Coolify starts a webhook deployment. Remove the previous GitHub App only after every application that uses it has been switched and verified. # GitLab (/docs/applications/sources/gitlab) GitLab [#gitlab] Coolify can deploy GitLab repositories through a public HTTPS URL, an SSH deploy key, or a GitLab App. | Method | Best for | Repository access | | :---------------- | :------------------------------------------------------------------------------------ | :----------------------------------------- | | Public repository | Public source that needs no authentication | HTTPS URL | | Deploy key | One private repository or a GitLab instance where an OAuth application is unavailable | SSH URL and repository deploy key | | GitLab App | Private repositories on GitLab.com or a self-managed GitLab instance | OAuth application with repository browsing | Set up a GitLab App [#set-up-a-gitlab-app] GitLab App integration is available in Coolify v4.3.0 or above A GitLab App lets Coolify list repositories and branches, clone private source over HTTPS, and receive push and merge-request events. Add the source in Coolify [#add-the-source-in-coolify] Open **Sources** and select **New source > GitLab App**. Enter **Name** and optionally comma-separated values in **Group name** to limit the repositories Coolify lists. For a self-managed instance, expand **Self-hosted GitLab** and enter **GitLab URL** and **API URL**. GitLab.com is the default. On a self-hosted Coolify instance, enable **System wide** only when every team should be able to select this source. Otherwise, keep the source scoped to the active team. Select **Continue**. Coolify displays the redirect URI required by the OAuth application. Create the OAuth application in GitLab [#create-the-oauth-application-in-gitlab] In GitLab, open **User Settings > Applications**. A group or instance administrator can create the application at group or instance level when ownership should not belong to one user. Create an application with: * the exact redirect URI shown by Coolify * `api`, `read_user`, and `read_repository` scopes Save the application, then copy its **Application ID** and **Secret**. Connect Coolify to GitLab [#connect-coolify-to-gitlab] Return to the GitLab source in Coolify. Enter the Application ID and Secret, confirm the GitLab and API URLs, then save the credentials. Select **Connect to GitLab** and authorize the OAuth application. Use **Test Connection** after GitLab redirects back to Coolify. Configure repository webhooks [#configure-repository-webhooks] Copy the webhook URL and secret token from the connected source. In each GitLab project that should deploy automatically, open **Settings > Webhooks**, add the URL and matching secret token, then enable: * **Push events** for branch deployments * **Merge request events** for preview deployments Coolify rejects GitLab webhook requests when the secret token is missing or does not match. Deploy a repository [#deploy-a-repository] Open a Coolify project, select **+ New**, then select **Private Repository (with GitLab App)**. Choose the server and connected GitLab App, load the repositories, select a repository and branch, then configure and deploy the application. Verify that the deployment log clones the selected repository and checks out the requested commit. Use a deploy key [#use-a-deploy-key] Use a deploy key when Coolify only needs one private repository or cannot connect to the GitLab instance through OAuth. 1. Add a private key under **Keys & Tokens > Private Keys**. 2. Add its public key under the GitLab repository's **Settings > Repository > Deploy keys**. 3. Copy the repository SSH URL, such as `git@gitlab.com:example/application.git`. 4. In Coolify, create **Private Repository (with deploy key)** and select the stored key. Read [Deploy keys](/applications/sources/deploy-keys) for the complete setup and security guidance. Configure a manual GitLab webhook [#configure-a-manual-gitlab-webhook] For an application created from a public URL or deploy key: 1. Open **Webhooks** in the Coolify application. 2. Copy the **GitLab** webhook URL and enter **Webhook secret** in the **GitLab** section, then select **Save changes**. 3. In GitLab, open **Settings > Webhooks** and enter the same URL and secret. 4. Enable push events and, when using preview deployments, merge-request events. 5. Open **Advanced > Deployment** and choose **Deploy on push (webhooks)** in **Auto deploy** in Coolify. Test the webhook from GitLab, then push to the configured branch and inspect **Deployment Logs** in Coolify. Use GitLab Container Registry [#use-gitlab-container-registry] Repository credentials do not authenticate Docker to GitLab Container Registry. For a private registry, create a GitLab deploy token with `read_registry` and authenticate Docker on every server that pulls the image: ```bash echo "$GITLAB_REGISTRY_TOKEN" | \ docker login registry.gitlab.com \ --username "$GITLAB_REGISTRY_USER" \ --password-stdin ``` Use the complete image reference, including its tag, in a Docker Image or Docker Compose application. Read [Docker registries](/applications/builds/docker-registries) for server authentication and build-server requirements. # Other Git Providers (/docs/applications/sources/other-providers) Other Git providers [#other-git-providers] Coolify can deploy from another Git-compatible provider, including Forgejo, Gogs, and self-hosted Git servers. Use: * [Public Repository](/applications/sources/public-repositories) with an unauthenticated HTTPS clone URL * [Private Repository (with deploy key)](/applications/sources/deploy-keys) with an SSH clone URL The deployment server must be able to resolve and reach the Git host. Automatic deployments [#automatic-deployments] The manual provider webhooks in Coolify have provider-specific payload and signature handling for GitHub, GitLab, Bitbucket, and Gitea. For another provider, use its CI or workflow system to call **Deploy webhook URL** after the required checks pass: ```bash curl --fail --request POST "$COOLIFY_WEBHOOK" \ --header "Authorization: Bearer $COOLIFY_TOKEN" ``` Store the webhook URL and API token as protected CI secrets. Preview deployments [#preview-deployments] Automatic pull-request previews require a supported provider event format. If the provider is not supported, use the Coolify API or a deployment webhook from CI to implement the required preview workflow, or deploy previews manually. Test the clone, one manual deployment, and one automated deployment before depending on the integration for production releases. # Overview (/docs/applications/sources/overview) Connect source code [#connect-source-code] Git-based applications need a repository URL, branch, and authentication method that Coolify can use from the deployment path. Use HTTPS for a public repository, an SSH deploy key for one private repository, or a GitHub App for scoped repository access with integrated webhooks. *** Choose a source method [#choose-a-source-method] | Method | When to use it | Guide | | :---------------- | :------------------------------------------------------------------------------------ | :----------------------------------------------------------------------- | | Public repository | The repository is public and can be cloned over HTTPS without credentials. | [Connect a public repository](/applications/sources/public-repositories) | | Deploy key | One private repository needs read-only SSH access. | [Use a deploy key](/applications/sources/deploy-keys) | | GitHub App | GitHub repositories need scoped access, integrated webhooks, and pull-request events. | [Configure a GitHub App](/applications/sources/github/app) | Official Git App integrations configure provider webhooks as part of the source. Public repositories and deploy keys require [manual webhooks](/applications/deployments/manual-webhooks) for automatic deployments and previews. Repository access and container registries are separate [#repository-access-and-container-registries-are-separate] Git credentials let Coolify clone source code. Registry credentials let Docker pull or push images. A deploy key cannot authenticate to a private container registry. Read [Docker registries](/applications/builds/docker-registries) when the application uses a private image or pushes a built image. Choose the next source guide [#choose-the-next-source-guide] # Public Repositories (/docs/applications/sources/public-repositories) Public repositories [#public-repositories] Use **Public Repository** when the repository can be cloned over HTTPS without authentication. Create the application [#create-the-application] Copy the HTTPS URL [#copy-the-https-url] Copy the repository's clone URL: ```sh https://github.com/coollabsio/coolify-examples.git ``` Do not use an SSH URL for this source type. Select Public Repository [#select-public-repository] Open a project, select **+ New**, then select **Public Repository**. Choose the deployment server when Coolify asks for one. Check the repository [#check-the-repository] Paste the HTTPS URL and select **Check Repository**. Coolify loads the repository and branch information. If the URL contains a GitHub branch path (for example, `https://github.com/ShadowArcanist/netviz/tree/v2`), Coolify preselects that branch. Otherwise, review the selected branch before continuing. Configure and deploy [#configure-and-deploy] Choose the [**Build pack**](/applications/builds/overview), base directory, and required build settings. Configure the internal port and a domain when the application should be public. Select **Deploy** and inspect the deployment log. Enable automatic deployments [#enable-automatic-deployments] Connecting a public repository by URL does not configure automatic deployments. Use a repository webhook or an external workflow to deploy new commits automatically. Add a [manual Git webhook](/applications/deployments/manual-webhooks), then choose **Deploy on push (webhooks)** under **Advanced > Deployment > Auto deploy**. The provider can then notify Coolify when the configured branch changes. Use a [GitHub App](/applications/sources/github/app) instead when you want GitHub repository selection and webhook configuration through one integration. Call the authenticated **Deploy Webhook** from GitHub Actions or another CI system after its checks pass. The deployment step in the [GitHub Actions example](/applications/sources/github/actions#example-workflow) shows the authentication pattern. # What is an application (/docs/applications/what-is-an-application) What is an application [#what-is-an-application] An application is a workload that Coolify deploys and manages as one or more Docker containers on a connected server. You provide a Git repository, Dockerfile, or image reference. A Git repository can also contain a Docker Compose definition. Coolify coordinates image preparation, runtime configuration, domains, health checks, logs, and lifecycle actions. What an application includes [#what-an-application-includes] | Part | Purpose | | :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Deployment input | A Git repository, a Dockerfile entered without Git, or an existing Docker image reference. A Git repository can use Docker Compose as its build pack. | | Build method | How Coolify prepares required images from Git source. Most methods build one image; Docker Compose can build or pull an image for each service. Docker Image applications skip this stage. | | Runtime configuration | Environment variables, domains, ports, networks, storage, health checks, and resource limits. | | Deployment history | The queued and completed operations that build or pull images, apply runtime configuration, and start containers. | | Operations | Logs, terminal access, backups, rollbacks, metrics, tags, and lifecycle actions. | What Coolify manages [#what-coolify-manages] Coolify stores the application configuration and coordinates Docker on the selected server. Depending on the deployment method, Coolify can: * clone a Git repository * build or pull Docker images * create runtime environment files * attach networks and persistent storage * configure proxy routing for application domains * start, stop, restart, and replace containers * record deployment status and logs The connected server, Docker daemon, DNS records, firewall, application data, and external services remain part of your infrastructure. Before deploying [#before-deploying] Make sure: * Coolify has a validated deployment server * the Coolify proxy is running when the application needs a domain * the source or image can be accessed by Coolify * you know which port the application listens on * persistent data has an explicit storage and backup plan Follow [Deploy your first app](/deploy-your-first-app) if you want to verify deployments before connecting your own source. Continue learning [#continue-learning] # Choose your path (/docs/choose-your-path) Choose your path [#choose-your-path] Coolify can be used in two ways: self-hosted, where you run and maintain the Coolify instance yourself, or Coolify Cloud, where the Coolify team runs and maintains the Coolify instance for you. Self-hosted and Cloud use the same Coolify features. The choice is only who operates the Coolify instance: you manage it yourself, or Coolify manages it for you. | Area | Self-hosted | Coolify Cloud | | :--------------- | :------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------ | | Coolify instance | You install, update, backup, monitor, and restore the Coolify instance. | The Coolify team runs, updates, backs up, monitors, and restores the Coolify instance. | | Your servers | You provide the servers and secure the operating system, SSH access, firewall, and network. | You still provide the servers and secure the operating system, SSH access, firewall, and network. | | Your workloads | Your apps, databases, volumes, secrets, and runtime security remain your responsibility. | Your apps, databases, volumes, secrets, and runtime security remain your responsibility. | | Coolify updates | You decide when to update Coolify and how to handle maintenance windows. | Coolify team applies control-plane updates for you. | | Cost model | No Coolify license fee. You pay for your own infrastructure and operations time. | Paid managed service for the Coolify instance. You still pay for your own servers. | | Feature set | All Coolify features. | Same as self-hosted. No Cloud-only feature paywall. | Both paths give you the same core product experience, but they differ in who is responsible for operating and maintaining the Coolify instance. Coolify Cloud includes a monthly subscription for the managed instance, while self-hosted lets you run it yourself without recurring platform fees. **Start with Self-hosted if you are comfortable operating the control plane.** Self-hosted gives you the clearest ownership model from day one. Choose Cloud when you want the Coolify team to handle the instance maintenance for you. # Authentication (/docs/cli/authentication) Authenticate the Coolify CLI [#authenticate-the-coolify-cli] The Coolify CLI authenticates through the Coolify REST API. Each request uses an API token associated with a saved [context](/cli/contexts) or supplied for one command with `--token`. Use a separate, least-privilege token for each team and automation workflow. Do not commit tokens to a repository, paste them into shared logs, or store them in unprotected scripts. Create an API token [#create-an-api-token] Follow [API Tokens](/core/security/credentials/api-tokens) to create a token for the active team. Select only the permissions required by the CLI commands you plan to run. On self-hosted Coolify, an administrator must also enable **API Access** and allow the caller's source IP when an allowlist is configured. Read [IP Allowlist](/api/ip-allowlist) for these instance settings. Choose your Coolify deployment [#choose-your-coolify-deployment] Authenticate with Coolify Cloud [#authenticate-with-coolify-cloud] The CLI creates a `cloud` context for `https://app.coolify.io` when it creates the configuration file for the first time. Save your Cloud token, select the context, and verify it: ```sh coolify context set-token cloud coolify context use cloud coolify context verify ``` A successful verification reports that the connection and authentication are valid, followed by the Coolify version. Authenticate with self-hosted Coolify [#authenticate-with-self-hosted-coolify] Create a context with the full instance URL without `/api/v1`: ```sh coolify context add --default production https://coolify.example.com coolify context verify ``` The URL must start with `http://` or `https://`. Use HTTPS for any instance accessed over a network. Override a saved token [#override-a-saved-token] The global `--token ` flag overrides the token saved in the selected context for one command: ```sh coolify --context production --token resource list ``` Prefer a saved context for interactive work. In automation, inject the override from the CI or orchestration platform's secret store rather than writing it directly in the command or configuration file. Troubleshoot authentication [#troubleshoot-authentication] * Run `coolify context verify` to test the selected URL and token together. * A `401` response usually means the token is missing, expired, revoked, or invalid. * A `403` response can mean the token lacks permission, self-hosted API access is disabled, or the caller does not match the IP allowlist. * If expected resources are missing, confirm that the token belongs to the team that owns them. Read [API authorization](/api/authorization) for the complete access checks. Follow [Contexts](/cli/contexts) to add, switch, update, or remove saved connections. # Automate with the CLI (/docs/cli/automate-with-cli) Automate with the Coolify CLI [#automate-with-the-coolify-cli] The CLI supports multiple Coolify instances, structured output, and nonzero exit statuses for failed commands. These features let scripts and CI jobs inspect resources and start deployments without parsing human-readable tables. Configure separate contexts [#configure-separate-contexts] Save a context for each Coolify instance: ```sh coolify context add production https://coolify.example.com coolify context add staging https://staging-coolify.example.com coolify context use production ``` Use another context for one command without changing the default: ```sh coolify --context staging resource list ``` Verify every context before using it in automation: ```sh coolify --context production context verify coolify --context staging context verify ``` Request structured output [#request-structured-output] Use compact JSON for scripts: ```sh coolify --format json resource list ``` Use formatted JSON while developing or debugging a script: ```sh coolify --format pretty deploy list ``` `table` is the default for interactive terminal use. Do not parse table columns in automation because their display can change. Deploy several resources [#deploy-several-resources] Start a batch deployment with comma-separated resource names: ```sh coolify --context production deploy batch api,worker,frontend ``` Add `--force` only when every named resource must deploy without detected changes: ```sh coolify --context production deploy batch api,worker,frontend --force ``` Verify the resulting deployments: ```sh coolify --context production --format json deploy list ``` Handle failures safely [#handle-failures-safely] A failed CLI command returns a nonzero exit status, so shell scripts and CI jobs can stop immediately: ```sh set -e coolify --context production context verify coolify --context production deploy name api ``` Keep these restrictions in automated environments: * Store API tokens in the CI secret manager, not in repository files or command arguments. * Do not use `--show-sensitive` in shared logs. * Use `--debug` only during diagnosis because it adds operational details to output. * Give the context token only the permissions required by the job. # Clone (/docs/cli/command-reference/commands/app/clone) Clone [#clone] Clone an application to a destination Usage [#usage] ```sh coolify app clone ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :---------------- | | `--clone-volumes` | `boolean` | No | `false` | Clone volume data | | `--destination` | `string` | No | — | Destination UUID | | `--name` | `string` | No | — | Optional new name | Get current help [#get-current-help] ```sh coolify app clone --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create deploy key (/docs/cli/command-reference/commands/app/create-deploy-key) Create deploy key [#create-deploy-key] Create an application from a private repository using SSH deploy key Usage [#usage] ```sh coolify app create deploy-key ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------------------------- | :------------ | :------: | :------ | :------------------------------------------------------------------------------------------------ | | `--base-directory` | `string` | No | — | Base directory for the application | | `--build-command` | `string` | No | — | Custom build command | | `--build-pack` | `string` | Yes | — | Build pack: nixpacks, static, dockerfile, dockercompose (required) | | `--compose-domain` | `stringArray` | No | — | Docker Compose service domain in \=\\[,\] format (repeatable) | | `--custom-internal-name` | `string` | No | — | Custom internal hostname | | `--description` | `string` | No | — | Application description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--disable-build-cache` | `boolean` | No | `false` | Disable the build cache | | `--docker-images-to-keep` | `integer` | No | `0` | Number of Docker images to retain | | `--dockerfile-target-build` | `string` | No | — | Dockerfile target build stage | | `--domains` | `string` | No | — | Domain(s) for the application | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--git-branch` | `string` | Yes | — | Git branch (required) | | `--git-commit-sha` | `string` | No | — | Specific commit SHA to deploy | | `--git-repository` | `string` | Yes | — | Git repository SSH URL, e.g., '[git@github.com](mailto:git@github.com):owner/repo.git' (required) | | `--gpu-count` | `string` | No | — | GPU count | | `--gpu-device-ids` | `string` | No | — | GPU device IDs | | `--gpu-driver` | `string` | No | — | GPU driver | | `--gpu-options` | `string` | No | — | GPU options | | `--health-check-enabled` | `boolean` | No | `false` | Enable health checks | | `--health-check-path` | `string` | No | — | Health check path | | `--include-source-commit-in-build` | `boolean` | No | `false` | Include the source commit in the build | | `--inject-build-args-to-dockerfile` | `boolean` | No | `false` | Inject build arguments into the Dockerfile | | `--install-command` | `string` | No | — | Custom install command | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--is-consistent-container-name-enabled` | `boolean` | No | `false` | Use consistent container names | | `--is-env-sorting-enabled` | `boolean` | No | `false` | Sort environment variables | | `--is-git-lfs-enabled` | `boolean` | No | `false` | Enable Git LFS | | `--is-git-shallow-clone-enabled` | `boolean` | No | `false` | Use a shallow Git clone | | `--is-git-submodules-enabled` | `boolean` | No | `false` | Clone Git submodules | | `--is-gpu-enabled` | `boolean` | No | `false` | Enable GPU | | `--is-gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--is-log-drain-enabled` | `boolean` | No | `false` | Enable application log drain | | `--is-pr-deployments-public-enabled` | `boolean` | No | `false` | Make pull request deployments public | | `--is-preview-deployments-enabled` | `boolean` | No | `false` | Enable preview deployments | | `--is-raw-compose-deployment-enabled` | `boolean` | No | `false` | Deploy the raw Docker Compose definition | | `--is-stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--limits-cpus` | `string` | No | — | CPU limit | | `--limits-memory` | `string` | No | — | Memory limit | | `--max-restart-count` | `integer` | No | `0` | Maximum container restart count | | `--name` | `string` | No | — | Application name | | `--ports-exposes` | `string` | Yes | — | Exposed ports, e.g., '3000' or '3000,8080' (required) | | `--ports-mappings` | `string` | No | — | Port mappings (host:container) | | `--preview-url-template` | `string` | No | — | Preview URL template | | `--private-key-uuid` | `string` | Yes | — | Private key UUID (required) | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--publish-directory` | `string` | No | — | Publish directory for static builds | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--start-command` | `string` | No | — | Custom start command | | `--stop-grace-period` | `integer` | No | `0` | Container stop grace period in seconds | | `--tag` | `stringArray` | No | — | Tag to assign to the application (repeatable) | | `--tags` | `stringSlice` | No | — | Tags to assign to the application | | `--use-build-secrets` | `boolean` | No | `false` | Use Docker Build Secrets for build-time variables | Get current help [#get-current-help] ```sh coolify app create deploy-key --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create dockerfile (/docs/cli/command-reference/commands/app/create-dockerfile) Create dockerfile [#create-dockerfile] Create an application from a custom Dockerfile Usage [#usage] ```sh coolify app create dockerfile ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------------------------- | :------------ | :------: | :------ | :--------------------------------------------------- | | `--custom-internal-name` | `string` | No | — | Custom internal hostname | | `--description` | `string` | No | — | Application description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--disable-build-cache` | `boolean` | No | `false` | Disable the build cache | | `--docker-images-to-keep` | `integer` | No | `0` | Number of Docker images to retain | | `--dockerfile` | `string` | Yes | — | Dockerfile content (required) | | `--dockerfile-target-build` | `string` | No | — | Dockerfile target build stage | | `--domains` | `string` | No | — | Domain(s) for the application | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--gpu-count` | `string` | No | — | GPU count | | `--gpu-device-ids` | `string` | No | — | GPU device IDs | | `--gpu-driver` | `string` | No | — | GPU driver | | `--gpu-options` | `string` | No | — | GPU options | | `--health-check-enabled` | `boolean` | No | `false` | Enable health checks | | `--health-check-path` | `string` | No | — | Health check path | | `--include-source-commit-in-build` | `boolean` | No | `false` | Include the source commit in the build | | `--inject-build-args-to-dockerfile` | `boolean` | No | `false` | Inject build arguments into the Dockerfile | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--is-consistent-container-name-enabled` | `boolean` | No | `false` | Use consistent container names | | `--is-env-sorting-enabled` | `boolean` | No | `false` | Sort environment variables | | `--is-git-lfs-enabled` | `boolean` | No | `false` | Enable Git LFS | | `--is-git-shallow-clone-enabled` | `boolean` | No | `false` | Use a shallow Git clone | | `--is-git-submodules-enabled` | `boolean` | No | `false` | Clone Git submodules | | `--is-gpu-enabled` | `boolean` | No | `false` | Enable GPU | | `--is-gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--is-log-drain-enabled` | `boolean` | No | `false` | Enable application log drain | | `--is-pr-deployments-public-enabled` | `boolean` | No | `false` | Make pull request deployments public | | `--is-preview-deployments-enabled` | `boolean` | No | `false` | Enable preview deployments | | `--is-raw-compose-deployment-enabled` | `boolean` | No | `false` | Deploy the raw Docker Compose definition | | `--is-stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--limits-cpus` | `string` | No | — | CPU limit | | `--limits-memory` | `string` | No | — | Memory limit | | `--max-restart-count` | `integer` | No | `0` | Maximum container restart count | | `--name` | `string` | No | — | Application name | | `--ports-exposes` | `string` | No | — | Exposed ports, e.g., '3000' or '3000,8080' | | `--ports-mappings` | `string` | No | — | Port mappings (host:container) | | `--preview-url-template` | `string` | No | — | Preview URL template | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--stop-grace-period` | `integer` | No | `0` | Container stop grace period in seconds | | `--tag` | `stringArray` | No | — | Tag to assign to the application (repeatable) | | `--tags` | `stringSlice` | No | — | Tags to assign to the application | | `--use-build-secrets` | `boolean` | No | `false` | Use Docker Build Secrets for build-time variables | Get current help [#get-current-help] ```sh coolify app create dockerfile --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create dockerimage (/docs/cli/command-reference/commands/app/create-dockerimage) Create dockerimage [#create-dockerimage] Create an application from a pre-built Docker image Usage [#usage] ```sh coolify app create dockerimage ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------------------------- | :------------ | :------: | :------ | :--------------------------------------------------- | | `--custom-internal-name` | `string` | No | — | Custom internal hostname | | `--description` | `string` | No | — | Application description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--disable-build-cache` | `boolean` | No | `false` | Disable the build cache | | `--docker-images-to-keep` | `integer` | No | `0` | Number of Docker images to retain | | `--docker-registry-image-name` | `string` | Yes | — | Docker image name from registry (required) | | `--docker-registry-image-tag` | `string` | No | — | Docker image tag (defaults to 'latest') | | `--dockerfile-target-build` | `string` | No | — | Dockerfile target build stage | | `--domains` | `string` | No | — | Domain(s) for the application | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--gpu-count` | `string` | No | — | GPU count | | `--gpu-device-ids` | `string` | No | — | GPU device IDs | | `--gpu-driver` | `string` | No | — | GPU driver | | `--gpu-options` | `string` | No | — | GPU options | | `--health-check-enabled` | `boolean` | No | `false` | Enable health checks | | `--health-check-path` | `string` | No | — | Health check path | | `--include-source-commit-in-build` | `boolean` | No | `false` | Include the source commit in the build | | `--inject-build-args-to-dockerfile` | `boolean` | No | `false` | Inject build arguments into the Dockerfile | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--is-consistent-container-name-enabled` | `boolean` | No | `false` | Use consistent container names | | `--is-env-sorting-enabled` | `boolean` | No | `false` | Sort environment variables | | `--is-git-lfs-enabled` | `boolean` | No | `false` | Enable Git LFS | | `--is-git-shallow-clone-enabled` | `boolean` | No | `false` | Use a shallow Git clone | | `--is-git-submodules-enabled` | `boolean` | No | `false` | Clone Git submodules | | `--is-gpu-enabled` | `boolean` | No | `false` | Enable GPU | | `--is-gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--is-log-drain-enabled` | `boolean` | No | `false` | Enable application log drain | | `--is-pr-deployments-public-enabled` | `boolean` | No | `false` | Make pull request deployments public | | `--is-preview-deployments-enabled` | `boolean` | No | `false` | Enable preview deployments | | `--is-raw-compose-deployment-enabled` | `boolean` | No | `false` | Deploy the raw Docker Compose definition | | `--is-stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--limits-cpus` | `string` | No | — | CPU limit | | `--limits-memory` | `string` | No | — | Memory limit | | `--max-restart-count` | `integer` | No | `0` | Maximum container restart count | | `--name` | `string` | No | — | Application name | | `--ports-exposes` | `string` | Yes | — | Exposed ports, e.g., '80' or '80,443' (required) | | `--ports-mappings` | `string` | No | — | Port mappings (host:container) | | `--preview-url-template` | `string` | No | — | Preview URL template | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--stop-grace-period` | `integer` | No | `0` | Container stop grace period in seconds | | `--tag` | `stringArray` | No | — | Tag to assign to the application (repeatable) | | `--tags` | `stringSlice` | No | — | Tags to assign to the application | | `--use-build-secrets` | `boolean` | No | `false` | Use Docker Build Secrets for build-time variables | Get current help [#get-current-help] ```sh coolify app create dockerimage --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create github (/docs/cli/command-reference/commands/app/create-github) Create github [#create-github] Create an application from a private repository using GitHub App Usage [#usage] ```sh coolify app create github ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------------------------- | :------------ | :------: | :------ | :------------------------------------------------------------------------------- | | `--base-directory` | `string` | No | — | Base directory for the application | | `--build-command` | `string` | No | — | Custom build command | | `--build-pack` | `string` | Yes | — | Build pack: nixpacks, static, dockerfile, dockercompose (required) | | `--compose-domain` | `stringArray` | No | — | Docker Compose service domain in \=\\[,\] format (repeatable) | | `--custom-internal-name` | `string` | No | — | Custom internal hostname | | `--description` | `string` | No | — | Application description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--disable-build-cache` | `boolean` | No | `false` | Disable the build cache | | `--docker-images-to-keep` | `integer` | No | `0` | Number of Docker images to retain | | `--dockerfile-target-build` | `string` | No | — | Dockerfile target build stage | | `--domains` | `string` | No | — | Domain(s) for the application | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--git-branch` | `string` | Yes | — | Git branch (required) | | `--git-commit-sha` | `string` | No | — | Specific commit SHA to deploy | | `--git-repository` | `string` | Yes | — | Git repository in format 'owner/repo' (required) | | `--github-app-uuid` | `string` | Yes | — | GitHub App UUID (required) | | `--gpu-count` | `string` | No | — | GPU count | | `--gpu-device-ids` | `string` | No | — | GPU device IDs | | `--gpu-driver` | `string` | No | — | GPU driver | | `--gpu-options` | `string` | No | — | GPU options | | `--health-check-enabled` | `boolean` | No | `false` | Enable health checks | | `--health-check-path` | `string` | No | — | Health check path | | `--include-source-commit-in-build` | `boolean` | No | `false` | Include the source commit in the build | | `--inject-build-args-to-dockerfile` | `boolean` | No | `false` | Inject build arguments into the Dockerfile | | `--install-command` | `string` | No | — | Custom install command | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--is-consistent-container-name-enabled` | `boolean` | No | `false` | Use consistent container names | | `--is-env-sorting-enabled` | `boolean` | No | `false` | Sort environment variables | | `--is-git-lfs-enabled` | `boolean` | No | `false` | Enable Git LFS | | `--is-git-shallow-clone-enabled` | `boolean` | No | `false` | Use a shallow Git clone | | `--is-git-submodules-enabled` | `boolean` | No | `false` | Clone Git submodules | | `--is-gpu-enabled` | `boolean` | No | `false` | Enable GPU | | `--is-gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--is-log-drain-enabled` | `boolean` | No | `false` | Enable application log drain | | `--is-pr-deployments-public-enabled` | `boolean` | No | `false` | Make pull request deployments public | | `--is-preview-deployments-enabled` | `boolean` | No | `false` | Enable preview deployments | | `--is-raw-compose-deployment-enabled` | `boolean` | No | `false` | Deploy the raw Docker Compose definition | | `--is-stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--limits-cpus` | `string` | No | — | CPU limit | | `--limits-memory` | `string` | No | — | Memory limit | | `--max-restart-count` | `integer` | No | `0` | Maximum container restart count | | `--name` | `string` | No | — | Application name | | `--ports-exposes` | `string` | Yes | — | Exposed ports, e.g., '3000' or '3000,8080' (required) | | `--ports-mappings` | `string` | No | — | Port mappings (host:container) | | `--preview-url-template` | `string` | No | — | Preview URL template | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--publish-directory` | `string` | No | — | Publish directory for static builds | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--start-command` | `string` | No | — | Custom start command | | `--stop-grace-period` | `integer` | No | `0` | Container stop grace period in seconds | | `--tag` | `stringArray` | No | — | Tag to assign to the application (repeatable) | | `--tags` | `stringSlice` | No | — | Tags to assign to the application | | `--use-build-secrets` | `boolean` | No | `false` | Use Docker Build Secrets for build-time variables | Get current help [#get-current-help] ```sh coolify app create github --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create public (/docs/cli/command-reference/commands/app/create-public) Create public [#create-public] Create an application from a public git repository Usage [#usage] ```sh coolify app create public ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------------------------- | :------------ | :------: | :------ | :------------------------------------------------------------------------------- | | `--base-directory` | `string` | No | — | Base directory for the application | | `--build-command` | `string` | No | — | Custom build command | | `--build-pack` | `string` | Yes | — | Build pack: nixpacks, static, dockerfile, dockercompose (required) | | `--compose-domain` | `stringArray` | No | — | Docker Compose service domain in \=\\[,\] format (repeatable) | | `--custom-internal-name` | `string` | No | — | Custom internal hostname | | `--description` | `string` | No | — | Application description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--disable-build-cache` | `boolean` | No | `false` | Disable the build cache | | `--docker-images-to-keep` | `integer` | No | `0` | Number of Docker images to retain | | `--dockerfile-target-build` | `string` | No | — | Dockerfile target build stage | | `--domains` | `string` | No | — | Domain(s) for the application | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--git-branch` | `string` | Yes | — | Git branch (required) | | `--git-commit-sha` | `string` | No | — | Specific commit SHA to deploy | | `--git-repository` | `string` | Yes | — | Git repository URL (required) | | `--gpu-count` | `string` | No | — | GPU count | | `--gpu-device-ids` | `string` | No | — | GPU device IDs | | `--gpu-driver` | `string` | No | — | GPU driver | | `--gpu-options` | `string` | No | — | GPU options | | `--health-check-enabled` | `boolean` | No | `false` | Enable health checks | | `--health-check-path` | `string` | No | — | Health check path | | `--include-source-commit-in-build` | `boolean` | No | `false` | Include the source commit in the build | | `--inject-build-args-to-dockerfile` | `boolean` | No | `false` | Inject build arguments into the Dockerfile | | `--install-command` | `string` | No | — | Custom install command | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--is-consistent-container-name-enabled` | `boolean` | No | `false` | Use consistent container names | | `--is-env-sorting-enabled` | `boolean` | No | `false` | Sort environment variables | | `--is-git-lfs-enabled` | `boolean` | No | `false` | Enable Git LFS | | `--is-git-shallow-clone-enabled` | `boolean` | No | `false` | Use a shallow Git clone | | `--is-git-submodules-enabled` | `boolean` | No | `false` | Clone Git submodules | | `--is-gpu-enabled` | `boolean` | No | `false` | Enable GPU | | `--is-gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--is-log-drain-enabled` | `boolean` | No | `false` | Enable application log drain | | `--is-pr-deployments-public-enabled` | `boolean` | No | `false` | Make pull request deployments public | | `--is-preview-deployments-enabled` | `boolean` | No | `false` | Enable preview deployments | | `--is-raw-compose-deployment-enabled` | `boolean` | No | `false` | Deploy the raw Docker Compose definition | | `--is-stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--limits-cpus` | `string` | No | — | CPU limit | | `--limits-memory` | `string` | No | — | Memory limit | | `--max-restart-count` | `integer` | No | `0` | Maximum container restart count | | `--name` | `string` | No | — | Application name | | `--ports-exposes` | `string` | Yes | — | Exposed ports, e.g., '3000' or '3000,8080' (required) | | `--ports-mappings` | `string` | No | — | Port mappings (host:container) | | `--preview-url-template` | `string` | No | — | Preview URL template | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--publish-directory` | `string` | No | — | Publish directory for static builds | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--start-command` | `string` | No | — | Custom start command | | `--stop-grace-period` | `integer` | No | `0` | Container stop grace period in seconds | | `--tag` | `stringArray` | No | — | Tag to assign to the application (repeatable) | | `--tags` | `stringSlice` | No | — | Tags to assign to the application | | `--use-build-secrets` | `boolean` | No | `false` | Use Docker Build Secrets for build-time variables | Get current help [#get-current-help] ```sh coolify app create public --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/app/delete) Delete [#delete] Delete an application. This action cannot be undone. Usage [#usage] ```sh coolify app delete ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify app delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Deployments list (/docs/cli/command-reference/commands/app/deployments-list) Deployments list [#deployments-list] Retrieve a list of all deployments for a specific application. Usage [#usage] ```sh coolify app deployments list ``` Get current help [#get-current-help] ```sh coolify app deployments list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Deployments logs (/docs/cli/command-reference/commands/app/deployments-logs) Deployments logs [#deployments-logs] Get deployment logs for an application Usage [#usage] ```sh coolify app deployments logs [deployment-uuid] ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :-------- | :------: | :------ | :----------------------------------------------------------------- | | `--debuglogs` | `boolean` | No | `false` | Show debug logs (includes hidden commands and internal operations) | | `--follow (-f)` | `boolean` | No | `false` | Follow log output (like tail -f) | | `--lines (-n)` | `integer` | No | `0` | Number of log lines to display (0 = all) | Get current help [#get-current-help] ```sh coolify app deployments logs --help ``` The installed CLI help reflects the exact options available in your CLI version. # Destinations add (/docs/cli/command-reference/commands/app/destinations-add) Destinations add [#destinations-add] Attach a destination Usage [#usage] ```sh coolify app destinations add ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :--------------- | | `--destination` | `string` | No | — | Destination UUID | Get current help [#get-current-help] ```sh coolify app destinations add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Destinations list (/docs/cli/command-reference/commands/app/destinations-list) Destinations list [#destinations-list] List application destinations Usage [#usage] ```sh coolify app destinations list ``` Get current help [#get-current-help] ```sh coolify app destinations list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Destinations remove (/docs/cli/command-reference/commands/app/destinations-remove) Destinations remove [#destinations-remove] Detach a destination Usage [#usage] ```sh coolify app destinations remove ``` Get current help [#get-current-help] ```sh coolify app destinations remove --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env create (/docs/cli/command-reference/commands/app/env-create) Env create [#env-create] Create a new environment variable for a specific application. Use --key and --value flags to specify the variable. Usage [#usage] ```sh coolify app env create ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :--------------------------------------------------- | | `--build-time` | `boolean` | No | `true` | Available at build time (default: true) | | `--comment` | `string` | No | — | Comment for the environment variable | | `--is-literal` | `boolean` | No | `false` | Treat value as literal (don't interpolate variables) | | `--is-multiline` | `boolean` | No | `false` | Value is multiline | | `--key` | `string` | Yes | — | Environment variable key (required) | | `--preview` | `boolean` | No | `false` | Available in preview deployments | | `--runtime` | `boolean` | No | `true` | Available at runtime (default: true) | | `--value` | `string` | Yes | — | Environment variable value (required) | Get current help [#get-current-help] ```sh coolify app env create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env delete (/docs/cli/command-reference/commands/app/env-delete) Env delete [#env-delete] Delete an environment variable from an application. First UUID is the application, second is the specific environment variable to delete. Usage [#usage] ```sh coolify app env delete ``` Options [#options] | Option | Type | Required | Default | Description | | :-------- | :-------- | :------: | :------ | :----------------------- | | `--force` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify app env delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env get (/docs/cli/command-reference/commands/app/env-get) Env get [#env-get] Get detailed information about a specific environment variable by UUID or key name. Usage [#usage] ```sh coolify app env get ``` Get current help [#get-current-help] ```sh coolify app env get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env list (/docs/cli/command-reference/commands/app/env-list) Env list [#env-list] List all environment variables for an application Usage [#usage] ```sh coolify app env list ``` Options [#options] | Option | Type | Required | Default | Description | | :---------- | :-------- | :------: | :------ | :--------------------------------------------------------------- | | `--all` | `boolean` | No | `false` | Show all environment variables (non-preview first, then preview) | | `--preview` | `boolean` | No | `false` | Show preview environment variables instead of regular ones | Get current help [#get-current-help] ```sh coolify app env list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env sync (/docs/cli/command-reference/commands/app/env-sync) Env sync [#env-sync] Sync environment variables from a .env file Usage [#usage] ```sh coolify app env sync ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------------------------------------------- | | `--build-time` | `boolean` | No | `true` | Make all variables available at build time (default: true) | | `--file (-f)` | `string` | Yes | — | Path to .env file (required) | | `--is-literal` | `boolean` | No | `false` | Treat all values as literal (don't interpolate variables) | | `--preview` | `boolean` | No | `false` | Make all variables available in preview deployments | | `--runtime` | `boolean` | No | `true` | Make all variables available at runtime (default: true) | Get current help [#get-current-help] ```sh coolify app env sync --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env update (/docs/cli/command-reference/commands/app/env-update) Env update [#env-update] Update an existing environment variable. Identify it by UUID or key name. Usage [#usage] ```sh coolify app env update ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :---------------------------------------- | | `--build-time` | `boolean` | No | `true` | Available at build time (default: true) | | `--comment` | `string` | No | — | Comment for the environment variable | | `--is-literal` | `boolean` | No | `false` | Treat value as literal | | `--is-multiline` | `boolean` | No | `false` | Value is multiline | | `--key` | `string` | No | — | New environment variable key (rename) | | `--preview` | `boolean` | No | `false` | Available in preview deployments | | `--runtime` | `boolean` | No | `true` | Available at runtime (default: true) | | `--value` | `string` | Yes | — | New environment variable value (required) | Get current help [#get-current-help] ```sh coolify app env update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Execute task (/docs/cli/command-reference/commands/app/execute-task) Execute task [#execute-task] Execute a scheduled task now Usage [#usage] ```sh coolify app execute-task ``` Get current help [#get-current-help] ```sh coolify app execute-task --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/app/get) Get [#get] Retrieve detailed information about a specific application. Usage [#usage] ```sh coolify app get ``` Get current help [#get-current-help] ```sh coolify app get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/app/list) List [#list] List all applications in Coolify. Usage [#usage] ```sh coolify app list ``` Get current help [#get-current-help] ```sh coolify app list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Logs (/docs/cli/command-reference/commands/app/logs) Logs [#logs] Get application logs Usage [#usage] ```sh coolify app logs ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------ | :-------- | :------: | :------ | :------------------------------------------------------------------------ | | `--follow (-f)` | `boolean` | No | `false` | Follow log output (like tail -f) | | `--lines (-n)` | `integer` | No | `100` | Number of log lines to retrieve | | `--service` | `string` | No | — | Docker Compose service name (selects one container in multi-service apps) | | `--show-timestamps` | `boolean` | No | `false` | Show timestamps in log output | Get current help [#get-current-help] ```sh coolify app logs --help ``` The installed CLI help reflects the exact options available in your CLI version. # Move (/docs/cli/command-reference/commands/app/move) Move [#move] Move an application to another environment Usage [#usage] ```sh coolify app move ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :------- | :------: | :------ | :--------------------------------- | | `--environment-uuid` | `string` | Yes | — | Target environment UUID (required) | Get current help [#get-current-help] ```sh coolify app move --help ``` The installed CLI help reflects the exact options available in your CLI version. # Previews create (/docs/cli/command-reference/commands/app/previews-create) Previews create [#previews-create] Open or redeploy a preview deployment Usage [#usage] ```sh coolify app previews create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :-------------------------------------------------------------------- | | `--commit` | `string` | No | — | Commit SHA to deploy (required for Bitbucket) | | `--docker-tag` | `string` | No | — | Docker image tag (Docker Image applications only) | | `--force` | `boolean` | No | `false` | Rebuild without cache | | `--git-type` | `string` | No | — | Git provider of the pull request: github, gitlab, gitea, or bitbucket | | `--no-deploy` | `boolean` | No | `false` | Only create the preview, do not queue a deployment | | `--url` | `string` | No | — | Pull request URL | Get current help [#get-current-help] ```sh coolify app previews create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Previews delete (/docs/cli/command-reference/commands/app/previews-delete) Previews delete [#previews-delete] Delete a preview deployment for an application. First argument is the application UUID, second is the pull request ID. Usage [#usage] ```sh coolify app previews delete ``` Options [#options] | Option | Type | Required | Default | Description | | :-------- | :-------- | :------: | :------ | :----------------------- | | `--force` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify app previews delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Previews get (/docs/cli/command-reference/commands/app/previews-get) Previews get [#previews-get] Get a preview deployment of an application by pull request ID. Usage [#usage] ```sh coolify app previews get ``` Get current help [#get-current-help] ```sh coolify app previews get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Previews list (/docs/cli/command-reference/commands/app/previews-list) Previews list [#previews-list] List the preview deployments of an application, newest pull request first. Usage [#usage] ```sh coolify app previews list ``` Get current help [#get-current-help] ```sh coolify app previews list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Previews update (/docs/cli/command-reference/commands/app/previews-update) Previews update [#previews-update] Update the domains of a preview deployment Usage [#usage] ```sh coolify app previews update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------------ | :------------ | :------: | :------ | :------------------------------------------------------------------------------- | | `--compose-domain` | `stringArray` | No | — | Docker Compose service domain in \=\\[,\] format (repeatable) | | `--domains` | `string` | No | — | Domains (comma-separated) | | `--force-domain-override` | `boolean` | No | `false` | Save the domains even when another resource uses them | Get current help [#get-current-help] ```sh coolify app previews update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Restart (/docs/cli/command-reference/commands/app/restart) Restart [#restart] Restart a running application. Usage [#usage] ```sh coolify app restart ``` Get current help [#get-current-help] ```sh coolify app restart --help ``` The installed CLI help reflects the exact options available in your CLI version. # Rollback images (/docs/cli/command-reference/commands/app/rollback-images) Rollback images [#rollback-images] List rollback images Usage [#usage] ```sh coolify app rollback images ``` Get current help [#get-current-help] ```sh coolify app rollback images --help ``` The installed CLI help reflects the exact options available in your CLI version. # Rollback run (/docs/cli/command-reference/commands/app/rollback-run) Rollback run [#rollback-run] Rollback application to a commit Usage [#usage] ```sh coolify app rollback run ``` Options [#options] | Option | Type | Required | Default | Description | | :--------- | :------- | :------: | :------ | :------------- | | `--commit` | `string` | No | — | Git commit SHA | Get current help [#get-current-help] ```sh coolify app rollback run --help ``` The installed CLI help reflects the exact options available in your CLI version. # Run storage backup (/docs/cli/command-reference/commands/app/run-storage-backup) Run storage backup [#run-storage-backup] Run volume backup schedule now Usage [#usage] ```sh coolify app run-storage-backup ``` Get current help [#get-current-help] ```sh coolify app run-storage-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Start (/docs/cli/command-reference/commands/app/start) Start [#start] Start an application (initiates a deployment). Usage [#usage] ```sh coolify app start ``` Options [#options] | Option | Type | Required | Default | Description | | :----------------- | :-------- | :------: | :------ | :---------------------------- | | `--force` | `boolean` | No | `false` | Force rebuild | | `--instant-deploy` | `boolean` | No | `false` | Instant deploy (skip queuing) | Get current help [#get-current-help] ```sh coolify app start --help ``` The installed CLI help reflects the exact options available in your CLI version. # Stop (/docs/cli/command-reference/commands/app/stop) Stop [#stop] Stop a running application. Usage [#usage] ```sh coolify app stop ``` Get current help [#get-current-help] ```sh coolify app stop --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage create (/docs/cli/command-reference/commands/app/storage-create) Storage create [#storage-create] Create a storage for an application Usage [#usage] ```sh coolify app storage create ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :------------------------------------------------------------------- | | `--content` | `string` | No | — | File content (file only) | | `--fs-path` | `string` | No | — | Host directory path (file only, required when --is-directory is set) | | `--host-path` | `string` | No | — | Host path (persistent only) | | `--is-directory` | `boolean` | No | `false` | Whether this is a directory mount (file only) | | `--mount-path` | `string` | Yes | — | Mount path inside the container (required) | | `--name` | `string` | No | — | Volume name (persistent only) | | `--type` | `string` | Yes | — | Storage type: 'persistent' or 'file' (required) | Get current help [#get-current-help] ```sh coolify app storage create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage delete backup (/docs/cli/command-reference/commands/app/storage-delete-backup) Storage delete backup [#storage-delete-backup] Delete storage volume backup schedule Usage [#usage] ```sh coolify app storage delete-backup ``` Get current help [#get-current-help] ```sh coolify app storage delete-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage delete (/docs/cli/command-reference/commands/app/storage-delete) Storage delete [#storage-delete] Delete a storage from an application Usage [#usage] ```sh coolify app storage delete ``` Get current help [#get-current-help] ```sh coolify app storage delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage list (/docs/cli/command-reference/commands/app/storage-list) Storage list [#storage-list] List all persistent volumes and file storages for a specific application. Usage [#usage] ```sh coolify app storage list ``` Get current help [#get-current-help] ```sh coolify app storage list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage run backup (/docs/cli/command-reference/commands/app/storage-run-backup) Storage run backup [#storage-run-backup] Run storage volume backup now Usage [#usage] ```sh coolify app storage run-backup ``` Get current help [#get-current-help] ```sh coolify app storage run-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage set backup (/docs/cli/command-reference/commands/app/storage-set-backup) Storage set backup [#storage-set-backup] Create or replace storage volume backup schedule Usage [#usage] ```sh coolify app storage set-backup ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------------------------- | :-------- | :------: | :------ | :------------------------------------ | | `--disable-local-backup` | `boolean` | No | `false` | Disable local backup retention | | `--enabled` | `boolean` | No | `true` | Enable the schedule | | `--frequency` | `string` | Yes | — | Cron frequency (required) | | `--retention-amount-locally` | `integer` | No | `7` | Local retention count | | `--retention-amount-s3` | `integer` | No | `7` | S3 retention count | | `--retention-days-locally` | `integer` | No | `0` | Local retention days | | `--retention-days-s3` | `integer` | No | `0` | S3 retention days | | `--retention-max-storage-locally` | `float64` | No | `0` | Local max storage | | `--retention-max-storage-s3` | `float64` | No | `0` | S3 max storage | | `--s3-storage-uuid` | `string` | No | — | S3 storage UUID when --save-s3 is set | | `--save-s3` | `boolean` | No | `false` | Also save backups to S3 | | `--stop-during-backup` | `boolean` | No | `false` | Stop resource during backup | | `--timeout` | `integer` | No | `3600` | Backup timeout seconds | Get current help [#get-current-help] ```sh coolify app storage set-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage update (/docs/cli/command-reference/commands/app/storage-update) Storage update [#storage-update] Update a storage for an application Usage [#usage] ```sh coolify app storage update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------------- | :-------- | :------: | :------ | :-------------------------------------------------- | | `--content` | `string` | No | — | File content (file only) | | `--host-path` | `string` | No | — | Host path (persistent only) | | `--id` | `integer` | No | `0` | Storage ID (deprecated, use --uuid instead) | | `--is-preview-suffix-enabled` | `boolean` | No | `false` | Enable preview suffix for this storage | | `--mount-path` | `string` | No | — | Mount path inside the container | | `--name` | `string` | No | — | Storage name (persistent only) | | `--type` | `string` | Yes | — | Storage type: 'persistent' or 'file' (required) | | `--uuid` | `string` | No | — | Storage UUID (required, use 'storage list' to find) | Get current help [#get-current-help] ```sh coolify app storage update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag add (/docs/cli/command-reference/commands/app/tag-add) Tag add [#tag-add] Add an application tag Usage [#usage] ```sh coolify app tag add ``` Get current help [#get-current-help] ```sh coolify app tag add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag list (/docs/cli/command-reference/commands/app/tag-list) Tag list [#tag-list] List application tags Usage [#usage] ```sh coolify app tag list ``` Get current help [#get-current-help] ```sh coolify app tag list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag remove (/docs/cli/command-reference/commands/app/tag-remove) Tag remove [#tag-remove] Remove an application tag Usage [#usage] ```sh coolify app tag remove ``` Get current help [#get-current-help] ```sh coolify app tag remove --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task create (/docs/cli/command-reference/commands/app/task-create) Task create [#task-create] Create a scheduled task for an application Usage [#usage] ```sh coolify app task create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :-------------------------------------- | | `--command` | `string` | Yes | — | Command to run (required) | | `--container` | `string` | No | — | Container name to run the command in | | `--enabled` | `boolean` | No | `true` | Whether the task is enabled | | `--frequency` | `string` | Yes | — | Cron expression or frequency (required) | | `--name` | `string` | Yes | — | Task name (required) | | `--timeout` | `integer` | No | `300` | Timeout in seconds | Get current help [#get-current-help] ```sh coolify app task create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task delete (/docs/cli/command-reference/commands/app/task-delete) Task delete [#task-delete] Delete an application scheduled task Usage [#usage] ```sh coolify app task delete ``` Get current help [#get-current-help] ```sh coolify app task delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task execute (/docs/cli/command-reference/commands/app/task-execute) Task execute [#task-execute] Execute an application scheduled task now Usage [#usage] ```sh coolify app task execute ``` Get current help [#get-current-help] ```sh coolify app task execute --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task executions (/docs/cli/command-reference/commands/app/task-executions) Task executions [#task-executions] List executions for an application scheduled task Usage [#usage] ```sh coolify app task executions ``` Get current help [#get-current-help] ```sh coolify app task executions --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task list (/docs/cli/command-reference/commands/app/task-list) Task list [#task-list] List scheduled tasks for an application Usage [#usage] ```sh coolify app task list ``` Get current help [#get-current-help] ```sh coolify app task list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task update (/docs/cli/command-reference/commands/app/task-update) Task update [#task-update] Update an application scheduled task Usage [#usage] ```sh coolify app task update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :----------------------------------- | | `--command` | `string` | No | — | Command to run | | `--container` | `string` | No | — | Container name to run the command in | | `--enabled` | `boolean` | No | `true` | Whether the task is enabled | | `--frequency` | `string` | No | — | Cron expression or frequency | | `--name` | `string` | No | — | Task name | | `--timeout` | `integer` | No | `300` | Timeout in seconds | Get current help [#get-current-help] ```sh coolify app task update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/app/update) Update [#update] Update application configuration Usage [#usage] ```sh coolify app update ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------------------------- | :------------ | :------: | :------ | :------------------------------------------------------------------------------- | | `--base-directory` | `string` | No | — | Base directory | | `--build-command` | `string` | No | — | Build command | | `--compose-domain` | `stringArray` | No | — | Docker Compose service domain in \=\\[,\] format (repeatable) | | `--custom-internal-name` | `string` | No | — | Custom internal hostname | | `--description` | `string` | No | — | Application description | | `--disable-build-cache` | `boolean` | No | `false` | Disable the build cache | | `--docker-image` | `string` | No | — | Docker image name | | `--docker-images-to-keep` | `integer` | No | `0` | Number of Docker images to retain | | `--docker-tag` | `string` | No | — | Docker image tag | | `--dockerfile` | `string` | No | — | Dockerfile content | | `--dockerfile-target-build` | `string` | No | — | Dockerfile target build stage | | `--domains` | `string` | No | — | Domains (comma-separated) | | `--git-branch` | `string` | No | — | Git branch | | `--git-repository` | `string` | No | — | Git repository URL | | `--gpu-count` | `string` | No | — | GPU count | | `--gpu-device-ids` | `string` | No | — | GPU device IDs | | `--gpu-driver` | `string` | No | — | GPU driver | | `--gpu-options` | `string` | No | — | GPU options | | `--health-check-enabled` | `boolean` | No | `false` | Enable health check | | `--health-check-path` | `string` | No | — | Health check path | | `--include-source-commit-in-build` | `boolean` | No | `false` | Include the source commit in the build | | `--inject-build-args-to-dockerfile` | `boolean` | No | `false` | Inject build arguments into the Dockerfile | | `--install-command` | `string` | No | — | Install command | | `--is-consistent-container-name-enabled` | `boolean` | No | `false` | Use consistent container names | | `--is-env-sorting-enabled` | `boolean` | No | `false` | Sort environment variables | | `--is-git-lfs-enabled` | `boolean` | No | `false` | Enable Git LFS | | `--is-git-shallow-clone-enabled` | `boolean` | No | `false` | Use a shallow Git clone | | `--is-git-submodules-enabled` | `boolean` | No | `false` | Clone Git submodules | | `--is-gpu-enabled` | `boolean` | No | `false` | Enable GPU | | `--is-gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--is-log-drain-enabled` | `boolean` | No | `false` | Enable application log drain | | `--is-pr-deployments-public-enabled` | `boolean` | No | `false` | Make pull request deployments public | | `--is-preview-deployments-enabled` | `boolean` | No | `false` | Enable preview deployments | | `--is-raw-compose-deployment-enabled` | `boolean` | No | `false` | Deploy the raw Docker Compose definition | | `--is-stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--max-restart-count` | `integer` | No | `0` | Maximum container restart count | | `--name` | `string` | No | — | Application name | | `--ports-exposes` | `string` | No | — | Exposed ports | | `--ports-mappings` | `string` | No | — | Port mappings | | `--preview-url-template` | `string` | No | — | Preview URL template | | `--publish-directory` | `string` | No | — | Publish directory | | `--start-command` | `string` | No | — | Start command | | `--stop-grace-period` | `integer` | No | `0` | Container stop grace period in seconds | | `--use-build-secrets` | `boolean` | No | `false` | Use Docker Build Secrets for build-time variables | Get current help [#get-current-help] ```sh coolify app update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/cloud-init/create) Create [#create] Create a cloud-init script Usage [#usage] ```sh coolify cloud-init create ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :----------------------------- | | `--name` | `string` | No | — | Script name | | `--script` | `string` | No | — | Script contents | | `--script-file` | `string` | No | — | Read script contents from file | Get current help [#get-current-help] ```sh coolify cloud-init create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/cloud-init/delete) Delete [#delete] Delete a cloud-init script Usage [#usage] ```sh coolify cloud-init delete ``` Get current help [#get-current-help] ```sh coolify cloud-init delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/cloud-init/get) Get [#get] Get a cloud-init script Usage [#usage] ```sh coolify cloud-init get ``` Get current help [#get-current-help] ```sh coolify cloud-init get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/cloud-init/list) List [#list] List cloud-init scripts Usage [#usage] ```sh coolify cloud-init list ``` Get current help [#get-current-help] ```sh coolify cloud-init list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/cloud-init/update) Update [#update] Update a cloud-init script Usage [#usage] ```sh coolify cloud-init update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :----------------------------- | | `--name` | `string` | No | — | Script name | | `--script` | `string` | No | — | Script contents | | `--script-file` | `string` | No | — | Read script contents from file | Get current help [#get-current-help] ```sh coolify cloud-init update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/cloud-token/create) Create [#create] Create a cloud provider token Usage [#usage] ```sh coolify cloud-token create ``` Options [#options] | Option | Type | Required | Default | Description | | :----------------- | :------- | :------: | :------ | :------------------------------------------------------- | | `--name` | `string` | No | — | Friendly token name | | `--provider` | `string` | No | — | Cloud provider: hetzner, digitalocean, or vultr | | `--provider-token` | `string` | No | — | Provider API token (sensitive; never included in output) | Get current help [#get-current-help] ```sh coolify cloud-token create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/cloud-token/delete) Delete [#delete] Delete a cloud provider token Usage [#usage] ```sh coolify cloud-token delete ``` Get current help [#get-current-help] ```sh coolify cloud-token delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/cloud-token/get) Get [#get] Show a cloud provider token Usage [#usage] ```sh coolify cloud-token get ``` Get current help [#get-current-help] ```sh coolify cloud-token get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/cloud-token/list) List [#list] List cloud provider tokens Usage [#usage] ```sh coolify cloud-token list ``` Get current help [#get-current-help] ```sh coolify cloud-token list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/cloud-token/update) Update [#update] Rename a cloud provider token Usage [#usage] ```sh coolify cloud-token update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :---------------------- | | `--name` | `string` | No | — | New friendly token name | Get current help [#get-current-help] ```sh coolify cloud-token update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Validate (/docs/cli/command-reference/commands/cloud-token/validate) Validate [#validate] Validate a cloud provider token Usage [#usage] ```sh coolify cloud-token validate ``` Get current help [#get-current-help] ```sh coolify cloud-token validate --help ``` The installed CLI help reflects the exact options available in your CLI version. # Completion (/docs/cli/command-reference/commands/completion) Completion [#completion] Output shell completion code for the specified shell Usage [#usage] ```sh coolify completion ``` Get current help [#get-current-help] ```sh coolify completion --help ``` The installed CLI help reflects the exact options available in your CLI version. # Config (/docs/cli/command-reference/commands/config) Config [#config] Display the path to the Coolify CLI configuration file Usage [#usage] ```sh coolify config ``` Get current help [#get-current-help] ```sh coolify config --help ``` The installed CLI help reflects the exact options available in your CLI version. # Add (/docs/cli/command-reference/commands/context/add) Add [#add] Add a new context Usage [#usage] ```sh coolify context add ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :---------------------------------------- | | `--default (-d)` | `boolean` | No | `false` | Set as default context | | `--force (-f)` | `boolean` | No | `false` | Force overwrite if context already exists | Get current help [#get-current-help] ```sh coolify context add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/context/delete) Delete [#delete] Delete a context Usage [#usage] ```sh coolify context delete ``` Get current help [#get-current-help] ```sh coolify context delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/context/get) Get [#get] Get details of a specific context Usage [#usage] ```sh coolify context get ``` Get current help [#get-current-help] ```sh coolify context get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/context/list) List [#list] List all configured contexts Usage [#usage] ```sh coolify context list ``` Get current help [#get-current-help] ```sh coolify context list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Set default (/docs/cli/command-reference/commands/context/set-default) Set default [#set-default] Set a context as the default Usage [#usage] ```sh coolify context set-default ``` Get current help [#get-current-help] ```sh coolify context set-default --help ``` The installed CLI help reflects the exact options available in your CLI version. # Set token (/docs/cli/command-reference/commands/context/set-token) Set token [#set-token] Update the API token for a context Usage [#usage] ```sh coolify context set-token ``` Get current help [#get-current-help] ```sh coolify context set-token --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/context/update) Update [#update] Update a context's properties (name, URL, token) Usage [#usage] ```sh coolify context update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :------- | :------: | :------ | :------------------------ | | `--name (-n)` | `string` | No | — | New name for the context | | `--token (-t)` | `string` | No | — | New token for the context | | `--url (-u)` | `string` | No | — | New URL for the context | Get current help [#get-current-help] ```sh coolify context update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Use (/docs/cli/command-reference/commands/context/use) Use [#use] Switch to a different context (set as default) Usage [#usage] ```sh coolify context use ``` Get current help [#get-current-help] ```sh coolify context use --help ``` The installed CLI help reflects the exact options available in your CLI version. # Verify (/docs/cli/command-reference/commands/context/verify) Verify [#verify] Verify current context connection and authentication Usage [#usage] ```sh coolify context verify ``` Get current help [#get-current-help] ```sh coolify context verify --help ``` The installed CLI help reflects the exact options available in your CLI version. # Version (/docs/cli/command-reference/commands/context/version) Version [#version] Get current context's Coolify version Usage [#usage] ```sh coolify context version ``` Get current help [#get-current-help] ```sh coolify context version --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup create (/docs/cli/command-reference/commands/database/backup-create) Backup create [#backup-create] Create a new scheduled backup configuration Usage [#usage] ```sh coolify database backup create ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------------------------- | :-------- | :------: | :------ | :----------------------------------------------------------------- | | `--databases-to-backup` | `string` | No | — | Comma-separated list of databases to backup | | `--disable-local-backup` | `boolean` | No | `false` | Disable local backup storage | | `--dump-all` | `boolean` | No | `false` | Dump all databases | | `--enabled` | `boolean` | No | `false` | Enable backup schedule | | `--frequency` | `string` | No | — | Backup frequency (cron expression, e.g., '0 0 \* \* \*' for daily) | | `--retention-amount-locally` | `integer` | No | `0` | Number of backups to retain locally | | `--retention-amount-s3` | `integer` | No | `0` | Number of backups to retain in S3 | | `--retention-days-locally` | `integer` | No | `0` | Days to retain backups locally | | `--retention-days-s3` | `integer` | No | `0` | Days to retain backups in S3 | | `--retention-max-storage-locally` | `float64` | No | `0` | Max storage for local backups (GB) | | `--retention-max-storage-s3` | `float64` | No | `0` | Max storage for S3 backups (GB) | | `--s3-storage-uuid` | `string` | No | — | S3 storage UUID | | `--save-s3` | `boolean` | No | `false` | Save backups to S3 | | `--timeout` | `integer` | No | `0` | Backup timeout in seconds | Get current help [#get-current-help] ```sh coolify database backup create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup delete execution (/docs/cli/command-reference/commands/database/backup-delete-execution) Backup delete execution [#backup-delete-execution] Delete a specific backup execution and optionally from S3. First UUID is the database, second is the backup configuration, third is the specific execution. Usage [#usage] ```sh coolify database backup delete-execution ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :------------------------- | | `--delete-s3` | `boolean` | No | `false` | Delete backup file from S3 | Get current help [#get-current-help] ```sh coolify database backup delete-execution --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup delete (/docs/cli/command-reference/commands/database/backup-delete) Backup delete [#backup-delete] Delete a backup configuration and optionally all its executions from S3. First UUID is the database, second is the specific backup configuration. Usage [#usage] ```sh coolify database backup delete ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :-------------------------- | | `--delete-s3` | `boolean` | No | `false` | Delete backup files from S3 | Get current help [#get-current-help] ```sh coolify database backup delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup executions (/docs/cli/command-reference/commands/database/backup-executions) Backup executions [#backup-executions] List all executions for a backup configuration. First UUID is the database, second is the specific backup configuration. Usage [#usage] ```sh coolify database backup executions ``` Get current help [#get-current-help] ```sh coolify database backup executions --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup list (/docs/cli/command-reference/commands/database/backup-list) Backup list [#backup-list] List all backup configurations for a specific database. Usage [#usage] ```sh coolify database backup list ``` Get current help [#get-current-help] ```sh coolify database backup list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup trigger (/docs/cli/command-reference/commands/database/backup-trigger) Backup trigger [#backup-trigger] Trigger an immediate backup for a specific backup configuration. First UUID is the database, second is the specific backup configuration to trigger. Usage [#usage] ```sh coolify database backup trigger ``` Get current help [#get-current-help] ```sh coolify database backup trigger --help ``` The installed CLI help reflects the exact options available in your CLI version. # Backup update (/docs/cli/command-reference/commands/database/backup-update) Backup update [#backup-update] Update a backup configuration settings (frequency, retention, S3, etc.). First UUID is the database, second is the specific backup configuration. Usage [#usage] ```sh coolify database backup update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------------------------- | :-------- | :------: | :------ | :------------------------------------------ | | `--databases-to-backup` | `string` | No | — | Comma-separated list of databases to backup | | `--dump-all` | `boolean` | No | `false` | Dump all databases | | `--enabled` | `boolean` | No | `false` | Enable or disable backup | | `--frequency` | `string` | No | — | Backup frequency (cron expression) | | `--retention-amount-locally` | `integer` | No | `0` | Number of backups to retain locally | | `--retention-amount-s3` | `integer` | No | `0` | Number of backups to retain in S3 | | `--retention-days-locally` | `integer` | No | `0` | Days to retain backups locally | | `--retention-days-s3` | `integer` | No | `0` | Days to retain backups in S3 | | `--retention-max-storage-locally` | `float64` | No | `0` | Max storage for local backups (GB) | | `--retention-max-storage-s3` | `float64` | No | `0` | Max storage for S3 backups (GB) | | `--s3-storage-uuid` | `string` | No | — | S3 storage UUID | | `--save-s3` | `boolean` | No | `false` | Save backups to S3 | Get current help [#get-current-help] ```sh coolify database backup update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Clone (/docs/cli/command-reference/commands/database/clone) Clone [#clone] Clone a database to a destination Usage [#usage] ```sh coolify database clone ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :---------------- | | `--clone-volumes` | `boolean` | No | `false` | Clone volume data | | `--destination` | `string` | No | — | Destination UUID | | `--name` | `string` | No | — | Optional new name | Get current help [#get-current-help] ```sh coolify database clone --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/database/create) Create [#create] Create a new database Usage [#usage] ```sh coolify database create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------------- | :------------ | :------: | :------ | :--------------------------------------------------- | | `--clickhouse-admin-password` | `string` | No | — | Clickhouse admin password | | `--clickhouse-admin-user` | `string` | No | — | Clickhouse admin user | | `--description` | `string` | No | — | Database description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--dragonfly-password` | `string` | No | — | Dragonfly password | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--image` | `string` | No | — | Docker image | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--is-public` | `boolean` | No | `false` | Make database publicly accessible | | `--keydb-password` | `string` | No | — | KeyDB password | | `--limits-cpus` | `string` | No | — | CPU limit (e.g., '0.5', '2') | | `--limits-memory` | `string` | No | — | Memory limit (e.g., '512m', '2g') | | `--mariadb-database` | `string` | No | — | MariaDB database name | | `--mariadb-password` | `string` | No | — | MariaDB password | | `--mariadb-root-password` | `string` | No | — | MariaDB root password | | `--mariadb-user` | `string` | No | — | MariaDB user | | `--mongo-database` | `string` | No | — | MongoDB database name | | `--mongo-root-password` | `string` | No | — | MongoDB root password | | `--mongo-root-username` | `string` | No | — | MongoDB root username | | `--mysql-database` | `string` | No | — | MySQL database name | | `--mysql-password` | `string` | No | — | MySQL password | | `--mysql-root-password` | `string` | No | — | MySQL root password | | `--mysql-user` | `string` | No | — | MySQL user | | `--name` | `string` | No | — | Database name | | `--postgres-db` | `string` | No | — | PostgreSQL database name | | `--postgres-password` | `string` | No | — | PostgreSQL password | | `--postgres-user` | `string` | No | — | PostgreSQL user | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--public-port` | `integer` | No | `0` | Public port | | `--redis-password` | `string` | No | — | Redis password | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--tag` | `stringArray` | No | — | Tag to assign (repeatable) | | `--tags` | `stringSlice` | No | — | Comma-separated tags to assign | Get current help [#get-current-help] ```sh coolify database create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/database/delete) Delete [#delete] Delete a database and optionally clean up its configurations, volumes, and networks. Usage [#usage] ```sh coolify database delete ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------------- | :-------- | :------: | :------ | :------------------------ | | `--delete-configurations` | `boolean` | No | `true` | Delete configurations | | `--delete-connected-networks` | `boolean` | No | `true` | Delete connected networks | | `--delete-volumes` | `boolean` | No | `true` | Delete volumes | | `--docker-cleanup` | `boolean` | No | `true` | Run docker cleanup | Get current help [#get-current-help] ```sh coolify database delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env create (/docs/cli/command-reference/commands/database/env-create) Env create [#env-create] Create a new environment variable for a specific database. Use --key and --value flags to specify the variable. Usage [#usage] ```sh coolify database env create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :--------------------------------------------------- | | `--comment` | `string` | No | — | Comment for the environment variable | | `--is-literal` | `boolean` | No | `false` | Treat value as literal (don't interpolate variables) | | `--is-multiline` | `boolean` | No | `false` | Value is multiline | | `--is-shown-once` | `boolean` | No | `false` | Only show value once | | `--key` | `string` | Yes | — | Environment variable key (required) | | `--value` | `string` | Yes | — | Environment variable value (required) | Get current help [#get-current-help] ```sh coolify database env create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env delete (/docs/cli/command-reference/commands/database/env-delete) Env delete [#env-delete] Delete an environment variable from a database. First UUID is the database, second is the specific environment variable to delete. Usage [#usage] ```sh coolify database env delete ``` Options [#options] | Option | Type | Required | Default | Description | | :-------- | :-------- | :------: | :------ | :----------------------- | | `--force` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify database env delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env get (/docs/cli/command-reference/commands/database/env-get) Env get [#env-get] Get detailed information about a specific environment variable. First UUID is the database, second is the environment variable UUID or key name. Usage [#usage] ```sh coolify database env get ``` Get current help [#get-current-help] ```sh coolify database env get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env list (/docs/cli/command-reference/commands/database/env-list) Env list [#env-list] List all environment variables for a specific database. Usage [#usage] ```sh coolify database env list ``` Get current help [#get-current-help] ```sh coolify database env list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env sync (/docs/cli/command-reference/commands/database/env-sync) Env sync [#env-sync] Sync environment variables from a .env file Usage [#usage] ```sh coolify database env sync ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :-------------------------------------------------------- | | `--file (-f)` | `string` | Yes | — | Path to .env file (required) | | `--is-literal` | `boolean` | No | `false` | Treat all values as literal (don't interpolate variables) | Get current help [#get-current-help] ```sh coolify database env sync --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env update (/docs/cli/command-reference/commands/database/env-update) Env update [#env-update] Update an existing environment variable. Identify it by UUID or key name. Usage [#usage] ```sh coolify database env update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :---------------------------------------- | | `--comment` | `string` | No | — | Comment for the environment variable | | `--is-literal` | `boolean` | No | `false` | Treat value as literal | | `--is-multiline` | `boolean` | No | `false` | Value is multiline | | `--is-shown-once` | `boolean` | No | `false` | Only show value once | | `--key` | `string` | No | — | New environment variable key (rename) | | `--value` | `string` | Yes | — | New environment variable value (required) | Get current help [#get-current-help] ```sh coolify database env update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/database/get) Get [#get] Get detailed information about a specific database by UUID. Usage [#usage] ```sh coolify database get ``` Get current help [#get-current-help] ```sh coolify database get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/database/list) List [#list] List all databases in Coolify. Usage [#usage] ```sh coolify database list ``` Get current help [#get-current-help] ```sh coolify database list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Logs (/docs/cli/command-reference/commands/database/logs) Logs [#logs] Get database logs Usage [#usage] ```sh coolify database logs ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------ | :-------- | :------: | :------ | :------------------------------ | | `--lines (-n)` | `integer` | No | `100` | Number of log lines to retrieve | | `--show-timestamps` | `boolean` | No | `false` | Include timestamps in logs | Get current help [#get-current-help] ```sh coolify database logs --help ``` The installed CLI help reflects the exact options available in your CLI version. # Move (/docs/cli/command-reference/commands/database/move) Move [#move] Move a database to another environment Usage [#usage] ```sh coolify database move ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :------- | :------: | :------ | :--------------------------------- | | `--environment-uuid` | `string` | Yes | — | Target environment UUID (required) | Get current help [#get-current-help] ```sh coolify database move --help ``` The installed CLI help reflects the exact options available in your CLI version. # Restart (/docs/cli/command-reference/commands/database/restart) Restart [#restart] Restart a database by UUID. Usage [#usage] ```sh coolify database restart ``` Get current help [#get-current-help] ```sh coolify database restart --help ``` The installed CLI help reflects the exact options available in your CLI version. # Run storage backup (/docs/cli/command-reference/commands/database/run-storage-backup) Run storage backup [#run-storage-backup] Run a volume backup schedule now Usage [#usage] ```sh coolify database run-storage-backup ``` Get current help [#get-current-help] ```sh coolify database run-storage-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Start (/docs/cli/command-reference/commands/database/start) Start [#start] Start a database by UUID. Usage [#usage] ```sh coolify database start ``` Get current help [#get-current-help] ```sh coolify database start --help ``` The installed CLI help reflects the exact options available in your CLI version. # Stop (/docs/cli/command-reference/commands/database/stop) Stop [#stop] Stop a database by UUID. Usage [#usage] ```sh coolify database stop ``` Get current help [#get-current-help] ```sh coolify database stop --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage create (/docs/cli/command-reference/commands/database/storage-create) Storage create [#storage-create] Create a storage for a database Usage [#usage] ```sh coolify database storage create ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :------------------------------------------------------------------- | | `--content` | `string` | No | — | File content (file only) | | `--fs-path` | `string` | No | — | Host directory path (file only, required when --is-directory is set) | | `--host-path` | `string` | No | — | Host path (persistent only) | | `--is-directory` | `boolean` | No | `false` | Whether this is a directory mount (file only) | | `--mount-path` | `string` | Yes | — | Mount path inside the container (required) | | `--name` | `string` | No | — | Volume name (persistent only) | | `--type` | `string` | Yes | — | Storage type: 'persistent' or 'file' (required) | Get current help [#get-current-help] ```sh coolify database storage create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage delete backup (/docs/cli/command-reference/commands/database/storage-delete-backup) Storage delete backup [#storage-delete-backup] Delete database storage volume backup schedule Usage [#usage] ```sh coolify database storage delete-backup ``` Get current help [#get-current-help] ```sh coolify database storage delete-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage delete (/docs/cli/command-reference/commands/database/storage-delete) Storage delete [#storage-delete] Delete a storage from a database Usage [#usage] ```sh coolify database storage delete ``` Get current help [#get-current-help] ```sh coolify database storage delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage list (/docs/cli/command-reference/commands/database/storage-list) Storage list [#storage-list] List all persistent volumes and file storages for a specific database. Usage [#usage] ```sh coolify database storage list ``` Get current help [#get-current-help] ```sh coolify database storage list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage run backup (/docs/cli/command-reference/commands/database/storage-run-backup) Storage run backup [#storage-run-backup] Run database storage volume backup now Usage [#usage] ```sh coolify database storage run-backup ``` Get current help [#get-current-help] ```sh coolify database storage run-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage set backup (/docs/cli/command-reference/commands/database/storage-set-backup) Storage set backup [#storage-set-backup] Create or replace database storage volume backup schedule Usage [#usage] ```sh coolify database storage set-backup ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------------------------- | :-------- | :------: | :------ | :------------------------------------ | | `--disable-local-backup` | `boolean` | No | `false` | Disable local backup retention | | `--enabled` | `boolean` | No | `true` | Enable the schedule | | `--frequency` | `string` | Yes | — | Cron frequency (required) | | `--retention-amount-locally` | `integer` | No | `7` | Local retention count | | `--retention-amount-s3` | `integer` | No | `7` | S3 retention count | | `--retention-days-locally` | `integer` | No | `0` | Local retention days | | `--retention-days-s3` | `integer` | No | `0` | S3 retention days | | `--retention-max-storage-locally` | `float64` | No | `0` | Local max storage | | `--retention-max-storage-s3` | `float64` | No | `0` | S3 max storage | | `--s3-storage-uuid` | `string` | No | — | S3 storage UUID when --save-s3 is set | | `--save-s3` | `boolean` | No | `false` | Also save backups to S3 | | `--stop-during-backup` | `boolean` | No | `false` | Stop resource during backup | | `--timeout` | `integer` | No | `3600` | Backup timeout seconds | Get current help [#get-current-help] ```sh coolify database storage set-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage update (/docs/cli/command-reference/commands/database/storage-update) Storage update [#storage-update] Update a storage for a database Usage [#usage] ```sh coolify database storage update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------------- | :-------- | :------: | :------ | :-------------------------------------------------- | | `--content` | `string` | No | — | File content (file only) | | `--host-path` | `string` | No | — | Host path (persistent only) | | `--id` | `integer` | No | `0` | Storage ID (deprecated, use --uuid instead) | | `--is-preview-suffix-enabled` | `boolean` | No | `false` | Enable preview suffix for this storage | | `--mount-path` | `string` | No | — | Mount path inside the container | | `--name` | `string` | No | — | Storage name (persistent only) | | `--type` | `string` | Yes | — | Storage type: 'persistent' or 'file' (required) | | `--uuid` | `string` | No | — | Storage UUID (required, use 'storage list' to find) | Get current help [#get-current-help] ```sh coolify database storage update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag add (/docs/cli/command-reference/commands/database/tag-add) Tag add [#tag-add] Add a database tag Usage [#usage] ```sh coolify database tag add ``` Get current help [#get-current-help] ```sh coolify database tag add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag list (/docs/cli/command-reference/commands/database/tag-list) Tag list [#tag-list] List database tags Usage [#usage] ```sh coolify database tag list ``` Get current help [#get-current-help] ```sh coolify database tag list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag remove (/docs/cli/command-reference/commands/database/tag-remove) Tag remove [#tag-remove] Remove a database tag Usage [#usage] ```sh coolify database tag remove ``` Get current help [#get-current-help] ```sh coolify database tag remove --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/database/update) Update [#update] Update a database's configuration by UUID. Usage [#usage] ```sh coolify database update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :-------------------------------- | | `--description` | `string` | No | — | Database description | | `--image` | `string` | No | — | Docker image | | `--is-public` | `boolean` | No | `false` | Make database publicly accessible | | `--limits-cpus` | `string` | No | — | CPU limit | | `--limits-memory` | `string` | No | — | Memory limit | | `--name` | `string` | No | — | Database name | | `--public-port` | `integer` | No | `0` | Public port | Get current help [#get-current-help] ```sh coolify database update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Batch (/docs/cli/command-reference/commands/deploy/batch) Batch [#batch] Deploy multiple resources by name Usage [#usage] ```sh coolify deploy batch ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------ | :-------- | :------: | :------ | :------------------------------------------- | | `--docker-tag` | `string` | No | — | Docker image tag override for the deployment | | `--force` | `boolean` | No | `false` | Force deployment | | `--pull-request-id` | `integer` | No | `0` | Pull request ID for preview deployments | Get current help [#get-current-help] ```sh coolify deploy batch --help ``` The installed CLI help reflects the exact options available in your CLI version. # Cancel (/docs/cli/command-reference/commands/deploy/cancel) Cancel [#cancel] Cancel an in-progress deployment. This will stop the deployment process and clean up any temporary resources. Usage [#usage] ```sh coolify deploy cancel ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify deploy cancel --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/deploy/get) Get [#get] Get detailed information about a specific deployment by its UUID. Usage [#usage] ```sh coolify deploy get ``` Get current help [#get-current-help] ```sh coolify deploy get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/deploy/list) List [#list] List all currently running deployments across all resources. Usage [#usage] ```sh coolify deploy list ``` Get current help [#get-current-help] ```sh coolify deploy list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Name (/docs/cli/command-reference/commands/deploy/name) Name [#name] Deploy by resource name Usage [#usage] ```sh coolify deploy name ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------ | :-------- | :------: | :------ | :------------------------------------------- | | `--docker-tag` | `string` | No | — | Docker image tag override for the deployment | | `--force` | `boolean` | No | `false` | Force deployment | | `--pull-request-id` | `integer` | No | `0` | Pull request ID for preview deployments | Get current help [#get-current-help] ```sh coolify deploy name --help ``` The installed CLI help reflects the exact options available in your CLI version. # Uuid (/docs/cli/command-reference/commands/deploy/uuid) Uuid [#uuid] Deploy by uuid Usage [#usage] ```sh coolify deploy uuid ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------ | :-------- | :------: | :------ | :------------------------------------------- | | `--docker-tag` | `string` | No | — | Docker image tag override for the deployment | | `--force` | `boolean` | No | `false` | Force deployment | | `--pull-request-id` | `integer` | No | `0` | Pull request ID for preview deployments | Get current help [#get-current-help] ```sh coolify deploy uuid --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/destination/create) Create [#create] Create a destination for a server Usage [#usage] ```sh coolify destination create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------- | :------- | :------: | :------ | :---------------------------------------- | | `--name` | `string` | No | — | Destination name (defaults on the server) | | `--network` | `string` | Yes | — | Docker network name (required) | | `--server` | `string` | Yes | — | Server UUID (required) | | `--type` | `string` | No | — | Destination type: standalone or swarm | Get current help [#get-current-help] ```sh coolify destination create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/destination/delete) Delete [#delete] Delete an unused destination Usage [#usage] ```sh coolify destination delete ``` Get current help [#get-current-help] ```sh coolify destination delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/destination/get) Get [#get] Get a destination Usage [#usage] ```sh coolify destination get ``` Get current help [#get-current-help] ```sh coolify destination get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/destination/list) List [#list] List destinations Usage [#usage] ```sh coolify destination list ``` Options [#options] | Option | Type | Required | Default | Description | | :--------- | :------- | :------: | :------ | :---------------------------------------------- | | `--server` | `string` | No | — | Only destinations belonging to this server UUID | Get current help [#get-current-help] ```sh coolify destination list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/destination/update) Update [#update] Rename a destination Usage [#usage] ```sh coolify destination update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :------------------- | | `--name` | `string` | No | — | New destination name | Get current help [#get-current-help] ```sh coolify destination update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Branches (/docs/cli/command-reference/commands/github/branches) Branches [#branches] List branches for a repository Usage [#usage] ```sh coolify github branches ``` Get current help [#get-current-help] ```sh coolify github branches --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/github/create) Create [#create] Create a GitHub App integration Usage [#usage] ```sh coolify github create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :-------- | :------: | :------ | :------------------------------------------------------------------------- | | `--api-url` | `string` | No | — | GitHub API URL (derived from --html-url when omitted) | | `--app-id` | `integer` | Yes | `0` | GitHub App ID (required) | | `--client-id` | `string` | Yes | — | GitHub OAuth Client ID (required) | | `--client-secret` | `string` | Yes | — | GitHub OAuth Client Secret (required) | | `--custom-port` | `integer` | No | `0` | Custom port for SSH (default: 22) | | `--custom-user` | `string` | No | — | Custom user for SSH (default: git) | | `--html-url` | `string` | Yes | — | GitHub HTML URL (required, e.g., [https://github.com](https://github.com)) | | `--installation-id` | `integer` | Yes | `0` | GitHub Installation ID (required) | | `--name` | `string` | Yes | — | GitHub App name (required) | | `--organization` | `string` | No | — | GitHub organization | | `--private-key-uuid` | `string` | Yes | — | UUID of existing private key (required) | | `--system-wide` | `boolean` | No | `false` | Is this app system-wide (cloud only) | | `--webhook-secret` | `string` | No | — | GitHub Webhook Secret | Get current help [#get-current-help] ```sh coolify github create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/github/delete) Delete [#delete] Delete a GitHub App integration. The app must not be used by any applications. Usage [#usage] ```sh coolify github delete ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify github delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/github/get) Get [#get] Get detailed information about a specific GitHub App integration. Usage [#usage] ```sh coolify github get ``` Get current help [#get-current-help] ```sh coolify github get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/github/list) List [#list] List all GitHub App integrations configured in Coolify. Usage [#usage] ```sh coolify github list ``` Get current help [#get-current-help] ```sh coolify github list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Repos (/docs/cli/command-reference/commands/github/repos) Repos [#repos] List all repositories that are accessible by the specified GitHub App. Usage [#usage] ```sh coolify github repos ``` Get current help [#get-current-help] ```sh coolify github repos --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/github/update) Update [#update] Update an existing GitHub App integration. Provide the app UUID and the fields you want to update. Usage [#usage] ```sh coolify github update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :-------- | :------: | :------ | :------------------------- | | `--api-url` | `string` | No | — | GitHub API URL | | `--app-id` | `integer` | No | `0` | GitHub App ID | | `--client-id` | `string` | No | — | GitHub OAuth Client ID | | `--client-secret` | `string` | No | — | GitHub OAuth Client Secret | | `--custom-port` | `integer` | No | `0` | Custom port for SSH | | `--custom-user` | `string` | No | — | Custom user for SSH | | `--html-url` | `string` | No | — | GitHub HTML URL | | `--installation-id` | `integer` | No | `0` | GitHub Installation ID | | `--name` | `string` | No | — | GitHub App name | | `--organization` | `string` | No | — | GitHub organization | | `--private-key-uuid` | `string` | No | — | UUID of private key | | `--system-wide` | `boolean` | No | `false` | Is this app system-wide | | `--webhook-secret` | `string` | No | — | GitHub Webhook Secret | Get current help [#get-current-help] ```sh coolify github update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/gitlab/create) Create [#create] Create a GitLab App integration Usage [#usage] ```sh coolify gitlab create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :---------------------------------------------------------------------------- | | `--api-url` | `string` | No | — | GitLab API URL (defaults to \{html-url}/api/v4) | | `--client-id` | `string` | No | — | GitLab OAuth Application ID | | `--client-secret` | `string` | No | — | GitLab OAuth Application Secret | | `--custom-port` | `integer` | No | `0` | Custom SSH port (default: 22) | | `--custom-user` | `string` | No | — | Custom SSH user (default: git) | | `--group-name` | `string` | No | — | Optional comma-separated group filter | | `--html-url` | `string` | Yes | — | GitLab instance URL (required, e.g. [https://gitlab.com](https://gitlab.com)) | | `--name` | `string` | Yes | — | GitLab App name (required) | | `--redirect-uri` | `string` | No | — | OAuth redirect URI registered in GitLab | | `--system-wide` | `boolean` | No | `false` | Make this app system-wide (non-cloud instances only) | | `--webhook-token` | `string` | No | — | Webhook secret token (auto-generated when omitted) | Get current help [#get-current-help] ```sh coolify gitlab create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/gitlab/delete) Delete [#delete] Delete a GitLab App integration. The app must not be used by any applications. Usage [#usage] ```sh coolify gitlab delete ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify gitlab delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/gitlab/get) Get [#get] Get detailed information about a specific GitLab App integration. Usage [#usage] ```sh coolify gitlab get ``` Get current help [#get-current-help] ```sh coolify gitlab get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/gitlab/list) List [#list] List all GitLab App integrations configured in Coolify for the current team (includes system-wide sources). Usage [#usage] ```sh coolify gitlab list ``` Get current help [#get-current-help] ```sh coolify gitlab list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/gitlab/update) Update [#update] Update an existing GitLab App integration. Provide the app ID or UUID and the fields you want to update. Usage [#usage] ```sh coolify gitlab update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :------------------------------------ | | `--api-url` | `string` | No | — | GitLab API URL | | `--client-id` | `string` | No | — | GitLab OAuth Application ID | | `--client-secret` | `string` | No | — | GitLab OAuth Application Secret | | `--custom-port` | `integer` | No | `0` | Custom SSH port | | `--custom-user` | `string` | No | — | Custom SSH user | | `--group-name` | `string` | No | — | Optional comma-separated group filter | | `--html-url` | `string` | No | — | GitLab instance URL | | `--name` | `string` | No | — | GitLab App name | | `--redirect-uri` | `string` | No | — | OAuth redirect URI | | `--system-wide` | `boolean` | No | `false` | Is this app system-wide | | `--webhook-token` | `string` | No | — | Webhook secret token | Get current help [#get-current-help] ```sh coolify gitlab update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Global options (/docs/cli/command-reference/commands/global-options) Global options [#global-options] Coolify CLI Usage [#usage] ```sh coolify ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------- | :-------- | :------: | :------ | :------------------------------------------------ | | `--context` | `string` | No | — | Use specific context by name | | `--debug` | `boolean` | No | `false` | Debug mode | | `--format` | `string` | No | `table` | Format output (table\|json\|pretty) | | `--show-sensitive (-s)` | `boolean` | No | `false` | Show sensitive information | | `--token` | `string` | No | — | Token for authentication (override context token) | Get current help [#get-current-help] ```sh coolify --help ``` The installed CLI help reflects the exact options available in your CLI version. # Disable (/docs/cli/command-reference/commands/mcp/disable) Disable [#disable] Disable the Coolify MCP server (API: POST /mcp/disable). Requires a root team API token. Usage [#usage] ```sh coolify mcp disable ``` Get current help [#get-current-help] ```sh coolify mcp disable --help ``` The installed CLI help reflects the exact options available in your CLI version. # Enable (/docs/cli/command-reference/commands/mcp/enable) Enable [#enable] Enable the Coolify MCP server (API: POST /mcp/enable). Requires a root team API token. Usage [#usage] ```sh coolify mcp enable ``` Get current help [#get-current-help] ```sh coolify mcp enable --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/notification/get) Get [#get] Channels: email, discord, slack, telegram, pushover, webhook Usage [#usage] ```sh coolify notification get ``` Get current help [#get-current-help] ```sh coolify notification get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/notification/update) Update [#update] Pass settings as JSON via --json. Example: coolify notification update webhook --json '\{"webhook\_enabled":true}' Usage [#usage] ```sh coolify notification update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :------------------------------ | | `--json` | `string` | No | — | JSON object of fields to update | Get current help [#get-current-help] ```sh coolify notification update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Add (/docs/cli/command-reference/commands/private-key/add) Add [#add] Add a private key Usage [#usage] ```sh coolify private-key add ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :---------------------- | | `--description` | `string` | No | — | Private key description | Get current help [#get-current-help] ```sh coolify private-key add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/private-key/get) Get [#get] Get a private key by UUID Usage [#usage] ```sh coolify private-key get ``` Get current help [#get-current-help] ```sh coolify private-key get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/private-key/list) List [#list] List all private keys Usage [#usage] ```sh coolify private-key list ``` Get current help [#get-current-help] ```sh coolify private-key list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Remove (/docs/cli/command-reference/commands/private-key/remove) Remove [#remove] Remove a private key Usage [#usage] ```sh coolify private-key remove ``` Get current help [#get-current-help] ```sh coolify private-key remove --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/private-key/update) Update [#update] Update a private key Usage [#usage] ```sh coolify private-key update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :------------------------------------------------- | | `--description` | `string` | No | — | Private key description | | `--name` | `string` | No | — | Private key name | | `--private-key` | `string` | Yes | — | Private key content or path to key file (required) | Get current help [#get-current-help] ```sh coolify private-key update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/project/create) Create [#create] Create a new project Usage [#usage] ```sh coolify project create ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :---------------------- | | `--description` | `string` | No | — | Project description | | `--name` | `string` | Yes | — | Project name (required) | Get current help [#get-current-help] ```sh coolify project create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/project/delete) Delete [#delete] Delete a project Usage [#usage] ```sh coolify project delete ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify project delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environments create (/docs/cli/command-reference/commands/project/environments-create) Environments create [#environments-create] Create an environment in a project Usage [#usage] ```sh coolify project environments create ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :-------------------------- | | `--name` | `string` | Yes | — | Environment name (required) | Get current help [#get-current-help] ```sh coolify project environments create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environments delete (/docs/cli/command-reference/commands/project/environments-delete) Environments delete [#environments-delete] Delete a project environment Usage [#usage] ```sh coolify project environments delete ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify project environments delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environments list (/docs/cli/command-reference/commands/project/environments-list) Environments list [#environments-list] List environments in a project Usage [#usage] ```sh coolify project environments list ``` Get current help [#get-current-help] ```sh coolify project environments list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environments update (/docs/cli/command-reference/commands/project/environments-update) Environments update [#environments-update] Update a project environment Usage [#usage] ```sh coolify project environments update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :---------------------- | | `--description` | `string` | No | — | Environment description | | `--name` | `string` | No | — | Environment name | Get current help [#get-current-help] ```sh coolify project environments update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/project/get) Get [#get] Get a project by uuid Usage [#usage] ```sh coolify project get ``` Get current help [#get-current-help] ```sh coolify project get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/project/list) List [#list] List all projects Usage [#usage] ```sh coolify project list ``` Get current help [#get-current-help] ```sh coolify project list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update environment (/docs/cli/command-reference/commands/project/update-environment) Update environment [#update-environment] Update a project environment. Prefer: coolify project environments update Usage [#usage] ```sh coolify project update-environment ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :---------------------- | | `--description` | `string` | No | — | Environment description | | `--name` | `string` | No | — | Environment name | Get current help [#get-current-help] ```sh coolify project update-environment --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/project/update) Update [#update] Update a project Usage [#usage] ```sh coolify project update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :------- | :------: | :------ | :------------------ | | `--description` | `string` | No | — | Project description | | `--name` | `string` | No | — | Project name | Get current help [#get-current-help] ```sh coolify project update --help ``` The installed CLI help reflects the exact options available in your CLI version. # List resources (/docs/cli/command-reference/commands/resources) List resources [#list-resources] List all resources Usage [#usage] ```sh coolify resource list ``` Get current help [#get-current-help] ```sh coolify resource list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/s3/create) Create [#create] Create an S3 storage Usage [#usage] ```sh coolify s3 create ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :-------- | :------: | :------ | :--------------------- | | `--bucket` | `string` | No | — | Bucket name | | `--description` | `string` | No | — | Description | | `--endpoint` | `string` | No | — | S3 endpoint URL | | `--key` | `string` | No | — | Access key | | `--name` | `string` | No | — | Storage name | | `--region` | `string` | No | — | Region | | `--secret` | `string` | No | — | Secret key | | `--usable` | `boolean` | No | `true` | Mark storage as usable | Get current help [#get-current-help] ```sh coolify s3 create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/s3/delete) Delete [#delete] Delete an S3 storage Usage [#usage] ```sh coolify s3 delete ``` Get current help [#get-current-help] ```sh coolify s3 delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/s3/get) Get [#get] Get an S3 storage Usage [#usage] ```sh coolify s3 get ``` Get current help [#get-current-help] ```sh coolify s3 get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/s3/list) List [#list] List S3 storages Usage [#usage] ```sh coolify s3 list ``` Get current help [#get-current-help] ```sh coolify s3 list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/s3/update) Update [#update] Update an S3 storage Usage [#usage] ```sh coolify s3 update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :-------- | :------: | :------ | :--------------------- | | `--bucket` | `string` | No | — | Bucket name | | `--description` | `string` | No | — | Description | | `--endpoint` | `string` | No | — | S3 endpoint URL | | `--key` | `string` | No | — | Access key | | `--name` | `string` | No | — | Storage name | | `--region` | `string` | No | — | Region | | `--secret` | `string` | No | — | Secret key | | `--usable` | `boolean` | No | `true` | Mark storage as usable | Get current help [#get-current-help] ```sh coolify s3 update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Validate (/docs/cli/command-reference/commands/s3/validate) Validate [#validate] Validate S3 connection Usage [#usage] ```sh coolify s3 validate ``` Get current help [#get-current-help] ```sh coolify s3 validate --help ``` The installed CLI help reflects the exact options available in your CLI version. # Add (/docs/cli/command-reference/commands/server/add) Add [#add] Add a server Usage [#usage] ```sh coolify server add ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :-------- | :------: | :------ | :--------------------------------------------------------------------------------------- | | `--port (-p)` | `integer` | No | `22` | Port | | `--server-role` | `string` | No | — | Server role (deployment\|build\|both): 'deployment' requires another usable build server | | `--user (-u)` | `string` | No | `root` | User | | `--validate` | `boolean` | No | `false` | Validate the server | Get current help [#get-current-help] ```sh coolify server add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Cloudflare tunnel disable (/docs/cli/command-reference/commands/server/cloudflare-tunnel-disable) Cloudflare tunnel disable [#cloudflare-tunnel-disable] Disable Cloudflare tunnel flag Usage [#usage] ```sh coolify server cloudflare-tunnel disable ``` Get current help [#get-current-help] ```sh coolify server cloudflare-tunnel disable --help ``` The installed CLI help reflects the exact options available in your CLI version. # Cloudflare tunnel enable (/docs/cli/command-reference/commands/server/cloudflare-tunnel-enable) Cloudflare tunnel enable [#cloudflare-tunnel-enable] Enable Cloudflare tunnel flag Usage [#usage] ```sh coolify server cloudflare-tunnel enable ``` Get current help [#get-current-help] ```sh coolify server cloudflare-tunnel enable --help ``` The installed CLI help reflects the exact options available in your CLI version. # Cloudflare tunnel get (/docs/cli/command-reference/commands/server/cloudflare-tunnel-get) Cloudflare tunnel get [#cloudflare-tunnel-get] Get Cloudflare tunnel state Usage [#usage] ```sh coolify server cloudflare-tunnel get ``` Get current help [#get-current-help] ```sh coolify server cloudflare-tunnel get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Cloudflare tunnel update (/docs/cli/command-reference/commands/server/cloudflare-tunnel-update) Cloudflare tunnel update [#cloudflare-tunnel-update] Set Cloudflare tunnel enabled state Usage [#usage] ```sh coolify server cloudflare-tunnel update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------- | :-------- | :------: | :------ | :------------------------------------------------- | | `--enabled` | `boolean` | Yes | `false` | Enable (true) or disable (false) Cloudflare tunnel | Get current help [#get-current-help] ```sh coolify server cloudflare-tunnel update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Destinations create (/docs/cli/command-reference/commands/server/destinations-create) Destinations create [#destinations-create] Create a server destination Usage [#usage] ```sh coolify server destinations create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------- | :------- | :------: | :------ | :------------------------------------ | | `--name` | `string` | No | — | Destination name | | `--network` | `string` | Yes | — | Docker network name (required) | | `--type` | `string` | No | — | Destination type: standalone or swarm | Get current help [#get-current-help] ```sh coolify server destinations create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Destinations list (/docs/cli/command-reference/commands/server/destinations-list) Destinations list [#destinations-list] List server destinations Usage [#usage] ```sh coolify server destinations list ``` Get current help [#get-current-help] ```sh coolify server destinations list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Digitalocean create (/docs/cli/command-reference/commands/server/digitalocean-create) Digitalocean create [#digitalocean-create] Create a DigitalOcean server Usage [#usage] ```sh coolify server digitalocean create ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------- | :--------- | :------: | :------ | :---------------------------------- | | `--cloud-init` | `string` | No | — | Cloud-init YAML | | `--cloud-token` | `string` | No | — | Cloud provider token UUID | | `--enable-ipv6` | `boolean` | No | `true` | Enable public IPv6 | | `--image` | `string` | No | — | DigitalOcean image ID or slug | | `--monitoring` | `boolean` | No | `true` | Enable DigitalOcean monitoring | | `--name` | `string` | No | — | Server name | | `--private-key` | `string` | No | — | Coolify private key UUID | | `--region` | `string` | No | — | DigitalOcean region | | `--size` | `string` | No | — | DigitalOcean size | | `--ssh-key-ids` | `intSlice` | No | — | Additional DigitalOcean SSH key IDs | | `--validate` | `boolean` | No | `false` | Validate after creation | Get current help [#get-current-help] ```sh coolify server digitalocean create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Digitalocean images (/docs/cli/command-reference/commands/server/digitalocean-images) Digitalocean images [#digitalocean-images] List DigitalOcean images Usage [#usage] ```sh coolify server digitalocean images ``` Get current help [#get-current-help] ```sh coolify server digitalocean images --help ``` The installed CLI help reflects the exact options available in your CLI version. # Digitalocean regions (/docs/cli/command-reference/commands/server/digitalocean-regions) Digitalocean regions [#digitalocean-regions] List DigitalOcean regions Usage [#usage] ```sh coolify server digitalocean regions ``` Get current help [#get-current-help] ```sh coolify server digitalocean regions --help ``` The installed CLI help reflects the exact options available in your CLI version. # Digitalocean sizes (/docs/cli/command-reference/commands/server/digitalocean-sizes) Digitalocean sizes [#digitalocean-sizes] List DigitalOcean sizes Usage [#usage] ```sh coolify server digitalocean sizes ``` Get current help [#get-current-help] ```sh coolify server digitalocean sizes --help ``` The installed CLI help reflects the exact options available in your CLI version. # Digitalocean ssh keys (/docs/cli/command-reference/commands/server/digitalocean-ssh-keys) Digitalocean ssh keys [#digitalocean-ssh-keys] List DigitalOcean SSH keys Usage [#usage] ```sh coolify server digitalocean ssh-keys ``` Get current help [#get-current-help] ```sh coolify server digitalocean ssh-keys --help ``` The installed CLI help reflects the exact options available in your CLI version. # Docker cleanup executions (/docs/cli/command-reference/commands/server/docker-cleanup-executions) Docker cleanup executions [#docker-cleanup-executions] List docker cleanup executions Usage [#usage] ```sh coolify server docker-cleanup executions ``` Get current help [#get-current-help] ```sh coolify server docker-cleanup executions --help ``` The installed CLI help reflects the exact options available in your CLI version. # Docker cleanup get (/docs/cli/command-reference/commands/server/docker-cleanup-get) Docker cleanup get [#docker-cleanup-get] Get docker cleanup settings Usage [#usage] ```sh coolify server docker-cleanup get ``` Get current help [#get-current-help] ```sh coolify server docker-cleanup get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Docker cleanup run (/docs/cli/command-reference/commands/server/docker-cleanup-run) Docker cleanup run [#docker-cleanup-run] Run docker cleanup now Usage [#usage] ```sh coolify server docker-cleanup run ``` Get current help [#get-current-help] ```sh coolify server docker-cleanup run --help ``` The installed CLI help reflects the exact options available in your CLI version. # Docker cleanup update (/docs/cli/command-reference/commands/server/docker-cleanup-update) Docker cleanup update [#docker-cleanup-update] Update docker cleanup settings Usage [#usage] ```sh coolify server docker-cleanup update ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------------------- | :-------- | :------: | :------ | :---------------------------------- | | `--delete-unused-networks` | `boolean` | No | `false` | Delete unused networks | | `--delete-unused-volumes` | `boolean` | No | `false` | Delete unused volumes | | `--disable-image-retention` | `boolean` | No | `false` | Disable application image retention | | `--force` | `boolean` | No | `false` | Force cleanup | | `--frequency` | `string` | No | — | Cron frequency | | `--threshold` | `integer` | No | `0` | Disk usage threshold percent | Get current help [#get-current-help] ```sh coolify server docker-cleanup update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Domains (/docs/cli/command-reference/commands/server/domains) Domains [#domains] Get server domains by uuid Usage [#usage] ```sh coolify server domains ``` Get current help [#get-current-help] ```sh coolify server domains --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/server/get) Get [#get] Get server details by uuid Usage [#usage] ```sh coolify server get ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :------------- | | `--resources` | `boolean` | No | `false` | With resources | Get current help [#get-current-help] ```sh coolify server get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner create (/docs/cli/command-reference/commands/server/hetzner-create) Hetzner create [#hetzner-create] Create a Hetzner server Usage [#usage] ```sh coolify server hetzner create ``` Options [#options] | Option | Type | Required | Default | Description | | :----------------- | :--------- | :------: | :------ | :-------------------------------------- | | `--cloud-init` | `string` | No | — | Cloud-init YAML | | `--cloud-token` | `string` | No | — | Cloud provider token UUID | | `--enable-backups` | `boolean` | No | `false` | Enable Hetzner backups | | `--enable-ipv4` | `boolean` | No | `true` | Enable public IPv4 | | `--enable-ipv6` | `boolean` | No | `true` | Enable public IPv6 | | `--firewall-ids` | `intSlice` | No | — | Hetzner firewall IDs | | `--image` | `integer` | No | `0` | Hetzner image ID | | `--location` | `string` | No | — | Hetzner location name | | `--name` | `string` | No | — | Server name (auto-generated if omitted) | | `--network-ids` | `intSlice` | No | — | Hetzner network IDs | | `--private-key` | `string` | No | — | Coolify private key UUID | | `--server-type` | `string` | No | — | Hetzner server type | | `--ssh-key-ids` | `intSlice` | No | — | Additional Hetzner SSH key IDs | | `--validate` | `boolean` | No | `false` | Validate after creation | Get current help [#get-current-help] ```sh coolify server hetzner create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner firewalls (/docs/cli/command-reference/commands/server/hetzner-firewalls) Hetzner firewalls [#hetzner-firewalls] List Hetzner firewalls Usage [#usage] ```sh coolify server hetzner firewalls ``` Get current help [#get-current-help] ```sh coolify server hetzner firewalls --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner images (/docs/cli/command-reference/commands/server/hetzner-images) Hetzner images [#hetzner-images] List Hetzner images Usage [#usage] ```sh coolify server hetzner images ``` Get current help [#get-current-help] ```sh coolify server hetzner images --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner locations (/docs/cli/command-reference/commands/server/hetzner-locations) Hetzner locations [#hetzner-locations] List Hetzner locations Usage [#usage] ```sh coolify server hetzner locations ``` Get current help [#get-current-help] ```sh coolify server hetzner locations --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner networks (/docs/cli/command-reference/commands/server/hetzner-networks) Hetzner networks [#hetzner-networks] List Hetzner networks Usage [#usage] ```sh coolify server hetzner networks ``` Get current help [#get-current-help] ```sh coolify server hetzner networks --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner server types (/docs/cli/command-reference/commands/server/hetzner-server-types) Hetzner server types [#hetzner-server-types] List Hetzner server types Usage [#usage] ```sh coolify server hetzner server-types ``` Get current help [#get-current-help] ```sh coolify server hetzner server-types --help ``` The installed CLI help reflects the exact options available in your CLI version. # Hetzner ssh keys (/docs/cli/command-reference/commands/server/hetzner-ssh-keys) Hetzner ssh keys [#hetzner-ssh-keys] List Hetzner SSH keys Usage [#usage] ```sh coolify server hetzner ssh-keys ``` Get current help [#get-current-help] ```sh coolify server hetzner ssh-keys --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/server/list) List [#list] List all servers Usage [#usage] ```sh coolify server list ``` Get current help [#get-current-help] ```sh coolify server list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Log drains get (/docs/cli/command-reference/commands/server/log-drains-get) Log drains get [#log-drains-get] Get log drain settings Usage [#usage] ```sh coolify server log-drains get ``` Get current help [#get-current-help] ```sh coolify server log-drains get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Log drains update (/docs/cli/command-reference/commands/server/log-drains-update) Log drains update [#log-drains-update] Update log drain settings via JSON Usage [#usage] ```sh coolify server log-drains update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :------------------- | | `--json` | `string` | No | — | JSON fields to patch | Get current help [#get-current-help] ```sh coolify server log-drains update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Proxy get (/docs/cli/command-reference/commands/server/proxy-get) Proxy get [#proxy-get] Get proxy settings Usage [#usage] ```sh coolify server proxy get ``` Get current help [#get-current-help] ```sh coolify server proxy get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Proxy restart (/docs/cli/command-reference/commands/server/proxy-restart) Proxy restart [#proxy-restart] Restart proxy Usage [#usage] ```sh coolify server proxy restart ``` Get current help [#get-current-help] ```sh coolify server proxy restart --help ``` The installed CLI help reflects the exact options available in your CLI version. # Proxy set config (/docs/cli/command-reference/commands/server/proxy-set-config) Proxy set config [#proxy-set-config] Save raw proxy configuration Usage [#usage] ```sh coolify server proxy set-config ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------------- | :------- | :------: | :------ | :--------------------------- | | `--configuration` | `string` | No | — | Raw proxy configuration | | `--configuration-file` | `string` | No | — | Read configuration from file | Get current help [#get-current-help] ```sh coolify server proxy set-config --help ``` The installed CLI help reflects the exact options available in your CLI version. # Proxy update (/docs/cli/command-reference/commands/server/proxy-update) Proxy update [#proxy-update] Update proxy settings Usage [#usage] ```sh coolify server proxy update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------------ | :-------- | :------: | :------ | :------------------------ | | `--generate-exact-labels` | `boolean` | No | `false` | Generate exact labels | | `--proxy-type` | `string` | No | — | Proxy type (e.g. TRAEFIK) | | `--redirect-enabled` | `boolean` | No | `true` | Enable proxy redirect | | `--redirect-url` | `string` | No | — | Redirect URL | Get current help [#get-current-help] ```sh coolify server proxy update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Registry check (/docs/cli/command-reference/commands/server/registry-check) Registry check [#registry-check] Check that the saved registry login of a server still works Usage [#usage] ```sh coolify server registry check ``` Get current help [#get-current-help] ```sh coolify server registry check --help ``` The installed CLI help reflects the exact options available in your CLI version. # Registry list (/docs/cli/command-reference/commands/server/registry-list) Registry list [#registry-list] List registry logins of a server Usage [#usage] ```sh coolify server registry list ``` Get current help [#get-current-help] ```sh coolify server registry list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Registry login (/docs/cli/command-reference/commands/server/registry-login) Registry login [#registry-login] Log in to a Docker registry on one or more servers Usage [#usage] ```sh coolify server registry login [...] ``` Options [#options] | Option | Type | Required | Default | Description | | :----------------- | :-------- | :------: | :------ | :------------------------------------------------------------------------------------------------------------------- | | `--password-stdin` | `boolean` | No | `false` | Read the password or access token from stdin | | `--registry` | `string` | Yes | — | Registry host, optionally with a port (e.g. ghcr.io, registry.example.com:5000, docker.io for Docker Hub) (required) | | `--username (-u)` | `string` | Yes | — | Registry username (required) | Get current help [#get-current-help] ```sh coolify server registry login --help ``` The installed CLI help reflects the exact options available in your CLI version. # Registry logout (/docs/cli/command-reference/commands/server/registry-logout) Registry logout [#registry-logout] Log out from a Docker registry on a server Usage [#usage] ```sh coolify server registry logout ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :----------------------- | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify server registry logout --help ``` The installed CLI help reflects the exact options available in your CLI version. # Remove (/docs/cli/command-reference/commands/server/remove) Remove [#remove] Remove a server Usage [#usage] ```sh coolify server remove ``` Options [#options] | Option | Type | Required | Default | Description | | :----------------------- | :-------- | :------: | :------ | :----------------------------------------------------------------------------------------------------- | | `--delete-from-provider` | `boolean` | No | `false` | Also delete the server from its cloud provider (Hetzner, Vultr or DigitalOcean). This cannot be undone | | `--force` | `boolean` | No | `false` | Also delete all resources on the server | Get current help [#get-current-help] ```sh coolify server remove --help ``` The installed CLI help reflects the exact options available in your CLI version. # Sentinel get (/docs/cli/command-reference/commands/server/sentinel-get) Sentinel get [#sentinel-get] Get Sentinel settings Usage [#usage] ```sh coolify server sentinel get ``` Get current help [#get-current-help] ```sh coolify server sentinel get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Sentinel update (/docs/cli/command-reference/commands/server/sentinel-update) Sentinel update [#sentinel-update] Update Sentinel settings via JSON Usage [#usage] ```sh coolify server sentinel update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :------------------- | | `--json` | `string` | No | — | JSON fields to patch | Get current help [#get-current-help] ```sh coolify server sentinel update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/server/update) Update [#update] Update a server Usage [#usage] ```sh coolify server update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------------------------ | :-------- | :------: | :------ | :--------------------------------------------------------------------------------------- | | `--concurrent-builds` | `integer` | No | `0` | Max concurrent builds | | `--connection-timeout` | `integer` | No | `0` | SSH connection timeout in seconds | | `--deployment-queue-limit` | `integer` | No | `0` | Deployment queue limit | | `--description` | `string` | No | — | Server description | | `--disk-usage-check-frequency` | `string` | No | — | Disk usage check frequency (cron) | | `--disk-usage-notification-threshold` | `integer` | No | `0` | Disk usage notification threshold percent | | `--dynamic-timeout` | `integer` | No | `0` | Dynamic timeout | | `--instant-validate` | `boolean` | No | `false` | Validate server after update | | `--ip` | `string` | No | — | Server IP address | | `--is-build-server` | `boolean` | No | `false` | Deprecated: use --server-role build (true) or --server-role both (false) | | `--is-terminal-enabled` | `boolean` | No | `false` | Enable terminal access | | `--name` | `string` | No | — | Server name | | `--port` | `integer` | No | `22` | SSH port | | `--private-key-uuid` | `string` | No | — | Private key UUID | | `--proxy-type` | `string` | No | — | Proxy type (e.g. TRAEFIK, CADDY, NGINX) | | `--server-role` | `string` | No | — | Server role (deployment\|build\|both): 'deployment' requires another usable build server | | `--user` | `string` | No | — | SSH user | Get current help [#get-current-help] ```sh coolify server update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Validate (/docs/cli/command-reference/commands/server/validate) Validate [#validate] Validate a server Usage [#usage] ```sh coolify server validate ``` Options [#options] | Option | Type | Required | Default | Description | | :---------- | :-------- | :------: | :------ | :------------------------------------------------------------ | | `--install` | `boolean` | No | `false` | Install missing prerequisites and Docker (may restart Docker) | Get current help [#get-current-help] ```sh coolify server validate --help ``` The installed CLI help reflects the exact options available in your CLI version. # Vultr create (/docs/cli/command-reference/commands/server/vultr-create) Vultr create [#vultr-create] Create a Vultr server Usage [#usage] ```sh coolify server vultr create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------- | :------------ | :------: | :------ | :--------------------------- | | `--cloud-init` | `string` | No | — | Cloud-init YAML | | `--cloud-token` | `string` | No | — | Cloud provider token UUID | | `--disable-public-ipv4` | `boolean` | No | `false` | Disable public IPv4 | | `--enable-ipv6` | `boolean` | No | `true` | Enable public IPv6 | | `--name` | `string` | No | — | Server name | | `--os-id` | `integer` | No | `0` | Vultr operating system ID | | `--plan` | `string` | No | — | Vultr plan | | `--private-key` | `string` | No | — | Coolify private key UUID | | `--region` | `string` | No | — | Vultr region | | `--ssh-key-ids` | `stringSlice` | No | — | Additional Vultr SSH key IDs | | `--validate` | `boolean` | No | `false` | Validate after creation | Get current help [#get-current-help] ```sh coolify server vultr create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Vultr os (/docs/cli/command-reference/commands/server/vultr-os) Vultr os [#vultr-os] List Vultr operating systems Usage [#usage] ```sh coolify server vultr os ``` Get current help [#get-current-help] ```sh coolify server vultr os --help ``` The installed CLI help reflects the exact options available in your CLI version. # Vultr plans (/docs/cli/command-reference/commands/server/vultr-plans) Vultr plans [#vultr-plans] List Vultr plans Usage [#usage] ```sh coolify server vultr plans ``` Get current help [#get-current-help] ```sh coolify server vultr plans --help ``` The installed CLI help reflects the exact options available in your CLI version. # Vultr regions (/docs/cli/command-reference/commands/server/vultr-regions) Vultr regions [#vultr-regions] List Vultr regions Usage [#usage] ```sh coolify server vultr regions ``` Get current help [#get-current-help] ```sh coolify server vultr regions --help ``` The installed CLI help reflects the exact options available in your CLI version. # Vultr ssh keys (/docs/cli/command-reference/commands/server/vultr-ssh-keys) Vultr ssh keys [#vultr-ssh-keys] List Vultr SSH keys Usage [#usage] ```sh coolify server vultr ssh-keys ``` Get current help [#get-current-help] ```sh coolify server vultr ssh-keys --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application get (/docs/cli/command-reference/commands/service/application-get) Application get [#application-get] Get an application in a service Usage [#usage] ```sh coolify service application get ``` Get current help [#get-current-help] ```sh coolify service application get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application list (/docs/cli/command-reference/commands/service/application-list) Application list [#application-list] List applications in a service Usage [#usage] ```sh coolify service application list ``` Get current help [#get-current-help] ```sh coolify service application list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application logs (/docs/cli/command-reference/commands/service/application-logs) Application logs [#application-logs] Get logs for an application in a service Usage [#usage] ```sh coolify service application logs ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :------------------------------ | | `--lines (-n)` | `integer` | No | `100` | Number of log lines to retrieve | Get current help [#get-current-help] ```sh coolify service application logs --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application restart (/docs/cli/command-reference/commands/service/application-restart) Application restart [#application-restart] Restart an application in a service Usage [#usage] ```sh coolify service application restart ``` Get current help [#get-current-help] ```sh coolify service application restart --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application start (/docs/cli/command-reference/commands/service/application-start) Application start [#application-start] Start or redeploy an application in a service Usage [#usage] ```sh coolify service application start ``` Options [#options] | Option | Type | Required | Default | Description | | :--------- | :-------- | :------: | :------ | :---------------------- | | `--force` | `boolean` | No | `false` | Rebuild the application | | `--latest` | `boolean` | No | `false` | Pull the latest image | Get current help [#get-current-help] ```sh coolify service application start --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application stop (/docs/cli/command-reference/commands/service/application-stop) Application stop [#application-stop] Stop an application in a service Usage [#usage] ```sh coolify service application stop ``` Get current help [#get-current-help] ```sh coolify service application stop --help ``` The installed CLI help reflects the exact options available in your CLI version. # Application update (/docs/cli/command-reference/commands/service/application-update) Application update [#application-update] Update an application in a service Usage [#usage] ```sh coolify service application update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------------ | :-------- | :------: | :------ | :------------------------------------- | | `--description` | `string` | No | — | Description | | `--exclude-from-status` | `boolean` | No | `false` | Exclude from service status | | `--force-domain-override` | `boolean` | No | `false` | Allow conflicting or duplicate domains | | `--gzip-enabled` | `boolean` | No | `false` | Enable gzip compression | | `--human-name` | `string` | No | — | Human-readable name | | `--image` | `string` | No | — | Container image | | `--log-drain-enabled` | `boolean` | No | `false` | Enable log drain | | `--stripprefix-enabled` | `boolean` | No | `false` | Enable path prefix stripping | | `--url` | `string` | No | — | Comma-separated public URLs | Get current help [#get-current-help] ```sh coolify service application update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Clone (/docs/cli/command-reference/commands/service/clone) Clone [#clone] Clone a service to a destination Usage [#usage] ```sh coolify service clone ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :---------------- | | `--clone-volumes` | `boolean` | No | `false` | Clone volume data | | `--destination` | `string` | No | — | Destination UUID | | `--name` | `string` | No | — | Optional new name | Get current help [#get-current-help] ```sh coolify service clone --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/service/create) Create [#create] Create a new one-click service Usage [#usage] ```sh coolify service create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :------------ | :------: | :------ | :--------------------------------------------------------- | | `--description` | `string` | No | — | Service description | | `--destination-uuid` | `string` | No | — | Destination UUID if server has multiple destinations | | `--docker-compose` | `string` | No | — | Custom Docker Compose content (for advanced customization) | | `--environment-name` | `string` | No | — | Environment name | | `--environment-uuid` | `string` | No | — | Environment UUID | | `--instant-deploy` | `boolean` | No | `false` | Deploy immediately after creation | | `--list-types` | `boolean` | No | `false` | List all available service types | | `--name` | `string` | No | — | Service name | | `--project-uuid` | `string` | Yes | — | Project UUID (required) | | `--server-uuid` | `string` | Yes | — | Server UUID (required) | | `--tag` | `stringArray` | No | — | Tag to assign (repeatable) | | `--tags` | `stringSlice` | No | — | Comma-separated tags to assign | Get current help [#get-current-help] ```sh coolify service create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database get (/docs/cli/command-reference/commands/service/database-get) Database get [#database-get] Get a database in a service Usage [#usage] ```sh coolify service database get ``` Get current help [#get-current-help] ```sh coolify service database get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database list (/docs/cli/command-reference/commands/service/database-list) Database list [#database-list] List databases in a service Usage [#usage] ```sh coolify service database list ``` Get current help [#get-current-help] ```sh coolify service database list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database logs (/docs/cli/command-reference/commands/service/database-logs) Database logs [#database-logs] Get logs for a database in a service Usage [#usage] ```sh coolify service database logs ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :------------------------------ | | `--lines (-n)` | `integer` | No | `100` | Number of log lines to retrieve | Get current help [#get-current-help] ```sh coolify service database logs --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database restart (/docs/cli/command-reference/commands/service/database-restart) Database restart [#database-restart] Restart a database in a service Usage [#usage] ```sh coolify service database restart ``` Get current help [#get-current-help] ```sh coolify service database restart --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database start (/docs/cli/command-reference/commands/service/database-start) Database start [#database-start] Start or redeploy a database in a service Usage [#usage] ```sh coolify service database start ``` Options [#options] | Option | Type | Required | Default | Description | | :--------- | :-------- | :------: | :------ | :----------------------------- | | `--force` | `boolean` | No | `false` | Rebuild the database container | | `--latest` | `boolean` | No | `false` | Pull the latest image | Get current help [#get-current-help] ```sh coolify service database start --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database stop (/docs/cli/command-reference/commands/service/database-stop) Database stop [#database-stop] Stop a database in a service Usage [#usage] ```sh coolify service database stop ``` Get current help [#get-current-help] ```sh coolify service database stop --help ``` The installed CLI help reflects the exact options available in your CLI version. # Database update (/docs/cli/command-reference/commands/service/database-update) Database update [#database-update] Update a database in a service Usage [#usage] ```sh coolify service database update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------- | :-------- | :------: | :------ | :------------------------------ | | `--description` | `string` | No | — | Description | | `--exclude-from-status` | `boolean` | No | `false` | Exclude from service status | | `--human-name` | `string` | No | — | Human-readable name | | `--image` | `string` | No | — | Container image | | `--log-drain-enabled` | `boolean` | No | `false` | Enable log drain | | `--public` | `boolean` | No | `false` | Expose the database publicly | | `--public-port` | `integer` | No | `0` | Public database port | | `--public-port-timeout` | `integer` | No | `0` | Public proxy timeout in seconds | Get current help [#get-current-help] ```sh coolify service database update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/service/delete) Delete [#delete] Delete a service and optionally clean up its configurations, volumes, and networks. Usage [#usage] ```sh coolify service delete ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------------- | :-------- | :------: | :------ | :------------------------ | | `--delete-configurations` | `boolean` | No | `true` | Delete configurations | | `--delete-connected-networks` | `boolean` | No | `true` | Delete connected networks | | `--delete-volumes` | `boolean` | No | `true` | Delete volumes | | `--docker-cleanup` | `boolean` | No | `true` | Run docker cleanup | | `--force (-f)` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify service delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env create (/docs/cli/command-reference/commands/service/env-create) Env create [#env-create] Create a new environment variable for a specific service. Use --key and --value flags to specify the variable. Usage [#usage] ```sh coolify service env create ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :--------------------------------------------------- | | `--build-time` | `boolean` | No | `true` | Available at build time (default: true) | | `--comment` | `string` | No | — | Comment for the environment variable | | `--is-literal` | `boolean` | No | `false` | Treat value as literal (don't interpolate variables) | | `--is-multiline` | `boolean` | No | `false` | Value is multiline | | `--key` | `string` | Yes | — | Environment variable key (required) | | `--runtime` | `boolean` | No | `true` | Available at runtime (default: true) | | `--value` | `string` | Yes | — | Environment variable value (required) | Get current help [#get-current-help] ```sh coolify service env create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env delete (/docs/cli/command-reference/commands/service/env-delete) Env delete [#env-delete] Delete an environment variable from a service. First UUID is the service, second is the specific environment variable to delete. Usage [#usage] ```sh coolify service env delete ``` Options [#options] | Option | Type | Required | Default | Description | | :-------- | :-------- | :------: | :------ | :----------------------- | | `--force` | `boolean` | No | `false` | Skip confirmation prompt | Get current help [#get-current-help] ```sh coolify service env delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env get (/docs/cli/command-reference/commands/service/env-get) Env get [#env-get] Get detailed information about a specific environment variable. First UUID is the service, second is the environment variable UUID or key name. Usage [#usage] ```sh coolify service env get ``` Get current help [#get-current-help] ```sh coolify service env get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env list (/docs/cli/command-reference/commands/service/env-list) Env list [#env-list] List all environment variables for a specific service. Usage [#usage] ```sh coolify service env list ``` Get current help [#get-current-help] ```sh coolify service env list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env sync (/docs/cli/command-reference/commands/service/env-sync) Env sync [#env-sync] Sync environment variables from a .env file Usage [#usage] ```sh coolify service env sync ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------------------------------------------- | | `--build-time` | `boolean` | No | `true` | Make all variables available at build time (default: true) | | `--file (-f)` | `string` | Yes | — | Path to .env file (required) | | `--is-literal` | `boolean` | No | `false` | Treat all values as literal (don't interpolate variables) | | `--runtime` | `boolean` | No | `true` | Make all variables available at runtime (default: true) | Get current help [#get-current-help] ```sh coolify service env sync --help ``` The installed CLI help reflects the exact options available in your CLI version. # Env update (/docs/cli/command-reference/commands/service/env-update) Env update [#env-update] Update an existing environment variable. Identify it by UUID or key name. Usage [#usage] ```sh coolify service env update ``` Options [#options] | Option | Type | Required | Default | Description | | :--------------- | :-------- | :------: | :------ | :--------------------------------------------------- | | `--build-time` | `boolean` | No | `true` | Available at build time (default: true) | | `--comment` | `string` | No | — | Comment for the environment variable | | `--is-literal` | `boolean` | No | `false` | Treat value as literal (don't interpolate variables) | | `--is-multiline` | `boolean` | No | `false` | Value is multiline | | `--key` | `string` | No | — | New environment variable key (rename) | | `--runtime` | `boolean` | No | `true` | Available at runtime (default: true) | | `--value` | `string` | Yes | — | New environment variable value (required) | Get current help [#get-current-help] ```sh coolify service env update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Execute task (/docs/cli/command-reference/commands/service/execute-task) Execute task [#execute-task] Execute a service scheduled task now Usage [#usage] ```sh coolify service execute-task ``` Get current help [#get-current-help] ```sh coolify service execute-task --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/service/get) Get [#get] Get detailed information about a specific service. Usage [#usage] ```sh coolify service get ``` Get current help [#get-current-help] ```sh coolify service get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/service/list) List [#list] List all services in Coolify. Usage [#usage] ```sh coolify service list ``` Get current help [#get-current-help] ```sh coolify service list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Logs (/docs/cli/command-reference/commands/service/logs) Logs [#logs] Get logs for a service sub-resource Usage [#usage] ```sh coolify service logs ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :-------- | :------: | :------ | :-------------------------------------------------------------------------- | | `--lines (-n)` | `integer` | No | `100` | Number of log lines to retrieve | | `--show-timestamps` | `boolean` | No | `false` | Include timestamps in logs | | `--sub-service-name` | `string` | Yes | — | Sub-service name from the service applications or databases list (required) | Get current help [#get-current-help] ```sh coolify service logs --help ``` The installed CLI help reflects the exact options available in your CLI version. # Move (/docs/cli/command-reference/commands/service/move) Move [#move] Move a service to another environment Usage [#usage] ```sh coolify service move ``` Options [#options] | Option | Type | Required | Default | Description | | :------------------- | :------- | :------: | :------ | :--------------------------------- | | `--environment-uuid` | `string` | Yes | — | Target environment UUID (required) | Get current help [#get-current-help] ```sh coolify service move --help ``` The installed CLI help reflects the exact options available in your CLI version. # Restart (/docs/cli/command-reference/commands/service/restart) Restart [#restart] Restart a service (restart all containers). Usage [#usage] ```sh coolify service restart ``` Get current help [#get-current-help] ```sh coolify service restart --help ``` The installed CLI help reflects the exact options available in your CLI version. # Run storage backup (/docs/cli/command-reference/commands/service/run-storage-backup) Run storage backup [#run-storage-backup] Run a service volume backup schedule now Usage [#usage] ```sh coolify service run-storage-backup ``` Get current help [#get-current-help] ```sh coolify service run-storage-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Start (/docs/cli/command-reference/commands/service/start) Start [#start] Start a service (deploy all containers). Usage [#usage] ```sh coolify service start ``` Get current help [#get-current-help] ```sh coolify service start --help ``` The installed CLI help reflects the exact options available in your CLI version. # Stop (/docs/cli/command-reference/commands/service/stop) Stop [#stop] Stop a service (stop all containers). Usage [#usage] ```sh coolify service stop ``` Get current help [#get-current-help] ```sh coolify service stop --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage create (/docs/cli/command-reference/commands/service/storage-create) Storage create [#storage-create] Create a storage for a service Usage [#usage] ```sh coolify service storage create ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------- | :-------- | :------: | :------ | :------------------------------------------------------------------- | | `--content` | `string` | No | — | File content (file only) | | `--fs-path` | `string` | No | — | Host directory path (file only, required when --is-directory is set) | | `--host-path` | `string` | No | — | Host path (persistent only) | | `--is-directory` | `boolean` | No | `false` | Whether this is a directory mount (file only) | | `--mount-path` | `string` | Yes | — | Mount path inside the container (required) | | `--name` | `string` | No | — | Volume name (persistent only) | | `--resource-uuid` | `string` | Yes | — | UUID of the service sub-resource (required) | | `--type` | `string` | Yes | — | Storage type: 'persistent' or 'file' (required) | Get current help [#get-current-help] ```sh coolify service storage create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage delete backup (/docs/cli/command-reference/commands/service/storage-delete-backup) Storage delete backup [#storage-delete-backup] Delete service storage volume backup schedule Usage [#usage] ```sh coolify service storage delete-backup ``` Get current help [#get-current-help] ```sh coolify service storage delete-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage delete (/docs/cli/command-reference/commands/service/storage-delete) Storage delete [#storage-delete] Delete a storage from a service Usage [#usage] ```sh coolify service storage delete ``` Get current help [#get-current-help] ```sh coolify service storage delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage list (/docs/cli/command-reference/commands/service/storage-list) Storage list [#storage-list] List all persistent volumes and file storages for a specific service. Usage [#usage] ```sh coolify service storage list ``` Get current help [#get-current-help] ```sh coolify service storage list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage run backup (/docs/cli/command-reference/commands/service/storage-run-backup) Storage run backup [#storage-run-backup] Run service storage volume backup now Usage [#usage] ```sh coolify service storage run-backup ``` Get current help [#get-current-help] ```sh coolify service storage run-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage set backup (/docs/cli/command-reference/commands/service/storage-set-backup) Storage set backup [#storage-set-backup] Create or replace service storage volume backup schedule Usage [#usage] ```sh coolify service storage set-backup ``` Options [#options] | Option | Type | Required | Default | Description | | :-------------------------------- | :-------- | :------: | :------ | :------------------------------------ | | `--disable-local-backup` | `boolean` | No | `false` | Disable local backup retention | | `--enabled` | `boolean` | No | `true` | Enable the schedule | | `--frequency` | `string` | Yes | — | Cron frequency (required) | | `--retention-amount-locally` | `integer` | No | `7` | Local retention count | | `--retention-amount-s3` | `integer` | No | `7` | S3 retention count | | `--retention-days-locally` | `integer` | No | `0` | Local retention days | | `--retention-days-s3` | `integer` | No | `0` | S3 retention days | | `--retention-max-storage-locally` | `float64` | No | `0` | Local max storage | | `--retention-max-storage-s3` | `float64` | No | `0` | S3 max storage | | `--s3-storage-uuid` | `string` | No | — | S3 storage UUID when --save-s3 is set | | `--save-s3` | `boolean` | No | `false` | Also save backups to S3 | | `--stop-during-backup` | `boolean` | No | `false` | Stop resource during backup | | `--timeout` | `integer` | No | `3600` | Backup timeout seconds | Get current help [#get-current-help] ```sh coolify service storage set-backup --help ``` The installed CLI help reflects the exact options available in your CLI version. # Storage update (/docs/cli/command-reference/commands/service/storage-update) Storage update [#storage-update] Update a storage for a service Usage [#usage] ```sh coolify service storage update ``` Options [#options] | Option | Type | Required | Default | Description | | :---------------------------- | :-------- | :------: | :------ | :-------------------------------------------------- | | `--content` | `string` | No | — | File content (file only) | | `--host-path` | `string` | No | — | Host path (persistent only) | | `--id` | `integer` | No | `0` | Storage ID (deprecated, use --uuid instead) | | `--is-preview-suffix-enabled` | `boolean` | No | `false` | Enable preview suffix for this storage | | `--mount-path` | `string` | No | — | Mount path inside the container | | `--name` | `string` | No | — | Storage name (persistent only) | | `--type` | `string` | Yes | — | Storage type: 'persistent' or 'file' (required) | | `--uuid` | `string` | No | — | Storage UUID (required, use 'storage list' to find) | Get current help [#get-current-help] ```sh coolify service storage update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag add (/docs/cli/command-reference/commands/service/tag-add) Tag add [#tag-add] Add a service tag Usage [#usage] ```sh coolify service tag add ``` Get current help [#get-current-help] ```sh coolify service tag add --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag list (/docs/cli/command-reference/commands/service/tag-list) Tag list [#tag-list] List service tags Usage [#usage] ```sh coolify service tag list ``` Get current help [#get-current-help] ```sh coolify service tag list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Tag remove (/docs/cli/command-reference/commands/service/tag-remove) Tag remove [#tag-remove] Remove a service tag Usage [#usage] ```sh coolify service tag remove ``` Get current help [#get-current-help] ```sh coolify service tag remove --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task create (/docs/cli/command-reference/commands/service/task-create) Task create [#task-create] Create a scheduled task for a service Usage [#usage] ```sh coolify service task create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :-------------------------------------- | | `--command` | `string` | Yes | — | Command to run (required) | | `--container` | `string` | No | — | Container name to run the command in | | `--enabled` | `boolean` | No | `true` | Whether the task is enabled | | `--frequency` | `string` | Yes | — | Cron expression or frequency (required) | | `--name` | `string` | Yes | — | Task name (required) | | `--timeout` | `integer` | No | `300` | Timeout in seconds | Get current help [#get-current-help] ```sh coolify service task create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task delete (/docs/cli/command-reference/commands/service/task-delete) Task delete [#task-delete] Delete a service scheduled task Usage [#usage] ```sh coolify service task delete ``` Get current help [#get-current-help] ```sh coolify service task delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task execute (/docs/cli/command-reference/commands/service/task-execute) Task execute [#task-execute] Execute a service scheduled task now Usage [#usage] ```sh coolify service task execute ``` Get current help [#get-current-help] ```sh coolify service task execute --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task executions (/docs/cli/command-reference/commands/service/task-executions) Task executions [#task-executions] List executions for a service scheduled task Usage [#usage] ```sh coolify service task executions ``` Get current help [#get-current-help] ```sh coolify service task executions --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task list (/docs/cli/command-reference/commands/service/task-list) Task list [#task-list] List scheduled tasks for a service Usage [#usage] ```sh coolify service task list ``` Get current help [#get-current-help] ```sh coolify service task list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Task update (/docs/cli/command-reference/commands/service/task-update) Task update [#task-update] Update a service scheduled task Usage [#usage] ```sh coolify service task update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------ | :-------- | :------: | :------ | :----------------------------------- | | `--command` | `string` | No | — | Command to run | | `--container` | `string` | No | — | Container name to run the command in | | `--enabled` | `boolean` | No | `true` | Whether the task is enabled | | `--frequency` | `string` | No | — | Cron expression or frequency | | `--name` | `string` | No | — | Task name | | `--timeout` | `integer` | No | `300` | Timeout in seconds | Get current help [#get-current-help] ```sh coolify service task update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Email get (/docs/cli/command-reference/commands/settings/email-get) Email get [#email-get] Get instance email settings Usage [#usage] ```sh coolify settings email get ``` Get current help [#get-current-help] ```sh coolify settings email get --help ``` The installed CLI help reflects the exact options available in your CLI version. # Email update (/docs/cli/command-reference/commands/settings/email-update) Email update [#email-update] Pass settings as JSON via --json. Requires write:sensitive. Example: coolify settings email update --json '\{"smtp\_ehlo\_domain":"coolify.example.com"}' Usage [#usage] ```sh coolify settings email update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :------------------------------ | | `--json` | `string` | No | — | JSON object of fields to update | Get current help [#get-current-help] ```sh coolify settings email update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environment create (/docs/cli/command-reference/commands/shared-env/environment-create) Environment create [#environment-create] Create environment shared env Usage [#usage] ```sh coolify shared-env environment create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env environment create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environment delete (/docs/cli/command-reference/commands/shared-env/environment-delete) Environment delete [#environment-delete] Delete environment shared env Usage [#usage] ```sh coolify shared-env environment delete ``` Get current help [#get-current-help] ```sh coolify shared-env environment delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environment list (/docs/cli/command-reference/commands/shared-env/environment-list) Environment list [#environment-list] List environment shared envs Usage [#usage] ```sh coolify shared-env environment list ``` Get current help [#get-current-help] ```sh coolify shared-env environment list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Environment update (/docs/cli/command-reference/commands/shared-env/environment-update) Environment update [#environment-update] Update environment shared env Usage [#usage] ```sh coolify shared-env environment update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env environment update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Project create (/docs/cli/command-reference/commands/shared-env/project-create) Project create [#project-create] Create project shared env Usage [#usage] ```sh coolify shared-env project create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env project create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Project delete (/docs/cli/command-reference/commands/shared-env/project-delete) Project delete [#project-delete] Delete project shared env Usage [#usage] ```sh coolify shared-env project delete ``` Get current help [#get-current-help] ```sh coolify shared-env project delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Project list (/docs/cli/command-reference/commands/shared-env/project-list) Project list [#project-list] List project shared envs Usage [#usage] ```sh coolify shared-env project list ``` Get current help [#get-current-help] ```sh coolify shared-env project list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Project update (/docs/cli/command-reference/commands/shared-env/project-update) Project update [#project-update] Update project shared env Usage [#usage] ```sh coolify shared-env project update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env project update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Server create (/docs/cli/command-reference/commands/shared-env/server-create) Server create [#server-create] Create server shared env Usage [#usage] ```sh coolify shared-env server create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env server create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Server delete (/docs/cli/command-reference/commands/shared-env/server-delete) Server delete [#server-delete] Delete server shared env Usage [#usage] ```sh coolify shared-env server delete ``` Get current help [#get-current-help] ```sh coolify shared-env server delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Server list (/docs/cli/command-reference/commands/shared-env/server-list) Server list [#server-list] List server shared envs Usage [#usage] ```sh coolify shared-env server list ``` Get current help [#get-current-help] ```sh coolify shared-env server list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Server update (/docs/cli/command-reference/commands/shared-env/server-update) Server update [#server-update] Update server shared env Usage [#usage] ```sh coolify shared-env server update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env server update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Team create (/docs/cli/command-reference/commands/shared-env/team-create) Team create [#team-create] Create team shared env Usage [#usage] ```sh coolify shared-env team create ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env team create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Team delete (/docs/cli/command-reference/commands/shared-env/team-delete) Team delete [#team-delete] Delete team shared env Usage [#usage] ```sh coolify shared-env team delete ``` Get current help [#get-current-help] ```sh coolify shared-env team delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # Team list (/docs/cli/command-reference/commands/shared-env/team-list) Team list [#team-list] List team shared envs Usage [#usage] ```sh coolify shared-env team list ``` Get current help [#get-current-help] ```sh coolify shared-env team list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Team update (/docs/cli/command-reference/commands/shared-env/team-update) Team update [#team-update] Update team shared env Usage [#usage] ```sh coolify shared-env team update ``` Options [#options] | Option | Type | Required | Default | Description | | :------------- | :-------- | :------: | :------ | :--------------------- | | `--comment` | `string` | No | — | Comment | | `--key` | `string` | No | — | Variable key | | `--literal` | `boolean` | No | `false` | Treat value as literal | | `--multiline` | `boolean` | No | `false` | Multiline value | | `--shown-once` | `boolean` | No | `false` | Show value only once | | `--value` | `string` | No | — | Variable value | Get current help [#get-current-help] ```sh coolify shared-env team update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Create (/docs/cli/command-reference/commands/tag/create) Create [#create] Create a team tag Usage [#usage] ```sh coolify tag create ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :---------- | | `--name` | `string` | No | — | Tag name | Get current help [#get-current-help] ```sh coolify tag create --help ``` The installed CLI help reflects the exact options available in your CLI version. # Delete (/docs/cli/command-reference/commands/tag/delete) Delete [#delete] Delete a team tag Usage [#usage] ```sh coolify tag delete ``` Get current help [#get-current-help] ```sh coolify tag delete --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/tag/list) List [#list] List all team tags Usage [#usage] ```sh coolify tag list ``` Get current help [#get-current-help] ```sh coolify tag list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/tag/update) Update [#update] Rename a team tag Usage [#usage] ```sh coolify tag update ``` Options [#options] | Option | Type | Required | Default | Description | | :------- | :------- | :------: | :------ | :----------- | | `--name` | `string` | No | — | New tag name | Get current help [#get-current-help] ```sh coolify tag update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Current (/docs/cli/command-reference/commands/teams/current) Current [#current] Get details of the team associated with the authentication token (API: GET /team). Usage [#usage] ```sh coolify teams current ``` Get current help [#get-current-help] ```sh coolify teams current --help ``` The installed CLI help reflects the exact options available in your CLI version. # Get (/docs/cli/command-reference/commands/teams/get) Get [#get] Get detailed information about a specific team by its ID. Usage [#usage] ```sh coolify teams get ``` Get current help [#get-current-help] ```sh coolify teams get --help ``` The installed CLI help reflects the exact options available in your CLI version. # List (/docs/cli/command-reference/commands/teams/list) List [#list] List all teams you have access to. Usage [#usage] ```sh coolify teams list ``` Get current help [#get-current-help] ```sh coolify teams list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Members list (/docs/cli/command-reference/commands/teams/members-list) Members list [#members-list] List members of a specific team by ID, or list members of the current team if no ID is provided. Usage [#usage] ```sh coolify teams members list [team_id] ``` Get current help [#get-current-help] ```sh coolify teams members list --help ``` The installed CLI help reflects the exact options available in your CLI version. # Update (/docs/cli/command-reference/commands/update) Update [#update] Update Coolify CLI Usage [#usage] ```sh coolify update ``` Get current help [#get-current-help] ```sh coolify update --help ``` The installed CLI help reflects the exact options available in your CLI version. # Version (/docs/cli/command-reference/commands/version) Version [#version] Current Coolify CLI version Usage [#usage] ```sh coolify version ``` Get current help [#get-current-help] ```sh coolify version --help ``` The installed CLI help reflects the exact options available in your CLI version. # Contexts (/docs/cli/contexts) Manage CLI contexts [#manage-cli-contexts] A context stores a Coolify URL and API token under a name such as `production` or `staging`. Contexts let one CLI installation connect to Coolify Cloud and multiple self-hosted instances without repeating connection details. The configuration file contains API tokens in plain text and is created with permissions limited to your user. Do not commit, share, or print the file. Add a context [#add-a-context] Create a self-hosted context with the full instance URL without `/api/v1`: ```sh coolify context add production https://coolify.example.com ``` Add `--default` to make the new context the default: ```sh coolify context add --default staging https://staging-coolify.example.com ``` The first context added to an otherwise empty configuration becomes the default even without `--default`. For Coolify Cloud, update the preconfigured `cloud` context by following [Authentication](/cli/authentication#authenticate-with-coolify-cloud). Select a context [#select-a-context] List saved contexts and select the default used by subsequent commands: ```sh coolify context list coolify context use production ``` Use another context for one command without changing the default: ```sh coolify --context staging app list ``` Verify a context [#verify-a-context] ```sh coolify context verify coolify context version ``` `context verify` checks the selected URL and authentication. `context version` prints the Coolify version returned by the selected instance. Update a context [#update-a-context] Change one or more saved properties: ```sh coolify context update production --name primary coolify context update primary --url https://new-coolify.example.com coolify context set-token primary ``` Renaming a context fails when the new name already exists. The URL must start with `http://` or `https://`. Remove a context [#remove-a-context] ```sh coolify context delete staging ``` Deleting the default context makes the first remaining context the new default. Deleting a context removes only the locally saved URL and token; it does not revoke the token in Coolify. Revoke unused credentials under **Keys & Tokens > API Tokens**. Configuration file location [#configuration-file-location] Run `coolify config` to print the active path. | Platform | Default path | | :-------------- | :------------------------------ | | Linux and macOS | `~/.config/coolify/config.json` | | Windows | `%APPDATA%\coolify\config.json` | Follow [Uninstall](/cli/uninstallation#optionally-delete-saved-contexts) if you also want to delete all saved contexts after removing the CLI. # Manage Database Backups (/docs/cli/database-backups) Manage database backups with the CLI [#manage-database-backups-with-the-cli] This workflow creates a backup configuration for an existing database, runs it immediately, and verifies the execution. Before you begin [#before-you-begin] You need: * a verified CLI context with permission to manage the database * the database UUID * an S3 storage UUID when the backup should also be uploaded to S3-compatible storage * a cron expression and retention policy Find the database and available S3 destinations: ```sh coolify context verify coolify database list coolify s3 list ``` Create a backup configuration [#create-a-backup-configuration] The following example runs every day at 02:00, keeps local backups for seven days, and uploads a copy to S3: ```sh coolify database backup create \ --frequency "0 2 * * *" \ --enabled \ --save-s3 \ --s3-storage-uuid \ --retention-days-locally 7 ``` Use [Backup create](/cli/command-reference/commands/database/backup-create) for amount, age, storage-size, timeout, database-selection, and S3 retention options. The response contains the backup configuration UUID. Save it for updates, manual runs, and execution history. Run the backup immediately [#run-the-backup-immediately] Trigger the new configuration instead of waiting for its next scheduled time: ```sh coolify database backup trigger ``` Triggering a backup does not change its schedule. Verify the execution [#verify-the-execution] List execution records for the configuration: ```sh coolify database backup executions ``` Confirm that the latest execution completed successfully. When S3 storage is enabled, also confirm that the expected backup appears in the configured bucket. Change retention or scheduling [#change-retention-or-scheduling] Update the existing configuration: ```sh coolify database backup update \ --frequency "0 3 * * *" \ --retention-days-locally 14 ``` The command changes only the flags you supply. It returns an error when no update flags are present. Remove a backup configuration [#remove-a-backup-configuration] ```sh coolify database backup delete ``` After deletion, list backup configurations and confirm that the removed UUID is absent: ```sh coolify database backup list ``` # Deploy Applications (/docs/cli/deploy-applications) Deploy applications with the CLI [#deploy-applications-with-the-cli] This workflow creates an application from a public Git repository, configures its environment variables, deploys it, and verifies the result. Before you begin [#before-you-begin] You need: * a verified CLI context with a token that can create and deploy applications * the UUIDs of the target project and server * the target environment name or UUID * a public Git repository, branch, build pack, and exposed port Find the required resources: ```sh coolify context verify coolify project list coolify server list ``` Create the application [#create-the-application] ```sh coolify app create public \ --server-uuid \ --project-uuid \ --environment-name production \ --git-repository https://github.com/example/api \ --git-branch main \ --build-pack nixpacks \ --ports-exposes 3000 ``` The response contains the new application UUID. Save it for later commands. Use [Create public](/cli/command-reference/commands/app/create-public) for all available build, routing, health-check, resource-limit, and deployment options. Configure environment variables [#configure-environment-variables] Create one variable: ```sh coolify app env create \ --key API_URL \ --value https://api.example.com ``` To load several variables, sync a dotenv file: ```sh coolify app env sync --file .env.production ``` Sync updates matching keys and creates missing keys. It does not delete variables that are absent from the file. Command arguments can be stored in shell history or CI logs. Pass sensitive values through your automation platform's secret handling and review its log redaction. Deploy the application [#deploy-the-application] Deploy by application UUID: ```sh coolify deploy uuid ``` You can also deploy by its Coolify name: ```sh coolify deploy name ``` Use `--force` only when the deployment must run without detected changes. Verify the deployment [#verify-the-deployment] List deployments and inspect the returned deployment UUID: ```sh coolify deploy list coolify deploy get ``` Then inspect the running application and its logs: ```sh coolify app get coolify app logs --lines 100 --show-timestamps ``` For a Docker Compose application, add `--service ` to select one service container. Add `--follow` when you need to stream new log entries. # How the CLI works (/docs/cli/how-cli-works) How the CLI works [#how-the-cli-works] The Coolify CLI translates terminal commands into requests to the Coolify REST API. It selects a saved Coolify connection, sends the request with an API token, and formats the response for a person or automation workflow. The same process applies to Coolify Cloud and self-hosted Coolify. The selected URL, token permissions, and self-hosted API controls determine which resources and operations are available. From a command to a response [#from-a-command-to-a-response] When you run a resource command, the CLI follows this sequence: 1. Loads the CLI configuration file. 2. Selects the context named by `--context`, or the default context when the flag is absent. 3. Uses the token supplied by `--token`, or the token saved in the selected context when the flag is absent. 4. Adds `/api/v1/` and the command's endpoint path to the context URL. 5. Sends the token in the `Authorization: Bearer ` header. 6. Checks the HTTP response and formats successful response data for the terminal. For example, a context URL of `https://coolify.example.com` and an operation that uses `resources` produce a request to: ```txt https://coolify.example.com/api/v1/resources ``` The CLI does not connect directly to the Docker engine for resource commands. Coolify receives the API request and performs the requested operation on the relevant resource or server. Context and token precedence [#context-and-token-precedence] The CLI resolves connection details in this order: | Setting | First choice | Fallback | | :---------- | :-------------------------------- | :---------------------------------- | | Coolify URL | Context selected with `--context` | Default context | | API token | Token supplied with `--token` | Token saved in the selected context | The `--token` flag changes only the token used for that command. It does not modify the saved context. Follow [Contexts](/cli/contexts) to change a saved URL or token. Access boundaries [#access-boundaries] Each API token belongs to the Coolify user and team that created it. The CLI can access only the resources and operations allowed by that token's team and permissions. Coolify Cloud keeps API access enabled. On self-hosted Coolify, **API Access** and the optional IP allowlist are checked before the token's permissions. Read [API permissions](/api/permissions) for token scope and [IP Allowlist](/api/ip-allowlist) for self-hosted controls. Request failures and retries [#request-failures-and-retries] Each API request has a 30-second timeout. When a request fails because of a network error, server error, or `429 Too Many Requests` response, the CLI retries up to three times with waits of 1, 2, and 4 seconds. The CLI does not retry other `4xx` responses. Correct the URL, token, permissions, command arguments, or requested resource before running the command again. If every attempt fails, the command returns an error and exits with a nonzero status. This lets shell scripts and CI jobs stop when a Coolify operation fails. Response formats [#response-formats] The CLI supports three global output formats: | Format | Intended use | | :------- | :------------------------------------------ | | `table` | Default human-readable terminal output. | | `json` | Compact output for scripts and automation. | | `pretty` | Indented JSON for inspection and debugging. | Select a format for one command: ```sh coolify --format json resource list ``` Sensitive values remain hidden unless the API token can read them and `--show-sensitive` is supplied. Avoid `--show-sensitive` in shared terminals and CI logs. Follow [Deploy applications](/cli/deploy-applications), [Automate with the CLI](/cli/automate-with-cli), or [Manage database backups](/cli/database-backups) for operational examples. Open **Commands** in the sidebar for operation-level syntax and options. # Installation (/docs/cli/installation) Install the Coolify CLI [#install-the-coolify-cli] Install the `coolify` binary on the computer or CI runner that will send requests to Coolify. Choose an installation method [#choose-an-installation-method] Install with the install script [#install-with-the-install-script] The install script detects `amd64` and `arm64`, downloads the latest GitHub release, and installs the binary in `/usr/local/bin`: ```sh curl -fsSL https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.sh | bash ``` A global installation may request `sudo`. To install without administrator access, pass `--user`; the binary is written to `~/.local/bin`: ```sh curl -fsSL https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.sh | bash -s -- --user ``` Add `~/.local/bin` to `PATH` if your shell cannot find `coolify`. Homebrew [#homebrew] On macOS or Linux, you can install from the Coolify tap: ```sh brew install coollabsio/coolify-cli/coolify-cli ``` Install with PowerShell [#install-with-powershell] Run PowerShell as an administrator to install into `%ProgramFiles%\Coolify`: ```powershell irm https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.ps1 | iex ``` For a user installation without administrator access, install into `%LOCALAPPDATA%\Coolify`: ```powershell $env:COOLIFY_USER_INSTALL=1; irm https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.ps1 | iex ``` To install a specific release, set `COOLIFY_VERSION` before running the installer: ```powershell $env:COOLIFY_VERSION='v1.0.0'; irm https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.ps1 | iex ``` Restart the terminal if `coolify` is not found after the installer updates `PATH`. Install with Go [#install-with-go] If Go is installed, build and install the latest CLI release into `GOBIN`, or `GOPATH/bin` when `GOBIN` is unset: ```sh go install github.com/coollabsio/coolify-cli/coolify@latest ``` Ensure that directory is in `PATH`. Verify the installation [#verify-the-installation] ```sh coolify version coolify --help ``` The first CLI command creates its configuration file when the file does not exist. Follow [Authentication](/cli/authentication) to configure a token, then use [Contexts](/cli/contexts) to manage saved Coolify connections. Enable shell completion [#enable-shell-completion] Generate completion instructions for your shell: ```sh coolify completion bash coolify completion zsh coolify completion fish coolify completion powershell ``` Run `coolify completion --help` for the commands that load completion now or enable it for future sessions. To install a newer release later, follow [Update the Coolify CLI](/cli/update). To remove the binary and optionally its saved contexts, follow [Uninstall the Coolify CLI](/cli/uninstallation). # Uninstall (/docs/cli/uninstallation) Uninstall the Coolify CLI [#uninstall-the-coolify-cli] Uninstalling the CLI removes the local `coolify` command. It does not remove your Coolify instance or any applications, databases, services, servers, or other resources managed through Coolify. Remove the CLI [#remove-the-cli] Use the method that installed the binary. Remove an install-script binary [#remove-an-install-script-binary] For a global installation: ```sh sudo rm /usr/local/bin/coolify ``` For a user installation: ```sh rm ~/.local/bin/coolify ``` Uninstall with Homebrew [#uninstall-with-homebrew] ```sh brew uninstall coolify-cli ``` Remove a PowerShell-installed binary [#remove-a-powershell-installed-binary] For an administrator installation, run PowerShell as an administrator: ```powershell Remove-Item "$env:ProgramFiles\Coolify\coolify.exe" ``` For a user installation: ```powershell Remove-Item "$env:LOCALAPPDATA\Coolify\coolify.exe" ``` Remove the corresponding `Coolify` directory from your user or system `PATH` if the installer added it and no other programs use that directory. Remove a Go-installed binary [#remove-a-go-installed-binary] On Linux or macOS, print the directory where Go installs binaries: ```sh go env GOBIN GOPATH ``` When `GOBIN` is set, remove `coolify` from that directory. Otherwise, remove it from the `bin` directory under the first `GOPATH` entry. For the common default location: ```sh rm "$(go env GOPATH)/bin/coolify" ``` On Windows, run the following in PowerShell: ```powershell $goBin = go env GOBIN if (-not $goBin) { $goBin = Join-Path (go env GOPATH) "bin" } Remove-Item (Join-Path $goBin "coolify.exe") ``` Verify binary removal [#verify-binary-removal] Open a new terminal, then run: ```sh coolify version ``` The shell should report that `coolify` is not a recognized command. If it still runs, inspect the resolved path with `command -v coolify` on Linux or macOS, or `Get-Command coolify` in PowerShell, and remove the remaining installation through its owning method. Optionally delete saved contexts [#optionally-delete-saved-contexts] The CLI configuration contains every saved Coolify URL and API token. Copy any context details you still need before deleting the file. Removing the file does not revoke its API tokens in Coolify. Delete the configuration only if you no longer need the saved contexts. Delete the Linux or macOS configuration [#delete-the-linux-or-macos-configuration] ```sh rm ~/.config/coolify/config.json ``` Delete the Windows configuration [#delete-the-windows-configuration] ```powershell Remove-Item "$env:APPDATA\coolify\config.json" ``` Revoke tokens you no longer use under **Keys & Tokens > API Tokens** in each affected Coolify team. Deleting the local file alone leaves those tokens valid. # Update (/docs/cli/update) Update the Coolify CLI [#update-the-coolify-cli] The CLI checks GitHub for newer releases when it starts. When an update is available, it prints the available version and the `coolify update` command to standard error. Choose an update method [#choose-an-update-method] Use the package or installation method that owns the binary when you want it to continue managing future updates. Update the current binary [#update-the-current-binary] The built-in updater downloads the latest release for your operating system and architecture, then replaces the running CLI binary: ```sh coolify update ``` If the binary is installed in a system directory such as `/usr/local/bin` or `%ProgramFiles%\Coolify`, run the command with the administrator permissions required to replace that file. Rerun the Linux or macOS installer [#rerun-the-linux-or-macos-installer] For a global installation: ```sh curl -fsSL https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.sh | bash ``` For an installation in `~/.local/bin`: ```sh curl -fsSL https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.sh | bash -s -- --user ``` The installer displays the installed version and asks before replacing an existing binary. Upgrade with Homebrew [#upgrade-with-homebrew] ```sh brew update brew upgrade coolify-cli ``` Rerun the PowerShell installer [#rerun-the-powershell-installer] For an administrator installation: ```powershell irm https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.ps1 | iex ``` For a user installation: ```powershell $env:COOLIFY_USER_INSTALL=1; irm https://raw.githubusercontent.com/coollabsio/coolify-cli/main/scripts/install.ps1 | iex ``` The installer displays the installed version and asks before replacing an existing binary. Reinstall with Go [#reinstall-with-go] ```sh go install github.com/coollabsio/coolify-cli/coolify@latest ``` Go replaces the binary in `GOBIN`, or `GOPATH/bin` when `GOBIN` is unset. Verify the update [#verify-the-update] ```sh coolify version coolify context verify ``` Confirm that `coolify version` shows the expected CLI release. A successful context verification confirms that the updated CLI can still connect and authenticate to the selected Coolify instance. Updating the CLI does not change its configuration file or saved contexts. # What is the Coolify CLI? (/docs/cli/what-is-the-coolify-cli) What is the Coolify CLI? [#what-is-the-coolify-cli] The Coolify CLI lets you inspect and manage Coolify resources from a terminal. It calls the Coolify REST API and works with both Coolify Cloud and self-hosted Coolify. Use the CLI for repeatable deployments, scripts, CI jobs, resource inventory, and operational tasks that do not require the dashboard. Before you begin [#before-you-begin] You need: * an [API token](/core/security/credentials/api-tokens) with the permissions required by your commands * API access, which is enabled by default on Coolify Cloud and must be [enabled by an administrator on self-hosted Coolify](/api/ip-allowlist) Get started [#get-started] 1. [Install the CLI](/cli/installation). 2. [Authenticate the CLI](/cli/authentication) and [create a context](/cli/contexts) for Coolify Cloud or your self-hosted instance. 3. Verify the saved URL and token with `coolify context verify`. 4. Run an inventory command: ```sh coolify resource list ``` The command uses your default context and displays a table of applications, services, and databases that the token can access. How the CLI connects to Coolify [#how-the-cli-connects-to-coolify] Read [How the CLI works](/cli/how-cli-works) to understand how the CLI selects a context, authenticates API requests, handles failures, and formats responses. Find commands and options [#find-commands-and-options] Run `coolify --help` to list command groups. Add `--help` after any group or command to see its current arguments and flags: ```sh coolify app --help coolify app create --help coolify database backup --help ``` The built-in help is the authoritative reference for the installed CLI version. Open **Commands** in the sidebar for operation-level syntax and options. Follow [Deploy applications](/cli/deploy-applications), [Automate with the CLI](/cli/automate-with-cli), or [Manage database backups](/cli/database-backups) for complete workflows. Use [Update the Coolify CLI](/cli/update) when a new release is available. Follow [Uninstall the Coolify CLI](/cli/uninstallation) to remove the local command without affecting resources managed through Coolify. Use the CLI with AI agents [#use-the-cli-with-ai-agents] The CLI repository publishes generated catalogs for tools that need machine-readable command context: * [`llms.txt`](https://github.com/coollabsio/coolify-cli/blob/main/llms.txt) contains concise instructions and common commands. * [`llms-full.txt`](https://github.com/coollabsio/coolify-cli/blob/main/llms-full.txt) contains the generated command and flag catalog. CLI contributors can regenerate both files from the repository with: ```sh go run ./coolify docs llms ``` The [Coolify CLI source repository](https://github.com/coollabsio/coolify-cli) also contains build, test, contribution, and release instructions for CLI development. # Concepts (/docs/concepts)
Many people start their self-hosting journey after discovering Coolify. If you’re one of them, here’s a list of a few concepts that could make your experience smoother. Servers [#servers] A server is a computer designed to run applications or services, providing the necessary computing power for your projects. It can be either physical such as a machine you have at home, like a Raspberry Pi, or one rented from a hosting provider like Hetzner. Resources [#resources] In Coolify, a resource refers to an application or service you set up on your server—like a website, database, or API. Each resource comes with its own configuration, like domains, backups, health checks, and so on. Coolify offers a handy list of pre-set resources, called one-click services, that you can deploy instantly. But if you prefer, you can also deploy your own application easily. Environments [#environments] In Coolify, a environment is a tailored setup on your server that determines how your resources operate. For instance, you could have a development environment for testing and debugging your code, alongside a production environment where your finished application goes live. With Coolify, you can set up multiple environments on a single server, letting you switch between them effortlessly. Projects [#projects] A project in Coolify is a group of environments and resources you’ve deployed on your server. It serves as the highest-level structure in Coolify, organizing your deployment setup. You can manage multiple projects on the same server, each with its own unique set of environments and resources. For example, you might create one project for all your hobby-related resources and another for work-related ones. Containers [#containers] In Coolify, everything you deploy runs as a Docker container, making it easy to manage and isolate your application. You can use pre-built Docker images from public registries like Docker Hub or GitHub Container Registry to deploy without building them yourself. To deploy, you need a Docker image, either one you’ve built or one from someone else. If you’re coding your own app, Coolify can auto-build the image from a Dockerfile or Docker Compose file, though this resource-heavy process requires a capable server. Alternatively, you can build the image elsewhere, push it to a registry, and let Coolify deploy it as a container. Reverse Proxy [#reverse-proxy] A reverse proxy is a server or app that sits between your application and users, forwarding requests to the right place. Coolify includes two proxy options, Caddy and Traefik, which handle requests to your website by directing them to the container running your app. This setup lets you run multiple applications on one server without tweaking configs or ports. Plus, Coolify supports unlimited domains, so you could deploy 20 different apps, each with its own unique domain. The reverse proxy also automatically manages SSL/TLS certificates for your applications. When you enter a domain with `https://`, the proxy requests and installs certificates from [Let's Encrypt](https://letsencrypt.org?utm_source=coolify.io) automatically, with no manual configuration needed. Certificates are renewed automatically before they expire, keeping your applications secure without any intervention. Security [#security] Coolify doesn’t manage your server’s security or updates, that’s your responsibility to keep everything secure and up to date. It’s built to simplify deployment management for you. While the Coolify core team plans to introduce more security features eventually, for now, securing your server is entirely up to you. Teams [#teams] Coolify supports multiple users and teams, allowing each team to have its own projects and environments. You can assign roles like admin to users, simplifying project management and collaboration on a single server. Currently, the teams feature isn’t fully polished for production use, but the Coolify core team plans to enhance it down the line. # Contributing to Core (/docs/contribute/coolify) Contributing to Coolify [#contributing-to-coolify] Set up the local Coolify development environment and prepare code contributions for the core repository. Set up Docker, Spin, and a local fork of [coollabsio/coolify](https://github.com/coollabsio/coolify). Start the stack with `spin up`, test at **[http://localhost:8000](http://localhost:8000)**, and open pull requests against the `next` branch. *** Use WSL2 with Docker CE for the closest Linux development experience. * Install [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install?ref=coolify) with a Linux distribution such as Ubuntu. * Install [Docker Engine](https://docs.docker.com/engine/install/?ref=coolify) inside WSL2, or use [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/?ref=coolify) with the WSL2 backend enabled. * Install [Spin for Windows](https://serversideup.net/open-source/spin/docs/installation/install-windows#download-and-install-spin-into-wsl2?ref=coolify). OrbStack is recommended because it is lighter than Docker Desktop for local development. * Install [OrbStack](https://docs.orbstack.dev/quick-start#installation?ref=coolify) or [Docker Desktop for Mac](https://docs.docker.com/desktop/install/mac-install/?ref=coolify). * Install [Spin for macOS](https://serversideup.net/open-source/spin/docs/installation/install-macos/#download-and-install-spin?ref=coolify). * If permission errors appear when starting the stack, try running Spin with sudo. Docker Engine is recommended because it avoids the extra VM layer. * Install [Docker Engine](https://docs.docker.com/engine/install/?ref=coolify) for your distribution, or use [Docker Desktop for Linux](https://docs.docker.com/desktop/install/linux-install/?ref=coolify) if you want a GUI. * Install [Spin for Linux](https://serversideup.net/open-source/spin/docs/installation/install-linux#configure-docker-permissions?ref=coolify). * Make sure your user can run Docker commands without restarting the setup flow repeatedly. *** After installing Docker or OrbStack and Spin, confirm both commands are available. ```bash docker --version spin --version ``` *** *** *** Open a terminal in the local Coolify repository and leave the process running. ```bash spin up ``` If you hit permission errors, especially on macOS, run: ```bash sudo spin up ``` You may see some errors during startup. That can be expected while the development stack is booting. *** Use the seeded development account to sign in locally. [http://localhost:8000](http://localhost:8000) [test@example.com](mailto:test@example.com) password | Tool | URL | Note | | :-------------- | :----------------------------------------------------------------- | :----------------------------------------------------------------------- | | Coolify app | [http://localhost:8000](http://localhost:8000) | Use [test@example.com](mailto:test@example.com) and password. | | Laravel Horizon | [http://localhost:8000/horizon](http://localhost:8000/horizon) | Available to the root user and users listed in `HORIZON_ALLOWED_EMAILS`. | | Mailpit | [http://localhost:8025](http://localhost:8025) | Catch local development emails. | | Telescope | [http://localhost:8000/telescope](http://localhost:8000/telescope) | Disabled by default; enable it with TELESCOPE\_ENABLED=true. | *** Telescope is disabled by default. Add this to your `.env` file when you need the debugging dashboard. ```bash TELESCOPE_ENABLED=true ``` *** * Commit and push your changes to your fork. * Open the pull request against the Coolify repository. * Set the base branch to `next`, not `v4.x`. * Manually test the changed flow in the local app, not only through test files. * Fill in the pull request template with the details maintainers need. * Move the pull request out of draft as soon as it is ready for review. Pull requests that stay in draft for a long time may be closed by maintainers. *** Run migrations after switching branches, pulling updates, or changing database structure. ```bash docker exec -it coolify php artisan migrate ``` To reset the development database with default seed data, run: ```bash docker exec -it coolify php artisan migrate:fresh --seed ``` *** If the local stack or database is broken, remove the development containers and volumes, then start from a clean slate. **Stop the running Spin process** Press Ctrl+C in the terminal where Spin is running. **Remove development containers** ```bash docker rm coolify coolify-db coolify-redis coolify-testing-host coolify-minio coolify-vite-1 coolify-mail ``` **Remove development volumes** ```bash docker volume rm coolify_dev_backups_data coolify_dev_postgres_data coolify_dev_coolify_data coolify_dev_minio_data ``` If your volume names do not use the `coolify` prefix, remove the prefix from the volume command before running it. **Remove unused images** ```bash docker image prune -a ``` **Start Coolify again** ```bash spin up ``` **Run migrations and seeders** ```bash docker exec -it coolify php artisan migrate:fresh --seed ``` *** # Contributing to Documentation (/docs/contribute/documentation) Coolify Docs Contribution Guide [#coolify-docs-contribution-guide] Contribute updates and fixes to the Coolify documentation with the same workflow and review expectations as other Coolify contributions. Fork [coollabsio/coolify-docs](https://github.com/coollabsio/coolify-docs), work from the `next` branch, run the docs locally with Bun, and open focused pull requests back to `next`. *** *** Install dependencies and start the documentation site from the repository root. ```bash bun install bun run dev ``` The development server starts at [http://localhost:3000/docs/](http://localhost:3000/docs/). Bun is the expected package manager. If you use another tool locally, do not commit its lockfile or configuration files. *** * Use clear, simple English for readers who may not be native English speakers. * Break guides into small steps that a new self-hoster can follow without guessing. * Add screenshots when they help explain a screen, setting, or expected result. * Use existing docs components and nearby pages as the pattern before creating anything new. *** Screenshots should make a step easier to follow, not decorate the page. | Rule | Expectation | | :-------- | :--------------------------------------------------------------------------------------- | | Format | Use .webp images for documentation screenshots and illustrations. | | Location | Place image files in `public/images/...`, then reference them from MDX as `/images/...`. | | Component | Use the zoomable image component to add images to docs. | Use this component for docs screenshots: ```tsx ``` Example: ```tsx ``` *** *** The docs are actively being rewritten for better structure and clarity. Contributions that improve accuracy, reduce confusion, or follow the existing page patterns are especially helpful. *** Yes. Small, obvious documentation fixes can be opened as a pull request without prior discussion. Target next. The main branch represents production, while next is the development branch. You can use a different package manager locally, but do not include its generated files in your commit. Open an issue for repository-specific problems, or ask in the contribute channel on Discord. *** API schema for unreleased docs [#api-schema-for-unreleased-docs] The API reference reads `config/openapi.json`. The fetch script defaults to upstream Coolify `main`; set `COOLIFY_OPENAPI_URL` to a raw schema URL for the intended release revision when documenting unreleased features. Check generated endpoint routes and redirects after refreshing the schema. Network failures preserve the local spec, so confirm that it contains the expected endpoints before committing API changes. # Contribution Guidelines (/docs/contribute/guidelines) Contributing to Coolify [#contributing-to-coolify] We are happy that you are interested in contributing to Coolify. Coolify is used by 470K+ people and maintained by two core maintainers. Contributions are welcome, but alignment matters more than volume: keep changes focused, discuss larger work before coding, test what you submit, and target the `next` branch. These guidelines are stricter than many open-source projects on purpose. Clear structure and boundaries reduce maintainer burnout and keep Coolify sustainable long term. Commit messages and pull request titles should start with an action and category. Keep descriptions concise; walls of text listing every small change may be rejected. | Prefix | Use | | :------------- | :------------------------ | | fix(ui): | UI-related fixes | | fix(api): | API-related fixes | | feat(api): | API-related additions | | feat(service): | One-click service changes | AI tools are allowed, but you must disclose AI usage in the pull request description. You are still responsible for understanding every change, verifying correctness, and following existing project patterns. No. Small, obvious fixes can be submitted directly as a pull request. Discuss it first in GitHub Discussions or Discord. New features without prior alignment may be closed without review. Comment first to confirm the issue is still relevant and that no one else is actively working on it. Keep the pull request focused on the stated goal. Refactors and cleanup work should be discussed and submitted separately. Yes, but disclose it in the pull request description. You must understand, verify, and own every change. It usually means the change did not align with project direction, required too much review capacity, or targeted work that is not planned. # Add a new service template to Coolify (/docs/contribute/service) Adding a new service template to Coolify [#adding-a-new-service-template-to-coolify] Services in Coolify are templates made from normal Docker Compose files with Coolify metadata, magic environment variables, storage handling, and one-click deployment behavior. Add the compose file and logo, test it through **Docker Compose Empty**, open the template pull request against `next`, and open the matching service docs pull request before the template can be merged. The service repository must have at least **1,000 GitHub stars** before it can be added to Coolify as a one-click service. *** *** Add metadata as comments at the top of the compose file. ```yaml # documentation: https://docs.example.com/ # slogan: A brief description of your service # category: One word, broad app type # tags: tag1,tag2,tag3 # logo: svgs/your-service.svg # port: 1234 ``` | Field | Expectation | | :------------ | :------------------------------------------------------ | | documentation | Link to the official service documentation. | | slogan | Short description shown in Coolify. | | category | One broad app type, written as a single word. | | tags | Comma-separated search terms. | | logo | Path to the service logo, for example svgs/example.svg. | | port | Main entrypoint port for the service. | Always specify a port. Caddy proxy cannot automatically determine every service port. *** Use Coolify magic variables for generated values and user-provided configuration. Declare the storage mounts the service needs. ```yaml services: app: image: your-service-image:1.2.3 environment: - DATABASE_URL=${COOLIFY_DATABASE_URL} volumes: - app-data:/data ``` Mark critical configuration as required so users understand what must be set before deployment. ```yaml services: app: image: your-service:1.2.3 environment: # Required - must be set by the user - DATABASE_URL=${DATABASE_URL:?} - API_KEY=${API_KEY:?} # Required with sensible defaults - PORT=${PORT:?8080} - LOG_LEVEL=${LOG_LEVEL:?info} # Optional with fallback values - DEBUG=${DEBUG:-false} - CACHE_TTL=${CACHE_TTL:-3600} ``` Do not use latest or other floating tags. Pin the image to a specific version. Configuration Coolify adds [#configuration-coolify-adds] For a normal service template, Coolify generates part of the deployment configuration: | Configuration | What to include in the template | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `container_name` | Omit it. Coolify generates names from the Compose service name and resource UUID. | | `restart` | Omit it to use Coolify's `unless-stopped` default. Set it explicitly only when the service needs different behavior, such as `restart: "no"` for a one-time setup container. | | Top-level `volumes` | You can omit empty declarations for ordinary named volumes. Coolify adds declarations for the named volumes referenced by the services. Keep explicit declarations when they contain options such as `external`, `name`, or driver configuration. | | Default network | Coolify creates a resource-specific network and connects the proxy. Declare custom networks only when the template requires them. | The example above still needs `app-data:/data` under the service's `volumes`: Coolify cannot infer which container paths need persistent storage. It generates the named-volume declaration from that mount; it does not make every container directory persistent. Test the parsed deployment through **Docker Compose Empty**. These additions apply to Coolify's normal service parsing, not to running the template directly with Docker Compose or using an application's raw Compose deployment mode. *** Put the logo in the Coolify repository and reference it from the compose metadata, then test the compose file before opening the pull request. * Example: a service named wordpress should use templates/compose/wordpress.yaml, svgs/wordpress.svg, and # logo: svgs/wordpress.svg. * Prefer SVG logos. Use WebP or PNG only when SVG is unavailable. * Avoid low-quality JPG logos. * Test from a fresh Docker Compose Empty resource, not only an already-running local container. * Confirm the service starts and the exposed port works. *** * Open the template pull request against the Coolify repository's `next` branch. * Add `templates/compose/.yaml`. * Add `svgs/.svg` and reference that same path in the compose metadata. * Test the template through the Docker Compose Empty deployment flow. * Open the matching service docs pull request in this repository; it is required before the template PR can be merged. * Link the docs pull request from the template pull request so reviewers can check both together. Coolify deploys from templates/service-templates.json, a parsed list generated from the compose templates in the Coolify repository. You do not need to edit that JSON file directly. *** Open a matching docs page pull request in this repository before the service template pull request is merged. * Add the service logo under `public/images/services`. * Create `content/docs/services/.mdx`. * Use lowercase kebab-case for the slug and filename. * Run the service generators or let dev/build run them for you. * Verify the service card, category filter, and all-services entry. Start the docs page with this frontmatter. Keep the description short so cards and search results stay readable. ```yaml --- title: "Service Name" description: "Short service description for cards and search." og: description: "SEO/social-card description." category: "Analytics" icon: "/images/services/service-name-logo.svg" --- ``` | Field | Required | Notes | | :------------- | :------- | :--------------------------------------------------------------------------- | | title | yes | Display name shown on the service card. | | description | yes | Short description used on cards and search results. | | category | yes | Category used by the overview and generated all-services page. | | icon | optional | Only set this if automatic logo resolution cannot find the logo. | | og.description | optional | Longer social and SEO description. | | disabled | optional | Set true to hide the service from listings while keeping the page reachable. | To hide a service from generated listings while keeping the page reachable, include the disabled field in the service page frontmatter: ```yaml --- title: "Service Name" description: "Short service description for cards and search." category: "Analytics" disabled: true --- ``` *** Use this as a small starting point for the service page body. ```markdown # Service Name ![Service Name](/docs/images/services/service-name-logo.svg) ## What is Service Name? Brief description and use cases. ## Links - [Official website](https://example.com?utm_source=coolify.io) - [GitHub](https://github.com/example/repo?utm_source=coolify.io) ``` Add screenshots with the zoomable image component when the image benefits from a larger view: ```tsx ``` Do not use ZoomableImage for the logo. The services overview and all-services directory are generated from service frontmatter. The generators run during dev and build, but you can run them directly when checking a service page. ```bash bun run generate:services ``` *** If you want a service template but are not submitting it yourself, search the [service template requests](https://github.com/coollabsio/coolify/discussions/categories/service-template-requests) first. Upvote an existing request, or create a new one if it does not exist. *** No. The upstream service repository must have at least 1,000 GitHub stars before it can be added as a one-click service. Caddy cannot always detect the correct service port automatically. The metadata port tells Coolify what to expose. No. Service listings are generated from service docs frontmatter and refreshed by the generator scripts. Use the service template request category in GitHub Discussions. Search first, then upvote an existing request or create a new one. *** # Cron Syntax (/docs/core/automation/cron-syntax) Cron syntax [#cron-syntax] Coolify uses cron expressions to schedule tasks, backups, updates, Docker cleanup, and other recurring work. Most schedule fields accept a standard five-field expression. Some also accept Coolify's named schedules. Five-field format [#five-field-format] A cron expression contains five space-separated fields: ```txt ┌───────────── minute (0-59) │ ┌───────────── hour (0-23) │ │ ┌───────────── day of month (1-31) │ │ │ ┌───────────── month (1-12) │ │ │ │ ┌───────────── day of week (0-7, Sunday is 0 or 7) │ │ │ │ │ * * * * * ``` Common operators [#common-operators] | Character | Meaning | Example | | --------- | ------------------ | -------------------------------------------------- | | `*` | Every valid value | `* * * * *` runs every minute. | | `,` | A list of values | `0 8,16 * * *` runs at 08:00 and 16:00. | | `-` | An inclusive range | `0 9 * * 1-5` runs at 09:00 Monday through Friday. | | `/` | A step interval | `*/15 * * * *` runs every 15 minutes. | Field-specific values [#field-specific-values] | Value | Field | Meaning | Example | | ---------------------------------------------------------------------- | --------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | `JAN`-`DEC` | Month | A three-letter month name | `0 0 1 JAN *` runs on January 1. | | `SUN`-`SAT` | Day of week | A three-letter weekday name | `0 9 * * MON-FRI` runs at 09:00 on weekdays. | | `?` | Day of month or day of week | No specific value for that field | `0 9 ? * MON` runs at 09:00 every Monday. | | `L` | Day of month | The last day of the month | `0 0 L * *` runs at 00:00 on the last day of each month. | | `W` | Day of month | The weekday nearest the specified date | `0 9 15W * *` runs at 09:00 on the weekday nearest the 15th. | | `L` | Day of week | The last specified weekday of the month | `0 9 * * 5L` runs at 09:00 on the last Friday. | | `#` | Day of week | The numbered occurrence of a weekday in the month | `0 9 * * 5#2` runs at 09:00 on the second Friday. | *** Named schedules [#named-schedules] Coolify recognizes these exact values and translates them to five-field expressions: | Named schedule | Equivalent expression | Runs | | ----------------------------------- | --------------------- | ---------------------------------------- | | `every_minute` | `* * * * *` | Every minute | | `hourly` or `@hourly` | `0 * * * *` | At minute 0 of every hour | | `daily`, `@daily`, or `@midnight` | `0 0 * * *` | Every day at 00:00 | | `weekly` or `@weekly` | `0 0 * * 0` | Every Sunday at 00:00 | | `monthly` or `@monthly` | `0 0 1 * *` | On the first day of every month at 00:00 | | `yearly`, `@yearly`, or `@annually` | `0 0 1 1 *` | Every January 1 at 00:00 | `@every_minute` is not supported. Use `every_minute` or `* * * * *` instead. *** Common examples [#common-examples] | Schedule | Expression | | --------------------------------- | ------------- | | Every five minutes | `*/5 * * * *` | | Every day at 02:30 | `30 2 * * *` | | Monday through Friday at 09:00 | `0 9 * * 1-5` | | Every Sunday at 03:00 | `0 3 * * 0` | | First day of every month at 00:00 | `0 0 1 * *` | *** Timezone [#timezone] The schedule runs in the timezone used by the feature that owns it. Scheduled tasks use the timezone configured for the server that runs the application or service. Other scheduled features can use an instance or server timezone described on their own settings page. When an exact local time matters, confirm the relevant timezone before saving the schedule. *** Validate a schedule [#validate-a-schedule] Enter the expression in the schedule's **Frequency** field and save the setting. Coolify rejects values that its cron parser cannot evaluate. For a scheduled task, use **Execute Now** to verify the command and container separately. Manual execution tests the command immediately; it does not prove that a different cron expression represents the time you intended. # Deploy Webhooks (/docs/core/automation/deploy-webhooks) Deploy webhooks [#deploy-webhooks] A deploy webhook is an authenticated Coolify API URL that starts a deployment without using the dashboard. Use it after CI checks pass, from a Git provider without a native Coolify integration, or from another automation system. Resource deploy webhooks target one application or service. Tag deploy webhooks target every application and service assigned to the selected [tag](/core/automation/tags/overview). Before you start [#before-you-start] You need: * API access enabled for the Coolify instance * permission to create an API token for the active team * the resource or tag you want the webhook to deploy * a secure secret store in the system that will call the webhook On a self-hosted instance, open **Settings > Advanced** and turn on **API Access** if the API is disabled. *** Create a deploy token [#create-a-deploy-token] Open API Tokens [#open-api-tokens] Open **Keys & Tokens** in the main sidebar, then select **API Tokens**. Configure the token [#configure-the-token] Enter a description, choose an expiration period, and select the `deploy` permission. A deploy-only token can trigger deploy webhooks without receiving general read or write access to the API. Create and copy the token [#create-and-copy-the-token] Click **Create**, then copy the token immediately. Coolify shows the token value only once. Store the token [#store-the-token] Save it in your CI or automation platform's secret store, for example as `COOLIFY_TOKEN`. Do not commit it to a repository or place it directly in a workflow file. Read [API Tokens](/core/security/credentials/api-tokens) for team scoping, expiration, and API access controls. *** Copy a webhook URL [#copy-a-webhook-url] Choose the URL that matches the deployment target. Use a resource webhook to deploy one application or service. 1. Open the application or service. 2. Select **Webhooks**. 3. Copy **Deploy Webhook (auth required)**. The generated URL has this form: ```txt https://coolify.shadowarcanist.com/api/v1/deploy?uuid=&force=false ``` Use a tag webhook to deploy every application and service assigned to one tag. 1. Open **Tags** in the main sidebar. 2. Select the tag. 3. Copy **Deploy Webhook URL**. The generated URL has this form: ```txt https://coolify.shadowarcanist.com/api/v1/deploy?tag= ``` Review [Deploy by Tag](/core/automation/tags/deploy-by-tag) before automating a group deployment. *** Trigger the deployment [#trigger-the-deployment] Store the copied URL as `COOLIFY_DEPLOY_WEBHOOK`, then send a `GET` request with the token in the `Authorization` header: ```sh curl --request GET "$COOLIFY_DEPLOY_WEBHOOK" \ --header "Authorization: Bearer $COOLIFY_TOKEN" ``` Coolify also accepts `POST` requests. The endpoint requires either `uuid` or `tag`; do not send both in one request. The URL identifies the deployment target, but the Bearer token authorizes the action. Revoke the token from **Keys & Tokens > API Tokens** if it is exposed. *** Request options [#request-options] | Option | Purpose | Example | | ------- | ---------------------------------------------------------------------- | ---------------- | | `uuid` | Deploy one or more resource UUIDs. Separate several UUIDs with commas. | `uuid=abc,def` | | `tag` | Deploy one or more tag groups. Separate several names with commas. | `tag=api,worker` | | `force` | Rebuild an application without using its build cache. | `force=true` | For a JSON `POST` request, send the same option names in the request body: ```sh curl --request POST "https://coolify.shadowarcanist.com/api/v1/deploy" \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Content-Type: application/json" \ --data '{"uuid":"","force":false}' ``` *** Verify the deployment [#verify-the-deployment] A successful application request returns deployment details, including a deployment UUID when a deployment was queued. Open the application's **Deployments** page and confirm that the matching deployment starts and finishes successfully. For a service or tag request, verify each affected resource from its Coolify page. Do not treat an accepted API request as proof that every resource became healthy. *** Troubleshooting [#troubleshooting] Confirm that the complete token is present after `Bearer`, has not expired, and belongs to the team that owns the target resource or tag. Create or use a token with `deploy` permission. A read-only token cannot trigger the endpoint. Copy the generated URL again or include exactly one of `uuid` and `tag` in the query string or JSON body. Confirm that the resource UUID or tag name is correct and belongs to the token's active team. For a tag request, confirm that at least one application or service still has the tag. Wait for the `Retry-After` interval before trying again. A busy application deployment queue can also return `429` while a group deployment is being created. # Create a Task (/docs/core/automation/scheduled-tasks/create-a-task) Create a scheduled task [#create-a-scheduled-task] Create a scheduled task when an application or service needs to run the same command on a recurring schedule. Before you create a task [#before-you-create-a-task] Make sure you know: * the exact command that works inside the resource container * how often the command should run * which container or service component should receive the command * the longest time the command should be allowed to run If the command changes or deletes data, test it inside the intended container before scheduling it. *** Create the task [#create-the-task] Open Scheduled Tasks [#open-scheduled-tasks] Open the application or service, select **Scheduled Tasks** in the resource sidebar. Open the task form [#open-the-task-form] Click **+ Add**. Coolify opens **New Scheduled Task**. Name the task [#name-the-task] Enter a short name that describes the command's purpose, such as `Run Laravel scheduler` or `Clear expired sessions`. Enter the command [#enter-the-command] Enter the command exactly as it should run inside the container. For example: ```sh php artisan schedule:run ``` Do not include `docker exec`. Coolify enters the selected container before running the command. Set the frequency [#set-the-frequency] Enter a five-field cron expression such as `0 0 * * *`, or a named schedule such as `daily`. The schedule uses the timezone configured for the server that runs the resource. See [Cron Syntax](/core/automation/cron-syntax) for more examples. Set the timeout [#set-the-timeout] Enter the maximum execution time in seconds. The dashboard accepts values from `60` to `36000` and uses `300` seconds by default. Choose a value longer than the task's normal runtime, but short enough to stop a stuck command. Select the container [#select-the-container] For an application with one container, you can leave **Container** empty. If the application has multiple containers, select or enter the container that contains the command. For a service, select the service component. If you enter it manually later, use the component name from the Docker Compose definition, such as `mysql`, without Coolify's generated resource suffix. Save the task [#save-the-task] Click **Add task**. Coolify creates the task as enabled and adds it to the **Scheduled Tasks** list. *** Verify the task [#verify-the-task] Open the new task. If the resource is running, click **Execute now**. Under **Recent executions**, open the new execution and confirm that: * the status changes to **Success** * the start and end times are shown * the command output matches the expected result Scheduled runs use the same command, container, and timeout. Their results appear in the same execution history. *** Troubleshooting [#troubleshooting] Use a valid five-field expression or one of Coolify's named schedules. The named value `daily` is valid; `@every_minute` is not supported. Compare the value with [Cron Syntax](/core/automation/cron-syntax). Open the task and set **Container** to the application container or service component that should run the command. Start the application or service, confirm that its target container is running, then click **Execute now** again. # Execution History (/docs/core/automation/scheduled-tasks/execution-history) Scheduled task execution history [#scheduled-task-execution-history] Coolify records each scheduled and manual task run under **Recent executions**. Use these records to confirm that a command finished and to inspect its output when it fails. Open execution history [#open-execution-history] 1. Open the application or service. 2. Select **Scheduled Tasks**. 3. Select a task. 4. Scroll to **Recent executions**. Coolify shows the 20 most recent execution records, newest first. *** Read an execution [#read-an-execution] | Status | Meaning | What to do | | ----------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------- | | In Progress | The command is still running. | Keep the task page open while Coolify refreshes the record. | | Success | The command exited without a reported error. | Open the output and confirm the command produced the intended result. | | Failed | The command failed, timed out, or could not run in the selected container. | Open the output and start with the first reported error. | Completed records also show the start time, end time, and duration. Times are displayed in the timezone configured for the server that runs the resource. *** Inspect and download output [#inspect-and-download-output] Users need permission to update the resource to see scheduled commands and output. API access to task output requires `read:sensitive`. Click an execution record to expand its captured output. For long output, click **Load More** to reveal another group of lines or **Load All** to show the complete captured output. Click **Download Logs** to save non-empty output as a `.log` file. An execution can succeed without printing output. Verify the actual result of the command when output alone is not enough. *** Troubleshooting [#troubleshooting] Executions that exceed their timeout are marked failed with the timeout error. Lost queued scheduled tasks are recorded as failed and the team is notified. Refresh the task page to review the result. If the command regularly needs more time, increase **Timeout** and run it again. The dashboard accepts up to `36000` seconds. The command may not write to standard output or standard error. Check the effect the command was meant to produce. If you need a visible record, update the command or script so it prints a concise success or failure message. Confirm that the resource is running and that **Container name** or **Service name** matches the intended component. Save the task, then click **Execute Now**. # Manage Tasks (/docs/core/automation/scheduled-tasks/manage-tasks) Manage scheduled tasks [#manage-scheduled-tasks] Each application and service keeps its own scheduled tasks. Open a task to change its configuration or control whether it can run. Open a task [#open-a-task] 1. Open the application or service. 2. Select **Scheduled Tasks**. 3. Select the task you want to manage. The task page shows its configuration and recent executions. *** Update task configuration [#update-task-configuration] You can change the task's **Name**, **Schedule**, **Timeout (seconds)**, **Container** or **Service**, and **Command**. Click **Save changes** after making changes. Coolify validates the schedule before saving it. If you change the command or target container, run the task manually and review its output before relying on the next scheduled execution. *** Enable or disable a task [#enable-or-disable-a-task] Click **Disable** to stop future scheduled executions without deleting the configuration or its history. Click **Enable** when the task should run on its schedule again. Disabling a task does not stop an execution that is already running. *** Run a task now [#run-a-task-now] When the application or service is running, click **Execute now** to dispatch the task immediately. Manual execution uses the saved command, container, and timeout, but it does not change the task's next scheduled time. Open the new record under **Recent executions** to verify the result. If **Execute now** is not shown, start the resource first. *** Delete a task [#delete-a-task] Deleting a scheduled task removes its configuration from the resource, and its execution history is no longer available from the dashboard. Disable the task instead if you may need it again. 1. Open the task. 2. Click **Delete**. 3. Enter the scheduled task name shown in the confirmation dialog. 4. Click **Permanently Delete**. Coolify returns to the resource's **Scheduled Tasks** list, and the deleted task no longer runs. *** Troubleshooting [#troubleshooting] Confirm that the task is enabled, the application or service is running, and its server is validated and functional. Then compare **Schedule** with [Cron Syntax](/core/automation/cron-syntax) and the server timezone. Open the task and set **Container** or **Service** to the component that contains the command. Save the change before running the task again. # Overview (/docs/core/automation/scheduled-tasks/overview) Scheduled tasks overview [#scheduled-tasks-overview] Scheduled tasks let Coolify run a command inside an application or service container on a recurring schedule. Use them for work such as framework schedulers, queue maintenance, cache cleanup, and recurring imports. Add a task from an application's or service's **Scheduled Tasks** page. Choose the command, schedule, timeout, and target container. Coolify records the result and output of each run. *** What a scheduled task contains [#what-a-scheduled-task-contains] Each task has five main settings: * **Name** identifies the task in Coolify. * **Command** is the exact command Coolify runs inside the container. * **Frequency** controls when the command runs. It accepts a five-field cron expression or a supported named schedule. * **Timeout** limits how long one execution may run. * **Container name** selects where the command runs when the resource has more than one container. Read [Cron Syntax](/core/automation/cron-syntax) for supported fields, named schedules, and examples. *** How a task runs [#how-a-task-runs] Scheduled tasks, database backups, volume backups, and Docker cleanups each have their own scheduler process that dispatches due work every minute. A busy queue or slow schedule type does not delay dispatch of the others. Coolify evaluates the schedule in the timezone configured for the server that runs the resource. When the task is due, Coolify runs the command in a shell inside the selected running container. A scheduled execution is skipped when the task is disabled, the application or service is not running, or the connected server is not functional. A task with multiple containers also needs the correct container or service name. Fixed-time schedules run once when daylight saving time repeats an hour. One failing schedule does not prevent other due schedules from being dispatched. After Coolify starts a command, **Recent executions** shows its status, start and end times, duration, and captured output. *** Choose the next task [#choose-the-next-task] # Deploy by Tag (/docs/core/automation/tags/deploy-by-tag) Deploy resources by tag [#deploy-resources-by-tag] Deploy by tag when several applications and services should be started or redeployed as one group. Coolify acts on every resource assigned to the selected tag in the active team. Before deploying [#before-deploying] Open **Tags** in the main sidebar and select the tag. Review every application and service shown under **Tag Details**. If a resource does not belong in the deployment group, remove the tag from that resource before continuing. **Redeploy All** starts work for the full group. Resources can be temporarily unavailable while their deployment or restart is in progress. *** Redeploy from the dashboard [#redeploy-from-the-dashboard] Select the tag [#select-the-tag] Open **Tags** in the main sidebar, then select the tag you want to deploy. Review the group [#review-the-group] Check the applications and services listed under **Tag Details**. Select any resource card if you need to inspect its current configuration first. Start the deployment [#start-the-deployment] Click **Redeploy All**. Enter the tag name in the confirmation dialog, then click **Redeploy All** again. Coolify queues a deployment for each application and starts each service assigned to the tag. Verify the resources [#verify-the-resources] Watch **Deployments** on the tag page for queued and in-progress application deployments. Open each application deployment to inspect its logs. For services, open the service page and confirm that its components are running. *** Automate deployment with a webhook [#automate-deployment-with-a-webhook] The selected tag's **Deploy Webhook URL** calls the same team-scoped deployment API. Use it from CI or another automation system when you do not want to open the dashboard. Follow [Deploy Webhooks](/core/automation/deploy-webhooks) to create a token with `deploy` permission, call the URL, and verify the response. *** Troubleshooting [#troubleshooting] Open the resource's **Tags** page and confirm that the same tag is assigned. Also confirm that you are using the team where the tag was created. Confirm that the tag still has applications or services assigned. Application deployments appear in the tag's **Deployments** list; services must be checked from their resource pages. # Manage Tags (/docs/core/automation/tags/manage-tags) Manage tags [#manage-tags] Manage tags from the application or service that should belong to the group. Coolify creates a new team tag when the name does not exist and reuses an existing tag when it does. Add tags to a resource [#add-tags-to-a-resource] Open the resource [#open-the-resource] Open the application or service you want to tag, then select **Tags**. Enter one or more names [#enter-one-or-more-names] In **Create new or assign existing tags**, enter a tag name. To add several tags at once, separate the names with spaces: ```txt production storefront eu ``` Each name must contain at least two characters. Coolify removes HTML and stores the name in lowercase. Add the tags [#add-the-tags] Click **Add**. Newly created and reused tags appear under **Assigned Tags**. Open **Tags** in the main sidebar and select one of the assigned names. The resource should appear in that tag's details. *** Assign an existing tag [#assign-an-existing-tag] Tags from the active team that are not assigned to the resource appear under **Existing Tags**. Click a name to assign it without entering the name again. The same tag can be assigned to applications and services in different projects or environments within the team. *** Remove a tag [#remove-a-tag] Under **Assigned Tags**, click the remove icon beside the tag name. Coolify removes the tag from this resource immediately. Removing a tag does not stop, restart, or redeploy the resource. *** How unused tags are removed [#how-unused-tags-are-removed] Coolify removes a tag from the team after it is detached from its last application or service. There is no separate delete action on the main **Tags** page. If you want to keep a grouping, leave the tag assigned to at least one application or service. *** Troubleshooting [#troubleshooting] Use a name with at least two characters. Separate multiple names with spaces instead of commas. The resource already has that tag. Check **Assigned Tags** instead of adding the same name again. You need permission to update the resource before you can assign or remove tags. Ask a team administrator to update your role or make the change for you. # Overview (/docs/core/automation/tags/overview) Tags overview [#tags-overview] Tags group related applications and services across projects and environments. Use them to find a resource group and redeploy every resource in that group from one page or webhook. Add tags from a resource's **Tags** page. Then open **Tags** in the main sidebar to review the resources with a tag, redeploy them together, or copy the tag's deploy webhook URL. *** What tags do [#what-tags-do] A tag describes a relationship that matters to your team. For example: * `production` for resources that serve production traffic * `storefront` for an application and its supporting service * `eu` for resources deployed in one region * `release-group-a` for resources that should be redeployed together Tags do not change resource configuration, networking, or deployment order. They provide a shared grouping for navigation and bulk deployment. *** Tag scope [#tag-scope] Tags belong to the active team. A tag created in one team does not group resources from another team, and deploy webhooks only act on resources available to the token's team. Coolify stores tag names in lowercase. Within a team, resources that use the same name share the same tag. Bulk deployment by tag covers applications and services assigned to that tag. *** Manage and deploy tagged resources [#manage-and-deploy-tagged-resources] # Change Root Email (/docs/core/backup-and-recovery/change-root-email) Change Root Email [#change-root-email] Change the root email from the server terminal when the address is incorrect, inaccessible, or cannot receive Coolify's verification email. Coolify Cloud users cannot access the container that runs this command. To change a Coolify Cloud account email when you cannot use the dashboard, [contact the Coolify team](/support). Choose the right method [#choose-the-right-method] If you are signed in and your self-hosted instance can send transactional email, use the dashboard: 1. Open **Profile > General**. 2. Select **Change Email**. 3. Enter the new address and select **Send Verification Code**. 4. Enter the six-digit code sent to the new address, then select **Verify & Update Email**. Use the terminal procedure below when you cannot sign in, cannot access the current address, or have not configured transactional email. The terminal command changes the login email immediately and does not send a verification message. Before you change the email [#before-you-change-the-email] Make sure you have: * SSH access to the server that runs the self-hosted Coolify instance * permission to run Docker commands on that server * the root account's current password, or a plan to [reset the root password](/core/backup-and-recovery/reset-root-password) after changing the email * a correctly spelled email address that is not used by another account on the same Coolify instance The command does not check the email format or whether the mailbox can receive messages. Coolify saves the address in lowercase, and the instance database rejects an address already used by another Coolify account. Check the complete address before submitting it. Change the root email [#change-the-root-email] Connect to the Coolify server [#connect-to-the-coolify-server] Connect over SSH to the machine that runs the Coolify control plane: ```sh ssh root@ ``` Replace `` with the server's IP address. If you connect as a non-root user, that account must have permission to run Docker commands. Add `sudo` before the Docker commands below when your server requires it. Confirm that the Coolify container is running [#confirm-that-the-coolify-container-is-running] ```sh docker inspect --format '{{.State.Status}}' coolify ``` The command should print `running`. If Docker reports that the `coolify` container does not exist or is not running, [update or repair the Coolify installation](/core/instance-management/update) before continuing. Run the email-change command [#run-the-email-change-command] ```sh docker exec -it coolify php artisan root:change-email ``` Coolify displays this interactive prompt: ```console You are about to change the root user's email. Give me a new email for root user: ``` Enter the complete new email address. When Coolify saves it, the command prints: ```console Updating root email... Root user's email updated successfully. ``` The command updates only the root account's active login email. The current password, 2FA configuration, browser sessions, and API tokens remain unchanged. Coolify does not restart, and deployed applications, databases, and services continue running. Verify the new login email [#verify-the-new-login-email] Keep the current dashboard session open, if one is available. Open the Coolify login page in a private browser window and sign in with: * the new email address * the existing root password * the root account's two-factor authentication code, if 2FA is enabled You should be able to sign in to the root account with the new email address. You should no longer be able to sign in with the email address used before the command. Troubleshooting [#troubleshooting] If the command saved a misspelled or unintended address, do not edit the Coolify database directly. Run the same command again from the Coolify server: ```sh docker exec -it coolify php artisan root:change-email ``` Enter the correct address, wait for `Root user's email updated successfully.`, then repeat the private-window login check with the corrected address and existing password. First confirm that no other Coolify account already uses the new address. The `users` table requires every account email to be unique, but the command reports a generic failure when the database rejects a duplicate. Then confirm that the `coolify-db` container is running: ```sh docker inspect --format '{{.State.Status}}' coolify-db ``` If the command does not print `running`, repair the Coolify installation before retrying. If the database is running and the address is unique, keep the command output and [contact support](/support). Enter the new address in lowercase and use the root account's existing password. If the password is also unknown, follow [Reset Root Password](/core/backup-and-recovery/reset-root-password). If 2FA blocks the login after the email and password are accepted, follow [Reset 2FA](/core/backup-and-recovery/reset-2fa). # Back up Coolify (/docs/core/backup-and-recovery/instance-backup) Back up Coolify [#back-up-coolify] An instance backup saves Coolify's own data, including your projects, resources, settings, and deployment history. It does not back up data stored inside your applications, databases, or volumes. The Coolify team manages Coolify Cloud instance backups. You are still responsible for backing up the applications and databases deployed to your connected servers. For a self-hosted instance, open **Settings** in the left sidebar, then select **Backup**. If Coolify says instance backups are disabled, validate the server that runs Coolify: 1. Select **Open server settings**. 2. On the server page, select **Validate connection**. 3. After validation succeeds, open **Settings > Backup** again. The first time you open **Backup**, select **Configure backup**. Coolify then creates the backup configuration and turns on a daily backup schedule. Before you back up [#before-you-back-up] * Choose where you will keep a copy of the backup, such as another server or your computer. Do not keep the only copy on the Coolify server. * Save the instance `APP_KEY` as described below. Coolify uses this key to encrypt secrets stored in its database. *** Choose a backup path [#choose-a-backup-path] Use the dashboard while it is available. Use the terminal when the dashboard is unavailable or you need a backup that does not depend on the configured schedule. Create a backup from the dashboard [#create-a-backup-from-the-dashboard] **Queue the backup** Under **Backup schedule**, select **Back up now**. **Confirm the result** After you select **Back up now**, a new entry appears under **Executions**. Its status changes from **In Progress** to **Success** when the backup is ready. If it changes to **Failed**, read the message shown in the entry. Select **Download** while **Local Storage** is available to save a copy to your computer. Create a backup from the terminal [#create-a-backup-from-the-terminal] Run the following command on the server that hosts Coolify to create the backup file: ```sh mkdir -p /data/backups docker exec coolify-db \ pg_dump --format=custom --no-acl --no-owner \ --username=coolify coolify \ > /data/backups/coolify-db-manual-backup.dmp ``` Confirm that the file exists and is not empty: ```sh test -s /data/backups/coolify-db-manual-backup.dmp \ && ls -lh /data/backups/coolify-db-manual-backup.dmp ``` The backup is now stored at `/data/backups/coolify-db-manual-backup.dmp`. Copy it to another computer or server so it is not lost if the Coolify server fails. *** Save the instance encryption key [#save-the-instance-encryption-key] Coolify encrypts saved credentials and private keys before storing them in its database. The `APP_KEY` in `/data/coolify/source/.env` is the key used for that encryption. A database backup does not include this file. Save the `APP_KEY` before you need to restore the instance. Treat it like a password and do not publish or share it. On the server that hosts Coolify, display the key: ```sh grep '^APP_KEY=' /data/coolify/source/.env ``` Copy the complete `APP_KEY=...` line into a password manager or another secure place outside the Coolify server. S3 instance backups include only the database backup file, so you must save this key separately. *** Configure recurring backups [#configure-recurring-backups] The default **Frequency** is `0 0 * * *`, which creates one backup each day at midnight in the instance timezone. **Set the schedule** {/* */} Select **Enable backup** if the schedule is disabled. Select **Disable backup** to pause scheduled runs. Enter a valid cron expression in **Frequency**, or use `every_minute`, `hourly`, `daily`, `weekly`, `monthly`, or `yearly`. **Timezone** is read-only and uses the instance timezone. Set **Timeout** to the maximum backup runtime in seconds, then select **Save changes**. The accepted range is `60` to `36000`; the default is `3600` seconds. **Configure local retention** {/* */} Under **Retention > Local backups**, set any combination of these limits: * **Backups to keep** accepts `0` or a positive integer. * **Days to keep** accepts `0` or a positive integer. * **Maximum storage (GB)** accepts `0` or a positive number, including decimals. A value of `0` makes that limit unlimited. The limits work independently, and Coolify removes the oldest successful backups when any configured limit is reached. **Add an S3 copy** {/* */} Under **S3 storage**, select a validated **S3 storage** target, select **Enable S3**, then select **Save changes**. If no validated target exists, add and validate a storage target first. When S3 is enabled, **Retention > S3 backups** provides the same three independent limits for S3 copies. Set **Local copy** to **Delete after S3 upload** only when S3 should be the sole backup location. Keep **Keep local backup** to retain both copies. Coolify deletes the local file after a successful upload. If an S3 upload fails, Coolify keeps the local file and marks the execution **Success (S3 Warning)**. The dashboard cannot download a remote-only file. Download the backup from your S3 storage provider instead. *** Verify and manage backups [#verify-and-manage-backups] **Executions** shows the status, database name, size, location, and storage availability for each backup. For a usable backup, confirm that the execution shows **Success** and that at least one storage location is available. Local instance backups are stored under `/data/coolify/backups/coolify/coolify-db-/`; use the exact **Location** shown in the execution to find a specific file. The available actions depend on the execution: * **Download** saves the local backup to your computer. * **Delete** removes the local backup and can also remove its S3 copy when one exists. * **Clean failed backups** removes failed execution records. * **Clean deleted entries** removes execution records already marked as deleted from local storage. It does not delete backup files. Periodically check that you can access the copies stored on another server or your computer. Also confirm that you still have the saved `APP_KEY`. To test or perform recovery, follow [Restore a Coolify instance](/core/backup-and-recovery/instance-restore). # Restore Coolify (/docs/core/backup-and-recovery/instance-restore) Restore Coolify [#restore-coolify] Restoring Coolify replaces the instance database with a backup. It restores your projects, resources, settings, saved credentials, and deployment history. It does not restore data stored inside your applications, databases, services, or volumes. The Coolify team manages Coolify Cloud instance recovery. This guide is for self-hosted Coolify instances. Before you restore [#before-you-restore] Make sure you have: * a Coolify database backup file ending in `.dmp` * the value after `APP_KEY=` in `/data/coolify/source/.env` that you saved when you followed [Back up Coolify](/core/backup-and-recovery/instance-backup) * SSH access to the server where you will restore Coolify * the version number shown in the Coolify dashboard when the backup was created, if you saved it * when moving Coolify to another machine, access to `/data/coolify/ssh/keys/` and `~/.ssh/authorized_keys` on the original machine, or a separate backup of those files If the backup is in S3, download it from your S3 storage provider and copy it to the server where you will perform the restore. The restore command removes the current Coolify database objects before loading the backup. Do not continue unless the backup file and saved `APP_KEY` belong to the instance you want to recover. Prepare the restore target [#prepare-the-restore-target] Choose where you are restoring Coolify. Choose this option when you are restoring Coolify on the same machine where the instance was already installed. Confirm that the `coolify-db` container is running, then place the backup somewhere on that machine, such as `/data/backups/coolify-db-backup.dmp`. ```sh docker ps --filter name=coolify-db --format '{{.Names}} {{.Status}}' ``` The command should show `coolify-db` as running and healthy. Choose this option when you are moving Coolify to another machine. Install Coolify on the replacement machine before restoring the database. Use the version that was installed when the backup was created. ```sh curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash -s 4.1.2 ``` `4.1.2` is an example. Replace it with the version that was installed when the backup was created. If you do not know the previous version, install the latest stable release instead: ```sh curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash ``` Confirm that the fresh dashboard opens, then copy the database backup to the replacement server. Restore the instance [#restore-the-instance] Check the backup file [#check-the-backup-file] Confirm that the backup exists and is not empty: ```sh export BACKUP_PATH=/data/backups/coolify-db-backup.dmp test -s "$BACKUP_PATH" && ls -lh "$BACKUP_PATH" ``` Change the value of `BACKUP_PATH` if your backup is stored somewhere else. The restore command below uses this variable, so you only need to enter the file path once. Stop the Coolify control plane [#stop-the-coolify-control-plane] Stop the containers that can use the instance database, but keep `coolify-db` running: ```sh docker stop coolify coolify-redis ``` On releases from before the [Reverb migration](/core/instance-management/reverb-migration), also stop the `coolify-realtime` container. The dashboard will be unavailable during the restore. Deployed resources and Coolify Proxy keep running. Set the saved APP_KEY [#set-the-saved-app_key] Coolify needs the same `APP_KEY` value that was used when the database backup was created. Without it, Coolify cannot read encrypted credentials and private keys from the restored database. Open Coolify's environment file on the server where you are performing the restore: ```sh sudo nano /data/coolify/source/.env ``` Find the `APP_KEY=` line and replace its current value with the `APP_KEY` value you saved while following [Back up Coolify](/core/backup-and-recovery/instance-backup). If you are restoring Coolify on the original machine and the existing value already matches the saved value, leave the `APP_KEY=` line unchanged. On a replacement server, keep the rest of the new installation's `.env` file. Values such as `DB_PASSWORD` belong to the new installation and must continue to match its running containers. Restore the database [#restore-the-database] Run the restore while `coolify-db` is the only Coolify container using the database: ```sh docker exec -i coolify-db pg_restore \ --clean \ --if-exists \ --exit-on-error \ --no-acl \ --no-owner \ --username=coolify \ --dbname=coolify \ < "$BACKUP_PATH" ``` `--exit-on-error` stops the restore at the first error so a failed restore is not mistaken for success. Restore the SSH keys [#restore-the-ssh-keys] If the original key files are still under `/data/coolify/ssh/keys/`, skip this step. If those files were removed, restore them from a separate backup before continuing. Remove the keys created by the fresh Coolify installation: ```sh rm -f /data/coolify/ssh/keys/* ``` Copy the contents of `/data/coolify/ssh/keys/` from the original Coolify server into the same directory on the replacement server. If the original server is unavailable, use your separate backup of that directory. Make sure the corresponding public key from the original Coolify server is also present in `~/.ssh/authorized_keys` on the replacement server. Start Coolify [#start-coolify] Run the installer again. If you installed a specific Coolify version, include that version number: ```sh curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash -s 4.1.2 ``` `4.1.2` is an example. Replace it with the version you installed before restoring the database. If you installed the latest stable release, omit `-s 4.1.2`. The installer starts the Coolify containers and applies any required database migrations. Wait for the installation to finish before opening the dashboard. Verify the restore [#verify-the-restore] Open the Coolify dashboard after the installer finishes. Confirm that: * the dashboard opens without an encryption error * your projects, environments, and resources are present * **Servers > localhost** validates successfully * other managed servers connect successfully * recent deployments and instance settings appear as expected Application volume and database data are not part of an instance backup. Restore those resources from their own backups when needed. Troubleshooting [#troubleshooting] The active `APP_KEY` does not match the key used to encrypt the restored database. Stop `coolify`, confirm that `/data/coolify/source/.env` contains the saved `APP_KEY` value, then run the installer again. Current Coolify reads `APP_KEY`; do not add `APP_PREVIOUS_KEYS`. Keep the Coolify control-plane containers stopped and read the first error in the command output. Confirm that the file is a non-empty `.dmp` backup created by `pg_dump --format=custom`, then rerun the restore after correcting the problem. Confirm that the original SSH key files are under `/data/coolify/ssh/keys/` and that the matching public key from the original Coolify server is present in `~/.ssh/authorized_keys` on the replacement server. Open that server's **Private Key** page and confirm that the expected key is selected. Use **Copy public key** and make sure that public key still exists in the remote user's `~/.ssh/authorized_keys` file. An instance backup restores Coolify's own database only. Restore each application's volumes and each database resource from their separate backups. # Reset 2FA (/docs/core/backup-and-recovery/reset-2fa) Reset 2FA [#reset-2fa] Reset two-factor authentication (2FA) from the server terminal when an account cannot complete the 2FA challenge and has no usable recovery codes. The reset removes the account's current authenticator setup and recovery codes. It does not change the account password. Coolify Cloud users cannot access the container required for this procedure. If you cannot complete the 2FA challenge for a Coolify Cloud account, [contact the Coolify team](/support). Choose the right recovery method [#choose-the-right-recovery-method] Use the first method that is available: 1. Enter a current code from the account's authenticator app. 2. Enter one of the recovery codes saved when 2FA was configured. 3. If authenticator codes are rejected even though the correct account is selected in the app, check [2FA time synchronization](/troubleshoot/server/two-factor-stopped-working) before clearing the setup. 4. Use the terminal procedure below when the authenticator and recovery codes are unavailable. Before you reset 2FA [#before-you-reset-2fa] Make sure you have: * SSH access to the server that runs the self-hosted Coolify instance * permission to run Docker commands on that server * the email address of the affected account, unless you are resetting the root account * the account password required for the login check after the reset If you are resetting the root account and do not know its password, follow [Reset Root Password](/core/backup-and-recovery/reset-root-password) before verifying access. This procedure clears the selected account's authenticator secret and recovery codes. The existing authenticator entry and every recovery code for that account will stop working. Configure 2FA again after access is restored. Reset 2FA from the server [#reset-2fa-from-the-server] Connect to the Coolify server [#connect-to-the-coolify-server] Connect over SSH to the machine that runs the Coolify control plane: ```sh ssh root@ ``` Replace `` with the server's IP address. If you connect as a non-root user, that account must have permission to run Docker commands. Add `sudo` before the Docker commands below when your server requires it. Confirm that the Coolify container is running [#confirm-that-the-coolify-container-is-running] ```sh docker inspect --format '{{.State.Status}}' coolify ``` The command should print `running`. If it does not, [update or repair the Coolify installation](/core/instance-management/update) before continuing. Open Laravel Tinker [#open-laravel-tinker] Run Tinker inside the `coolify` container: ```sh docker exec -it coolify php artisan tinker ``` Wait for the `>` prompt before entering the PHP commands in the following steps. Select the affected account [#select-the-affected-account] Select the root account by user ID `0`: ```php $user = App\Models\User::find(0); ``` Replace `user@example.com` with the account's complete email address: ```php $user = App\Models\User::where('email', strtolower('user@example.com'))->first(); ``` Verify the selected account [#verify-the-selected-account] ```php $user?->only(['id', 'email', 'two_factor_confirmed_at']); ``` Tinker should print the expected user ID and email address. `two_factor_confirmed_at` normally contains a timestamp when 2FA is enabled. If Tinker prints `null` or shows a different account, do not continue. Select the correct account first. Clear the 2FA setup [#clear-the-2fa-setup] ```php $user->two_factor_secret = null; $user->two_factor_recovery_codes = null; $user->two_factor_confirmed_at = null; $user->save(); ``` The final command should return `true`. These assignments update only the selected account's 2FA fields. Verify the database update [#verify-the-database-update] ```php $user->refresh()->only([ 'two_factor_secret', 'two_factor_recovery_codes', 'two_factor_confirmed_at', ]); ``` Tinker should report `null` for all three fields: ```console [ "two_factor_secret" => null, "two_factor_recovery_codes" => null, "two_factor_confirmed_at" => null, ] ``` Exit Tinker: ```php exit; ``` Coolify does not need to restart after this update. Deployed applications, databases, and services are not affected. Verify account access [#verify-account-access] Open the Coolify login page in a private browser window. Sign in with the affected account's email address and password. You should be able to sign in without seeing the 2FA challenge. If the account is the root account and its email address is also unavailable, follow [Change Root Email](/core/backup-and-recovery/change-root-email). Configure 2FA again [#configure-2fa-again] After signing in: 1. Open **Profile > General**. 2. Under **Two-factor Authentication**, select **Configure**. 3. Add the new setup to your authenticator app and validate it with a current code. 4. Store the new recovery codes in a secure location outside the Coolify server. 5. Sign in through a private browser window again and confirm that the new authenticator code works. The authenticator secret and recovery codes cleared during the reset cannot be reused. Troubleshooting [#troubleshooting] For the root account, confirm that you used `App\Models\User::find(0)`. For another account, check the complete email address and run the lowercase email lookup again. Do not clear any fields until `$user?->only(...)` prints the account you intend to reset. Leave Tinker and confirm that the internal database container is running: ```sh docker inspect --format '{{.State.Status}}' coolify-db ``` The command should print `running`. If the database is running, reopen Tinker, select the account again, and repeat the update. If saving still fails, keep the error output and [contact support](/support). Reopen Tinker, select the same account, and repeat the database verification command. All three 2FA fields must report `null`. Then open a new private browser window and sign in again. A page that was already displaying the 2FA challenge may still show the previous login attempt. Resetting 2FA does not change the account password. For the root account, follow [Reset Root Password](/core/backup-and-recovery/reset-root-password). For another account, use **Forgot Password** when the instance can send transactional email. # Reset Root Password (/docs/core/backup-and-recovery/reset-root-password) Reset Root Password [#reset-root-password] Reset the root password from the server terminal when you cannot sign in to the root account and cannot use an emailed password-reset link. Coolify Cloud users cannot access the container that runs this command. If you cannot access your Coolify Cloud account, [contact the Coolify team](/support). Choose the right recovery method [#choose-the-right-recovery-method] Use the least disruptive method available: * If you are signed in and know the current password, open **Profile > General**, enter the current and new passwords under **Change Password**, then select **Save**. * If you can receive transactional email from the instance, select **Forgot Password** on the login page and use the emailed reset link. * If neither option is available, use the terminal procedure below. It does not require the current root password or a working email configuration. Before you reset the password [#before-you-reset-the-password] Make sure you have: * SSH access to the server that runs the self-hosted Coolify instance * permission to run Docker commands on that server * the root account's current login email, or a plan to [change the root email](/core/backup-and-recovery/change-root-email) after the reset * a strong, unique password ready to enter twice The terminal command checks only that both password entries match. It does not enforce the password rules used by the Coolify dashboard. Use a long, randomly generated password that you do not use for another account, and store it in a password manager. After the password changes, Coolify signs the root account out on every device and revokes every API token owned by that account. Sessions and API tokens for other users are not affected. Reset the root password [#reset-the-root-password] Connect to the Coolify server [#connect-to-the-coolify-server] Connect over SSH to the machine that runs the Coolify control plane: ```sh ssh root@ ``` Replace `` with the server's IP address. If you connect as a non-root user, that account must have permission to run Docker commands. Add `sudo` before the Docker commands below when your server requires it. Confirm that the Coolify container is running [#confirm-that-the-coolify-container-is-running] ```sh docker inspect --format '{{.State.Status}}' coolify ``` The command should print `running`. If Docker reports that the `coolify` container does not exist or is not running, [update or repair the Coolify installation](/core/instance-management/update) before continuing. Run the password-reset command [#run-the-password-reset-command] ```sh docker exec -it coolify php artisan root:reset-password ``` Coolify displays these interactive prompts: ```console You are about to reset the root password. Give me a new password for root user: Again: ``` Type the new password at the first prompt, then type the same password again. The terminal does not display the password while you type. When both entries match and the root account exists, Coolify prints: ```console Updating root password... Root password updated successfully. ``` The command updates only the root account password. It does not restart Coolify or interrupt deployed applications, databases, or services. Verify root access [#verify-root-access] Open the Coolify login page in a private browser window and sign in with: * the root account's current email * the new password * the root account's two-factor authentication code, if 2FA is enabled Using a private window verifies a fresh login without relying on an existing browser session. Existing root sessions should no longer open the dashboard after the password change. If an integration used an API token owned by the root account, create a replacement token after signing in and update that integration. The revoked token cannot be restored. If the reset fails [#if-the-reset-fails] The two entries were different, so Coolify did not change the password. Run the command again and enter the same value at both prompts. The instance database does not contain the root account at user ID `0`. Do not create or edit the database record manually. Confirm that you connected to the correct Coolify server, then [restore the instance database](/core/backup-and-recovery/instance-restore) from a known backup or [contact support](/support). Coolify found the command but could not save the new password. Confirm that the `coolify-db` container is running: ```sh docker inspect --format '{{.State.Status}}' coolify-db ``` If the command does not print `running`, repair the Coolify installation before retrying. If the database is running and the reset still fails, keep the command output and [contact support](/support). Confirm that you are using the root account's current email and the exact password entered in the terminal. If you no longer know or cannot use the root email, follow [Change Root Email](/core/backup-and-recovery/change-root-email), then try a fresh login again. If 2FA blocks the login after the password is accepted, follow [Reset 2FA](/core/backup-and-recovery/reset-2fa). # Build and Deployment Model (/docs/core/build-deployment-model) Build and deployment model [#build-and-deployment-model] Coolify turns source code, Docker configuration, or an existing image into running containers on a connected server. The exact path depends on whether Coolify builds an image, pulls one from a registry, or applies a Docker Compose definition. Coolify coordinates the deployment while Docker builds and runs the workload on your infrastructure. This page focuses on applications. Databases and one-click services use their own Docker lifecycle and do not follow every build path described here. Each deployment is a queued operation. Coolify resolves the requested source or image, prepares the runtime configuration, starts the required containers, and updates the running application according to the available replacement path. The result is a set of standard Docker resources on the connected server. Coolify is the open source control plane for deploying and managing them. *** What starts a deployment [#what-starts-a-deployment] An application deployment combines configuration saved in Coolify with a trigger such as **Deploy**, **Redeploy**, a Git webhook, or an API request. The application source determines whether a build is required before Coolify can start containers. *** From configuration to running containers [#from-configuration-to-running-containers] Coolify follows the same broad lifecycle even when the source and replacement paths differ. *** How Coolify prepares an image [#how-coolify-prepares-an-image] Every application container starts from a Docker image. Coolify can create that image from application source or use an image that already exists in a registry. For Git deployments that use Nixpacks, Railpack, Static, or Dockerfile, Coolify looks for an image tagged with the requested commit. If the image exists locally or in the configured registry and no build configuration changed, Coolify skips the build and reuses that image. Use **Force deploy (without cache)** when you need Coolify to rebuild the image without Docker's build cache. Server roles determine whether a machine can build, deploy, or do both. A deployment-only server never builds locally. A dedicated build server separates build load from the deployment server. Using a build server requires a registry image name so the deployment server can pull the completed image. Read [Build Server](/core/infrastructure/servers/build-servers) for the server and registry requirements. *** How Coolify replaces running containers [#how-coolify-replaces-running-containers] For source-based applications, Coolify completes the image build before changing the running containers. A failed source build leaves the current application version running. After the build finishes, or after Coolify prepares the existing image reference and runtime configuration, the replacement behavior depends on the application type and configuration. Configure a [health check](/applications/configuration/health-checks) when a rolling update must verify that the new container is ready. Without a configured or image-provided health check, Coolify cannot test application readiness before treating the new container as available. Open **Deployments** on the application to inspect each deployment status and its logs. After the application is running, use **Logs**, **Terminal** on non-Swarm servers, and the application lifecycle actions to operate the containers. *** What persists between deployments [#what-persists-between-deployments] Containers are replaceable. Persistent data must live outside the container's writable filesystem so a new container can use the same data. * **Build-time configuration** affects the image and can require a new build. * **Runtime configuration** is applied when the container starts, so Coolify can reuse the same image when only runtime settings change. * **Persistent volumes and mounted files** remain outside the replaceable container filesystem and are attached to the new container definition. * **Unmounted container data** is not persistent and can be lost when Coolify replaces or removes the container. Read [Docker and containers](/core/docker-and-containers) for the relationship between images, containers, volumes, and networks. # Docker and Containers (/docs/core/docker-and-containers) Docker and containers [#docker-and-containers] Coolify uses Docker to run applications, databases, and services on the servers you connect. Coolify coordinates the work; Docker provides the images, containers, storage, and networks that make each resource run. You do not need to manage Docker by hand for a first deployment. Understanding these Docker concepts helps you choose storage, follow deployment logs, and diagnose why a resource cannot start or connect. An image describes what to run. A container is a running instance of an image. Persistent storage keeps data outside the replaceable container. Networks connect containers, while a Docker Compose definition describes how multiple containers run together. Coolify prepares the container configuration and directs Docker to build or pull images, attach storage and networks, and start containers on the connected server. *** Core Docker concepts [#core-docker-concepts] Docker images, containers, storage, and networks follow standard Docker behavior. Docker Compose describes how containers, storage, and networks work together. Coolify translates your resource settings into Docker operations on the connected server. *** Images and containers [#images-and-containers] An image is the reusable package Docker uses to create a container. The image contains the application and the files it needs, but it is not a running application by itself. Based on your Coolify resource settings, Docker can build an application image from source code, pull a prebuilt image from a container registry, or start the images defined in a Docker Compose file. During a redeployment, Coolify may replace a container to apply a new image or configuration. The image remains reusable, while the new container receives the current resource settings. Read Docker’s guides to [images](https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-an-image/) and [containers](https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/) for more detail. *** Persistent data [#persistent-data] A container’s writable filesystem is not a safe location for data that must survive a redeployment. If Docker deletes and replaces the container, changes stored only in that filesystem disappear with it. Coolify persistent storage can use a named Docker volume or a bind mount from the server filesystem. Both types attach storage from outside the container to a path inside it. A redeployment preserves only data stored in configured persistent storage or an external system. Adding a mount later does not recover files from a container that has already been removed. Persistent storage is not a backup. Back up databases, uploads, and other important data separately. Read [Persistent Storage](/core/persistent-storage/storage-mounts/overview) to configure volume, bind, directory, and file mounts in Coolify. Docker’s [storage guide](https://docs.docker.com/get-started/docker-concepts/running-containers/persisting-container-data/) explains the underlying model. *** Networks and Docker Compose [#networks-and-docker-compose] Networks and Compose describe how containers fit together. Networks provide the connections; Compose records the desired multi-container configuration. Networks [#networks] Docker networks let containers communicate without exposing every service directly to the internet. Containers on the same network can reach the services they need. Containers on different, unconnected networks cannot communicate through those networks. Coolify creates or uses the networks required by each resource and connects the server proxy when HTTP routing is required. The proxy receives public traffic, then forwards it to the correct container over a Docker network. Read [Networking in Coolify](/core/networking-in-coolify) for domains, proxy modes, public ports, and internal service connections. Docker’s [networking guide](https://docs.docker.com/engine/network/) covers the underlying network drivers and behavior. Docker Compose [#docker-compose] A Docker Compose file describes one or more services and their images, environment variables, ports, storage mounts, networks, health checks, and dependencies. Coolify generates the Compose configuration needed for resources such as applications and databases. For a Docker Compose application or a one-click service, Coolify uses the Compose definition you provide or select. You do not need to write a Compose file for every resource. Compose defines the desired runtime configuration; it does not make container-local data persistent. Storage still needs a volume, bind mount, or external data service. Read Docker’s [Compose application model](https://docs.docker.com/compose/intro/compose-application-model/) for the relationship between services, networks, and volumes. *** Resource labels [#resource-labels] Coolify identifies resource containers with UUID labels: `coolify.applicationUuid`, `coolify.serviceUuid`, `coolify.service.subUuid`, and `coolify.databaseUuid`. Existing containers remain compatible and receive the new labels on their next deploy or restart. Update scripts that rely on the old numeric ID labels to use the corresponding UUID label. From configuration to running containers [#from-configuration-to-running-containers] *** Inspect Docker resources [#inspect-docker-resources] You can inspect Docker state without changing it. Connect over SSH to the server that runs the resource, then use the standard Docker listing commands: ```bash docker ps docker image ls docker volume ls docker network ls ``` These commands show resources on the current server only. If one Coolify instance manages several connected servers, run them on the server assigned to the resource you are checking. Check the self-hosted Coolify containers [#check-the-self-hosted-coolify-containers] Coolify itself also runs in containers when you self-host it. Run this command on the machine that hosts your Coolify instance: ```bash docker ps --filter "name=coolify" \ --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}" ``` Coolify Cloud users do not have access to the managed control plane host. You can inspect the workload servers connected to your Cloud account instead. Use direct Docker commands for inspection and carefully scoped debugging. Changes made directly to a Coolify-managed container can disappear when Coolify recreates it. Put lasting changes in the resource settings in Coolify or in the source Docker Compose file. *** Why standard Docker matters [#why-standard-docker-matters] Docker keeps the workload layer familiar and portable. You can use normal Docker concepts and inspection tools on the servers you control, and running resources remain standard Docker containers. If the Coolify control plane becomes unavailable, containers that are already running remain on their connected servers. Dashboard controls and deployment automation are unavailable until the Coolify instance returns. Read [How Coolify works](/core/how-coolify-works) for the relationship between the control plane, connected servers, Docker, and proxy traffic. *** Go deeper [#go-deeper] Continue with the part of the Docker model that affects your next deployment. # How Coolify works (/docs/core/how-coolify-works) How Coolify works [#how-coolify-works] Coolify separates platform control from workload runtime. The Coolify instance stores configuration and coordinates actions, while Docker on each connected server runs your applications, databases, and services. That separation determines where deployments run, how traffic reaches resources, what each backup contains, and what happens during an outage. You configure a resource in the Coolify dashboard or API. The Coolify instance connects to the selected server over SSH, then runs the Docker operations needed to build, deploy, and manage that resource. For HTTP resources, requests go to the reverse proxy on the server running the resource and then to its containers. The Coolify server does not relay your application traffic. You can run the Coolify server yourself or use Coolify Cloud. With self-hosted Coolify, you maintain the Coolify server. With Coolify Cloud, the Coolify team maintains it. In both setups, your applications, databases, and services run on servers you provide. *** The control path and traffic path [#the-control-path-and-traffic-path] Coolify sends deployment and management commands through the control path. Your users reach running HTTP resources through the application traffic path. A self-hosted Coolify server can also run deployed resources. In that setup, the Coolify server and resource containers share a machine but still run as separate containers. *** Parts of a Coolify setup [#parts-of-a-coolify-setup] A Coolify setup has four main parts. Coolify does not require a persistent deployment agent on a connected server. It uses SSH for deployments and server actions. The optional `coolify-sentinel` container adds monitoring data, but it does not replace SSH. Inside a self-hosted Coolify instance [#inside-a-self-hosted-coolify-instance] A standard self-hosted installation runs three base containers. | Container | Role | | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `coolify` | Serves the Coolify dashboard and API, processes queued jobs with Laravel Horizon, runs scheduled jobs, provides realtime updates with Laravel Reverb, and runs the browser terminal server. | | `coolify-db` | Runs PostgreSQL for Coolify configuration and state. | | `coolify-redis` | Supports queued work and caching. | The `coolify-proxy` and `coolify-sentinel` containers belong to the server runtime rather than this base control-plane stack. Coolify starts a reverse proxy on each server where it is enabled, while Sentinel remains optional. *** From configuration to running containers [#from-configuration-to-running-containers] The details vary by resource type, but most operations follow the same control path. Applications built from Git have more build stages than databases, one-click services, or prebuilt images. Read the [Build and deployment model](/core/build-deployment-model) for those resource-specific paths. *** How requests reach a resource [#how-requests-reach-a-resource] When an HTTP resource has a domain and uses the reverse proxy, a request follows this sequence: 1. DNS or an upstream network layer directs the domain to the connected server. 2. The reverse proxy on that server receives the request on port `80` or `443` and handles TLS when configured. 3. The reverse proxy matches the hostname and path, then forwards the request to the resource container over an attached Docker network. 4. The container handles the request and returns the response. The Coolify server does not relay these requests. If Coolify and the resource run on the same machine, the reverse proxy still sends each request directly to the resource container. If you disable the Coolify-managed reverse proxy for a server, you must provide the external routing and TLS path yourself. Non-HTTP resources can communicate over Docker networks or through explicitly published ports instead of this reverse proxy path. Read [Networking in Coolify](/core/networking-in-coolify) for Docker networks, reverse proxy options, domains, and your firewall responsibilities. *** Where configuration and data live [#where-configuration-and-data-live] Coolify configuration and workload data do not all live in one place. | Layer | Location | What it contains | | :--------------------------- | :---------------------------------------------- | :---------------------------------------------------------------------------------------------------------------- | | Coolify configuration | Coolify instance | Projects, environments, server and resource settings, credentials, and platform state used by the control plane. | | Deployment and runtime files | Connected server or build server | Generated deployment files, build artifacts, Docker images, containers, and networks used for that server's work. | | Resource data | Connected server or external storage | Docker volumes, bind mounts, and external storage used by applications, databases, and services. | | Reverse proxy state | Connected server with the reverse proxy enabled | The reverse proxy configuration and certificate data used to route traffic on that server. | An [instance backup](/core/backup-and-recovery/instance-backup) contains a copy of the Coolify database used by the control plane. Application files, database data, volumes, and external storage on connected servers are not part of an instance backup. *** When the Coolify instance is unavailable [#when-the-coolify-instance-is-unavailable] Already-running resources use Docker and the existing reverse proxy configuration. They do not need the Coolify server to handle each request. Losing SSH access has a similar boundary: Coolify cannot operate that server, but the SSH failure does not stop existing containers by itself. If the connected server, Docker daemon, reverse proxy, or upstream network fails, resources on that path can become unavailable even while the Coolify instance remains healthy. Standard Docker resources reduce platform lock-in because you can inspect and operate them directly. The Coolify instance still holds the configuration and automation that make them manageable as Coolify resources. Keep separate backups of the Coolify database and workload data. *** Continue learning [#continue-learning] Use the detailed Core pages to follow each part of the model. # Cloud Load Balancing (/docs/core/infrastructure/scaling/cloud-load-balancing) Cloud load balancing [#cloud-load-balancing] A cloud load balancer accepts traffic for your public domain and forwards each request to one of your application servers. Health checks allow the load balancer to stop sending traffic to an instance that cannot serve requests. Coolify deploys and manages the application instances. You configure the load balancer, backend targets, TLS settings, health checks, DNS, and network rules with your infrastructure provider. Before you begin [#before-you-begin] * Complete [Multi-server Deployments](/core/infrastructure/scaling/multi-server-deployments) and verify the application on every server. * Create a health endpoint that returns a successful response when the instance is ready to receive traffic. * Decide whether the load balancer will connect directly to a mapped host port or through the Coolify Proxy on each server. * Put the load balancer and application servers on a private network when your provider supports one. * Decide where TLS terminates. A common setup terminates TLS at the cloud load balancer and sends HTTP traffic over a private network to the application servers. The examples below use `app.example.com` as the public domain, port `443` on the load balancer, and `/health` as the health-check path. Replace them with values for your application. Choose how the load balancer reaches each server [#choose-how-the-load-balancer-reaches-each-server] | Origin path | Use when | Trade-off | | :---------------------------------------------------------- | :-------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Direct host port | The load balancer serves one application or you want to bypass the proxy on each application server | Requires a host port mapping and strict firewall rules; host port mappings disable Coolify rolling updates for that application | | Coolify Proxy | The application servers host several domains or you want Coolify-managed routing on each server | Adds one proxy hop and requires the load balancer to preserve the request host name | Map the same host port on every application server. For example, `8080:3000` maps port `8080` on each server to port `3000` in the application container. 1. Open **Configuration** > **General** for the application. 2. Add the mapping to **Ports Mappings**. 3. Remove the public domain from **Domains** because requests will bypass the Coolify Proxy. 4. Redeploy the application and test `http://:8080` from a network that can reach the server. 5. Add each server address and port `8080` as a backend target in the load balancer. A mapped host port can expose the application directly. Configure the provider firewall or server firewall so the port accepts traffic only from the load balancer or its private network. Keep the same HTTP domain on the application deployed to every server. The load balancer terminates public TLS, connects to port `80` on each server, and forwards the original `Host` header so the Coolify Proxy can select the correct route. 1. Open **Configuration** > **General** for the application. 2. Set **Domains** to the load-balanced domain with the `http://` scheme, such as `http://app.example.com`. 3. Redeploy the application to every server. 4. Add each server address and port `80` as a backend target in the load balancer. 5. Configure the load balancer to preserve `Host: app.example.com` when it sends a request to an application server. Before adding the servers to the load balancer, test each proxy route from a network that can reach the server: ```bash curl --header 'Host: app.example.com' http:///health ``` Do not add a host port mapping for this path. The Coolify Proxy must receive the request and forward it to the application container over its Docker network. Configure the load balancer [#configure-the-load-balancer] Create the load balancer with your infrastructure provider, then configure: 1. A public listener on port `443` with a certificate for `app.example.com`. 2. A backend pool containing every application server and the port selected above. 3. An HTTP health check for `/health` on the same backend port. For the Coolify Proxy path, configure the health check to send `Host: app.example.com`. 4. A forwarding policy or algorithm appropriate for your traffic. 5. Optional sticky sessions only when the application cannot yet keep session state in a shared store. The exact labels vary by provider. Confirm that a healthy response adds the server to rotation and a failed response removes it. Point DNS to the load balancer [#point-dns-to-the-load-balancer] At your DNS provider, point `app.example.com` to the public address or hostname supplied by the load balancer. Do not point the public record at one of the application servers. Wait for the DNS change to propagate, then open `https://app.example.com` and confirm that the certificate is valid. Verify traffic and failover [#verify-traffic-and-failover] 1. Confirm that every backend target is healthy in the load balancer dashboard. 2. Send several requests to `https://app.example.com` and check application logs on the servers to confirm that more than one instance receives traffic. 3. Stop the application on one additional server from **Configuration** > **Servers**. 4. Confirm that the load balancer marks that backend unhealthy and the public domain continues to respond through another server. 5. Deploy the stopped server again and confirm that it returns to the healthy backend pool. Operating considerations [#operating-considerations] * Adding or removing an application server in Coolify does not update the cloud load balancer. Keep its backend pool in sync with the application's **Servers** page. * Store sessions, uploads, queues, caches, and other shared state outside the application containers. * Restrict backend ports to the load balancer and required administrative networks. * Monitor the public endpoint from outside your infrastructure as well as the individual servers. * Test a complete server failure, not only a stopped container, before relying on the setup for availability. For a provider-specific example, read [Load Balancing on Hetzner](/knowledge-base/hetzner-loadbalancing). For a custom Traefik configuration instead of a provider-managed load balancer, read [Traefik Load-balancing](/core/networking/proxy/traefik/load-balancing). # Docker Swarm (Deprecated) (/docs/core/infrastructure/scaling/docker-swarm) Docker Swarm (deprecated) [#docker-swarm-deprecated] Coolify added Docker Swarm support as an experimental feature, and some parts of the integration were never fully implemented. Docker Swarm will be removed in Coolify v5. Existing Swarm deployments continue to work on Coolify v4, but you should not create a new Swarm deployment. Coolify v5 will replace Docker Swarm support with native Docker Compose replicas and Coolify's own scaling solution. Until that replacement is available, use [multi-server deployments](/core/infrastructure/scaling/multi-server-deployments) with an external load balancer for new infrastructure that must run across servers. Existing Coolify v4 deployments [#existing-coolify-v4-deployments] Coolify v4 keeps the existing Swarm controls for teams that already use Swarm. Other teams cannot enable it. Maintain an existing deployment while planning its replacement. On a server's **Swarm** page, Coolify identifies the server as either a Swarm manager or a Swarm worker. A node cannot be marked as both roles in the Coolify interface. For an application deployed to a Swarm destination, **Swarm Configuration** includes: * **Replicas** for the number of application tasks * **Only Start on Worker nodes** to prevent tasks from starting on manager nodes * **Custom Placement Constraints** for Docker Swarm placement rules These settings do not create the Swarm cluster. The manager and worker nodes must already belong to a working Docker Swarm. Registry and storage requirements [#registry-and-storage-requirements] An application deployed to a Swarm destination must have **Docker Image** configured. The manager pushes the built image to that registry, and every node that may run the application must be able to pull it. Authenticate the configured server user to the registry on the manager and worker nodes. See [Docker registries](/applications/builds/docker-registries#authenticate-a-private-registry). Local Docker volumes belong to one node. If a Swarm task can move between workers, use storage that is available from every eligible node, such as a shared network filesystem or an external storage service supported by the application. Check an existing cluster [#check-an-existing-cluster] Run the following command on a manager node: ```bash docker node ls ``` Confirm that: * one manager reports `Leader` in **MANAGER STATUS** * every required manager and worker reports `Ready` in **STATUS** * each node that may run the application reports `Active` in **AVAILABILITY** Then deploy the application from Coolify and verify the desired task count on a manager node: ```bash docker service ls ``` The value under **REPLICAS** should reach the configured replica count. Inspect the service with `docker service ps ` when a task does not start. Move away from Docker Swarm [#move-away-from-docker-swarm] Plan the replacement before upgrading to Coolify v5. Record the application's image, environment variables, domains, health check, storage, networks, and placement requirements. Then deploy the application to standalone servers and place a load balancer in front of them. Test the replacement through its public domain before removing the Swarm service. Keep the existing Coolify v4 deployment available until the new setup passes application, data, and failover checks. # Multi-server Deployments (/docs/core/infrastructure/scaling/multi-server-deployments) Multi-server deployments [#multi-server-deployments] Coolify can deploy the same application to a primary server and one or more additional standalone servers. This gives each server its own running instance of the application. Adding deployment servers does not distribute traffic by itself. After the application is running on every server, configure a [cloud load balancer](/core/infrastructure/scaling/cloud-load-balancing) or another external traffic layer in front of them. The application's **Servers** page does not support Docker Compose applications. Coolify also prevents you from adding another server when the application has persistent storage configured. Before you begin [#before-you-begin] Prepare the application and servers before attaching another deployment destination. * Add and validate every server in Coolify. Follow [Add Server](/core/infrastructure/servers/add-server) for each new server. * Use servers with the same CPU architecture, such as AMD64 or ARM64, so every server can run the same image. * Use the same [proxy](/core/networking/proxy/overview) type, Traefik or Caddy, on every server that has a proxy. Coolify generates the proxy labels for the primary server and uses them on every server, so Traefik labels do not work on a Caddy server and the reverse. A server without a proxy can still be attached. * Make application state available outside the containers. Use shared or external services for databases, sessions, queues, caches, and uploaded files. * Create a Docker registry repository that the primary server, any build server, and every additional server can access. * Authenticate the SSH user configured in Coolify to that registry on every server that must push or pull the image. See [Docker registries](/applications/builds/docker-registries#authenticate-a-private-registry). Configure the application image [#configure-the-application-image] 1. Open the application in Coolify. 2. Select **General**. 3. Under **Container image**, enter the full registry repository in **Image**. For example: ```text ghcr.io/example/acme-web ``` 4. Save the application settings. Coolify requires **Image** before it can deploy an application to additional servers. During a deployment, the primary server or configured build server builds the image and pushes it to the registry. The additional servers then pull the same image. Add deployment servers [#add-deployment-servers] 1. Open the application. 2. Select **Servers** in its sidebar. 3. Under **Add another server**, select the server and network you want to attach. 4. Repeat the selection for each additional server. The server originally selected for the application remains the **Primary Server**. Each attached server appears under **Additional Server(s)**. If no server is available to attach, confirm that the candidate server is validated, usable, belongs to the same team, and has a standalone Docker destination. A server already attached to the application is not shown again. Coolify rejects a server that uses a different proxy type than the primary server. If an application already has such a server, each deployment log shows a warning, and the application domains do not work through the proxy on that server. Change the proxy type on that server to match the primary server, then deploy again. Deploy and verify [#deploy-and-verify] Deploy the application after attaching all required servers. 1. Select **Deploy** from the application page. 2. Follow the deployment logs. Confirm that Coolify pushes the built image to the configured registry and starts a deployment for each attached server. 3. Open **Servers** and confirm that the primary and additional servers show a running status. 4. Test every server through the origin path you plan to use before adding it to a load balancer. If an additional server cannot pull the image, log in from that server’s **Registries** page, then deploy again. Additional servers pull the primary server’s published image instead of building it; commit, rollback, and image tag match the primary deployment. Coolify sends one deployment notification after all servers finish. Manage deployment servers [#manage-deployment-servers] The **Servers** page provides actions for each attached server: * **Deploy** deploys the application to only that server. * **Stop** stops the application on that server. * **Promote to Primary** makes an additional server the primary deployment destination. The former primary server becomes an additional server. * **Remove from server** stops the application on that server and removes the deployment destination after you confirm the server name. Normal application-wide deploy, restart, and stop actions include the primary and additional servers. Stop attempts every server even if one is unreachable. Existing configurations that combine multiple servers with persistent storage or Compose receive a deployment-log warning. A pull request preview is not deployed to the additional destinations. What multi-server deployment does not provide [#what-multi-server-deployment-does-not-provide] Attaching servers gives you multiple application instances, but it does not create a complete highly available system. You must still configure: * a load balancer with health checks * DNS for the public domain * firewall or security-group rules for the application servers * shared data and session storage * monitoring for the application and every server Continue with [Cloud Load Balancing](/core/infrastructure/scaling/cloud-load-balancing) to route traffic across the deployed instances. # Overview (/docs/core/infrastructure/scaling/overview) Scaling overview [#scaling-overview] Scaling an application can mean giving one server more capacity, running the application on more than one server, or distributing traffic across those servers. Coolify can deploy the same application image to multiple connected servers. A cloud load balancer can then direct requests to the healthy application instances. Coolify does not create or manage that external load balancer for you. Add infrastructure when load, availability requirements, or measured bottlenecks justify it. A single appropriately sized server is easier to operate than a multi-server deployment. Choose a scaling path [#choose-a-scaling-path] | Need | Approach | Start here | | :------------------------------------------------------------------- | :----------------------------------------------------------------------- | :-------------------------------------------------------------------------------- | | More CPU, memory, or storage for the current workload | Resize the current server or move the resource to a larger server | [Servers overview](/core/infrastructure/servers/overview) | | Run the same application on several standalone servers | Attach additional deployment servers to the application | [Multi-server Deployments](/core/infrastructure/scaling/multi-server-deployments) | | Distribute public traffic and remove unhealthy servers from rotation | Put a provider-managed load balancer in front of the application servers | [Cloud Load Balancing](/core/infrastructure/scaling/cloud-load-balancing) | | Maintain an existing Docker Swarm deployment on Coolify v4 | Continue only as a temporary legacy setup | [Docker Swarm (Deprecated)](/core/infrastructure/scaling/docker-swarm) | Multi-server deployment and load balancing solve different parts of the same architecture. Coolify deploys a consistent application image to each attached server. The load balancer decides which server receives each incoming request. What Coolify handles [#what-coolify-handles] For a supported multi-server application, Coolify: * keeps one server as the primary deployment server * builds the application on the primary server or a configured build server * pushes the built image to the Docker registry configured for the application * deploys that image to the additional servers attached to the application * lets you deploy, stop, remove, or promote individual servers from the application's **Servers** page You remain responsible for: * configuring the external load balancer and its health checks * securing traffic between the load balancer and application servers * keeping sessions, uploads, and other application state available to every instance * operating shared databases, caches, queues, and file storage * monitoring capacity and deciding when to add or remove servers Prepare the application [#prepare-the-application] Horizontal scaling works best when any application instance can serve any request. Before adding servers: 1. Move session state, user uploads, queues, and caches out of the container filesystem. 2. Use a database and storage location reachable from every application server. 3. Add a health endpoint that returns a successful response only when the instance can serve traffic. 4. Confirm that the application can run from the same image and configuration on every server. 5. Decide where TLS terminates and how the load balancer reaches each server. Applications with persistent storage configured in Coolify cannot use the current multi-server deployment feature. Docker Compose applications also cannot attach additional deployment servers through the application's **Servers** page. Related scaling guides [#related-scaling-guides] This section covers infrastructure-level scaling across servers. For a provider-specific example, read [Load Balancing on Hetzner](/knowledge-base/hetzner-loadbalancing). To use multiple CPU cores for a Node.js process on one server, read [Node.js Multi-core Scaling](/knowledge-base/nodejs-multi-core-scaling). # Add Server (/docs/core/infrastructure/servers/add-server) Add a server manually [#add-a-server-manually] Use the **IP address or domain** server flow when you already have a Linux server. Coolify connects to it through SSH and prepares it to run applications, databases, and services. To purchase and create a server from the Coolify dashboard instead, follow [Provision a Cloud Server](/core/infrastructure/servers/provision-cloud-server). What you need [#what-you-need] Before you start, make sure you have: * a Linux server with an IP address or hostname that Coolify can reach * console or password access to the server * an open SSH port, usually port `22` * access to the Coolify dashboard This guide uses the `root` account. To connect with another account, complete the [Non-root User](/core/infrastructure/servers/non-root-user) setup first. If the server does not have a public IP address, or you do not want to expose SSH publicly, connect it through [Server SSH Access via Cloudflare Tunnels](/integrations/networking/cloudflare/tunnels/server-ssh). Server validation can install Docker and restart the Docker service. Existing containers may be temporarily unavailable. *** Create and authorize an SSH key [#create-and-authorize-an-ssh-key] Coolify must have a private key whose public key is authorized for the server account. Create the key in Coolify [#create-the-key-in-coolify] 1. Open **Keys & Tokens > Private Keys**. 2. Open **New private key** and select **Generate ED25519**. 3. Select the generated key's **Edit** icon. 4. Give it a recognizable name and select **Save changes**. 5. Copy the complete **Public key**. Do not add a passphrase. Coolify must use the private key without an interactive prompt. Authorize the public key on the server [#authorize-the-public-key-on-the-server] Connect to the server: ```sh ssh root@ ``` If SSH uses a port other than `22`, run: ```sh ssh -p root@ ``` Create the SSH directory and open the authorized-keys file: ```sh mkdir -p ~/.ssh chmod 700 ~/.ssh nano ~/.ssh/authorized_keys ``` Paste the complete public key on a new line, save the file, then run: ```sh chmod 600 ~/.ssh/authorized_keys ``` You can also generate or import a private key from the **New key** menu beside **Private key** in the server form. The matching public key must still be present in the server user's `~/.ssh/authorized_keys` file before validation. *** Connect the server [#connect-the-server] Open the server form [#open-the-server-form] 1. Select **Servers** in the Coolify sidebar. 2. Select **New server**. 3. Select **IP address or domain**. Enter the connection details [#enter-the-connection-details] | Field | What to enter | | :----------------------- | :------------------------------------------------------------------------------------------------------------- | | **Name** | A name you will recognize, such as `production-server`. | | **Description** | Optional information about the server's purpose. | | **IP address or domain** | A reachable IP address or hostname. Do not include `http://` or `https://`. | | **Port** | The SSH port, usually `22`. | | **User** | Enter `root` for this guide. | | **Private key** | Select the key whose public key you authorized on the server. | | **Server role** | Select **Deployments and builds**, **Deployments only**, or **Builds only** according to the server's purpose. | Expand **Advanced settings** to access **User**, **Port**, and **Server role**. Choose **Deployments and builds** for a server that builds and runs resources, or **Deployments only** to keep builds on other servers. Choose **Builds only** for a dedicated build server. See [Server roles](/core/infrastructure/servers/build-servers#server-roles). Select **Continue**. Coolify creates the server record and opens its **General** page. Validate the server [#validate-the-server] Select **Validate connection** to open the validation panel. After a successful validation, the action is **Revalidate connection**. During validation, Coolify: 1. tests the SSH connection 2. checks the operating system and required tools 3. installs or verifies Docker Engine and Docker Compose 4. records server information 5. starts the Coolify proxy The process can take several minutes on a new server. Confirm the server is ready [#confirm-the-server-is-ready] Wait until the **General** page reports that the server is reachable and validated. The server can then be selected as a deployment destination. If validation reports an SSH error: * confirm the IP address or domain, port, and user * confirm the selected private key matches the public key in the user's `~/.ssh/authorized_keys` file * confirm the SSH port is open in the [firewall](/core/infrastructure/servers/firewall) * follow [OpenSSH](/core/infrastructure/servers/openssh) to check the SSH service *** Set a wildcard domain [#set-a-wildcard-domain] After validation, you can set **Wildcard Domain** under **General**. For example, `https://example.com` lets Coolify suggest a domain such as `https://.example.com` for a new resource. Create a DNS record for `*.example.com` that points to this server before using the generated domains. The setting does not change existing resource domains, update DNS, or change how Coolify connects to the server. *** Oracle Cloud (free ARM) notes [#oracle-cloud-free-arm-notes] Oracle Cloud free ARM servers need a few extra steps before Coolify can use them, whether as the Coolify host or as a remote server. **Use the root user.** Oracle images disable root login by default. To enable it: 1. Switch to root: `sudo su -` 2. In `/etc/ssh/sshd_config`, set `PermitRootLogin` to `without-password`. 3. Restart SSH: `service sshd restart` 4. Add the public key of the [SSH key configured in Coolify](#create-and-authorize-an-ssh-key) to `/root/.ssh/authorized_keys`. **Or use a non-root user.** A non-root user works with passwordless `sudo` (experimental). Add the Coolify SSH key to the user's `~/.ssh/authorized_keys`, then follow [Non-root User](/core/infrastructure/servers/non-root-user). **Open the firewall.** Oracle ARM servers enable a firewall by default. If you self-host Coolify on the server, open the required ports — see [Firewall](/core/infrastructure/servers/firewall). # Automated Docker Cleanup (/docs/core/infrastructure/servers/automated-docker-cleanup) Automated Docker cleanup [#automated-docker-cleanup] Docker stores images and build files on the server. Over time, unused files can fill the disk and prevent deployments from completing. Coolify can clean the server automatically on a schedule or when disk usage reaches a limit. Docker cleanup can be CPU-intensive while it scans and removes unused data. If the server has limited CPU resources, schedule cleanup less frequently and run it when applications receive less traffic. *** Configure Docker cleanup [#configure-docker-cleanup] Open Docker Cleanup [#open-docker-cleanup] 1. Open **Servers** in the Coolify sidebar. 2. Select the server you want to clean. 3. Select **Docker Cleanup** in the server menu. The page shows the cleanup settings and recent cleanup executions. Choose when cleanup runs [#choose-when-cleanup-runs] Start with these settings: * Keep **Cleanup frequency** at `0 0 * * *` to check once each day at midnight. * Set **Cleanup trigger** to **Run on every schedule** if you want cleanup to run every time the schedule is due. * Set **Cleanup trigger** to **Only above disk threshold** if cleanup should wait until disk usage reaches **Disk threshold**. * Keep the threshold at `80` unless you need cleanup to start sooner. Select **Save changes** after changing the schedule or threshold. Keep volume and network deletion disabled. Leave application image retention enabled. This removes common unused Docker data without deliberately pruning persistent volumes or every rollback image. Choose what Coolify may delete [#choose-what-coolify-may-delete] Under **Advanced cleanup**, the defaults keep unused volumes, unused networks, and retained application images: | Setting and choice | What happens | | :--------------------------------------------- | :------------------------------------------------------------------------------------ | | **Unused volumes > Delete unused volumes** | Deletes every Docker volume that is not currently attached to a container. | | **Unused networks > Delete unused networks** | Deletes every Docker network that is not currently used by a container. | | **Application images > Delete all old images** | Removes old application images instead of keeping the configured number for rollback. | A stopped or removed container can leave an unused volume containing application or database data. Back up important data and identify every volume before enabling **Unused volumes > Delete unused volumes**. Keep **Keep unused volumes**, **Keep unused networks**, and **Keep retained images** selected unless you have confirmed the unused objects can be deleted. Run a manual cleanup [#run-a-manual-cleanup] Use a manual cleanup to confirm the settings before relying on the schedule: 1. Review the three advanced cleanup options. 2. Select **Run cleanup** and review the confirmation, then select **Run Docker Cleanup**. 3. Wait for the execution to finish. A manual cleanup does not wait for the schedule or disk threshold. If another cleanup is running, it waits for that execution instead of being dropped. Only one cleanup runs per server at a time. Review the result [#review-the-result] Open **Recent executions** and select the latest cleanup. Confirm that: 1. the execution completed successfully 2. the command output does not show an unexpected error 3. disk usage decreased when unused data was available 4. important applications and databases still work 5. the application rollback images you expect are still available Cleanup after resource operations [#cleanup-after-resource-operations] Stopping or deleting a resource triggers Docker cleanup only when disk usage is at or above the configured cleanup threshold and no cleanup has completed in the last hour. Scheduled cleanup is dispatched every minute by its own scheduler process. Lost queued cleanup jobs are recorded as failed and the team is notified. # Build Servers (/docs/core/infrastructure/servers/build-servers) Build servers [#build-servers] A build server builds application images on a separate machine. The completed image is pushed to a container registry, then the deployment server pulls and runs it. By default, Coolify builds an application on the same server where the application will be deployed. Add a build server when builds use too much CPU, memory, or disk space on the deployment server. Server roles [#server-roles] Set **Server role** in the server's **General** settings: | Role | Behavior | API value | | :--------------------- | :------------------------------------------------------------------------------------------------------ | :----------- | | Deployments only | Runs resources; images must be built elsewhere. Applications need a Docker image name. | `deployment` | | Builds only | Builds images for other servers; cannot host resource deployments. Required for GitHub Actions runners. | `build` | | Deployments and builds | Builds images and runs resources on this server. | `both` | The API uses `server_role`. The deprecated `is_build_server` field remains compatible, but use `server_role` for new integrations. Under **Team**, configure **Build server fallback** to choose whether builds may fall back to a deployment server when no build server is usable. The server must have a role that allows builds. Disable fallback if builds must stay off deployment machines. What you need [#what-you-need] Before you start, make sure you have: * a fresh remote server that is not running applications, databases, or services * Docker Engine on the build server, or permission for Coolify to install it * a container registry where Coolify can push the completed image * the registry repository for the application, such as `ghcr.io/example/my-app` * access to the application's source repository The build server should use the same CPU architecture as the deployment server. A server marked as a build server cannot be selected as a deployment destination. Do not enable this setting on a server that runs applications, databases, or services. *** Configure a build server [#configure-a-build-server] Choose whether you are adding a new server or using a server that is already connected to Coolify. Prepare the SSH key [#prepare-the-ssh-key] Complete [Create and authorize an SSH key](/core/infrastructure/servers/add-server#create-and-authorize-an-ssh-key) before opening the server form. Open the Servers page [#open-the-servers-page] 1. Open the Coolify dashboard. 2. Select **Servers** in the sidebar. 3. Select **New server**. 4. Select **IP address or domain**. Add the build server [#add-the-build-server] 1. Enter the server name, IP address or domain, SSH port, user, and private key. 2. Expand **Advanced settings** and set **Server role** to **Builds only**. 3. Select **Continue**. Coolify adds the server and opens its **General** page. Validate the build server [#validate-the-build-server] 1. Select **Validate connection**. 2. Keep the page open while Coolify validates the SSH connection and prepares Docker. 3. Wait for the page to show **Server is reachable and validated**. Confirm that the server has no resources [#confirm-that-the-server-has-no-resources] 1. Open **Servers** in the Coolify sidebar. 2. Select the server you want to use. 3. Open **Resources > Managed**. 4. Confirm that the page says **No managed resources found**. If the server has managed resources, move or delete them before continuing. Coolify disables the build-server setting while resources are connected to the server. Enable the build-server role [#enable-the-build-server-role] 1. Open **General** for the server. 2. Expand **Advanced settings** and set **Server role** to **Builds only**. The setting saves immediately. The server can no longer be selected as a deployment destination while it remains a build server. When more than one usable build server is available, Coolify selects one at random for each build. Build servers can also run the GitHub Actions workflow jobs of your organization. Refer to [GitHub Actions runners](/core/infrastructure/servers/github-actions-runners). *** Sign in to the container registry [#sign-in-to-the-container-registry] Use **Servers > \[server] > Registries** to log in on the build server and deployment server. See [Registry login](/applications/builds/docker-registries#authenticate-a-private-registry) for presets and credential updates. The SSH procedure below remains available. Connect to the build server [#connect-to-the-build-server] Connect with the same SSH user configured on the server's **General** page: ```sh ssh @ ``` Replace `` and `` with the values used by your server. If the server uses an SSH port other than `22`, run: ```sh ssh -p @ ``` Log in to the registry [#log-in-to-the-registry] ```sh docker login ``` Replace `` with the registry hostname, such as `ghcr.io`. Enter the registry username and access token when prompted. The login creates `~/.docker/config.json` for the current SSH user. Coolify requires this file on the build server. If the registry repository is private, log in to the registry on the deployment server as well so it can pull the completed image. *** Configure an application to use the build server [#configure-an-application-to-use-the-build-server] Open the application General page [#open-the-application-general-page] 1. Open **Projects** in the Coolify sidebar. 2. Select the project and environment. 3. Select the application that should use the build server. 4. Open **General**. Enter the Docker image [#enter-the-docker-image] Enter the full registry repository in **Docker Image**, for example `ghcr.io/example/my-app`. Select **Save** after entering the image. Coolify cannot deploy with a build server until **Docker Image** is set. Enable the build server [#enable-the-build-server] 1. Find **Use a Build Server?**. 2. Enable the setting. The setting saves immediately. It is not available for Docker Compose applications. Deploy the application [#deploy-the-application] Start a new deployment and open the deployment logs. When Coolify selects a build server, the log shows: ```console Found a suitable build server (). ``` Wait for the deployment to finish, then confirm: 1. the completed image appears in the container registry 2. the application runs on its deployment server 3. the application opens from its configured domain If no usable build server is available, Coolify builds on the deployment server only when the team enables **Build server fallback** and that server permits builds. A **Deployments only** server never builds images itself. # Docker Images (/docs/core/infrastructure/servers/docker-images) Docker images [#docker-images] Open **Servers > \[server] > Images** to inspect images stored on that server. The page shows repository, tag, image ID, creation time, size, and containers that use each image. Search by repository, tag, or ID and use **Refresh** after changes. **Total** shows image disk usage and **Reclaimable** shows space Docker can recover. Images with no container references are marked **Unused**. Delete an unused image [#delete-an-unused-image] 1. Find an image marked **Unused** and review its reference. 2. Select its delete action. 3. Type the requested image reference and confirm. 4. Refresh the list and check reclaimable space. Only unused images can be deleted here. A future deployment may need to pull or rebuild a removed image. Use [Docker cleanup](/core/infrastructure/servers/automated-docker-cleanup) for scheduled cleanup. # Firewall (/docs/core/infrastructure/servers/firewall) Firewall [#firewall] Coolify needs inbound ports for SSH connections, web traffic, dashboard updates, and the web terminal. The required ports depend on whether you use self-hosted Coolify or Coolify Cloud. Self-hosted users must also choose whether they are configuring the Coolify server or a remote server. Do not remove the SSH rule while configuring the firewall. A wrong SSH rule can lock you out of the server. Choose the correct ports [#choose-the-correct-ports] Server running Coolify [#server-running-coolify] Use these ports on the server where the self-hosted Coolify instance is installed. | Port | Used for | | :-------------------------------------------------- | :------------------------------------------------------------------ | | `8000/tcp` | Direct access to the Coolify dashboard at `http://:8000` | | `6001/tcp` | Real-time dashboard updates when using direct IP access | | `6002/tcp` | Coolify web terminal when using direct IP access | | `22/tcp` | SSH access, unless you configured a different SSH port | | `80/tcp` | HTTP traffic and certificate generation through the Coolify proxy | | `443/tcp` | HTTPS traffic through the Coolify proxy | After the dashboard works through a domain using the Coolify proxy, you can close public access to ports `8000`, `6001`, and `6002`. The dashboard, real-time connection, and terminal will use ports `80` and `443` through the proxy. Remote server connected to self-hosted Coolify [#remote-server-connected-to-self-hosted-coolify] Use these ports on a remote server managed by your self-hosted Coolify instance. | Port | Used for | | :-------------------------------------------------- | :---------------------------------------------------------------------------------- | | `22/tcp` | SSH connection from the server running Coolify, unless you use a different SSH port | | `80/tcp` | Public HTTP traffic and certificate generation | | `443/tcp` | Public HTTPS traffic | Restrict the SSH rule to the public IP address of the server running Coolify when possible. Ports `80` and `443` are only needed when this server runs applications or services that receive public web traffic. Remote server connected to Coolify Cloud [#remote-server-connected-to-coolify-cloud] Use these ports on a server managed from Coolify Cloud. | Port | Used for | | :-------------------------------------------------- | :--------------------------------------------------------------------- | | `22/tcp` | SSH connection from Coolify Cloud, unless you use a different SSH port | | `80/tcp` | Public HTTP traffic and certificate generation | | `443/tcp` | Public HTTPS traffic | Restrict the SSH rule to the published Coolify Cloud source addresses: * [Coolify Cloud IPv4 addresses](https://coolify.io/ipv4.txt) * [Coolify Cloud IPv6 addresses](https://coolify.io/ipv6.txt) Ports `80` and `443` are only needed when this server runs applications or services that receive public web traffic. Do not open ports that your server does not use. *** Configure the firewall [#configure-the-firewall] Use the hosting provider firewall [#use-the-hosting-provider-firewall] Most hosting providers include a network firewall in their dashboard. Use that firewall when it is available because it blocks unwanted traffic before the traffic reaches your server. 1. Open the firewall, security group, or inbound-rule settings in the hosting provider dashboard. 2. Add the TCP rules from the section above. 3. Attach the firewall to the correct server. 4. Restrict the SSH rule to the Coolify source address whenever possible. 5. Allow ports `80` and `443` from `0.0.0.0/0` and `::/0` only when the server receives public web traffic. Use ufw-docker when no provider firewall is available [#use-ufw-docker-when-no-provider-firewall-is-available] Docker adds NAT and iptables rules for published container ports. These rules can bypass the normal rules created by UFW. Blocking a port with UFW does not guarantee that a Docker-published port is blocked. Do not rely on plain UFW to protect resources. Use [ufw-docker](https://github.com/chaifeng/ufw-docker) when the hosting provider does not offer a firewall. It is a community-maintained tool that makes UFW rules apply to Docker-published ports. Follow the installation and rule instructions in the ufw-docker repository. Keep the current SSH session open while changing firewall rules, then check the result from another machine before closing the session. Troubleshooting [#troubleshooting] Check whether a rule created with ufw-docker uses the IP address of the `coolify` container. A container can receive a different IP address when it is recreated during a Coolify update, [server patch](/core/infrastructure/servers/server-patching), or reboot. The rule then continues pointing to the old IP address and blocks access to Coolify. Remove the rule that uses the old container IP address. Replace it with a rule for the required destination port so the rule continues working when the container IP changes. Check whether the firewall rule uses the IP address of an application container. An application container can receive a different IP address when it is restarted or redeployed. For applications accessed through a domain, allow ports `80` and `443` for the Coolify proxy instead of creating rules for individual application container IP addresses. If the application uses a public port mapping, create the ufw-docker rule for that destination port without using a fixed container IP address. Restrict Coolify ports with a Compose override [#restrict-coolify-ports-with-a-compose-override] This option is only for the server running a self-hosted Coolify instance. It changes how ports `8000`, `6001`, and `6002` are published by Coolify's own containers. The Compose files for Coolify are stored in `/data/coolify/source` on the server running Coolify. Create the override as `/data/coolify/source/docker-compose.custom.yml`. This does not replace the firewall rules required for SSH, applications, databases, or services. Complete these steps only after the Coolify dashboard, real-time updates, and web terminal work through your configured domain. Removing the public port bindings before the domain works can lock you out of Coolify. Coolify updates replace `/data/coolify/source/docker-compose.yml` and `/data/coolify/source/docker-compose.prod.yml`. Changes made directly to those files will be reset during an update. The `docker-compose.custom.yml` file is loaded automatically and is not replaced by a Coolify update. Connect to the Coolify server [#connect-to-the-coolify-server] Connect through SSH to the server where self-hosted Coolify is installed. Open the Coolify source directory [#open-the-coolify-source-directory] ```sh cd /data/coolify/source ``` This directory contains the base Compose files used to run Coolify. Create the custom Compose file [#create-the-custom-compose-file] ```sh nano docker-compose.custom.yml ``` Choose one of the following examples and paste it into the file. Use this example to keep the direct-access ports available from the Coolify server while preventing other machines from connecting to them. ```yaml services: coolify: ports: !override - "127.0.0.1:${APP_PORT:-8000}:8080" - "127.0.0.1:${SOKETI_PORT:-6001}:6001" - "127.0.0.1:6002:6002" ``` Use this example when the Coolify proxy is configured for the dashboard and you do not need direct access through ports `8000`, `6001`, or `6002`. ```yaml services: coolify: ports: !override [] ``` Save the file by pressing Ctrl + X, then Y, and then Enter. Validate the Compose file [#validate-the-compose-file] ```sh docker compose --env-file .env \ -f docker-compose.yml \ -f docker-compose.prod.yml \ -f docker-compose.custom.yml \ config ``` Continue only when the command prints the merged configuration without an error. Apply the Compose override [#apply-the-compose-override] ```sh curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` The installation script detects `docker-compose.custom.yml` and includes it when starting Coolify. Open the Coolify dashboard using its domain and confirm that real-time updates and the web terminal still work. For other changes and more examples, see [Compose overrides](/start-with-self-hosted#_4-compose-overrides). *** Confirm the firewall works [#confirm-the-firewall-works] After saving the rules: * For self-hosted Coolify, open the dashboard using port `8000` or its configured domain. * Validate a connected server from **Servers > your server > General**. * Open an application domain and confirm it loads through HTTPS. * Open the [Web Terminal](/core/infrastructure/servers/web-terminal) if you use it. If server validation times out, check the SSH port and allowed source address first. If validation succeeds but an application does not load, check ports `80` and `443` and confirm the domain points to the correct server. *** Open additional ports only when needed [#open-additional-ports-only-when-needed] The standard port tables cover normal Coolify access. Open another port only when a resource or integration requires it. Applications behind a domain receive traffic through the Coolify proxy on ports `80` and `443`. You do not need to open their internal container ports. If you add a public port mapping, open that exact port in the firewall. For example, a PostgreSQL mapping on `5432` requires an inbound TCP rule for port `5432`. Restrict database and administration ports to the client IP addresses that need them. Do not expose these ports to `0.0.0.0/0` or `::/0` unless another security layer protects them. GitHub sends webhook requests to the Coolify dashboard when a connected repository changes. If the dashboard uses a domain through the Coolify proxy, ports `80` and `443` must remain open. To restrict webhook traffic by source address, use the current ranges under `hooks` in the [GitHub API metadata](https://api.github.com/meta). GitHub can change these ranges, so review them regularly. # GitHub Actions Runners (/docs/core/infrastructure/servers/github-actions-runners) GitHub Actions runners [#github-actions-runners] Coolify can run the GitHub Actions workflow jobs of a GitHub organization on your [build servers](/core/infrastructure/servers/build-servers). Each job runs in a new runner container. Coolify deletes the container after the job. GitHub Actions runners are in beta. The settings and the behavior can change in later versions. The runners run on your own servers, on self-hosted Coolify and on Coolify Cloud. Coolify never runs them on the server that runs Coolify itself. How it works [#how-it-works] 1. A workflow job asks for `runs-on: [self-hosted, ]`. 2. GitHub sends a **Workflow job** webhook event to Coolify through your GitHub App. 3. Coolify finds an enabled build server whose labels match the job and that has free capacity. It selects the least busy server. 4. Coolify starts an ephemeral runner container on that server and registers it with GitHub. 5. The runner takes one job. When the job completes, Coolify deletes the container, its network, and its volumes. When all runners are busy, the job waits in the Coolify queue until a runner is free. When a runner cannot start, Coolify removes it and tries again, up to 3 times. Refer to [Monitor runners](#monitor-runners). In the **Docker (privileged, full host access)** mode, each job gets a privileged Docker daemon. A malicious workflow can take control of the build server. Use **Isolated Docker (Sysbox)** or **No Docker** to keep jobs away from the server. Coolify creates a runner group that is limited to private repositories. Do not use these runners for repositories that accept code from untrusted contributors. What you need [#what-you-need] Before you start, make sure you have: * a server with the **Builds only** role. Refer to [Build servers](/core/infrastructure/servers/build-servers). * a GitHub App source in Coolify that belongs to a **GitHub organization**. Runners are registered at organization level, so GitHub Apps of personal accounts cannot run workflow jobs. * a Coolify instance that GitHub can send webhook events to. * outbound internet access from the build server to `github.com`, `ghcr.io` (runner image), and Docker Hub (Docker sidecar image). *** Set up the GitHub App [#set-up-the-github-app] The GitHub App needs these permissions and events: | Type | Name | Access | | ----------------------- | ------------------- | ------ | | Organization permission | Self-hosted runners | Write | | Repository permission | Actions | Read | | Webhook event | Workflow job | - | Create the source [#create-the-source] 1. Open **Sources** in the Coolify sidebar. 2. Select **+ Add** to create a source. 3. Enter the **Name** and the **Organization**. 4. In **Use this App for**, select **GitHub Actions runners**. 5. Select **Continue**. The **Organization** field is required when you select **GitHub Actions runners**. Register the App on GitHub [#register-the-app-on-github] 1. On the next page, make sure that **GitHub Actions runners** is set to **Run workflow jobs on build servers**. 2. Select **Register with GitHub**. 3. Complete the registration and install the App in your organization. Coolify adds the required permissions and the **Workflow job** webhook event to the App. For the full registration flow, refer to [Set up a GitHub App](/applications/sources/github/app). Use this procedure for a GitHub App that belongs to an organization and that you created before you used runners. Update the App on GitHub [#update-the-app-on-github] 1. Open the settings of the GitHub App on GitHub. 2. In **Permissions**, set **Organization permissions > Self-hosted runners** to **Read and write**. 3. Set **Repository permissions > Actions** to **Read-only**. 4. In **Subscribe to events**, select **Workflow job**. 5. Save the changes. 6. Accept the new permissions for the App installation in your organization. Refetch the permissions in Coolify [#refetch-the-permissions-in-coolify] 1. Open **Sources** in the Coolify sidebar and select the GitHub App. 2. Open **Permissions** and select **Refetch**. 3. Make sure that the **GitHub Actions runners** section does not show **Not ready for runners**. *** Configure runners on a build server [#configure-runners-on-a-build-server] Enable the runners [#enable-the-runners] 1. Open **Servers** in the Coolify sidebar and select the server. 2. Open **GitHub Runners**. 3. Select **Enable runners**. Coolify saves the default settings and shows the runner settings. If the server does not have the **Builds only** role, the page shows **This server is not enabled for builds**. Change the role in the **General** settings of the server first. Set the runner settings [#set-the-runner-settings] | Setting | Description | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | **GitHub App** | The organization GitHub App that receives the **Workflow job** events. Coolify selects the first App that has all the required permissions. | | **Labels** | Comma-separated custom labels, for example `coolify`. Coolify also registers `self-hosted` and `linux`. | | **Application builds** | **Also build applications**, or **Dedicated to runners**. A dedicated server is not used for application builds while its runners are enabled. | **Pull request jobs** defaults to **Refuse pull request jobs**. Jobs started by pull requests, including `pull_request_target` and review events, are refused before a step runs. Choose **Run pull request jobs** only when your repository and organization approval policies permit it. The setting applies to runners started after you save; push, scheduled, and manual jobs are unaffected. If Coolify shows **The GitHub App is not ready**, complete [Set up the GitHub App](#set-up-the-github-app). You can save the settings with an App that is not ready, but Coolify does not get jobs until the App has the required permissions. Set the resources [#set-the-resources] | Setting | Default | Description | | -------------------- | --------------------------------------- | ------------------------------------------------------------------------ | | **Parallel runners** | `2` | The maximum number of runners on this server at the same time (1 to 32). | | **CPU limit** | No limit | The number of CPUs for each runner, for example `2`. | | **Memory limit** | No limit | The memory for each runner, for example `4g`. | | **Docker in jobs** | Docker (privileged, full host access) | Refer to [Docker in jobs](#docker-in-jobs). | | **Runner image** | `ghcr.io/actions/actions-runner:latest` | Refer to [Runner image](#runner-image). | The CPU and memory limits apply to the runner container and to its Docker sidecar. Set the timeouts [#set-the-timeouts] All values are in minutes. | Setting | Default | Description | | --------------- | ------- | -------------------------------------------------------- | | **Queue wait** | `60` | Coolify drops a job that waits longer for a free runner. | | **Idle runner** | `10` | Coolify removes a runner that gets no job in this time. | | **Job** | `360` | Coolify stops a job that runs longer. | Save the settings [#save-the-settings] Select **Save**. When the GitHub App has all the required permissions, Coolify creates a runner group named `Coolify ` in your organization. The group is limited to private repositories. Organizations on the GitHub Free plan cannot create runner groups. In that case, Coolify uses the **Default** runner group and shows a warning. On GitHub, check which repositories can use the Default group. You can configure runners on more than one build server. Coolify sends each job to the least busy server that matches the job labels. *** Use the runners in a workflow [#use-the-runners-in-a-workflow] Add `self-hosted` and one of your custom labels to `runs-on`: ```yaml jobs: build: runs-on: [self-hosted, coolify] steps: - uses: actions/checkout@v4 - run: docker build -t my-app . ``` Coolify takes a job only when: * the job asks for at least one of your custom labels, and * all labels of the job are registered by the runner (`self-hosted`, `linux`, and your custom labels). Jobs that ask only for generic labels, such as `self-hosted`, are left for other runners. This prevents Coolify from taking jobs that are for other self-hosted runners of your organization. A custom label can contain letters, numbers, dots, dashes, and underscores. You cannot use `self-hosted`, `linux`, `x64`, `arm64`, `arm`, `windows`, or `macos` as the only label. *** Docker in jobs [#docker-in-jobs] | Mode | Description | | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Docker (privileged, full host access)** | Each runner gets its own Docker daemon in a privileged sidecar container. A job can get root access to the build server. Use this mode only for trusted repositories. | | **Isolated Docker (Sysbox)** | Each runner gets its own Docker daemon in an unprivileged sidecar container that uses the [Sysbox](https://github.com/nestybox/sysbox) runtime. The root user in a job has no rights on the build server. The server must have Sysbox. Refer to [Install Sysbox](#install-sysbox). | | **No Docker (isolated, no container actions)** | Jobs run in an unprivileged container without Docker. | What works in each mode: | Workflow feature | Docker (privileged) | Isolated Docker (Sysbox) | No Docker | | ------------------------------------------------------------------------------------ | :-----------------: | :----------------------: | :-------: | | Shell steps, JavaScript actions, and composite actions | Yes | Yes | Yes | | `docker` commands | Yes | Yes | No | | Service containers (`services:`) | Yes | Yes | No | | Container jobs (`container:`) | Yes | Yes | No | | Docker container actions (`uses: docker://...` or actions with `runs.using: docker`) | Yes | Yes | No | Coolify never shares the Docker socket of the host with a runner. Each runner has its own network and volumes. Install Sysbox [#install-sysbox] When you select **Isolated Docker (Sysbox)**, Coolify checks if the server has Sysbox. If Sysbox is not installed, select **Install Sysbox**. Coolify shows the installation logs. The automatic installation needs: * Debian or Ubuntu. * The `amd64` or `arm64` architecture. * Linux kernel 5.12 or newer. During the installation, Coolify: 1. Writes the current `bip` and `default-address-pools` values of Docker to `/etc/docker/daemon.json`. It keeps the other settings and saves a backup of the file as `/etc/docker/daemon.json.before-sysbox`. Without these values, the Sysbox package restarts Docker, or stops when containers exist. 2. Downloads the pinned Sysbox package from GitHub and checks its SHA-256 checksum. 3. Installs the package and `fuse3`. Docker reloads its configuration. Running containers are not restarted. For other distributions, [install Sysbox manually](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/install-package.md). Coolify detects it when the Sysbox services run and Docker lists the `sysbox-runc` runtime. Sysbox has an [open issue](https://github.com/nestybox/sysbox/issues/1018) in which a host can stop responding. Coolify does not remove Sysbox from a server. To remove it, refer to the [Sysbox uninstall instructions](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/install-package.md). *** Runner image [#runner-image] By default, Coolify uses `ghcr.io/actions/actions-runner:latest` and pulls it each time it starts a runner, so the runner stays up to date. When the registry is not available, Coolify uses the image that is already on the server. In **Runner image**, you can: * pin a version, for example `ghcr.io/actions/actions-runner:2.337.0`. * use a custom image based on the official runner image, to add tools. GitHub stops sending jobs to runners that are more than 30 days behind the newest runner version. If you pin a version or use a custom image, update it regularly. *** Monitor runners [#monitor-runners] The **Recent runners** section on the **GitHub Runners** page shows the queued jobs, the active runners, and their results. The list updates every 10 seconds. | Status | Description | | ------------------- | --------------------------------------------------------------------------------------- | | **Queued** | The job waits for a free runner. | | **Provisioning** | Coolify starts the runner container. | | **Waiting for job** | The runner is registered and waits for GitHub to give it a job. | | **Running** | The runner runs the job. | | **Completed** | The job completed and Coolify removed the runner. | | **Failed** | Coolify could not start the runner after 3 attempts. The error message shows the cause. | | **Cancelled** | The job ended before a runner started, the runner got no job, or a user cancelled it. | | **Timed out** | The job waited or ran longer than the configured timeout. | When a runner cannot start, Coolify removes it and puts the job back in the queue. It tries again after 30 seconds, and then after 60 seconds, possibly on another build server. While it waits, the row shows **Attempt 1 of 3 failed** or **Attempt 2 of 3 failed** with the cause. After the last failed attempt, the job stays queued on GitHub until GitHub cancels it. Another runner with matching labels can still take it. To stop an active runner, select **Cancel** on its row. *** Disable runners [#disable-runners] Select **Disable runners** to stop taking new jobs. Coolify removes the runners that wait for a job. Running jobs continue until they finish. Coolify keeps the settings and the execution history of the server. To take jobs again, select **Enable runners**. You cannot change the role of a build server while its runners are enabled. Disable the runners first. *** Troubleshooting [#troubleshooting] | Problem | Solution | | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **This server is not enabled for builds** | Set the server role to **Builds only** in the **General** settings of the server. | | The **GitHub Runners** menu does not show | Coolify does not run runners on the server that runs Coolify. Use another server. | | No GitHub App shows in the settings | Add a GitHub App that belongs to an organization, and install it. | | **The GitHub App is not ready** | Add the missing permissions or events on GitHub, then select **Refetch** on the **Permissions** page of the App. | | Jobs stay in **Queued** on GitHub and Coolify shows nothing | Make sure that `runs-on` has one of your custom labels, and that all labels of the job are registered by the runner. Make sure that GitHub can send webhook events to Coolify. | | Jobs stay in **Queued** in Coolify | All runners are busy. Increase **Parallel runners** or configure runners on more build servers. | | A job fails at **Initialize containers** or at a Docker step | The job needs Docker. Select **Docker (privileged, full host access)** or **Isolated Docker (Sysbox)**. | | **Install Sysbox** fails | Make sure that the server runs Debian or Ubuntu on `amd64` or `arm64`, with Linux kernel 5.12 or newer. Otherwise, install Sysbox manually. | | **Sysbox is not installed** shows after a manual installation | Make sure that the `sysbox-mgr` and `sysbox-fs` services run, that `/usr/bin/fusermount3` exists, and that `docker info` lists the `sysbox-runc` runtime. Select **Install Sysbox** to repair the installation on Debian or Ubuntu. | | Runners show **Failed** with **Could not start a runner after 3 attempts** | Read the error message. For Isolated Docker, check the Sysbox services on the server. | | GitHub does not send jobs to the runners | A pinned or custom **Runner image** can be too old. Use a newer runner version. | | The job cannot find a tool | Use a custom **Runner image** based on the official runner image that includes the tool. | # Manage Server (/docs/core/infrastructure/servers/manage-server) Manage a server [#manage-a-server] Open **Servers**, select a server, then open **General** to manage its identity, SSH connection, domain defaults, and role. Before changing the IP address, domain, SSH user, port, or connection timeout, confirm that the new connection works from the Coolify machine. General settings [#general-settings] | Setting | What it controls | | :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | The name shown for the server in Coolify. | | **Description** | Optional notes about the server or its purpose. | | **Wildcard domain** | The base domain Coolify can use when suggesting domains for new resources. | | **IP address or domain** | The address Coolify uses for SSH and server communication. | | **SSH user** | The account Coolify uses for SSH. | | **SSH port** | The SSH port. | | **Connection timeout** | How long Coolify waits for the SSH connection, from 1 to 300 seconds. | | **Server timezone** | The timezone used for scheduled operations such as backups and cron jobs. | | **Server role** | Choose **Deployments only**, **Builds only**, or **Deployments and builds**. See [Server roles](/core/infrastructure/servers/build-servers#server-roles). | Select **Save changes** after changing fields that do not save automatically. If you changed the connection, run the server validation again to confirm Coolify can still reach it. You cannot switch a server with managed resources to **Builds only**. Move or delete those resources first. The role cannot change while GitHub Actions runners are enabled. Read [Build Servers](/core/infrastructure/servers/build-servers) before changing the role. Wildcard domain [#wildcard-domain] For example, setting **Wildcard domain** to `https://example.com` lets Coolify suggest a domain such as `https://.example.com` for a new resource. Create a DNS record for `*.example.com` that points to this server. Changing the setting does not create DNS records or update domains already assigned to resources. *** Server details [#server-details] After successful validation, the **General** page displays detected information such as: * operating system * CPU architecture and core count * memory * kernel version * Docker versions Coolify refreshes this information when it validates or checks the server. Use it to confirm that the connected machine and its available resources match what you expect. *** Link an existing server to a cloud provider [#link-an-existing-server-to-a-cloud-provider] If you added a Hetzner, DigitalOcean, Vultr, or Hostinger server manually, you can link its Coolify record to the matching provider machine. Linking lets Coolify read provider status and display provider-backed actions such as **Power On** when the machine is stopped. It does not create a new machine. Add the provider token [#add-the-provider-token] Follow [Cloud Tokens](/core/security/credentials/cloud-tokens) to add a token for the account containing the server. Open the linking flow [#open-the-linking-flow] 1. Open **Servers** and select the server. 2. Open **General**. 3. Select **Link Cloud Provider**. 4. Choose **Hetzner**, **DigitalOcean**, **Vultr**, or **Hostinger**. 5. Select the matching provider token. Find the provider machine [#find-the-provider-machine] Search using the provider's server ID or the server IP address. Confirm that **Match Found** shows the intended machine, then select **Link This Server**. For Hostinger, the flow is different: 1. Select **Link Provider**, then select **Hostinger**. 2. Select the Hostinger token. 3. Enter the Virtual Machine ID, or select **Search By Server IP**. 4. Select **Link Resource**. Confirm the link [#confirm-the-link] Return to the server page and confirm that provider status is shown. If the status is stale, refresh it before taking a provider-backed action. A linked Hostinger server shows a `Hostinger · ` badge. Select **Refresh Status** to update it. If the VPS is stopped, you can start it from Coolify. Coolify does not validate the server over SSH while the VPS is stopped or suspended. Link only the provider machine represented by this Coolify server record. Provider-backed actions and deletion options apply to the linked machine. *** Revalidate after connection changes [#revalidate-after-connection-changes] Run validation again after changing: * IP address or domain * SSH user or port * network routing, firewall rules, or tunnel configuration If the connection fails, restore the previous settings or use the provider console to correct SSH access. Follow [OpenSSH](/core/infrastructure/servers/openssh) and [Firewall](/core/infrastructure/servers/firewall) for the common checks. *** Build and deployment limits [#build-and-deployment-limits] Open **Advanced** to control how many deployments a server runs at once and how long each deployment may run. | Setting | What it controls | Default | | :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | | **Concurrent builds** | How many build and deployment processes run at the same time on this server. Raise it to deploy more resources in parallel; lower it to protect a small server from resource exhaustion during builds. | `2` | | **Deployment timeout** | The maximum time a single deployment may run before Coolify cancels it. Increase it for large images or slow builds that legitimately exceed the limit. | `3600` | | **Queue limit** | The maximum number of deployments allowed to wait in the queue. When the limit is reached, Coolify rejects new deployments with an HTTP `429` response. | — | Select **Save changes** after changing these values. The concurrent-build count and queue limit apply to each server independently. A dedicated [build server](/core/infrastructure/servers/build-servers) has its own limits, so raising them there does not affect deployments on other servers. Disk usage notifications [#disk-usage-notifications] Set the high-disk notification interval under **Advanced**. Alerts repeat at most once per interval per server, with a default of 24 hours. If usage falls at least five percentage points below the threshold and later rises above it, Coolify can alert sooner. The API field is `server_disk_usage_notification_interval_hours`. A server becomes unreachable after two consecutive failed connection checks. A single failed check does not mark every resource as exited; deployment attempts recheck servers marked unreachable before failing. # Non-root User (/docs/core/infrastructure/servers/non-root-user) Use a non-root server user [#use-a-non-root-server-user] Coolify can connect to a server using an account other than `root`. This feature is experimental and still requires the account to run commands with passwordless `sudo`. The user created in this guide can run any command as `root` without entering a password. Use a dedicated account and SSH key only for Coolify. This guide uses `cooluser` as the username. Replace `cooluser` with the username you want to use. *** Configure the non-root user [#configure-the-non-root-user] Sign in as root [#sign-in-as-root] Connect to the server as `root` using SSH or the server console. Keep this session open until Coolify successfully validates the new account. Create the user [#create-the-user] Run the command for the server's operating system. ```sh useradd --create-home --user-group --shell /bin/bash --password 'NP' cooluser ``` Use this for CentOS, RHEL, Rocky Linux, AlmaLinux, Fedora, Amazon Linux, Oracle Linux, or TencentOS. ```sh useradd --create-home --user-group --shell /bin/bash --password 'NP' cooluser ``` ```sh useradd --create-home --user-group --shell /bin/bash --password 'NP' cooluser ``` ```sh useradd --create-home --user-group --shell /bin/bash --password 'NP' cooluser ``` ```sh adduser -D -s /bin/ash cooluser ``` `--password 'NP'` leaves the account unlocked while keeping password login disabled (`NP` is not a valid hash). A brand-new account otherwise has a locked password (`!` in `/etc/shadow`), and OpenSSH refuses key-based logins to a locked account, so Coolify's server validation fails. Alpine's busybox `adduser` has no equivalent flag, so its account stays locked. Alpine's OpenSSH is built without PAM and still accepts key-based logins, so no change is needed. If your Alpine build uses PAM, unlock the account with `apk add shadow && usermod -p 'NP' cooluser`. Confirm the account exists and is not locked: ```sh id cooluser passwd -S cooluser ``` `id` prints the user's ID and group information. In `passwd -S`, the status field (second column) should be `P`, not `L`. Open the Coolify dashboard [#open-the-coolify-dashboard] 1. Select **Keys & Tokens** in the sidebar. 2. Select **Private Keys**. 3. Open **New private key**. Generate the SSH key [#generate-the-ssh-key] 1. Select **Generate ED25519**. Coolify generates and saves the key. 2. Select its **Edit** icon and enter a name such as `cooluser-key`. 3. Copy the complete **Public key**. 4. Select **Save changes**. Do not add a passphrase to the private key. Coolify must use it without an interactive prompt. Add the key to the new user [#add-the-key-to-the-new-user] Back in the root session on the server, run: ```sh install -d -m 700 -o cooluser -g cooluser /home/cooluser/.ssh nano /home/cooluser/.ssh/authorized_keys ``` Paste the public key on a new line and save the file. Then run: ```sh chown cooluser:cooluser /home/cooluser/.ssh/authorized_keys chmod 600 /home/cooluser/.ssh/authorized_keys ``` Allow passwordless sudo [#allow-passwordless-sudo] Make sure the `sudo` command is installed, then run these commands as `root`: ```sh echo 'cooluser ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/cooluser chmod 440 /etc/sudoers.d/cooluser ``` Check that the new user can use `sudo` without a password: ```sh su - cooluser -c 'sudo -n whoami' ``` The command should print `root` without asking for a password. Prepare the Coolify data directory [#prepare-the-coolify-data-directory] Coolify stores application, database, service, proxy, and certificate files under `/data/coolify` on the server. Create the directory and give the non-root user ownership: ```sh mkdir -p /data/coolify chown -R cooluser:cooluser /data/coolify chmod -R o-rwx /data/coolify ``` The `cooluser` user can now manage files under `/data/coolify`. Coolify applies the same ownership pattern when it creates additional directories for a non-root server user. Continue to Add Server [#continue-to-add-server] Follow [Connect the server](/core/infrastructure/servers/add-server#connect-the-server) to add and validate the server. When you complete the server form: * Enter `cooluser` in **User**. * Select the private key whose public key you added to `/home/cooluser/.ssh/authorized_keys`. * Skip the key-creation steps in that guide because the key is already configured. After validation, the server's **General** page should report **Server is reachable and validated**. If validation fails: * Run `su - cooluser -c 'sudo -n true'` again. A password prompt means the sudo rule is incorrect. * Run `passwd -S cooluser` and confirm the status is `P`. An `L` (locked) account rejects key-based logins. * Confirm the public key is in `/home/cooluser/.ssh/authorized_keys`. * Confirm **User** is `cooluser` in Coolify. * Check the [OpenSSH](/core/infrastructure/servers/openssh) settings and [firewall](/core/infrastructure/servers/firewall) rule for the SSH port. Coolify supports proxy operations, database starts/backups, deployments, log drains, and volume clones when the SSH user cannot directly write to `/data/coolify`. Keep the documented sudo access available rather than making resource data broadly writable. # OpenSSH (/docs/core/infrastructure/servers/openssh) Configure OpenSSH [#configure-openssh] Coolify uses SSH to manage the servers connected to it. Choose **Localhost** when configuring the server where a self-hosted Coolify instance is installed. Choose **Remote server** when preparing another Linux server for Coolify Cloud or self-hosted Coolify. *** Choose the server [#choose-the-server] The official Coolify installation script normally installs OpenSSH and creates the **localhost** SSH connection. Choose **Semi-automatic** to configure OpenSSH before installing Coolify, or **Manual** if the localhost connection is missing or broken. Do not close your current SSH or console session until the **localhost** server connects successfully. You will need this session to correct the configuration if SSH access stops working. Configure OpenSSH before installing Coolify [#configure-openssh-before-installing-coolify] Use this method when you want to install and configure OpenSSH yourself, but want the Coolify installation script to create the **localhost** SSH key and dashboard connection. Log in to the server [#log-in-to-the-server] Login as `root` user using SSH or use the console provided by your hosting provider. Install OpenSSH [#install-openssh] Run the commands below based on your server's operating system. ```sh apt-get update apt-get install -y openssh-server systemctl enable --now ssh ``` Use this for CentOS, RHEL, Rocky Linux, AlmaLinux, Fedora, Amazon Linux, Oracle Linux, or TencentOS. ```sh dnf install -y openssh-server systemctl enable --now sshd ``` ```sh zypper refresh zypper install -y openssh systemctl enable --now sshd ``` ```sh pacman -Sy --noconfirm openssh systemctl enable --now sshd ``` ```sh apk add openssh rc-update add sshd default service sshd start ``` Configure key-based SSH access [#configure-key-based-ssh-access] Open the OpenSSH configuration file: ```sh nano /etc/ssh/sshd_config ``` Find these settings and change them to the values below. Add them at the bottom if they are missing. ```ini PubkeyAuthentication yes PermitRootLogin prohibit-password ``` `PermitRootLogin prohibit-password` allows `root` to connect with an SSH key but prevents password-based SSH login. Before restarting OpenSSH, make sure the public key used for your current `root` login is already in `/root/.ssh/authorized_keys`. Otherwise, keep the console open so you can restore access. Check and restart OpenSSH [#check-and-restart-openssh] Check the configuration: ```sh sshd -t ``` The command should return no output. If it reports an error, correct the file before continuing. Restart OpenSSH with the command for the server's operating system: ```sh systemctl restart ssh ``` ```sh systemctl restart sshd ``` ```sh service sshd restart ``` Run the Coolify installation script [#run-the-coolify-installation-script] ```sh curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` The script uses the OpenSSH service you configured, creates the **localhost** SSH key, authorizes it, and adds the **localhost** server to Coolify. Confirm the localhost server is ready [#confirm-the-localhost-server-is-ready] 1. Open the Coolify dashboard. 2. Select **Servers**. 3. Open **localhost**. 4. Confirm that the **General** page says **Server is reachable and validated**. If **localhost** is not reachable, use the **Manual** tab. Configure OpenSSH and the localhost connection manually [#configure-openssh-and-the-localhost-connection-manually] Use these steps when the automatic setup did not complete or the existing **localhost** connection is broken. Log in to the server [#log-in-to-the-server-1] Log in as `root` through SSH or use the console provided by your hosting provider. Install OpenSSH [#install-openssh-1] Run the commands below based on your server's operating system. ```sh apt-get update apt-get install -y openssh-server systemctl enable --now ssh ``` Use this for CentOS, RHEL, Rocky Linux, AlmaLinux, Fedora, Amazon Linux, Oracle Linux, or TencentOS. ```sh dnf install -y openssh-server systemctl enable --now sshd ``` ```sh zypper refresh zypper install -y openssh systemctl enable --now sshd ``` ```sh pacman -Sy --noconfirm openssh systemctl enable --now sshd ``` ```sh apk add openssh rc-update add sshd default service sshd start ``` OpenSSH is installed and configured to start when the server boots. Configure key-based SSH access [#configure-key-based-ssh-access-1] Open the OpenSSH configuration file: ```sh nano /etc/ssh/sshd_config ``` Find these settings and change them to the values below. Add them at the bottom of the file if they are missing. ```ini PubkeyAuthentication yes PermitRootLogin prohibit-password ``` `PermitRootLogin prohibit-password` allows `root` to connect with an SSH key but prevents password-based SSH login. Keep this server session open. Do not restart OpenSSH until the localhost public key has been added to `/root/.ssh/authorized_keys`, or you may lose SSH access. Generate the localhost SSH key [#generate-the-localhost-ssh-key] Create the directories used by Coolify: ```sh mkdir -p /data/coolify/ssh/keys mkdir -p /root/.ssh chmod 700 /root/.ssh ``` Generate a new key without a passphrase: ```sh ssh-keygen -t ed25519 -a 100 \ -f /data/coolify/ssh/keys/id.root@host.docker.internal \ -q -N "" -C coolify ``` If the command asks whether to overwrite an existing key, enter `y`. The remaining steps add the replacement private key to Coolify. Authorize the localhost SSH key [#authorize-the-localhost-ssh-key] Add the generated public key to the `root` account: ```sh cat /data/coolify/ssh/keys/id.root@host.docker.internal.pub \ >> /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys chown 9999:root /data/coolify/ssh/keys/id.root@host.docker.internal ``` The key must not have a passphrase. Coolify cannot answer an interactive passphrase or two-factor authentication prompt when it connects. Check and restart OpenSSH [#check-and-restart-openssh-1] Check the configuration before restarting the service: ```sh sshd -t ``` The command should return no output. If it reports an error, correct the file before continuing. Restart OpenSSH with the command for the server's operating system: ```sh systemctl restart ssh ``` ```sh systemctl restart sshd ``` ```sh service sshd restart ``` Keep the current session open and use a second terminal to confirm that key-based SSH access still works before closing it. Copy the localhost private key [#copy-the-localhost-private-key] Display the private key in the server terminal: ```sh cat /data/coolify/ssh/keys/id.root@host.docker.internal ``` Copy the complete output, including the `BEGIN` and `END` lines. Open the Keys and Tokens page on dashboard [#open-the-keys-and-tokens-page-on-dashboard] 1. Open **Keys & Tokens** in the Coolify sidebar. 2. Select **Private Keys**. 3. Select **+ Add**. Add the localhost private key [#add-the-localhost-private-key] 1. Enter a name such as `localhost key`. 2. Paste the value copied in the previous step into **Private Key**. 3. Select **Continue**. Do not paste the private key into **Public Key** or `/root/.ssh/authorized_keys`. Open the localhost server [#open-the-localhost-server] 1. Open **Servers** in the Coolify sidebar. 2. Select **localhost**. Select the private key [#select-the-private-key] 1. Select **Private Key** in the server sidebar. 2. Find the key you added in the previous step. 3. Select **Use this key**. Coolify checks the connection before saving the new key. Validate the localhost server [#validate-the-localhost-server] 1. Open **General** for the **localhost** server. 2. Select **Validate connection**. 3. Wait for validation to finish. The setup is complete when the page says **Server is reachable and validated**. Configure OpenSSH on a remote server [#configure-openssh-on-a-remote-server] Most Linux servers already have OpenSSH installed. Use these steps to install it when needed and confirm that public-key authentication is enabled. Log in to the server [#log-in-to-the-server-2] Log in as `root` through SSH or use the server console. Install OpenSSH [#install-openssh-2] If OpenSSH is missing, run the commands below based on your server's operating system. ```sh apt-get update apt-get install -y openssh-server systemctl enable --now ssh ``` Use this for CentOS, RHEL, Rocky Linux, AlmaLinux, Fedora, Amazon Linux, Oracle Linux, or TencentOS. ```sh dnf install -y openssh-server systemctl enable --now sshd ``` ```sh zypper refresh zypper install -y openssh systemctl enable --now sshd ``` ```sh pacman -Sy --noconfirm openssh systemctl enable --now sshd ``` ```sh apk add openssh rc-update add sshd default service sshd start ``` Make sure the root SSH key is authorized [#make-sure-the-root-ssh-key-is-authorized] Before disabling password-based root login, make sure the public key used for the `root` account is already in `/root/.ssh/authorized_keys`. If you have not added a key yet, complete [Create and authorize an SSH key](/core/infrastructure/servers/add-server#create-and-authorize-an-ssh-key), then return to this step. Update the OpenSSH configuration [#update-the-openssh-configuration] Open the configuration file: ```sh nano /etc/ssh/sshd_config ``` Find these settings and change them to the values below. Add them at the bottom if they are missing. ```ini PubkeyAuthentication yes PermitRootLogin prohibit-password ``` `PermitRootLogin prohibit-password` allows `root` to connect with an SSH key but prevents password-based SSH login. Do not close the current SSH or console session until you confirm that the public key works. This session lets you correct the configuration if the new connection fails. Check and restart OpenSSH [#check-and-restart-openssh-2] Check the configuration: ```sh sshd -t ``` The command should return no output. If it reports an error, correct the file before restarting OpenSSH. Restart OpenSSH with the command for the server's operating system: ```sh systemctl restart ssh ``` ```sh systemctl restart sshd ``` ```sh service sshd restart ``` Confirm the SSH connection [#confirm-the-ssh-connection] Open a second terminal and connect with the authorized key: ```sh ssh root@ ``` If OpenSSH uses a port other than `22`, run: ```sh ssh -p root@ ``` Keep the original server session open until this connection succeeds. Connect the server to Coolify [#connect-the-server-to-coolify] Finish the [Connect the server](/core/infrastructure/servers/add-server#connect-the-server) steps and validate the server. *** Troubleshooting [#troubleshooting] The private key selected for the server does not match a public key in the SSH user's `authorized_keys` file. For **localhost**, repeat the **Authorize the localhost SSH key** and **Select the private key** steps in the **Manual** tab. For a remote server, repeat the SSH key steps in [Add Server](/core/infrastructure/servers/add-server#create-and-authorize-an-ssh-key). Confirm that the server IP address and SSH port are correct. Then confirm that the [firewall](/core/infrastructure/servers/firewall) allows the SSH connection from Coolify. OpenSSH is not running or is listening on a different port. Start the OpenSSH service, then confirm that the port in **Servers > your server > General** matches the port used by OpenSSH. # Servers Overview (/docs/core/infrastructure/servers/overview) Servers overview [#servers-overview] A server is a machine where Coolify runs applications, databases, and services, or builds application images. Coolify manages a connected server through SSH. The machine and its provider account remain under your control. Coolify Cloud users must connect or provision a server before deploying a resource. Self-hosted installations start with a **localhost** server. Server roles [#server-roles] Localhost [#localhost] A self-hosted installation starts with a server named **localhost**. You can deploy resources to it, but those resources share CPU, memory, and storage with the Coolify dashboard. For production workloads, consider adding a remote server so application activity does not affect Coolify itself. The localhost server cannot be removed. Deployment servers [#deployment-servers] A deployment server is a Linux server that you own or rent and connect to Coolify. Use one to: * deploy resources with Coolify Cloud * keep workloads separate from the Coolify dashboard * deploy resources in another location * divide workloads across multiple machines Coolify needs a working SSH path to the server. The server can use a reachable IP address, hostname, or [Cloudflare Tunnel](/integrations/networking/cloudflare/tunnels/server-ssh). Build servers [#build-servers] Applications build on their deployment server by default. A separate build server is optional and is useful when builds need dedicated CPU, memory, or storage. A server marked as a build server cannot host applications, databases, or services. Read [Build Servers](/core/infrastructure/servers/build-servers) before enabling this role. *** Choose how to add a server [#choose-how-to-add-a-server] | Your situation | Guide | | :--------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------ | | You already have a Linux server | [Add a server manually](/core/infrastructure/servers/add-server) | | You want Coolify to purchase and create a server at Hetzner, DigitalOcean, Vultr, or Hostinger | [Provision a cloud server](/core/infrastructure/servers/provision-cloud-server) | | You need a server used only for application builds | [Configure a build server](/core/infrastructure/servers/build-servers) | Both manual and provider-created servers must be validated before Coolify can deploy resources to them. During validation, Coolify checks SSH access, verifies the operating system and required tools, and installs or verifies Docker Engine and Docker Compose. Validation can install Docker and restart the Docker service. Use a fresh server when possible. Existing containers may be temporarily unavailable. *** After connecting a server [#after-connecting-a-server] # Provision Cloud Server (/docs/core/infrastructure/servers/provision-cloud-server) Provision a cloud server [#provision-a-cloud-server] Coolify can create a server in a connected Hetzner, DigitalOcean, Vultr, or Hostinger account. After the provider assigns an IP address, validate the server so Coolify can prepare it for deployments. Selecting **Buy & Create Server** sends a server-creation request to the provider. The provider charges your account according to the selected plan and options. A Hostinger order is a paid purchase. Hostinger charges the default payment method of the account for the full billing period (1 month, 1 year, or 2 years). Hostinger does not bill per hour. Read [Hostinger billing and deletion](#hostinger-billing-and-deletion). What you need [#what-you-need] Before you start: 1. Follow [Cloud Tokens](/core/security/credentials/cloud-tokens) to add a valid provider token. 2. Open **Keys & Tokens > Private Keys** and create or import an SSH key. 3. Confirm that the provider account can create servers and has a valid payment method. Coolify uploads the selected public key to the provider when needed. It uses the `root` user and SSH port `22` for the new server. *** Create the server [#create-the-server] Choose a provider [#choose-a-provider] 1. Select **Servers** in the Coolify sidebar. 2. Select **New server**. 3. Select **Hetzner**, **DigitalOcean**, **Vultr**, or **Hostinger**. 4. Select the cloud token for the provider account. Configure the server [#configure-the-server] Complete the fields for your provider. | Field | What to choose | | :-------------- | :---------------------------------- | | **Server Name** | A recognizable name for the server. | | **Location** | The Hetzner data center location. | | **Server Type** | The server plan and resources. | | **Image** | A supported Linux image. | | **Private Key** | The SSH key Coolify will use. | Under **Advanced Hetzner Options**, you can add extra SSH keys, firewalls, and private networks; control IPv4 and IPv6; enable Hetzner backups; and provide a cloud-init script. Hetzner backups add 20% to the monthly server price. | Field | What to choose | | :-------------- | :----------------------------------- | | **Server Name** | A recognizable name for the Droplet. | | **Region** | The DigitalOcean data-center region. | | **Size** | The Droplet plan and resources. | | **Image** | A supported Linux image. | | **Private Key** | The SSH key Coolify will use. | Under the advanced options, you can add extra SSH keys, control IPv6, enable DigitalOcean monitoring, and provide a cloud-init script. | Field | What to choose | | :------------------- | :------------------------------------ | | **Server Name** | A recognizable name for the instance. | | **Region** | The Vultr data-center region. | | **Plan** | The instance plan and resources. | | **Operating System** | A supported Linux image. | | **Private Key** | The SSH key Coolify will use. | Under the advanced options, you can add SSH keys, control IPv6, disable public IPv4, and provide a cloud-init script. Do not disable public IPv4 unless Coolify has another working SSH path to the server. The Hostinger form opens at `/servers/new/hostinger`. | Field | What to choose | | :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Server name** | A name for the VPS. Use a fully qualified domain name, such as `vps.example.com`, to set it as the VPS hostname. | | **Data center** | The Hostinger data center. | | **Plan and billing period** | A KVM plan (KVM 1, KVM 2, KVM 4, or KVM 8) and a billing period (1 month, 1 year, or 2 years). The label shows the price for the first period and the renewal price. | | **Operating system** | A plain operating system. The default is Ubuntu 24.04 LTS. | | **Private key** | The SSH key Coolify will use. Coolify adds it to the VPS. | Instead of a plain operating system, you can select an **Operating system with application**. These templates install an application or a control panel on the VPS. The application can use ports `80` and `443`, which the Coolify proxy also needs. Use a plain operating system for a Coolify server. Under the advanced options, you can: * Turn **Enable weekly Hostinger backups (extra cost)** on or off. It is off by default. Hostinger charges extra for backups. Check the price in hPanel before you turn them on. * Add more SSH keys from your Hostinger account. * Select a Hostinger post-install script. If the server name is not a fully qualified domain name (it has no dot), Hostinger uses its default hostname, such as `srv123456.hstgr.cloud`. Hostinger does not use cloud-init. Use a Hostinger post-install script for startup configuration. If you need startup configuration on Hetzner, DigitalOcean, or Vultr, select a saved script or enter one in the cloud-init field. Read [Cloud-Init Scripts](/core/security/credentials/cloud-init-scripts) before using this option. Send the creation request [#send-the-creation-request] Review the selected plan and options, then select **Buy & Create Server**. For Hostinger, select **Buy and create**. Coolify creates its server record immediately. The provider may take several minutes to create the machine and assign its public IP address. Wait for the provider [#wait-for-the-provider] Keep the server page open while Coolify checks the provider status and updates the server IP address. Wait until: * the provider reports that the server is running * the server has its final reachable IP address * SSH has had time to start If the provider reports the machine as stopped or otherwise unavailable, power it on in the provider console or relink it before validation. For Hostinger, Coolify waits a short time for the public IP address. The IP address can appear 1 to 2 minutes later. Coolify adds it to the server automatically. Validate the server [#validate-the-server] Select **Validate connection**. The server page shows **Revalidate connection** after successful validation. Coolify checks SSH access, the operating system, required tools, Docker Engine, and Docker Compose. When validation finishes, confirm that the server is reachable and validated. *** Hostinger billing and deletion [#hostinger-billing-and-deletion] Hostinger works differently from the other providers. Read this section before you buy a Hostinger VPS. Payment is still processing [#payment-is-still-processing] Sometimes Hostinger accepts the order but the payment is not complete. In this case, Coolify does not create a server. Coolify shows this message: ```text Hostinger order N is waiting for payment. Finish the VPS setup in hPanel. ``` Open [hPanel](https://hpanel.hostinger.com/) and finish the VPS setup there. To manage the VPS in Coolify, [add the server](/core/infrastructure/servers/add-server). Then [link it to Hostinger](/core/infrastructure/servers/manage-server#link-an-existing-server-to-a-cloud-provider). Setup fails after payment [#setup-fails-after-payment] Sometimes Hostinger charges the order, but the VPS setup fails. Coolify then tries the setup again. Coolify also links the VPS to the server, so you do not lose it. If the setup still fails, the server shows the state `initial`. Finish the VPS setup in hPanel. Server status [#server-status] A linked Hostinger server shows a `Hostinger · ` badge on the server page. Select **Refresh Status** to get the current state from Hostinger. If the VPS is stopped, you can start it from Coolify. Coolify does not validate the server over SSH while the VPS is stopped or suspended. Delete a Hostinger VPS [#delete-a-hostinger-vps] Hostinger has no API to delete a VPS immediately. When you delete the server in Coolify, you can select **Also delete VPS from Hostinger (at the end of the paid period)**. Coolify then turns off auto-renewal for the VPS. The VPS keeps running until the paid period ends. Then Hostinger deletes the VPS and all its data. If you do not select this option, the VPS keeps running and Hostinger continues to bill you. To delete the VPS now, or to request a refund in the 30-day money-back period, cancel the VPS in hPanel under **Billing > Subscriptions**. Read [Remove Server](/core/infrastructure/servers/remove-server) for the full deletion steps. *** Create a Hostinger server with the API [#create-a-hostinger-server-with-the-api] You can also create a Hostinger server with the [Coolify API](/api/overview). All endpoints are under `/api/v1` and use a Bearer token. Use these endpoints to find the values for the request. Send `cloud_provider_token_uuid` as a query parameter. | Endpoint | Returns | | :------------------------------------ | :-------------------------------------------------------------------------------------------------------- | | `GET /hostinger/data-centers` | The Hostinger data centers. | | `GET /hostinger/catalog` | The KVM plans and their prices. | | `GET /hostinger/templates` | The operating system templates. | | `GET /hostinger/ssh-keys` | The SSH keys in the Hostinger account. | | `GET /hostinger/post-install-scripts` | The post-install scripts. Returns `403` with the Hostinger message if the token does not have permission. | Then send `POST /servers/hostinger` with these fields: | Field | Type | Required | Description | | :-------------------------- | :------------ | :------- | :----------------------------------------------------------------------------------- | | `cloud_provider_token_uuid` | string | Yes | The UUID of the Hostinger cloud token. | | `item_id` | string | Yes | The price ID of the plan and billing period, such as `hostingercom-vps-kvm1-usd-1m`. | | `data_center_id` | integer | Yes | The data center ID. | | `template_id` | integer | Yes | The operating system template ID. | | `private_key_uuid` | string | Yes | The UUID of the Coolify private key. | | `name` | string | No | The server name. | | `enable_backups` | boolean | No | Enables weekly Hostinger backups, which cost extra. The default is `false`. | | `public_key_ids` | integer array | No | The IDs of more SSH keys from the Hostinger account. | | `post_install_script_id` | integer | No | The ID of a Hostinger post-install script. | | `instant_validate` | boolean | No | Validates the server immediately. | The API returns: * `201` with `uuid`, `hostinger_virtual_machine_id`, `ip`, and `provisioning` when Coolify creates the server. * `202` with `message` when the payment is still processing. Coolify does not create a server. * `422` when the request is not valid. * `429` when you send too many requests. Hostinger allows about 90 requests per minute. A successful `POST /servers/hostinger` request places a paid order. Hostinger charges the default payment method of the account. *** If provisioning fails [#if-provisioning-fails] * Confirm that the cloud token is valid and has write permissions. * Confirm that the provider account can create the selected plan in the selected region. * Check provider quotas, account balance, and payment status. * Confirm that the selected SSH key is valid. * Open the provider console to determine whether the machine was created before retrying. Delete unwanted billable machines there. * For Hostinger, open hPanel before you try again. Hostinger can charge an order even if Coolify shows an error. Read [Hostinger billing and deletion](#hostinger-billing-and-deletion). For token-specific checks, follow [Cloud Tokens troubleshooting](/core/security/credentials/cloud-tokens#troubleshooting). # Remove Server (/docs/core/infrastructure/servers/remove-server) Remove a server [#remove-a-server] Deleting a server always removes it's details from the Coolify database. Depending on the options you choose, Coolify can also delete its managed resources and its linked Hetzner, DigitalOcean, Vultr, or Hostinger machine. The **localhost** server in a self-hosted Coolify installation cannot be deleted. Deleting resources or the linked provider machine can permanently destroy application files, databases, volumes, and backups stored on that machine. Decide what to delete [#decide-what-to-delete] Before opening the deletion dialog, choose the required outcome. | Option | Result | | :----------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Only delete server from Coolify** | Removes the server from Coolify. The Linux machine, Docker installation, and files remain. | | **Delete all resources** | Starts deletion for every resource Coolify manages on this server, then removes the server from database. | | **Also delete server/droplet from the provider** | Sends a deletion request for the linked Hetzner server, Vultr instance, or DigitalOcean Droplet. For a Hostinger VPS, turns off auto-renewal so Hostinger deletes the VPS at the end of the paid period. | Provider deletion is not selected by default. If you leave it disabled, the provider continues billing for a machine that still exists. Hostinger has no API to delete a VPS immediately. If you select the Hostinger option, Coolify turns off auto-renewal. The VPS keeps running until the paid period ends. Then Hostinger deletes the VPS and all its data. To delete the VPS now, or to request a refund in the 30-day money-back period, cancel the VPS in [hPanel](https://hpanel.hostinger.com/) under **Billing > Subscriptions**. *** Prepare for removal [#prepare-for-removal] Review managed resources [#review-managed-resources] 1. Open **Servers** and select the server. 2. Open **Resources > Managed**. 3. Review every listed application, database, and service. Back up important data. Redeploy resources you want to keep to another server and update their DNS records. Choose how resources will be handled [#choose-how-resources-will-be-handled] For the safest and most controlled migration, move or delete each resource before removing the server. If resources remain, the confirmation dialog offers **Delete all resources** and shows how many will be deleted. Enable it only if every remaining resource can be destroyed. Check the provider link [#check-the-provider-link] If the server is linked to Hetzner, DigitalOcean, Vultr, or Hostinger, decide whether the actual provider machine should also be deleted. Keep the provider option disabled if you need the machine, its files, or console access after removing it from Coolify. *** Delete the server [#delete-the-server] Open the Danger Zone [#open-the-danger-zone] Open the server's **Danger** page and find **Delete Server** under **Danger Zone**. Review the confirmation [#review-the-confirmation] Select **Delete** and review every action shown in the dialog. When applicable: * enable **Delete all resources** only if the remaining managed resources can be destroyed * enable **Also delete server from Hetzner Cloud** only if the linked Hetzner server should be permanently deleted * enable **Also delete server from Vultr** only if the linked Vultr instance should be permanently deleted * enable **Also delete droplet from DigitalOcean** only if the linked DigitalOcean Droplet should be permanently deleted * enable **Also delete VPS from Hostinger (at the end of the paid period)** only if the linked Hostinger VPS should be deleted when its paid period ends Enter the required confirmation value and complete the deletion. Verify the result [#verify-the-result] Confirm that the server no longer appears on the **Servers** page. If you selected provider deletion, open the provider console and confirm that the machine was deleted. If it still exists, delete it through the provider console to prevent unexpected charges. For Hostinger, open hPanel and confirm that auto-renewal is off. The VPS stays active until the end of the paid period. Coolify does not uninstall Docker or remove application files merely because you delete the server record. Clean up or repurpose the machine yourself if it remains at the provider. *** Add the machine again [#add-the-machine-again] There is no restore action for a deleted server record. If the Linux machine still exists, follow [Add Server](/core/infrastructure/servers/add-server) and validate it again. This creates a new Coolify server record. Applications, databases, and services from the deleted record do not automatically return, even if their containers or files remain on the machine. Recreate or redeploy each resource that Coolify should manage. Provider deletion through the API [#provider-deletion-through-the-api] For Hetzner, Vultr, or DigitalOcean, `DELETE /servers/{uuid}?delete_from_provider=true` also deletes the linked provider machine. Review the provider link before requesting deletion. The default is `false`. Use `force=true` only when you also intend to delete all resources. Deleting a server marks its queued deployments as failed. # Server Patching (/docs/core/infrastructure/servers/server-patching) Patch server packages [#patch-server-packages] **Server Patching** lets you check for operating-system package updates and install them from the Coolify dashboard. Coolify does not install updates automatically. You choose when to update one package or all available packages. Docker, kernel, and system updates can restart services or require a server reboot. Back up important data and choose a maintenance window before selecting **Update All Packages**. Newer package versions, especially Docker releases, can introduce changes that break Coolify or your applications. Review the release notes carefully before updating. *** Update server packages [#update-server-packages] Open Server Patching [#open-server-patching] 1. Open **Servers** in the Coolify sidebar. 2. Select the server you want to update. 3. Select **Security** in the server menu. 4. Select **Server Patching**. Check for updates [#check-for-updates] Select **Check for Updates**. Coolify connects to the server and refreshes its package list. Keep the page open until the check finishes. When updates are available, the page lists the package name and the version that can be installed. If no packages appear after a successful check, the server is up to date. Review the packages [#review-the-packages] Before installing anything: 1. Read the package names in the update list. 2. Check release notes for important services you run. 3. Pay extra attention to Docker and kernel packages. 4. Create a current backup for important applications and databases. If you are unsure about a package, update it during a maintenance window or leave it for your server administrator. Install updates [#install-updates] Choose one of these options: * Select **Update** beside one package to install only that update. * Select **Update All Packages** to install everything in the list. Complete the confirmation when Coolify asks. An activity window shows the output from the server while the update runs. Do not close the activity window until the command finishes. Check the server again [#check-the-server-again] After the update finishes: 1. Select **Check for Updates** again. 2. Confirm the installed packages no longer appear. 3. Return to **Servers** and confirm the server is reachable. 4. Open important applications and databases hosted on the server. 5. If the update requires a reboot, reboot the server through your normal server-management method and wait for it to reconnect to Coolify. *** Update notifications [#update-notifications] Coolify checks connected servers for package updates once a week. It sends a **Server Patching** notification when updates are available or when the check fails. To review the notification setting: 1. Open **Notifications** in Coolify. 2. Select the notification channel you use. 3. Find **Server Patching**. 4. Enable or disable the notification and save the channel settings. The weekly check only reports available updates. It does not install them. *** Supported package managers [#supported-package-managers] Server Patching currently supports APK, APT, DNF, Pacman, and Zypper. Coolify reads `/etc/os-release` on the server to pick the package manager. | Package manager | Operating systems | | --------------- | ------------------------------------------------------------------------ | | APK | Alpine Linux | | APT | Ubuntu, Debian, Raspberry Pi OS, Pop!\_OS, Linux Mint, Zorin OS | | DNF | Fedora, CentOS, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Amazon Linux | | Pacman | Arch Linux, Manjaro, EndeavourOS | | Zypper | SLES, openSUSE Leap, openSUSE Tumbleweed | # Web Terminal (/docs/core/infrastructure/servers/web-terminal) Web terminal [#web-terminal] The Coolify Web Terminal lets you open a shell for a connected server or running container from the dashboard. Only team owners and administrators can use terminal features. Commands run with the permissions of the selected server user or container, so close the terminal when you finish. Before you start [#before-you-start] Make sure: * the server is reachable and validated * **Terminal Access** is enabled for the server * you are a team owner or administrator *** Open a terminal [#open-a-terminal] Select a server or container [#select-a-server-or-container] 1. Select **Terminal** in the Coolify sidebar. 2. Under **Start a terminal session**, use **Filter targets** to find the target if needed. 3. Select the server or running container. Coolify starts the session immediately. Coolify creates a short-lived terminal session token on the server rather than sending SSH command details through the browser. Wait for the command prompt to appear. If the session cannot start, the terminal displays an error; review it and check server reachability and terminal access before retrying. Confirm the terminal works [#confirm-the-terminal-works] Run a read-only command first: ```sh pwd ``` For a server, the output should show the current directory for the SSH user configured in Coolify. For a container, it shows the current directory inside that container. You can now run the command needed for your task. Close the browser terminal when you finish. Open a resource terminal [#open-a-resource-terminal] You can also open **Terminal** from an individual server, application, database, or service when that resource provides a terminal page. The same server setting controls both the global Terminal page and these resource terminals. *** Change terminal access [#change-terminal-access] Use this setting when nobody should be able to open dashboard terminals for a server or its containers. Disable terminal access [#disable-terminal-access] 1. Open **Servers**. 2. Select the server. 3. Select **Security**. 4. Open **Terminal Access**. 5. Select **Disable terminal**. 6. Enter the server name and your Coolify account password in the confirmation window. 7. Complete the confirmation. The change takes effect immediately. The server and its containers disappear from dashboard terminal selectors, including for owners and administrators. Disabling this setting does not block normal SSH connections made outside Coolify. Enable terminal access again [#enable-terminal-access-again] 1. Return to **Servers > your server > Security > Terminal Access**. 2. Select **Enable terminal**. 3. Enter the server name and your Coolify account password. 4. Complete the confirmation. 5. Return to **Terminal** and confirm the server appears in the target list. *** If the terminal does not connect [#if-the-terminal-does-not-connect] * Confirm the server is reachable from its **General** page. * Confirm **Terminal Access** is enabled. * Confirm the container is running if you selected a container. * If you open a self-hosted Coolify dashboard directly on port `8000`, confirm port `6002` is allowed by the [firewall](/core/infrastructure/servers/firewall). * Try the server terminal before the container terminal to confirm the SSH connection works. # Downgrade Coolify (/docs/core/instance-management/downgrade) Downgrade Coolify [#downgrade-coolify] Downgrading Coolify replaces the version of the self-hosted Coolify control plane. It does not roll back your applications, databases, services, managed servers, or their data. The Coolify team manages instance versions for Coolify Cloud. You must wait for the Coolify team to downgrade the instance if the latest version causes a serious issue. If you are experiencing any issues with Coolify, [contact the Coolify team](/support). You have to use the terminal to downgrade Coolify. The dashboard and automatic updates only install newer releases. Before you downgrade [#before-you-downgrade] * [Create an instance backup](/core/backup-and-recovery/instance-backup). * Review the [release notes](https://github.com/coollabsio/coolify/releases) for the current and target versions. * Choose a maintenance window: the dashboard will be unavailable while Coolify restarts, but your apps keep running. * Check for active deployments and let them finish before continuing. An older Coolify release may not work with database changes made by a newer release. Changing the version does not restore the earlier database state. If the downgrade breaks your Coolify instance, restore the known-good instance backup instead of downgrading through multiple older releases. Perform the downgrade [#perform-the-downgrade] Disable automatic updates [#disable-automatic-updates] Prevent Coolify from returning to the newest release after the downgrade. Open **Settings** in the left sidebar, then select **Updates**. Under **Automatic updates**, choose **Disabled**. This setting saves immediately. If you cannot change **Automatic updates**, check whether `/data/coolify/source/.env` contains the `AUTOUPDATE` environment variable. If it does, set it to `false`. The upgrade script saves a timestamped backup of `.env` before changing it. Save your own copy of `/data/coolify/source/.env` before downgrading in case anything goes wrong. Install the target version [#install-the-target-version] Connect to the Coolify server over SSH: ```sh ssh root@ ``` Replace `` with your server's IP address. If you normally sign in with a non-root account, run `sudo -i` first to open a root shell. Run the upgrade script with the exact target version: ```sh curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh | bash -s 4.3.21 ``` Replace `4.3.21` with the version from the release you selected. The upgrade script downloads the Coolify configuration files, pulls the target Coolify image, then restarts the Coolify containers in the background. Wait for the restart confirmation before closing the SSH session. Verify the downgrade [#verify-the-downgrade] After the upgrade script completes, wait for the dashboard to be available again, then confirm: * the dashboard opens and shows the expected Coolify version * you can see your projects and resources * managed servers still connect The upgrade script writes a timestamped log such as `/data/coolify/source/upgrade-2026-07-11-12-00-00.log`. Review the newest `upgrade-*.log` file if the dashboard is still unavailable or a container fails to start. Troubleshooting [#troubleshooting] Return to **Settings > Updates** and confirm **Automatic updates** is set to **Disabled**. If the control is unavailable because `AUTOUPDATE` is set in `/data/coolify/source/.env`, change it to `AUTOUPDATE=false` and rerun the target-version command. Review the newest `/data/coolify/source/upgrade-*.log` file first. Check that the `coolify`, `coolify-db`, and `coolify-redis` containers are running and healthy. Then make sure your firewall still allows access to the dashboard. Releases before the [Reverb migration](/core/instance-management/reverb-migration) also start a `coolify-realtime` container. A downgrade to one of those releases brings that container back, and ports `6001` and `6002` move to it again. Stop here if the target version cannot use the existing database or the dashboard remains unavailable. Do not keep downgrading to older releases. Use the backup created before the change and follow [Restore a Coolify instance](/core/backup-and-recovery/instance-restore). Restore uses the backup database together with the matching `.env` file so Coolify retains the encryption key required to read encrypted values. # Instance Environment Variables (/docs/core/instance-management/environment-variables) Instance environment variables [#instance-environment-variables] Self-hosted Coolify reads its instance environment from `/data/coolify/source/.env`. Use this file for settings such as PHP memory, workers, and scheduled job dispatch that are not exposed in the dashboard. These settings affect the Coolify instance. To configure a deployed application, use that application's [environment variables](/applications/configuration/environment-variables) and image configuration instead. PHP memory and worker settings [#php-memory-and-worker-settings] The standard production Compose configuration supplies these defaults when the corresponding variable is unset: | Variable | Coolify default | Purpose | | :----------------------------- | :-------------- | :------------------------------------------------------------------------------------ | | `PHP_MEMORY_LIMIT` | `256M` | PHP memory limit for an individual script. | | `PHP_FPM_PM_CONTROL` | `dynamic` | PHP-FPM process-manager mode. The image supports `dynamic`, `ondemand`, and `static`. | | `PHP_FPM_PM_START_SERVERS` | `1` | Number of workers started when using `dynamic` mode. | | `PHP_FPM_PM_MIN_SPARE_SERVERS` | `1` | Minimum idle workers maintained in `dynamic` mode. | | `PHP_FPM_PM_MAX_SPARE_SERVERS` | `10` | Maximum idle workers maintained in `dynamic` mode. | `PHP_MEMORY_LIMIT` is separate from Docker's container memory limit. Raising it does not allocate more RAM to the container or server. PHP workers and other processes still share the available memory. Keep worker settings consistent with the selected process-manager mode and the server's resources. Additional image-supported settings are listed in the [Server Side Up PHP environment reference](https://serversideup.net/open-source/docker-php/docs/reference/environment-variable-specification). Coolify's own configuration can override image defaults, so verify the effective value after making changes. Scheduled job dispatch [#scheduled-job-dispatch] `SCHEDULED_JOBS_DISPATCH_MODE` controls how the scheduler checks every minute which database backups, tasks, volume backups, and Docker cleanups are due: | Value | Behavior | | :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sequential` | One process checks all four job types, one after another. This uses the least CPU and memory. A slow job type can delay the other types. | | `concurrent` | One process for each job type, all at the same time. A slow job type cannot delay the other types, but each process loads Coolify, so CPU and memory usage are higher every minute. | When the variable is not set, or has another value, self-hosted instances use `sequential`. Use `concurrent` when many backups or tasks are due at the same minute and one slow job type delays the others. To change the mode, add or update this entry in `/data/coolify/source/.env`: ```dotenv SCHEDULED_JOBS_DISPATCH_MODE=concurrent ``` Then follow [Apply the changes](#apply-the-changes) below to recreate the Coolify container while preserving its current image and any custom Compose overrides. Change a setting [#change-a-setting] Connect to the server where the Coolify instance runs. Back up the existing environment file, then edit it: ```bash cp /data/coolify/source/.env /data/coolify/source/.env.backup nano /data/coolify/source/.env ``` For example, to raise the PHP memory limit to `512M`, add or update this line: ```dotenv PHP_MEMORY_LIMIT=512M ``` Update the existing entry rather than adding duplicate keys. Keep the instance's other values, including `APP_KEY`, unchanged. Store the backup securely: it contains instance credentials. Do not edit the generated `docker-compose.prod.yml` to change one of these defaults. Installer and update scripts can replace that file. Apply the changes [#apply-the-changes] Changing `.env` does not update an existing container's environment. Recreate the Coolify container using your installation's Compose configuration; a plain `docker restart coolify` does not reload these variables. For a standard self-hosted installation, run these commands in Bash from the source folder: ```bash cd /data/coolify/source || exit 1 coolify_image=$(docker inspect --format '{{.Config.Image}}' coolify) || exit 1 compose_files=(-f docker-compose.yml -f docker-compose.prod.yml) if [ -f docker-compose.custom.yml ]; then compose_files+=(-f docker-compose.custom.yml) fi docker compose "${compose_files[@]}" -f - up -d --no-deps --force-recreate coolify < If you use **Coolify Cloud**, the Coolify team manages the Coolify instance for you. Coolify Cloud users cannot access or edit these settings. The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **Domain Name:** `shadowarcanist.com` * **Coolify Dashboard:** `https://coolify.shadowarcanist.com` Open **Settings** in the left sidebar, or visit: ```bash https://coolify.shadowarcanist.com/settings ``` The Settings page groups options under **Configuration** (General, Advanced, and Updates) and **Instance** (Backup, Email, and Authentication). Select a section from the Settings navigation, then use **Save changes** to apply your edits. Configuration [#configuration] Use General for the dashboard URL, HTTP-to-HTTPS behavior, instance label, timezone, and network addresses Coolify should use. URL [#url] This is the address you use to open the Coolify dashboard. Coolify also uses it when it needs to generate links back to the instance. If you want the dashboard to use HTTPS, the value must start with `https://`. Enter the full dashboard URL in **URL** and click **Save changes**. Before changing it, make sure DNS for the domain points to the server where Coolify is running. If DNS validation is enabled, Coolify checks the domain. Coolify also warns you when the instance URL is already used by another resource. **Accepted values:** * A full URL with a protocol, for example `https://coolify.shadowarcanist.com`. * Use `https://` when the dashboard should be served over HTTPS. * A root domain or subdomain. **Notes:** * Path-based URLs such as `https://shadowarcanist.com/coolify` are not supported. * Do not reuse an application or service domain for the dashboard. If the instance URL conflicts with a resource domain, SSL certificates and routing can become unpredictable. *** Redirect HTTP to HTTPS [#redirect-http-to-https] Controls whether requests to the Coolify dashboard over HTTP are redirected to HTTPS. Choose **Enabled** or **Disabled**, then click **Save changes**. **Notes:** * If a reverse proxy or Cloudflare Tunnel connects to Coolify over HTTP while users access the dashboard over HTTPS, enabling this setting can create a redirect loop. Disable the redirect in Coolify when your proxy handles HTTPS redirection. * Keep this enabled when Cloudflare uses **Full** or **Full (Strict)** SSL. **Accepted values:** * Enabled: redirect HTTP requests to HTTPS. * Disabled: do not redirect HTTP requests. *** Name [#name] Adds the instance name in brackets before the page title shown in the browser tab. For example, a name of `Production` appears as `[Production] Settings | Coolify`. It does not change the Coolify name or logo in the sidebar. Update **Name** and click **Save changes**. **Accepted values:** * Any text value up to 255 characters. * Leave it empty to keep the default Coolify instance name. *** Instance timezone [#instance-timezone] This timezone is used by instance-level schedules, including update checks and automatic updates. It does not change the timezone inside your applications or databases. Search for the timezone in **Instance timezone**, select it from the list, and click **Save changes**. **Accepted values:** * A valid timezone identifier from the dashboard list, for example `UTC`, `Europe/Berlin`, or `America/New_York`. **Notes:** * Database backup schedules can use the server timezone when the server has one configured. Otherwise, they fall back to the instance timezone. *** Instance public IPv4 [#instance-public-ipv4] Coolify normally detects the public IPv4 address of the server that runs the instance. Use this field only when the detected address is wrong, usually on servers with multiple public IPs. Enter the IPv4 address Coolify should use and click **Save changes**. **Accepted values:** * Leave it empty to let Coolify use the detected address. * A valid IPv4 address, for example `203.0.113.10`. *** Instance public IPv6 [#instance-public-ipv6] Coolify normally detects the public IPv6 address of the server that runs the instance. Use this field only when Coolify picks the wrong IPv6 address or cannot detect it. Enter the IPv6 address Coolify should use and click **Save changes**. **Accepted values:** * Leave it empty to let Coolify use the detected address. * A valid IPv6 address, for example `2001:db8::1`. Advanced contains access, DNS validation, API and MCP, outbound endpoint, interface and telemetry, and image storage controls. Access [#access] Registration [#registration] Controls whether users can create their own accounts from the registration page. Choose **Anyone can register** or **Registration disabled**, then click **Save changes**. **Accepted values:** * **Anyone can register:** anyone who can reach the registration page can create an account. * **Registration disabled:** only administrators can create accounts. **Notes:** * Keep registration disabled unless you intentionally want public self-registration. *** Destructive action confirmation [#destructive-action-confirmation] Controls whether destructive actions require password and text confirmation. Choose **Require two-step confirmation** or **Skip two-step confirmation**, then click **Save changes**. **Accepted values:** * **Require two-step confirmation:** destructive actions require the extra confirmation step. * **Skip two-step confirmation:** destructive actions do not require the extra confirmation step. **Notes:** * Skipping confirmation increases the chance of accidental deletions or unwanted changes. *** DNS [#dns] DNS validation [#dns-validation] Checks whether custom domains point to the right server before deployment. Choose **Enabled** or **Disabled**, then click **Save changes**. **Accepted values:** * **Enabled:** validate custom domains before deployment. * **Disabled:** skip DNS validation. *** Custom DNS servers [#custom-dns-servers] Changes which DNS resolvers Coolify uses for domain validation. Enter the resolver IPs in **Custom DNS servers**, then click **Save changes**. **Accepted values:** * Leave it empty to use the system default DNS resolvers. * A comma-separated list of valid IPv4 or IPv6 addresses, for example `1.1.1.1,8.8.8.8`. *** API and MCP [#api-and-mcp] API access [#api-access] Controls whether authenticated requests to the Coolify REST API are allowed. Choose **Enabled** or **Disabled**, then click **Save changes**. For API tokens, follow [API tokens](/core/security/credentials/api-tokens). **Accepted values:** * **Enabled:** authenticated API requests are accepted. * **Disabled:** API requests are blocked. *** MCP server [#mcp-server] Enables the MCP endpoint at `/mcp` for authenticated clients. Use your instance URL followed by `/mcp` and authenticate with a Sanctum bearer token created from [API tokens](/core/security/credentials/api-tokens). **Accepted values:** * **Enabled:** the instance MCP endpoint is available to authenticated clients. * **Disabled:** the instance MCP endpoint is unavailable. For the detailed guide, follow [MCP integration](/mcp/what-is-mcp). *** Allowed API IPs [#allowed-api-ips] Restricts which source IP addresses can call the Coolify API. Enter comma-separated IPs or CIDR ranges, then click **Save changes**. **Accepted values:** * Empty or `0.0.0.0` allows API access from anywhere. * Single IPv4 or IPv6 addresses, for example `192.168.1.100` or `2001:db8::10`. * CIDR ranges, for example `10.0.0.0/8` or `203.0.113.0/24`. **Notes:** * Allowing access from anywhere is not recommended for production instances. *** Outbound endpoints [#outbound-endpoints] These controls limit which internal destinations Coolify can reach when making outbound requests. Allowed internal targets [#allowed-internal-targets] Lists the internal destinations Coolify can reach when making outbound requests. Enter the hostnames, IP addresses, or CIDR ranges required by your integrations. Separate entries with commas or new lines, then click **Save changes**. *** Localhost targets [#localhost-targets] Controls whether outbound requests can target localhost addresses. Choose **Allowed** or **Blocked**, then click **Save changes**. **Notes:** * Loopback targets must also be included in **Allowed internal targets**. *** Interface and telemetry [#interface-and-telemetry] Navigation [#navigation] Enables SPA-style navigation and prefetching for smoother dashboard page transitions. Choose **SPA navigation** or **Full page navigation**, then click **Save changes**. **Accepted values:** * **SPA navigation:** dashboard links can prefetch and move between pages without full reloads. * **Full page navigation:** dashboard navigation uses full page loads. **Notes:** * Choose full page navigation if the dashboard has navigation issues after a browser or Livewire change. *** Anonymous telemetry [#anonymous-telemetry] Controls whether this instance sends an anonymous installation count to Coolify, contributing to the self-hosted installation count shown on [coolify.io](https://coolify.io/). Coolify does not store IP addresses or send error reports. Choose **Enabled** or **Disabled**, then click **Save changes**. **Accepted values:** * **Enabled:** do not send anonymous installation counts. * **Disabled:** allow anonymous installation counts. *** Sponsorship reminders [#sponsorship-reminders] Controls whether Coolify displays a sponsorship popup each month. Choose **Enabled** or **Disabled**, then click **Save changes**. **Accepted values:** * **Enabled:** monthly sponsorship reminders can be shown. * **Disabled:** sponsorship reminders are hidden for the instance. *** Image storage [#image-storage] These controls determine where compressed profile pictures and project icons are stored and how Coolify serves them. Storage destination [#storage-destination] Choose **Local storage** or a configured S3-compatible storage destination, then click **Save changes**. Add and test an S3 storage under **Storages** before selecting it here. *** Image CDN URL [#image-cdn-url] Optionally sets the public CDN URL for profile pictures and project icons stored on S3. Enter the URL provided by your CDN, then click **Save changes**. Use the Updates page to check for new Coolify releases, install an update manually, or configure automatic updates. Update Coolify [#update-coolify] When an update is available, click **Upgrade Now** to start the update. Coolify installs the latest version automatically. Follow [Update Coolify](/core/instance-management/update) for details. *** Update checks [#update-checks] Sets how often Coolify checks the [Coolify versions file](https://cdn.coollabs.io/coolify/versions.json) for a new release. Set **Check frequency**, then click **Save changes**. Click **Check Now** to check for an update immediately. **Accepted values:** * `every_minute`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, or a valid cron expression. * The default is `0 * * * *`, which checks every hour. *** Automatic updates [#automatic-updates] Controls whether Coolify installs updates automatically on the configured schedule. Choose **Enabled** or **Disabled** under **Automatic updates**. This setting saves immediately. When enabled, set **Update frequency** and click **Save changes**. If the control is disabled, `AUTOUPDATE` is set in `/data/coolify/source/.env` and controls automatic updates instead. **Accepted values:** * **Enabled:** Coolify installs updates on the configured schedule. * **Disabled:** Coolify does not install updates automatically. *** Update frequency [#update-frequency] Sets how often Coolify installs updates when automatic updates are enabled. Enter the schedule in **Update frequency**, then click **Save changes**. This field is available when automatic updates are enabled and is managed by `AUTOUPDATE` in `/data/coolify/source/.env` when that variable is set. **Accepted values:** * `every_minute`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, or a valid cron expression. * The default is `0 0 * * *`, which runs every day at `00:00`. *** Image registry [#image-registry] Choose the registry Coolify uses to pull its images. Switch registries if the current source is rate limited or unreachable, then click **Save changes**. **Accepted values:** * **Docker Hub** * **GitHub Container Registry** Instance [#instance] The Backup page manages backups of Coolify's internal database. It does not back up application volumes or external databases. For the full backup guide, see [Instance backup](/core/backup-and-recovery/instance-backup). First-time setup [#first-time-setup] When instance backup has not been configured, the page shows **Backup is not configured**. Click **Configure backup** to create the internal `coolify-db` resource and its scheduled backup. The localhost server must be functional; if it is not, open server settings and validate the localhost connection first. *** Instance database [#instance-database] This section shows Coolify's internal `coolify-db` resource used for instance backups. Its **Name**, **UUID**, **User**, and **Password** are read-only. You can edit the **Description** and click **Save changes**. *** Backup schedule [#backup-schedule] Enable or disable backups [#enable-or-disable-backups] Use **Enable backup** or **Disable backup** to turn the scheduled backup job on or off. This action saves immediately. Click **Back up now** to start a backup without waiting for the next scheduled run. The database must be running for this action. Frequency [#frequency] Sets how often the internal Coolify database is backed up. Enter a preset such as `hourly`, `daily`, `weekly`, `monthly`, or `yearly`, `every_minute`, or a valid cron expression, then click **Save changes**. For example, `0 0 * * *` runs daily at midnight. Timezone [#timezone] Shows the timezone Coolify uses for the backup schedule. This field is read-only and uses the timezone set for Coolify's localhost server, or the instance timezone if no server timezone is set. Timeout [#timeout] Sets the maximum backup runtime in seconds. If a backup exceeds this time, Coolify marks that execution as failed. Enter a value from `60` to `36000`, then click **Save changes**. Missing backup alert after [#missing-backup-alert-after] Sets how many days can pass without a backup execution before Coolify sends an alert through backup failure notification channels. Enter `0` to disable this alert, or a value from `1` to `365`, then click **Save changes**. *** S3 storage [#s3-storage] Use S3 storage to keep a remote copy of each instance backup. [Set up and validate an S3 storage destination](/core/s3-storage/overview) before enabling S3 backups. Click **Enable S3** to turn on uploads, then select an **S3 storage** destination. Choose whether **Local copy** should **Keep local backup** or **Delete after S3 upload**. Save changes after updating the local copy option. The storage selector is unavailable until a validated destination exists. *** Retention [#retention] Set separate retention limits for **Local backups** and **S3 backups**. The first limit reached removes the oldest backup. A value of `0` means unlimited for that limit. Enter the limits, then click **Save changes**. For each location, you can set: * **Backups to keep:** maximum number of recent backups. * **Days to keep:** remove backups older than this many days. * **Maximum storage (GB):** remove the oldest backups after the total size reaches this value. Decimal values are accepted. *** Executions [#executions] Review backup status, database, file path, finish time, duration, size, and local or S3 availability. To delete a backup, click its delete icon. Whether Coolify asks for password confirmation depends on [Destructive action confirmation](#destructive-action-confirmation): **Require two-step confirmation** shows the prompt, while **Skip two-step confirmation** skips it. Coolify deletes the local backup file, if it is still present, and removes the execution from the list. Click the download icon on a successful run to download its backup. **Clean failed backups** removes rows for unsuccessful runs. **Clean deleted entries** removes rows for backups whose local files have already been deleted; it does not delete files. Successful runs appear here after a scheduled or manual backup completes. Configure the sender identity and choose SMTP or Resend to deliver Coolify's transactional email. Sender [#sender] Sender settings are shared by SMTP and Resend. From name [#from-name] Sets the display name shown in outgoing email, such as password resets and invitations. Enter a name, then click **Save changes**. **Accepted values:** * A required text value, for example `Coolify`. From address [#from-address] Sets the sender address used for outgoing email. Enter a valid email address, then click **Save changes**. **Accepted values:** * A required email address, for example `noreply@shadowarcanist.com`. *** SMTP server [#smtp-server] Connect Coolify to an SMTP-compatible email provider. Enter the required **Host**, **Port**, and **Encryption** values supplied by your provider. Fill the remaining fields as needed. SMTP delivery [#smtp-delivery] Choose **Enabled** to send email through SMTP or **Disabled** to turn SMTP off. This selection saves immediately. Enabling SMTP turns off Resend. Host [#host] Enter the SMTP server hostname provided by your email provider, for example `smtp.mailgun.org`. Port [#port] Enter the port provided by your email provider. It must be between `1` and `65535`; common values are `587`, `465`, and `25`. Encryption [#encryption] Select the encryption method required by your email provider: * **StartTLS** * **TLS / SSL** * **None** Username and password [#username-and-password] Enter the credentials required by your SMTP provider. Leave these fields empty if the provider does not require authentication. Timeout [#timeout-1] Sets the maximum delivery time in seconds. Leave it empty to use the default mailer behavior. EHLO domain [#ehlo-domain] Optionally set the fully qualified domain Coolify sends in the SMTP EHLO command. Leave it empty to use the system default. After editing SMTP connection settings, click **Save changes**. *** Resend [#resend] Connect Coolify to [Resend](https://resend.com) to send transactional email through that provider. Create an API key in Resend and enter it in **API key**. The key is required when Resend is enabled. Choose **Enabled** under **Resend delivery** to use Resend, or **Disabled** to turn it off. This selection saves immediately, and enabling Resend turns off SMTP. Click **Save changes** to save the API key and sender fields. The **Authentication** page lists the OAuth providers supported by Coolify. Each provider has its own section with an **Enable** action, credentials, a redirect URI, and any additional fields that provider requires. The page also controls password registration while OAuth is enabled. Each provider can auto-join newly created users to the Root team as members. For OIDC user creation and verification controls, see [OpenID Connect](/core/security/authentication/sso/oidc). OAuth providers [#oauth-providers] Currently supported providers are: * Authentik * Bitbucket * Clerk * Discord * GitHub * GitLab * Google * Infomaniak * Microsoft * OpenID Connect (OIDC) * Zitadel For the detailed guide, follow [OAuth setup](/core/security/authentication/oauth/overview). *** Enabled providers [#enabled-providers] Controls whether the provider appears as a sign-in option on the Coolify login page. Fill in the required provider fields, then click **Enable**. Click **Disable** to remove the provider from the login page. *** Redirect URI [#redirect-uri] Defines the callback URL the identity provider redirects back to after authorization. Copy the **Redirect URI** shown by Coolify into the OAuth application at the provider, then save the same value in Coolify if you override it. **Accepted values:** * A full URL matching the provider callback, usually `https://coolify.shadowarcanist.com/auth//callback`. *** Client ID [#client-id] Stores the OAuth application client ID from the identity provider. Create an OAuth application with the provider, copy its client ID, paste it into **Client ID**, then click **Save changes**. **Accepted values:** * Any provider-issued client ID string required by the provider. *** Client Secret [#client-secret] Stores the OAuth application secret from the identity provider. Copy the provider client secret, paste it into **Client Secret**, then click **Save changes**. **Accepted values:** * Any provider-issued client secret string required by the provider. *** Provider-specific fields [#provider-specific-fields] Provider sections show additional fields when required by that provider. Base URL [#base-url] Stores the provider base URL for self-hosted or issuer-based OAuth providers. Enter the provider base URL, then click **Save changes**. **Accepted values:** * Use a full URL from the provider, for example `https://auth.shadowarcanist.com`. *** Tenant [#tenant] Stores tenant information for providers that support or require tenant scoping. For Azure, enter the required tenant value. Google uses a **Hosted domain** field that restricts sign-in to the configured Workspace domain; `*` allows any Workspace account. **Accepted values:** * Azure: required tenant value. * Google: optional allowed Workspace domain, for example `shadowarcanist.com`, or `*`. Instance environment settings [#instance-environment-settings] Set `HORIZON_ALLOWED_EMAILS` in the instance environment to grant additional users access to Laravel Horizon. See [Coolify development](/contribute/coolify) for the Horizon URL. `SSH_COMMAND_TIMEOUT` defaults to `3600` seconds. A value of `0` or an invalid value uses that default rather than disabling the timeout. `PROXY_CONNECT_NETWORKS_INTERVAL_SECONDS` and `NIGHTWATCH_ENABLED` are removed. Proxy networks are connected during destination creation, deployment, and proxy startup/restart. Laravel Nightwatch no longer runs inside the Coolify container. # Migrate realtime services to Reverb (/docs/core/instance-management/reverb-migration) Migrate realtime services to Reverb [#migrate-realtime-services-to-reverb] New Coolify releases run Laravel Reverb and the web terminal server inside the main `coolify` container. They no longer use the separate `coolify-realtime` container. Most installations do not need a manual change. Review your configuration before the update if you use a custom Compose override, custom realtime ports, a firewall, or a Cloudflare Tunnel. The update accepts a `soketi` override in `docker-compose.custom.yml`. Existing proxy routes and port settings remain compatible. You can move custom port bindings to `coolify` to make the override reflect the new container layout. What changes [#what-changes] | Before | After | | :---------------------------------------------------------- | :------------------------------------------------- | | Soketi listens in `coolify-realtime` | Reverb listens in `coolify` | | The terminal server listens in `coolify-realtime` | The terminal server listens in `coolify` | | The proxy sends realtime traffic to `coolify-realtime:6001` | The proxy sends realtime traffic to `coolify:6001` | | The proxy sends terminal traffic to `coolify-realtime:6002` | The proxy sends terminal traffic to `coolify:6002` | The external paths do not change: * `/app/*` carries browser WebSocket connections. * `/apps/*` carries Pusher-compatible API requests. * `/terminal/ws` carries web terminal connections. The update keeps the existing Pusher application ID, key, and secret. It also keeps `SOKETI_PORT` as the compatible Docker host-port setting. Do not rename that variable during this migration. The update script also removes the old `coolify-realtime` container. If `.env` still contains `PUSHER_BACKEND_HOST=coolify-realtime`, the script changes it to `127.0.0.1`, because Reverb now runs in the same container as Coolify. The `coolify` container also has `coolify-realtime` as a network alias on the `coolify` Docker network. A reverse proxy that still sends traffic to `coolify-realtime:6001` or `coolify-realtime:6002` keeps working. Before you update [#before-you-update] Back up the instance configuration [#back-up-the-instance-configuration] ```sh cd /data/coolify/source cp .env .env.before-reverb if [ -f docker-compose.custom.yml ]; then cp docker-compose.custom.yml docker-compose.custom.yml.before-reverb fi ``` Check for a Soketi service override [#check-for-a-soketi-service-override] ```sh grep -nE '^[[:space:]]*soketi:' docker-compose.custom.yml 2>/dev/null || true ``` If the command prints a line, review the override. Migrating it as shown below is optional; legacy `soketi` overrides are still accepted. Record custom realtime settings [#record-custom-realtime-settings] ```sh grep -E '^(PUSHER_HOST|PUSHER_PORT|PUSHER_SCHEME|PUSHER_BACKEND_PORT|SOKETI_PORT|TERMINAL_PORT)=' .env || true ``` Keep this output until you finish the verification. Migrate a custom Compose override [#migrate-a-custom-compose-override] The old firewall example configured ports on two services: ```yaml services: coolify: ports: !override - "127.0.0.1:${APP_PORT:-8000}:8080" soketi: ports: !override - "127.0.0.1:${SOKETI_PORT:-6001}:6001" - "127.0.0.1:6002:6002" ``` Move all three bindings to the `coolify` service: ```yaml services: coolify: ports: !override - "127.0.0.1:${APP_PORT:-8000}:8080" - "127.0.0.1:${SOKETI_PORT:-6001}:6001" - "127.0.0.1:6002:6002" ``` The web terminal always uses host port `6002`. `TERMINAL_PORT` does not change the Docker host port. If your override removed all public bindings, replace this: ```yaml services: coolify: ports: !override [] soketi: ports: !override [] ``` with this: ```yaml services: coolify: ports: !override [] ``` Move only port bindings that are still required. Remove Soketi-specific image, command, environment, health-check, and volume settings. Remove the `soketi` service block when it is empty. Keep ports `8000`, `6001`, and `6002` reachable until the dashboard, realtime updates, and terminal work through your domain. You can restrict them after you complete the verification. Check the environment variables [#check-the-environment-variables] The variables have different purposes: | Variable | Purpose | | :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SOKETI_PORT` | Compatible Docker host-port override for origin port `6001` | | `REVERB_PORT` | Optional. Takes precedence over `SOKETI_PORT` for the Docker host port of origin port `6001`. You do not need it when you already use `SOKETI_PORT`. | | `PUSHER_PORT` | Public port used by the browser | | `PUSHER_BACKEND_PORT` | Internal Reverb listen port, normally `6001` | | `PUSHER_BACKEND_HOST` | Host that Coolify uses to send events to Reverb, normally unset or `127.0.0.1` | | `TERMINAL_PORT` | Public port used by the browser for the web terminal, for example `443` behind a reverse proxy. It does not change the Docker host port, which is always `6002`. | Do not change an existing `SOKETI_PORT` value. Existing firewall rules and port forwarding can depend on it. For a dashboard behind Cloudflare, the public browser port is normally `443`: ```bash PUSHER_PORT=443 PUSHER_BACKEND_PORT=6001 ``` Do not set `PUSHER_PORT=6001` for a Cloudflare-proxied hostname. Port `6001` is the origin port. The browser connects to Cloudflare on port `443`. If you do not have an explicit `PUSHER_PORT`, leave it unset. Coolify selects the public port from the dashboard request and keeps direct IP access compatible. Cloudflare configurations [#cloudflare-configurations] Dashboard through the Coolify proxy [#dashboard-through-the-coolify-proxy] This is the recommended configuration. Send the dashboard hostname to the Coolify proxy on port `80` or `443`. The generated proxy configuration routes: ```text /app/* -> coolify:6001 /apps/* -> coolify:6001 /terminal/ws -> coolify:6002 /* -> coolify:8080 ``` You do not need separate Cloudflare routes for Reverb or the terminal. For a Cloudflare Tunnel that terminates TLS at Cloudflare, set the tunnel service URL to `http://localhost:80`. For end-to-end TLS, use the HTTPS origin configuration from the [Full TLS guide](/integrations/networking/cloudflare/tunnels/full-tls). Separate realtime hostname [#separate-realtime-hostname] Older tunnel configurations can use a separate hostname: | Public hostname or path | Tunnel service | | :-------------------------------- | :---------------------- | | `coolify.example.com` | `http://localhost:8000` | | `coolify.example.com/terminal/ws` | `http://localhost:6002` | | `coolify-realtime.example.com` | `http://localhost:6001` | This remains compatible. Keep: ```bash PUSHER_HOST=coolify-realtime.example.com PUSHER_PORT=443 PUSHER_BACKEND_PORT=6001 ``` The Cloudflare route still connects to origin port `6001`, but Reverb now handles that port in the `coolify` container. Update [#update] Update Coolify from **Settings > Updates**. Existing realtime routes, port settings, and legacy `soketi` overrides remain compatible. Keep the configuration backups until you have verified the dashboard, realtime updates, and terminal. If you choose to migrate an override manually, check that all required port bindings are now on `coolify`. Review the update log in `/data/coolify/source/upgrade-*.log` if the update reports a configuration error. Verify the migration [#verify-the-migration] Run these checks after the update: ```sh docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' docker logs --tail 100 coolify ``` Confirm that: 1. `coolify`, `coolify-db`, and `coolify-redis` are running. 2. The `coolify-realtime` container is gone. The update removes it. 3. The dashboard loads through its normal URL. 4. The browser developer tools show a successful WebSocket request to `/app/...`. 5. The WebSocket request uses `wss` and public port `443` when Cloudflare serves the dashboard over HTTPS. 6. A deployment or status change appears in the dashboard without a page refresh. 7. The web terminal connects through `/terminal/ws`. You can also open `/realtime` in two browser tabs and send a test event. Troubleshooting [#troubleshooting] The `coolify` container stays unhealthy [#the-coolify-container-stays-unhealthy] The container healthcheck now includes Reverb. Check the Reverb log inside the container and confirm that nothing else listens on port `6001`: ```sh docker exec coolify curl --fail http://127.0.0.1:6001/up sudo ss -tulpn | grep :6001 ``` The dashboard keeps working while the container is unhealthy. Only realtime updates stop. Cloudflare returns an error for the WebSocket request [#cloudflare-returns-an-error-for-the-websocket-request] * Confirm the browser connects to public port `443`, not origin port `6001`. * Confirm Cloudflare WebSockets are enabled for the zone. * Confirm the tunnel or proxy route includes `/app/*`. * Confirm the Coolify proxy can reach `coolify:6001` on the `coolify` Docker network. The dashboard works but realtime updates do not [#the-dashboard-works-but-realtime-updates-do-not] Check `PUSHER_HOST` and `PUSHER_PORT` in `/data/coolify/source/.env`. Remove obsolete overrides when the dashboard and Reverb use the same hostname, or keep port `443` for a separate Cloudflare realtime hostname. Also confirm that `PUSHER_BACKEND_HOST` is unset or `127.0.0.1`. A public hostname in that variable sends server-side events to the wrong place. Direct IP access stops receiving updates [#direct-ip-access-stops-receiving-updates] Confirm that the `coolify` container publishes host port `${REVERB_PORT:-${SOKETI_PORT:-6001}}` to container port `6001` and host port `6002` to container port `6002`. Also confirm that the server firewall permits these host ports from your client address. # Uninstall Coolify (/docs/core/instance-management/uninstallation) Uninstall Coolify [#uninstall-coolify] The uninstall steps depend on how you use Coolify. For a self-hosted instance, the steps remove Coolify's containers and its data. For Coolify Cloud, they remove Coolify Proxy and Sentinel from your servers. Deployed applications and services may keep running after removal. Removing Coolify Proxy stops the domains and TLS routing it provides. Remove the self-hosted instance [#remove-the-self-hosted-instance] Before you uninstall [#before-you-uninstall] * [Create an instance backup](/core/backup-and-recovery/instance-backup) and keep a copy outside this server. * Save `/data/coolify/source/.env` separately. It contains the encryption key needed to restore the instance backup. * Save or migrate the application configuration, deployment files, local backups, and proxy routing you need after removal. These are stored in `/data/coolify`. * Plan a replacement proxy before continuing if your resources use Coolify-managed domains or TLS certificates. * Confirm that there are no active deployments and that you are connected to the Coolify server over SSH. Deleting `/data/coolify` permanently removes Coolify's configuration, SSH keys, deployment files, proxy configuration, and locally stored instance backups. An instance backup contains the Coolify database; it does not back up the applications, databases, services, or volumes you deploy with Coolify. Connect to the Coolify server [#connect-to-the-coolify-server] Connect to the server that runs the Coolify instance over SSH: ```sh ssh root@ ``` Replace `` with your server's IP address. If you normally sign in with a non-root account, run `sudo -i` first to open a root shell. Remove Coolify containers [#remove-coolify-containers] ```sh docker rm -f coolify coolify-db coolify-redis coolify-sentinel ``` Installations from before the [Reverb migration](/core/instance-management/reverb-migration) also have a `coolify-realtime` container. Remove it as well if it exists: ```sh docker rm -f coolify-realtime ``` Application, database, and service containers keep running. Remove Coolify Proxy according to the Docker mode used by the server. For standalone Docker, run: ```sh docker rm -f coolify-proxy ``` For Docker Swarm, run this command on a manager node instead: ```sh docker stack rm coolify-proxy ``` Removing Coolify Proxy stops the domains and TLS routing it provides. Remove Coolify data volumes [#remove-coolify-data-volumes] Remove the volumes that store the Coolify database and Redis data: ```sh docker volume rm coolify-db coolify-redis ``` Do not run a broad `docker volume prune` command as part of this process. It can remove unused volumes that belong to other workloads on the server. Remove the Coolify network [#remove-the-coolify-network] If application or service containers still use the `coolify` network, connect them to another network before removing it. If you want them to keep using the `coolify` network, leave the network in place and skip the command below. When no workloads need the network, remove it: ```sh docker network rm coolify ``` Delete Coolify files [#delete-coolify-files] After confirming that your backup and any application or service files you still need are stored elsewhere, delete the Coolify data directory: ```sh rm -rf /data/coolify ``` This is the final destructive step. It permanently removes the instance `.env` file, local instance backups, and deployment and configuration files Coolify stored under `/data/coolify`. Remove Docker images [#remove-docker-images] Image tags can vary depending on when you last updated Coolify. Run `docker images` to see the images and tags on your server, then use those tags in the commands below. Remove the default Coolify images to free disk space: ```sh docker rmi ghcr.io/coollabsio/coolify:latest docker rmi ghcr.io/coollabsio/coolify-helper:latest docker rmi ghcr.io/coollabsio/sentinel:1.0.1 docker rmi postgres:15-alpine docker rmi redis:7-alpine ``` If you removed a `coolify-realtime` container, remove its image too: ```sh docker rmi ghcr.io/coollabsio/coolify-realtime:1.0.16 ``` If you used the default Traefik proxy, remove its image too: ```sh docker rmi traefik:v3.7 ``` If you used Caddy instead: ```sh docker rmi lucaslorentz/caddy-docker-proxy ``` *** Verify the removal [#verify-the-removal] Confirm that no Coolify control-plane containers remain: ```sh docker ps -a --format '{{.Names}}' | grep -E '^(coolify|coolify-db|coolify-redis|coolify-realtime|coolify-sentinel|coolify-proxy)(_|$)' || true ``` The command should return no container names. Then confirm that Docker reports the `coolify-db` and `coolify-redis` volumes as missing and that `/data/coolify` no longer exists: ```sh docker volume inspect coolify-db coolify-redis test ! -d /data/coolify && echo "Coolify data directory removed" ``` `docker volume inspect` should report that the two volumes do not exist. If applications or services remain on the server, manage or migrate them directly with Docker and replace Coolify Proxy routing before exposing them publicly again. Remove the Coolify Cloud services [#remove-the-coolify-cloud-services] Before you uninstall [#before-you-uninstall-1] * Cancel your subscription from [Billing page](https://app.coolify.io/subscription/) * Plan a replacement proxy before continuing if your resources use Coolify-managed domains or TLS certificates. *** Connect to the server [#connect-to-the-server] Connect to the server that you connected to Coolify Cloud: ```sh ssh root@ ``` Replace `` with your server's IP address. If you normally sign in with a non-root account, run `sudo -i` first to open a root shell. Remove Coolify containers [#remove-coolify-containers-1] Remove the proxy according to the Docker mode used by the server. For a standalone Docker server, run: ```sh docker rm -f coolify-proxy ``` For a Docker Swarm server, run this command on a manager node instead: ```sh docker stack rm coolify-proxy ``` Then remove Sentinel if it is running on the server: ```sh if docker container inspect coolify-sentinel >/dev/null 2>&1; then docker rm -f coolify-sentinel fi ``` Removing Coolify Proxy stops the domains and TLS routing it provides. Remove the Coolify network [#remove-the-coolify-network-1] If application or service containers still use the `coolify` network, connect them to another network before removing it. If you want them to keep using the `coolify` network, leave the network in place and skip the command below. When no workloads need the network, remove it: ```sh docker network rm coolify ``` Delete Coolify files [#delete-coolify-files-1] Back up any application or service files you still need from this server, then remove the Coolify data directory: ```sh rm -rf /data/coolify ``` This permanently deletes files Coolify stored under `/data/coolify` on this server, including deployment and configuration files. Remove Docker images [#remove-docker-images-1] Image tags can vary depending on when you last updated Coolify. Run `docker images` to see the images and tags on your server, then use those tags in the commands below. Remove the default Coolify images to free disk space: ```sh docker rmi ghcr.io/coollabsio/coolify-helper:latest docker rmi ghcr.io/coollabsio/sentinel:1.0.1 ``` If you used the default Traefik proxy, remove its image too: ```sh docker rmi traefik:v3.7 ``` If you used Caddy instead: ```sh docker rmi lucaslorentz/caddy-docker-proxy ``` *** Verify the removal [#verify-the-removal-1] Confirm that no Coolify control-plane containers remain: ```sh docker ps -a --format '{{.Names}}' | grep -E '^coolify-(proxy|sentinel)(_|$)' || true ``` The command should return no container names. If applications or services remain on the server, manage or migrate them directly with Docker and replace Coolify Proxy routing before exposing them publicly again. # Update Coolify Database (/docs/core/instance-management/update-coolify-database) Update Coolify Database [#update-coolify-database] Coolify stores its projects, resources, settings, and deployment history in an internal PostgreSQL database. The database runs in the `coolify-db` container. Coolify Cloud users cannot access the internal Coolify database. If you see any `500` status code errors while accessing Coolify Cloud, [contact the Coolify team](/support). A normal [Coolify update](/core/instance-management/update) does not migrate this database to a newer PostgreSQL major version. Major-version changes require the migration script described on this page. This procedure does not apply to PostgreSQL databases that you deploy as project resources. Back up and upgrade those databases separately. Before you update [#before-you-update] * [Create an instance backup](/core/backup-and-recovery/instance-backup), copy the backup outside the Coolify server, and confirm that `/data/coolify/source/.env` is saved outside the server. It contains the instance `APP_KEY`. * Let active deployments finish before starting the migration. * Choose a PostgreSQL major version newer than the version currently used by `coolify-db`. The migration script keeps the previous PostgreSQL Docker volume and creates an on-server database dump. These are rollback safeguards, but neither replaces the external instance backup. *** Update the database [#update-the-database] Check the migration script [#check-the-migration-script] On the server that runs Coolify, confirm that the script exists and is executable: ```sh test -x /data/coolify/source/upgrade-postgres.sh \ && echo "PostgreSQL upgrade script is ready" ``` If the command prints nothing, [update Coolify](/core/instance-management/update) and check again. The Coolify installer and updater download the current migration script but do not run it automatically. Check the current PostgreSQL version [#check-the-current-postgresql-version] Confirm that `coolify-db` is running and print its active PostgreSQL version: ```sh docker ps --filter name=coolify-db --format '{{.Names}} {{.Status}}' docker exec coolify-db sh -lc \ 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atc "SHOW server_version;"' ``` The first command should show `coolify-db` as running. The second command prints the current PostgreSQL version. The target must be a numeric PostgreSQL major version of `10` or newer, and it must be higher than the major version reported above for the running `coolify-db` container. The script does not support downgrading by passing an older version number. Run the database update [#run-the-database-update] The script stops the `coolify` application container before creating the database dump and keeps it stopped during the migration. Applications, databases, services, and Coolify Proxy managed by the instance continue running. Run the script with the target PostgreSQL major version. This example upgrades the internal database to PostgreSQL 18: ```sh /data/coolify/source/upgrade-postgres.sh 18 ``` Replace `18` with your target major version. Do not close the shell while the script is running. The script performs these actions in order: 1. Detects the active PostgreSQL version, image, Docker volume, and mount path. 2. Stops the `coolify` application container to prevent writes. 3. Creates a compressed `pg_dumpall` backup under `/data/coolify/backups/internal-postgres/`. 4. Creates a new Docker volume and starts a temporary container with the target PostgreSQL version. 5. Restores the dump into the new volume and checks that the Coolify database responds. 6. Saves rollback metadata and writes a Docker Compose override for the new image and volume. 7. Replaces the `coolify-db` container and starts the Coolify stack with the upgraded database. If something goes wrong during the update, the script stops as soon as it encounters an error. Keep the terminal output and review `/data/coolify/source/postgres-upgrade-.log` for the migration progress and recorded command output. Verify the database update [#verify-the-database-update] Run the version check again: ```sh docker exec coolify-db sh -lc \ 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atc "SHOW server_version;"' ``` Confirm that the output starts with the target major version. Then open the Coolify dashboard and check that: * the dashboard loads without a database error * your projects and resources are present * **Servers > localhost** validates successfully * other managed servers still connect *** Roll back the database update [#roll-back-the-database-update] If the updated database does not work, run the rollback command: ```sh /data/coolify/source/upgrade-postgres.sh rollback ``` Rollback reads `/data/coolify/source/postgres-upgrade-rollback.env`, switches the Coolify stack back to the previously active PostgreSQL image, Docker volume, and mount path, then starts the stack. Rollback requires the metadata file and previous Docker volume to remain on the Coolify server. Each successful database update replaces the rollback metadata, so the command can restore only the database version used before the latest update. | Database update history | Version restored by rollback | | ----------------------------------------------- | ---------------------------- | | PostgreSQL 15 to PostgreSQL 18 | PostgreSQL 15 | | PostgreSQL 15 to PostgreSQL 18 to PostgreSQL 19 | PostgreSQL 18 | The rollback does not delete the updated Docker volume. Keep it until you have confirmed that the previous database version and Coolify dashboard work. Remove unused volumes only after identifying them and confirming that they are no longer needed. Verify the rollback [#verify-the-rollback] Check the active PostgreSQL version: ```sh docker exec coolify-db sh -lc \ 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atc "SHOW server_version;"' ``` Confirm that the output starts with the version shown in the **Version restored by rollback** column. Then open the Coolify dashboard and check that: * the dashboard loads without a database error * your projects and resources are present * **Servers > localhost** validates successfully * other managed servers still connect *** How the database update changes Docker Compose [#how-the-database-update-changes-docker-compose] The migration script does not change `/data/coolify/source/docker-compose.yml` or `/data/coolify/source/docker-compose.prod.yml`. It creates this override instead: ```sh /data/coolify/source/docker-compose.postgres-upgrade.yml ``` For an upgrade to PostgreSQL 18 using the default volume name, the file contains configuration similar to this: ```yaml services: postgres: image: "postgres:18-alpine" volumes: - coolify-db:/var/lib/postgresql volumes: coolify-db: name: "coolify-db-pg18" external: true ``` PostgreSQL 18 and newer use `/var/lib/postgresql` as the container mount path. Earlier versions use `/var/lib/postgresql/data`. The script selects the correct path for the target version. Future Coolify updates include `docker-compose.postgres-upgrade.yml` when the file exists, so the upgraded PostgreSQL image and volume remain active. If `/data/coolify/source/docker-compose.custom.yml` also exists, the PostgreSQL upgrade override is loaded after it and takes precedence for conflicting `postgres` service settings. To inspect the complete Compose configuration in the same order Coolify loads it, run the following commands from a Bash shell on the Coolify server: ```bash cd /data/coolify/source compose_files=(-f docker-compose.yml -f docker-compose.prod.yml) [[ -f docker-compose.custom.yml ]] \ && compose_files+=(-f docker-compose.custom.yml) [[ -f docker-compose.postgres-upgrade.yml ]] \ && compose_files+=(-f docker-compose.postgres-upgrade.yml) docker compose --env-file .env "${compose_files[@]}" config ``` *** Files created by the database update [#files-created-by-the-database-update] | File | Purpose | | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | `/data/coolify/source/docker-compose.postgres-upgrade.yml` | Keeps the upgraded PostgreSQL image, Docker volume, and mount path active during normal Coolify updates. | | `/data/coolify/source/postgres-upgrade-rollback.env` | Records the previously active database image, Docker volume, mount path, and override state for rollback. | | `/data/coolify/source/postgres-upgrade-.log` | Records the migration or rollback actions and errors. | | `/data/coolify/backups/internal-postgres/postgres-upgrade-.sql.gz` | Contains the compressed `pg_dumpall` backup created before the database is migrated. | # Update Coolify (/docs/core/instance-management/update) Update Coolify [#update-coolify] Updating Coolify changes the self-hosted Coolify control plane. It does not update the applications, databases, services, or servers you manage with Coolify. If you use **Coolify Cloud**, the Coolify team manages instance updates. You must wait for the Coolify team to update the instance. For a self-hosted instance, open **Settings** in the left sidebar, select **Updates**. Before you update [#before-you-update] * [Create an instance backup](/core/backup-and-recovery/instance-backup). * Review the [release notes](https://github.com/coollabsio/coolify/releases) for the version you plan to install. * Check for active deployments; they can fail during the update process. Read the [Reverb migration guide](/core/instance-management/reverb-migration) before you update if you use custom Compose overrides, realtime ports, firewall rules, or Cloudflare Tunnels. *** Choose an update path [#choose-an-update-path] Automatic updates [#automatic-updates] Enable **Automatic updates** and set **Update frequency**. Coolify then checks for a new release and installs it automatically when one is available. Enable automatic updates [#enable-automatic-updates] Choose **Enabled** under **Automatic updates**. This option saves immediately, and **Update frequency** becomes available. If automatic updates cannot be configured in the dashboard, `AUTOUPDATE` is set in `/data/coolify/source/.env`. Configure automatic updates in that file instead. Update frequency [#update-frequency] **Update frequency** sets how often Coolify checks for a new release and installs it if one is available. Enter a cron expression or a preset such as `every_minute`, `hourly`, `daily`, `weekly`, `monthly`, or `yearly`, then click **Save changes**. The default is `0 0 * * *`, which runs daily at midnight in the instance timezone. During an update, Coolify restarts to apply the new version. The dashboard is unavailable briefly, usually for less than a minute. **Update frequency is unavailable when `AUTOUPDATE` is set in `/data/coolify/source/.env`.** Check frequency [#check-frequency] **Check frequency** sets how often Coolify checks the [versions file on the CDN](https://cdn.coollabs.io/coolify/versions.json) and updates the available-version status. Coolify installs an update only when a new version is available. Enter a cron expression or a preset such as `every_minute`, `hourly`, `daily`, `weekly`, `monthly`, or `yearly`, then click **Save changes**. The default is `0 * * * *`, which runs hourly. Click **Check now** to check for a new version immediately. This does not install the update. Manual updates via dashboard [#manual-updates-via-dashboard] Open the **Settings** page, then select **Updates**. Check frequency [#check-frequency-1] When a new version is available, Coolify shows **Update available** beside the version number at the top left of the sidebar. **Check frequency** controls how often Coolify checks the [versions file on the CDN](https://cdn.coollabs.io/coolify/versions.json). To check immediately, click **Check now** in the **Update checks** section. This checks for an update but does not install it. Update Coolify [#update-coolify-1] Click **Upgrade Now** in the **Update Coolify** section, or click **Update available** beside the version number in the sidebar. Both options open the upgrade modal. Review update version [#review-update-version] Review the current and new version in the modal. Check that no deployments are pending or running, because deployments during the update will fail. Then click **Upgrade Now** to start the update. Wait for the update to finish [#wait-for-the-update-to-finish] An update usually takes less than a minute. It can take longer depending on network conditions and server resources. Coolify restarts while applying the update, so the dashboard may be unavailable briefly. If the progress modal remains on **Restart** for more than five minutes, refresh the page. Coolify may have finished updating but failed to reload the page automatically. If you see a **Gateway Timeout** or **Bad Gateway** error, wait two minutes before refreshing. If the error remains after refreshing, check the update logs under `/data/coolify/source/upgrade-*`. Upgrade complete [#upgrade-complete] When all update stages are complete, Coolify confirms the new version and reloads the page. If the page does not reload automatically, click **Reload Now**. Manual update via terminal [#manual-update-via-terminal] Use the Coolify upgrade script to update an existing instance. On an existing instance, `install.sh` resets ownership and permissions under `/data/coolify`, including managed service data. Use `upgrade.sh` instead. **Connect to the Coolify server** Connect to the server that runs the Coolify instance over SSH: ```sh ssh @ ``` **Run the upgrade script** Run the upgrade script with the Coolify version you want to install. Use the version without a leading `v`. ```sh curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh | bash -s 4.3.23 ``` Replace `4.3.23` with the Coolify version you want to install. The upgrade script updates configuration files from the [versions file on the CDN](https://cdn.coollabs.io/coolify/versions.json) as part of the process. Do not omit the version. Without one, the script writes `COOLIFY_VERSION=latest` to `.env`, which prevents update checks from working correctly. **Visit the dashboard** Wait for the script to finish, then open the dashboard and confirm everything is working. *** Verify the update [#verify-the-update] After an update, confirm that the dashboard is reachable, the expected Coolify version is shown, and your resources are running. If the dashboard does not return, review the update logs on the Coolify server. Coolify writes update logs under `/data/coolify/source/` with names such as `upgrade-2026-07-11-12-00-00.log`. # Create a Destination (/docs/core/networking/destinations/create) Create a destination [#create-a-destination] Create a destination when you need another Docker network for isolation. Before you start [#before-you-start] You need: * a validated, reachable server that can run deployed resources * a Docker network name that is not already registered as a destination on that server A build server cannot be selected as a deployment destination. If you still need to connect a server, follow [Add Server](/core/infrastructure/servers/add-server) first. Create a new destination [#create-a-new-destination] Open the new destination form [#open-the-new-destination-form] 1. Select **Destinations** in the Coolify sidebar. 2. Select **New destination**. You can also open **Servers**, select a server, open **Destinations**, and select **+ Add**. Coolify uses the selected server in the form. Configure the destination [#configure-the-destination] Review the generated values before continuing:
Field What to enter
Name A recognizable name for the network in the Coolify dashboard. Coolify initially combines the server name and generated network value.
Network The Docker network name. Keep the generated value or enter a name that starts with a letter or number and contains only letters, numbers, periods, hyphens, and underscores.
Server The validated, reachable server where the Docker network should exist.
The **Network** value can contain up to 255 characters and must be unique among destinations of the same type on that server. You cannot change this value after creating the destination.
Create and verify the destination [#create-and-verify-the-destination] Select **Create destination**. Coolify records the destination, creates the Docker network when it does not already exist, and connects the Coolify Proxy to the networks it needs on the server. The destination's **General** page opens after creation. Confirm that **Name**, **Server IP**, and **Docker Network** show the values you selected.
Import an existing Docker network [#import-an-existing-docker-network] Use the server's destination scanner when the Docker network already exists but does not appear in Coolify. Scan the server [#scan-the-server] 1. Select **Servers** in the Coolify sidebar. 2. Select the server that owns the Docker network. 3. Open **Destinations**. 4. Select **Scan networks**. Coolify excludes the built-in `bridge`, `host`, and `none` networks, along with networks already registered as destinations. Add the discovered network [#add-the-discovered-network] Under **Discovered networks**, select **Add \** for the network you want to use. Coolify adds the network under **Destinations** and connects the Coolify Proxy to the server networks it needs. Select the destination and confirm that its **Docker Network** value matches the existing network name. Troubleshooting [#troubleshooting] Open the existing destination instead of creating another entry for the same network. Confirm that the server belongs to the current team and is validated, reachable, and not configured only as a build server. Start the name with a letter or number and remove spaces or characters other than periods, hyphens, and underscores. # Delete Destination (/docs/core/networking/destinations/delete) Delete a destination [#delete-a-destination] Deleting a standalone Docker destination removes the destination from Coolify and removes its Docker network from the server. The default `coolify` destination cannot be deleted from the dashboard. Before you delete [#before-you-delete] Open the destination and select **Resources**. Review every application, database, and service listed on the page. For each resource you want to keep: * back up its database and persistent-storage data * recreate or clone the resource to another destination * restore or migrate its data separately because cloning copies configuration only Deleting a Docker network can interrupt containers that still use it. Continue only after **Resources** shows **No resources are using this destination**. Delete the destination [#delete-the-destination] Open the destination [#open-the-destination] 1. Select **Destinations** in the Coolify sidebar. 2. Select the destination you want to delete. 3. Open **Danger Zone**. Confirm the deletion [#confirm-the-deletion] 1. Select **Delete destination**. 2. Review the deletion action. 3. Enter the destination name exactly as shown. 4. Select **Permanently Delete**. Coolify disconnects the Coolify Proxy from the network, removes the Docker network from the server, and removes the destination from Coolify. Verify the deletion [#verify-the-deletion] Open the global or server-specific **Destinations** page and confirm that the deleted destination no longer appears. If you need the destination again [#if-you-need-the-destination-again] There is no restore action for a deleted destination. Follow [Create a Destination](/core/networking/destinations/create), then redeploy or restore each resource separately. # Manage Destinations (/docs/core/networking/destinations/manage) Manage destinations [#manage-destinations] Use the **Destinations** pages to review Docker networks across your team's servers, see which resources use a network, and change or remove a destination. Find a destination [#find-a-destination] Select **Destinations** in the Coolify sidebar to see destinations across all usable servers in the current team. Each entry shows the destination name and its server. To see destinations for one server, select **Servers**, choose the server, and open **Destinations**. Review destination details and resources [#review-destination-details-and-resources] Select a destination to open its management page. * **General** shows its dashboard name, server IP address, and Docker network name. * **Resources** lists the applications, databases, and services recorded against a standalone Docker destination. Use the search field to filter by resource, project, environment, or type. | Field | Behavior | | :----------------- | :------------------------------------------------------------------------ | | **Name** | Editable dashboard label. Renaming it does not rename the Docker network. | | **Server IP** | Read-only address of the server that owns the destination. | | **Docker Network** | Read-only Docker network name used on the server. | Rename a destination [#rename-a-destination] 1. Open the destination's **General** page. 2. Change **Name**. 3. Select **Save changes**. 4. Return to **Destinations** and confirm that the new name appears with the same server. The server and Docker network cannot be changed after creation. Create another destination if a resource needs a different server or network. Choose a destination for a new resource [#choose-a-destination-for-a-new-resource] When you create an application, database, or service, Coolify asks you to select a server. * If the server has one destination, Coolify selects it automatically. * If the server has more than one destination, select the destination whose Docker network the resource should use. The selected destination becomes part of the resource configuration. Coolify does not provide an in-place action that changes an existing resource to another destination. Clone a resource to another destination [#clone-a-resource-to-another-destination] Clone a resource when you need a separate copy of its configuration on another server or Docker network. 1. Open the resource in its project and environment. 2. Select **Resource Operations** in the resource sidebar. 3. Under **Clone to another destination**, choose **Server**. 4. Choose **Network destination**. 5. Select **Clone resource**. 6. Open the cloned resource and verify its destination and configuration before deploying it. Cloning duplicates configuration such as environment variables and build settings. It does not copy database contents, persistent-storage files, or data held by an external provider. The original resource remains unchanged. Use a backup or a resource-specific migration procedure when the clone also needs existing data. **Move Resource** on the same page changes only the project or environment; it does not change the server or network destination. Connect Docker Compose resources [#connect-docker-compose-resources] Docker Compose applications and service stacks use a resource-specific network by default, even though the resource has a selected destination. Enable **Connect To Predefined Network** in the resource settings when its containers must join the selected destination and communicate with other resources on that Docker network. Read [Docker Compose networking](/applications/builds/docker-compose#application-networking) for the Compose requirements and limitations. Do not add a custom Compose network only to reproduce a Coolify destination. Conflicting network configuration can prevent the Coolify Proxy from reaching the resource. To remove a destination and its Docker network, follow [Delete Destination](/core/networking/destinations/delete). # Destinations Overview (/docs/core/networking/destinations/overview) Destinations overview [#destinations-overview] A destination represents a Docker network on one of your servers. Selecting a destination tells Coolify which server and Docker network to use for an application, database, or service. Each destination belongs to one server. A server can have more than one destination, and a destination can be used by multiple resources. Coolify creates a destination named `coolify` during installation. Applications use this destination by default. Docker Compose applications are the exception: they use their own resource-specific network unless you enable **Connect To Predefined Network**. What a destination controls [#what-a-destination-controls] A destination combines three pieces of information: | Property | Purpose | | :----------------- | :------------------------------------------------------------------ | | **Name** | Identifies the destination in the Coolify dashboard. | | **Server** | Identifies the machine where the resource will run. | | **Docker Network** | Identifies the Docker network the resource can join on that server. | Resources on the same Docker network can communicate through container or service names and internal ports. Resources on separate networks remain isolated unless you connect them to a shared network. A destination does not move traffic between servers. It also does not replace DNS, firewall, or proxy configuration. Read [Networking in Coolify](/core/networking-in-coolify) for the complete path between a public domain, the Coolify Proxy, Docker networks, and resource containers. The default destination [#the-default-destination] The default `coolify` destination represents the `coolify` Docker network on the server. When you create a resource, Coolify first asks you to select a server. If the server has only one destination, Coolify selects it automatically. If the server has multiple destinations, you choose the Docker network for the new resource. The default `coolify` destination cannot be deleted from the dashboard. When to create another destination [#when-to-create-another-destination] Most deployments only need the default `coolify` destination. Create another destination when selected applications need to use a separate Docker network instead of the default network. Creating more destinations does not create more servers. Every destination still belongs to one connected server. Destination behavior for Docker Compose [#destination-behavior-for-docker-compose] Docker Compose applications and service stacks use a resource-specific Docker network by default. They do not join their selected Coolify destination automatically. Enable **Connect To Predefined Network** when a Docker Compose resource must communicate with other resources through its Coolify destination. Review [Docker Compose networking](/applications/builds/docker-compose#application-networking) before enabling the setting. Existing Coolify v4 Docker Swarm destinations may still appear with a **Deprecated** badge. Do not create a new Swarm deployment. Read [Docker Swarm (Deprecated)](/core/infrastructure/scaling/docker-swarm) when maintaining an existing deployment. Continue with destinations [#continue-with-destinations] # DNS (/docs/core/networking/dns) DNS [#dns] DNS connects a domain such as `app.example.com` to the server that runs your Coolify resource. Coolify configures the resource route and proxy, but you create and manage DNS records with your DNS provider. Point each domain to the server where the application or service runs, not to the server that runs the Coolify dashboard. Point a domain to the server [#point-a-domain-to-the-server] 1. Open the resource in Coolify and identify its server. 2. Copy the server's public IPv4 address. If you use IPv6, copy its public IPv6 address as well. 3. Open the DNS zone with the provider that manages your domain. 4. Create the DNS record for the hostname you want to use. 5. Wait until public DNS resolvers return the new value. 6. Follow [Add a custom domain](/core/networking/domains#add-a-custom-domain) to configure the matching URL in Coolify and redeploy the resource. For example, to use `app.example.com` with a server at `203.0.113.10`, create this record: | Type | Name | Value | | :--- | :---- | :------------- | | `A` | `app` | `203.0.113.10` | DNS providers use different names for the **Name** field. Some display the complete hostname instead of `app`. You can point several root domains and subdomains to the same server IP address. The Coolify Proxy uses the requested hostname to route each request to the correct resource. Choose the DNS record [#choose-the-dns-record] | What you want to use | Record | Name at most providers | Value | | :----------------------------- | :----- | :----------------------- | :--------------------------- | | `example.com` | `A` | `@` or empty | Server's public IPv4 address | | `app.example.com` | `A` | `app` | Server's public IPv4 address | | Any subdomain of `example.com` | `A` | `*` | Server's public IPv4 address | | An IPv6 route | `AAAA` | `@`, a subdomain, or `*` | Server's public IPv6 address | Create an `AAAA` record only when the server and its network path accept IPv6 traffic. If a hostname has both `A` and `AAAA` records, both addresses must reach the same intended resource path. A broken IPv6 path can cause domain or certificate requests to fail even when IPv4 works. For a self-hosted Coolify dashboard domain, point the record to the server that runs the Coolify instance. Then follow [Set the Coolify dashboard domain](/core/networking/domains#set-the-coolify-dashboard-domain) to configure the URL. Verify the DNS change [#verify-the-dns-change] DNS changes may take time to propagate because resolvers cache the previous result. Check the public result before troubleshooting Coolify. Run the following command from your computer, replacing the hostname with your domain: ```sh dig +short app.example.com A ``` The output should contain the public IPv4 address of the server that runs the resource. If you created an `AAAA` record, check it separately: ```sh dig +short app.example.com AAAA ``` You can also query the default Coolify validation resolver directly: ```sh dig @1.1.1.1 +short app.example.com A ``` If the result is empty or shows an unexpected address, check the record name, value, and DNS zone at your provider. If the result is correct but the domain does not open, confirm that: * the resource uses the same domain in Coolify * the domain points to the server where that resource runs * ports `80` and `443` are open on the server * the Coolify Proxy is running on the server * the application listens on the container port configured in Coolify Configure wildcard DNS [#configure-wildcard-dns] A wildcard DNS record lets multiple subdomains resolve to the same server without a separate record for each name. For example, create this record to send subdomains of `example.com` to `203.0.113.10`: | Type | Name | Value | | :--- | :--- | :------------- | | `A` | `*` | `203.0.113.10` | The wildcard record covers matching subdomains, but it does not cover the apex domain `example.com`. Create a separate record for the apex domain when you also use it. After the wildcard record resolves to the server, follow [Use generated domains](/core/networking/domains#use-generated-domains) to configure **Wildcard Domain** and generate application URLs in Coolify. Preview deployments can generate additional subdomains from the application's preview URL template. Make sure the DNS records cover those names before relying on the generated preview URLs. See [Preview Deployments](/applications/deployments/preview-deployments) for the preview-specific setup. Configure Coolify DNS validation [#configure-coolify-dns-validation] Coolify can check application domains and the self-hosted instance URL against public DNS. DNS validation is enabled by default. Open **Settings > Advanced** to manage: * **DNS Validation**: enables or disables the check. * **Custom DNS Servers**: sets the resolvers used for the check. The default is `1.1.1.1`. Enter a comma-separated list of IPv4 or IPv6 resolver addresses, such as `1.1.1.1,8.8.8.8`, or leave the field empty to use the system resolvers. Current DNS validation checks the domain's `A` records. Validation succeeds when an address matches the selected server's IPv4 address or a recognized Cloudflare proxy address. Coolify skips this check for generated `sslip.io` domains. DNS validation reports a mismatch, but it does not replace a public DNS check. A cached resolver result, an incorrect `AAAA` record, firewall rules, or a proxy configuration can still prevent the domain from working. Use internationalized domain names [#use-internationalized-domain-names] Convert domains that contain non-ASCII characters to [Punycode](https://en.wikipedia.org/wiki/Punycode) before you create DNS records or enter the domain in Coolify. For example, use `xn--mnchen-3ya.example.com` for `münchen.example.com`. Some DNS providers perform this conversion automatically, but the DNS record and the domain saved in Coolify must resolve to the same hostname. Related networking guides [#related-networking-guides] If DNS resolves correctly but HTTPS still fails, follow [Let's Encrypt troubleshooting](/troubleshoot/dns-and-domains/lets-encrypt-not-working). Cloudflare managed records [#cloudflare-managed-records] With a team Cloudflare integration token, Coolify can create, replace, and remove managed DNS records from resource Domains pages. Follow [Cloudflare DNS management](/integrations/security/cloudflare/dns-management) for token permissions and record lifecycle. # Domains (/docs/core/networking/domains) Domains [#domains] Coolify uses domains to route public HTTP and HTTPS traffic through the proxy to an application or a web-facing service container. The domain's DNS record points to the server running the resource. The Coolify proxy then matches the hostname and path and forwards the request to the correct container port. Complete the [DNS setup](/core/networking/dns), add the hostname on **Domains**, choose **http** or **https** in **Protocol**, and redeploy the resource. Use `https://` for automatic TLS. Add a port to target a specific port inside the container, or add a path to share one hostname between resources. *** Choose a domain option [#choose-a-domain-option] Choose the option that matches how you plan to use the resource. A domain does not expose a standalone database. Use the database's public port when an external client must connect. These instructions assume the server uses the integrated Traefik or Caddy proxy. With **Custom (None)**, you must configure routing and TLS in your own proxy. See [Proxy overview](/core/networking/proxy/overview) before continuing. *** Add a custom domain [#add-a-custom-domain] Before starting, [point the domain to the resource server and verify its DNS records](/core/networking/dns#point-a-domain-to-the-server). Inbound TCP ports `80` and `443` must be open on the resource server, and the application must listen on the container port that Coolify will target. Enter the domain in Coolify [#enter-the-domain-in-coolify] Open the application or Service, then select **Domains** in its settings sidebar. 1. Select **Add domain**. 2. Choose **https** or **http** in **Protocol**. 3. Enter the hostname in **Domain**, for example `app.shadowarcanist.com`. 4. Set **Port** when the proxy must target a specific container port, and **Path** when routing a prefix such as `/api`. 5. For Docker Compose, choose the non-database **Service** that receives the request. 6. Select **Add domain** to save the route. Review any DNS or domain-conflict warning before proceeding. Redeploy and verify the domain [#redeploy-and-verify-the-domain] Redeploy the resource so the proxy uses the new configuration. After the deployment completes: 1. Confirm the hostname resolves to the expected server or CDN. 2. Open the configured URL in a browser. 3. Confirm it loads the intended application. 4. For an `https://` URL, confirm the browser shows the expected certificate. If DNS was changed recently, you may need to wait for the previous record's TTL to expire. Supported domain formats [#supported-domain-formats] The domain form separates **Protocol**, **Domain**, **Port**, and **Path**. The examples below show the resulting URLs; add each hostname as a separate domain. | Goal | Resulting URL | | :------------------------------------ | :------------------------------------------------ | | Route one hostname | `https://app.example.com` | | Route multiple hostnames | `https://app.example.com,https://www.example.com` | | Target container port `3000` | `https://app.example.com:3000` | | Route a path to container port `80` | `https://app.example.com/api` | | Route a path to container port `8080` | `https://app.example.com:8080/api` | When **Port** is empty, a standard application uses the first value in **Ports exposes**, and a static site uses port `80`. Docker Compose routes use the selected service's detected port when available. Set **Port** explicitly when the detected default does not match the application. Add multiple hostnames with **Add domain**, one at a time. Coolify normalizes application domains and rejects duplicate entries. When a value contains both a port and a path, put the port before the path: * Correct: `https://app.shadowarcanist.com:8080/api` * Incorrect: `https://app.shadowarcanist.com/api:8080` *** Route to a port or path [#route-to-a-port-or-path] The port in a domain value selects the port inside the container. It does not create a public host-port mapping. Visitors still reach an `https://` domain through the proxy on port `443`. | Domain value | Proxy behavior | | :------------------------------------ | :---------------------------------------------------------------------------- | | `https://app.shadowarcanist.com` | Send requests for the hostname to the resource's default container port. | | `https://app.shadowarcanist.com:3000` | Send requests for the hostname to port `3000` inside the container. | | `https://shadowarcanist.com/api` | Send requests beginning with `/api` to the resource's default container port. | | `https://shadowarcanist.com:8080/api` | Send requests beginning with `/api` to port `8080` inside the container. | Path-based routes let several resources share one hostname. For example, one application can use `https://shadowarcanist.com`, while another uses `https://shadowarcanist.com/api`. Coolify creates a path-prefix route from the value. More specific paths take priority over the root route in the proxy's routing model. Control prefix stripping [#control-prefix-stripping] By default, Coolify strips the configured prefix before forwarding the request. A request to `https://shadowarcanist.com/api/users` reaches the application as `/users`. For an application, open **Advanced > Proxy** and choose **Keep paths as-is** in **Path prefixes** when it expects to receive `/api/users` instead. Keep every resource serving a shared hostname running and healthy. If a path route is unavailable, the result depends on the remaining proxy routes and application responses. *** Configure HTTPS and redirects [#configure-https-and-redirects] Use an `https://` URL when you want the integrated proxy to configure TLS. Coolify generates the route, and Traefik or Caddy requests and renews the certificate. An `http://` value creates an HTTP route. Other resource or proxy settings can still redirect that route to HTTPS. The hostname must resolve through the resource server or a correctly configured CDN, ports `80` and `443` must reach the Coolify proxy, and the domain must be present in the resource configuration. If the browser shows a certificate warning, follow [Let's Encrypt not working](/troubleshoot/dns-and-domains/lets-encrypt-not-working). For wildcard certificates, follow the guide for [Traefik](/core/networking/proxy/traefik/wildcard-certs) or the [Caddy DNS challenge](/core/networking/proxy/caddy/dns-challenge). Redirect www and non-www [#redirect-www-and-non-www] Add both hostnames on **Domains** and create DNS records for both. Edit a domain, then use **www redirect** to choose the canonical hostname. For a Compose application, this choice applies to all domains of the selected service. | **www redirect** | Behavior | | :---------------------- | :------------------------------------------------------------------ | | **No redirect** | Serve both configured hostnames without a Coolify-managed redirect. | | **Redirect to www** | Redirect the non-www hostname to the configured `www` hostname. | | **Redirect to non-www** | Redirect the `www` hostname to the configured non-www hostname. | Coolify will not enable **Redirect to www** unless a `www` URL is present in **Domains**. The corresponding `www` DNS record must also resolve to the resource server. *** Control search engine indexing [#control-search-engine-indexing] Coolify can mark individual application and service domains as **Noindex** without changing application code. The integrated Traefik or Caddy proxy then adds this response header for that domain: ```http X-Robots-Tag: noindex, nofollow ``` A resource with several domains can keep its production domain indexable while marking a staging or temporary domain as noindex. 1. Open the application or Service and select **Domains** in its settings sidebar. 2. Edit the domain. 3. Choose **Noindex** in **Search engine indexing**, then save. Choose **Indexable** to remove the header. 4. Redeploy the resource to apply the updated proxy configuration. 5. Check the response header: ```sh curl -sI https://staging.example.com | grep -i x-robots-tag ``` A noindex domain returns: ```http x-robots-tag: noindex, nofollow ``` Preview deployment domains are always served as noindex. Removing a domain also removes its stored indexing selection; renaming a domain preserves the selection for the renamed domain. Search crawlers can choose whether to honor this header, and anyone who knows the URL can still open it. Use authentication or network restrictions when access must be limited. For applications, the selector is available while **General > Container labels > Label management** is set to **Managed by Coolify (auto-generated)**. When you choose manual label management, add the equivalent `X-Robots-Tag` response header in your custom proxy labels. *** Use generated domains [#use-generated-domains] Coolify can generate an application domain from the server's **Wildcard Domain** setting. Before configuring generated domains, [create and verify a wildcard DNS record](/core/networking/dns#configure-wildcard-dns) for the server. Configure the server wildcard domain [#configure-the-server-wildcard-domain] In Coolify, open **Servers**, select the server, and open **General**. Enter `https://shadowarcanist.com` in **Wildcard Domain**, then save the server. Generate an application domain [#generate-an-application-domain] Open an application on that server, select **Domains**, then **Add domain**. Use **Generate domain** in the form, review the generated values, and add the domain. Coolify generates a hostname such as `https://.shadowarcanist.com`. Open the generated URL after redeploying the application to confirm it works. The wildcard setting affects generated domains; it does not change domains already assigned to resources. When **Wildcard Domain** is empty, Coolify can generate an `sslip.io` domain from the server IP address. Use that URL to verify a deployment or proxy route before configuring your own domain. *** Use sslip.io testing domains [#use-sslipio-testing-domains] When a server has no [Wildcard Domain](#use-generated-domains) configured, Coolify generates an [sslip.io](https://sslip.io?utm_source=coolify.io) domain from the server IP address when you create a resource. `sslip.io` is a free, public DNS service that resolves any subdomain that contains an IP address back to that IP address. There is nothing to register, no DNS record to create, and no certificate to install — it is a *magic resolver*: * `1.2.3.4.sslip.io` resolves to `1.2.3.4` * `anything.1.2.3.4.sslip.io` also resolves to `1.2.3.4` * `myapp.staging.1.2.3.4.sslip.io` also resolves to `1.2.3.4` Because the IP address is encoded into the hostname, sslip.io answers for an unlimited number of subdomains without anyone configuring DNS in advance. This gives you a working URL on a fresh server in seconds, before you point a real domain. The generated URL always uses `http://`. Do not change it to `https://`: [Let's Encrypt](https://letsencrypt.org?utm_source=coolify.io) rate-limits the entire shared `sslip.io` zone, so certificate issuance fails. Use your own domain, or a wildcard you own, when you need HTTPS. sslip.io domains are best for trying Coolify on a new server, sharing a quick preview link, and internal demos — any flow where plain HTTP and an instantly working URL are enough. Move to a custom domain, or a wildcard you own, before you need TLS, go to production, or share the link with end users. *** Resolve domain conflicts [#resolve-domain-conflicts] Coolify warns when the same complete domain is already assigned to another application, service, or the Coolify dashboard in the same team. Reusing a domain can make routing unpredictable and can prevent the correct TLS certificate from being served. Only one resource can receive the traffic reliably. Open the resource linked in the conflict message and remove or change its domain. Override the warning only when you are deliberately replacing that route. *** Set the Coolify dashboard domain [#set-the-coolify-dashboard-domain] Self-hosted users can assign a domain to the Coolify dashboard from **Settings > General**. Set **URL** to a complete value such as `https://coolify.shadowarcanist.com` only after you [point its DNS record to the server running Coolify](/core/networking/dns#point-a-domain-to-the-server). Do not reuse an application or service domain for the dashboard. Read [Instance settings](/core/instance-management/instance-settings#url) for the complete setting reference. *** Continue with domain routing [#continue-with-domain-routing] Use these guides to prepare the public route or investigate a domain that does not work as expected. Cloudflare managed records [#cloudflare-managed-records] With a team Cloudflare integration token, Coolify can create, replace, and remove managed DNS records from resource Domains pages. Follow [Cloudflare DNS management](/integrations/security/cloudflare/dns-management) for token permissions and record lifecycle. # Basic Authentication (/docs/core/networking/proxy/caddy/basic-auth) Basic authentication [#basic-authentication] HTTP basic authentication requires a username and password before Caddy forwards a request to an application. Coolify can generate the required Caddy label and bcrypt hash for standard applications. HTTP basic authentication protects a route with one shared credential. It does not replace application accounts, role-based access, multi-factor authentication, or single sign-on. Protect a resource [#protect-a-resource] Choose the path that matches how the resource is deployed. Automatic [#automatic] Open the application settings [#open-the-application-settings] Open the application, select **General**, then find **Security > Authentication**. Add the credentials [#add-the-credentials] Choose **HTTP Basic Authentication** in **Authentication**, then enter a **Username** and **Password**. Save the application settings. Coolify hashes the password and adds a `caddy_.basicauth.` label for each generated Caddy route. Redeploy and verify [#redeploy-and-verify] Redeploy the application. Open its domain in a private browser window and confirm that the browser requests the new credentials before loading the application. Manual [#manual] Generate credentials [#generate-credentials] Generate a bcrypt hash with the Caddy CLI: ```bash caddy hash-password --plaintext '' ``` Add the label [#add-the-label] Open the application **General** page, find **Container labels**, then set **Label management** to **Managed manually (edit labels yourself)**. Add one `basicauth` label matching the index Coolify already generated for you domain: ```ini caddy_0.basicauth.="" # [!code ++][!code focus] caddy_0.encode=zstd gzip caddy_0.handle.0_reverse_proxy={{upstreams 3000}} caddy_0.handle=/* caddy_0.header=-Server caddy_0.try_files={path} /index.html /index.php caddy_0=https://domain.com # [!code focus] caddy_ingress_network=coolify ``` Redeploy and verify [#redeploy-and-verify-1] Redeploy the application. Open its domain in a private browser window and confirm that the browser requests the new credentials before loading the application. Generate a bcrypt hash with the Caddy CLI: ```bash caddy hash-password --plaintext '' ``` Add the result to the service labels. The `caddy_0` prefix must match the generated Caddy route index for the domain you want to protect. ```yaml services: app: image: nginx:alpine labels: # [!code ++:2][!code focus:2] - 'caddy_0.basicauth.=""' ``` Save and redeploy the resource. Open the domain in a private browser window to verify the prompt and credentials. Do not place the plaintext password in the label. Caddy expects a supported password hash; `caddy hash-password` generates the correct format. Troubleshooting [#troubleshooting] Confirm the resource was redeployed after enabling authentication or changing its labels. Generate a new hash with `caddy hash-password`, replace the existing label value, and redeploy the resource. Do not use the plaintext password or a hash generated for a different authentication format. Confirm the `caddy_0` route index matches the domain label on the running container. Inspect **Servers > your server > Proxy > Logs** for Caddyfile adaptation or authentication errors. # Custom SSL Certificates (/docs/core/networking/proxy/caddy/custom-ssl-certs) Custom SSL certificates [#custom-ssl-certificates] Caddy normally obtains certificates automatically for HTTPS domains. Use a custom certificate when your organization or another certificate provider manages TLS certificates for you. Caddy supports `tls `, as shown in its [TLS directive examples](https://caddyserver.com/docs/caddyfile/directives/tls#examples). Coolify uses [caddy-docker-proxy](https://github.com/lucaslorentz/caddy-docker-proxy#labels-to-caddyfile-conversion), so you add the equivalent label to the resource's existing Caddy route. Prepare the certificate files [#prepare-the-certificate-files] You need: * a PEM-encoded certificate, including any required intermediate certificates, whose subject alternative names cover the domain * the matching unencrypted private key * shell access to every server whose Caddy proxy serves the domain On each server, create a certificate directory: ```bash sudo install -d -m 700 /data/coolify/proxy/caddy/certs ``` Copy the files from your computer to the server. Replace the paths and server address: ```bash scp /path/to/example.com.crt root@:/data/coolify/proxy/caddy/certs/example.com.crt scp /path/to/example.com.key root@:/data/coolify/proxy/caddy/certs/example.com.key ``` Restrict access to the private key: ```bash sudo chmod 600 /data/coolify/proxy/caddy/certs/example.com.key ``` Transfer the key over an encrypted connection. Never commit it to Git or paste its contents into the Coolify dashboard. If you run Caddy as a non-root user, ensure that user can read the files without making the key publicly readable. Mount the files into Caddy [#mount-the-files-into-caddy] Open **Servers > your server > Proxy > Configuration**. Add this mount to the existing `volumes` list under the `caddy` service, keeping all other configuration: ```yaml services: caddy: volumes: # Keep the existing mounts. - /data/coolify/proxy/caddy/certs:/certs:ro ``` Select **Save changes**, then **Restart Proxy** to apply the new mount. Caddy will read the files at `/certs/example.com.crt` and `/certs/example.com.key` inside the proxy container. Configure the resource's certificate [#configure-the-resources-certificate] Configure an HTTPS domain for the resource, such as `https://example.com`, before adding the certificate label. For a standard application, open **General > Container labels**. Set **Label management** to **Managed manually (edit labels yourself)**. Keep the generated routing labels and add: ```ini caddy_0.tls=/certs/example.com.crt /certs/example.com.key ``` Use the prefix of the existing HTTPS domain label. For example, if `caddy_1=https://example.com`, use `caddy_1.tls` instead. Replace an existing `tls` value for that route rather than adding a second one. For a Docker Compose application, add the same label to the service that receives traffic: ```yaml services: app: labels: # Keep the existing routing labels. - 'caddy_0.tls=/certs/example.com.crt /certs/example.com.key' ``` Save and redeploy the resource. The label produces this Caddyfile directive within the existing site block: ```yaml https://example.com { tls /certs/example.com.crt /certs/example.com.key # Existing routing directives remain here. } ``` This is an illustration of the generated configuration. Configure the label on the existing route so you preserve Coolify's upstream routing. Verify and renew [#verify-and-renew] Open the HTTPS domain and inspect its certificate issuer, hostname coverage, and expiration date. Check **Servers > your server > Proxy > Logs** if Caddy cannot read the files or continues serving another certificate. Caddy does not automatically renew certificates supplied this way. Replace the certificate and key files before expiration, then restart the proxy to load them. Certificates from a private CA also require clients to trust that CA. # DNS Challenge (/docs/core/networking/proxy/caddy/dns-challenge) DNS challenge [#dns-challenge] Caddy's default HTTP challenge requires public access to port `80`. Use the DNS challenge when you need wildcard certificates or cannot expose port `80` during certificate validation. Caddy DNS providers are modules compiled into the Caddy binary. Coolify's default `lucaslorentz/caddy-docker-proxy:2.13-alpine` image does not include these modules, so you must build a compatible image from the proxy Docker Compose configuration. What you need [#what-you-need] * a domain hosted by a [Caddy DNS provider](https://github.com/orgs/caddy-dns/repositories) * provider credentials that can create and delete DNS records Changing the proxy image rebuilds the component that serves every public route on the server. A failed module build or invalid Caddy option can leave all routes unavailable. Add a DNS-enabled Caddy build [#add-a-dns-enabled-caddy-build] Open **Servers > your server > Proxy > Configuration**. In the `caddy` service, remove the existing `image` line and add the provider-specific `build`, credential, and `caddy.acme_dns` label below. Keep the existing networks, ports, volumes, and Coolify labels. Each example visually marks the existing image line in red and the replacement lines in green. ```yaml services: caddy: image: 'lucaslorentz/caddy-docker-proxy:2.13-alpine' # [!code --][!code focus] build: # [!code ++:9][!code focus:9] dockerfile_inline: | FROM caddy:2.11-builder AS builder RUN xcaddy build \ --with github.com/lucaslorentz/caddy-docker-proxy/v2@v2.8.11 \ --with github.com/caddy-dns/cloudflare@v0.2.4 FROM caddy:2.11-alpine COPY --from=builder /usr/bin/caddy /usr/bin/caddy CMD ["caddy", "docker-proxy"] environment: - CADDY_DOCKER_POLLING_INTERVAL=5s - CADDY_DOCKER_CADDYFILE_PATH=/dynamic/Caddyfile - CF_API_TOKEN= # [!code ++][!code focus] labels: - coolify.managed=true - coolify.proxy=true - 'caddy.acme_dns=cloudflare {env.CF_API_TOKEN}' # [!code ++][!code focus] ``` ```yaml services: caddy: image: 'lucaslorentz/caddy-docker-proxy:2.13-alpine' # [!code --][!code focus] build: # [!code ++:9][!code focus:9] dockerfile_inline: | FROM caddy:2.11-builder AS builder RUN xcaddy build \ --with github.com/lucaslorentz/caddy-docker-proxy/v2@v2.8.11 \ --with github.com/caddy-dns/hetzner/v2@v2.0.0 FROM caddy:2.11-alpine COPY --from=builder /usr/bin/caddy /usr/bin/caddy CMD ["caddy", "docker-proxy"] environment: - CADDY_DOCKER_POLLING_INTERVAL=5s - CADDY_DOCKER_CADDYFILE_PATH=/dynamic/Caddyfile - HETZNER_API_TOKEN= # [!code ++][!code focus] labels: - coolify.managed=true - coolify.proxy=true - 'caddy.acme_dns=hetzner {env.HETZNER_API_TOKEN}' # [!code ++][!code focus] ``` ```yaml services: caddy: image: 'lucaslorentz/caddy-docker-proxy:2.13-alpine' # [!code --][!code focus] build: # [!code ++:9][!code focus:9] dockerfile_inline: | FROM caddy:2.11-builder AS builder RUN xcaddy build \ --with github.com/lucaslorentz/caddy-docker-proxy/v2@v2.8.11 \ --with github.com/caddy-dns/route53@v1.6.2 FROM caddy:2.11-alpine COPY --from=builder /usr/bin/caddy /usr/bin/caddy CMD ["caddy", "docker-proxy"] environment: - CADDY_DOCKER_POLLING_INTERVAL=5s - CADDY_DOCKER_CADDYFILE_PATH=/dynamic/Caddyfile - AWS_ACCESS_KEY_ID= # [!code ++:3][!code focus:3] - AWS_SECRET_ACCESS_KEY= - AWS_REGION= labels: - coolify.managed=true - coolify.proxy=true - caddy.acme_dns=route53 # [!code ++][!code focus] ``` For another provider, use the module path and configuration from that provider's repository. Confirm that the module version supports the selected Caddy version before restarting the proxy. Restart and verify [#restart-and-verify] Save the proxy configuration, then select **Restart Proxy**. The first restart builds the custom image and can take longer than a normal restart. Redeploy a resource with an HTTPS domain, open the domain, and inspect its certificate. Check **Servers > your server > Proxy > Logs** for image-build, module, DNS, or ACME errors. Troubleshooting [#troubleshooting] The module was not compiled into the running binary. Confirm the `xcaddy build` command includes the correct provider module, then rebuild and restart the proxy. Confirm the token can edit the correct zone and that `_acme-challenge` TXT records become visible publicly. Follow the provider module's documentation for propagation settings when required. Add the staging CA label while testing: ```yaml labels: # [!code ++:2][!code focus:2] - caddy.acme_ca=https://acme-staging-v02.api.letsencrypt.org/directory ``` Remove it after validation succeeds. Staging certificates are not trusted by browsers. # Caddy Overview (/docs/core/networking/proxy/caddy/overview) Caddy overview [#caddy-overview] Caddy is an integrated proxy alternative to Traefik. Coolify runs `lucaslorentz/caddy-docker-proxy`, generates Caddy labels for resource domains, and stores Caddy configuration and certificate data on the selected server. Caddy is supported, but Traefik is the default and the proxy used by the Coolify core team in production. As a result, Traefik has broader documentation and support coverage. Choose Caddy if you are familiar with it or need a Caddy-specific feature. Coolify can generate normal Caddy routes and automatic HTTPS settings. Advanced Caddy features may require changes to the proxy Docker Compose configuration, a custom Caddy image, or files under `/data/coolify/proxy/caddy/dynamic/`. *** What Coolify manages [#what-coolify-manages] For a server using Caddy, Coolify: * runs the proxy as the `coolify-proxy` container * listens on ports `80` and `443`, including HTTP/3 on UDP port `443` * generates Caddy Docker labels for application and service domains * stores the main configuration at `/data/coolify/proxy/caddy/docker-compose.yml` * stores dynamic Caddy snippets under `/data/coolify/proxy/caddy/dynamic/` * reloads Caddy after dynamic configuration changes made in the dashboard The proxy imports `*.caddy` files from its dynamic directory. Coolify-generated files such as `Caddyfile`, `coolify.caddy`, and the default request handler are shown as read-only in the dashboard. Switching proxies replaces the proxy type and default configuration. Recreate custom routing in Caddy syntax and redeploy resources so their Caddy labels are applied. *** Configure Caddy [#configure-caddy] # Proxy Overview (/docs/core/networking/proxy/overview) Proxy overview [#proxy-overview] Coolify runs one `coolify-proxy` container on each server connected to Coolify. The proxy accepts public HTTP and HTTPS requests, matches each request to a configured domain, and forwards it to the correct resource container over a Docker network. [Traefik](https://traefik.io/) is the default proxy in Coolify. You can select [Caddy](https://caddyserver.com/) instead, or select **Custom (None)** and operate your own proxy without Coolify-managed routing. Use Traefik unless you already have a reason to use Caddy. Choose **Custom (None)** only when you are prepared to configure domains, TLS certificates, redirects, and routing outside Coolify. Switching proxies temporarily interrupts every public route on that server. Prepare the target proxy configurations before you stop the current proxy. *** Choose a proxy [#choose-a-proxy] A direct host port mapping bypasses the proxy. Use a mapped port only when a client must connect directly or the protocol does not belong behind an HTTP reverse proxy. *** Open the proxy settings [#open-the-proxy-settings] 1. Open **Servers** in the Coolify dashboard. 2. Select the server that receives traffic for your resources. 3. Select **Proxy**. The **Configuration** page shows the selected proxy, its generated Docker Compose configuration, and controls for starting, stopping, restarting, saving, or resetting that configuration. **Dynamic Configurations** stores file-provider configuration, and **Logs** shows proxy output. An invalid proxy configuration can make every application and service on the server unreachable. Keep a copy of working custom configuration and test changes on a non-production server when possible. *** Switch between Traefik and Caddy [#switch-between-traefik-and-caddy] The running proxy must be stopped before Coolify allows you to switch it. Plan a maintenance window because public routes remain unavailable until the new proxy starts and the resources have compatible labels. Prepare resource labels [#prepare-resource-labels] Confirm that applications and services have labels for the target proxy. For an application with **Label management** set to **Managed by Coolify (auto-generated)**, open its **General** page and use **Reset to defaults** if its generated labels are outdated. For a Docker Compose application or service, save the Compose configuration so Coolify can generate the current proxy labels. Stop the current proxy [#stop-the-current-proxy] Open **Servers > your server > Proxy**, then select **Stop Proxy**. Wait until the status changes to **Proxy Exited**. Stopping the proxy interrupts HTTP and HTTPS traffic for every resource routed through it. Select the new proxy [#select-the-new-proxy] Select **Switch Proxy**, confirm the warning, then choose **Traefik** or **Caddy**. Coolify replaces the selected proxy type and generates its default configuration. Custom changes in the previous proxy configuration may not carry over. Recreate only the settings that the new proxy supports. Start the proxy and redeploy resources [#start-the-proxy-and-redeploy-resources] Select **Start Proxy**. Redeploy or restart each affected application and service so the target proxy labels are present on the running containers. Verify public routes [#verify-public-routes] Open at least one HTTP and one HTTPS domain on the server. Confirm that HTTPS uses the expected certificate, redirects behave correctly, and the resource responds through the new proxy. If a route fails, inspect **Servers > your server > Proxy > Logs** and the resource's generated labels. *** Configure the selected proxy [#configure-the-selected-proxy] Network connections and configuration changes [#network-connections-and-configuration-changes] Coolify connects the proxy to a destination network when the destination is created, a resource is deployed, or the proxy starts or restarts. It no longer reconnects all networks on hourly checks or server validation. If a required network connection is missing, redeploy the resource or restart the proxy. Proxy configurations are validated before saving. New configurations use Traefik v3.7 or caddy-docker-proxy 2.13; existing custom configurations should be reviewed before changing their image version. # Basic Authentication (/docs/core/networking/proxy/traefik/basic-auth) Basic authentication [#basic-authentication] HTTP basic authentication requires a username and password before Traefik forwards a request to a resource. Coolify can generate the required Traefik middleware labels for standard applications. Docker Compose applications and services use labels in their Compose file. HTTP basic authentication protects a route with one shared credential. It does not replace application accounts, role-based access, multi-factor authentication, or single sign-on. Protect a resource [#protect-a-resource] Choose the path that matches how the resource is deployed. Automatic [#automatic] Coolify hashes the password and generates the Traefik middleware when you enable the built-in setting. Open the application settings [#open-the-application-settings] Open the application, select **General**, then find **Security > Authentication**. Add the credentials [#add-the-credentials] Choose **HTTP Basic Authentication** in **Authentication**, then enter a **Username** and **Password**. Save the application settings. Keep **Label management** set to **Managed by Coolify (auto-generated)** so Coolify continues to generate the proxy labels. Redeploy and verify [#redeploy-and-verify] Redeploy the application. Open its domain in a private browser window and confirm that the browser requests the new credentials before loading the application. Manual [#manual] Generate credentials [#generate-credentials] Generate a bcrypt credential with `htpasswd`. On Debian or Ubuntu, the command is provided by the `apache2-utils` package: ```bash htpasswd -nbB '' ``` Add the labels [#add-the-labels] Open the application **General** page, find **Container labels**, then set **Label management** to **Managed manually (edit labels yourself)**. Basic authentication takes two labels: one that **defines** the middleware and one that **attaches** it to the HTTPS router. ```ini traefik.enable=true traefik.http.middlewares.http-basic-auth.basicauth.users=: # [!code ++][!code focus] traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https traefik.http.routers.http-0-.entryPoints=http traefik.http.routers.http-0-.middlewares=redirect-to-https traefik.http.routers.http-0-.rule=Host(`domain.com`) && PathPrefix(`/`) traefik.http.routers.http-0-.service=http-0- traefik.http.routers.https-0-.entryPoints=https traefik.http.routers.https-0-.middlewares=http-basic-auth # [!code ++][!code focus] traefik.http.routers.https-0-.rule=Host(`domain.com`) && PathPrefix(`/`) # [!code focus] traefik.http.routers.https-0-.service=https-0- traefik.http.routers.https-0-.tls.certresolver=letsencrypt traefik.http.routers.https-0-.tls=true traefik.http.services.http-0-.loadbalancer.server.port=3000 traefik.http.services.https-0-.loadbalancer.server.port=3000 ``` If the HTTPS router already lists middleware such as `gzip`, append `,http-basic-auth` to the existing comma-separated value instead of replacing it. See [Custom middlewares](/core/networking/proxy/traefik/custom-middlewares) for what choosing manual label management makes you responsible for. Redeploy and verify [#redeploy-and-verify-1] Redeploy the application. Open its domain in a private browser window and confirm that the browser requests the new credentials before loading the application. Use only the `htpasswd` output in the Traefik label. Store the plaintext password in a password manager and rotate it by replacing the hash and redeploying the resource. Generate a bcrypt credential with `htpasswd`. On Debian or Ubuntu, the command is provided by the `apache2-utils` package: ```bash htpasswd -nbB '' ``` The output has the form `:`. Keep each `$` once in the source Compose file while **Escape special characters in labels?** is enabled, which is the default. Coolify writes the required `$$` form in the deployable Compose file. Add the middleware definition and the Coolify middleware shorthand to the service that receives the domain: ```yaml services: app: image: nginx:alpine labels: # [!code ++:3][!code focus:3] - 'traefik.http.middlewares.app-auth.basicauth.users=:' - 'coolify.traefik.middlewares=app-auth' ``` `coolify.traefik.middlewares` tells Coolify to add `app-auth` to the generated router middleware chain. Save and redeploy the Compose resource, then verify the domain in a private browser window. Use only the `htpasswd` output in the Traefik label. Store the plaintext password in a password manager and rotate it by replacing the hash and redeploying the resource. Troubleshooting [#troubleshooting] Confirm the resource was redeployed after enabling authentication or changing its labels. For a Docker Compose application or service, inspect the running container labels and confirm that `app-auth` is attached to the expected router. Check **Servers > your server > Proxy > Logs** for missing middleware errors. Keep **Escape special characters in labels?** enabled and enter each `$` once in the source Compose file. If you disable that setting, write every `$` as `$$` yourself. Also check the label quoting and make sure the generated `:` value remains on one line. Keep every existing middleware name when adding basic authentication. Append `app-auth` to the generated middleware chain instead of replacing middleware such as `gzip` or another custom middleware. # Custom Middlewares (/docs/core/networking/proxy/traefik/custom-middlewares) Custom middlewares [#custom-middlewares] Traefik middleware changes a request before it reaches a resource. Common uses include rate limits, response headers, IP allow lists, redirects, and external authentication. How you attach middleware depends on the resource type. Standard applications can use generated labels or manually edited labels. Docker Compose applications and services can use Coolify's `coolify.traefik.middlewares` shorthand. Choosing **Managed manually (edit labels yourself)** in **Label management** stops Coolify from regenerating application labels. You become responsible for every router, middleware, service, and certificate label for the application. Use dynamic configuration with a small reference label when it can meet the requirement. Define reusable middleware [#define-reusable-middleware] Open **Servers > your server > Proxy > Dynamic Configurations** and create a file such as `shared-middlewares.yaml`. Start with the example that matches the request change you need. You can combine multiple middleware definitions in the same file. ```yaml http: middlewares: app-rate-limit: rateLimit: average: 100 period: 1m burst: 50 ``` ```yaml http: middlewares: security-headers: headers: contentTypeNosniff: true frameDeny: true stsSeconds: 31536000 stsIncludeSubdomains: true ``` ```yaml http: middlewares: internal-only: ipAllowList: sourceRange: - '192.168.1.0/24' - '10.0.0.0/8' ``` The `@file` suffix identifies middleware loaded from Traefik's file provider. Attach middleware to a resource [#attach-middleware-to-a-resource] Open the application **General** page and find **Container labels**. Set **Label management** to **Managed manually (edit labels yourself)**, then append the middleware names to the existing HTTPS router label: ```ini traefik.http.routers.https-0-.middlewares=gzip # [!code --][!code focus] traefik.http.routers.https-0-.middlewares=gzip,app-rate-limit@file,security-headers@file # [!code ++][!code focus] ``` Keep every existing middleware name. Save and redeploy the application. If the route breaks, select **Reset to defaults**, set **Label management** back to **Managed by Coolify (auto-generated)**, and redeploy before trying again. Add the Coolify shorthand to the service that receives the domain: ```yaml services: app: image: nginx:alpine labels: # [!code ++:2][!code focus:2] - 'coolify.traefik.middlewares=app-rate-limit@file,security-headers@file' ``` Coolify reads this value while it generates the router and adds the named middleware to the chain. Save and redeploy the resource. You can also define middleware with Docker labels. For example: ```yaml labels: # [!code ++:5][!code focus:5] - 'traefik.http.middlewares.app-rate-limit.ratelimit.average=100' - 'traefik.http.middlewares.app-rate-limit.ratelimit.period=1m' - 'traefik.http.middlewares.app-rate-limit.ratelimit.burst=50' - 'coolify.traefik.middlewares=app-rate-limit' ``` Use file-based configuration when several resources share the same middleware. Use labels when the middleware belongs to one Compose service. *** Redirects [#redirects] Choose the redirect that matches the result you need. Standard applications have a built-in **www redirect** setting on **Domains**. Add both hostnames, keep labels managed by Coolify, then choose one of: | www redirect | Result | | ----------------------- | ------------------------------------------------------------------ | | **No redirect** | Both configured hostnames remain available. | | **Redirect to www** | The non-`www` hostname redirects to the configured `www` hostname. | | **Redirect to non-www** | The `www` hostname redirects to the configured non-`www` hostname. | Select **Save changes** and redeploy if the running container does not yet have the regenerated labels. Both hostnames also need DNS records that point to the server. Docker Compose applications and services [#docker-compose-applications-and-services] Add both domains to the resource, then add the redirect middleware labels to the service that receives them. ```yaml labels: # [!code ++:5][!code focus:5] - 'traefik.http.middlewares.example-redirect.redirectregex.regex=^(http|https)://(?:www\.)?(.+)' - 'traefik.http.middlewares.example-redirect.redirectregex.replacement=${1}://www.${2}' - 'traefik.http.middlewares.example-redirect.redirectregex.permanent=true' - 'coolify.traefik.middlewares=example-redirect' ``` ```yaml labels: # [!code ++:5][!code focus:5] - 'traefik.http.middlewares.example-redirect.redirectregex.regex=^(http|https)://www\.(.+)' - 'traefik.http.middlewares.example-redirect.redirectregex.replacement=${1}://${2}' - 'traefik.http.middlewares.example-redirect.redirectregex.permanent=true' - 'coolify.traefik.middlewares=example-redirect' ``` These examples assume **Escape special characters in labels?** remains enabled. If you disable it, write each `$` as `$$` in the source Compose file. Create a dynamic middleware that preserves the request path: ```yaml http: middlewares: move-domain: redirectRegex: regex: '^https?://source\.example\.com/(.*)' replacement: 'https://target.example.com/${1}' permanent: true ``` Configure `https://source.example.com` as a domain on the resource so Traefik creates the source router and certificate, then attach `move-domain@file` using the appropriate resource method above. Set `permanent: false` until the source hostname, certificate, path handling, and destination are correct. Browsers and search engines can cache permanent redirects. Troubleshooting [#troubleshooting] Confirm the middleware name and provider suffix match exactly. File-provider middleware uses `@file`. Inspect **Servers > your server > Proxy > Logs** for missing middleware or YAML errors. Confirm the middleware is attached to the expected router. Defining middleware without adding it to a router does not process traffic. Keep existing middleware such as `gzip` when editing a generated router chain. Append the new middleware instead of replacing the complete value. Coolify enables **Escape special characters in labels?** by default. With this setting enabled, enter each dollar sign once in the source Compose file. For example: ```yaml - 'traefik.http.middlewares.example-redirect.redirectregex.replacement=${1}://${2}' ``` Coolify writes each `$` as `$$` in the deployable Compose file so Docker Compose passes a single `$` to Traefik. After deployment, `docker inspect` should show `${1}://${2}` as the replacement value. If you disable **Escape special characters in labels?**, escape each dollar sign yourself by writing `$$` in the source Compose file. # Custom SSL Certificates (/docs/core/networking/proxy/traefik/custom-ssl-certs) Custom SSL certificates [#custom-ssl-certificates] Traefik normally obtains HTTPS certificates through the `letsencrypt` certificate resolver. Use a custom certificate when a private certificate authority, an organization-managed certificate, or another certificate workflow must terminate TLS at Traefik. The certificate and private key must exist on every server whose Traefik proxy serves the domain. Prepare the certificate files [#prepare-the-certificate-files] You need: * a PEM-encoded certificate file that includes any required intermediate certificates * the matching unencrypted private key * shell access to the server running the resource Copy the key over an encrypted connection, restrict its permissions, and never commit it to a repository or paste it into the Coolify dashboard. On the resource server, create the certificate directory: ```bash sudo install -d -m 700 /data/coolify/proxy/certs ``` Copy the files from your machine to the resource server. Replace the local paths and server address: ```bash scp /path/to/example.com.crt root@:/data/coolify/proxy/certs/example.com.crt scp /path/to/example.com.key root@:/data/coolify/proxy/certs/example.com.key ``` Restrict access to the private key on the server: ```bash sudo chmod 600 /data/coolify/proxy/certs/example.com.key ``` Coolify mounts `/data/coolify/proxy/` at `/traefik/` inside the Traefik container. Add the dynamic TLS configuration [#add-the-dynamic-tls-configuration] Open **Servers > your server > Proxy > Dynamic Configurations**, select **Add**, and create a file such as `custom-certificates.yaml`: ```yaml tls: certificates: - certFile: /traefik/certs/example.com.crt keyFile: /traefik/certs/example.com.key ``` Save the file. Traefik watches the dynamic configuration directory and selects a matching certificate from the certificate's subject alternative names when a request arrives. Verify the certificate [#verify-the-certificate] Open the HTTPS domain and inspect the certificate issuer, subject alternative names, and expiration date. You can also check from a terminal: ```bash openssl s_client -connect example.com:443 -servername example.com /dev/null \ | openssl x509 -noout -subject -issuer -dates ``` If Traefik continues to serve another certificate, confirm that the certificate covers the requested hostname and inspect **Servers > your server > Proxy > Logs** for file or key parsing errors. # Dashboard (/docs/core/networking/proxy/traefik/dashboard) Traefik dashboard [#traefik-dashboard] New proxy configurations do not expose the Traefik dashboard. The upgrade removes the legacy dashboard router from saved configurations; restart the proxy to apply that change. Create a dynamic router to access the dashboard through HTTPS and protect it with basic authentication. Do not route the Traefik dashboard at `/api` on the same hostname as the Coolify dashboard. Traefik's dashboard uses `/api`, which conflicts with Coolify's API routes. Use a separate hostname such as `traefik.example.com`. Create dashboard credentials [#create-dashboard-credentials] Generate a bcrypt credential with `htpasswd`: ```bash htpasswd -nbB '' ``` Copy the complete `:` output. Dynamic YAML does not require Docker Compose dollar-sign escaping. Enable the dashboard API [#enable-the-dashboard-api] In the proxy configuration, enable the dashboard API in secure mode with `--api.dashboard=true`. Save the validated configuration and restart the proxy. Keep insecure mode disabled. Coolify does not sync edits to `/data/coolify/proxy/docker-compose.yml` back into the UI once a proxy configuration is saved in Coolify. Make changes under **Servers > your server > Proxy > Configuration** and save them there. Starting or restarting the proxy through Coolify writes its saved configuration to disk and can overwrite disk-only edits. Add the dashboard route [#add-the-dashboard-route] Open **Servers > your server > Proxy > Dynamic Configurations**, select **Add**, and create `traefik-dashboard.yaml`: ```yaml http: middlewares: dashboard-auth: basicAuth: users: - ':' dashboard-https-redirect: redirectScheme: scheme: https routers: dashboard-http: rule: 'Host(`traefik.example.com`)' entryPoints: - http middlewares: - dashboard-https-redirect service: api@internal dashboard-https: rule: 'Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))' entryPoints: - https middlewares: - dashboard-auth service: api@internal tls: certResolver: letsencrypt ``` Replace the hostname and credential, then save the file. Point the hostname's DNS record to this server. Open `https://traefik.example.com/dashboard/` and sign in with the configured credential. Do not use insecure mode on a public server [#do-not-use-insecure-mode-on-a-public-server] Setting `--api.insecure=true` exposes the dashboard directly on Traefik's API port without authentication. If your proxy configuration publishes port `8080`, enabling insecure mode can expose the dashboard through the server firewall. Use the authenticated HTTPS route above instead. If you temporarily enable insecure mode for isolated debugging, restrict port `8080` at the firewall and remove `--api.insecure=true` immediately afterward. Troubleshooting [#troubleshooting] Open `/dashboard/` with the trailing slash. Traefik's dashboard redirects and assets expect it. Inspect **Servers > your server > Proxy > Logs** for dynamic configuration parsing errors. Confirm the Traefik dashboard uses a different hostname from the Coolify dashboard. Both products use an `/api` path, so they cannot share the same hostname with this router configuration. Confirm its DNS record points to the server running this Traefik proxy and that ports `80` and `443` can reach the server. # DNS Challenge (/docs/core/networking/proxy/traefik/dns-challenge) DNS challenge [#dns-challenge] Coolify's default Traefik configuration uses the ACME HTTP challenge, which requires public access to port `80`. Switch to the DNS challenge when you need wildcard certificates or cannot make port `80` reachable during certificate validation. Traefik uses its Lego DNS provider integration to create a temporary `_acme-challenge` TXT record, waits for DNS validation, and removes the record after the certificate is issued. What you need [#what-you-need] * a domain hosted by a [DNS provider supported by Lego](https://go-acme.github.io/lego/dns/) * provider credentials that can create and delete DNS records for the required zone Create a token limited to the DNS zone and record permissions Traefik needs. Do not reuse an account-wide key when the provider supports scoped tokens. Change the Traefik configuration [#change-the-traefik-configuration] Coolify does not sync edits to `/data/coolify/proxy/docker-compose.yml` back into the UI once a proxy configuration is saved in Coolify. Make changes under **Servers > your server > Proxy > Configuration** and save them there. Starting or restarting the proxy through Coolify writes its saved configuration to disk and can overwrite disk-only edits. Open **Servers > your server > Proxy > Configuration**. Keep the existing Docker Compose configuration, then make two changes inside the `traefik` service: 1. Add the DNS provider credentials under `environment`. 2. Remove the two `httpchallenge` command flags and add the provider's `dnschallenge` flags. Each example visually marks the lines to remove and add. Keep the other values from your existing proxy configuration. ```yaml services: traefik: environment: # [!code ++:2][!code focus:2] - CF_DNS_API_TOKEN= command: # Keep the other existing command values. - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true' # [!code --:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http' - '--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare' # [!code ++:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0' - '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json' ``` Use a Cloudflare API token with DNS edit permission for the zone. ```yaml services: traefik: environment: # [!code ++:2][!code focus:2] - HETZNER_API_TOKEN= command: # Keep the other existing command values. - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true' # [!code --:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http' - '--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=hetzner' # [!code ++:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0' - '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json' ``` ```yaml services: traefik: environment: # [!code ++:4][!code focus:4] - AWS_ACCESS_KEY_ID= - AWS_SECRET_ACCESS_KEY= - AWS_REGION= command: # Keep the other existing command values. - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true' # [!code --:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http' - '--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=route53' # [!code ++:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0' - '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json' ``` ```yaml services: traefik: environment: # [!code ++:2][!code focus:2] - HOSTINGER_API_TOKEN= command: # Keep the other existing command values. - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true' # [!code --:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http' - '--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=hostinger' # [!code ++:2][!code focus:2] - '--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0' - '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json' ``` For another provider, use the identifier and environment variables from the [Lego DNS provider documentation](https://go-acme.github.io/lego/dns/). Restart and verify [#restart-and-verify] Save the proxy configuration, then select **Restart Proxy**. Redeploy one resource with an HTTPS domain to trigger certificate issuance. Verify that the domain serves a valid certificate and inspect **Servers > your server > Proxy > Logs** for ACME messages. Troubleshooting [#troubleshooting] Increase the propagation delay: ```yaml - '--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0' # [!code --][!code focus] - '--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=30' # [!code ++][!code focus] ``` Some provider integrations follow CNAME records for `_acme-challenge`. If your delegated setup requires disabling that behavior, add: ```yaml services: traefik: environment: # [!code ++:2][!code focus:2] - LEGO_DISABLE_CNAME_SUPPORT=true ``` Temporarily add the staging ACME server, restart the proxy, and test issuance: ```yaml - '--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory' # [!code ++][!code focus] ``` Remove the staging line after the configuration works. Staging certificates are not trusted by browsers. Continue with [Wildcard Certificates](/core/networking/proxy/traefik/wildcard-certs) when you need one certificate for multiple subdomains. # Dynamic Configuration (/docs/core/networking/proxy/traefik/dynamic-config) Dynamic configuration [#dynamic-configuration] Traefik separates its startup configuration from dynamic routing configuration. Coolify stores file-based dynamic configuration under `/data/coolify/proxy/dynamic/` on the selected server and mounts it at `/traefik/dynamic/` inside the proxy container. Traefik watches that directory, so valid file changes can take effect without restarting the proxy. Add a configuration file [#add-a-configuration-file] Open Dynamic Configurations [#open-dynamic-configurations] Open **Servers > your server > Proxy > Dynamic Configurations**. Create the file [#create-the-file] Select **Add**, enter a filename and valid Traefik YAML, then save it. If the filename has no `.yaml` or `.yml` extension, Coolify adds `.yaml`. Filenames may contain letters, numbers, dots, dashes, and underscores, but cannot contain path separators or start with a dot. Verify Traefik loaded it [#verify-traefik-loaded-it] Reload the **Dynamic Configurations** page and confirm the file appears. Then check the behavior the file defines and inspect **Servers > your server > Proxy > Logs** for parsing or provider errors. The following example defines a reusable response-header middleware: ```yaml http: middlewares: security-headers: headers: contentTypeNosniff: true frameDeny: true referrerPolicy: no-referrer ``` Reference it as `security-headers@file` from a Traefik router. Coolify shows generated files such as `coolify.yaml` and `default_redirect_503.yaml`, but does not provide edit or delete controls for them. Change the corresponding Coolify setting instead of replacing generated files. Edit or remove a custom file [#edit-or-remove-a-custom-file] Open the custom file from **Dynamic Configurations**, change its YAML, and save. Delete a file only after removing every router reference to the middleware, service, or TLS option it defines. A YAML syntax error or a missing referenced object can leave affected routes unavailable even though Traefik itself continues running. Restore the last working file content and check the proxy logs when a change fails. When to restart the proxy [#when-to-restart-the-proxy] Dynamic files are watched and normally do not require a restart. Restart the proxy when you change the main `/data/coolify/proxy/docker-compose.yml`, including Traefik command flags, environment variables, ports, volumes, or the proxy image. Coolify does not sync edits to `/data/coolify/proxy/docker-compose.yml` back into the UI once a proxy configuration is saved in Coolify. Make changes under **Servers > your server > Proxy > Configuration** and save them there. Starting or restarting the proxy through Coolify writes its saved configuration to disk and can overwrite disk-only edits. # Load Balancing (/docs/core/networking/proxy/traefik/load-balancing) Load balancing [#load-balancing] A Traefik load-balancer service distributes requests for one domain across multiple upstream URLs. The upstreams can be containers on the same server or services on other servers, as long as the `coolify-proxy` container can reach every URL. Prepare the upstreams [#prepare-the-upstreams] Before creating the route: * deploy at least two healthy upstream instances * expose each upstream on an address and port reachable from the Traefik container * point the public domain to the server running this Traefik proxy * decide whether Traefik should terminate HTTPS for the public domain * remove any other resource route that uses the same hostname and path Do not use `localhost` for an upstream unless the service runs inside the Traefik container. For a host service, use `host.docker.internal:`. For a container on a shared Docker network, use its container or service name and internal port. Add the load-balancer route [#add-the-load-balancer-route] Open **Servers > your server > Proxy > Dynamic Configurations**, select **Add**, and create `app-load-balancer.yaml`. ```yaml http: middlewares: load-balancer-https-redirect: redirectScheme: scheme: https routers: app-load-balancer-http: rule: 'Host(`app.example.com`)' entryPoints: - http middlewares: - load-balancer-https-redirect service: app-load-balancer app-load-balancer-https: rule: 'Host(`app.example.com`)' entryPoints: - https service: app-load-balancer tls: certResolver: letsencrypt services: app-load-balancer: loadBalancer: healthCheck: path: /health interval: 10s timeout: 3s servers: - url: 'http://192.168.1.23:3000' - url: 'http://192.168.1.65:3000' ``` Replace the domain, health-check path, and upstream URLs. Remove `healthCheck` if the application does not provide an endpoint that returns a successful status. ```yaml http: routers: app-load-balancer: rule: 'Host(`app.example.com`)' entryPoints: - http service: app-load-balancer services: app-load-balancer: loadBalancer: servers: - url: 'http://192.168.1.23:3000' - url: 'http://192.168.1.65:3000' ``` Use HTTP-only public routing only when TLS terminates at another trusted proxy or load balancer before traffic reaches Traefik. Verify traffic distribution [#verify-traffic-distribution] Save the dynamic configuration, then: 1. Open the public domain and confirm it responds. 2. Check **Servers > your server > Proxy > Logs** for connection or configuration errors. 3. Stop one upstream and confirm requests continue through a healthy upstream. 4. Restore the upstream and confirm it returns to service. If every request returns a gateway error, test each upstream URL from the proxy network and confirm the service listens on the documented internal port. # Traefik Overview (/docs/core/networking/proxy/traefik/overview) Traefik overview [#traefik-overview] Traefik is Coolify's default integrated reverse proxy. Coolify generates Traefik routes from resource domains and container ports, connects the proxy to the required Docker networks, and configures automatic TLS certificates for HTTPS domains. Most deployments do not need to edit Traefik directly. Use the proxy guides only when the generated defaults do not cover your routing, certificate, or authentication requirement. Set a domain on an application or service and Coolify generates the normal Traefik route. Use dynamic configuration for reusable file-based middleware, custom certificates, dashboards, and load-balancer services. Changes to the main Traefik Docker Compose configuration require a proxy restart. File-based dynamic configuration is watched and can update without restarting Traefik. *** What Coolify manages [#what-coolify-manages] Coolify configures: * the `coolify-proxy` Traefik container on connected servers * public `http` and `https` entry points on ports `80` and `443` * Docker and file providers for generated routes and dynamic configuration * the `letsencrypt` TLS certificate resolver for HTTP challenge * resource router, middleware, service, and target-port labels * the Docker networks that let Traefik reach routed resources The main configuration is stored at `/data/coolify/proxy/docker-compose.yml`. Traefik file-provider configuration is stored under `/data/coolify/proxy/dynamic/` and mounted at `/traefik/dynamic/` inside the proxy container. Coolify does not sync edits to `/data/coolify/proxy/docker-compose.yml` back into the UI once a proxy configuration is saved in Coolify. Make changes under **Servers > your server > Proxy > Configuration** and save them there. Starting or restarting the proxy through Coolify writes its saved configuration to disk and can overwrite disk-only edits. Resetting the proxy configuration removes custom changes from the main Docker Compose file. Editing application labels after choosing manual label management also makes you responsible for preserving every generated route and middleware label. *** Choose a Traefik guide [#choose-a-traefik-guide] If Coolify shows a new-version notice, follow [Update Traefik](/core/networking/proxy/traefik/update) to review compatibility, change the image version, and restart the proxy. # Protect with Authentik (/docs/core/networking/proxy/traefik/protect-services-with-authentik) Protect with Authentik [#protect-with-authentik] Traefik's `forwardAuth` middleware can send each request to an Authentik proxy provider before it reaches an application. Authentik handles sign-in and returns identity headers to Traefik after successful authentication. Use this guide when Authentik and the protected resource can communicate over a shared Docker network on the same Coolify server. Configure Authentik [#configure-authentik] Deploy the [Authentik service](/services/authentik), then follow Authentik's [forward authentication documentation](https://docs.goauthentik.io/docs/add-secure-apps/providers/proxy/) to: 1. Create a proxy provider that uses forward authentication. 2. Create an Authentik application and attach the proxy provider. 3. Set the provider's cookie domain to the parent domain shared by the protected services when you want single sign-on across subdomains. 4. Add the protected domain to Authentik's application or provider configuration. Make sure the Authentik server container and protected resource share a Docker network that Traefik can use to reach Authentik. Create the Traefik middleware [#create-the-traefik-middleware] Find the Authentik server container or service name on the shared network. In the example below it is `authentik-server` and listens on port `9000`. Open **Servers > your server > Proxy > Dynamic Configurations** and create `authentik-forward-auth.yaml`: ```yaml http: middlewares: authentik-forward-auth: forwardAuth: address: 'http://authentik-server:9000/outpost.goauthentik.io/auth/traefik' trustForwardHeader: true authResponseHeaders: - X-authentik-username - X-authentik-groups - X-authentik-entitlements - X-authentik-email - X-authentik-name - X-authentik-uid - X-authentik-jwt - X-authentik-meta-jwks - X-authentik-meta-outpost - X-authentik-meta-provider - X-authentik-meta-app - X-authentik-meta-version ``` Replace `authentik-server` with the actual internal hostname. Do not use the public Authentik URL unless the proxy cannot reach Authentik privately and you intentionally want the external traffic path. Attach the middleware [#attach-the-middleware] Open the application **General** page and find **Container labels**. Set **Label management** to **Managed manually (edit labels yourself)**, then append the file-provider middleware to the existing HTTPS router: ```ini traefik.http.routers.https-0-.middlewares=gzip # [!code --][!code focus] traefik.http.routers.https-0-.middlewares=gzip,authentik-forward-auth@file # [!code ++][!code focus] ``` Save and redeploy the application. Add the Coolify shorthand to the service that receives the domain: ```yaml services: app: image: nginx:alpine labels: # [!code ++:2][!code focus:2] - 'coolify.traefik.middlewares=authentik-forward-auth@file' ``` Save and redeploy the resource. Verify authentication [#verify-authentication] Open the protected domain in a private browser window. Traefik should redirect you to Authentik, then return you to the application after sign-in. Troubleshooting [#troubleshooting] Confirm the Authentik internal hostname and port from the shared Docker network. Inspect both Authentik logs and **Servers > your server > Proxy > Logs** for connection errors. Confirm the proxy provider is assigned to the correct Authentik application and that `authentik-forward-auth@file` is attached to the resource's HTTPS router. Confirm the Authentik provider's cookie domain covers the protected hostname and that the protected domain is assigned to the expected Authentik application. A broken forward-auth route can lock every user out of the protected application. Keep Coolify dashboard access on a separate domain and know how to remove the middleware label before protecting administrative services. # TLS Certificates (/docs/core/networking/proxy/traefik/tls-certificates) Traefik TLS certificates [#traefik-tls-certificates] Open **Servers > \[server] > Proxy > TLS Certificates** to view certificates stored in Traefik's `acme.json`. This page manages Traefik ACME storage; for certificates you provide yourself, use [Custom SSL certificates](/core/networking/proxy/traefik/custom-ssl-certs). Delete a certificate [#delete-a-certificate] Review the domains covered by a certificate before deleting it. Deleting its entry removes it from local ACME storage; it does not revoke the certificate at the certificate authority. After a change, Coolify indicates that the proxy needs a restart. Restart the proxy to apply the updated storage. Traefik may need to obtain a replacement certificate for domains that still require one. Restore ACME storage [#restore-acme-storage] Coolify backs up `acme.json` before every change and retains the last 10 backups. On the same page, choose a backup to restore or delete. Restoring a backup restores the ACME storage file, which can affect several certificates. Review the backup before confirming and restart the proxy when Coolify indicates it is required. # Update Traefik (/docs/core/networking/proxy/traefik/update) Update Traefik [#update-traefik] When Coolify shows **Traefik patch update available** or **New Traefik minor version available**, update the proxy by changing its image version in the UI, saving the configuration, and restarting the proxy. Check compatibility first [#check-compatibility-first] Open the [Traefik releases](https://github.com/traefik/traefik/releases) and review the release notes between your current version and the version you want to use. Follow any linked migration guides to check whether configuration options have changed or been removed. Users with Coolify's default proxy configuration can usually update without additional configuration changes. If you have modified the default configuration, check your custom command flags, environment variables, routing rules, middleware, and dynamic files against the new version before updating. Major-version upgrades can require additional migration steps. Keep a copy of the current configuration and image version so you can restore them if needed. Restarting the proxy briefly interrupts traffic to resources routed through it. Open the proxy configuration [#open-the-proxy-configuration] Open **Servers**, select the server, then open **Proxy > Configuration**. Change the image version [#change-the-image-version] In **Configuration file**, find `image` under `services.traefik` and replace its tag with the version you reviewed. For example: ```yaml services: traefik: image: traefik:v3.7.14 # Keep the rest of your existing configuration. ``` The version above is an example. Use the release you selected and keep the rest of your configuration, applying any changes required by its release notes. Use an explicit version tag so future updates are deliberate. Edits made directly to `/data/coolify/proxy/docker-compose.yml` do not sync back into the UI once Coolify has a saved proxy configuration. A restart through Coolify can overwrite disk-only edits. Save and restart [#save-and-restart] Select **Save changes**, then **Restart Proxy** to apply the new image version. Wait for the proxy to report that it is running. Check **Proxy > Logs** for startup or configuration errors, then open your application domains and verify HTTPS and any custom routing or middleware. If the new version fails, restore the previous image tag and configuration in the UI, save, and restart the proxy again. # Wildcard Certificates (/docs/core/networking/proxy/traefik/wildcard-certs) Wildcard certificates [#wildcard-certificates] A wildcard certificate for `*.example.com` covers first-level subdomains such as `app.example.com` and `api.example.com`. It does not cover the apex `example.com` or deeper names such as `www.app.example.com` unless those names are included separately. Traefik can request wildcard certificates only through the DNS challenge. What you need [#what-you-need] * [Traefik DNS Challenge](/core/networking/proxy/traefik/dns-challenge) configured and working * an apex DNS record for `example.com` when the apex should resolve * a wildcard DNS record such as `*.example.com` pointing to the server or upstream traffic endpoint Request the certificate [#request-the-certificate] Open **Servers > your server > Proxy > Dynamic Configurations** and create `wildcard-example-com.yaml`: ```yaml http: routers: wildcard-example-com: rule: 'HostRegexp(`[a-z0-9-]+\.example\.com`)' entryPoints: - https priority: 1 service: wildcard-placeholder tls: certResolver: letsencrypt domains: - main: example.com sans: - '*.example.com' services: wildcard-placeholder: loadBalancer: servers: [] ``` Replace `example.com`, then save the file. The low-priority router requests the certificate and allows resource-specific routers to handle matching application traffic. Restarting Traefik is normally not required for this dynamic file. Inspect **Servers > your server > Proxy > Logs** until the ACME request succeeds. Use the wildcard certificate [#use-the-wildcard-certificate] Choose whether each subdomain belongs to its own resource or one application handles every subdomain. Set a normal HTTPS domain such as `https://app.example.com` on each application or service. Coolify generates the resource router, and Traefik selects the matching wildcard certificate from its certificate store. Redeploy each changed resource and verify the certificate presented by the domain. Use this only when one application handles arbitrary tenant subdomains. 1. Keep the wildcard DNS record and certificate configuration above. 2. Set **Label management** to **Managed manually (edit labels yourself)** for the application. 3. Use the configuration that matches the Traefik image version shown in **Servers > your server > Proxy > Configuration**. New Coolify proxy configurations use Traefik v3.7. Keep the Traefik v2 rule syntax only when the server still runs a v2 image. ```ini traefik.http.routers.tenant-http.rule=Host(`app.example.com`) # [!code --][!code focus] traefik.http.routers.tenant-http.rule=HostRegexp(`[a-z0-9-]+\.example\.com`) # [!code ++][!code focus] traefik.http.routers.tenant-http.entryPoints=http traefik.http.routers.tenant-http.middlewares=redirect-to-https traefik.http.routers.tenant-https.rule=Host(`app.example.com`) # [!code --][!code focus] traefik.http.routers.tenant-https.rule=HostRegexp(`[a-z0-9-]+\.example\.com`) # [!code ++][!code focus] traefik.http.routers.tenant-https.entryPoints=https traefik.http.routers.tenant-https.tls=true traefik.http.routers.tenant-https.tls.certresolver=letsencrypt traefik.http.routers.tenant-https.service=tenant-service traefik.http.services.tenant-service.loadbalancer.server.port= ``` ```ini traefik.http.routers.tenant-http.rule=Host(`app.example.com`) # [!code --][!code focus] traefik.http.routers.tenant-http.rule=HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.example.com`) # [!code ++][!code focus] traefik.http.routers.tenant-http.entryPoints=http traefik.http.routers.tenant-http.middlewares=redirect-to-https traefik.http.routers.tenant-https.rule=Host(`app.example.com`) # [!code --][!code focus] traefik.http.routers.tenant-https.rule=HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.example.com`) # [!code ++][!code focus] traefik.http.routers.tenant-https.entryPoints=https traefik.http.routers.tenant-https.tls=true traefik.http.routers.tenant-https.tls.certresolver=letsencrypt traefik.http.routers.tenant-https.service=tenant-service traefik.http.services.tenant-service.loadbalancer.server.port= ``` The `letsencrypt` value must match the certificate resolver name in the proxy configuration. Replace `` with the port on which the application listens inside its container. Redeploy the application and test at least two subdomains. After choosing manual label management, Coolify no longer repairs the application labels automatically. Use **Reset to defaults** to recover the generated route if the application becomes unreachable. # Networking in Coolify (/docs/core/networking-in-coolify) Networking in Coolify [#networking-in-coolify] Coolify separates public traffic from private container traffic. HTTP and HTTPS requests enter through the Coolify Proxy container on the server running the resource, while applications, databases, and services communicate over Docker networks. Understanding these paths makes domains, ports, destinations, and proxy settings easier to configure. For a domain, DNS resolves the hostname to the server running the resource. The Coolify Proxy container, named `coolify-proxy`, matches the domain and path, then forwards the request over a Docker network to the correct container port. Containers that share a Docker network communicate directly through internal names and ports. They do not need a public domain or a port mapped to the server. *** The three networking paths [#the-three-networking-paths] Most Coolify networking decisions belong to one of three paths. A domain is the normal path for a web application or HTTP service. Use private networking for dependencies such as databases. Map a port to the server only when a client must connect directly or the protocol does not belong behind the HTTP proxy. *** How public traffic reaches a resource [#how-public-traffic-reaches-a-resource] Coolify configures the route, but the Coolify instance does not relay application traffic. The request goes to the Coolify Proxy container on the server where the resource runs. The application must listen on the port configured for the resource. For example, if an application listens on port `3000` inside its container, the Coolify Proxy container must target port `3000` even though visitors connect over the standard HTTPS port `443`. Applications and services can use domains. Databases use private networking by default and can be exposed separately with a public database port when an external client must connect. *** How private container traffic works [#how-private-container-traffic-works] A **destination** represents a Docker network on a connected server. On a standalone server, Coolify creates an attachable Docker network named `coolify` during setup. The `coolify` network is the default destination, and Coolify deploys non-Docker Compose applications to it unless you select another destination. The Coolify Proxy container joins the `coolify` network and the resource-specific networks used by Docker Compose applications and service stacks. This allows the Coolify Proxy container to reach containers that have public routes. Other containers on a shared network can communicate directly through their container or service name, a network alias, and the internal port where the dependency listens. Common private paths include: * an application connecting to a database on its database port * one service container calling another by its Docker Compose service name * the Coolify Proxy container forwarding a domain request to an application port Private traffic does not need a public domain, a public IP address, or a host port mapping. Resources on separate Docker networks remain isolated unless you connect them to a shared network. Docker Compose applications and service stacks use their own resource-specific network by default and do not join the `coolify` network automatically. Enable **Connect To Predefined Network** when the stack must reach another resource through its Coolify destination. Read [Docker Compose networking](/applications/builds/docker-compose#application-networking) before changing that connection. *** Choose a proxy model [#choose-a-proxy-model] Coolify supports two integrated proxies, Traefik and Caddy, plus **Custom (None)**. Coolify selects Traefik by default when you add a server. You can select Caddy instead and keep Coolify-managed routing and TLS certificates, or bring your own proxy with **Custom (None)** and manage the entire public traffic path yourself. A direct host port mapping bypasses the proxy. It exposes the selected container port through the server, so you must choose a free host port and restrict it with the appropriate firewall rules. Application port mappings also disable rolling updates for that application. *** The networking responsibility boundary [#the-networking-responsibility-boundary] The same boundary applies to self-hosted Coolify and Coolify Cloud: resources run on servers you provide. When you self-host, you also operate the network path to the Coolify instance itself. When a connection fails, trace the path in order. For a domain, check DNS, the firewall, Coolify Proxy container status, the generated route, the shared Docker network, and the container port. For a private dependency, check the shared network, internal hostname, internal port, and credentials. *** Continue with networking [#continue-with-networking] Use the detailed guides for the part of the path you need to configure. Configure domains [#configure-domains] Use [Domains](/core/networking/domains) to configure DNS records, HTTPS, target ports, paths, redirects, and generated domains. Configure the proxy [#configure-the-proxy] * [Choose or switch proxies](/core/networking/proxy/overview) * [Configure Traefik](/core/networking/proxy/traefik/overview) * [Configure Caddy](/core/networking/proxy/caddy/overview) Secure and troubleshoot traffic [#secure-and-troubleshoot-traffic] * [Configure the server firewall](/core/infrastructure/servers/firewall) * [Troubleshoot Let's Encrypt](/troubleshoot/dns-and-domains/lets-encrypt-not-working) * [Troubleshoot gateway timeouts](/troubleshoot/applications/gateway-timeout) # Discord (/docs/core/notifications/channels/discord) Discord [#discord] Coolify sends Discord notifications through an incoming webhook created for a Discord text channel. Create a Discord webhook [#create-a-discord-webhook] Choose the destination [#choose-the-destination] Open the Discord server that should receive Coolify notifications. Create a text channel, such as `coolify-notifications`, or select an existing one. You need permission to manage webhooks in that server. Create the webhook [#create-the-webhook] 1. Open **Server Settings > Integrations > Webhooks**. 2. Select **New Webhook**. 3. Give the webhook a recognizable name, such as `Coolify`. 4. Select the text channel that should receive its messages. 5. Select **Copy Webhook URL**. See [Discord's webhook documentation](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) for provider-specific details. Anyone with the URL can post to the Discord channel. Store it as a secret and replace the webhook if the URL is exposed. *** Configure Coolify [#configure-coolify] 1. Open **Notifications > Discord**. 2. Paste the URL into **Webhook URL** and select **Save changes**. 3. Select **Enable**. 4. Optional: set **Critical event mention** to **Mention @here** to add `@here` to critical event notifications. Discord notifies only members who are online and can access the channel. 5. Under **Notification events**, select the events to send to Discord. 6. Select **Send test**. Confirm that the test appears in the selected Discord channel before selecting additional events. *** Troubleshoot Discord delivery [#troubleshoot-discord-delivery] If the test does not appear: 1. Return to **Server Settings > Integrations > Webhooks** and confirm that the webhook still exists. 2. Confirm that it targets the channel you are checking. A webhook can be moved to another channel without changing the workflow in Coolify. 3. Copy the URL again and replace the saved value in Coolify if the webhook was recreated or its token changed. 4. Confirm that the destination channel still exists and that the webhook can post to it. 5. Save the URL before selecting **Enable**, then send another test. See [Notification events](/core/notifications/events) for the trigger behind each event setting. # Email (/docs/core/notifications/channels/email) Email [#email] Coolify can send team notifications through a hosted email service, a team-specific SMTP server, or Resend. Self-hosted teams can also reuse the transactional email provider configured for the entire Coolify instance. Open **Notifications > Email** to configure the channel. The **Email service > Use system-wide settings** option appears only on self-hosted Coolify. It uses the sender and SMTP or Resend provider configured under [**Settings > Email**](/core/instance-management/instance-settings#transactional-email) for the Coolify instance. Coolify Cloud shows **Use hosted email service** instead. Cloud users do not configure the instance-wide provider. Choose an email provider [#choose-an-email-provider] The available choices depend on how you use Coolify: | Provider | Availability | What you need | | :--------------------------- | :------------------------------------ | :------------------------------------------------------------------------ | | **Use hosted email service** | Coolify Cloud | No provider credentials. | | **Use system-wide settings** | Self-hosted Coolify | A working email provider under **Settings > Email**. | | **SMTP server** | Coolify Cloud and self-hosted Coolify | SMTP sender, host, port, encryption, and optional authentication details. | | **Resend** | Coolify Cloud and self-hosted Coolify | A sender name, sender address, and Resend API key. | A team can use only one email path at a time. The hosted and instance-wide options disable team-specific SMTP and Resend. Enabling team-specific SMTP disables Resend, and enabling Resend disables SMTP. Before you start, prepare the values required by the option you plan to use: * For **SMTP**, copy the host, port, encryption method, username, and password from your email provider. Confirm that the provider permits the sender address you want to use. * For **Resend**, verify your sending domain or sender in Resend and create an API key. * For **system-wide email**, configure and test the instance provider first. This requires access to the self-hosted instance settings. *** Use the hosted or system-wide provider [#use-the-hosted-or-system-wide-provider] The dashboard shows the option for your Coolify deployment type. It does not show both options together. Configure the instance provider [#configure-the-instance-provider] As an instance administrator, open [**Settings > Email**](/core/instance-management/instance-settings#transactional-email). Enter the shared sender details, configure either SMTP or Resend, enable that provider, and save it. Use **Send test** on the instance settings page. Continue only after that test arrives. This confirms that the instance-wide provider works before a team tries to reuse it. Reuse it for the team [#reuse-it-for-the-team] Open **Notifications > Email** for the team and set **Email service** to **Use system-wide settings**. The team now uses the instance sender and provider credentials. It does not receive its own copy of those credentials, and team members cannot change them from the Notifications page. Choose events and test the team channel [#choose-events-and-test-the-team-channel] Select the events to send by email under **Notification events**. Then select **Send test**, enter a recipient address you can access, and send the test. Event selections and the test recipient remain specific to this team. Changing the instance-wide provider affects every team that reuses it. 1. Open **Notifications > Email** for the team. 2. Set **Email service** to **Use hosted email service**. No SMTP host, password, or Resend API key is required. 3. Select the events to send by email under **Notification events**. 4. Select **Send test**, enter a recipient address you can access, and send the test. 5. Confirm that the message arrives before relying on the channel for operational alerts. *** Configure a team provider [#configure-a-team-provider] Choose SMTP or Resend when this team should use its own email provider instead of the hosted or system-wide configuration. Enter the connection details supplied by your SMTP provider. 1. Open **Notifications > Email** and set **Email service** to **Use team email settings**. 2. Enter **From name** and a valid **From address**. 3. Under **SMTP server**, enter the connection details supplied by your email provider: | Field | Value | | :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | | **Host** | SMTP hostname, such as `smtp.example.com`. | | **Port** | Provider's SMTP port. Common values are `587`, `465`, and `25`; Coolify accepts ports from `1` to `65535`. | | **Encryption** | `StartTLS`, `TLS/SSL`, or `None`. Port `587` commonly uses StartTLS and port `465` commonly uses TLS/SSL, but follow your provider's instructions. | | **SMTP username** | Authentication username, when required. | | **SMTP password** | Authentication password, when required. | | **Timeout** | Optional send timeout in seconds. | 4. Check the values against your provider's documentation. A mismatched port and encryption option prevents Coolify from connecting. 5. Select **Save changes** in the **SMTP server** section. 6. Set **SMTP delivery** to **Enabled** and select **Save changes**. Coolify disables Resend when SMTP is enabled. Choose **None** only when your email provider explicitly requires it and the connection stays on a trusted network. Prefer an encrypted option supported by the provider. Create a Resend API key and use a sender address that Resend has verified. 1. Create an API key in the [Resend dashboard](https://resend.com/api-keys). 2. Verify the domain or sender address that Coolify will use in Resend. 3. Open **Notifications > Email** and set **Email service** to **Use team email settings**. 4. Enter **From name** and the verified **From address**. 5. Under **Resend**, enter the **API key** and select **Save changes**. 6. Set **Resend delivery** to **Enabled** and select **Save changes**. Coolify disables SMTP when Resend is enabled. *** Choose events and verify delivery [#choose-events-and-verify-delivery] Under **Notification events**, select the events to send by email. See [Notification events](/core/notifications/events) for the trigger behind each setting. Select **Send test**, enter a recipient address you can access, and send the test. Confirm that the message arrives. If it does not, check the provider's activity logs, sender verification, SMTP port access, and spam folder. *** Troubleshoot email delivery [#troubleshoot-email-delivery] If the test email does not arrive: 1. Confirm that the intended provider is enabled. SMTP, Resend, and the hosted or system-wide option are mutually exclusive. 2. For SMTP, compare the host, port, and encryption method with the provider's current settings. Also confirm that the Coolify server can make outbound connections on that port. 3. Check whether the provider requires the **From address** or its domain to be verified. 4. Check the provider's delivery or activity logs. An accepted request can still be rejected later because of sender policy or recipient filtering. 5. Check the recipient's spam or junk folder. 6. When using the self-hosted system-wide provider, send a test from **Settings > Email**. If that test also fails, fix the instance provider before troubleshooting the team channel. # Pushover (/docs/core/notifications/channels/pushover) Pushover [#pushover] Coolify sends Pushover notifications with your Pushover user key and an API token created for a Pushover application. Create a Pushover application [#create-a-pushover-application] Before configuring Coolify, sign in to Pushover and register at least one phone, tablet, or desktop client with your account. The test notification is delivered to devices registered to that account. Copy your user key [#copy-your-user-key] Sign in to the [Pushover dashboard](https://pushover.net/). Copy **Your User Key** from the account dashboard. The user key identifies the Pushover account that receives the notification. It is not the same as the application API token created in the next step. Create an application token [#create-an-application-token] 1. Open [Create an Application/API Token](https://pushover.net/apps/build). 2. Enter an application name, such as `Coolify`. 3. Accept the terms and create the application. The description, URL, and icon are optional unless Pushover states otherwise. 4. Open the created application and copy its **API Token/Key**. The application token identifies Coolify as the sender and lets Pushover track its message usage separately. Store the Pushover API token as a secret. If it is exposed, replace the token in Pushover and update Coolify. *** Configure Coolify [#configure-coolify] 1. Open **Notifications > Pushover**. 2. Enter the **User key** and **API token**, then select **Save changes**. 3. Select **Enable**. 4. Under **Notification events**, select the events to send through Pushover. 5. Select **Send test**. Confirm that the test arrives on a device connected to your Pushover account before selecting more events. *** Troubleshoot Pushover delivery [#troubleshoot-pushover-delivery] If the test does not arrive: 1. Confirm that **User key** came from the receiving account dashboard. 2. Confirm that **API token** came from the Pushover application you created for Coolify. Do not enter the user key in both fields. 3. Confirm that at least one device is registered and active on the receiving Pushover account. 4. Open the Pushover application page and check its message usage and status. 5. If you regenerated the application token, save the new value in Coolify and test again. See [Notification events](/core/notifications/events) for the trigger behind each event setting. # Slack & Mattermost (/docs/core/notifications/channels/slack-mattermost) Slack & Mattermost [#slack--mattermost] Coolify's **Slack** notification channel accepts a Slack incoming webhook URL. Mattermost incoming webhooks use a compatible message format, so you configure Mattermost on the same Coolify page. Configure a provider [#configure-a-provider] Choose the provider that should receive Coolify notifications. Create an incoming webhook for the Slack channel that should receive notifications. Create a Slack app [#create-a-slack-app] 1. Open the [Slack API apps page](https://api.slack.com/apps). 2. Select **Create New App > From scratch**. 3. Enter a name such as `Coolify Notifications` and select the workspace that owns the destination channel. 4. Select **Create App**. You need permission to install or authorize apps in the workspace. If approval is required, ask a workspace administrator to complete it. Create the incoming webhook [#create-the-incoming-webhook] 1. Open **Incoming Webhooks** in the app settings. 2. Turn on **Activate Incoming Webhooks**. 3. Select **Add New Webhook to Workspace**. 4. Choose the channel that should receive Coolify notifications and authorize the app. 5. Copy the webhook URL shown under **Webhook URLs for Your Workspace**. Add the webhook to Coolify [#add-the-webhook-to-coolify] Open **Notifications > Slack**, paste the URL into **Webhook URL**, and select **Save changes**. Then select **Enable**. Create a Mattermost incoming webhook, then enter it on Coolify's **Slack** page. Confirm that integrations are available [#confirm-that-integrations-are-available] Sign in to the Mattermost team that owns the destination channel. Your Mattermost administrator must allow incoming webhooks, and your account must have permission to create one. If **Integrations** or **Incoming Webhooks** is missing, contact the administrator. Create the incoming webhook [#create-the-incoming-webhook-1] 1. Open **Product Menu > Integrations > Incoming Webhooks**. 2. Select **Add Incoming Webhook**. 3. Enter a recognizable title and description, then choose the destination channel. 4. Save the webhook and copy the generated URL. It normally resembles `https://mattermost.example.com/hooks/...`. Mattermost displays the complete URL after creation. Copy it then, because it grants permission to post through the integration. Add the webhook to Coolify [#add-the-webhook-to-coolify-1] Open **Notifications > Slack** in Coolify, paste the Mattermost URL into **Webhook URL**, and select **Save changes**. Then select **Enable**. The webhook URL authorizes posts to its destination channel. Store it as a secret and replace it in the provider and Coolify if it is exposed. *** Choose events and verify delivery [#choose-events-and-verify-delivery] Under **Notification events**, select the events to send through this channel. See [Notification events](/core/notifications/events) for each trigger. Select **Send test** and confirm that the message arrives in the Slack or Mattermost channel. If it does not, verify that the incoming webhook remains enabled and still targets a channel the integration can access. *** Troubleshoot Slack or Mattermost delivery [#troubleshoot-slack-or-mattermost-delivery] If the test does not arrive: 1. Confirm that the saved URL belongs to the provider and workspace or server you are checking. 2. Confirm that the webhook still exists and still targets an accessible channel. 3. If the app or webhook was reinstalled or recreated, copy the new URL into Coolify and save it. 4. In Slack, confirm that the app remains authorized for the workspace and channel. 5. In Mattermost, confirm that incoming webhooks remain enabled in the server's integration settings. 6. Send another test before enabling production events. # Telegram (/docs/core/notifications/channels/telegram) Telegram [#telegram] Coolify sends Telegram notifications through a bot. You need the bot API token and the ID of the group, channel, or chat that should receive notifications. Create the bot and destination [#create-the-bot-and-destination] Create a Telegram bot [#create-a-telegram-bot] 1. Open [BotFather](https://t.me/botfather) in Telegram and confirm that the account is the official `@BotFather` account. 2. Send `/newbot`. 3. Follow the prompts to choose a display name and a unique username for the bot. 4. Copy the bot API token that BotFather returns. Create or choose the destination [#create-or-choose-the-destination] Create a group, channel, or direct chat for the notifications, or use an existing destination. A dedicated group keeps deployment and server alerts separate from general conversation. Add the bot by searching for the username you created. For a channel, promote the bot to an administrator with permission to post messages. For a group, make sure its permissions allow the bot to send messages; promote it if the group's restrictions require it. Optional: create topics [#optional-create-topics] To route different events into separate threads, use a Telegram group with **Topics** enabled: 1. Open the group's settings and edit the group. 2. Enable **Topics**. 3. Create the topics you want to use, such as `Deployments`, `Backups`, and `Servers`. 4. Send a message inside each topic whose ID you need. Telegram shows the Topics option only for groups that support forum topics. Generate an update for the bot [#generate-an-update-for-the-bot] Send a new message in the destination. If you use topics, send the message inside the relevant topic. Telegram must deliver an update to the bot before its API response contains the chat or thread ID. Anyone with the bot token can use the bot API. Store the token as a secret. If it is exposed, use BotFather to revoke it and create a replacement. *** Find the chat and topic IDs [#find-the-chat-and-topic-ids] 1. Open `https://api.telegram.org/bot/getUpdates` in a browser after replacing the entire `` placeholder with the token from BotFather. 2. Find the newest `message` object in the JSON response. 3. Copy `message.chat.id` for the **Chat ID**. Group and channel IDs are often negative; include the leading `-`. 4. If the message was sent inside a topic, copy `message.message_thread_id` for that topic. For example, the relevant part of a response can look like this: ```json { "message": { "message_thread_id": 42, "chat": { "id": -1001234567890 } } } ``` If the response does not include the destination, send another message in the group or topic and request `getUpdates` again. *** Configure Coolify [#configure-coolify] Save the bot and chat [#save-the-bot-and-chat] Open **Notifications > Telegram**. Enter the **Bot API token** and **Chat ID** exactly as returned by Telegram, including a leading `-` in the chat ID, then select **Save changes**. Enable the channel [#enable-the-channel] Select **Enable**. If Coolify does not keep the channel enabled, recheck that both required values were saved. Choose events and topics [#choose-events-and-topics] Under **Notification events**, select the events to send to Telegram. To route a supported event into a topic, enable the event, then enter that topic's numeric **Topic ID** for it under **Forum topics**. Select **Save changes**. Leave it empty to send the event to the main chat. Send a test [#send-a-test] Select **Send test** and confirm that it arrives in the configured chat. The general test uses the main chat configuration, not a custom thread ID. Custom thread IDs currently apply to deployment success and failure, application and container stopped or restarted events, backup success and failure, scheduled tasks, Docker cleanup, disk usage, server reachability, and server patching. Restart-limit alerts, backup S3 upload warnings, Traefik proxy outdated alerts, and test notifications use the main chat without a custom thread ID. *** Troubleshoot Telegram delivery [#troubleshoot-telegram-delivery] If the test does not arrive: 1. Confirm that the BotFather token was copied without spaces and that the full `` placeholder was replaced in the `getUpdates` URL. 2. Send a new message in the destination and load `getUpdates` again if the response is empty or does not show the chat. 3. Include the leading minus sign in a negative group or channel ID. 4. Confirm that the bot is still a member of the destination and has permission to post. Channels normally require the bot to be an administrator. 5. If only a topic-routed event fails, confirm that the thread ID belongs to the same group as the saved chat ID and that the event supports custom thread IDs. 6. If the token was revoked in BotFather, save the replacement token in Coolify and test again. See [Notification events](/core/notifications/events) for the trigger behind each event setting. # Payload Reference (/docs/core/notifications/channels/webhook/payload-reference) Webhook payload reference [#webhook-payload-reference] Coolify sends webhook notifications as JSON `POST` requests to the endpoint configured under **Notifications > Webhook**. Follow [Webhook setup](/core/notifications/channels/webhook/setup) before using this reference. Requests use the `Content-Type: application/json` header. Every payload includes these fields: | Field | Type | Description | | --------- | ------- | ----------------------------------------------------------- | | `success` | boolean | `true` for success events; `false` for failures and alerts. | | `event` | string | Machine-readable event identifier. | | `message` | string | Human-readable event summary. | Select an event identifier in each section to inspect its request body and conditional fields. *** Application deployments and status [#application-deployments-and-status] Sent when an application deployment completes successfully. ```json { "success": true, "event": "deployment_success", "message": "New version successfully deployed", "application_name": "my-app", "application_uuid": "...", "deployment_uuid": "...", "deployment_url": "...", "project": "...", "environment": "...", "fqdn": "..." } ``` Pull request preview deployments add these fields: ```json { "pull_request_id": 123, "preview_fqdn": "..." } ``` `fqdn` is included when the application has a domain. It may be absent from either regular or preview deployment payloads. Sent when an application deployment fails. ```json { "success": false, "event": "deployment_failed", "message": "Deployment failed", "application_name": "my-app", "application_uuid": "...", "deployment_uuid": "...", "deployment_url": "...", "project": "...", "environment": "...", "fqdn": "..." } ``` Same structure as `deployment_success`, with `"success": false`. PR preview fields apply in the same way. Sent when an application stops unexpectedly (not via a manual stop). ```json { "success": false, "event": "status_changed", "message": "Application stopped", "application_name": "my-app", "application_uuid": "...", "project": "...", "environment": "...", "fqdn": "...", "url": "..." } ``` Sent when Coolify stops an application after it reaches its automatic restart limit. This event uses the **Resources > Restart limit reached** notification selection. ```json { "success": false, "event": "restart_limit_reached", "message": "Restart limit reached", "application_name": "my-app", "application_uuid": "...", "restart_count": 10, "max_restart_count": 10, "url": "...", "project": "...", "environment": "...", "fqdn": "..." } ``` *** Database backups [#database-backups] Sent when a database backup completes successfully. ```json { "success": true, "event": "backup_success", "message": "Database backup successful", "database_name": "...", "database_uuid": "...", "database_type": "...", "frequency": "...", "url": "..." } ``` Sent when a database backup fails. ```json { "success": false, "event": "backup_failed", "message": "Database backup failed", "database_name": "...", "database_uuid": "...", "database_type": "...", "frequency": "...", "error_output": "...", "url": "..." } ``` Sent when the local backup succeeds but uploading to S3 fails. ```json { "success": true, "event": "backup_success_with_s3_warning", "message": "Database backup succeeded locally, S3 upload failed", "database_name": "...", "database_uuid": "...", "database_type": "...", "frequency": "...", "s3_error": "...", "s3_storage_url": "...", "url": "..." } ``` `s3_storage_url` is only present when the S3 storage URL is available. *** Scheduled tasks [#scheduled-tasks] Sent when a scheduled task completes successfully. ```json { "success": true, "event": "task_success", "message": "Scheduled task succeeded", "task_name": "...", "task_uuid": "...", "output": "...", "application_uuid": "...", "url": "..." } ``` Sent when a scheduled task fails. ```json { "success": false, "event": "task_failed", "message": "Scheduled task failed", "task_name": "...", "task_uuid": "...", "output": "...", "application_uuid": "...", "url": "..." } ``` `application_uuid` is included for application-level tasks. For service-level tasks, `service_uuid` is included instead. `url` is only present when available. *** Docker cleanup [#docker-cleanup] Sent when a Docker cleanup job completes successfully. ```json { "success": true, "event": "docker_cleanup_success", "message": "Docker cleanup job succeeded", "server_name": "...", "server_uuid": "...", "cleanup_message": "...", "url": "..." } ``` Sent when a Docker cleanup job fails. ```json { "success": false, "event": "docker_cleanup_failed", "message": "Docker cleanup job failed", "server_name": "...", "server_uuid": "...", "error_message": "...", "url": "..." } ``` *** Server events [#server-events] Sent when a previously unreachable server becomes reachable again. ```json { "success": true, "event": "server_reachable", "message": "Server revived", "server_name": "...", "server_uuid": "...", "url": "..." } ``` Sent when Coolify cannot reach a server. ```json { "success": false, "event": "server_unreachable", "message": "Server unreachable", "server_name": "...", "server_uuid": "...", "url": "..." } ``` Sent when disk usage on a server exceeds the configured threshold. ```json { "success": false, "event": "high_disk_usage", "message": "High disk usage detected", "server_name": "...", "server_uuid": "...", "disk_usage": 85, "threshold": 80, "url": "..." } ``` `disk_usage` and `threshold` are integer percentages. Sent when available OS patches are detected on a server. ```json { "success": false, "event": "server_patch_check", "message": "Server patches available", "server_name": "...", "server_uuid": "...", "total_updates": 12, "os_id": "ubuntu", "package_manager": "apt", "updates": [...], "critical_packages_count": 2, "url": "..." } ``` Sent when Coolify cannot complete the server patch check. ```json { "success": false, "event": "server_patch_check_error", "message": "Failed to check patches", "server_name": "...", "server_uuid": "...", "os_id": "ubuntu", "package_manager": "apt", "error": "...", "url": "..." } ``` Sent when one or more servers are running an outdated version of the Traefik proxy. ```json { "success": false, "event": "traefik_version_outdated", "message": "Traefik proxy outdated", "affected_servers_count": 1, "servers": [ { "name": "...", "uuid": "...", "current_version": "v3.1.0", "latest_version": "v3.1.4", "update_type": "patch_update", "upgrade_target": "v3.2", "newer_branch_target": "...", "newer_branch_latest": "..." } ] } ``` | Field | Description | | --------------------------------------------- | ------------------------------------------------------- | | `update_type` | `patch_update` or `minor_upgrade` | | `upgrade_target` | Target minor version — only present for `minor_upgrade` | | `newer_branch_target` / `newer_branch_latest` | Present when a newer major/minor branch is available | *** Container events [#container-events] Sent when a container stops unexpectedly (not via a manual stop action). ```json { "success": false, "event": "container_stopped", "message": "Resource stopped unexpectedly", "container_name": "...", "server_name": "...", "server_uuid": "...", "url": "..." } ``` Sent when a container is automatically restarted by Coolify. ```json { "success": true, "event": "container_restarted", "message": "Resource restarted automatically", "container_name": "...", "server_name": "...", "server_uuid": "...", "url": "..." } ``` `url` is only present when available. *** Test event [#test-event] `test` [#test] Sent when you click **Send test** in the Coolify dashboard. ```json { "success": true, "event": "test", "message": "This is a test webhook notification from Coolify.", "url": "..." } ``` # Setup (/docs/core/notifications/channels/webhook/setup) Set up webhook notifications [#set-up-webhook-notifications] Coolify webhook notifications send a JSON `POST` request to an endpoint you control. Use this channel to connect Coolify to an automation workflow, incident system, or custom application. Before you start [#before-you-start] Prepare an endpoint that: * Accepts `POST` requests over HTTP or HTTPS. * Accepts a JSON request body. * Is reachable from the Coolify instance. * Records requests or provides another way to verify delivery. * Returns a successful HTTP response promptly after accepting a request. * Can safely receive the same event more than once if a delivery is retried. For an initial test, use a development endpoint or request inspector where you can view the method, headers, and JSON body. Move to the production endpoint only after the test succeeds. *** Configure the webhook [#configure-the-webhook] Add the endpoint [#add-the-endpoint] Open **Notifications > Webhook**, enter the endpoint in **Webhook URL**, and select **Save changes**. Enable the channel [#enable-the-channel] Select **Enable**. Coolify requires a valid webhook URL before it enables the channel. Choose events [#choose-events] Under **Notification events**, select the events to send to the endpoint. See [Notification events](/core/notifications/events) for each trigger. Send a test [#send-a-test] Select **Send test** and inspect the request received by your endpoint. Confirm all of the following: * The request method is `POST`. * The body is valid JSON. * The body contains `"event": "test"`. * Your endpoint returns a successful response without waiting on long-running work. A received test confirms that Coolify can reach the current URL and submit a request. It does not verify that every event-specific field is handled by your application. *** Endpoint requirements [#endpoint-requirements] Coolify accepts URLs with the `http` or `https` scheme. The URL must contain a valid host. For server-side request protection, Coolify rejects: * `localhost`, `0.0.0.0`, and IPv6 loopback addresses. * IPv4 addresses in `127.0.0.0/8`. * Link-local IPv4 addresses in `169.254.0.0/16`, including common cloud metadata endpoints. * Hostnames ending in `.internal`. Private-network IP addresses are accepted, but the Coolify instance must still have a network route to the endpoint. *** Delivery behavior [#delivery-behavior] Coolify queues webhook deliveries and sends the JSON request body with Laravel's HTTP client. A delivery job allows up to five total attempts, with a 10-second backoff after an unhandled exception. Coolify currently does not fail the job only because the endpoint returns a non-2xx HTTP status. Return a 2xx response when your application accepts the event, and use the receiver's logs or monitoring to detect rejected requests. Your endpoint should respond promptly and handle duplicate event payloads safely. Coolify does not add a signature or shared-secret header, so use an unguessable HTTPS URL or an authenticated gateway when the endpoint is exposed to the internet. See the [webhook payload reference](/core/notifications/channels/webhook/payload-reference) for all event identifiers and fields. *** Troubleshoot webhook delivery [#troubleshoot-webhook-delivery] If the test does not reach your endpoint: 1. Confirm that the URL starts with `http://` or `https://` and includes the complete path expected by the receiver. 2. Confirm that the URL is not in one of the blocked loopback, link-local, or `.internal` ranges above. 3. From the Coolify server's network, confirm that DNS resolves the hostname and that firewalls allow the connection. 4. Check the receiving service's access and application logs. A request can reach a reverse proxy but fail before the application records it. 5. Confirm that the endpoint accepts `POST` with a JSON body and responds promptly. 6. If a private IP is used, confirm that the Coolify instance has a route to that private network. If the test succeeds but a production event does not arrive, confirm that the event is enabled under **Notification events** and compare the receiver's parser with the [payload for that event](/core/notifications/channels/webhook/payload-reference). # Notification Events (/docs/core/notifications/events) Notification events [#notification-events] Coolify lets you choose events separately for email, Discord, Telegram, Slack, Pushover, and webhook notifications. Open **Notifications**, select a channel, then use the dropdowns under **Notification events** to change that channel's event selections. Events are grouped into **Deployments**, **Resources**, **Backups**, **Scheduled tasks**, and **Servers** (**Server** on Email). Changing an event for one channel does not change the other channels. Deployments [#deployments] | Setting | When Coolify sends the notification | | :-------------------------- | :--------------------------------------------------------------------------------- | | **Deployment Success** | An application deployment completes successfully. | | **Deployment Failure** | An application deployment fails. | | **Resource status changes** | An application or resource container stops unexpectedly or restarts automatically. | | **Restart limit reached** | A resource reaches its automatic restart limit and is stopped. | Pull request preview deployments use the same **Deployment Success** and **Deployment Failure** selections as regular application deployments. *** Backups [#backups] | Setting | When Coolify sends the notification | | :----------------- | :--------------------------------------------------------------------------------------- | | **Backup Success** | A scheduled database backup completes successfully. | | **Backup Failure** | A scheduled database backup fails, or the local backup succeeds but its S3 upload fails. | When Coolify creates the local backup but cannot upload its S3 copy, it sends a warning through channels that have **Backup Failure** selected. *** Scheduled tasks [#scheduled-tasks] | Setting | When Coolify sends the notification | | :------------------------- | :-------------------------------------------------------------- | | **Scheduled Task Success** | A scheduled application or service task completes successfully. | | **Scheduled Task Failure** | A scheduled application or service task fails. | *** Server events [#server-events] | Setting | When Coolify sends the notification | | :------------------------------------------------------ | :------------------------------------------------------------------------------------- | | **Docker Cleanup Success** | An automatic Docker cleanup job completes successfully. | | **Docker Cleanup Failure** | An automatic Docker cleanup job fails. | | **Disk usage warning** (**Server disk usage** on Email) | Server disk usage exceeds the threshold configured for that server. | | **Server Reachable** | A previously unreachable server becomes reachable again. | | **Server Unreachable** | Coolify cannot reach a server after two consecutive checks. | | **Server Patching** | Coolify finds operating system updates during a patch check, or the patch check fails. | | **Traefik Proxy Outdated** | Coolify detects one or more servers running an outdated Traefik version. | *** Test the selection [#test-the-selection] After you configure a channel, select its test action: * Email uses **Send test** and asks for a recipient address. * Discord, Telegram, Slack, Pushover, and webhook channels use **Send test**. A test confirms that the current channel credentials can deliver a message. It does not trigger or verify every selected event. For webhook event identifiers and fields, see the [webhook payload reference](/core/notifications/channels/webhook/payload-reference). High-disk alerts default to a 24-hour repeat interval per server; configure the interval under the server’s **Advanced** settings. A proxy stuck in a restart loop sends at most one container-restarted notification per hour. # Overview (/docs/core/notifications/overview) Notifications overview [#notifications-overview] Coolify sends team notifications when selected deployment, backup, scheduled task, container, and server events occur. Each notification channel has its own connection details and event selections, so you can send urgent alerts to one destination and routine updates to another. How notifications work [#how-notifications-work] A notification requires both parts of the configuration: 1. An enabled channel with valid connection details. 2. The event selected under that channel's **Notification events**. Coolify stores notification settings for the current team. Team members with permission to update notification settings can change a channel, while sending a test notification requires the corresponding permission. *** Choose a channel [#choose-a-channel] | Channel | What you need | Guide | | :------------------ | :----------------------------------------------------------------------- | :------------------------------------------------------------------ | | Email | Hosted email, system-wide transactional email, SMTP, or a Resend API key | [Email](/core/notifications/channels/email) | | Discord | A Discord webhook URL | [Discord](/core/notifications/channels/discord) | | Telegram | A bot API token and chat ID | [Telegram](/core/notifications/channels/telegram) | | Slack or Mattermost | A Slack-compatible incoming webhook URL | [Slack & Mattermost](/core/notifications/channels/slack-mattermost) | | Pushover | A Pushover user key and application API token | [Pushover](/core/notifications/channels/pushover) | | Webhook | An HTTP or HTTPS endpoint that accepts JSON `POST` requests | [Webhook notifications](/core/notifications/channels/webhook/setup) | You can enable more than one channel. Event selections are independent for each channel. *** Configure notifications [#configure-notifications] The exact fields differ by channel, but the main flow is the same: 1. Open **Notifications** in the Coolify sidebar. 2. Select a channel. 3. Enter and save the channel's connection details. 4. Select **Enable**. 5. Under **Notification events**, open each event-group dropdown and select the events to send through this channel. 6. Select **Send test** and confirm that it arrives at the destination. If the test does not arrive, keep the channel enabled while you check its credentials, destination permissions, and provider logs. *** What to read next [#what-to-read-next] * [Notification events](/core/notifications/events) explains every selectable event and its trigger. * [Webhook payload reference](/core/notifications/channels/webhook/payload-reference) documents the JSON body for each webhook event. # Axiom (/docs/core/observability/log-drains/axiom) Send logs to Axiom [#send-logs-to-axiom] Coolify's built-in Axiom log drain sends opted-in resource logs to an existing Axiom dataset over HTTPS. Create an Axiom dataset and ingest-capable API token, save both values on the server's **Log Drains** page, enable the Axiom drain, then configure **Log drain** as described in [Enable log draining for a resource](/core/observability/log-drains/overview#enable-log-draining-for-a-resource) and restart each resource you want to forward. *** Before you start [#before-you-start] Create the dataset and token in [Axiom](https://axiom.co/docs), then copy their exact values before opening Coolify. Coolify accepts letters, numbers, underscores, hyphens, and periods in both Axiom fields. The built-in integration sends data to `api.axiom.co` on port `443`. This endpoint is not configurable from the Axiom section in Coolify. *** Configure Axiom in Coolify [#configure-axiom-in-coolify] Coolify checks that both fields are present and use accepted characters. It does not verify the token, dataset permissions, or Axiom ingestion before showing the drain as enabled. *** Enable a resource [#enable-a-resource] Follow [Enable log draining for a resource](/core/observability/log-drains/overview#enable-log-draining-for-a-resource), then restart or redeploy the resource. The Axiom configuration sends logs as gzip-compressed JSON, writes the event time to `_time` in ISO 8601 format, and flushes every five seconds. *** Identify logs [#identify-logs] The built-in configuration adds fields that help you filter records. For example, add this environment variable to the resource: ```dotenv COOLIFY_APP_NAME=web ``` The built-in filter excludes log records whose message contains `127.0.0.1`. Local health-check requests may therefore be absent from the dataset. *** Verify delivery [#verify-delivery] 1. Cause the resource to write a recognizable message to `stdout` or `stderr`. 2. Wait at least five seconds. 3. Open the Axiom dataset and search recent events for the message, `coolify.server_name`, or `coolify.app_name`. Verification in Axiom is required because Coolify does not perform a provider connection test. *** Update the dataset or token [#update-the-dataset-or-token] 1. Set **Status** to **Disabled** in the Axiom section. 2. Update **API key** or **Dataset name**. 3. Select **Save changes**. 4. Set **Status** to **Enabled** again. 5. Generate a new resource log and confirm that it arrives in the expected dataset. *** Fix missing logs [#fix-missing-logs] 1. Confirm Axiom is the enabled server drain and the resource's **Log drain** setting is on. 2. Confirm you restarted or redeployed the resource after enabling the setting. 3. Confirm the token can ingest into the exact dataset name entered in Coolify. 4. Confirm the server can reach `api.axiom.co:443`. 5. Inspect the Fluent Bit container on the resource server: ```sh docker ps --filter name=coolify-log-drain docker logs --tail 100 coolify-log-drain ``` Authentication, dataset, and network errors appear in the Fluent Bit output. *** Continue with log drains [#continue-with-log-drains] # Custom Fluent Bit (/docs/core/observability/log-drains/custom-fluent-bit) Configure a custom Fluent Bit log drain [#configure-a-custom-fluent-bit-log-drain] Use **Custom Fluent Bit** when the built-in Axiom and New Relic destinations do not match your logging provider. Coolify runs the configuration as supplied, so you must define the input, filters, parsing, output, authentication, and destination behavior that your provider requires. Provide a complete Fluent Bit 2.0 configuration that accepts the `forward` protocol on port `24224` and sends records to your destination. Coolify writes the configuration, starts `coolify-log-drain`, and connects opted-in resource containers to it. Coolify only checks that **Fluent Bit configuration** is not empty. An invalid directive, unavailable plugin, or rejected credential can leave `coolify-log-drain` stopped or unable to deliver logs. *** Before you start [#before-you-start] Read the [Fluent Bit configuration documentation](https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode/configuration-file) before writing the configuration. Treat the configuration as sensitive when it contains credentials. Coolify does not provide a separate custom environment-variable field for provider secrets. *** How Coolify runs the configuration [#how-coolify-runs-the-configuration] By default, Coolify writes these files on the resource server: | File | Purpose | | :-------------------------------------------- | :--------------------------------------------------- | | `/data/coolify/log-drains/fluent-bit.conf` | The complete value from **Fluent Bit configuration** | | `/data/coolify/log-drains/parsers.conf` | The optional value from **Parser configuration** | | `/data/coolify/log-drains/docker-compose.yml` | The Coolify-managed Fluent Bit service | The container mounts the two configuration files at `/fluent-bit.conf` and `/parsers.conf`. *** Write the main configuration [#write-the-main-configuration] This skeleton shows the required input and an example HTTPS output. Replace the host, URI, authentication, and output options with values supported by your provider: ```ini [SERVICE] Flush 5 Daemon off Log_Level info Parsers_File parsers.conf [INPUT] Name forward Listen 0.0.0.0 Port 24224 Buffer_Chunk_Size 1M Buffer_Max_Size 6M [OUTPUT] Name http Match * Host logs.example.com Port 443 URI /ingest format json tls On ``` The example is not a complete configuration for a specific provider. Add the provider's required header, token, payload, retry, and TLS options before enabling the drain. Use only input, filter, parser, and output plugins included in the Fluent Bit 2.0 image used by Coolify. *** Add parser definitions [#add-parser-definitions] **Parser configuration** is optional. It becomes `parsers.conf`, but adding a parser definition does not apply it automatically. The main configuration must reference the parser. For example, add this parser definition to **Parser configuration**: ```ini [PARSER] Name app_json Format json ``` Then add a parser filter to **Fluent Bit configuration**: ```ini [FILTER] Name parser Match * Key_Name log Parser app_json Reserve_Data On ``` This example parses JSON stored in the incoming `log` field and preserves the other record fields. *** Configure Coolify [#configure-coolify] 1. Open **Servers** and select the server that runs the resources. 2. Open **Log Drains**. 3. In **Custom Fluent Bit**, keep **Status** set to **Disabled**. 4. Paste the complete main configuration into **Fluent Bit configuration**. 5. If needed, paste parser definitions into **Parser configuration**. 6. Select **Save changes** in the custom section. 7. Set **Status** to **Enabled**. Coolify writes the files and starts `coolify-log-drain`. *** Enable a resource [#enable-a-resource] Follow [Enable log draining for a resource](/core/observability/log-drains/overview#enable-log-draining-for-a-resource), then restart or redeploy the resource. Your custom configuration receives the Docker log record as delivered by the local Fluentd driver. *** Verify delivery [#verify-delivery] 1. Cause the opted-in resource to write a recognizable message to `stdout` or `stderr`. 2. Wait for the **Flush** interval in your configuration. 3. Confirm the message appears in the external destination. 4. Confirm the Fluent Bit container remains running: ```sh docker ps --filter name=coolify-log-drain docker logs --tail 100 coolify-log-drain ``` Run these commands in Coolify's server terminal or over SSH on the server that hosts the resource. *** Update the configuration [#update-the-configuration] The configuration fields are read-only while the drain is enabled. 1. Set **Status** to **Disabled** to stop `coolify-log-drain`. 2. Update the main or parser configuration. 3. Select **Save changes**. 4. Set **Status** to **Enabled** again. 5. Generate a new resource log and verify the result externally. *** Fix a failed custom drain [#fix-a-failed-custom-drain] * Confirm the main configuration has a `forward` input listening on port `24224`. * Read `docker logs --tail 100 coolify-log-drain` for syntax, plugin, DNS, TLS, and authentication errors. * Confirm every parser referenced by the main configuration exists in **Parser configuration**. * Confirm the selected plugins and options are available in Fluent Bit 2.0. * Confirm the resource's **Log drain** setting is enabled and that the resource was restarted afterward. * Confirm the resource server can reach the configured output host and port. *** Continue with log drains [#continue-with-log-drains] # New Relic (/docs/core/observability/log-drains/new-relic) Send logs to New Relic [#send-logs-to-new-relic] Coolify's built-in New Relic log drain sends opted-in resource logs to the New Relic Log API. Copy an ingest license key, choose the Log API endpoint for your New Relic region, save both values on the server's **Log Drains** page, then configure **Log drain** as described in [Enable log draining for a resource](/core/observability/log-drains/overview#enable-log-draining-for-a-resource) and restart each resource you want to forward. *** Before you start [#before-you-start] Create or copy a New Relic [ingest license key](https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#ingest-license-key). Coolify accepts letters, numbers, underscores, hyphens, and periods in **License key**. *** Choose the endpoint [#choose-the-endpoint] Coolify requires **Endpoint** to be a valid URL. *** Configure New Relic in Coolify [#configure-new-relic-in-coolify] Coolify checks the required field formats and starts Fluent Bit. It does not verify the license key or send a test event to the New Relic endpoint. *** Enable a resource [#enable-a-resource] Follow [Enable log draining for a resource](/core/observability/log-drains/overview#enable-log-draining-for-a-resource), then restart or redeploy the resource. The built-in New Relic configuration flushes records every five seconds. *** Identify logs [#identify-logs] The built-in configuration adds fields that help you filter records. For example, add this environment variable to the resource: ```dotenv COOLIFY_APP_NAME=worker ``` The built-in filter excludes log records whose message contains `127.0.0.1`. Local health-check requests may therefore be absent from New Relic. *** Verify delivery [#verify-delivery] 1. Cause the resource to write a recognizable message to `stdout` or `stderr`. 2. Wait at least five seconds. 3. Open New Relic Logs and search recent events for the message, `coolify.server_name`, or `coolify.app_name`. Verification in New Relic is required because Coolify does not perform a provider connection test. *** Update the endpoint or license key [#update-the-endpoint-or-license-key] 1. Set **Status** to **Disabled** in the New Relic section. 2. Update **License key** or **Endpoint**. 3. Select **Save changes**. 4. Set **Status** to **Enabled** again. 5. Generate a new resource log and confirm that it arrives in New Relic. *** Fix missing logs [#fix-missing-logs] 1. Confirm New Relic is the enabled server drain and the resource's **Log drain** setting is on. 2. Confirm you restarted or redeployed the resource after enabling the setting. 3. Confirm the key is an ingest license key for the same New Relic account and region as the endpoint. 4. Confirm the server can reach the selected endpoint on port `443`. 5. Inspect the Fluent Bit container on the resource server: ```sh docker ps --filter name=coolify-log-drain docker logs --tail 100 coolify-log-drain ``` Authentication, endpoint, and network errors appear in the Fluent Bit output. *** Continue with log drains [#continue-with-log-drains] # Overview (/docs/core/observability/log-drains/overview) Log drains overview [#log-drains-overview] Coolify log drains forward workload container output to an external logging destination. Configure one destination on a server, then enable log draining for the resources you want to include. Enable Axiom, New Relic, or a custom Fluent Bit configuration on the server. Then turn on **Log drain** for each application, database, or service component and restart or redeploy it. *** What log drains forward [#what-log-drains-forward] Coolify starts `coolify-log-drain` on the server. Opted-in resource containers send their `stdout` and `stderr` to this local Fluent Bit container, which forwards the records to your destination. *** Choose a destination [#choose-a-destination] A server can have only one Coolify-managed log drain enabled at a time. Follow the destination guide for its credentials and configuration. *** Configure the server [#configure-the-server] 1. Open **Servers** and select the validated server that runs the resources. 2. Open **Log Drains**. 3. Enter and save the settings for one destination while **Status** is **Disabled**. 4. Set **Status** to **Enabled** to start `coolify-log-drain`. Coolify checks the required field formats but does not validate provider authentication or send a test event. *** Enable log draining for a resource [#enable-log-draining-for-a-resource] The server drain must be enabled first. Otherwise, Coolify turns the resource's **Log drain** setting off again. Coolify applies the Docker logging driver when it creates the resource container. Restart or redeploy the resource after turning **Log drain** on or off. Open the application [#open-the-application] Open the application, then select **Advanced**. This also applies to Docker Compose applications. Enable Drain Logs [#enable-drain-logs] Under **Logs**, set **Log drain** to **Send logs to the log drain endpoint**. Apply the change [#apply-the-change] Restart or redeploy the application. Open the database [#open-the-database] Open the standalone database, then select **General**. Enable Drain Logs [#enable-drain-logs-1] Under **Log delivery**, set **Log drain** to **Forward logs to the server drain**. Apply the change [#apply-the-change-1] Restart the database. Open the component [#open-the-component] Open the application or database component inside the one-click service and find **Advanced**. Enable Drain Logs [#enable-drain-logs-2] Set **Log drain** to **Send logs to drain**. Apply the change [#apply-the-change-2] Restart or redeploy the service. *** Verify delivery [#verify-delivery] 1. Make the resource write a recognizable message to `stdout` or `stderr`. 2. Open the logging provider and search recent events for that message. 3. If the event is missing, inspect the log-drain container on the resource server: ```sh docker ps --filter name=coolify-log-drain docker logs --tail 100 coolify-log-drain ``` The built-in Axiom and New Relic destinations flush every five seconds. A custom configuration uses its own **Flush** value. *** Limitations [#limitations] * A server can use only one Coolify-managed log drain at a time. * Retention, queries, dashboards, and log-based alerts are managed by the external provider. * Disabling the server drain stops forwarding but does not clear the saved **Log drain** settings on resources. # Metrics (/docs/core/observability/monitoring/metrics) Metrics [#metrics] Coolify displays CPU and memory history collected by Sentinel. Server charts show total CPU and memory usage, while resource charts show the usage of an individual application or standalone database container. Enable metrics on an eligible server to collect CPU and memory samples through Sentinel. Sampling and retention are configured per server, and charts show only the history still stored on that server. Resource metrics are not available for Docker Compose applications or one-click service deployments. The resource container must also be running before Coolify can display its metrics. *** What metrics are available [#what-metrics-are-available] *** Before you enable metrics [#before-you-enable-metrics] * Use a validated, non-Swarm server that is not configured as a build server. * Enable and sync [Sentinel](/core/observability/monitoring/sentinel) on that server. * Allow enough disk space on the connected server for the sampling rate and retention period you configure. *** Enable metrics [#enable-metrics] Metrics are enabled at the server level and use the Sentinel container already assigned to that server. Select the server [#select-the-server] Open **Servers** and select the eligible connected server. Open the Charts page [#open-the-charts-page] Open **Charts** and select **Enable Metrics**. Wait for Sentinel to restart [#wait-for-sentinel-to-restart] Coolify saves the setting and restarts Sentinel with the metrics collector enabled. The collector then begins storing server samples and samples for supported running resources. Confirm that metrics are available [#confirm-that-metrics-are-available] Wait for the **CPU Usage** and **Memory Usage** charts to begin showing data. If Sentinel is disabled, the Metrics page directs you to enable it first. Enabling metrics starts Sentinel when the server is eligible. *** View metrics [#view-metrics] Server and resource charts use different memory units. Server metrics [#server-metrics] Open **Servers > \[server] > Charts**. * **CPU Usage** is the percentage of total server CPU in use. * **Memory Usage** is the percentage of total server memory in use. Application and database metrics [#application-and-database-metrics] Open the application or standalone database, then select **Charts**. * **CPU Usage** is the percentage of CPU used by the resource container. * **Memory Usage** is the memory used by the resource container in MB. The Metrics page offers these time ranges: * 5 minutes and 10 minutes, with live refresh * 30 minutes * 1 hour * 12 hours * 1 week * 30 days The live ranges ask Coolify for new chart data every five seconds. The Sentinel sampling rate determines how often a new metric point is available. *** Sampling and retention [#sampling-and-retention] Open **Servers > \[server] > Charts** to change these values: * **Collection rate** controls the collection interval. The default is `10`, and the minimum is `1`. * **History retention** controls local retention. The default is `7`, and the minimum is `1`. * **Push interval** controls health-report frequency. The default is `60` seconds, and the minimum is `10`. Save the settings to apply them. Chart tooltips show both your local time and UTC. Sentinel stores this history under `/data/coolify/sentinel` on the connected server. A lower collection interval creates more points and uses more disk space. The chart can offer a longer range than the retained data. For example, a 30-day chart shows only the available history when **History retention** remains at its seven-day default. *** Disable metrics [#disable-metrics] Open the server **Charts** page and select **Disable Metrics**. Coolify restarts Sentinel with the collector disabled. Disabling metrics does not disable Sentinel itself. Server heartbeats, container state, health information, and disk usage reporting can continue without CPU and memory history. *** Troubleshooting [#troubleshooting] Confirm that the server Metrics page shows metrics as enabled and that Sentinel shows **In Sync**. If Sentinel is out of sync, follow [Troubleshooting Sentinel](/core/observability/monitoring/sentinel#troubleshooting) before checking the charts again. Confirm that the application or standalone database is running. Resource metrics are not currently available for Docker Compose applications or one-click service deployments. Compare the selected chart range with **History retention**. Data older than the configured retention period is unavailable. For example, the 30-day chart shows only seven days of history while the retention setting remains at its seven-day default. # Overview (/docs/core/observability/monitoring/overview) Monitoring overview [#monitoring-overview] Coolify tracks the state of connected servers and the workloads running on them. The dashboard shows current status, while notification channels can report selected failures and operational events to your team. [Sentinel](/core/observability/monitoring/sentinel) provides the preferred server-to-Coolify status path on supported servers. [Metrics](/core/observability/monitoring/metrics) adds historical CPU and memory charts. Metrics can be disabled while Sentinel continues to report server and container health. *** What Coolify monitors [#what-coolify-monitors] Monitoring in Coolify covers server state, workload state, resource usage, operational events, and logs. *** Monitoring boundaries [#monitoring-boundaries] Built-in monitoring provides platform and container visibility, but it is not a complete external observability system. Log drains forward workload container output. They do not forward Coolify deployment logs or replace the retention and alerting controls in your log provider. *** Proxy traffic analytics [#proxy-traffic-analytics] [Traffic analytics](/core/observability/monitoring/traffic-analytics) adds request, bandwidth, visitor, latency, and traffic breakdowns for Traefik and Caddy. Enable it separately on each server; collection is off by default. Continue with observability [#continue-with-observability] # Sentinel (/docs/core/observability/monitoring/sentinel) Sentinel [#sentinel] [Sentinel](https://github.com/coollabsio/sentinel) is the Rust-based lightweight agent Coolify runs on a connected server. It reports server and container health to your Coolify instance and can collect the data used by CPU and memory charts. Coolify runs Sentinel as the `coolify-sentinel` container on each eligible server. Sentinel sends authenticated status updates to Coolify and stores metric history locally when metrics are enabled. Sentinel is not available on build servers or Docker Swarm servers. Validate a standard Docker server before configuring Sentinel. *** What Sentinel reports [#what-sentinel-reports] Sentinel supplies the preferred status path from a connected server to Coolify. *** How Sentinel works [#how-sentinel-works] New server settings enable Sentinel by default, but an existing server can remain disabled. Metrics collection is separately disabled by default. *** Enable or sync Sentinel [#enable-or-sync-sentinel] 1. Open **Servers** and select the server. 2. Open **Sentinel > Configuration**. 3. If Sentinel is disabled, select **Enable Sentinel**. 4. If Coolify shows **Out of Sync**, select **Sync**. If Sentinel is already live, the same action is labeled **Restart**. 5. Wait for the server header to show **Sentinel In Sync**. Sentinel needs a URL it can reach from the connected server. If **Coolify URL** is empty, configure the instance [URL](/core/instance-management/instance-settings#url), return to Sentinel, and sync again. *** Sentinel settings [#sentinel-settings] | Setting | Default | Accepted value and effect | | :----------------- | :------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | **Coolify URL** | Generated from the Coolify instance settings | A full URL. Sentinel sends its updates to this address. Changing the instance URL updates remote servers that use the generated URL. | | **Sentinel token** | Generated by Coolify | A required authentication token. Use **Regenerate** instead of creating your own token. | Collection rate, history retention, and push interval are configured on the server's **Charts** page. See [Sampling and retention](/core/observability/monitoring/metrics#sampling-and-retention). Use **Apply and restart** after changing the Sentinel custom image. Sentinel runs with Docker's `unless-stopped` restart policy. Coolify restarts unhealthy agents or agents that stop pushing, and shows the last push error while Sentinel is out of sync. Treat the Sentinel token as a secret. Coolify encrypts it in the instance database and sends it to the Sentinel container as an environment variable. *** Sentinel and metrics [#sentinel-and-metrics] Sentinel and metrics have separate controls. Enable or disable the collector from **Servers > \[server] > Charts**. Disabling Sentinel also disables metrics. For chart scope, retention, and resource limitations, read [Metrics](/core/observability/monitoring/metrics). *** Troubleshooting [#troubleshooting] Confirm that the server is validated and shown as reachable in Coolify. Then open **Sentinel > Configuration** and select **Sync**. If Sentinel remains out of sync, open **Sentinel > Logs** and read the `coolify-sentinel` container output. After recovery, confirm that the server header changes to **Sentinel In Sync** and that its timestamp continues to update. Sentinel needs a **Coolify URL** that the connected server can reach. If the field is empty, configure the instance [URL](/core/instance-management/instance-settings#url), return to **Sentinel > Configuration**, and select **Sync** again. Open **Sentinel > Configuration** and select **Regenerate** beside **Sentinel token**. Coolify creates a new token and restarts Sentinel. Confirm that the server returns to **Sentinel In Sync**. # Traffic Analytics (/docs/core/observability/monitoring/traffic-analytics) Traffic analytics [#traffic-analytics] Coolify's Rust-based Sentinel agent reads JSON proxy access logs and stores aggregate rollups for traffic analytics. Traefik and Caddy are supported. Collection is off by default and enabled per server. Enable collection [#enable-collection] 1. Open **Servers > \[server] > Analytics**. 2. Enable traffic analytics and review the restart confirmation. 3. Wait for the proxy and Sentinel to restart. Traffic can be briefly interrupted. 4. For Caddy, redeploy applications and service stacks after enabling or disabling analytics so their logging labels are updated. 5. Send requests through the proxy, then check the analytics view. Caddy requires caddy-docker-proxy 2.9 or newer. New Coolify configurations use 2.13. If the page reports an unsupported configuration or outdated image, resolve it before enabling collection. Configure collection [#configure-collection] | Setting | Effect | | :------------------------ | :-------------------------------------------------------------------------------------------------------- | | Top-N cap | Maximum distinct values retained per dimension, such as paths or countries. Overflow is grouped as Other. | | Sample threshold | Events per second above which Sentinel samples traffic. `0` disables sampling. | | Hourly retention | Days to retain fine-grained hourly rollups. | | Daily retention | Days to retain daily rollups. | | Geolocation | Enable or disable visitor country enrichment. | | GeoIP refresh interval | Days between GeoIP database update checks. | | MaxMind GeoIP license key | Optional key for downloading GeoLite2. GeoIP works without a key using the default database source. | Save the settings after editing. Raw access logs are rotated on the server; Coolify's analytics stores aggregates rather than raw request logs. View analytics [#view-analytics] Use the dashboard widget, the global **Analytics** page, the server's **Analytics** page, or an application's or service's **Analytics** tab. The global page supports server and application filters. Views include request count, bandwidth, unique visitors, and p95 latency with sparklines, a requests chart, status-code breakdown, a country globe and country list, and device, path, host, referrer, and browser breakdowns. The 24-hour range supports optional live refresh. Traffic analytics measures requests reaching the supported proxy. CPU and memory history are separate [metrics](/core/observability/monitoring/metrics). For Caddy views with no data, check the proxy version and redeploy resources after changing collection. # Backup (/docs/core/persistent-storage/storage-mounts/backups) Back up storage mounts [#back-up-storage-mounts] Coolify can create scheduled file-level archives of eligible storage mounts attached to an application. Coolify first creates each compressed `.tar.gz` archive on the application's deployment server. It can then send a copy to S3-compatible storage and, if configured, remove the local archive after a successful upload. If the application changes files while Coolify creates the archive, the backup may be inconsistent or corrupted. This is especially important for databases. Use an application-aware backup when one is available, or stop application writes during the archive step. Check whether the mount is supported [#check-whether-the-mount-is-supported] The dashboard backup workflow described on this page is available for application storage mounts. | Mount workflow | Scheduled storage backup | | :----------------------------------------- | :----------------------- | | **Volume Mount** without a **Source Path** | Supported | | **Volume Mount** with a **Source Path** | Supported | | **Directory Mount** | Supported | | **File Mount** | Not supported | | **Host File Mount** | Not supported | For a File Mount or Host File Mount, back up the source file through source control or the process that manages the file. For database data, use the database engine's supported backup workflow instead of relying only on a file-level storage archive. Create a scheduled backup [#create-a-scheduled-backup] The application must already have an eligible mount before you can select it as a backup target. 1. Open the application in its project and environment. 2. Select **Backups**. 3. Under **Storage backups**, select **Add**. 4. Select the volume or directory in **Backup target**. 5. Enter `every_minute`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, or a valid cron expression in **Frequency**. 6. Select **Create schedule**. Coolify creates and enables the schedule. Open it to change its settings or select **Back up now**. The default frequency shown for a new schedule is `daily`. You can also open **Persistent Storage**, find the eligible volume or directory, and select **Configure Backup**. Reduce interruptions or consistency risk [#reduce-interruptions-or-consistency-risk] Under **General > Backup schedule**, choose whether Coolify should stop containers that use the selected storage while it creates the archive: * Set **Archive behavior** to **Keep containers running** to avoid an intentional interruption. Files may change during the archive. * Select **Stop containers during archive** for a safer file-level backup. Coolify gracefully stops containers that use the storage, creates the archive, and starts those containers again. The application is unavailable during that archive step. Set **Timeout** to the maximum backup runtime in seconds. The accepted range is `60` to `36000`, and the default is `3600` seconds. **Timezone** is read-only and follows the server that runs the schedule, or the instance timezone when the server has no timezone configured. Choose where backups are stored [#choose-where-backups-are-stored] Every schedule keeps a local archive on the deployment server by default. Local storage alone does not protect against losing that server. To create an off-server copy: 1. Configure and validate an [S3-compatible storage destination](/core/s3-storage/overview) for the current team. 2. Open the storage backup schedule and select **S3** to open **S3 storage**. 3. Select the **S3 storage** destination, then select **Enable S3**. 4. Select **Save changes**. Set **Local copy** to **Delete after S3 upload** only when S3 should hold the only retained copy. Coolify deletes the local archive after a successful S3 upload. If the S3 upload fails, the execution shows **Success (S3 Warning)** and Coolify keeps the local archive. Set retention limits [#set-retention-limits] Under **Retention**, local and S3 archives each have three independent limits: * **Backups to keep** * **Days to keep** * **Maximum storage (GB)** A value of `0` makes that limit unlimited. When several limits are configured, reaching any one of them triggers cleanup of the oldest successful archives in that location. The default number of local and S3 backups to keep is `7`; the day and storage limits default to `0`. Verify and download a backup [#verify-and-download-a-backup] Open **Executions** and wait for the run to finish. A usable result shows **Success** and at least one available location under **Backup Availability**. * **Local Storage** means the archive still exists on the deployment server. Select **Download** to save this local archive to your computer. * **S3 Storage** means the archive was uploaded to the selected S3 destination. * **Success (S3 Warning)** means the local archive succeeded but its S3 upload failed. Read the execution message and correct the S3 problem before relying on the remote copy. * **Failed** means the archive was not completed. Read the execution message before retrying. * **Needs attention** means recovery requires action. Read the reason, correct it, and use the retry button. Failed recovery does not indefinitely block new backups. The storage backup workflow creates, downloads, and deletes archives, but it does not provide a dashboard restore action. Before relying on a schedule, download an archive and test your restore procedure in a separate environment. Delete a backup or schedule [#delete-a-backup-or-schedule] Deleting one execution removes its local archive. When an S3 copy exists, select the S3 deletion option if you also want to remove that copy. Deleting the scheduled backup is broader: it permanently deletes the schedule and every local and S3 archive created by it. A volume or Directory Mount with a schedule cannot be deleted until you remove the schedule and its archives. # Bind mounts (/docs/core/persistent-storage/storage-mounts/bind-mounts) Bind mounts [#bind-mounts] A bind mount maps a directory on the deployment server directly to a path inside the container. The **Source Path** is the directory on the server. The **Destination Path** is where the same files appear inside the container. Changes made at either location affect the same data. When to use a bind mount [#when-to-use-a-bind-mount] Use a bind mount when you need: * a predictable server path for backups or external tools * an existing directory mounted into a container * direct access to files over SSH * a directory shared with another carefully coordinated process on the same server Use a [volume mount](/core/persistent-storage/storage-mounts/volume-mounts) when you do not need a specific server path. Docker-managed volumes reduce the chance of choosing an unsafe path or incorrect server permissions. Bind mount options [#bind-mount-options] Coolify displays existing bind-backed volume records and provides directory mounts for standard applications and standalone databases: | Workflow | Fields | Dashboard location | Behavior | | :----------------------------------------------- | :---------------------------------------------- | :------------------------------------------------------------ | :----------------------------------------------------------------------------------------------- | | Existing **Volume Mount** with a **Source Path** | **Name**, **Source Path**, **Destination Path** | **Volumes** | Keeps the existing source directory; Source Path is read-only | | **Directory Mount** | **Source Directory**, **Destination Directory** | **Directories** | Creates the source directory when needed and lets Coolify manage the directory record separately | Use **Directory Mount** for a new directory bind mount. New **Volume Mounts** create named Docker volumes and do not accept a host source path. Add a bind mount [#add-a-bind-mount] This example maps `/srv/my-app/uploads` on the deployment server to `/app/uploads` in the container. 1. Connect over SSH to the deployment server and create `/srv/my-app/uploads`. 2. Set its owner and permissions for the user that the application image runs as. 3. Open the application or database in Coolify. 4. Select **Configuration** > **Persistent Storage**. 5. Select **Add** > **Directory Mount**. 6. Enter `/srv/my-app/uploads` as the **Source Directory**. 7. Enter `/app/uploads` as the **Destination Directory** only if the application writes uploads there. 8. Select **Add**, then redeploy the resource. Upload or create a test file through the application. Confirm that it appears under `/srv/my-app/uploads` on the deployment server. Redeploy once more and confirm that the application can still read it. Do not mount `/`, `/etc`, `/var/lib/docker`, `/data/coolify`, or another broad system directory into an application container. Use a dedicated directory that contains only the files the resource needs. Prepare permissions [#prepare-permissions] Docker does not translate file ownership between the server and the container. A process running as user ID `1000` in the container still accesses the source files as user ID `1000` on the server. Check the image documentation for its runtime user, then set the source directory owner and permissions accordingly. If the application reports `Permission denied`, inspect the numeric owner on the server and the user running inside the container before making the directory globally writable. Use bind mounts with preview deployments [#use-bind-mounts-with-preview-deployments] For application preview deployments, Coolify adds `-pr-N` to the bind source path by default. A pull request numbered `12` therefore uses `/srv/my-app/uploads-pr-12` instead of `/srv/my-app/uploads`. Keep **Add suffix for PR deployments** enabled to isolate preview data. Disable it only when the source contains read-only configuration or the application is explicitly designed for concurrent access to the same files. Define bind mounts in Docker Compose [#define-bind-mounts-in-docker-compose] For a Docker Compose application or one-click service, define the server path in the Compose file: ```yaml services: app: image: example/app:latest volumes: - /srv/my-app/uploads:/app/uploads ``` Create `/srv/my-app/uploads` with the correct permissions on the deployment server before deploying. Coolify parses the mount and displays it under **Persistent Storage**, but the Compose file remains the source of truth. For repository-relative directories, read the [Docker Compose storage guide](/applications/builds/docker-compose#storage). Coolify resolves supported relative sources into the resource's configuration directory on the deployment server. Back up and move bind-mounted data [#back-up-and-move-bind-mounted-data] For an application, Coolify can schedule file-level archives for both bind mount workflows on this page: a Existing **Volume Mount** with a **Source Path** and a **Directory Mount**. Read [Storage mount backups](/core/persistent-storage/storage-mounts/backups) to configure local archives, an optional S3 copy, and retention. For a manual backup or server move, copy the source directory on the deployment server. The container destination is only another view of those same files. When moving the resource to another server: 1. Stop application writes. 2. Copy the source directory to the same path on the destination server, or update the mount to a new absolute path. 3. Preserve the required numeric owners and permissions. 4. Deploy the resource on the destination server. 5. Verify the application can read and write the mounted data. The Directory Mount deletion dialog can remove the source directory and all its contents from the deployment server. Back up the directory and read every confirmation option before deleting the mount. If the directory has a storage backup schedule, delete that schedule and its archives before Coolify will let you delete the mount. # File mounts (/docs/core/persistent-storage/storage-mounts/file-mounts) File mounts [#file-mounts] A file mount places one file from the deployment server at an exact path inside a container. Coolify provides two file workflows under **Persistent Storage**: | Workflow | Source file | What Coolify manages | | :------------------ | :-------------------------------------------------------------------- | :-------------------------------------------------------- | | **File Mount** | Coolify creates the file under the resource's configuration directory | The source file, its content, and the mount configuration | | **Host File Mount** | You create and maintain an existing file at an absolute server path | Only the mount configuration | Use a file mount for one configuration file, initialization script, policy file, or mapping file. Use a [bind mount](/core/persistent-storage/storage-mounts/bind-mounts) for a directory, and keep database files, uploads, and other changing application data in a [volume mount](/core/persistent-storage/storage-mounts/volume-mounts). Do not use the dashboard editor as a replacement for source control or a secret manager. Anyone with permission to manage the resource may be able to view or change the content of a managed File Mount. Add a managed file mount [#add-a-managed-file-mount] 1. Open the application or standalone database in Coolify. 2. Select **Configuration** > **Persistent Storage**. 3. Select **Add** > **File Mount**. 4. Enter the exact **Destination Path** inside the container, such as `/etc/example/app.conf`. 5. Check the displayed **Host file path**. This is where Coolify will create the source file on the deployment server. 6. Enter the file **Content**. 7. Select **Add**, then redeploy the resource. Coolify creates the source file under a resource-specific directory on the deployment server: * Application: `/data/coolify/applications//` * Standalone database: `/data/coolify/databases//` For example, the application destination `/etc/example/app.conf` is stored at `/data/coolify/applications//etc/example/app.conf` on the deployment server. After redeploying, verify that the file exists at the destination path inside the running container and that the application loads the expected configuration. Edit a managed file mount [#edit-a-managed-file-mount] The content shown in Coolify may be older than the file currently stored on the deployment server. 1. Select **Load from server** before editing when the application or an administrator may have changed the source file outside Coolify. 2. Edit **Content**. 3. Select **Save**. Coolify writes the updated content to the source file on the deployment server. The running container sees the mounted file, but the application may need a reload or restart before it reads the new content. Add a host file mount [#add-a-host-file-mount] Use **Host File Mount** when a file already exists on the deployment server and another process or administrator manages it. 1. Connect over SSH to the resource's deployment server. 2. Create the source file at its permanent absolute path and set permissions that allow the container process to read it. 3. Open the application or standalone database in Coolify. 4. Select **Configuration** > **Persistent Storage**. 5. Select **Add** > **Host File Mount**. 6. Enter the existing absolute path in **Host File Path**. 7. Enter the exact path inside the container in **Destination Path**. 8. Select **Add**, then redeploy the resource. Verify that the container can read the file and that the application loads the expected configuration. Coolify does not create, edit, load, change permissions on, or delete the source file used by a Host File Mount. If the source file is missing or unreadable, correct it directly on the deployment server. Coolify writes managed content files before containers start. If Docker previously created a directory at the file path, Coolify preserves the configured content when preparing the file. For an unmanaged host file, verify that the source exists as a file before deployment. Define file mounts in Docker Compose [#define-file-mounts-in-docker-compose] For a Docker Compose application or one-click service, define file mounts in the Compose file. Coolify supports a bind mount with inline `content`: ```yaml services: app: image: example/app:latest volumes: - type: bind source: ./config/app.conf target: /etc/example/app.conf content: | log_level=info ``` Save the Compose file and reload its configuration in Coolify. The dashboard lists the parsed file mount. Change its source or destination in the Compose file. Read the [Docker Compose storage guide](/applications/builds/docker-compose#storage) for directory mounts and other Compose-specific storage behavior. File mount limits [#file-mount-limits] * Coolify does not edit managed files larger than 5 MiB in the dashboard. * Binary files cannot be edited in the text field. * A file declared read-only in Docker Compose cannot be changed from the dashboard. * The destination must be a file path, not a directory. Use **Directory Mount** for a directory. * File paths cannot contain `.` or `..` path segments or use backslashes as directory separators. * The container process still needs permission to read the mounted file. If a managed file exceeds the editor limit, edit it directly on the deployment server or manage it through the resource's source repository. Back up file mounts [#back-up-file-mounts] File Mounts and Host File Mounts are not targets for Coolify's scheduled storage backups. Keep the original managed content in source control or another secure location when appropriate, and back up an existing host file through the process that manages it. Coolify can schedule file-level archives for application volumes and Directory Mounts. Read [Storage mount backups](/core/persistent-storage/storage-mounts/backups) for supported targets and limitations. Delete a file mount safely [#delete-a-file-mount-safely] Deleting a managed **File Mount** can also delete its source file from the deployment server. Before confirming deletion: 1. Copy the source file if its content is not stored anywhere else. 2. Check whether the application still requires the destination path. 3. Read the permanent-deletion option in the confirmation dialog. 4. Redeploy after removing the mount so the next container no longer expects it. Deleting a **Host File Mount** removes only the mount configuration. Coolify leaves the source file on the deployment server. Redeploy the resource so its next container starts without the mount. Relative paths and permissions [#relative-paths-and-permissions] Relative file and directory sources resolve inside the resource directory rather than the SSH user’s home directory. File-storage paths must stay within the permitted resource directory; Coolify does not write through symbolic links there or delete unrelated host paths. API requests for mounts outside the resource directory require `deploy` permission. # Overview (/docs/core/persistent-storage/storage-mounts/overview) Persistent storage overview [#persistent-storage-overview] Containers are replaceable. When Coolify redeploys a resource, Docker may remove its current container and create a new one from the latest image and configuration. Data written only to the container filesystem disappears when that container is removed. Persistent storage keeps important data on the deployment server and mounts it into each replacement container at the path your application expects. Persistent storage protects data from normal container replacement, but it does not protect against accidental deletion, disk failure, server loss, or corrupted data. For application volumes and directory mounts, Coolify can create [scheduled storage backups](/core/persistent-storage/storage-mounts/backups). Keep at least one backup outside the deployment server and test how you will restore it. How persistent storage works [#how-persistent-storage-works] A storage mount connects two locations: * the storage location outside the container, such as a Docker volume or a directory on the deployment server * the **Destination Path** inside the container where the application reads and writes the data For example, an application may write uploads to `/app/uploads` inside its container. A mount at that destination stores the uploads outside the replaceable container and makes them available again after a redeployment. Only data written under a mounted destination path is persistent. Adding a mount later does not recover data from a container that Docker has already removed. Choose a storage mount [#choose-a-storage-mount] Coolify shows four choices under **Persistent Storage**. New **Volume Mounts** use named Docker volumes, including on Swarm. Existing volume records that use a bind source retain it as a read-only **Source Path**. These dashboard workflows map to two underlying Docker storage types: named volumes and bind mounts. | Choice in Coolify | Storage location | Use it for | | :----------------------------------------------- | :--------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | | **Volume Mount** | A named Docker volume managed on the deployment server | Application data, uploads, and database files when you do not need a specific server path | | Existing **Volume Mount** with a **Source Path** | The exact directory you choose on the deployment server | Data you need to inspect, copy, or manage directly from the server filesystem | | **Directory Mount** | The exact directory you choose on the deployment server | A server directory that Coolify creates when needed and shows under **Directories** | | **File Mount** | A Coolify-managed file on the deployment server | A single configuration file mounted at one exact path inside the container | | **Host File Mount** | An existing file at the exact path you choose on the deployment server | A file that Coolify mounts without creating, editing, changing permissions, or deleting it | Start with a [volume mount](/core/persistent-storage/storage-mounts/volume-mounts) unless the application or an operational requirement needs a specific server path. Docker manages the volume location, while you only provide its name and container destination. Use a [bind mount](/core/persistent-storage/storage-mounts/bind-mounts) when the source must be a known server directory. Use a [file mount](/core/persistent-storage/storage-mounts/file-mounts) when the container needs one file rather than a directory. Coolify can manage the file content, or it can bind an existing host file without managing it. Where mounts are configured [#where-mounts-are-configured] For a standard application or standalone database: 1. Open the resource in its project and environment. 2. Select **Configuration**. 3. Select **Persistent Storage**. 4. Select **Add**, then choose the mount type. For a Docker Compose application or one-click service, the Compose file is the source of truth. Define or change mounts in the Compose file, then reload the Compose configuration. Coolify displays parsed volume mounts in the dashboard, but does not let you change those volume fields there. The deployment server stores the volume or bind-mounted files. If one Coolify instance manages several servers, storage configured for a resource is not automatically copied to the other servers. Important storage boundaries [#important-storage-boundaries] * **Destination paths depend on the image.** Use the exact path where the application writes its data. `/app` is common, but it is not a universal container base directory. * **Server storage is local to that server.** A Docker volume or local bind mount does not become shared storage just because multiple servers are connected to Coolify. * **Current multi-server applications cannot use persistent storage.** Coolify prevents adding another deployment server to an application that has persistent storage configured. * **Permissions still apply.** The user running inside the container must be able to read or write the mounted destination and its underlying storage. * **Shared writable paths need coordination.** Do not mount one writable directory or file into several containers unless the application supports concurrent access and file locking. Continue with a mount guide [#continue-with-a-mount-guide] # Volume mounts (/docs/core/persistent-storage/storage-mounts/volume-mounts) Volume mounts [#volume-mounts] A volume mount stores data in a named Docker volume on the resource's deployment server. Docker manages the volume's directory, and Coolify mounts the volume at the **Destination Path** inside each replacement container. Choose a volume mount when the data must survive redeployments but you do not need it at a specific server filesystem path. When to use a volume mount [#when-to-use-a-volume-mount] Volume mounts are a good default for: * application uploads and generated files * stateful application data * database data directories * caches that must survive container replacement Do not use a volume for temporary build files or caches that the application can safely recreate. Persistent data consumes disk space until you remove or clean up the volume. Add a volume mount [#add-a-volume-mount] Before adding the mount, find the exact directory where the application writes its data. Check the image or application documentation instead of assuming that the path starts with `/app`. 1. Open the application or database in Coolify. 2. Select **Configuration** > **Persistent Storage**. 3. Select **Add** > **Volume Mount**. 4. Review the pre-filled resource-based **Name** and change it if needed. 5. Enter the **Destination Path** inside the container. For example, use `/app/uploads` only when the application writes uploads to that exact path. 6. Select **Add**. 7. Redeploy the resource so Docker creates the new container with the mount attached. Coolify prefixes the name with the resource UUID to prevent name collisions on the deployment server. The name shown by `docker volume ls` is therefore longer than the value entered in **Name**. Verify the mount by letting the application write a test file under the destination path. Redeploy the resource again and confirm that the application can still read the file. Use volume mounts with preview deployments [#use-volume-mounts-with-preview-deployments] Application preview deployments use separate storage by default. Coolify adds a `-pr-N` suffix to the volume name, where `N` is the pull request number. After creating a mount, keep **Add suffix for PR deployments** enabled when each preview should have isolated data. Disable it only when the main application and every preview can safely share the same volume. Sharing a volume gives the main application and preview containers access to the same files. A preview can overwrite production data or apply an incompatible data change. Define volumes in Docker Compose [#define-volumes-in-docker-compose] For a Docker Compose application or one-click service, define the named volume in the Compose file: ```yaml services: app: image: example/app:latest volumes: - app-data:/app/data volumes: app-data: ``` Replace `/app/data` with the exact data directory used by the image. Save the Compose file and reload its configuration in Coolify. Coolify prefixes managed Compose volume names to avoid collisions, but preserves volumes declared `external: true`. Existing resources that used renamed external volumes keep their current volume until you explicitly migrate. Review the deployment log, copy the data to the external volume, and follow the storage page’s migration instructions before switching. Compose `driver`, `driver_opts`, and `labels` are preserved; existing volumes retain their settings. The **Persistent Storage** page displays the resulting mount as read-only because the Compose file owns its configuration. Edit the Compose file when the source or destination needs to change. Back up a volume [#back-up-a-volume] For an application, Coolify can create scheduled file-level archives of a Volume Mount, including a Volume Mount with a **Source Path**. You can keep archives on the deployment server and optionally copy them to S3-compatible storage. Read [Storage mount backups](/core/persistent-storage/storage-mounts/backups) to choose a target, reduce the risk of an inconsistent archive, set retention, and verify each execution. A file-level volume archive created while a database is writing may be inconsistent. Use the database engine's supported backup workflow for database data. If you also archive its storage, stop writes or enable **Stop containers while creating the archive**. Coolify does not let you delete a volume while its storage backup schedule exists. Delete the schedule and its archives first, then delete the volume only after confirming that you no longer need its data. Inspect a volume [#inspect-a-volume] Connect over SSH to the deployment server, then list its Docker volumes: ```bash docker volume ls ``` Inspect the volume after finding its actual name: ```bash docker volume inspect ``` The inspection output includes Docker's server-side mountpoint. Avoid editing files inside Docker's internal volume directory while the application is running. An unused volume can still contain important data. Keep **Delete Unused Volumes** disabled unless you have identified and backed up every volume that cleanup may remove. Read [Automated Docker Cleanup](/core/infrastructure/servers/automated-docker-cleanup) before enabling it. # Amazon S3 (/docs/core/s3-storage/aws) Configure Amazon S3 Storage [#configure-amazon-s3-storage] Connect a private Amazon S3 bucket to Coolify so it can store backup files. This guide creates bucket-scoped IAM credentials and validates the storage connection in Coolify. Replace these example values with your own values while following the guide: * **S3 Bucket Name:** `envix-coolify-backups-s3` * **IAM Policy Name:** `EnvixCoolifyBackupS3Access` * **IAM Username:** `EnvixCoolifyBackupS3User` * **Endpoint:** `https://s3.ap-northeast-2.amazonaws.com` 1. Create a bucket in the AWS Console. 2. Create a custom IAM policy with the permissions below. 3. Create an IAM user and attach the policy. 4. Create an access key for the IAM user. 5. Add the access key and secret key when you create the S3 storage in Coolify. ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:DeleteObject", "s3:GetObjectAcl", "s3:PutObjectAcl", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::your-bucket-name", "arn:aws:s3:::your-bucket-name/*" ] } ] } ``` Replace `your-bucket-name` in both resource values with your bucket name. Use the S3 HTTP endpoint without the bucket name, for example `https://s3.eu-central-1.amazonaws.com`. Set up Amazon S3 [#set-up-amazon-s3] Create an S3 bucket [#create-an-s3-bucket] Open the [Amazon S3 console](https://console.aws.amazon.com/s3) and select **Create bucket**. Enter the bucket name and choose its AWS Region, object ownership, and other settings. The default settings work for a standard private backup bucket. Change encryption, versioning, object ownership, or public access only when your AWS requirements call for it. Select **Create bucket**. After AWS creates the bucket, it appears in the bucket list. Create an IAM policy [#create-an-iam-policy] Open [IAM Policies](https://console.aws.amazon.com/iam/home#/policies) and select **Create policy**. Choose the **JSON** policy editor. Paste this policy into the editor: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:DeleteObject", "s3:GetObjectAcl", "s3:PutObjectAcl", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::envix-coolify-backups-s3", "arn:aws:s3:::envix-coolify-backups-s3/*" ] } ] } ``` Replace `envix-coolify-backups-s3` in both resource values with the bucket name created in the previous step. Continue to the policy details and enter the policy name. Create the policy. AWS opens the policy page after creation. If the policy does not appear immediately in a list, search for the exact policy name you entered. Create an IAM user [#create-an-iam-user] Open [IAM Users](https://console.aws.amazon.com/iam/home#/users) and select **Create user**. Enter the IAM username. Select **Next** after entering the name. 1. Select **Attach policies directly**. 2. Select the policy created in the previous step. 3. Select **Next**. Review the user and select **Create user**. Select the username to create its access key. Create an access key [#create-an-access-key] On the IAM user page, open **Security credentials**. Under **Access keys**, select **Create access key**. Choose **Other**, then continue. Select **Create access key**. Save the **Access key** and **Secret access key** somewhere secure, then select **Done**. AWS does not show the secret access key again after you close this page. If you lose it, create a replacement access key. Set up Amazon S3 in Coolify [#set-up-amazon-s3-in-coolify] In the Coolify dashboard, open **S3 Storage** from the sidebar. Select **New storage**. Complete the form: 1. Enter a name for the S3 storage. This name only identifies it in Coolify. 2. Enter an optional description. 3. Set **Protocol** to `https` and **Host** to `s3.YOUR_REGION_NAME.amazonaws.com`. Leave **Port** and **Path** empty for the standard AWS endpoint. Keep the bucket name separate. 4. Enter the S3 bucket name. 5. Enter the bucket's AWS Region. 6. Enter the IAM **Access Key**. 7. Enter the IAM **Secret Key**. 8. Select **Validate Connection & Continue**. After validation succeeds, Coolify opens the storage details page. The connection is configured and validated. You can now select this storage when you configure an [instance backup](/core/backup-and-recovery/instance-backup) or a [database backup](/databases/backups). # S3 Storage Overview (/docs/core/s3-storage/overview) S3 storage overview [#s3-storage-overview] Coolify connects to S3-compatible storage for backup files. You create the bucket with a storage provider, then add its connection details to Coolify as an S3 storage. Before you add S3 storage [#before-you-add-s3-storage] Create the bucket with your provider and collect these connection details: * Endpoint * Bucket name * Region * Access key * Secret key Coolify uses MinIO's [`mc` client](https://min.io/docs/minio/linux/reference/minio-mc.html) to transfer backup files. When you validate the storage, Coolify sends a `ListObjectsV2` request to the configured bucket. The bucket must already exist before you add and validate the storage in Coolify. Choose a storage provider [#choose-a-storage-provider] These guides cover the complete provider setup and the values to enter in Coolify: | Provider | Provider setup | Guide | | :--------------- | :----------------------------------------------- | :------------------------------------------------------ | | Amazon S3 | S3 bucket, IAM policy, IAM user, and access key | [Configure Amazon S3](/core/s3-storage/aws) | | Cloudflare R2 | R2 bucket and Object Read & Write API token | [Configure Cloudflare R2](/core/s3-storage/r2) | | Supabase Storage | Storage bucket, S3 endpoint, and access key pair | [Configure Supabase Storage](/core/s3-storage/supabase) | Other supported providers [#other-supported-providers] Coolify also supports these S3-compatible storage providers: * DigitalOcean Spaces * MinIO * Backblaze B2 * Scaleway Object Storage * Hetzner S3 Storage * Wasabi Hot Cloud Storage * Vultr * CloudPe Object Storage * IDrive e2 Other providers may also work. If you successfully connect another provider, let the Coolify team know. Add the storage to Coolify [#add-the-storage-to-coolify] After you prepare the bucket and credentials: 1. Open **S3 Storage** in the Coolify sidebar. 2. Select **New storage**. 3. Enter **Name**, optional **Description**, **Bucket**, **Region**, **Access Key**, and **Secret Key**. Split the endpoint into **Protocol**, **Host**, optional **Port**, and optional **Path**. Keep the bucket name separate from the endpoint. 4. Select **Validate Connection & Continue**. After validation succeeds, Coolify opens the storage details page. The S3 storage is then ready to select when you configure a backup. Recovering an unusable storage [#recovering-an-unusable-storage] Coolify tests S3 storages marked unusable again every hour. Once the connection works, the storage becomes usable automatically. You can also validate it after correcting credentials or connectivity. # Cloudflare R2 (/docs/core/s3-storage/r2) Cloudflare R2 [#cloudflare-r2] Cloudflare R2 is S3-compatible storage that you can use for Coolify backups. Configure Cloudflare R2 [#configure-cloudflare-r2] Create a bucket [#create-a-bucket] Create the bucket that will hold the backup files in the Cloudflare R2 dashboard. Create an R2 API token [#create-an-r2-api-token] Create an R2 API token with **Object Read & Write** permission. Scope the token to the backup bucket when you do not want it to access other R2 buckets. Save the S3 credentials [#save-the-s3-credentials] After Cloudflare creates the token, copy the S3 client credentials shown on the confirmation page. Save the **Access Key ID**, **Secret Access Key**, and **S3 endpoint**. You need all three values when adding the storage to Coolify. Add Cloudflare R2 to Coolify [#add-cloudflare-r2-to-coolify] Open **S3 Storage** in the Coolify sidebar, select **New storage**, and enter the bucket name, endpoint, and credentials from the previous steps. Set **Protocol** to `https` and **Host** to the hostname from the R2 S3 endpoint, without `https://`. Leave **Port** and **Path** empty for the standard endpoint. Leave **Region** at its default value for R2. Select **Validate Connection & Continue**. Coolify verifies the connection by listing objects in the bucket. # Supabase Storage (/docs/core/s3-storage/supabase) Supabase Storage [#supabase-storage] Supabase Storage exposes an S3-compatible endpoint that you can use with Coolify backups. This guide uses a Supabase project as a remote S3 storage endpoint for Coolify backups. It is different from self-hosting the [Supabase service](/services/supabase) on Coolify. Configure Supabase Storage [#configure-supabase-storage] Create the bucket [#create-the-bucket] In Supabase, create the bucket that will hold the backup files. Create an access key pair [#create-an-access-key-pair] Open the project and go to **Storage > S3 Configuration**, then create a new access key pair. Save the **Access Key ID** and **Secret Access Key** somewhere secure. Copy the endpoint and region [#copy-the-endpoint-and-region] Copy the S3 endpoint: * Preferred: `https://.storage.supabase.co/storage/v1/s3` * Fallback: `https://.supabase.co/storage/v1/s3` Also record the project Region shown in the Supabase dashboard. Add Supabase Storage to Coolify [#add-supabase-storage-to-coolify] In Coolify, open **S3 Storage** and select **New storage**. Enter: | Coolify field | Supabase value | | -------------- | --------------------------------------------------------------------------------- | | **Protocol** | `https`. | | **Host** | `.storage.supabase.co`, or the fallback `.supabase.co`. | | **Port** | Leave empty for the standard HTTPS endpoint. | | **Path** | `/storage/v1/s3`. | | **Bucket** | The bucket created in Supabase. | | **Region** | The Supabase project Region. | | **Access Key** | The generated **Access Key ID**. | | **Secret Key** | The generated **Secret Access Key**. | Select **Validate Connection & Continue**. Split the endpoint as shown above and keep `/storage/v1/s3` in **Path**. Do not append the bucket name to the endpoint. Verify the connection [#verify-the-connection] Coolify verifies the connection with a `ListObjectsV2` request, so the bucket must already exist before validation. Supabase Storage is S3-compatible, but it does not support every Amazon S3 feature. For Coolify backups, the endpoint, bucket, Region, and access keys above are the required values. # 2FA (/docs/core/security/authentication/2fa) Two-factor authentication [#two-factor-authentication] Two-factor authentication (2FA) adds an authenticator-code challenge after a successful password, OAuth, or SSO sign-in. Each Coolify user configures 2FA for their own account from the profile page. Coolify requests its 2FA challenge after provider authentication when 2FA is enabled for the account. SSO users can enable 2FA without a Coolify password. Configure 2FA [#configure-2fa] Before you start, install an authenticator application that supports time-based one-time passwords (TOTP). Open your profile [#open-your-profile] In Coolify, open the user menu and select **Profile**. Find **Two-factor Authentication**, then select **Configure 2FA**. Confirm your password if Coolify requests it. Add Coolify to the authenticator [#add-coolify-to-the-authenticator] Scan the QR code with the authenticator application. If you cannot scan it, select **Show manual setup** and copy the secret or OTP URL into the authenticator application. Treat the secret as a password because anyone with it can generate valid codes. Confirm the authenticator code [#confirm-the-authenticator-code] Enter the six-digit code from the authenticator application in **One-time code**, then select **Validate 2FA**. Coolify enables 2FA only after the code is accepted. Save the recovery codes [#save-the-recovery-codes] Copy every recovery code shown after confirmation and store them outside Coolify in a password manager or another secure location. Do not keep the only copy in the browser, on the Coolify server, or on the same device as the authenticator application. *** Sign in with 2FA [#sign-in-with-2fa] After Coolify accepts your password or completes provider sign-in, enter the current six-digit code from the authenticator application. To use a recovery code instead, select **Use Recovery Code Instead**, enter a saved recovery code, and continue. Return to an authenticator code with **Use Authenticator Code Instead**. If correct authenticator codes are rejected, check that the device running the authenticator and the Coolify server have accurate time. Follow [2FA stopped working](/troubleshoot/server/two-factor-stopped-working) for the self-hosted server time checks. *** Manage recovery codes [#manage-recovery-codes] Open **Profile > Two-factor Authentication**, then select **Regenerate recovery codes** when: * a recovery code may have been exposed * you no longer have the saved set * your recovery storage has changed Coolify displays the replacement set after regeneration. Replace every previously saved copy with the new codes. *** Disable 2FA [#disable-2fa] Open **Profile > Two-factor Authentication** and select **Disable 2FA**. Confirm your password if requested. Disabling 2FA removes the authenticator setup and its recovery codes from the account. It does not change the account password or disable OAuth providers. *** Regain access without a working code [#regain-access-without-a-working-code] Try the least destructive recovery path first: 1. Check the authenticator device time and the self-hosted Coolify server time. 2. Use one of the recovery codes saved during setup. 3. If neither works, use the recovery path for your Coolify deployment. | Deployment | Recovery path | | :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Self-hosted Coolify | A server administrator can follow [Reset 2FA](/core/backup-and-recovery/reset-2fa). The procedure clears the authenticator secret and recovery codes for the selected account. | | Coolify Cloud | [Contact the Coolify team](/support). Coolify Cloud users cannot access the container required for the self-hosted reset procedure. | After access is restored, configure 2FA again and save the new recovery codes. # Azure (/docs/core/security/authentication/oauth/azure) Configure Azure OAuth [#configure-azure-oauth] Register Coolify as a Microsoft Entra web application. Coolify uses Microsoft Graph `User.Read` to obtain the signed-in user's name and user principal name. Replace the example domain while following this guide: * **Coolify callback:** `https://coolify.shadowarcanist.com/auth/azure/callback` * **Tenant:** the Microsoft Entra **Directory (tenant) ID** Set up Azure OAuth [#set-up-azure-oauth] Create an app registration [#create-an-app-registration] Open the [Microsoft Entra admin center](https://entra.microsoft.com/), then go to **Identity > Applications > App registrations** and select **New registration**. Enter a name such as `Coolify`. Choose the supported account type that matches who may sign in. Under **Redirect URI**, select **Web** and enter: ```txt https://coolify.shadowarcanist.com/auth/azure/callback ``` Select **Register**. Copy the application and tenant IDs [#copy-the-application-and-tenant-ids] On the app registration **Overview** page, copy: * **Application (client) ID** * **Directory (tenant) ID** For a single-tenant organization, use the Directory tenant ID in Coolify. Microsoft also supports tenant selectors such as `organizations`, `common`, or `consumers` for app registrations configured for those account types. Create a client secret [#create-a-client-secret] Open **Certificates & secrets > Client secrets**, select **New client secret**, enter a description and expiration, then select **Add**. Copy the secret **Value** immediately. Do not copy the **Secret ID**; Coolify needs the secret value. Confirm Microsoft Graph access [#confirm-microsoft-graph-access] Open **API permissions** and confirm that the delegated Microsoft Graph permission **User.Read** is present. Add it if the registration does not already include it. Apply administrator consent when your Microsoft Entra policies require it. Configure Azure in Coolify [#configure-azure-in-coolify] Open **Settings > Authentication** and find **Azure**. | Coolify field | Microsoft Entra value | | :---------------- | :---------------------------------------------------------------------------------- | | **Client ID** | **Application (client) ID** | | **Client Secret** | Client secret **Value** | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/azure/callback` | | **Tenant** | **Directory (tenant) ID**, or the allowed tenant selector for the app registration. | Select **Save**, then turn on **Enabled** for Azure. Verify Azure sign-in [#verify-azure-sign-in] Open the Coolify login page in a private browser window and select **Login with Azure**. Sign in with an account allowed by the app registration, then confirm that Coolify opens the matching account. Troubleshooting [#troubleshooting] Open **Authentication** on the app registration and confirm the **Web** redirect URI exactly matches `/auth/azure/callback` on the public Coolify domain. Confirm that **User.Read** is granted and that Microsoft Graph returns a user principal name Coolify can use as the account email. Also confirm that the client secret has not expired. # Bitbucket (/docs/core/security/authentication/oauth/bitbucket) Configure Bitbucket OAuth [#configure-bitbucket-oauth] Create a Bitbucket Cloud OAuth consumer so Coolify can read the signed-in user's profile and confirmed primary email address. Replace the example domain while following this guide: * **Coolify URL:** `https://coolify.shadowarcanist.com` * **Callback URL:** `https://coolify.shadowarcanist.com/auth/bitbucket/callback` Set up Bitbucket OAuth [#set-up-bitbucket-oauth] Open OAuth consumers [#open-oauth-consumers] Open Bitbucket Cloud, select the workspace that will own the integration, then go to **Workspace settings > OAuth consumers**. You need permission to manage settings for the workspace. See Atlassian's [Bitbucket OAuth documentation](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/) when the workspace navigation differs. Add an OAuth consumer [#add-an-oauth-consumer] Select **Add consumer** and enter: | Bitbucket field | Value | | :--------------- | :----------------------------------------------------------- | | **Name** | A recognizable name such as `Coolify`. | | **Website** | `https://coolify.shadowarcanist.com` | | **Callback URL** | `https://coolify.shadowarcanist.com/auth/bitbucket/callback` | Under permissions, grant read access to the account and email address. Coolify requests the `email` scope and uses the confirmed primary email returned by Bitbucket. Save the consumer. Save the Bitbucket credentials [#save-the-bitbucket-credentials] Expand the created consumer and copy its **Key** and **Secret**. The Bitbucket **Key** is the OAuth client ID. Store the secret securely. Configure Bitbucket in Coolify [#configure-bitbucket-in-coolify] Open **Settings > Authentication** and find **Bitbucket**. | Coolify field | Bitbucket value | | :---------------- | :----------------------------------------------------------- | | **Client ID** | OAuth consumer **Key** | | **Client Secret** | OAuth consumer **Secret** | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/bitbucket/callback` | Select **Save**, then turn on **Enabled** for Bitbucket. Verify Bitbucket sign-in [#verify-bitbucket-sign-in] Open the Coolify login page in a private browser window and select **Login with Bitbucket**. Approve the consumer if requested, then confirm that Coolify opens the account matching the confirmed primary Bitbucket email. Troubleshooting [#troubleshooting] Compare the consumer **Callback URL** with **Redirect URI** in Coolify. Both must use the same HTTPS domain and `/auth/bitbucket/callback` path. Confirm that the consumer has email read permission and that the Bitbucket account has a confirmed primary email address. # Discord (/docs/core/security/authentication/oauth/discord) Configure Discord OAuth [#configure-discord-oauth] Create a Discord application so Coolify can request the `identify` and `email` scopes during sign-in. Replace the example domain while following this guide: * **Coolify URL:** `https://coolify.shadowarcanist.com` * **Redirect:** `https://coolify.shadowarcanist.com/auth/discord/callback` Set up Discord OAuth [#set-up-discord-oauth] Create a Discord application [#create-a-discord-application] Open the [Discord Developer Portal](https://discord.com/developers/applications), select **New Application**, enter a name such as `Coolify`, and create the application. The application does not need a bot for Coolify sign-in. Register the Coolify redirect [#register-the-coolify-redirect] Open **OAuth2** for the Discord application. Under **Redirects**, select **Add Redirect** and enter: ```txt https://coolify.shadowarcanist.com/auth/discord/callback ``` Save the changes. Coolify supplies the `identify` and `email` scopes when it starts authorization. You do not need to generate or copy an OAuth URL from Discord. Copy the Discord credentials [#copy-the-discord-credentials] On the **OAuth2** or **General Information** page, copy **Client ID**. Copy or reset the **Client Secret**, then store the complete value securely. Resetting the secret invalidates the previous value. Configure Discord in Coolify [#configure-discord-in-coolify] Open **Settings > Authentication** and find **Discord**. | Coolify field | Discord value | | :---------------- | :--------------------------------------------------------- | | **Client ID** | Discord application **Client ID** | | **Client Secret** | Discord application **Client Secret** | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/discord/callback` | Select **Save**, then turn on **Enabled** for Discord. Verify Discord sign-in [#verify-discord-sign-in] Coolify identifies an existing user by email address. The email address on the Discord account must match the email address on the Coolify account. Matching is case-insensitive. Open the Coolify login page in a private browser window and select **Login with Discord**. Authorize the application, then confirm that Coolify opens the account with the matching email address. An existing account can be linked only when Discord returns a verified email address. New accounts follow the registration settings. See [OAuth sign-in behavior](/core/security/authentication/oauth/overview). Troubleshooting [#troubleshooting] Confirm that the exact Coolify callback appears under the Discord application's **OAuth2 > Redirects** list and has been saved. Confirm that the Discord account has an email address and that it matches the email address on the existing Coolify account. Also confirm that the authorization screen includes both `identify` and `email` access. If the client secret was reset, update **Client Secret** in Coolify. # GitHub (/docs/core/security/authentication/oauth/github) Configure GitHub OAuth [#configure-github-oauth] Create a GitHub OAuth App so GitHub can return a verified primary email address to Coolify after sign-in. Replace the example domain while following this guide: * **Coolify URL:** `https://coolify.shadowarcanist.com` * **Authorization callback URL:** `https://coolify.shadowarcanist.com/auth/github/callback` Set up GitHub OAuth [#set-up-github-oauth] Open GitHub OAuth Apps [#open-github-oauth-apps] Open [GitHub Developer settings](https://github.com/settings/developers), select **OAuth Apps**, then select **New OAuth App**. To let an organization own the credential, open that organization's settings and create the OAuth App there instead. You need permission to manage OAuth Apps for the selected account or organization. Register the Coolify application [#register-the-coolify-application] Complete the GitHub form: | GitHub field | Value | | :----------------------------- | :-------------------------------------------------------------------- | | **Application name** | A recognizable name such as `Coolify`. | | **Homepage URL** | The public Coolify URL, such as `https://coolify.shadowarcanist.com`. | | **Application description** | Optional information for people authorizing the app. | | **Authorization callback URL** | `https://coolify.shadowarcanist.com/auth/github/callback` | Select **Register application**. A GitHub OAuth App has one callback URL. Create another OAuth App when a second Coolify instance uses a different public domain. Create the client secret [#create-the-client-secret] On the OAuth App page, copy **Client ID**, then select **Generate a new client secret**. Copy the generated client secret and store it securely. You need the complete secret in Coolify. Configure GitHub in Coolify [#configure-github-in-coolify] In Coolify, open **Settings > Authentication** and find **GitHub**. | Coolify field | GitHub value | | :---------------- | :-------------------------------------------------------- | | **Client ID** | The GitHub OAuth App client ID. | | **Client Secret** | The generated GitHub client secret. | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/github/callback` | Select **Save**, then turn on **Enabled** for GitHub. Verify GitHub sign-in [#verify-github-sign-in] Open the Coolify login page in a private browser window and select **Login with GitHub**. Authorize the OAuth App if GitHub asks, then confirm that Coolify opens the account with the same email address as the verified primary GitHub email. Troubleshooting [#troubleshooting] Compare the **Authorization callback URL** in GitHub with **Redirect URI** in Coolify. The scheme, domain, `/auth/github/callback` path, and trailing slash must match. GitHub must return a verified primary email address. Confirm that the GitHub account has one under **Settings > Emails** and that the OAuth authorization grants the requested `user:email` access. # GitLab (/docs/core/security/authentication/oauth/gitlab) Configure GitLab OAuth [#configure-gitlab-oauth] Create a GitLab OAuth application so Coolify can read the authenticated user's profile and email address. The same Coolify provider card supports GitLab.com and self-managed GitLab. Replace these values while following the guide: * **Coolify callback:** `https://coolify.shadowarcanist.com/auth/gitlab/callback` * **GitLab.com Base URL:** leave empty * **Self-managed Base URL:** `https://gitlab.shadowarcanist.com` Set up GitLab OAuth [#set-up-gitlab-oauth] Open GitLab applications [#open-gitlab-applications] Sign in to GitLab, open your avatar menu, select **Edit profile**, then open **Access > Applications**. On a self-managed instance, an administrator can create an instance-wide application instead when organizational ownership is required. Follow GitLab's [OAuth provider documentation](https://docs.gitlab.com/integration/oauth_provider/) for the applicable application location. Create the OAuth application [#create-the-oauth-application] Select **Add new application** and enter: | GitLab field | Value | | :--------------- | :-------------------------------------------------------- | | **Name** | A recognizable name such as `Coolify`. | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/gitlab/callback` | | **Confidential** | Enabled. Coolify stores and uses a client secret. | | **Scopes** | Select `read_user`. | Save the application. Save the GitLab credentials [#save-the-gitlab-credentials] Copy the **Application ID** and **Secret** from the created application. Store the secret securely. If GitLab no longer shows the complete value, create or rotate the secret before continuing. Configure GitLab in Coolify [#configure-gitlab-in-coolify] Open **Settings > Authentication** and find **GitLab**. | Coolify field | GitLab value | | :---------------- | :----------------------------------------------------------------------------------------------------------------------- | | **Client ID** | The GitLab **Application ID**. | | **Client Secret** | The GitLab application **Secret**. | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/gitlab/callback` | | **Base URL** | Leave empty for GitLab.com. For self-managed GitLab, enter only its origin, such as `https://gitlab.shadowarcanist.com`. | Select **Save**, then turn on **Enabled** for GitLab. Verify GitLab sign-in [#verify-gitlab-sign-in] Open the Coolify login page in a private browser window and select **Login with GitLab**. Approve the application if requested, then confirm that Coolify opens the account matching the GitLab email address. Troubleshooting [#troubleshooting] Set **Base URL** to the self-managed GitLab origin. Do not include `/oauth/authorize`, `/api`, or a trailing application path. Confirm that GitLab and Coolify contain the exact `https://coolify.shadowarcanist.com/auth/gitlab/callback` value and that the application is confidential with the `read_user` scope. # Google (/docs/core/security/authentication/oauth/google) Configure Google OAuth [#configure-google-oauth] Create a Google OAuth client for a web application so Google can return the user's OpenID profile and email address to Coolify. Replace the example domain while following this guide: * **Coolify URL:** `https://coolify.shadowarcanist.com` * **Authorized redirect URI:** `https://coolify.shadowarcanist.com/auth/google/callback` * **Hosted domain:** `shadowarcanist.com` (optional) Set up Google OAuth [#set-up-google-oauth] Select a Google Cloud project [#select-a-google-cloud-project] Open the [Google Auth Platform](https://console.cloud.google.com/auth/overview) and select or create the Google Cloud project that will own the OAuth client. If Google asks you to configure the consent screen, complete **Branding**, choose the appropriate **Audience**, and add contact information. For an external app in testing, add every person who will test Coolify as a test user. Create a web OAuth client [#create-a-web-oauth-client] Open **Clients**, select **Create client**, and choose **Web application** as the application type. Enter a name such as `Coolify`. Under **Authorized redirect URIs**, add: ```txt https://coolify.shadowarcanist.com/auth/google/callback ``` Create the client. Save the Google credentials [#save-the-google-credentials] Copy the generated **Client ID** and **Client secret**. You can also download the client JSON, but Coolify only needs these two values. Configure Google in Coolify [#configure-google-in-coolify] Open **Settings > Authentication** and find **Google**. | Coolify field | Google value | | :---------------- | :-------------------------------------------------------------------------------------------------------- | | **Client ID** | The Google web client ID. | | **Client Secret** | The Google client secret. | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/google/callback` | | **Hosted domain** | Optional allowed Google Workspace domain, such as `shadowarcanist.com`. Use `*` for any Workspace domain. | Select **Save**, then turn on **Enabled** for Google. Coolify enforces the configured Workspace domain. `*` allows any Google Workspace account, but rejects personal Google accounts. Leave the field empty when you do not need a Workspace restriction. Verify Google sign-in [#verify-google-sign-in] Open the Coolify login page in a private browser window and select **Login with Google**. Complete consent if requested, then confirm that Coolify opens the account matching the Google email address. Troubleshooting [#troubleshooting] Open the web client in Google Auth Platform and compare **Authorized redirect URIs** with the Coolify **Redirect URI**. Google requires an exact match. If the consent screen is in testing, add the Google account under **Audience > Test users**. For an internal app, confirm that the account belongs to the selected Google Workspace organization. # Infomaniak (/docs/core/security/authentication/oauth/infomaniak) Configure Infomaniak OAuth [#configure-infomaniak-oauth] Create an Infomaniak Application credential so Coolify can request the OpenID, email, and profile information used during sign-in. Replace the example domain while following this guide: * **Coolify URL:** `https://coolify.shadowarcanist.com` * **Redirect URL:** `https://coolify.shadowarcanist.com/auth/infomaniak/callback` Set up Infomaniak OAuth [#set-up-infomaniak-oauth] Open Infomaniak applications [#open-infomaniak-applications] Sign in to Infomaniak and open [Applications](https://manager.infomaniak.com/v3/ng/profile/user/applications/list) in the user profile settings. Select the option to create an application credential. Create the application [#create-the-application] Choose **Application** as the application type. Enter a recognizable name such as `Coolify` and use this redirect URL: ```txt https://coolify.shadowarcanist.com/auth/infomaniak/callback ``` Create the application. Save the Infomaniak credentials [#save-the-infomaniak-credentials] Copy the application client ID and client secret shown by Infomaniak. Store the client secret securely before leaving the credential page. Configure Infomaniak in Coolify [#configure-infomaniak-in-coolify] Open **Settings > Authentication** and find **Infomaniak**. | Coolify field | Infomaniak value | | :---------------- | :------------------------------------------------------------ | | **Client ID** | Infomaniak application client ID | | **Client Secret** | Infomaniak application client secret | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/infomaniak/callback` | Select **Save**, then turn on **Enabled** for Infomaniak. Verify Infomaniak sign-in [#verify-infomaniak-sign-in] Open the Coolify login page in a private browser window and select **Login with Infomaniak**. Complete authorization, then confirm that Coolify opens the account matching the Infomaniak email address. Troubleshooting [#troubleshooting] Open the Infomaniak application and confirm its redirect URL exactly matches the public Coolify domain and `/auth/infomaniak/callback` path. Confirm that the client ID and secret belong to the same Infomaniak application and that the Infomaniak account returns an email address. Create a new secret if the original value was not saved completely. # Overview (/docs/core/security/authentication/oauth/overview) OAuth overview [#oauth-overview] OAuth lets people sign in to a self-hosted Coolify instance through a supported external provider instead of entering their Coolify password. Coolify Cloud manages its own sign-in providers. On a self-hosted instance, a root team administrator or owner can configure providers under **Settings > Authentication**. How OAuth sign-in works [#how-oauth-sign-in-works] Coolify links an account to the provider identity returned at sign-in. On the first OAuth login after upgrading, an existing account is linked only if the provider verifies its email address. An exception applies to passwordless accounts created by OAuth before this release. Each account links to one OAuth provider. If you previously used several providers with the same email address, use the provider you want to keep on your first sign-in after upgrading. Subsequent sign-ins use the linked identity rather than email matching alone. New accounts follow the registration settings. Linked identities appear on **Profile**, and provider-managed email addresses cannot be changed in Coolify. A denied sign-in displays the reason on the login page. When Coolify 2FA is enabled, OAuth sign-in also requires the Coolify authenticator or recovery code. Users without a password can enable 2FA from their profile. See [Two-factor authentication](/core/security/authentication/2fa). Choose an OAuth provider [#choose-an-oauth-provider] Each guide creates the external provider application, registers the exact Coolify callback URL, adds the provider credentials to Coolify, and verifies sign-in. | Provider | What you create | Guide | | :--------- | :------------------------------------------------------ | :--------------------------------------------------------------------------- | | GitHub | OAuth App with `user:email` access | [Configure GitHub OAuth](/core/security/authentication/oauth/github) | | GitLab | OAuth application with `read_user` access | [Configure GitLab OAuth](/core/security/authentication/oauth/gitlab) | | Google | Web OAuth client with OpenID, profile, and email access | [Configure Google OAuth](/core/security/authentication/oauth/google) | | Azure | Microsoft Entra app registration with `User.Read` | [Configure Azure OAuth](/core/security/authentication/oauth/azure) | | Bitbucket | OAuth consumer with email access | [Configure Bitbucket OAuth](/core/security/authentication/oauth/bitbucket) | | Discord | Discord application using `identify` and `email` | [Configure Discord OAuth](/core/security/authentication/oauth/discord) | | Infomaniak | Infomaniak Application credential | [Configure Infomaniak OAuth](/core/security/authentication/oauth/infomaniak) | For Authentik, Clerk, and Zitadel, use the [SSO guides](/core/security/authentication/sso/overview). Control account creation [#control-account-creation] Use **Settings > Authentication** to disable password registration while an OAuth provider is enabled. The login page then shows **Only OAuth registration is enabled**. The OIDC provider has an **Allow OIDC user creation** setting that can permit account creation when password registration is disabled. Each provider can **Auto-join new users to Root team** as members instead of creating a personal team. This applies to newly created users. Coolify does not map provider groups or claims to team roles; manage those roles in Coolify. Keep linked identities working after a provider change [#keep-linked-identities-working-after-a-provider-change] If you change a self-hosted GitLab, Authentik, Clerk, or Zitadel host, or change the Azure tenant, rekey existing identities from the Coolify server: ```sh docker exec coolify php artisan oauth:rekey --from= ``` Replace `` with `gitlab`, `authentik`, `clerk`, `zitadel`, or `azure`. Keep the old URL or tenant value before changing the settings. Test safely [#test-safely] Configure and test one provider at a time. Use a non-root account first, and keep a working administrator password until provider sign-in has been verified from a private browser window. # Profile and Account Deletion (/docs/core/security/authentication/profile) Profile and account deletion [#profile-and-account-deletion] Open the user menu and select **Profile** to manage your account and [two-factor authentication](/core/security/authentication/2fa). Linked SSO identities are displayed here. When your email is managed by a provider, change it at the provider; Coolify does not allow editing it locally. For an account with a linked OAuth identity, destructive actions use typed confirmation without requiring a Coolify password. Review every action listed by the confirmation before proceeding. Delete your account [#delete-your-account] Use the account-deletion action on **Profile** and complete the confirmation. Deleting an account: * deletes teams where you are the only member * removes you from all other teams * revokes your API tokens and sessions Deletion is blocked for the root user, while a team you own alone still has servers, projects, or Git sources, and when leaving a shared team would leave it without an administrator or owner. Before retrying a blocked deletion, remove the remaining resources or arrange the required ownership and administration in each team. Account deletion is separate from removing a member through team administration; see [Remove a member](/core/team/members/remove-a-member). # Authentik (/docs/core/security/authentication/sso/authentik) Configure Authentik SSO [#configure-authentik-sso] Create an OAuth2/OpenID Connect provider and application in Authentik, then connect the provider to Coolify with a confidential client ID and secret. Authentik SSO is available in Coolify v4.3.0 or above Replace these values while following the guide: * **Coolify callback:** `https://coolify.shadowarcanist.com/auth/authentik/callback` * **Authentik Base URL:** `https://auth.shadowarcanist.com` * **Application name:** `Coolify` Set up Authentik SSO [#set-up-authentik-sso] Start an Authentik application [#start-an-authentik-application] Sign in to the Authentik administration interface and open **Applications > Applications**. Select **Create with Provider**, enter a name such as `Coolify`, and choose a slug. Continue with **OAuth2/OpenID Connect** as the provider type. If your Authentik version creates providers separately, open **Applications > Providers**, create an **OAuth2/OpenID Provider**, then attach it to a new application. See Authentik's [OAuth2/OpenID provider documentation](https://docs.goauthentik.io/add-secure-apps/providers/oauth2/) if the navigation or field names differ in your installed version. Configure the OAuth2/OpenID provider [#configure-the-oauth2openid-provider] Configure the provider as a confidential authorization-code client: | Authentik setting | Value | | :------------------------ | :------------------------------------------------------------------------------------------------------ | | **Client type** | **Confidential** | | **Redirect URIs/Origins** | Strict URI `https://coolify.shadowarcanist.com/auth/authentik/callback` | | **Scopes** | Include `openid`, `profile`, and `email`. Coolify also requests Authentik's `goauthentik.io/api` scope. | | **Authorization flow** | Select the flow your users should complete. | | **Signing key** | Use the signing key required by your Authentik policy. | For Authentik 2025.10 and later, linking an existing Coolify account requires the email scope to return `email_verified: true`. Under **Customization > Property Mappings**, add a scope mapping for `email` with this expression: ```python return {"email": request.user.email, "email_verified": True} ``` Use it on the provider instead of the default email mapping. Only assert verification for users whose email addresses your organization trusts. Save the provider and application. Use Authentik policies, groups, or application bindings to restrict who may access the Coolify application. Save the Authentik credentials [#save-the-authentik-credentials] Copy the provider **Client ID** and **Client Secret**. Store the secret securely. The **Base URL** for Coolify is the Authentik instance origin, such as `https://auth.shadowarcanist.com`. Do not append `/application/o/authorize/` or the application slug. Configure Authentik in Coolify [#configure-authentik-in-coolify] Open **Settings > Authentication** and find **Authentik**. | Coolify field | Authentik value | | :---------------- | :----------------------------------------------------------- | | **Client ID** | Authentik provider client ID | | **Client Secret** | Authentik provider client secret | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/authentik/callback` | | **Base URL** | Authentik origin, such as `https://auth.shadowarcanist.com` | Select **Save**, then turn on **Enabled** for Authentik. Verify Authentik sign-in [#verify-authentik-sign-in] Open the Coolify login page in a private browser window and select **Login with Authentik**. Complete the assigned Authentik flow, then confirm that Coolify opens the account matching the Authentik email address. Also test an Authentik user who is not allowed by the application policy and confirm that Authentik blocks access. Troubleshooting [#troubleshooting] Open the Authentik OAuth2/OpenID provider and compare its strict redirect URI with the Coolify **Redirect URI**. Do not use a regex unless your Authentik policy requires one. Confirm that **Base URL** contains only the public Authentik origin and is reachable from the Coolify server. Authentik exposes authorization, token, and user information below `/application/o/`. Confirm that the provider includes the `email` scope and returns an email address for the user. Also check that the application policy permits that user. # Clerk (/docs/core/security/authentication/sso/clerk) Configure Clerk SSO [#configure-clerk-sso] Configure Clerk as the identity provider for Coolify by creating a Clerk OAuth application with profile and email access. Clerk SSO is available in Coolify v4.3.0 or above Replace these values while following the guide: * **Coolify callback:** `https://coolify.shadowarcanist.com/auth/clerk/callback` * **Clerk Base URL:** `https://shadowarcanist.clerk.accounts.dev` Set up Clerk SSO [#set-up-clerk-sso] Create a Clerk OAuth application [#create-a-clerk-oauth-application] Open the Clerk Dashboard for the Clerk instance that will authenticate Coolify users, then go to **OAuth applications**. Select **Add OAuth application**, enter a name such as `Coolify`, and include the `email` and `profile` scopes. Add `openid` only when another client needs OIDC; Coolify's Clerk integration requests `email` and `profile`. Select **Add**. See Clerk's [OAuth application guide](https://clerk.com/docs/guides/configure/auth-strategies/oauth/single-sign-on) if the dashboard navigation differs. Save the Clerk credentials [#save-the-clerk-credentials] Copy the **Client Secret** from the creation modal and store it securely. Clerk does not show the complete secret again. On the OAuth application's settings page, copy **Client ID**. Register the Coolify redirect [#register-the-coolify-redirect] In the Clerk OAuth application, add this value under **Redirect URIs**: ```txt https://coolify.shadowarcanist.com/auth/clerk/callback ``` Save the application. Use Clerk's user and organization controls to decide who may authenticate through the OAuth application. Copy the Clerk Base URL [#copy-the-clerk-base-url] Open **API Keys** in the Clerk Dashboard and copy the instance's **Frontend API URL**. A development instance usually resembles: ```txt https://shadowarcanist.clerk.accounts.dev ``` A production instance may use a custom Clerk domain. Use the origin shown by Clerk without `/oauth/authorize`, `/oauth/token`, or another path. Configure Clerk in Coolify [#configure-clerk-in-coolify] Open **Settings > Authentication** and find **Clerk**. | Coolify field | Clerk value | | :---------------- | :------------------------------------------------------- | | **Client ID** | Clerk OAuth application client ID | | **Client Secret** | Clerk OAuth application client secret | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/clerk/callback` | | **Base URL** | Clerk Frontend API URL | Select **Save**, then turn on **Enabled** for Clerk. Verify Clerk sign-in [#verify-clerk-sign-in] Open the Coolify login page in a private browser window and select **Login with Clerk**. Complete Clerk authentication, then confirm that Coolify opens the account matching the primary Clerk email address. Troubleshooting [#troubleshooting] Confirm that the Clerk OAuth application lists the exact public Coolify callback under **Redirect URIs**. Confirm that **Base URL** is the Clerk Frontend API origin, not `dashboard.clerk.com` and not a URL with `/oauth/authorize` appended. Confirm that the OAuth application grants `email` and `profile`, that the Clerk user has a primary email address, and that the client secret in Coolify is current. # OpenID Connect (/docs/core/security/authentication/sso/oidc) OpenID Connect [#openid-connect] Use a generic OpenID Connect (OIDC) provider for sign-in to a self-hosted Coolify instance. Configure it as a root team administrator or owner under **Settings > Authentication > OpenID Connect**. Configure the provider [#configure-the-provider] 1. Create a confidential web application at your identity provider. 2. Copy the **Redirect URI** displayed by Coolify into the provider's allowed redirect URIs. Keep an exact match, including the scheme and path. 3. Enter the **Issuer URL**, **Client ID**, and **Client secret** in Coolify. Coolify discovers the authorization, token, userinfo, and JWKS endpoints from the issuer. 4. Set **Scopes** to include `openid`. Include `email` and `profile` when supported. Request any additional scopes your provider requires. 5. Configure **Use PKCE**, **Require verified email**, and **Clock skew (seconds)** for your provider. You can customize the **Login button label**. 6. Save the settings and enable the provider. Configure the instance URL before setup so Coolify generates the correct default callback URL. Registration and team membership [#registration-and-team-membership] **Allow OIDC user creation** permits a successful OIDC login to create a user when password registration is disabled. Disable it when only existing users should sign in. **Auto-join new users to Root team** adds newly created users as members without creating a personal team. Under **Settings > Authentication**, you can disable password registration while OAuth is enabled. Review [OAuth account linking](/core/security/authentication/oauth/overview) before linking existing users. Existing-account linking requires a verified email address; disabling the OIDC verification setting does not bypass that requirement. Microsoft Entra ID [#microsoft-entra-id] Use this issuer URL, replacing the tenant placeholder: ```text https://login.microsoftonline.com//v2.0 ``` In the app registration, add the optional ID token claims `email` and `xms_edov`. Coolify accepts `xms_edov` as evidence of email verification. Register the OIDC callback displayed by Coolify, rather than the callback for the separate Microsoft OAuth integration. Verify sign-in [#verify-sign-in] Test in a private browser window with an approved non-root user. Confirm that the expected account and team open, new account creation follows your policy, and Coolify requests a 2FA code when enabled. Linked identities appear on **Profile**; provider-managed email addresses cannot be edited there. If login fails, read the reason on the login page and check the issuer, callback, scopes, and email-verification claims. Keep an administrator recovery sign-in available while testing. # Overview (/docs/core/security/authentication/sso/overview) SSO overview [#sso-overview] Single sign-on (SSO) lets an organization use its identity provider as the sign-in authority for a self-hosted Coolify instance. Coolify provides named integrations for Authentik, Clerk, and Zitadel under **Settings > Authentication**. The Authentik, Clerk, and Zitadel integrations are available in Coolify v4.3.0 or above Coolify Cloud manages its own authentication. A root team administrator or owner can configure SSO providers for a self-hosted instance. Choose an SSO provider [#choose-an-sso-provider] | Provider | What you create | Guide | | :-------- | :------------------------------------------------------------- | :--------------------------------------------------------------------- | | Authentik | OAuth2/OpenID Connect provider and application | [Configure Authentik SSO](/core/security/authentication/sso/authentik) | | Clerk | OAuth application with profile and email scopes | [Configure Clerk SSO](/core/security/authentication/sso/clerk) | | Zitadel | Confidential web application using the authorization code flow | [Configure Zitadel SSO](/core/security/authentication/sso/zitadel) | Use [OpenID Connect](/core/security/authentication/sso/oidc) for other OIDC providers. How Coolify handles SSO accounts [#how-coolify-handles-sso-accounts] Coolify links users to a provider identity. Linking an existing account requires a verified email address, subject to the legacy passwordless-account exception described in [OAuth sign-in](/core/security/authentication/oauth/overview). Each account links to one provider. Restrict access to the Coolify application at your identity provider, then assign the required Coolify team roles. Provider groups and claims do not automatically assign roles. Providers can auto-join newly created users to the Root team as members. When Coolify 2FA is enabled, SSO sign-in also requires its challenge. Passwordless SSO users can enable 2FA on their profile. Configure account creation and password-registration policy under **Settings > Authentication**. Disabling new account creation does not prevent an already linked user from signing in. Removing provider access prevents the next provider sign-in, but does not remove active Coolify sessions, memberships, or API tokens. Complete those actions in Coolify during offboarding. Test before relying on SSO [#test-before-relying-on-sso] Use a private browser window and verify that: * an assigned user reaches the expected Coolify account and team * an unassigned provider user cannot authenticate * a new email address cannot create an account when registration is disabled * provider multi-factor authentication is enforced * at least one administrator retains a tested recovery sign-in path # Zitadel (/docs/core/security/authentication/sso/zitadel) Configure Zitadel SSO [#configure-zitadel-sso] Create a confidential web application in Zitadel so Coolify can use the authorization code flow and request the user's OpenID profile and email address. Zitadel SSO is available in Coolify v4.3.0 or above Replace these values while following the guide: * **Coolify callback:** `https://coolify.shadowarcanist.com/auth/zitadel/callback` * **Zitadel Base URL:** `https://id.shadowarcanist.com` Set up Zitadel SSO [#set-up-zitadel-sso] Create or select a Zitadel project [#create-or-select-a-zitadel-project] Open the Zitadel Console, select the organization that will own the integration, then create or open a project for Coolify. Use project roles and user grants when only selected organization members should access Coolify. See Zitadel's [OIDC login guide](https://zitadel.com/docs/guides/integrate/login/oidc/login-users) if the Console navigation differs. Add a web application [#add-a-web-application] In the project, select **New Application**, enter a name such as `Coolify`, and choose **Web** as the application type. Choose the authorization code flow with a client secret. For the token endpoint authentication method, select **POST** so the client ID and secret are sent with the token request. Register the callback URL [#register-the-callback-url] Add this redirect URI: ```txt https://coolify.shadowarcanist.com/auth/zitadel/callback ``` Keep development mode disabled for a production HTTPS domain, then finish creating the application. Coolify requests the `openid`, `profile`, and `email` scopes. Save the Zitadel credentials [#save-the-zitadel-credentials] Copy the generated **Client ID** and **Client Secret** and store the secret securely. Record the Zitadel instance origin as the **Base URL**, for example `https://id.shadowarcanist.com`. Do not append `/oauth/v2/authorize`, `/oauth/v2/token`, or `/oidc/v1/userinfo`. Configure Zitadel in Coolify [#configure-zitadel-in-coolify] Open **Settings > Authentication** and find **Zitadel**. | Coolify field | Zitadel value | | :---------------- | :--------------------------------------------------------- | | **Client ID** | Zitadel web application client ID | | **Client Secret** | Zitadel web application client secret | | **Redirect URI** | `https://coolify.shadowarcanist.com/auth/zitadel/callback` | | **Base URL** | Zitadel instance origin | Select **Save**, then turn on **Enabled** for Zitadel. Coolify may allow the provider card to be enabled before **Base URL** is filled. Zitadel sign-in cannot work without it because Coolify builds the authorization, token, and user information endpoints from this value. Verify Zitadel sign-in [#verify-zitadel-sign-in] Open the Coolify login page in a private browser window and select **Login with Zitadel**. Complete authentication, then confirm that Coolify opens the account matching the Zitadel email address. Test a user without the required project grant or provider access policy and confirm that Zitadel blocks access. Troubleshooting [#troubleshooting] Open the web application and confirm that its redirect URI exactly matches the public Coolify domain and `/auth/zitadel/callback` path. Confirm that the web application uses a client secret and the **POST** token endpoint authentication method. Then verify that the client secret in Coolify has not been rotated. Confirm that **Base URL** is the Zitadel instance origin and is reachable from the Coolify server. Do not enter a console page or OAuth endpoint path. # API Tokens (/docs/core/security/credentials/api-tokens) API tokens [#api-tokens] API tokens authenticate integrations, scripts, deploy webhooks, and MCP clients to Coolify. Each token belongs to the user who creates it, is bound to the active team, and carries selected permissions. A token grants access without an interactive sign-in or 2FA challenge. Store it in a secret manager, never commit it to a repository, and revoke it immediately if it is exposed. Before you create a token [#before-you-create-a-token] Choose the team and API controls first: * Switch to the team that owns the resources the integration must access. A token cannot access another team's resources. * On self-hosted Coolify, open **Settings > Advanced** and set **API access** to **Enabled**. * When callers use predictable source addresses, set **Allowed API IPs** to the required IP addresses or CIDR ranges. * Decide the smallest permission set and shortest practical expiration period. Coolify Cloud keeps API access available, so Cloud users do not enable the instance-wide **API access** setting. *** Create a token [#create-a-token] Open API Tokens [#open-api-tokens] Open **Keys & Tokens** in the main sidebar, then select **API Tokens**. Describe the token [#describe-the-token] Enter a **Description** that identifies the caller and purpose, such as `production-status-monitor` or `docs-deploy-workflow`. The description must contain between 3 and 255 characters. Choose an expiration [#choose-an-expiration] Use **Expires in** to select **7 days**, **30 days**, **60 days**, **90 days**, **1 year**, or **Never**. Prefer an expiration date for automation that can be rotated. Use **Never** only when the integration cannot be rotated safely on a schedule. Select permissions [#select-permissions] Open **Permissions** and select only the permissions required by the integration. Review [Token permissions](#token-permissions) before using `write`, `read:sensitive`, or `root`. Create and copy the token [#create-and-copy-the-token] Select **Create token**, then copy the generated token immediately. Coolify shows the complete token value only once. Store it in the caller's secret manager before leaving the page. If the value is lost, revoke the issued token and create another one. *** Token permissions [#token-permissions] | Permission | Use it for | Important behavior | | :--------------- | :-------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `read` | List and inspect resources. | Sensitive response values remain redacted. | | `read:sensitive` | Read secrets, logs, passwords, private keys, environment values, and Compose content returned by supported endpoints. | Coolify also adds `read` when this permission is selected. | | `write` | Create, update, and delete resources through write endpoints. | The token owner must remain an administrator or owner of the token's team when the request runs. | | `deploy` | Trigger deployments, restarts, stops, cancellations, and deploy webhooks. | Selecting `deploy` creates a deploy-only token in the dashboard. | | `root` | Bypass the `read`, `write`, and `deploy` permission checks on API endpoints. | Instance-wide **API access** and IP allowlist controls still apply. Only team administrators and owners can create this token. Selecting it removes the other permissions because they are unnecessary. | Use `read` for inventory and monitoring, `deploy` for a deployment-only workflow, and `write` only when the caller must change configuration. Add `read:sensitive` only when redacted values are insufficient. A `root` token still belongs to one team and its owner must remain a member of that team. It does not provide cross-team access. *** Make a test request [#make-a-test-request] Send the complete token as a Bearer credential: ```sh export COOLIFY_URL="https://coolify.shadowarcanist.com" export COOLIFY_TOKEN="" curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ "$COOLIFY_URL/api/v1/teams/current" ``` A successful request returns the team bound to the token. Do not paste a real token directly into shell history; load it from the caller's secret store in production. Read [Making Requests](/api/making-requests) for request examples and [API Permissions](/api/permissions) for token scope and role restrictions. [Rate Limits](/api/rate-limits) documents response headers and retry behavior, while [API Errors](/api/errors) covers status codes. For deployment-only automation, follow [Deploy Webhooks](/core/automation/deploy-webhooks). *** Team and role scope [#team-and-role-scope] Coolify records the active team when the token is created. Switching teams later does not change an issued token. * Create a separate token for each team an integration must access. * Removing the token owner from the team makes the token invalid. * A `write` or `root` request fails if the token owner no longer has the administrator or owner role. * Changing a user's password revokes that user's API tokens. * Removing a member, downgrading a member's role through Coolify, or deleting a team revokes affected team tokens. The **Issued Tokens** list belongs to the signed-in user. A user can revoke their own token but cannot copy its secret value again. *** Rotate or revoke a token [#rotate-or-revoke-a-token] Rotate a token before it expires or whenever its storage or caller changes: 1. Create a replacement with the same team and only the permissions still required. 2. Copy the replacement into the integration's secret store. 3. Make a test request with the replacement. 4. Return to **Keys & Tokens > API Tokens** and select **Revoke token** for the previous token. 5. Confirm that the integration continues working and the previous token now returns `401 Unauthenticated`. An expired token is rejected automatically. Coolify checks hourly for tokens expiring within 24 hours and sends the team's enabled **API token expiring** notifications. *** Troubleshooting [#troubleshooting] Confirm that the complete token appears after `Bearer`, has not expired or been revoked, and still belongs to a user who is a member of the token's team. A password change, team removal, or team deletion can revoke or invalidate the token. On self-hosted Coolify, confirm that **API access** is enabled and the caller's IP matches **Allowed API IPs**. Then check the endpoint's required permission. For `write` or `root`, confirm that the token owner is still a team administrator or owner. Create or use a token with both `read` and `read:sensitive`, or use a `root` token only when full administrative access is required. The resource may belong to another team. Switch to that team in the dashboard and create a separate token; an issued token's team cannot be changed. Coolify displays the complete token only after creation. Revoke the token if its value was not saved, then create and store a replacement. # Cloud-Init Scripts (/docs/core/security/credentials/cloud-init-scripts) Cloud-init scripts [#cloud-init-scripts] A cloud-init script configures a new cloud server during its first startup. Coolify can send one as provider user data when creating a Hetzner, DigitalOcean, or Vultr server. Use a script to perform repeatable initialization such as creating files, installing packages, or applying operating-system settings before Coolify validates the server. A broken cloud-init script can leave a new server incomplete or unreachable. Test with a temporary server and avoid changing the SSH access Coolify requires. Only team administrators and owners can create, update, or delete cloud-init scripts. Scripts belong to the active team. Create a reusable script [#create-a-reusable-script] Open Cloud-Init Scripts [#open-cloud-init-scripts] Open **Keys & Tokens** in the Coolify sidebar, then select **Cloud-Init Scripts**. Add the script [#add-the-script] 1. Select **New script**. 2. Enter a descriptive **Script name**. 3. Enter the cloud-config YAML under **Script content**. 4. Select **Create script**. The name and script content are required. Coolify validates that the content is valid cloud-init YAML before saving it. For example: ```yaml #cloud-config package_update: true packages: - curl write_files: - path: /etc/motd content: | Managed by Coolify ``` Cloud-init features vary by Linux image and provider. Check the image's cloud-init support before relying on a module. *** Use a script while provisioning [#use-a-script-while-provisioning] 1. Open **Servers** and select **New server**. 2. Choose **Hetzner**, **DigitalOcean**, or **Vultr**. 3. Complete the provider's server settings. 4. Open the advanced options. 5. Select the saved cloud-init script. 6. Review the remaining options, then select **Buy & Create Server**. You can also enter a script directly in the provisioning form. Enable **Save this script for later use** if it should be added to the team's reusable scripts. The script is sent only when the provider creates the server. It does not run when you validate a server or add an existing server manually. Hostinger does not use cloud-init scripts. For a Hostinger VPS, select a Hostinger post-install script in the advanced options. Read [Provision Cloud Server](/core/infrastructure/servers/provision-cloud-server). Editing a saved script changes future provisioning requests that use it. It does not rerun cloud-init or modify servers that were already created. *** Edit or delete a script [#edit-or-delete-a-script] Open **Keys & Tokens > Cloud-Init Scripts**, then select the script's **Edit** icon. * Change **Script name** or **Script content**, then select **Save changes**. * Select **Delete**, enter the requested confirmation, then select **Delete script** to remove it permanently. Deleting a saved script does not affect servers that were already provisioned with it. *** Troubleshooting [#troubleshooting] If a new server is not configured as expected: 1. Check the provider console to confirm the server was created and is running. 2. Open the server console and inspect the cloud-init status: ```sh cloud-init status --long ``` 3. Review the cloud-init logs: ```sh sudo less /var/log/cloud-init.log sudo less /var/log/cloud-init-output.log ``` 4. Correct the saved script and provision a temporary server to test it again. Cloud-init normally runs during the machine's first boot. Changing the saved template does not repair an existing machine. # Cloud Tokens (/docs/core/security/credentials/cloud-tokens) Cloud tokens [#cloud-tokens] Coolify uses cloud tokens to connect to supported cloud providers. A cloud token belongs to the active Coolify team and can be used when creating or managing a server in that provider account. Only team administrators and owners can manage cloud tokens. Coolify encrypts the token value in its database and does not display the saved value again. Create a dedicated provider token for Coolify, grant only the access it needs, and store the original value in a secret manager. Revoke and replace the token immediately if it is exposed. Create a provider token [#create-a-provider-token] Choose the provider account where Coolify will create and manage servers. Most readers need only one of these procedures. Hetzner tokens belong to one project. Create the token in the project where Coolify should manage servers. Open the Hetzner project [#open-the-hetzner-project] Open the [Hetzner Cloud Console](https://console.hetzner.cloud/projects), then select the required project. Open API tokens [#open-api-tokens] Select **Security** in the project sidebar, open **API Tokens**, then select **Generate API Token**. Configure the token [#configure-the-token] Enter a description such as `coolify-shadowarcanist`, then select **Read & Write**. Coolify needs write access to create and delete servers, upload SSH keys, control server power, and optionally enable Hetzner backups. A **Read** token may pass the initial validation but cannot perform these actions. Generate and copy the token [#generate-and-copy-the-token] Select **Generate API Token**, copy the complete value, and store it securely. Hetzner does not show the token again after you close the dialog. Create a DigitalOcean personal access token for the team where Coolify should manage Droplets. Open personal access tokens [#open-personal-access-tokens] Open [Applications & API](https://cloud.digitalocean.com/account/api/tokens), find **Personal access tokens**, then select **Generate New Token**. Name the token and choose an expiration [#name-the-token-and-choose-an-expiration] Enter a name such as `coolify-shadowarcanist`. Choose an expiration period that gives you enough time to rotate the token before it expires. Select custom scopes [#select-custom-scopes] Choose **Custom Scopes**, then grant these scopes: * `account:read` * `regions:read` * `sizes:read` * `image:read` * `ssh_key:read` * `ssh_key:create` * `droplet:read` * `droplet:create` * `droplet:update` * `droplet:delete` These scopes let Coolify validate the account, list the options required by the server form, manage SSH keys, and create, inspect, start, or delete Droplets. **Full Access** also works but grants broader access than Coolify needs. Generate and copy the token [#generate-and-copy-the-token-1] Select **Generate Token**, copy the complete value, and store it securely. DigitalOcean shows the token secret only once. Create a Vultr API key for the account where Coolify should manage instances. Open Vultr API access [#open-vultr-api-access] Open the [Vultr API page](https://console.vultr.com/user/apiaccess/). Depending on the Vultr Console version, this page appears as **Vultr API** under **Orchestration** or as **API Access** under **Account**. Enable API access for the Vultr user if it is disabled. Check API access control [#check-api-access-control] If the Vultr account restricts API access by IP address, allow the public outbound IP address of the Coolify instance. The API requests come from Coolify, not from your browser or the server that Coolify will create. Create the API key [#create-the-api-key] Under **User Access Tokens**, enter a name such as `coolify-shadowarcanist`, choose an expiration option, and select **Add Key**. The Vultr user must be allowed to list plans, regions, operating systems, and SSH keys, and to create, inspect, start, and delete instances. Copy the API key [#copy-the-api-key] Copy the complete key and store it securely. Vultr does not let you recover the value after leaving the page. Create a Hostinger API token for the account where Coolify should buy and manage VPS servers. If you do not have a Hostinger account, you can [create one with the Coolify link](https://www.hostinger.com/vps/coolify-hosting?ref=coolify.io). Coolify shows the same link in the token form. Open the API page in hPanel [#open-the-api-page-in-hpanel] Log in to Hostinger and open the [API page in hPanel](https://hpanel.hostinger.com/profile/api). Create the token [#create-the-token] Create a new API token. Give it a name that identifies Coolify, such as `coolify-shadowarcanist`. Copy the token [#copy-the-token] Copy the complete token value. Store it in a secure location. Coolify uses this token to order VPS servers. Hostinger charges each order to the default payment method of the account. Keep the token secret. *** Add the token to Coolify [#add-the-token-to-coolify] Open Cloud Tokens [#open-cloud-tokens] Open **Keys & Tokens** in the Coolify sidebar, then select **Cloud Tokens**. Choose the provider [#choose-the-provider] Select **New token**, then choose the **Provider**: **Hetzner**, **DigitalOcean**, **Vultr**, or **Hostinger**. Enter the token details [#enter-the-token-details] Complete the form: * **Token name:** Enter a name that identifies the provider account or environment, such as `shadowarcanist-production`. * **Description:** Optionally record the project, team, account, or intended use. * **API token:** Paste the complete token or API key copied from the provider. Select **Validate and add**. Confirm the token was added [#confirm-the-token-was-added] After validation succeeds, Coolify closes the form and displays the new token on the **Cloud Provider Tokens** page. Coolify validates a Hetzner token by listing servers and validates DigitalOcean and Vultr tokens through their account endpoints. Coolify validates a Hostinger token with `GET https://developers.hostinger.com/api/vps/v1/virtual-machines`. A successful result confirms that the provider accepts the credential, but it does not prove that every permission required to create or manage a server is available. *** Manage a cloud token [#manage-a-cloud-token] Open **Keys & Tokens > Cloud Tokens**, then select the token's **Edit** icon. * Change **Name** or **Description**, then select **Save changes**. * Select **Validate** to check whether the provider still accepts the saved credential. * Select **Delete** to remove an unused token. The provider and creation date are read-only. Coolify does not show or replace the saved secret on this page. To rotate a credential, create a replacement at the provider, add it as a new cloud token, and move every dependent server to the replacement before revoking the previous credential. Coolify blocks deletion while one or more servers still use the token. Do not revoke the credential at the provider until those servers have been moved to another token or are no longer managed through that provider connection. *** Troubleshooting [#troubleshooting] Confirm that you selected the matching provider and pasted the complete token without surrounding spaces. Check that the credential has not expired or been revoked. For Hetzner, confirm that the project still exists. For DigitalOcean, confirm that the token includes `account:read`. For Vultr, confirm that API access is enabled and that Vultr's access-control list permits requests from the Coolify instance. Initial validation does not test every write operation. * For Hetzner, use a **Read & Write** token. * For DigitalOcean, compare the token's custom scopes with the list in the [DigitalOcean tab](#cloud-token-provider). * For Vultr, confirm that the Vultr user can manage instances and SSH keys and that API access control permits the Coolify instance. * For Hostinger, confirm that the account has a valid default payment method. If Coolify cannot list post-install scripts, the token does not have permission for them. Coolify shows the message from Hostinger. After correcting the provider permissions, return to the saved cloud token and select **Validate**. Check **Access Control** on the Vultr API page. If an IP allowlist is enabled, it must contain the public outbound IP address of the Coolify instance. Adding your browser's IP address or the address of the server you intend to create does not authorize requests sent by Coolify. Hetzner tokens are project-specific. Confirm that the token was created in the project containing the servers, networks, firewalls, and SSH keys you expect Coolify to use. Create and add a separate token when Coolify must work with another Hetzner project. The token is still assigned to one or more servers. Move those servers to another valid provider token or remove the provider relationship before trying to delete it again. Do not revoke the provider credential first. Coolify needs the working credential for provider-backed server actions until the dependency has been removed. # SSH Keys (/docs/core/security/credentials/ssh-keys) SSH keys [#ssh-keys] Coolify uses SSH private keys to connect to servers without passwords and to access private Git repositories through deploy keys. Keys belong to the active Coolify team and can be reused by resources in that team. Coolify must use SSH keys without an interactive prompt. Do not add a passphrase or a second-factor prompt to a key used by Coolify. How Coolify uses a key pair [#how-coolify-uses-a-key-pair] An SSH key pair has two parts: * Coolify stores and uses the **private key** when it starts an SSH connection. * You add the matching **public key** to the server account's `~/.ssh/authorized_keys` file or to the Git provider as a deploy key. The public key does not grant access without its matching private key. Never copy the private key to a managed server or Git repository. *** Create an SSH key [#create-an-ssh-key] Open **Keys & Tokens** in the main sidebar, select **Private Keys**, then open **New private key**. Select **Generate ED25519** for the default choice. Use **Generate RSA** only when the target system does not accept ED25519 keys. Coolify generates and saves the key immediately. Select its **Edit** icon to review the public key or change the name to identify its purpose, such as `production-servers`. Select **Save changes** after editing. Select **Add manually**, then paste the complete private key into **Private key**, including its `BEGIN` and `END` lines. Coolify validates the private key and derives the matching **Public Key**. Enter a recognizable name and optional description, then select **Continue**. Do not import a passphrase-protected key. Coolify cannot answer an interactive passphrase prompt during deployments or server checks. Coolify rejects invalid private keys and duplicate keys in the active team. *** Authorize the public key on a server [#authorize-the-public-key-on-a-server] Add the public key to the account Coolify will use for SSH. The following commands use `root`; replace it with the configured non-root account when needed. Copy the public key from Coolify [#copy-the-public-key-from-coolify] Open **Keys & Tokens > Private Keys**, select its **Edit** icon, and copy **Public key**. Connect to the server [#connect-to-the-server] From a trusted terminal, connect with an existing administrative method: ```sh ssh root@ ``` If SSH uses another port, add `-p `. Add the key to the SSH account [#add-the-key-to-the-ssh-account] On the server, run: ```sh mkdir -p ~/.ssh chmod 700 ~/.ssh nano ~/.ssh/authorized_keys ``` Paste the complete public key on its own line. Save the file, then run: ```sh chmod 600 ~/.ssh/authorized_keys ``` Do not remove the key used by your current SSH session until the new Coolify connection has been verified. For server requirements and firewall rules, follow [OpenSSH](/core/infrastructure/servers/openssh). *** Select and verify a server key [#select-and-verify-a-server-key] For a new server, select the key in the **Private Key** field while following [Add Server](/core/infrastructure/servers/add-server). For a connected server: 1. Open **Servers** and select the server. 2. Open **Private Key** in the server settings. 3. Find the authorized key and select **Use this key**. 4. Select **Check connection**. The change is verified when Coolify reports that the server is reachable. If the check fails, restore the previously working key selection and confirm that the new public key is in the configured SSH user's `~/.ssh/authorized_keys` file. *** Use a key for a private Git repository [#use-a-key-for-a-private-git-repository] When creating an application from a private repository through a deploy key, select or create a private key in Coolify and add its public key to the repository's deploy-key settings. Repository access and server access are separate. Adding a public key to a Git provider does not authorize that key on a server, and adding it to `~/.ssh/authorized_keys` does not grant repository access. Use a dedicated key when you want to rotate or revoke repository access without affecting server connections. *** Rotate an SSH key [#rotate-an-ssh-key] Create a new key instead of replacing a shared private key in place. This keeps the current connection available during the transition. 1. Create the replacement key under **Keys & Tokens > Private Keys**. 2. Add its public key to every target server account or Git repository that needs it. 3. For each connected server, select the replacement under **Server > Private Key** and run **Check connection**. 4. Update applications or Git integrations that use the previous key and verify repository access with a deployment. 5. Remove the previous public key from each server or provider only after every dependent resource uses the replacement. 6. Delete the previous key from Coolify after it is marked unused. If several resources share one key, rotate them one at a time. Replacing the private key value on the existing key changes the credential for every linked server and Git integration at once. *** Delete unused keys [#delete-unused-keys] The **Private Keys** list marks a key **Unused** when no server, application, GitHub App, or GitLab App references it. * Open an unused key and select **Delete** to remove it. * Select **Delete unused keys** on the list page to remove all keys currently marked unused for the active team. Coolify prevents its safe-delete operation from removing a key that is still referenced. Remove or replace every dependency before deleting the key. *** Security and storage [#security-and-storage] Only team administrators and owners can create, change, or delete private keys. Give each key a purpose-specific name and avoid sharing one key across unrelated environments. Coolify encrypts the private-key value stored in its database. On a self-hosted instance, Coolify also writes the key to its SSH key storage with restrictive file permissions so the SSH client can use it. Protect the Coolify database, `/data/coolify/source/.env`, `/data/coolify/ssh/keys/`, and instance backups as privileged recovery material. For a self-hosted instance migration, follow [Restore Coolify](/core/backup-and-recovery/instance-restore) so the database, encryption key, and SSH key files remain consistent. # Security Model (/docs/core/security-model) Security model [#security-model] Coolify is a privileged control plane: the administrative layer that stores credentials and connects to servers over SSH so it can deploy and manage Docker resources on your infrastructure. Coolify protects access to its own controls and authenticates supported API and webhook requests. You remain responsible for the security of every server, application, database, network, and backup you control. Treat administrative access to Coolify as privileged infrastructure access. Protect Coolify accounts, API tokens, instance data, and SSH keys with the same care as direct server access. Coolify Cloud changes who operates the Coolify instance. It does not transfer responsibility for the connected servers, applications, databases, and services you provide. *** Security boundary [#security-boundary] Coolify supplies security controls for the management layer. Those controls do not replace host hardening, application security, or an incident response plan. For Coolify Cloud, the Coolify team operates the Coolify control plane. You still secure your account, API tokens, connected servers, deployed resources, and workload data. *** Security controls in Coolify [#security-controls-in-coolify] The built-in controls cover four parts of control-plane security. On self-hosted instances, **Settings > Advanced** also lets you disable API access or restrict it to specific IP addresses and CIDR ranges. Create and revoke tokens under **Keys & Tokens > API Tokens**. Read [API tokens](/core/security/credentials/api-tokens) for the available token permissions and request format. These controls reduce risk in the paths Coolify manages. They do not replace security reviews, dependency updates, or runtime protections inside your applications. *** Protect the Coolify control plane [#protect-the-coolify-control-plane] The control plane holds the access needed to coordinate deployments. A weakness at this layer can affect every connected server that trusts it. Coolify stores SSH private keys and uses them to run commands on connected servers. An attacker who gains sufficient administrative access to the Coolify instance can use the same management paths. Restrict administrative access. If you self-host Coolify, install supported updates and protect the instance database, `/data/coolify/source/.env`, backups, and SSH key storage. Secure account access [#secure-account-access] * Keep **Registration Allowed** disabled unless you intentionally allow people to create accounts. * Enable two-factor authentication for every account with elevated access and store recovery codes safely. * Give team members the lowest role they need, then remove access when it is no longer required. * Configure OAuth or SSO with trusted identity providers and limit who the provider allows to sign in. Limit API and integration access [#limit-api-and-integration-access] * Enable **API Access** only when an integration needs it. * Restrict **Allowed IPs for API Access** on a self-hosted instance whenever the callers have predictable source addresses. * Give each integration its own token with only the permissions it needs and an appropriate expiration date. * Revoke unused or exposed tokens, then replace them in every integration that used them. Protect encrypted data and recovery material [#protect-encrypted-data-and-recovery-material] Coolify encrypts supported credentials before storing them in its database. On a self-hosted instance, the `APP_KEY` in `/data/coolify/source/.env` is the key used for that encryption. A database backup does not include the environment file. Save the `APP_KEY` separately in a password manager or another secure location outside the Coolify server, and keep it with the recovery material for that instance. Without the matching key, Coolify cannot read encrypted credentials from a restored database. Follow [Back up Coolify](/core/backup-and-recovery/instance-backup) for the exact backup and `APP_KEY` procedure. Keep the control plane recoverable [#keep-the-control-plane-recoverable] For self-hosted Coolify, install supported updates, keep instance backups outside the server, and test the [instance restore procedure](/core/backup-and-recovery/instance-restore). Coolify Cloud handles control-plane updates and backups, but you still need a recovery plan for the workloads on your servers. *** Protect connected servers and workloads [#protect-connected-servers-and-workloads] Coolify automates work on connected servers; it does not become the security boundary for those servers or the resources running on them. Harden each server [#harden-each-server] * Keep the operating system, Docker Engine, and the Coolify proxy running on the server updated. * Use a dedicated SSH key for Coolify and restrict who can use the corresponding server account. * Restrict inbound SSH in the provider firewall or security group and in the host firewall when your network setup allows it. * Open only the ports required by the Coolify proxy and the resources you intentionally expose. * Monitor host availability, disk usage, authentication activity, and unexpected container changes. Coolify's automated SSH connection must work without an interactive prompt. Follow the [OpenSSH guide](/core/infrastructure/servers/openssh) when configuring the server account and key. Control network exposure [#control-network-exposure] Application traffic goes to the proxy on the server running the resource. Secure the firewall, DNS, and any external load balancer, content delivery network, or web application firewall in front of that server. Keep databases and internal services on Docker networks unless they require public access. Publishing a host port creates a direct network path that does not depend on domain-based proxy routing, so expose one only when a trusted client needs that connection. Read [Networking in Coolify](/core/networking-in-coolify) for the traffic and Docker network model. Secure applications and data [#secure-applications-and-data] * Review the source repository, container image, Dockerfile, and Docker Compose configuration before deployment. * Keep application dependencies and base images updated. * Implement authentication, authorization, validation, rate limiting, and logging inside the application where required. * Back up application and database data independently from the Coolify control-plane backup, then test recovery. Docker separates workloads into containers and networks, but that isolation does not replace host hardening or application-level security. *** Security baseline for production [#security-baseline-for-production] Review this baseline before placing production workloads on a connected server: 1. Serve the Coolify dashboard over HTTPS and restrict who can reach it when possible. 2. Disable public registration unless it is required, enable 2FA, and review team roles. 3. Keep API access disabled unless needed; otherwise, restrict source IPs and issue separate least-privilege tokens. 4. Use a dedicated SSH key, harden SSH, patch the server, and allow only required firewall ports. 5. Review deployment sources, environment values, volume mounts, and every publicly exposed port. 6. Back up workload data. For self-hosted Coolify, also back up the instance database and save its `APP_KEY` separately. 7. Configure monitoring and alerts, document how to revoke access, and test restore procedures before an incident. Security is an ongoing operational responsibility. Repeat this review when you add a server, grant access, expose a new service, or change an integration. *** Where to go next [#where-to-go-next] Use the detailed guides to apply the security model to your Coolify instance and connected servers. Configuration validation and secrets [#configuration-validation-and-secrets] Coolify validates Git refs, Git-based Compose definitions, container names, network names, image references, storage paths, and proxy configurations before using them. Correct validation errors rather than trying to bypass them with shell syntax. Queued remote commands are encrypted and removed after the task ends. Commands and resolved secrets are excluded or redacted from failure logs and notifications. Team ownership controls which credentials and resources can be selected, including when teams change in another browser tab. # Self Hosted vs Coolify Cloud (/docs/core/selfhosted-cloud-comparison) Self Hosted vs Coolify Cloud [#self-hosted-vs-coolify-cloud] You can use Coolify in two ways: run the Coolify instance yourself, or use the instance hosted and maintained by the Coolify team. The Coolify instance is the control plane that provides the dashboard and coordinates deployments. Your applications, databases, and services still run on servers you connect in either model. Choose **self-hosted Coolify** when you want to operate the Coolify instance and control its updates, backups, availability, and recovery. Choose **Coolify Cloud** when you want the Coolify team to operate that instance for you. You still provide and secure the servers where your workloads run. *** What stays the same [#what-stays-the-same] The option you choose changes who operates the Coolify instance. It does not change the resource workflow or move your workloads onto Coolify-managed servers. *** Compare self-hosted Coolify and Coolify Cloud [#compare-self-hosted-coolify-and-coolify-cloud] The main differences are control-plane operations, dashboard access, notification delivery, and cost. | Area | Self-hosted Coolify | Coolify Cloud | | :-------------------------- | :-------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | | Coolify instance | Runs on infrastructure you control. | Runs on infrastructure managed by the Coolify team. | | Setup and maintenance | You install, monitor, maintain, and restore the instance from backups. | The Coolify team sets up, monitors, maintains, and restores the instance from backups. | | Coolify updates | You choose when to update the instance. | The Coolify team manages control-plane updates. | | Coolify instance backups | You configure, store, and test instance backups. | The Coolify team manages backups of the Cloud instance. | | Dashboard access | You configure the domain for your instance. | You use [app.coolify.io](https://app.coolify.io). | | Email alerts | You configure SMTP or Resend. | Email delivery for Coolify notifications is preconfigured by the Coolify team. | | Other notification channels | You configure each channel, such as Discord or Telegram. | You configure each channel, such as Discord or Telegram. | | Features | All current and upcoming Coolify features, free forever. | All current and upcoming Coolify features are included in the subscription. | | Codebase | Open source. | Open source. | | Teams | Unlimited. | Unlimited; each team requires a separate subscription. | | Team members | Unlimited. | Unlimited. | | Connected servers | Unlimited. | Unlimited. Each server after the first two increases the subscription cost. | | Workload servers and data | Applications, databases, services, and persistent data run on your servers. | Applications, databases, services, and persistent data run on your servers. | | Platform cost | No Coolify license fee. You pay for your infrastructure. | Paid managed service. You also pay for your workload servers. | *** Compare the cost [#compare-the-cost] Self-hosted Coolify has no license fee. You still pay for the infrastructure that runs the Coolify instance and your workloads. Coolify Cloud starts at $5 per month and includes up to two connected servers. Each additional connected server adds $3 per month. Cloud pricing can change. Check the [current Coolify Cloud pricing](https://coolify.io/pricing) before subscribing. *** Understand the responsibility boundary [#understand-the-responsibility-boundary] Coolify Cloud manages the control plane, not the servers and workloads you connect to it. If you self-host, you operate both sides of this boundary. Read the [Security model](/core/security-model) before placing production workloads on a connected server. *** Choose your path [#choose-your-path] Choose self-hosted Coolify if control of the instance matters more than avoiding control-plane maintenance. Choose Coolify Cloud if you want a managed instance and the subscription fits your operating model. # Audit Log (/docs/core/team/audit-log) Team audit log [#team-audit-log] Team administrators and owners can open **Team > Audit Log** to review activity from the UI, API, MCP, and webhooks. Search and filter events to find an actor, resource, or action. Events cover resource changes, deployments, backups, proxy controls, membership, API tokens, integrations, account security, and server, application, service, and instance settings. Each entry records actor, resource, and request context where available. Review changes [#review-changes] Select **View changes** to compare previous and new values for changed fields. Changes are encrypted at rest. Secrets, commands, and configuration content are excluded, and sensitive request metadata is redacted. The audit log is an activity record rather than a configuration backup. Events are pruned after 90 days. Export events through the API if your team needs a separate archive beyond that window. API access [#api-access] Use `GET /audit-events` with a token owned by a team administrator or owner. Actor email, token context, metadata, changes, IP address, and user agent are returned only with `read:sensitive` or `root`. See the [API reference](/api) for filters and pagination and [API permissions](/api/permissions) for token abilities. # Add a Member (/docs/core/team/members/add-a-member) Add a member [#add-a-member] Invite a person to the active team and choose the role they will receive when they accept. Before you invite someone [#before-you-invite-someone] You must be an **Owner** or **Admin** in the active team. Choose the lowest role the person needs: * **Member** for read-only access to team resources * **Admin** to manage team settings, invitations, and members at the Admin or Member level * **Owner** for full control over roles, including other Owners Only an Owner can invite another Owner. Read [Roles & Permissions](/core/team/roles-and-permissions) for the role comparison. Sending the invitation from Coolify requires transactional email to be enabled. If email is not configured, you can still generate a link and send it to the person yourself. *** Invite the member [#invite-the-member] Open the active team's Members page [#open-the-active-teams-members-page] 1. Confirm that the intended team is active. 2. Select **Team** in the Coolify sidebar. 3. Select **Members**. Enter the email address [#enter-the-email-address] Under **Invite a member**, enter the person's email address. Coolify stores invitation email addresses in lowercase and uses the address to identify who may accept the invitation. If the address already belongs to this team, Coolify reports that the person is already a member. If Coolify reports an existing pending invitation for the address, that invitation must be accepted, revoked from the team that created it, or allowed to expire before you create another one. Choose a role [#choose-a-role] Select **Member**, **Admin**, or **Owner** from **Role**. Admins can invite Members and Admins. Owners can invite all three roles. *** Send or copy the invitation [#send-or-copy-the-invitation] Send the invitation by email [#send-the-invitation-by-email] Select **Send email**. Coolify sends the invitation to the entered address using the instance's transactional email configuration. Share an invitation link [#share-an-invitation-link] Select **Generate link** to add the invitation under **Pending Invitations**. On an HTTPS dashboard, select **Copy Invitation Link** and send it directly to that person. On an HTTP dashboard, copy the displayed link manually. The invitation is tied to the entered email address and grants the selected role. Treat the link as sensitive until it is accepted or revoked. When the email address does not yet have a Coolify account, Coolify prepares an account for that address as part of the invitation flow. The invited person uses the link to sign in, join the team, and set their own password when prompted. An existing Coolify user must sign in with the invited email address, then accept on the invitation page. Signing in alone no longer accepts an invitation automatically. Pending invitations also appear on the dashboard. *** Verify the invitation [#verify-the-invitation] Before acceptance, confirm that **Pending Invitations** shows the correct email address, delivery method, and role. After the person accepts, confirm that: 1. the invitation no longer appears under **Pending Invitations** 2. the person appears in the member list 3. the **Role** column shows the role you selected *** If the invitation is not accepted [#if-the-invitation-is-not-accepted] Invitation links are valid for three days. After a link expires, create a new invitation. To invalidate a link before it is accepted, select **Revoke** beside the pending invitation. The revoked link can no longer be used to join the team. # Delete a User (/docs/core/team/members/delete-user) Delete a user [#delete-a-user] Deleting a user removes the user account itself from a self-hosted Coolify instance. This is different from [removing a member](/core/team/members/remove-a-member), which only ends a person's membership in the active team while their account stays available. If Coolify still has a working connection to the user's servers, deleting the user also deletes all resources on those servers, not only the records in Coolify's database. Before you delete a user [#before-you-delete-a-user] * You must belong to the `root` team. Only `root` team members can delete users from the UI. * The `root` team and the `root` user cannot be deleted. * Confirm which teams the user belongs to and what resources those teams own. Delete the user [#delete-the-user] 1. Go to the **Team** page. 2. Switch to the **Admin View** tab. This lists every user registered in Coolify. 3. Select **Delete** next to the user you want to remove. What happens during deletion [#what-happens-during-deletion] Coolify iterates over every team the user belongs to and applies these rules per team: The user is alone in the team [#the-user-is-alone-in-the-team] The team and all of its resources are deleted from both the servers and Coolify's database. The user is not alone in the team [#the-user-is-not-alone-in-the-team] 1. The user is the owner or admin, no other owner or admin exists, and the team **has** other members: * Ownership transfers to the first team member who is not the owner or admin. * The user is removed from the team. No resources are deleted. 2. The user is the owner or admin, no other owner or admin exists, and the team has **no** other members: * The team and all of its resources are deleted from both the servers and Coolify's database. 3. The user is not the owner or admin of the team: * The user is removed from the team. No resources are deleted. Delete your own account [#delete-your-own-account] Use [Profile and account deletion](/core/security/authentication/profile) to delete your own account. Root team administrators cannot delete the root user, root team owners, or their own account from the team admin view. # Manage Members (/docs/core/team/members/manage-members) Manage members [#manage-members] Use the active team's **Members** page to review access, change another member's role, and revoke invitations that should no longer be accepted. Review the member list [#review-the-member-list] 1. Confirm that the intended team is active. 2. Select **Team** in the Coolify sidebar. 3. Select **Members**. The table shows **Name**, **Email**, **Role**, and the actions your role permits. Owners and administrators also see **2FA** status. Use search and the role or 2FA filters to narrow the list. Review the list regularly and remove access that is no longer needed. A person's role applies only to this team; the same account can have a different role in another team. *** Change a member's role [#change-a-members-role] Owners and Admins can change another member's role. The available actions depend on your role and the other person's current role. | Your role | Role changes available | | :--------- | :-------------------------------------------------------------------------------- | | **Owner** | Change another Owner, Admin, or Member to any of the other roles. | | **Admin** | Change an Admin to Member, or change a Member to Admin. Owners cannot be changed. | | **Member** | No role-change actions. | Find the member, open **Manage**, then select **Make owner**, **Make admin**, or **Make member**. When you change a member's role, Coolify revokes that user's API tokens for this team. The person must create replacement tokens if they still need API access. The member list reloads after the change. Confirm that the **Role** column shows the new role. You cannot change your own role from the member list. Ask another person with sufficient access to make the change. *** Review pending invitations [#review-pending-invitations] Owners and Admins can review **Pending Invitations** below the invitation form. Each row shows: * the invited email address * whether the invitation was created for email delivery or as a link * the role the person will receive * the invitation link Invitation links are valid for three days. A valid invitation for an email address must be accepted, revoked, or allowed to expire before another invitation can be created for that address. *** Revoke an invitation [#revoke-an-invitation] Select **Revoke** beside an invitation that should no longer grant access. Coolify removes the pending invitation immediately. Confirm that its row disappears from **Pending Invitations**. If the person still needs access, create a new invitation with the correct role. # Overview (/docs/core/team/members/overview) Members overview [#members-overview] A Coolify team groups the people, resources, and settings they work with. Each person can belong to more than one team and can have a different role in each team. Select the team you want to work with before changing its members. Owners and administrators can invite people, change other members' roles, revoke pending invitations, and remove members. *** How team membership works [#how-team-membership-works] Coolify uses the active team as the boundary for dashboard work. Projects, servers, shared variables, credentials, notification settings, and other team-owned resources shown in the dashboard belong to that team. When you switch teams, Coolify changes the resources and settings available in the dashboard. Your role is also evaluated for the newly active team. Removing someone from a team removes their access to that team. It does not delete their Coolify account, their membership in other teams, or resources owned by the team. Read [Roles & Permissions](/core/team/roles-and-permissions) before granting administrative access. *** What the Members page shows [#what-the-members-page-shows] Open **Team** in the Coolify sidebar, then select **Members**. The member list shows each person's name, email address, role in the active team, and the actions available to you. Owners and administrators also see the invitation form and any pending invitations. Coolify marks your own row with **You**. You cannot change your own role or remove yourself from this page. *** Choose the next task [#choose-the-next-task] # Remove a Member (/docs/core/team/members/remove-a-member) Remove a member [#remove-a-member] Removing a member ends their membership in the active team. Their Coolify account and any other team memberships remain available. Before you remove a member [#before-you-remove-a-member] You must be an **Owner** or **Admin** in the active team. The role hierarchy limits who you can remove: * Owners can remove any other team member, including another Owner. * Admins can remove Admins and Members, but not Owners. * You cannot remove yourself from the **Members** page. Confirm that the person no longer needs access to the team's projects, servers, credentials, shared variables, or other resources. *** Remove the member [#remove-the-member] The **Manage > Remove member** action does not open a confirmation step. Confirm the person's name, email address, and role before selecting it. Open the member list [#open-the-member-list] 1. Confirm that the intended team is active. 2. Select **Team** in the Coolify sidebar. 3. Select **Members**. Select Remove [#select-remove] Find the person by name and email address, open **Manage** in their row, then select **Remove member**. Coolify removes the team membership and revokes API tokens that belong to that user and team. Confirm the removal [#confirm-the-removal] Verify that the person's row no longer appears in the member list. The removed person can no longer work in that team. If they are signed in, Coolify clears the unavailable active-team selection when their next request checks membership. *** What removal changes [#what-removal-changes] Removing a member does not: * delete their Coolify account * remove them from other teams * delete projects, servers, applications, databases, services, or settings owned by this team * transfer team resources to another person To restore access later, [invite the person again](/core/team/members/add-a-member) and select the role they should receive. # Roles & Permissions (/docs/core/team/roles-and-permissions) Roles and permissions [#roles-and-permissions] Coolify assigns each person a role for each team they join. A person can be an Owner in one team and a Member or Admin in another. In Coolify v4.x, **Member** is the read-only role for most team resources. **Admin** and **Owner** can operate resources and manage team settings. Owner adds control over who else can become or remain an Owner. Role comparison [#role-comparison] Team and members [#team-and-members] | Permission | Owner | Admin | Member | | :----------------------------------- | :---: | :---: | :----: | | View the team and member list | Yes | Yes | Yes | | Change the team name and description | Yes | Yes | No | | Invite Members or Admins | Yes | Yes | No | | Invite Owners | Yes | No | No | | Change or remove Members or Admins | Yes | Yes | No | | Change or remove Owners | Yes | No | No | | Delete an eligible team | Yes | Yes | No | The member-management controls apply to other people. Coolify does not show actions for changing your own role or removing yourself on the **Members** page. Projects and resources [#projects-and-resources] | Permission | Owner | Admin | Member | | :----------------------------------------------------------------------------------------------- | :---: | :---: | :----: | | View projects, environments, applications, databases, and services | Yes | Yes | Yes | | Create, update, or delete projects and environments | Yes | Yes | No | | Create, update, or delete applications, databases, and services | Yes | Yes | No | | Deploy applications and services | Yes | Yes | No | | Start, stop, restart, or otherwise operate resources | Yes | Yes | No | | Manage deployments, environment variables, storage, scheduled tasks, tags, webhooks, and backups | Yes | Yes | No | | Open a resource terminal | Yes | Yes | No | Member access lets a person inspect team resources without changing or deploying them. A page may still be visible to a Member while its editing and operational controls are unavailable. Servers and destinations [#servers-and-destinations] | Permission | Owner | Admin | Member | | :-------------------------------------------------- | :---: | :---: | :----: | | View team servers and destinations | Yes | Yes | Yes | | Add, update, or remove servers and destinations | Yes | Yes | No | | Manage the proxy and server certificate authorities | Yes | Yes | No | | View or manage server security and Sentinel | Yes | Yes | No | | Use the Web Terminal | Yes | Yes | No | Terminal commands run on your infrastructure. Coolify therefore restricts both the global [Web Terminal](/core/infrastructure/servers/web-terminal) and resource terminals to Owners and Admins. Team configuration and credentials [#team-configuration-and-credentials] | Permission | Owner | Admin | Member | | :------------------------------------------------------------------ | :---: | :---: | :----: | | View shared-variable entries | Yes | Yes | Yes | | Create, update, or delete shared variables | Yes | Yes | No | | View notification settings | Yes | Yes | Yes | | Configure notifications or send test notifications | Yes | Yes | No | | View team S3 storage, Git sources, and private-key entries | Yes | Yes | Yes | | Create, update, or delete S3 storage, Git sources, and private keys | Yes | Yes | No | | View or manage cloud-init scripts and cloud provider tokens | Yes | Yes | No | Viewing a credential entry does not mean Coolify reveals every stored secret. Secret fields can remain concealed even when the surrounding resource is visible. API tokens [#api-tokens] When API access is enabled for the instance, each role can create and revoke its own tokens. | Permission | Owner | Admin | Member | | :---------------------------------------------------------------------------------- | :---: | :---: | :----: | | Create and revoke personal API tokens | Yes | Yes | Yes | | Create a token with `read` permission | Yes | Yes | Yes | | Grant `read:sensitive`, `write`, `write:sensitive`, `deploy`, or `root` permissions | Yes | Yes | No | API tokens belong to the person who creates them and are scoped to the active team. A Member can create a read-only token, but cannot grant it sensitive, write, deployment, or root permissions. See [API permissions](/api/permissions) for the available token permissions. *** Owner-only controls [#owner-only-controls] Owner is the highest team role. Only an Owner can: * invite another Owner * promote an Admin or Member to Owner * change another Owner to Admin or Member * remove another Owner from the team More than one person can have the Owner role. Keep at least one trusted Owner available so the team does not depend on a single account. *** Instance administration [#instance-administration] Team roles and instance administration are separate. On a self-hosted Coolify instance, only an Owner or Admin of the default team can view or update instance-wide settings and access system resources. An Owner or Admin role in another team does not make a person an instance administrator. That role applies to that team's resources. *** Choose a role [#choose-a-role] * Choose **Member** when the person only needs to review team resources and their current state. * Choose **Admin** when the person should deploy and operate resources, manage servers and credentials, change team settings, and manage Members or Admins. * Choose **Owner** only when the person must also grant, change, or remove Owner access. Use the lowest role that provides the access the person needs. You can update another person's role from **Teams > Members**. Follow [Manage Members](/core/team/members/manage-members) for the role-change rules and verification steps. Team administrators and owners can review [Audit Log](/core/team/audit-log) events. Members cannot read the team audit log. Sensitive content in the dashboard [#sensitive-content-in-the-dashboard] Users without permission to update a resource cannot view container logs, scheduled-task commands/output, Compose or file-mount content, hardcoded Compose environment values, proxy configuration, server shared values, or protected credentials such as basic-auth passwords, log-drain keys, and the Sentinel token. Sensitive API responses have an additional token-permission check; see [API permissions](/api/permissions). The team Danger Zone is visible only to its owner. Impersonation and the team admin view require an instance administrator. Credentials such as private keys, Git sources, S3 storage, and integration tokens must belong to the team that owns the resource. # Shared Variables (/docs/core/team/shared-variables) Shared variables [#shared-variables] Shared variables let you define a value once and reference it from more than one resource. Coolify supports team, project, environment, and server scopes. Defining a shared variable does not automatically add it to every application, database, or service. Add a reference where the resource needs the value, then redeploy or restart the resource as required for its configuration change. How shared variables work [#how-shared-variables-work] A shared variable has a name, a value, and a scope. For example, a team variable named `NODE_ENV` can be referenced as: ```txt {{team.NODE_ENV}} ``` Keep `team` as the literal scope keyword. Do not replace it with the team's name. When Coolify prepares a resource configuration, it replaces a valid reference with the value stored at that scope. If the reference does not match an available shared variable, it remains unresolved. *** Choose a scope [#choose-a-scope] Use the narrowest scope that covers every resource which needs the value. | Scope | Available to | Reference syntax | | :-------------- | :---------------------------------------------------------------------- | :------------------------------ | | **Team** | Resources in the active team | `{{team.VARIABLE_NAME}}` | | **Project** | Resources in one project | `{{project.VARIABLE_NAME}}` | | **Environment** | Resources in one project environment, such as `production` or `staging` | `{{environment.VARIABLE_NAME}}` | | **Server** | Resources deployed to one server | `{{server.VARIABLE_NAME}}` | The scope words `team`, `project`, `environment`, and `server` are fixed. Replace only `VARIABLE_NAME` with the shared variable's name. Server-scoped references use the server that runs the resource. This lets the same resource configuration resolve a server-specific value when deployed to different servers. *** Create a shared variable [#create-a-shared-variable] Open Shared Variables [#open-shared-variables] Select **Shared Variables** in the Coolify sidebar. Choose the scope [#choose-the-scope] Select **Team wide**, **Project wide**, **Environment wide**, or **Server wide**. For project, environment, or server scope, select the specific item that should own the variable. Add the variable [#add-the-variable] Select **Add variable**, then enter: * **Name**: the variable key, such as `NODE_ENV` * **Value**: the value to reuse, such as `production` * **Comment**: optional context about what uses the value Set **Value type** to **Multiline** when the value contains line breaks. Select **Add variable**. The new entry appears on the selected scope page. *** Reference a shared variable [#reference-a-shared-variable] Open the resource environment variables [#open-the-resource-environment-variables] Open the application, database, or service that needs the value, then open its **Environment Variables** page. Add the resource variable [#add-the-resource-variable] Create the environment variable the workload should receive. For example: ```dotenv NODE_ENV={{team.NODE_ENV}} ``` The left side is the environment variable available to the workload. The right side tells Coolify which shared value to insert. You can also combine shared references with text: ```dotenv DATABASE_URL=postgresql://{{environment.DB_HOST}}:{{environment.DB_PORT}}/app ``` Apply and verify the change [#apply-and-verify-the-change] Save the resource environment variable, then redeploy or restart the resource when its configuration requires it. Verify inside the workload or through its behavior that the environment variable contains the expected resolved value. Do not print a secret value into public deployment logs. *** Manage variables in Developer view [#manage-variables-in-developer-view] Select **Developer view** on a scope page to edit ordinary shared variables as `KEY=value` lines. Select **Save changes** to apply the complete editor contents. Lines beginning with `#` are treated as comments. Developer view can create new variables, update existing ordinary values, and delete variables omitted from the editor. Removing a variable's line and saving deletes that shared variable. Review the entire editor before selecting **Save changes**. Locked and multiline variables appear as placeholders in Developer view and cannot be changed there. Edit multiline variables in **Normal view**. To change a locked value, delete the variable and create it again. *** Update or delete a shared variable [#update-or-delete-a-shared-variable] In **Normal view**, open the variable entry to change its name, value, comment, or **Value type**, then select **Update variable**. References use the variable name. If you rename a shared variable, update every `{{scope.VARIABLE_NAME}}` reference that used the previous name. To permanently remove a variable, select **Delete**, enter the variable name shown in the confirmation dialog, and select **Permanently Delete**. Deleting a shared variable does not remove its references from resource configuration. Search the affected resources and replace or remove those references before their next deployment. *** Use shared variables in Docker Compose [#use-shared-variables-in-docker-compose] Docker Compose resources can reference shared variables in their Compose configuration. The placement depends on whether the value configures Compose interpolation or a container environment variable. Follow [Environment variables in Docker Compose](/applications/builds/docker-compose#environment-variables) for the supported patterns and examples. Copying resolved values [#copying-resolved-values] Resource environment-variable pages can copy resolved shared values. Locked shared-variable references remain references and cannot be copied as secret values. Rename invalid keys to follow `[A-Za-z_][A-Za-z0-9_.]*`, then update their references. # What is Coolify (/docs/core/what-is-coolify) What is Coolify [#what-is-coolify] Coolify is an open source, self-hostable platform for deploying and managing applications, databases, and services on servers you control. Coolify gives you a platform-as-a-service (PaaS) workflow for configuring, deploying, and operating a resource from a dashboard or API, while the workloads remain standard Docker resources on your infrastructure. Coolify is the control plane for your infrastructure. Coolify connects to each server over SSH, prepares the server to run Docker workloads, and coordinates builds, deployments, domains, HTTPS, health checks, and day-to-day operations. You can run the Coolify instance yourself or use Coolify Cloud. In both cases, you provide the servers where applications, databases, and services run. *** What Coolify manages [#what-coolify-manages] Coolify calls each deployable item a **resource**. A resource belongs to a project and environment, then runs on a server connected to Coolify. A single Coolify instance can manage resources on one or more connected servers. *** How Coolify fits into your infrastructure [#how-coolify-fits-into-your-infrastructure] The Coolify instance coordinates work. Docker runs the resulting resources on the servers you connect. Because deployed resources use standard Docker containers, networks, and storage on your servers, they do not depend on a proprietary Coolify runtime. If the Coolify instance becomes unavailable, resources that are already running keep running; you lose Coolify automation and dashboard control until the Coolify instance returns. Workload data and persistent storage remain on the connected servers. Read [How Coolify works](/core/how-coolify-works) for a closer look at the control plane, connected servers, Docker, and proxy traffic. *** What stays in your control [#what-stays-in-your-control] Coolify is not a hosting provider for workload servers. Coolify automates deployment work on infrastructure you supply, but you still operate that infrastructure. Read the [Security model](/core/security-model) before placing production workloads on a connected server. *** Self-hosted or Coolify Cloud [#self-hosted-or-coolify-cloud] Coolify has two deployment models. The resource workflow stays the same; the difference is who operates the Coolify control plane. [Compare self-hosted Coolify and Coolify Cloud](/core/selfhosted-cloud-comparison) for a detailed responsibility and pricing breakdown. *** Start using Coolify [#start-using-coolify] If you are new to Coolify, choose a control plane model first. Then connect a server and deploy a first resource. # Backups (/docs/databases/backups) Backups [#backups] Coolify can create scheduled, engine-aware database backups for PostgreSQL, MySQL, MariaDB, MongoDB, ClickHouse, and SQLite. Each backup schedule creates a backup on the database's server, and can upload a copy to an S3-compatible storage provider. Redis, Dragonfly, and KeyDB do not support this scheduled database backup workflow. Use the engine's persistence and backup tools for those databases, or deploy a backup-capable service separately. A successful backup only proves that Coolify created a file. [Restore a copy](/databases/restore) into a disposable database and verify the application can read it before treating the backup as recoverable. Create a backup schedule [#create-a-backup-schedule] 1. Open a supported database. 2. Select **Backups** in the resource navigation. 3. Select **+ Add** next to **Database backups**. 4. Enter a cron expression or a supported human-readable frequency. 5. Select **Add schedule**. The schedule runs on the server where the database is deployed. The **Timezone** field is read-only: it uses the server timezone when one is configured, otherwise the Coolify instance timezone. SQLite backups use its configured database files. See [SQLite](/databases/sqlite) for application connections and file recovery. A backup job runs only while the database is running. If the database is stopped when the schedule fires, Coolify skips that execution. Back up a database inside a service [#back-up-a-database-inside-a-service] A database component deployed inside a Service uses credentials from the environment of its running container. This differs from a standalone database resource, whose connection values are stored directly by Coolify. Coolify reads the resolved container variables listed below. These names do not need to match the variable names shown on the parent Service's **Environment Variables** page. A one-click Service commonly maps a generated value such as `SERVICE_PASSWORD_POSTGRES` to `POSTGRES_PASSWORD` in its Compose definition. | Database | Variables used by Coolify | Fallback behavior | | :--------- | :--------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | PostgreSQL | `POSTGRES_PASSWORD`, `POSTGRES_USER`, `POSTGRES_DB` | `POSTGRES_USER` defaults to `postgres`. `POSTGRES_DB` defaults to the resolved username. When `POSTGRES_PASSWORD` is absent, Coolify runs the dump without setting `PGPASSWORD`; password-authenticated databases require this value. | | MySQL | `MYSQL_ROOT_PASSWORD`, `MYSQL_DATABASE` | `MYSQL_DATABASE` has no fallback. Without it, the backup stops before running `mysqldump`. A standard password-authenticated database also requires `MYSQL_ROOT_PASSWORD`. | | MariaDB | `MARIADB_ROOT_PASSWORD` or `MYSQL_ROOT_PASSWORD`; `MARIADB_DATABASE` or `MYSQL_DATABASE` | Coolify checks the `MARIADB_*` name first, then its `MYSQL_*` fallback. At least one password variable and one database variable are needed for a standard password-authenticated backup. | | MongoDB | `MONGO_INITDB_ROOT_USERNAME`, `MONGO_INITDB_ROOT_PASSWORD` | Coolify uses both values to construct the service database connection URL. The backup fails when either value is unavailable. | For example, a PostgreSQL component can map Service variables to the names Coolify reads: ```yaml services: postgres: environment: POSTGRES_USER: ${SERVICE_USER_POSTGRES} POSTGRES_PASSWORD: ${SERVICE_PASSWORD_POSTGRES} POSTGRES_DB: ${POSTGRES_DB:-app} ``` Variable names inside the database container are case-sensitive. Do not add duplicate `POSTGRES_*`, `MYSQL_*`, `MARIADB_*`, or `MONGO_INITDB_*` entries to **Environment Variables** when the Compose definition already maps generated Service variables to those names. To verify or correct the configuration: 1. Open the parent Service and select **Edit Compose File**. 2. Find the database component and inspect its `environment` entries. 3. Confirm that the required container-variable names in the table are present and mapped to the intended Service variables or values. 4. To change a referenced value such as `SERVICE_PASSWORD_POSTGRES`, open **Environment Variables**. Change a hard-coded value in the Compose file instead. 5. Restart or deploy the Service so Coolify recreates the database container with the updated environment. 6. Confirm that the database component is running, then open its backup schedule and select **Back up now**. 7. Inspect the execution status and message. Read [Service environment variables](/services/configuration/environment-variables) for details about generated, referenced, and hard-coded Compose values. A missing MySQL or MariaDB database-name variable can stop the job before Coolify creates a normal execution entry. If **Back up now** produces no execution, confirm that the database is running and recheck the variables in the table. Set the backup scope [#set-the-backup-scope] Open a schedule and use **General > Backup schedule** to configure the databases included in each execution. Select **Enable backup** or **Disable backup** to control scheduled runs, and **Save changes** after editing fields. | Database | Scope controls | Backup created by Coolify | | :--------- | :------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | | PostgreSQL | **Database selection** (**All databases** or **Specific databases**) and **Databases to back up** | `pg_dump` custom format for selected databases; `pg_dumpall` gzip output when all databases are selected. | | MySQL | **Database selection** (**All databases** or **Specific databases**) and **Databases to back up** | `mysqldump` output; all-database dumps use gzip compression. | | MariaDB | **Database selection** (**All databases** or **Specific databases**) and **Databases to back up** | `mariadb-dump` output; all-database dumps pass the command's `--compress` option but are not piped through `gzip` by Coolify. | | MongoDB | **Databases to include** | `mongodump` gzip archive. Empty includes all databases and collections. | | ClickHouse | **Databases to back up** | A ClickHouse backup archive created with the database's backup command. | For PostgreSQL, MySQL, and MariaDB, select **Specific databases**, then type each database name and press Enter in **Databases to back up**. For ClickHouse, enter a comma-separated list. An empty field uses the database configured in the resource. For MongoDB, use `database:collection1,collection2|database2` to exclude collections from each database. For example: ```sh app:events,logs|analytics ``` This includes all collections in `app` except `events` and `logs`, and all collections in `analytics`. Leave the field empty to include all databases and collections. Choose a frequency [#choose-a-frequency] Coolify accepts standard five-field cron expressions and these named schedules: | Name | Cron expression | | :------------- | :-------------- | | `every_minute` | `* * * * *` | | `hourly` | `0 * * * *` | | `daily` | `0 0 * * *` | | `weekly` | `0 0 * * 0` | | `monthly` | `0 0 1 * *` | | `yearly` | `0 0 1 1 *` | Use a **Timeout** of at least `60` seconds when a database dump needs more time. The timeout applies to the backup job and defaults to `3600` seconds in the job when no value is set. Store backups locally [#store-backups-locally] Coolify writes local database backups under `/data/coolify/backups` on the deployment server. The exact subdirectory includes the team, database, and execution name; use the **Executions** page to inspect the result instead of relying on a manually reconstructed path. Local retention can remove successful backup files after an execution completes. In **Retention**, set any of these values to `0` for no limit: * **Backups to keep** * **Days to keep** * **Maximum storage (GB)** The limits work independently. Coolify deletes a backup when any configured limit is reached, keeping the most recent backups first. Upload backups to S3 [#upload-backups-to-s3] 1. Configure and validate an S3-compatible storage under [S3 storage](/core/s3-storage/overview). 2. Open the database schedule and open **S3 storage**. 3. Select the validated **S3 storage**, select **Enable S3**, and select **Save changes**. 4. Optionally set **Local copy** to **Delete after S3 upload**. Coolify uploads the local backup file to the selected S3 storage after the local dump succeeds. If the upload fails, the local backup can still remain available and the execution reports the S3 warning. **Local copy > Delete after S3 upload** removes the local file after a successful S3 upload. It does not remove the S3 copy. Set S3 retention separately; local and S3 retention rules are independent. Run and verify a backup [#run-and-verify-a-backup] Open a schedule and select **Back up now** while the database is running. Coolify queues the backup job and shows the execution in the schedule. Open the execution to verify: * status is **Success** * the database names match the intended scope * the file size is greater than zero * S3 upload status is successful when S3 is enabled * the local copy still exists unless **Local copy** was set to **Delete after S3 upload** A failed S3 upload does not necessarily mean the local database dump failed. Read the execution message and notification to identify which copy is available. Related guides [#related-guides] Scheduling and failed executions [#scheduling-and-failed-executions] Due database backups are dispatched every minute independently of other schedule types. A scheduled backup whose queued job was lost is queued again after 60 minutes. A backup is skipped while the database starts, restarts, or imports, and a backup that exceeds its timeout fails with the timeout error. For backups of several databases, each database has its own result and finish time. All-database PostgreSQL, MySQL, and MariaDB backups fail if the dump command fails rather than retaining an incomplete archive. Review every result before relying on a backup set. # Choose a Database (/docs/databases/choose-a-database) Choose a database [#choose-a-database] Choose the database engine that matches the data model and workload your application already uses. [What is a database](/databases/what-is-a-database) explains the one-click resource that Coolify creates for each supported engine. Choose an engine [#choose-an-engine] | Engine | Use it for | Default port | Coolify scheduled backups | | :---------------------------------- | :--------------------------------------------------------------------------------- | :----------: | :-----------------------: | | [PostgreSQL](/databases/postgresql) | Relational data, transactions, and PostgreSQL extensions. | `5432` | Yes | | [MySQL](/databases/mysql) | Relational applications and the MySQL ecosystem. | `3306` | Yes | | [MariaDB](/databases/mariadb) | MySQL-compatible relational workloads. | `3306` | Yes | | [MongoDB](/databases/mongodb) | Document data and flexible schemas. | `27017` | Yes | | [SQLite](/databases/sqlite) | File-based databases mounted into an application on the same server; experimental. | None | Yes | | [Redis](/databases/redis) | Caches, queues, streams, and key-value data. | `6379` | No | | [Dragonfly](/databases/dragonfly) | Redis-compatible workloads using a multithreaded datastore. | `6379` | No | | [KeyDB](/databases/keydb) | Redis-compatible workloads using multithreading. | `6379` | No | | [ClickHouse](/databases/clickhouse) | Analytical queries and column-oriented data. | `9000` | Yes | Backup support means that the database resource exposes Coolify's engine-specific backup workflow. It does not mean that the engine cannot create its own backups. Choose a one-click database or a service [#choose-a-one-click-database-or-a-service] Use a one-click database when one standalone database container is enough and you want Coolify to manage its standard configuration and lifecycle. A [Service](/services) is a Docker Compose deployment. A one-click Service starts from a curated Compose template; **Docker Compose Empty** lets you provide your own Compose file. Use a Service when you need multiple database nodes, a custom topology, an unsupported engine, or configuration that the one-click database form does not expose. Create the database from **New Resource > Databases**. Use an application only for a workload that runs your application image. Keep the application and database as separate resources so their containers and deployments have separate lifecycles. Read [What is a database](/databases/what-is-a-database) for the creation flow and resource boundaries. Choose a version and image [#choose-a-version-and-image] The database selector provides the versions and images supported by the current Coolify release. PostgreSQL currently offers PostgreSQL 18, 17, and 16, plus Supabase PostgreSQL, PostGIS, and PGVector extension images. Select an image that matches your application's compatibility, architecture, and migration requirements. Do not change a production database image to another major version without checking the engine's upgrade procedure and taking a verified backup first. A database image version is not the same as a Coolify version. Verify the choice [#verify-the-choice] After creating the database: 1. Open **General** and confirm the image, credentials, database name, and internal port. 2. Confirm the persistent storage mount under **Persistent Storage**. 3. Start the database and check its status and logs. 4. Connect an application on the same destination with the **Internal URL**, or mount the data volume for SQLite. 5. Configure [backups](/databases/backups) for a supported engine and verify the [restore workflow](/databases/restore). If your application uses a different engine or requires a cluster, do not force it into a one-click resource. Use a Compose service or an external database provider instead. # ClickHouse (/docs/databases/clickhouse) ClickHouse [#clickhouse] Coolify deploys ClickHouse as a standalone analytical database on the selected server and destination. A new resource gets a generated administrator password, a persistent volume at `/var/lib/clickhouse`, an internal connection URL, and a health check. ClickHouse is a column-oriented database for analytical queries and online analytical processing (OLAP). Create a ClickHouse database [#create-a-clickhouse-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select ClickHouse [#select-clickhouse] Under **Databases**, select **ClickHouse**. You can also search for **ClickHouse** by name. Select a server [#select-a-server] Select the server that should run ClickHouse. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that ClickHouse should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, administrator username, generated password, native port, and connection URL. Keep the default private networking unless an external client requires access. Start ClickHouse [#start-clickhouse] Select **Start** and follow the startup output. Wait until ClickHouse is running and healthy, then copy the **Clickhouse URL (internal)** into clients on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :--------------------- | :------------------------------------------------- | | Native internal port | `9000` | | Default image | `clickhouse/clickhouse-server:25.11` | | HTTP interface | `8123` inside the container | | Administrator username | `default` | | Database | `default` when no other database is configured | | Data mount | `/var/lib/clickhouse` | | Scheduled backups | Supported | | SSL | Not available in the standalone database interface | Coolify's generated **Clickhouse URL (internal)** uses the native protocol and port `9000`: ```sh clickhouse://:@:9000/ ``` If an HTTP client or GUI needs the HTTP interface, map the container's `8123` port with **Port mappings**. When **Public access > Access** is **Public through TCP proxy**, use the generated **Clickhouse URL (public)** for the native protocol; configure an HTTP mapping separately when the client requires HTTP. For example, map `8123:8123` and connect an HTTP client to `http://:8123` with the ClickHouse administrator username and password. Map `9000:9000` when a client uses the native TCP protocol, such as `clickhouse-client`. Configure ClickHouse [#configure-clickhouse] Open **General** to change the image, administrator credentials, **Port mappings**, public proxy, and supported custom Docker options. The current standalone ClickHouse form does not expose a database-name field; the generated URL uses the resource's configured database value, which defaults to `default`. Coolify creates a persistent volume at `/var/lib/clickhouse` when it creates the resource. ClickHouse does not expose a custom configuration editor or SSL selector in the standalone database interface. Use a Docker Compose deployment when you need to manage a custom ClickHouse topology or configuration files directly. Back up and restore ClickHouse [#back-up-and-restore-clickhouse] Coolify supports scheduled ClickHouse backups. Configure a schedule under **Backups**, enter one or more comma-separated database names, and configure local or S3 retention. Coolify creates a ClickHouse backup archive and removes expired copies according to the schedule's retention rules. Use the database's **Terminal** or an approved ClickHouse client to verify the restored tables. Coolify's built-in [Import Backup workflow](/databases/restore#restore-support) does not support ClickHouse. The backup archive is created through ClickHouse's backup workflow. Test an archive against a disposable ClickHouse resource before relying on it for recovery. Health checks [#health-checks] Coolify's default health check runs `clickhouse-client` inside the container and executes a simple query. Configure the interval, timeout, retries, and start period under **Healthcheck**, then restart ClickHouse after saving. Official ClickHouse resources [#official-clickhouse-resources] * [ClickHouse documentation](https://clickhouse.com/docs) * [ClickHouse source](https://github.com/ClickHouse/ClickHouse) * [ClickHouse Docker image](https://hub.docker.com/r/clickhouse/clickhouse-server) * [ClickHouse backup and restore](https://clickhouse.com/docs/operations/backup) Existing data volumes with file mounts [#existing-data-volumes-with-file-mounts] If an older ClickHouse resource with a file mount was affected by the data-volume issue, Coolify keeps its existing data and asks you to adopt it before the next start. Review the volume and take a backup before confirming; do not replace it with an empty volume. # Environment Variables (/docs/databases/configuration/environment-variables) Environment variables [#environment-variables] Database environment variables pass configuration to the database container at runtime. Open the database resource, then select **Environment Variables**. Add or edit a variable [#add-or-edit-a-variable] Use **Normal view** to add or edit variables individually. Select **Add**, fill in **Name** and **Value**, choose **Value type** and **Interpolation** as needed, then select **Add variable**. To edit a variable, select its name or edit icon and select **Update variable** after making changes. Use **Developer view** to review or edit the production variable list as text. The exact controls depend on your team permissions. Each variable has a key and value. Treat passwords, tokens, and connection strings as secrets. Do not put a secret in a database image, custom configuration that is committed to Git, or a public URL. External secret managers [#external-secret-managers] Link Doppler, Infisical, or HashiCorp Vault and reference a remote value with `{{vault.KEY}}`. Restart or redeploy the database after the provider value changes. Follow [Use a secret manager](/integrations/security/using-secret-managers). Database variables and General settings [#database-variables-and-general-settings] Environment variables are separate from the credentials and engine fields on **General**. Some database images use environment variables during initialization, while other settings are generated from the General form. On new KeyDB and Dragonfly resources, `REDIS_PASSWORD` sets both the server password and connection URLs. Resources created before this release keep their stored password unless the variable uses a secret-manager reference. Review the engine-specific behavior before changing an existing resource’s credentials. Apply changes [#apply-changes] Saving a variable updates the stored resource configuration. Restart or redeploy the database so the container starts with the new environment. After it starts: 1. Open the database **Runtime Logs** and confirm the process starts without an environment-variable error. 2. Check the database status and health check. 3. Connect using the updated **Internal URL** or the client configuration that uses the variable. Many database images use environment variables only when the data directory is initialized. Changing an initialization variable does not necessarily change an existing database. Follow the engine documentation and use a deliberate migration or SQL command for an already-initialized data directory. Names and copying values [#names-and-copying-values] New environment variable names must match `[A-Za-z_][A-Za-z0-9_.]*`: begin with a letter or underscore, then use letters, numbers, underscores, or dots. Existing invalid runtime-only names, such as `my-var`, deploy with a warning and suggested name. Invalid build-time names stop the image build. Use the copy button to copy a resolved value. Shared-variable and `$SERVICE_*` references resolve to their actual values. Locked variables have no copy button, and references to locked shared variables remain references rather than exposing the secret. # General (/docs/databases/configuration/general) General settings [#general-settings] Open a database resource, then select **General**. The page contains common resource settings and controls specific to the selected database engine. Common settings [#common-settings] | Setting | What it controls | | :----------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | The database name shown throughout Coolify. | | **Description** | Optional information about the database or its owner. | | **Image** | The Docker image and tag used to run the database. | | **Credentials and initial database** | The account and database values used by the engine's entrypoint and Coolify's connection details. The labels vary by engine. | | **Port mappings** | Docker host-to-container mappings such as `15432:5432`. | | **Public access > Access** | Choose **Private** or **Public through TCP proxy**. The public option starts a separate TCP proxy for external clients after a **Public port** is set. | | **Public port** | The server port used by the public TCP proxy. | | **Proxy timeout** | How long the public proxy keeps an idle connection open. The default is `3600`; the minimum is `1`. | | **Custom engine configuration** | Optional configuration text mounted or passed to the selected database image. | Connection fields include the engine name, such as **Postgres URL (internal)** and **Postgres URL (public)**. The public URL becomes available after configuring public access. Coolify does not expose a public database endpoint by default. Prefer the **Internal URL** for applications on the same destination network. Read [Network access](/databases#network-access) before enabling public access. Engine-specific settings [#engine-specific-settings] The available controls change with the selected engine: | Engine | Additional settings | | :---------------------------------- | :------------------------------------------------------------------------------------------------------------------- | | [PostgreSQL](/databases/postgresql) | Initial database arguments, host authentication method, custom PostgreSQL configuration, and initialization scripts. | | [MySQL](/databases/mysql) | Root and normal-user credentials, initial database, and custom MySQL configuration. | | [MariaDB](/databases/mariadb) | Root and normal-user credentials, initial database, and custom MariaDB configuration. | | [MongoDB](/databases/mongodb) | Initial root credentials, initial database, and custom MongoDB configuration. | | [Redis](/databases/redis) | Username, password, and custom Redis configuration. | | [Dragonfly](/databases/dragonfly) | Password and supported custom Docker options. | | [KeyDB](/databases/keydb) | Password and custom KeyDB configuration. | | [ClickHouse](/databases/clickhouse) | Initial administrator credentials and the native database port. | Keep credentials synchronized [#keep-credentials-synchronized] Coolify uses the values saved in **General** to build connection URLs and run database automation. If you change a username, password, or initial database directly inside the database, update the matching value in Coolify as well. Redis, Dragonfly, and KeyDB apply authentication through container configuration or environment variables. Follow the engine guide when changing those values so the running database and Coolify use the same credentials. Apply changes [#apply-changes] Select **Save changes**, then restart or redeploy the database when Coolify marks the configuration as changed. Confirm the database starts successfully and copy the updated **Internal URL** from the resource after changing connection values. Changing the Docker image can change the database major version or available configuration. Take a verified backup, check the engine upgrade procedure, and confirm the persistent data path before deploying the new image. # Health Checks (/docs/databases/configuration/health-checks) Health checks [#health-checks] Coolify configures a Docker health check for each standalone database. The engine-specific probe runs inside the database container and reports whether the configured check succeeds. Open the database resource, then select **Healthcheck**. Configure the check [#configure-the-check] | Setting | Default | Accepted value | | :------------------------- | :-----: | :--------------------------- | | **Interval (seconds)** | `15` | Whole number `1` or greater. | | **Timeout (seconds)** | `5` | Whole number `1` or greater. | | **Retries** | `5` | Whole number `1` or greater. | | **Start period (seconds)** | `5` | Whole number `0` or greater. | The database image supplies the probe command. The settings above control when Docker runs it and when Docker marks the container unhealthy; they do not change the database's authentication, storage, or connection URL. Enable or disable the check [#enable-or-disable-the-check] The health check is enabled by default. Select **Disable healthcheck** only when the image or custom configuration cannot support the generated probe. When disabled, Docker runs no health probe and Coolify cannot report a healthy or unhealthy state for the database. Select **Save changes**, then restart the database to apply the generated health-check configuration. Verify a health check [#verify-a-health-check] After the database restarts: 1. Open the database status and confirm it reports healthy. 2. Open **Runtime Logs** and check that the database completed startup. 3. Connect with the **Internal URL** from an application on the same destination network. A passing health check confirms only that the configured probe passed. It does not validate application queries, backup integrity, replication, or available disk space. Set **Start period (seconds)** high enough for the database to initialize on the selected server and storage. A short start period can mark a slow first startup unhealthy even when the database would become ready later. MongoDB health checks ping the database, so a running container whose database cannot respond is no longer treated as healthy automatically. Review container logs when the check fails. # Overview (/docs/databases/configuration/overview) Configure a database [#configure-a-database] Open a database resource and choose a page from the resource sidebar. **General** contains engine settings, credentials, and networking; storage, health checks, environment variables, and resource limits have their own pages. The available pages depend on the database engine and the resource state. For example, **Backups** is available only for engines supported by Coolify's database backup workflow, while **Import Backup** is available only for supported restore paths. Configuration pages [#configuration-pages] | Configuration page | What it controls | Guide | | :---------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------ | | **General** | Database identity, image, credentials, engine settings, network access, and proxy settings. | [Review General settings](/databases/configuration/general) | | **Environment Variables** | Runtime variables passed to the database container. | [Configure environment variables](/databases/configuration/environment-variables) | | **Servers** | The server and destination where the database runs. | [Configure multi-server deployments](/core/infrastructure/scaling/multi-server-deployments) | | **Persistent Storage** | Volumes, directories, and files mounted into the database container. | [Configure persistent storage](/databases/configuration/persistent-storage) | | **Import Backup** | Restore a supported PostgreSQL, MySQL, MariaDB, or MongoDB backup. The page is also shown for unsupported engines, where Coolify displays that restore is not supported. | [Restore a database](/databases/restore) | | **Webhooks** | Authenticated requests for database operations from external automation. | [Deploy webhooks](/core/automation/deploy-webhooks) | | **Healthcheck** | The Docker health probe used to report database health. | [Configure health checks](/databases/configuration/health-checks) | | **Resource Limits** | CPU and memory limits applied to the database container. | [Configure resource limits](/databases/configuration/resource-limits) | | **Resource Operations** | Clone the database to another destination or move it between projects and environments. | [Clone or move a database](/databases/operations/resource-operations) | | **Metrics** | CPU and memory usage for the database container. | [Monitor resource metrics](/core/observability/monitoring/metrics) | | **Tags** | Team-level labels used to organize resources. | [Organize resources with tags](/core/automation/tags/overview) | | **Danger Zone** | Destructive actions, including deleting the database resource. | [Delete a database](/databases/operations/danger-zone) | Apply configuration changes [#apply-configuration-changes] Saving a setting updates the database resource configuration. It does not always recreate the running container immediately. Restart or redeploy the database after changing settings that affect its container, including: * image, credentials, or engine configuration * environment variables * persistent storage mounts * ports or public proxy settings * health-check settings * resource limits Use the configuration-change indicator and the database status to confirm whether Coolify is waiting for a restart or redeploy. Take and verify a database backup before changing a production image, data mount, engine configuration, or credential. A configuration change can prevent the database from starting even when the stored data is intact. Continue with configuration guides [#continue-with-configuration-guides] # Persistent Storage (/docs/databases/configuration/persistent-storage) Configure persistent storage [#configure-persistent-storage] Database containers are replaceable. Coolify mounts database files outside the container so normal container recreation does not remove the data. Open the database resource, then select **Persistent Storage**. Removing or changing the data mount can make an existing database appear empty or prevent it from starting. Take a verified backup and confirm the engine's data path before changing storage. Default database data paths [#default-database-data-paths] Coolify creates the default persistent volume for a one-click database at the engine's data path: | Database | Data path | | :--------------------------- | :------------------------------ | | PostgreSQL before version 18 | `/var/lib/postgresql/data` | | PostgreSQL 18 and later | `/var/lib/postgresql` | | MySQL and MariaDB | `/var/lib/mysql` | | MongoDB | `/data/db` and `/data/configdb` | | Redis, Dragonfly, and KeyDB | `/data` | | ClickHouse | `/var/lib/clickhouse` | Use the path for the image and major version you selected. PostgreSQL 18 uses a different default path from earlier PostgreSQL images. Add a mount [#add-a-mount] Select **Add**, then choose the mount type that matches the database configuration: | Mount type | Use it for | | :------------------ | :----------------------------------------------------------------------------- | | **Volume Mount** | A Docker-managed volume attached at a container destination. | | **Directory Mount** | A directory that already exists or should be created on the deployment server. | | **File Mount** | A configuration file whose contents Coolify manages. | | **Host File Mount** | An existing file on the server that Coolify should bind into the container. | Enter the exact **Destination Path** expected by the database image. Save the mount, then restart or redeploy the database and verify that it starts with the expected data. Storage boundaries [#storage-boundaries] * Storage is local to the deployment server unless the Docker destination provides shared storage. * The database process must have permission to read and write the mounted path. * A mount does not recover data that was already deleted from a container or volume. * Persistent storage is not a backup. Configure [database backups](/databases/backups) for supported engines and test [restoring a database](/databases/restore). Read the [Core persistent storage guide](/core/persistent-storage/storage-mounts/overview) for mount permissions, source paths, and backup behavior. # Resource Limits (/docs/databases/configuration/resource-limits) Resource limits [#resource-limits] Open a database resource, then select **Resource Limits** to restrict the CPU and memory available to its container. Start with measured database usage and leave enough capacity for startup, backups, compaction, and query bursts. A limit that is too low can make a healthy database appear unavailable. CPU limits [#cpu-limits] | Setting | Accepted value | Default | Behavior | | :------------- | :----------------------------------------------- | :-----: | :---------------------------------------------------------- | | **CPU limit** | A whole or decimal number, such as `2` or `0.5`. | `0` | Maximum CPU capacity. `0` means no configured limit. | | **CPU set** | CPU numbers or ranges, such as `0-2` or `0,1,3`. | Empty | Restricts the container to selected CPU cores. | | **CPU weight** | A whole number of `0` or greater. | `1024` | Relative CPU priority when containers compete for CPU time. | **CPU weight** changes priority during contention; it does not reserve CPU capacity. Memory limits [#memory-limits] Memory fields accept `0` or a number followed by `b`, `k`, `m`, or `g`, such as `256m` or `1g`. | Setting | Default | Behavior | | :------------------------ | :-----: | :------------------------------------------------------------------------------- | | **Memory reservation** | `0` | Memory reservation used during server memory pressure. | | **Swappiness** | `60` | Value from `0` to `100` controlling how readily anonymous memory can be swapped. | | **Memory limit** | `0` | Hard memory limit for the container. | | **Memory and swap limit** | `0` | Total memory and swap available to the container. | `0` means no configured limit for the CPU and memory limit fields. Set an explicit limit only when you understand the database's memory behavior and the server's available capacity. A database that reaches its hard memory limit can be terminated by Docker. A low CPU limit can also make startup, health checks, backups, or queries time out. Review **Runtime Logs**, **Metrics**, and health status after applying a limit. Apply and verify [#apply-and-verify] Select **Save changes**, then restart or redeploy the database so the container starts with the new limits. After it starts: 1. Open **Metrics** and check CPU and memory usage. 2. Open **Runtime Logs** for out-of-memory exits, repeated restarts, or failed startup messages. 3. Run a representative application query and a backup, when supported. # Dragonfly (/docs/databases/dragonfly) Dragonfly [#dragonfly] Coolify deploys Dragonfly as a standalone Redis-compatible datastore on the selected server and destination. A new resource gets a generated password, a persistent volume at `/data`, an internal connection URL, and a health check. Dragonfly is a Redis-compatible datastore designed for in-memory workloads and multithreaded execution. Create a Dragonfly database [#create-a-dragonfly-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select Dragonfly [#select-dragonfly] Under **Databases**, select **Dragonfly**. You can also search for **Dragonfly** by name. Select a server [#select-a-server] Select the server that should run Dragonfly. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that Dragonfly should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, generated password, SSL settings, and connection URLs. Keep the default private networking unless an external client requires access. Start Dragonfly [#start-dragonfly] Select **Start** and follow the startup output. Wait until Dragonfly is running and healthy, then copy the **Dragonfly URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :------------------------- | :-------------------------------------------- | | Internal port | `6379`; TLS uses `6380` | | Default image | `docker.dragonflydb.io/dragonflydb/dragonfly` | | Authentication | Generated password | | Data mount | `/data` | | Scheduled database backups | Not supported by Coolify | | SSL | Supported with **SSL** | Dragonfly uses the Redis protocol for its connection URL. It does not expose a username field in the Coolify database form. Connect to Dragonfly [#connect-to-dragonfly] Use the **Dragonfly URL (internal)** for an application on the same Coolify destination network: ```sh redis://:@:6379/0 ``` With SSL enabled, use the generated `rediss` URL and TLS port `6380`. When **Public access > Access** is **Public through TCP proxy**, use the generated **Dragonfly URL (public)**. Configure Dragonfly [#configure-dragonfly] Open **General** to change the image, password, **Port mappings**, public proxy, and supported custom Docker options. Open **Persistent Storage** to manage the `/data` volume. Dragonfly's image and command options control persistence behavior. Review the image's documentation before changing the startup options or assuming that in-memory data has been written to disk. Backups and persistence [#backups-and-persistence] Coolify does not create scheduled database backups for Dragonfly. Keep the `/data` persistent volume and configure Dragonfly's supported snapshot or persistence features when you need recovery copies. Test restores independently. SSL and health checks [#ssl-and-health-checks] Dragonfly exposes **SSL** without an SSL mode selector. See [Database SSL](/databases/ssl) for the CA certificate mount and TLS connection workflow. Configure the Docker health check under **Healthcheck** and restart Dragonfly after saving. Official Dragonfly resources [#official-dragonfly-resources] * [Dragonfly documentation](https://www.dragonflydb.io/docs) * [Dragonfly source](https://github.com/dragonflydb/dragonfly) * [Dragonfly Docker image](https://hub.docker.com/r/dragonflydb/dragonfly) Password environment variable [#password-environment-variable] For a new database, `REDIS_PASSWORD` controls the server password and connection URLs. Databases created before this release keep their stored password unless the variable references a secret manager. After changing a remote secret, restart the database and verify connections. # How Databases Work (/docs/databases/how-databases-work) How databases work [#how-databases-work] Coolify combines a database definition in the control plane with a database container and persistent storage on a connected server. The database definition contains the selected engine and image, credentials, deployment destination, storage, networking, health-check, backup, and resource settings. Docker runs the container and stores the database files in the attached volume. How a one-click database works in Coolify [#how-a-one-click-database-works-in-coolify] A one-click database is created from an engine-specific helper in Coolify. The helper applies the defaults for that engine, generates credentials, creates the standalone database record, creates its default persistent storage, and sends you to the database's configuration page. It does not start the database container during resource creation; you review the generated settings and deploy it from Coolify. The resource is attached to a project and environment, then placed on a selected server and Docker network destination. Coolify excludes build servers from this selection because they are not intended to host running database resources. The supported engine determines the generated image, connection port, data path, credentials, health probe, connection URL format, SSL behavior, and whether Coolify's database-aware backup workflow is available. For example, PostgreSQL offers image choices after you select the server and destination; MySQL, MariaDB, MongoDB, Redis, Dragonfly, KeyDB, and ClickHouse use their engine-specific creation defaults. From creation to a running database [#from-creation-to-a-running-database] 1. Select an engine from **New Resource > Databases** inside a project and environment. 2. Select the server and network destination where the database should run. 3. Review the generated resource under **General**, including its image, credentials, ports, connection URLs, and engine-specific settings. 4. Confirm the persistent storage under **Persistent Storage**. 5. Select **Start**. Coolify queues the start operation, resolves secret-manager credentials when configured, and prepares the container, attaches the volume and destination network, and starts the database. 6. Docker runs the configured health check. A healthy database can accept connections from applications and clients that can reach its network. The resource remains available in the project after deployment. Use its configuration and operation pages to change settings, view logs, open a terminal, restart it, or redeploy it. SQLite applications connect by mounting database files from the data volume on the same server rather than using an internal URL. See [SQLite](/databases/sqlite). What Coolify manages [#what-coolify-manages] Coolify manages the resource definition and coordinates Docker operations on the selected server. Depending on the engine and settings, it can manage: * the database image and generated container configuration * generated credentials and the connection URLs shown in **General** * the default persistent volume and engine data path * the destination network and optional host port or public TCP proxy * the Docker health check and resource limits * SSL certificates and connection settings where the engine supports them * scheduled database backups for supported engines Coolify does not turn a one-click database into a cluster. Replication, sharding, failover, engine-level users, schema migrations, and major-version upgrades remain database-engine responsibilities. Containers can be replaced [#containers-can-be-replaced] Coolify can recreate the database container when its image or generated configuration changes. The named volume is separate from the container, so normal container replacement does not remove the database files. The default data path differs by engine and, for PostgreSQL, by major image version. Data written only to the container filesystem is not protected. Do not remove or change the database's persistent storage mount unless you have verified the data location and have a backup. Changing an image tag or generated configuration is not the same as performing a safe database upgrade. Take a verified backup and follow the engine's upgrade procedure before changing a production major version. How applications connect [#how-applications-connect] Applications on the same Coolify destination network should use the database's **Internal URL**. The URL contains the generated credentials, database name, container name, and engine port. | Connection location | Use | | :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | | Same destination network | The **Internal URL** from **General**. | | Another server or external client | A configured port mapping or **Public access > Access > Public through TCP proxy** TCP proxy, plus the generated public connection details. | Coolify does not publish a database endpoint by default. Read [Network access](/databases#network-access) before exposing one. Health checks show database readiness [#health-checks-show-database-readiness] The database health check is a Docker health check, not a backup or a data-integrity check. Configure it under **Healthcheck** with **Interval (seconds)**, **Timeout (seconds)**, **Retries**, and **Start period (seconds)**. A successful health check means the configured probe passed; it does not confirm that an application query or replication setup is correct. Backups are engine-specific [#backups-are-engine-specific] Coolify runs database-aware scheduled backups for PostgreSQL, MySQL, MariaDB, MongoDB, and ClickHouse. Redis, Dragonfly, and KeyDB have persistent storage but do not expose the standalone database backup workflow. The backup destination can be local storage or an S3-compatible bucket. A backup is separate from the live database volume: it gives you a recovery artifact that can be stored away from the database server. Read [Configure database backups](/databases/backups) for schedules, retention, and storage. Read [Restore a database](/databases/restore) for the supported import workflow. Control plane and database server [#control-plane-and-database-server] Coolify is the control plane that stores the resource configuration and coordinates operations. The connected server is the workload machine that stores the Docker volume and runs the database container. Running database containers can continue serving traffic while the Coolify control plane is unavailable, as long as Docker, the server, the network, and the database remain healthy. New Coolify operations require the control plane to be available. Continue learning [#continue-learning] # Databases (/docs/databases) Databases [#databases] Coolify deploys standalone databases as containers on the server and network you select. Each database resource includes generated credentials, a persistent data volume, an internal connection URL, and controls for networking, health checks, storage, and resource limits. Use the one-click database list when you want Coolify to create the container configuration for a supported engine. You can also deploy a database with Docker Compose when you need an engine or topology that is not in this list. If you are new to Coolify databases, start with [What is a database](/databases/what-is-a-database), [How databases work](/databases/how-databases-work), and [Choose a database](/databases/choose-a-database). Then follow [Deploy your first database](/deploy-your-first-database). Choose a database [#choose-a-database] | Database | Best suited for | Built-in scheduled backups | Default internal port | | :---------------------------------- | :------------------------------------------------------- | :------------------------: | :-------------------: | | [PostgreSQL](/databases/postgresql) | Relational data, extensions, and transactional workloads | Yes | `5432` | | [MySQL](/databases/mysql) | Relational applications and broad ecosystem support | Yes | `3306` | | [MariaDB](/databases/mariadb) | MySQL-compatible relational workloads | Yes | `3306` | | [MongoDB](/databases/mongodb) | Document-oriented data and flexible schemas | Yes | `27017` | | [Redis](/databases/redis) | Caching, queues, streams, and key-value data | No | `6379` | | [Dragonfly](/databases/dragonfly) | Redis-compatible workloads on a multithreaded datastore | No | `6379` | | [KeyDB](/databases/keydb) | Redis-compatible workloads with multithreading | No | `6379` | | [ClickHouse](/databases/clickhouse) | Analytical and column-oriented workloads | Yes | `9000` | Scheduled backup support means that Coolify can run an engine-specific dump job from the database's **Backups** page. Redis, Dragonfly, and KeyDB still have persistent storage, but they do not expose Coolify's scheduled database backup workflow. Deploy a database [#deploy-a-database] 1. Open a project and select **Create New Resource**. 2. Select a database from the database list. 3. Select the server and destination where the database should run. 4. Review the generated credentials and settings under **General**. 5. Select **Start**. Coolify creates the database container on the selected destination. The database does not receive a public network endpoint by default. For a complete first-deployment walkthrough, read [Deploy your first database](/deploy-your-first-database). Connect an application [#connect-an-application] When an application runs on the same Coolify destination network as the database, use the database's **Internal URL**. Coolify builds this URL with the database container name, internal port, credentials, and selected database. Copy the URL from the database's **General** configuration and add it to the application's environment variables. Do not replace the container name with a server IP for an internal connection. If the application runs on another server or network, use a public connection only when the database must accept external traffic. See [Network access](#network-access) for the two public access methods. Network access [#network-access] Coolify provides two ways to expose a database port: | Method | What it does | When to use it | | :---------------------------------------------------- | :---------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- | | **Port mappings** | Adds a Docker host-to-container port mapping to the database container. | A fixed host port or a client that connects directly to the server. | | **Public access > Access > Public through TCP proxy** | Runs a separate Nginx TCP proxy on the selected **Public port**. | A public connection that you want to change without changing the database container's port mappings. | A port mapping uses the format `host-port:container-port`, for example `15432:5432`. You can enter multiple comma-separated mappings. The database container is recreated when its generated configuration changes. The public TCP proxy requires the database to be running and a **Public port** between `1` and `65535`. **Proxy timeout** defaults to `3600` and must be at least `1`. The proxy is separate from the database container, so changes to the public port or timeout update the proxy rather than the database process. A public database port exposes a database protocol to the network. Use private networking whenever possible. If an external client must connect, restrict the port with your server or provider firewall and use SSL where the engine supports it. When a database is public, Coolify displays a **Public URL** next to the internal URL. Use that generated URL instead of assembling a connection string by hand. Persistent data [#persistent-data] Coolify creates a named Docker volume when it creates a standalone database. The volume remains separate from the database container so redeploying or recreating the container does not remove the database data. | Database | Container data path | | :--------------------------- | :------------------------------ | | PostgreSQL before version 18 | `/var/lib/postgresql/data` | | PostgreSQL 18 and later | `/var/lib/postgresql` | | MySQL and MariaDB | `/var/lib/mysql` | | MongoDB | `/data/db` and `/data/configdb` | | Redis, Dragonfly, and KeyDB | `/data` | | ClickHouse | `/var/lib/clickhouse` | Persistent storage is not a database-aware backup. Use [database backups](/databases/backups) for supported engines and test [restoring a database](/databases/restore) before relying on it. Open **Persistent Storage** to add or change storage mounts. Changing or removing a mount can make existing data unavailable to the container, so verify the source and destination before saving. Database health [#database-health] Coolify can attach a Docker health check to every standalone database. Open **Healthcheck** to configure: * **Interval (seconds)**: time between checks; minimum `1`. * **Timeout (seconds)**: maximum time for one check; minimum `1`. * **Retries**: failed checks before Docker marks the container unhealthy; minimum `1`. * **Start period (seconds)**: startup time before failed checks count; minimum `0`. Health checks are enabled by default in current Coolify versions. Save the settings, enable or disable the check, then restart the database to apply the generated container configuration. Database resource navigation [#database-resource-navigation] The database resource navigation separates configuration from day-to-day operations: | Area | Use it to | Guide | | :------------------------ | :----------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------ | | **General** | Change engine credentials, image, ports, proxy, and engine-specific configuration. | [General settings](/databases/configuration/general) | | **Environment Variables** | Manage runtime variables passed to the database container. | [Environment variables](/databases/configuration/environment-variables) | | **Servers** | Review or change the selected server and destination. | [Configure multi-server deployments](/core/infrastructure/scaling/multi-server-deployments) | | **Persistent Storage** | Manage the named volumes and mounts that keep database data across container recreation. | [Persistent storage](/databases/configuration/persistent-storage) | | **Import Backup** | Restore a supported PostgreSQL, MySQL, MariaDB, or MongoDB backup while the database is running. | [Restore a database](/databases/restore) | | **Webhooks** | Create authenticated requests for database operations from external automation. | [Deploy webhooks](/core/automation/deploy-webhooks) | | **Healthcheck** | Configure the Docker readiness and liveness probe. | [Health checks](/databases/configuration/health-checks) | | **Resource Limits** | Set CPU and memory limits for the database container. | [Resource limits](/databases/configuration/resource-limits) | | **Resource Operations** | Clone the database to another destination or move it between projects and environments. | [Clone or move a database](/databases/operations/resource-operations) | | **Metrics** | View CPU and memory usage for the database container. | [Monitor resource metrics](/core/observability/monitoring/metrics) | | **Tags** | Organize the resource and use it with tag-based automation. | [Organize resources with tags](/core/automation/tags/overview) | | **Danger Zone** | Delete the database resource and choose which related Docker resources to remove. | [Delete a database](/databases/operations/danger-zone) | Continue with a database guide [#continue-with-a-database-guide] # KeyDB (/docs/databases/keydb) KeyDB [#keydb] Coolify deploys KeyDB as a standalone Redis-compatible datastore on the selected server and destination. A new resource gets a generated password, a persistent volume at `/data`, an internal connection URL, and a health check. KeyDB is a Redis-compatible datastore with multithreading and support for Redis commands and clients. Create a KeyDB database [#create-a-keydb-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select KeyDB [#select-keydb] Under **Databases**, select **KeyDB**. You can also search for **KeyDB** by name. Select a server [#select-a-server] Select the server that should run KeyDB. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that KeyDB should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, generated password, SSL settings, and connection URLs. Keep the default private networking unless an external client requires access. Start KeyDB [#start-keydb] Select **Start** and follow the startup output. Wait until KeyDB is running and healthy, then copy the **KeyDB URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :------------------------- | :----------------------- | | Internal port | `6379`; TLS uses `6380` | | Default image | `eqalpha/keydb:latest` | | Authentication | Generated password | | Data mount | `/data` | | Scheduled database backups | Not supported by Coolify | | SSL | Supported with **SSL** | KeyDB uses the Redis protocol and does not expose a username field in the Coolify database form. Connect to KeyDB [#connect-to-keydb] Use the **KeyDB URL (internal)** for an application on the same Coolify destination network: ```sh redis://:@:6379/0 ``` With SSL enabled, use the generated `rediss` URL and TLS port `6380`. When **Public access > Access** is **Public through TCP proxy**, use the generated **KeyDB URL (public)**. Configure KeyDB [#configure-keydb] Open **General** to change the image, password, **Port mappings**, public proxy, **Custom KeyDB configuration**, and supported custom Docker options. Open **Persistent Storage** to manage the `/data` volume. Custom KeyDB configuration is written as the configuration file used to start KeyDB. When it is set, Coolify uses that file and adds the password only when the file does not already define `requirepass`. Include persistence and other required settings in the file. Backups and persistence [#backups-and-persistence] Coolify does not create scheduled database backups for KeyDB. Keep the `/data` persistent volume and configure KeyDB's supported persistence or replication features when you need recovery copies. Test restores independently. SSL and health checks [#ssl-and-health-checks] KeyDB exposes **SSL** without an SSL mode selector. See [Database SSL](/databases/ssl) for the CA certificate mount and TLS connection workflow. Configure the Docker health check under **Healthcheck** and restart KeyDB after saving. Official KeyDB resources [#official-keydb-resources] * [KeyDB documentation](https://docs.keydb.dev/) * [KeyDB source](https://github.com/EQ-Alpha/KeyDB) * [KeyDB Docker image](https://hub.docker.com/r/eqalpha/keydb) Password environment variable [#password-environment-variable] For a new database, `REDIS_PASSWORD` controls the server password and connection URLs. Databases created before this release keep their stored password unless the variable references a secret manager. After changing a remote secret, restart the database and verify connections. # MariaDB (/docs/databases/mariadb) MariaDB [#mariadb] Coolify deploys MariaDB as a standalone container on the selected server and destination. A new resource gets generated root and application-user passwords, a persistent data volume, an internal connection URL, and a health check. MariaDB is an open-source relational database that is compatible with many MySQL clients, schemas, and tools. Create a MariaDB database [#create-a-mariadb-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select MariaDB [#select-mariadb] Under **Databases**, select **MariaDB**. You can also search for **MariaDB** by name. Select a server [#select-a-server] Select the server that should run MariaDB. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that MariaDB should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, root password, normal username and password, initial database, and connection URLs. Keep the default private networking unless an external client requires access. Start MariaDB [#start-mariadb] Select **Start** and follow the startup output. Wait until MariaDB is running and healthy, then copy the **MariaDB URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :---------------- | :--------------------- | | Internal port | `3306` | | Default image | `mariadb:11` | | Normal user | `mariadb` | | Initial database | `default` | | Data mount | `/var/lib/mysql` | | Scheduled backups | Supported | | SSL | Supported with **SSL** | The root password and normal-user password are generated when the resource is created. If you change credentials or the initial database in MariaDB, update the matching values in **General** so connection URLs and automated backups continue to work. Connect to MariaDB [#connect-to-mariadb] MariaDB uses a MySQL-compatible connection URL. Use the **MariaDB URL (internal)** for an application on the same Coolify destination network: ```sh mysql://:@:3306/ ``` Coolify shows a **MariaDB URL (public)** only after **Public access > Access > Public through TCP proxy** and **Public port** are configured. Keep the database private unless an external client requires direct access. Configure MariaDB [#configure-mariadb] Open **General** to change the image, credentials, **Port mappings**, public proxy, custom Docker options, and **Custom MariaDB configuration**. Restart the resource after changing generated container configuration. Back up and restore MariaDB [#back-up-and-restore-mariadb] Coolify uses `mariadb-dump` for scheduled backups. Selected databases are dumped directly. **Database selection > All databases** passes `--compress` to `mariadb-dump`, but Coolify does not pipe the output through `gzip`; do not assume the resulting file is a gzip stream. For **Specific databases**, type each name and press Enter in **Databases to back up**. Use [Database backups](/databases/backups) to configure schedules, retention, and S3 storage. The built-in **Import Backup** form accepts MariaDB backups while the database is running; follow [Restore a database](/databases/restore) for the import workflow. Stop application writes and verify the target resource before confirming an import. Keep a separate copy of any data that must not be replaced. SSL and health checks [#ssl-and-health-checks] MariaDB exposes **SSL** without an SSL mode selector. Coolify configures the database TLS listener; configure the MariaDB client with its SSL options when connecting. See [Database SSL](/databases/ssl) for the CA certificate workflow. Configure the Docker health check under **Healthcheck** and restart MariaDB after saving. Official MariaDB resources [#official-mariadb-resources] * [MariaDB documentation](https://mariadb.com/kb/en/documentation/) * [MariaDB source](https://github.com/MariaDB/server) * [MariaDB Docker image](https://hub.docker.com/_/mariadb) * [MariaDB dump documentation](https://mariadb.com/kb/en/mariadb-dump/) # MongoDB (/docs/databases/mongodb) MongoDB [#mongodb] Coolify deploys MongoDB as a standalone container on the selected server and destination. A new resource gets a generated root password, a persistent data volume, an internal connection URL, and a health check. MongoDB is a document database that stores JSON-like documents instead of rows in fixed relational tables. Create a MongoDB database [#create-a-mongodb-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select MongoDB [#select-mongodb] Under **Databases**, select **MongoDB**. You can also search for **MongoDB** by name. Select a server [#select-a-server] Select the server that should run MongoDB. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that MongoDB should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, root username, generated password, initial database, SSL settings, and connection URLs. Keep the default private networking unless an external client requires access. Start MongoDB [#start-mongodb] Select **Start** and follow the startup output. Wait until MongoDB is running and healthy, then copy the **Mongo URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :---------------- | :------------------------------- | | Internal port | `27017` | | Default image | `mongo:7` | | Root username | `root` | | Initial database | `default` | | Data mounts | `/data/db` and `/data/configdb` | | Scheduled backups | Supported | | SSL | Supported with MongoDB SSL modes | If you change the root username, password, or initial database inside MongoDB, update the matching values in **General** so the generated URLs and automated backups use current credentials. Connect to MongoDB [#connect-to-mongodb] Use the **Mongo URL (internal)** for an application on the same Coolify destination network: ```sh mongodb://:@:27017/?directConnection=true ``` Coolify's generated internal URL includes `/?directConnection=true` after the port. Copy the generated URL when possible instead of rebuilding it manually. SSL adds `tls=true` and the CA path; `verify-full` also adds the server certificate path. See [Database SSL](/databases/ssl) for those paths. Coolify shows a **Mongo URL (public)** only after **Public access > Access > Public through TCP proxy** and **Public port** are configured. Keep MongoDB private unless an external client requires direct access. Configure MongoDB [#configure-mongodb] Open **General** to change the image, root credentials, **Port mappings**, public proxy, custom Docker options, and **Custom MongoDB configuration**. Restart the resource after changing generated container configuration. Back up MongoDB [#back-up-mongodb] Coolify uses `mongodump` and stores a gzip-compressed archive. An empty **Databases to include** field includes all databases and collections. To exclude collections, use this format: ```sh app:events,logs|analytics ``` This includes all collections in `app` except `events` and `logs`, and all collections in `analytics`. Configure the schedule, retention, and S3 copy in [Database backups](/databases/backups). The built-in **Import Backup** form accepts MongoDB archives while the database is running. Follow [Restore a database](/databases/restore), then verify the restored collections from a controlled client workflow. SSL and health checks [#ssl-and-health-checks] MongoDB supports `allow`, `prefer`, `require`, and `verify-full`. `verify-full` requires the client to trust the Coolify CA certificate. See [Database SSL](/databases/ssl). Configure the Docker health check under **Healthcheck** and restart MongoDB after saving. Official MongoDB resources [#official-mongodb-resources] * [MongoDB documentation](https://www.mongodb.com/docs/) * [MongoDB source](https://github.com/mongodb/mongo) * [MongoDB Docker image](https://hub.docker.com/_/mongo) * [`mongodump` documentation](https://www.mongodb.com/docs/database-tools/mongodump/) # MySQL (/docs/databases/mysql) MySQL [#mysql] Coolify deploys MySQL as a standalone container on the selected server and destination. A new resource gets generated root and application-user passwords, a persistent data volume, an internal connection URL, and a health check. MySQL is an open-source relational database used by applications that need SQL storage and transactions. Create a MySQL database [#create-a-mysql-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select MySQL [#select-mysql] Under **Databases**, select **MySQL**. You can also search for **MySQL** by name. Select a server [#select-a-server] Select the server that should run MySQL. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that MySQL should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, root password, normal username and password, initial database, and connection URLs. Keep the default private networking unless an external client requires access. Start MySQL [#start-mysql] Select **Start** and follow the startup output. Wait until MySQL is running and healthy, then copy the **MySQL URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :---------------- | :----------------------------- | | Internal port | `3306` | | Default image | `mysql:8` | | Normal user | `mysql` | | Initial database | `default` | | Data mount | `/var/lib/mysql` | | Scheduled backups | Supported | | SSL | Supported with MySQL SSL modes | The root password and normal-user password are generated when the resource is created. If you change credentials or the initial database inside MySQL, update the matching values in **General** so connection URLs and automated backups use the current values. Connect to MySQL [#connect-to-mysql] Use the **MySQL URL (internal)** for an application on the same Coolify destination network: ```sh mysql://:@:3306/ ``` When **Public access > Access** is **Public through TCP proxy**, Coolify shows a **MySQL URL (public)** using the server address and **Public port**. Keep MySQL private unless an external client requires direct access. Read [Databases](/databases) for port mappings, the public TCP proxy, and firewall considerations. Configure MySQL [#configure-mysql] Open **General** to change the image, credentials, **Port mappings**, public proxy, custom Docker options, and **Custom MySQL configuration**. Coolify mounts the custom configuration into the MySQL container and recreates the generated configuration when you restart the resource. Use the image version that matches your application and backup/restore tooling. Test major-version changes against a copy of the data before applying them to production. Back up and restore MySQL [#back-up-and-restore-mysql] Coolify uses `mysqldump` for scheduled backups. Selected databases are dumped directly; **Database selection > All databases** creates a gzip-compressed all-database dump. For **Specific databases**, type each name and press Enter in **Databases to back up**. Configure schedules, retention, and S3 storage under [Database backups](/databases/backups). The built-in **Import Backup** form accepts MySQL backups while the database is running; follow [Restore a database](/databases/restore) for the import workflow. Stop application writes and verify the target resource before confirming an import. Keep a separate copy of any data that must not be replaced. SSL and health checks [#ssl-and-health-checks] MySQL supports **Prefer**, **Require**, **Verify CA**, and **Verify Full**. The verification modes require the client to trust the Coolify CA certificate. See [Database SSL](/databases/ssl). Configure the Docker health check under **Healthcheck** and restart MySQL after saving. Official MySQL resources [#official-mysql-resources] * [MySQL documentation](https://dev.mysql.com/doc/) * [MySQL source](https://github.com/mysql/mysql-server) * [MySQL Docker image](https://hub.docker.com/_/mysql) * [MySQL `mysqldump` documentation](https://dev.mysql.com/doc/refman/8.4/en/mysqldump.html) # Danger Zone (/docs/databases/operations/danger-zone) Delete a database [#delete-a-database] Open the database and select **Danger Zone** to permanently remove the database resource. Deletion cannot be undone from Coolify. Deleting a database can remove its containers, configuration, volumes, and network resources. Take a verified database backup and record the connection settings before continuing. A persistent volume is not a substitute for a backup. Before deletion [#before-deletion] * Confirm that no application still needs the database. * Export or back up all required databases and test the restore path. * Record the database image, credentials, storage mounts, environment variables, ports, SSL settings, and backup settings if you may recreate it. * Confirm that you have permission to delete the resource. * Check the optional deletion actions in the confirmation dialog rather than accepting them automatically. Deletion actions [#deletion-actions] The confirmation dialog can select these actions. They are selected by default in the current interface: | Action | Effect | | :-------------------------------------------------------------------------------- | :------------------------------------------------------------------------------ | | **Permanently delete all volumes associated with this resource.** | Deletes the database's Docker volumes and their stored data. | | **Permanently delete all non-predefined networks associated with this resource.** | Deletes non-predefined Docker networks associated with the resource. | | **Permanently delete all configuration files from the server.** | Deletes Coolify-generated configuration files for the resource from the server. | | **Run Docker Cleanup (remove unused images and builder cache).** | Runs Docker cleanup on the resource's server after deletion. | Clear **volumes** only when you deliberately want to preserve the volume for a separate recovery or manual cleanup process. Keeping a volume does not keep the Coolify database resource or make the data available to a newly created resource automatically. Confirm deletion [#confirm-deletion] Select **Delete** in the confirmation dialog. Depending on the instance's confirmation settings, Coolify asks you to enter the exact database name and your Coolify account password. Coolify removes the resource record and queues cleanup of the selected Docker resources. The database may remain visible briefly while the deletion job finishes. Do not recreate a database with the same storage or public port until you have confirmed that the old resource and its containers are gone. After deletion [#after-deletion] 1. Confirm that the database no longer appears in the project environment. 2. Confirm that its container is no longer running on the server. 3. Remove or update application connection variables and public DNS or firewall rules that pointed to it. 4. If you recreate the database, use a supported image and restore the verified backup before reconnecting applications. Coolify does not manage DNS records at your DNS provider. Remove obsolete DNS records separately. When the server is unreachable, resource deletion warns that Docker resources remain on the server. The team is notified afterwards. Clean those resources up when server access returns. # Overview (/docs/databases/operations/overview) Operate databases [#operate-databases] After a database is deployed, Coolify provides separate views for configuration, backups, logs, terminal access, and runtime metrics. Use the page that matches the task you need to perform. Know where to look [#know-where-to-look] | Page | Use it to | | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **General** | Change the image, credentials, engine settings, and networking. Storage, health checks, environment variables, and resource limits have separate sidebar pages. | | **Backups** | Schedule and inspect engine-specific backups for PostgreSQL, MySQL, MariaDB, MongoDB, and ClickHouse. | | **Runtime Logs** | Read output from the database container. | | **Terminal** | Run a command inside the running database container when your team and server allow terminal access. | | **Metrics** | View CPU and memory usage when Sentinel & Metrics is enabled on the server and the container is running. | | **Resource Operations** | Clone the database to another server or destination, or move it to another project or environment. | | **Danger Zone** | Delete the database resource and optionally remove related Docker resources. | Redis, Dragonfly, and KeyDB do not show the **Backups** page because Coolify does not provide their standalone scheduled database backup workflow. Their persistent volumes still protect data during normal container replacement; persistent storage is not a backup. Choose a lifecycle action [#choose-a-lifecycle-action] The database header shows actions based on its current status: | Action | What it does | | :---------- | :------------------------------------------------------------------------------------------------------------------------------- | | **Start** | Starts a stopped database container. | | **Restart** | Restarts the database. The database is unavailable during the restart. | | **Stop** | Stops the database and removes non-persistent container data. The resource and persistent data remain so you can start it again. | Stop or restart a database only when clients can tolerate the interruption. A write in progress or a client that does not retry can fail while the database is unavailable. Use the deployment controls on the resource page when you first deploy a database or apply a configuration that requires a new deployment. After changing SSL, health checks, storage, ports, images, or engine settings, follow the page's status and activity messages and verify that the database is running before reconnecting applications. Protect database state [#protect-database-state] A persistent volume keeps database files across normal container replacement. It does not protect against deleting the volume, disk failure, corruption, or losing the server. Configure an engine-specific backup for supported engines and test a restore before relying on it. Keep at least one verified backup outside the database server. For Redis, Dragonfly, and KeyDB, use the engine's own persistence or backup tooling, a Compose service, or an external backup solution because the standalone Coolify backup workflow is not available. Continue operating the database [#continue-operating-the-database] Resource action buttons [#resource-action-buttons] The primary resource action is a one-click button. Use the adjacent dropdown for secondary actions. Confirm destructive actions in the Coolify modal and review the listed effects before continuing. Follow a running operation [#follow-a-running-operation] Use **Deploying… View log** to reopen a running deployment or startup log. Selecting Deploy, Start, or Restart while an operation runs reopens its log. The running-deployments indicator appears in the sidebar, in the top bar on mobile, and on the dashboard. The container log viewer separates **Time**, **Type**, and **Message**. Expand a row to view pretty-printed JSON. If containers cannot be loaded, read the displayed error instead of treating it as proof that none are running. Viewing container logs requires permission to update the resource. API log requests require `read:sensitive` or `root`. # Resource Operations (/docs/databases/operations/resource-operations) Clone or move a database [#clone-or-move-a-database] Open a database and select **Resource Operations**. This page provides these actions: * **Clone to another destination** creates a second database resource on another server or network destination. * **Clone to another environment** copies the configuration into another project environment on the same server and network. * **Move Resource** changes the project and environment of the existing database on the same Coolify instance. These placement actions do not migrate database contents. A clone starts with a separate persistent volume, and a move changes organization without copying data. Clone a database when you need the same configuration on another server or network destination. Coolify copies the database configuration, environment variables, storage definitions, scheduled backup configuration, and tags. It does not copy the contents of the database volume or other stored files. A clone is not a backup or a replica. Prepare the destination [#prepare-the-destination] Confirm that the target server can host resources and has the network destination that the clone should use. Build servers cannot host running database resources. Select the destination [#select-the-destination] Open **Resource Operations**. Under **Clone to another destination**, choose **Server**, then **Network destination**. Clone and review [#clone-and-review] Select **Clone Resource**. The clone is created stopped. Review its generated name, image, credentials, internal and public connection details, storage mounts, environment variables, backup settings, ports, SSL settings, and tags before starting it. Give the clone a distinct domain or port mapping. Do not point production applications at it until you have restored or copied the required data and tested the connection. Clone into another environment [#clone-into-another-environment] Under **Clone to another environment**, select **Project** and **Environment**, then select **Clone resource**. Review the stopped clone and restore any required data before starting it. Move a database when it should belong to another project or environment on the same Coolify instance. Moving does not change the database's server, network destination, configuration, or persistent volume. The running database is not stopped and its data is not copied. To run a second copy on another server, use **Clone Resource** and then restore or copy the data separately. Choose the target project [#choose-the-target-project] Open **Resource Operations**. Under **Move Resource**, choose **Project**. Choose the target environment [#choose-the-target-environment] Choose **Environment**. Coolify excludes the database's current environment. Select an environment in the current project or another project. Move and verify [#move-and-verify] Select **Move Resource**. Coolify changes the database's project and environment without stopping the running resource. Open the database from its new location and verify its status, internal URL, backups, webhooks, and related application references. # PostgreSQL (/docs/databases/postgresql) PostgreSQL [#postgresql] Coolify deploys PostgreSQL as a standalone container on the selected server and destination. A new resource gets a generated password, a persistent data volume, an internal connection URL, and a health check. PostgreSQL is an object-relational database for transactional workloads, relational data, and extensions. Create a PostgreSQL database [#create-a-postgresql-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select PostgreSQL [#select-postgresql] Under **Databases**, select **PostgreSQL**. You can also search for **PostgreSQL** by name. Select a server [#select-a-server] Select the server that should run PostgreSQL. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that PostgreSQL should join. Select a PostgreSQL type [#select-a-postgresql-type] Choose the PostgreSQL image that matches your required major version and extensions. Use the standard PostgreSQL option unless the database needs an offered extension image. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, username, generated password, initial database, and connection URLs. Keep the default private networking unless an external client requires access. Start PostgreSQL [#start-postgresql] Select **Start** and follow the startup output. Wait until PostgreSQL is running and healthy, then copy the **Postgres URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :---------------------- | :---------------------------------------------------------------------------------------------------- | | Internal port | `5432` | | Default image selection | PostgreSQL 18 (`postgres:18-alpine`) | | Username | `postgres` | | Initial database | `postgres` | | Data mount | PostgreSQL 17 and earlier: `/var/lib/postgresql/data`; PostgreSQL 18 and later: `/var/lib/postgresql` | | Scheduled backups | Supported | | SSL | Supported with PostgreSQL SSL modes | Coolify's PostgreSQL selector includes PostgreSQL 18, 17, and 16 images, plus Supabase PostgreSQL, PostGIS, and PGVector extension images. Select the image that matches the extensions, architecture, and major version your application requires. The password is generated when the resource is created. If you change the username, password, or initial database in the running database outside Coolify, update the matching values in **General** so connection URLs and automated backups continue to work. Connect to PostgreSQL [#connect-to-postgresql] Use the **Postgres URL (internal)** for an application on the same Coolify destination network: ```sh postgres://:@:5432/ ``` When **Public access > Access** is **Public through TCP proxy**, Coolify also shows a **Postgres URL (public)** using the server address and **Public port**. Do not expose port `5432` unless an external client requires it; prefer private networking for application connections. Read [Databases](/databases) for port mappings, the public TCP proxy, and firewall considerations. Configure PostgreSQL [#configure-postgresql] Open **General**, then use the section that matches the setting you need to change. Resource details [#resource-details] Use **Name** and **Description** to identify the resource in Coolify. **Image** controls the PostgreSQL image used when Coolify creates the container. Database credentials [#database-credentials] **Username**, **Password**, and **Initial database** determine the generated connection URLs and the values used by Coolify's database operations. If you change the corresponding values inside PostgreSQL, keep the fields in Coolify synchronized. Initial database options [#initial-database-options] **Initial database arguments** passes arguments to PostgreSQL initialization. **Host authentication method** controls the authentication method used by the image while it initializes a new data directory. These settings do not reinitialize an existing persistent data directory. Initialization scripts [#initialization-scripts] Add a filename and content under **Initialization scripts**. Coolify mounts the scripts under `/docker-entrypoint-initdb.d/`. The PostgreSQL image runs these scripts only when it initializes an empty data directory. Adding or editing a script does not run it against an existing database. Custom PostgreSQL configuration [#custom-postgresql-configuration] Use **Custom PostgreSQL configuration** to provide the `postgresql.conf` content used by the container. Coolify mounts the generated file and adds `listen_addresses = '*'` when the configuration does not define it. Review every directive against the selected PostgreSQL image before applying it. An invalid directive can prevent PostgreSQL from starting. Network access [#network-access] Use **Port mappings** for direct Docker host-to-container mappings. Under **Public access**, set **Public port** and **Proxy timeout**, then choose **Public through TCP proxy** in **Access** to use Coolify's separate TCP proxy. Keep PostgreSQL private unless an external client requires direct access. Read [Network access](/databases#network-access) before publishing a database port. Docker options [#docker-options] Use **Custom Docker options** only for supported Docker run options that are not represented by another field. Invalid or conflicting options can prevent the container from starting. Changing the image, port mapping, configuration, or health check marks the resource as changed. Restart the database to recreate the container with the new generated Compose configuration. Back up and restore PostgreSQL [#back-up-and-restore-postgresql] Coolify's scheduled backup job uses `pg_dump` in custom format for selected databases: ```sh pg_dump --format=custom --no-acl --no-owner ``` When **Database selection** is **All databases**, Coolify uses `pg_dumpall` and stores a gzip-compressed dump. Configure the schedule, retention, and S3 destination in [Database backups](/databases/backups). Follow [Restore a database](/databases/restore) for the built-in PostgreSQL import workflow. The built-in **Import Backup** form accepts PostgreSQL backups while the database is running. Coolify detects the dump format and generates the appropriate restore command using `pg_restore` or `psql`. Review the read-only **Import command** before starting the restore. A custom-format dump is not a plain `.sql` file. Use `pg_restore` for a custom-format file and `psql` for plain SQL. Review the command before restoring because the restore replaces data in the target database. SSL and health checks [#ssl-and-health-checks] PostgreSQL supports `allow`, `prefer`, `require`, `verify-ca`, and `verify-full`. The last two modes require the client to trust the Coolify CA certificate. See [Database SSL](/databases/ssl). The default health check runs inside the PostgreSQL container. Configure its interval, timeout, retries, and start period under **Healthcheck**, then restart PostgreSQL to apply changes. Official PostgreSQL resources [#official-postgresql-resources] * [PostgreSQL documentation](https://www.postgresql.org/docs/) * [PostgreSQL source](https://github.com/postgres/postgres) * [PostgreSQL Docker image](https://hub.docker.com/_/postgres) * [PostgreSQL `pg_dump` documentation](https://www.postgresql.org/docs/current/app-pgdump.html) # Redis (/docs/databases/redis) Redis [#redis] Coolify deploys Redis as a standalone in-memory datastore on the selected server and destination. A new resource gets a generated password, a persistent volume at `/data`, an internal connection URL, and a health check. Redis is a key-value datastore commonly used for caching, queues, streams, and short-lived application state. Create a Redis database [#create-a-redis-database] Open New Resource [#open-new-resource] Open the project and environment where the database should live, then select **New Resource**. Select Redis [#select-redis] Under **Databases**, select **Redis**. You can also search for **Redis** by name. Select a server [#select-a-server] Select the server that should run Redis. Build servers cannot be selected because they do not host running database resources. Select a destination [#select-a-destination] Select the Docker network destination that Redis should join. Review the generated configuration [#review-the-generated-configuration] Coolify creates the resource and opens **General**. Review the image, username, generated password, SSL settings, and connection URLs. Keep the default private networking unless an external client requires access. Start Redis [#start-redis] Select **Start** and follow the startup output. Wait until Redis is running and healthy, then copy the **Redis URL (internal)** into applications on the same destination network. Default configuration [#default-configuration] | Setting | Default or behavior | | :------------------------- | :----------------------- | | Internal port | `6379`; TLS uses `6380` | | Default image | `redis:7.2` | | Username | `default` | | Data mount | `/data` | | Scheduled database backups | Not supported by Coolify | | SSL | Supported with **SSL** | Coolify stores the Redis username and password as runtime environment variables. If you change `REDIS_USERNAME` or `REDIS_PASSWORD` in Redis or under **Environment Variables**, keep the values synchronized with the credentials shown in the resource configuration. Connect to Redis [#connect-to-redis] Use the **Redis URL (internal)** for an application on the same Coolify destination network: ```sh redis://:@:6379/0 ``` When SSL is enabled, Coolify uses the `rediss` scheme and TLS port `6380`. When **Public access > Access** is **Public through TCP proxy**, copy the generated **Redis URL (public)** instead of changing the host manually. Configure Redis [#configure-redis] Open **General** to change the image, credentials, **Port mappings**, public proxy, **Custom Redis configuration**, and supported custom Docker options. When **Custom Redis configuration** is set, Coolify writes it as the Redis configuration file and starts Redis with that file. Include persistence and authentication directives you need; Coolify adds the password only when the file does not already define `requirepass`. Open **Persistent Storage** to manage the `/data` volume. Persistent storage keeps Redis data across container recreation, but it is not a scheduled backup. Backups and persistence [#backups-and-persistence] Redis, Dragonfly, and KeyDB do not support Coolify's scheduled database backup page. Configure persistence and use Redis-compatible snapshot or append-only-file tools when you need recovery copies. Test the restore workflow separately from the running resource. SSL and health checks [#ssl-and-health-checks] Redis exposes **SSL** without an SSL mode selector. The generated TLS URL uses the `rediss` scheme and port `6380`; configure CA verification in the client library when required. See [Database SSL](/databases/ssl) before connecting an application with TLS. Configure the Docker health check under **Healthcheck** and restart Redis after saving. Official Redis resources [#official-redis-resources] * [Redis documentation](https://redis.io/docs/) * [Redis source](https://github.com/redis/redis) * [Redis Docker image](https://hub.docker.com/_/redis) # Restore a Database (/docs/databases/restore) Restore a database [#restore-a-database] Open a running database's **Import Backup** page to restore a backup from your computer, the database server, or S3 storage. Imports are also available for supported database components inside a service stack. Stop application writes and take a separate backup of the target before importing. Review the selected database, backup format, generated script, and replacement options. An import can overwrite data and credentials. Supported backups [#supported-backups] | Database | Supported restore inputs and options | | :---------------------------------- | :---------------------------------------------------------------------------------- | | PostgreSQL | SQL dumps, custom archives, tar archives, and all-database dumps. | | MySQL and MariaDB | SQL dumps, including all-database backups; optional user and privilege restoration. | | MongoDB | Archives and dump directories. | | SQLite | Database files; choose the target file under **Restore into**. | | Redis, Dragonfly, KeyDB, ClickHouse | No built-in Import Backup workflow; use an engine-specific restore process. | Coolify detects formats before changing data and supports gzip, bz2, xz, and zip compression as well as supported archives. Ensure the backup matches the target engine and version, and that the server has enough free space. Review restore options [#review-restore-options] The **Import command** shows the exact generated restore script and is read-only. Choose **Backup contents** for a selected-database or all-database dump as appropriate. * **Replace objects that already exist** is off by default for single-database PostgreSQL imports. Enable it to request the previous clean/replace behavior. Existing objects can otherwise make an import fail. * **Keep owners and privileges** is off by default for PostgreSQL archives. Enable it only when the destination has the required roles and you intend to restore ownership and grants. * **Restore users and privileges (mysql system database)** applies to all-database MySQL/MariaDB imports. It can replace users and passwords, including administrative credentials. Coolify's saved credentials and health checks may then need updating. * **Restore into** selects a configured SQLite file. Coolify preselects the file identified by the backup name when possible. * MongoDB offers **Replace collections that already exist** for replacing existing collections. PostgreSQL restores run in one transaction. Replace restores of SQL backups swap in the new database only after success. Format detection occurs before destructive changes; keep a verified backup for recovery regardless of these safeguards. Select and import a backup [#select-and-import-a-backup] 1. Open **Import Backup** on the running target database. 2. Select a source: * Upload a backup from your computer. * Enter the backup's absolute server path and select **Check file**. * Select available team **S3 storage**, enter the file path within the bucket, and check the file. 3. Review file information, backup contents, restore options, and the generated import command. 4. Start the restore and complete its confirmation. 5. Follow **Database Restore Output** until the operation finishes. Coolify uses the selected source; an earlier unused upload does not replace a checked server path. A second start, restart, or import is rejected while an import runs. Interrupted or stale imports are stopped and cleaned up so they do not indefinitely block later operations. Import through the API [#import-through-the-api] For a standalone database, use: | Endpoint | Purpose | | :-------------------------------------------- | :---------------------------------------- | | `POST /databases/{uuid}/imports/uploads` | Upload a backup. | | `POST /databases/{uuid}/imports` | Start an import from the selected source. | | `GET /databases/{uuid}/imports/{activity_id}` | Read import progress and result. | For a service database, the same suffixes are under `/services/{uuid}/databases/{database_uuid}/imports`. Uploading and starting an import require `write`. A server-path import also requires `deploy`. Options include `replace_existing`, `keep_owners`, `restore_mysql_users`, and `sqlite_database`. Concurrent database operations return `409`; invalid requests return `422`. Use the [API reference](/api/overview) for source fields and upload formats. Example: import a server file [#example-import-a-server-file] After stopping application writes and backing up the target, start an import using the backup's absolute path on the database server: ```sh curl --request POST "https://coolify.example.com/api/v1/databases//imports" \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Content-Type: application/json" \ --data '{"source":"server","path":"/var/backups/database.sql.gz","dump_all":false,"replace_existing":false}' ``` Use a token with the required `write` and `deploy` abilities. Poll the activity endpoint with the returned activity ID and verify the result before resuming writes. Upload imports use `source: "upload"` and `upload_id`; S3 imports use `source: "s3"`, `s3_storage_uuid`, and `path`. Verify the result [#verify-the-result] 1. Confirm the database is running and healthy and review its logs. 2. Connect with a database client and check schemas, tables or collections, and representative records. 3. For SQLite, verify the application reads the intended mounted file. 4. Update credentials if the import restored users or passwords. 5. Reconnect application writes after validation and create a new [backup](/databases/backups). # SQLite (/docs/databases/sqlite) SQLite [#sqlite] SQLite support is experimental. Coolify runs a standalone database resource using a `peakimages/sqlite` image and persistent data volume. Applications access database files through a volume mount rather than a network connection URL. Create the database [#create-the-database] 1. In a project environment, select **New Resource > Databases > SQLite**. 2. Select the server and destination. 3. Review the image and **File names** under **General**. 4. Start the database to create its files and volume. Connect an application [#connect-an-application] Under the database's **General > Connect application** section, select an application on the same server, choose the container **Mount path**, and select **Mount volume**. Configure the application to open the database file at that path and redeploy it. The application must run as user `65532` or root to access the files. For a Docker Compose application, Coolify shows the volume lines to add to the service that uses SQLite. Copy them into the application's Compose file and redeploy. Start the SQLite database first because Compose does not create the external volume. Coolify protects connected volumes. Use **Unlink** to remove a managed application connection; for Compose connections, remove the volume reference from the Compose file. Review application configuration before unlinking so it does not continue writing to an unintended local file. Backups and recovery [#backups-and-recovery] SQLite supports manual and scheduled [database backups](/databases/backups). Use [Import Backup](/databases/restore) to restore a backup and choose the database file under **Restore into**. Stop application writes before replacing a file and verify the application after recovery. # Database SSL (/docs/databases/ssl) Database SSL [#database-ssl] Coolify can generate a server certificate for supported standalone databases and add the certificate to the database container. For engines that expose SSL connection parameters, the **General** page also includes those parameters in the generated internal and public connection URLs. SSL settings are changed from the database's **General** page. Stop the database before changing **SSL** or **SSL mode**, then restart it after saving so the generated certificate and connection port are applied. Applications use SSL only when their connection configuration enables it. Copy the new **Internal URL** or **Public URL** after enabling SSL and update the application that connects to the database. Enable SSL [#enable-ssl] 1. Stop the database. 2. Open **General**. 3. Under **SSL configuration**, set **SSL** to **Enabled**. 4. Choose an **SSL mode** when the database provides that field. 5. Select **Save changes** if other configuration changed, then restart the database. Coolify creates a database certificate signed by the CA certificate for the database's server. If no server CA certificate exists, Coolify attempts to generate one. The certificate status and expiration date appear on the database's General page. To regenerate a database certificate, use **Regenerate SSL Certificates** on the General page, then restart the database. PostgreSQL, MySQL, MariaDB, Redis, KeyDB, and Dragonfly use separate `server.crt` and `server.key` files. New and regenerated certificates use a P-256 key, including for compatibility with Electron-based clients such as MongoDB Compass. The CA file on the server matches the signing CA. A regenerated certificate can require the connecting application to trust the server CA again. SSL modes [#ssl-modes] PostgreSQL exposes these modes. The default is `require`. | Mode | Behavior | | :------------ | :---------------------------------------------------------------------- | | `allow` | Allows an unencrypted connection and does not require SSL. | | `prefer` | Tries SSL first, then can fall back to an unencrypted connection. | | `require` | Requires encryption but does not verify the server certificate. | | `verify-ca` | Requires encryption and verifies the certificate authority. | | `verify-full` | Requires encryption, verifies the CA, and verifies the server hostname. | Use `verify-ca` or `verify-full` only when the client container trusts the Coolify CA certificate. MySQL exposes **Prefer**, **Require**, **Verify CA**, and **Verify Full**. The default is **Require**. Coolify writes these values to the connection URL as `ssl-mode` options. **Verify CA** and **Verify Full** also require the client to trust the Coolify CA certificate. MongoDB exposes `allow`, `prefer`, `require`, and `verify-full`. The default is `require`, and **SSL** is **Enabled** by default for newly created MongoDB resources. The generated MongoDB URL uses `/etc/mongo/certs/ca.pem` for the CA and adds `/etc/mongo/certs/server.pem` for `verify-full`. If the consuming application runs in another container, mount or configure the client certificate paths expected by its MongoDB driver instead of assuming that paths inside the database container are available to the application. These databases expose an **SSL** dropdown but no SSL mode selector in the Coolify interface. Coolify configures the database's TLS listener. Redis, Dragonfly, and KeyDB generated URLs use the `rediss` scheme and TLS port `6380`; configure the MariaDB client with its SSL options when connecting. ClickHouse does not expose SSL controls in the standalone database interface. Trust the Coolify CA certificate [#trust-the-coolify-ca-certificate] When the connection URL requires certificate verification, mount the server CA certificate into the application container that connects to the database. The common mount used by Coolify clients is: ```sh /data/coolify/ssl/coolify-ca.crt:/etc/ssl/certs/coolify-ca.crt:ro ``` The path on the left is on the database server. The path on the right is inside the application container. Configure the application or Compose service to trust `/etc/ssl/certs/coolify-ca.crt` using the client library's CA option. Redis, Dragonfly, and KeyDB do not expose a normal SSL mode selector. Their generated URLs use `rediss` and port `6380`; configure CA verification in the client library when required. The generated URL does not add a CA parameter for these engines. For a Compose application, define the mount on the service that opens the database connection, not only on the database service. Verify the connection [#verify-the-connection] After restarting the database: 1. Copy the updated connection URL from the database's **General** page. 2. Confirm the client container contains the CA file when using certificate verification. 3. Run the application's database connection check or a simple query. 4. Open the database logs if the connection fails. A URL that still uses the old non-SSL parameters can connect without SSL or fail, depending on the engine and client. Update the consuming application configuration rather than editing only the database resource. Server CA management [#server-ca-management] Open the server's advanced CA certificate settings to view or regenerate the server CA certificate. Regenerating a server CA can invalidate certificates signed by the previous CA; restart affected databases and update clients that trust the CA before using the new certificate. # What is a database (/docs/databases/what-is-a-database) What is a database [#what-is-a-database] A database stores and organizes data for an application. In Coolify, a standalone database is a database engine that Coolify deploys and manages as a Docker container on a selected server and destination. Coolify currently provides one-click resources for PostgreSQL, MySQL, MariaDB, MongoDB, Redis, Dragonfly, KeyDB, and ClickHouse. What is a one-click database? [#what-is-a-one-click-database] A one-click database is a standalone database resource that Coolify creates from the **New Resource > Databases** list. You choose a supported engine, and Coolify creates the database resource with an engine-specific image, generated credentials, connection details, persistent storage, and the configuration needed to deploy it. One-click means that Coolify supplies the initial resource configuration. It does not mean that the database is a managed cluster or that Coolify provides replication, automatic failover, or a multi-node topology. The result is one database resource that runs as a Docker container on the server and destination you select. Read [How databases work](/databases/how-databases-work#how-a-one-click-database-works-in-coolify) for the creation and deployment lifecycle. Use a [Service](/services) instead when you need a Docker Compose topology, multiple database containers, an unsupported engine, or configuration that the one-click database form does not expose. What a database resource includes [#what-a-database-resource-includes] When Coolify creates a one-click database, it creates and stores: | Part | Purpose | | :--------------------------- | :---------------------------------------------------------------------------------------------------------------- | | Database container | Runs the selected database engine on the server and destination you choose. | | Generated credentials | Provides the initial username, password, and database name used by the connection details. | | Persistent storage | Keeps database files outside the replaceable container. | | Internal URL | Gives applications on the same destination network a connection string. | | Configuration and operations | Lets you manage networking, health checks, backups where supported, logs, terminal access, and lifecycle actions. | The exact connection format, storage path, SSL behavior, and backup support depend on the database engine. Read the engine guide before changing a production database. Standalone databases and applications [#standalone-databases-and-applications] An application uses a database; it does not contain the database's data. Keep the resources separate so you can deploy the application without replacing the database container. For an application on the same Coolify destination, use the database's **Internal URL**. Coolify uses the database container name and internal port in that URL. Do not replace the container name with a server IP for an internal connection. If a client runs outside the destination network, configure [network access](/databases#network-access) only when necessary. A public database endpoint exposes a database protocol, so restrict the port with your firewall and enable SSL when the engine supports it. What a standalone database is not [#what-a-standalone-database-is-not] A standalone database is not an application and is not a managed database service. Coolify manages the resource configuration and container lifecycle, but the database engine is still responsible for its own data integrity, replication, clustering, and upgrade procedures. The persistent volume protects data during normal container replacement. It does not protect against volume deletion, disk failure, corruption, or server loss. Configure [database backups](/databases/backups) for supported engines and test [restoring one](/databases/restore) before relying on it. Continue learning [#continue-learning] SQLite is also available as an experimental standalone database. Applications on the same server mount its data volume to access database files. See [SQLite](/databases/sqlite). # Deploy your first app (/docs/deploy-your-first-app) Deploy your first app [#deploy-your-first-app] Deploying your first app in Coolify is the quickest way to confirm your setup is working end-to-end. In this guide, you will deploy an **Nginx** app using the **Docker Image** option. You will create a project, create a Docker Image resource, use `nginx:alpine`, expose port `80`, deploy it, and open the generated application URL. This path is ideal for a first deployment because you do not need a Git repository or build configuration. *** Before you start [#before-you-start] Make sure these things are ready before you deploy the app. If Coolify is not ready yet, first follow [Start with Self-hosted](/start-with-self-hosted) or [Start with Coolify Cloud](/start-with-cloud). *** Deployment overview [#deployment-overview]
Coolify deploys applications as containers. A container packages the app with what it needs to run, so Coolify can start it, stop it, restart it, and route traffic to it. In this guide, `nginx:alpine` is the container image Coolify will run. *** Deploy your first nginx app [#deploy-your-first-nginx-app] Choose the deployment method you want to use. Each tab reaches the same first-deployment outcome. Create your first project [#create-your-first-project] On the Coolify dashboard: * click **New Project** * enter a project name, for example `my-first-project` * click **Continue** If you already have a project, skip this step and continue to Step 2. Create a new resource [#create-a-new-resource] Open your project and click **Create New Resource**. A resource is something Coolify will run for you, such as an app, database, or service. In this guide, the resource will be a small Nginx app. Choose deployment type [#choose-deployment-type] From the deployment options, choose **Docker Image**. Choose this option because the app already exists as a ready-to-run container image. Coolify only needs to pull the image and start it. Enter the image reference [#enter-the-image-reference] In the image field, enter: ```js nginx:alpine ``` Then continue to the configuration screen. This image starts a simple web server that shows the default Nginx welcome page. That makes it a safe first deployment test. Configure network settings [#configure-network-settings] Set: * **Ports Exposes**: `80` Nginx listens on port `80`, so Coolify needs to know that it should send web traffic to port `80` inside the app. By default, Coolify generates a testing domain like `http://..sslip.io`. For your first deployment test, using the generated `sslip.io` domain is the fastest path. Deploy [#deploy] Click the **Deploy** button. During deployment, Coolify will: * pull `nginx:alpine` * create and start the container * connect it to the proxy so the generated URL can reach it Wait until the deployment finishes before opening the app link. Visit application link [#visit-application-link] After deployment completes: * open the application URL shown in Coolify * confirm that the default Nginx welcome page loads If you can see the default Nginx welcome page in your browser, your first Coolify application deployment worked. Create a `root` API token for this tutorial. Coolify Cloud already has API access enabled, so Cloud users only need to create the token. On self-hosted Coolify, an administrator must also [enable API access](/api/ip-allowlist#api-access-controls). See [API authorization](/api/authorization) before sending these requests. Set your base URL and token in the terminal where you will run cURL: ```sh export COOLIFY_URL="https://" export COOLIFY_TOKEN="" ``` Coolify Cloud users should set `COOLIFY_URL` to `https://app.coolify.io`. This tutorial uses a `root` token so the same credential works across every read, write, deployment, and sensitive-data request. A `root` token has more access than most integrations need. For production, create a separate token with only the permissions required by that workflow, and revoke the tutorial token when you finish. Create a project and find a server [#create-a-project-and-find-a-server] Create the project: ```sh curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data '{"name":"my-first-project"}' \ "$COOLIFY_URL/api/v1/projects" ``` Copy the `uuid` from the response and set it as `PROJECT_UUID`. Then list your servers and copy the UUID of the server that will run Nginx: ```sh export PROJECT_UUID="" curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/servers" export SERVER_UUID="" ``` If you already have a project, use `GET /api/v1/projects` instead of creating another one. Create and deploy the application [#create-and-deploy-the-application] Create the Docker Image application in the project's `production` environment. `instant_deploy` queues the first deployment, while `autogenerate_domain` gives the application a test URL: ```sh curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data "{"project_uuid":"$PROJECT_UUID","server_uuid":"$SERVER_UUID","environment_name":"production","docker_registry_image_name":"nginx","docker_registry_image_tag":"alpine","ports_exposes":"80","name":"my-first-nginx","autogenerate_domain":true,"instant_deploy":true}" \ "$COOLIFY_URL/api/v1/applications/dockerimage" ``` Copy the returned application `uuid`: ```sh export APPLICATION_UUID="" ``` Verify the application [#verify-the-application] Read the application until its status is `running`: ```sh curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/applications/$APPLICATION_UUID" ``` Open the domain returned for the application. The default Nginx welcome page confirms the deployment worked. See the [API reference](/api/overview) for response schemas and error handling. [Install the Coolify CLI](/cli/installation), then create a `root` API token for the team that will own the resource. **Coolify Cloud:** API access is already enabled. Save the token in the preconfigured `cloud` context, select it, and verify authentication: ```sh coolify context set-token cloud coolify context use cloud coolify context verify ``` **Self-hosted Coolify:** An administrator must [enable API access](/api/ip-allowlist#api-access-controls) first. Add a context using the full instance URL without `/api/v1`, then verify authentication: ```sh coolify context add --default production https://coolify.example.com coolify context verify ``` A successful verification reports that the connection and authentication are valid. See [CLI authentication](/cli/authentication) for token safety, IP allowlists, and troubleshooting. This tutorial uses a `root` token so the same credential works across every read, write, deployment, and sensitive-data request. A `root` token has more access than most integrations need. For production, create a separate token with only the permissions required by that workflow, and revoke the tutorial token when you finish. Create a project and find a server [#create-a-project-and-find-a-server-1] ```sh coolify project create --name my-first-project coolify server list ``` Copy the project and server UUIDs from the output. If the project already exists, run `coolify project list` instead. Create and deploy the application [#create-and-deploy-the-application-1] ```sh coolify app create dockerimage \ --project-uuid \ --server-uuid \ --environment-name production \ --name my-first-nginx \ --docker-registry-image-name nginx \ --docker-registry-image-tag alpine \ --ports-exposes 80 \ --instant-deploy ``` Copy the application UUID from the response. Verify the application [#verify-the-application-1] ```sh coolify app get coolify app logs --lines 100 ``` Wait for the application status to become `running`, then open its generated domain. For every available flag, see [`coolify app create dockerimage`](/cli/command-reference/commands/app/create-dockerimage). Coolify MCP can inspect and start existing resources, but its current tools cannot create applications, databases, services, or projects. Create the resource with the Dashboard, API, or CLI tab first. You can then use the prompts below to start and verify it without returning to the dashboard. After [setting up Coolify MCP](/mcp/setup), create a `root` token for this end-to-end workflow, then give your MCP client the application UUID or its exact name. The prompts need to inspect the application, start it, and inspect it again. A `deploy` token cannot perform the read operations because selecting `deploy` creates a deploy-only token. A `root` token bypasses the `read`, `write`, and `deploy` endpoint checks and can return supported sensitive data. It remains limited to the active team, but it grants more access than routine MCP use requires. Revoke it when you finish this first deployment. Find the application [#find-the-application] ```txt Find the application named my-first-nginx in my-first-project. Show me its UUID, current status, and domain. Do not change anything yet. ``` Confirm that the returned application is the one you created. Start and verify the application [#start-and-verify-the-application] ```txt Start the Coolify application with UUID . Then check its status and tell me when it is running. Show me the domain I should open, and do not stop or restart any other resource. ``` Open the returned domain and confirm that the default Nginx welcome page loads. The client uses the MCP `control` tool to start the resource and application inspection tools to verify it. *** Common first-deploy issues [#common-first-deploy-issues] Use these checks when the deployment finishes but the application link does not behave as expected. Usually caused by wrong port settings. Check: * **Ports Exposes** is set to `80` * the image is `nginx:alpine` Usually means the server or proxy is not reachable from your browser. Check: * Coolify proxy says **Proxy is running** * your server firewall allows ports `80` and `443` * if using your own domain, DNS points to your server IP address Browsers show a site-not-secure warning when you open the app with `http://`. To make the warning go away, open the app with `https://`. For `https://` to work, Coolify needs a TLS certificate from Let's Encrypt. Let's Encrypt can rate-limit shared testing domains like `sslip.io`, so use a real domain. If you are using your own domain, make sure: * DNS is pointed correctly to your server IP * the domain is added in Coolify with `https://`, for example `https://shadowarcanist.com` * restart the app after changing the domain *** What to do next [#what-to-do-next] Your first app confirms that Coolify can create and run an application. From here, you can deploy a database, deploy a service, or learn how Git-based app builds work. # Deploy your first database (/docs/deploy-your-first-database) Deploy your first database [#deploy-your-first-database] Deploying your first database in Coolify helps you validate database creation, credentials, port mapping, and terminal access in a simple flow. In this guide, you will deploy **Redis** from the one-click database resources list. A one-click database is a standalone database resource that Coolify creates from its **New Resource > Databases** list. Coolify supplies the Redis image, generated credentials, persistent storage, network, and connection details so you can deploy it without writing a Docker Compose file. Create or open a project, create a Redis database resource, map a host port, deploy Redis, copy the generated password, and run `PING` from your terminal. This path is ideal for a first database deployment because Redis is lightweight and easy to test. *** Before you start [#before-you-start] Make sure these things are ready before you deploy the database. If Coolify is not ready yet, first follow [Start with Self-hosted](/start-with-self-hosted) or [Start with Coolify Cloud](/start-with-cloud). *** Deployment overview [#deployment-overview]
Coolify deploys databases as containers. For this guide, Coolify will create and run a Redis container, generate credentials, and keep the database data on the server. The Redis container listens on port `6379` internally. You will map a temporary host port so your terminal can connect to it for testing. *** Deploy your first Redis database [#deploy-your-first-redis-database] Choose the deployment method you want to use. Each tab reaches the same first-deployment outcome. Create your first project [#create-your-first-project] On the Coolify dashboard: * click **New Project** * enter a project name, for example `my-first-project` * click **Continue** If you already have a project, skip this step and continue to Step 2. Create a new resource [#create-a-new-resource] Open your project and click **Create New Resource**. A resource is something Coolify will run for you, such as an app, database, or service. In this guide, the resource will be a Redis database. Choose Redis from the database list [#choose-redis-from-the-database-list] In the resource list: * search for **Redis** * click **Redis** Coolify will create a Redis database resource with generated settings and credentials. Configure port mapping [#configure-port-mapping] Set a temporary port mapping so you can connect from your terminal. Example: ```txt 6380:6379 ``` Open the mapped host port on your firewall [#open-the-mapped-host-port-on-your-firewall] Port mapping publishes Redis on the server, but your firewall or cloud provider may still block incoming traffic. Open the mapped host port, for example TCP `6380`, wherever you manage firewall rules for the server running Redis. This is different for each provider and server setup, so check your provider firewall, security group, or server firewall configuration. For safer testing, allow the port only from your own IP address and close it again when you are done. For general guidance, see [Firewall](/core/infrastructure/servers/firewall). Exposing a database port publicly is risky in production. This guide maps a Redis port only so you can test the first deployment from your terminal. For real production workloads, keep databases private unless you have a specific reason and strict network controls. Start Redis [#start-redis] Click **Start**. After deployment, keep these values ready: * server IP address * mapped host port, for example `6380` * Redis password from the Coolify dashboard Connect to Redis from terminal [#connect-to-redis-from-terminal] Use `redis-cli` from your terminal: ```sh redis-cli --user default -h -p -a "" ``` Example: ```sh redis-cli --user default -h 203.0.113.10 -p 6380 -a "your-password" ``` Then run: ```sh PING ``` If everything is working, Redis returns: ```txt PONG ``` Run `redis-cli` from a temporary Redis container instead: ```sh docker run --rm -it redis:alpine redis-cli --user default -h -p -a "" PING ``` If the connection works, it returns `PONG`. Create a `root` API token for this tutorial. Coolify Cloud already has API access enabled, so Cloud users only need to create the token. On self-hosted Coolify, an administrator must also [enable API access](/api/ip-allowlist#api-access-controls). See [API authorization](/api/authorization) before sending these requests. Set your base URL and token in the terminal where you will run cURL: ```sh export COOLIFY_URL="https://" export COOLIFY_TOKEN="" ``` Coolify Cloud users should set `COOLIFY_URL` to `https://app.coolify.io`. This tutorial uses a `root` token so the same credential works across every read, write, deployment, and sensitive-data request. A `root` token has more access than most integrations need. For production, create a separate token with only the permissions required by that workflow, and revoke the tutorial token when you finish. Create a project and find a server [#create-a-project-and-find-a-server] Create a project, then copy its UUID: ```sh curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data '{"name":"my-first-project"}' \ "$COOLIFY_URL/api/v1/projects" export PROJECT_UUID="" ``` List servers, copy the target server UUID, and set it: ```sh curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/servers" export SERVER_UUID="" ``` Use `GET /api/v1/projects` instead if the project already exists. Create and start Redis [#create-and-start-redis] The following request publishes Redis on server port `6380`, generates a password when `redis_password` is omitted, and starts it immediately: ```sh curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data "{"project_uuid":"$PROJECT_UUID","server_uuid":"$SERVER_UUID","environment_name":"production","name":"my-first-redis","is_public":true,"public_port":6380,"instant_deploy":true}" \ "$COOLIFY_URL/api/v1/databases/redis" ``` Copy the database UUID from the response: ```sh export DATABASE_UUID="" ``` Allow TCP port `6380` from your own IP address in the server firewall before testing. Do not open the port to every source. Read the password and test Redis [#read-the-password-and-test-redis] The `root` token used by this tutorial allows the API response to include the password: ```sh curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/databases/$DATABASE_UUID" ``` Copy the Redis password, then run the same `redis-cli` test shown in the Dashboard tab. A `PONG` response confirms that Redis is reachable. [Install the Coolify CLI](/cli/installation), then create a `root` API token for the team that will own the resource. **Coolify Cloud:** API access is already enabled. Save the token in the preconfigured `cloud` context, select it, and verify authentication: ```sh coolify context set-token cloud coolify context use cloud coolify context verify ``` **Self-hosted Coolify:** An administrator must [enable API access](/api/ip-allowlist#api-access-controls) first. Add a context using the full instance URL without `/api/v1`, then verify authentication: ```sh coolify context add --default production https://coolify.example.com coolify context verify ``` A successful verification reports that the connection and authentication are valid. See [CLI authentication](/cli/authentication) for token safety, IP allowlists, and troubleshooting. This tutorial uses a `root` token so the same credential works across every read, write, deployment, and sensitive-data request. A `root` token has more access than most integrations need. For production, create a separate token with only the permissions required by that workflow, and revoke the tutorial token when you finish. Create a project and find a server [#create-a-project-and-find-a-server-1] ```sh coolify project create --name my-first-project coolify server list ``` Copy the project and server UUIDs. Use `coolify project list` if the project already exists. Create and start Redis [#create-and-start-redis-1] ```sh coolify database create redis \ --project-uuid \ --server-uuid \ --environment-name production \ --name my-first-redis \ --is-public \ --public-port 6380 \ --instant-deploy ``` Copy the database UUID from the response. Allow TCP port `6380` from your own IP address in the server firewall before testing. Read the connection details and test Redis [#read-the-connection-details-and-test-redis] ```sh coolify database get ``` Copy the generated password, then test the connection: ```sh redis-cli --user default -h -p 6380 -a "" PING ``` A `PONG` response confirms the deployment worked. See [`coolify database create`](/cli/command-reference/commands/database/create) for the other database types and options. Coolify MCP can inspect and start existing resources, but its current tools cannot create applications, databases, services, or projects. Create the resource with the Dashboard, API, or CLI tab first. You can then use the prompts below to start and verify it without returning to the dashboard. After [setting up Coolify MCP](/mcp/setup), create a `root` token for this end-to-end workflow, then give your client the Redis UUID or exact name. The prompts need to inspect Redis, start it, and read its sensitive connection values. A `deploy` token cannot perform read operations, and `read:sensitive` cannot start the database. A `root` token bypasses the `read`, `write`, and `deploy` endpoint checks and can return supported sensitive data. It remains limited to the active team, but it grants more access than routine MCP use requires. Revoke it when you finish this first deployment. Find Redis [#find-redis] ```txt Find the database named my-first-redis in my-first-project. Show me its UUID, type, current status, and public connection settings. Do not change anything yet. ``` Confirm that the returned database is the Redis resource you created. Start and verify Redis [#start-and-verify-redis] ```txt Start the Coolify database with UUID . Then check its status and tell me when it is running. Show the host, public port, and Redis password needed for a redis-cli PING test. Do not stop or restart any other resource. ``` Run the `redis-cli` command from the Dashboard or CLI tab. A `PONG` response verifies the deployment. Sensitive values remain redacted unless the MCP token has `read:sensitive`. *** Common first-deploy issues [#common-first-deploy-issues] Use these checks when Redis deploys but the terminal test does not behave as expected. Usually means Redis is not reachable on the host port you are using. Check: * Redis deployment is in **running** state * **Ports Mappings** uses the host port you are connecting to * your server firewall allows the mapped host port * you are using the server IP address, not the Redis container IP Usually means the password in your command does not match the Redis password in Coolify. Check: * copy the Redis password from the Coolify dashboard again * keep the password inside quotes if it contains special characters * remove accidental spaces before or after the password If your computer does not have `redis-cli`, use Docker to run it temporarily. ```sh docker run --rm -it redis:alpine redis-cli --user default -h -p -a "" PING ``` If Docker is not installed either, install Redis CLI locally or test from a machine that has it. *** What to do next [#what-to-do-next] Your first database confirms that Coolify can create a database, generate credentials, expose a test port, and accept a connection. For an experimental file-based database, follow [SQLite](/databases/sqlite). Its applications mount the database volume on the same server instead of using a network connection URL. # Deploy your first service (/docs/deploy-your-first-service) Deploy your first service [#deploy-your-first-service] Deploying your first service in Coolify helps you validate one-click resources, proxy routing, generated domains, and browser access in a simple flow. In this guide, you will deploy **Umami**, an open source analytics service, from the one-click service resources list. Create or open a project, create an Umami service resource, keep the service port in the URL configuration, deploy it, open the public URL, and sign in with the default credentials. This path is ideal for a first service deployment because Umami is ready-made, uses prebuilt Docker images, and gives you a clear browser check after deployment. *** Before you start [#before-you-start] Make sure these things are ready before you deploy the service. If Coolify is not ready yet, first follow [Start with Self-hosted](/start-with-self-hosted) or [Start with Coolify Cloud](/start-with-cloud). *** Deployment overview [#deployment-overview]
Coolify deploys one-click services from predefined templates. For this guide, Coolify will create and run the containers Umami needs, then route traffic through the Coolify proxy. One-click services use prebuilt Docker images, so you do not need to configure a Git repository or build settings for this first test. *** Deploy your first Umami service [#deploy-your-first-umami-service] Choose the deployment method you want to use. Each tab reaches the same first-deployment outcome. Create your first project [#create-your-first-project] On the Coolify dashboard: * click **New Project** * enter a project name, for example `my-first-project` * click **Continue** If you already have a project, skip this step and continue to Step 2. Create a new resource [#create-a-new-resource] Open your project and click **Create New Resource**. A resource is something Coolify will run for you, such as an app, database, or service. In this guide, the resource will be an Umami service. Choose Umami from the service list [#choose-umami-from-the-service-list] In the resource list: * search for **Umami** * click **Umami** Coolify will create an Umami service resource with generated settings. Review the service URL [#review-the-service-url] Coolify gives the service a generated URL so you can test it quickly. For the first deployment, you can keep the generated `sslip.io` URL. Do not remove the `:3000` port from the URL field in Coolify, because Coolify uses it to route traffic to Umami. If you use your own domain, configure it in Coolify as `https://analytics.example.com:3000`. Make sure DNS points to your server IP address and ports `80` and `443` are open on your server firewall. Deploy [#deploy] Click the **Deploy** button. Coolify will pull the required Docker images and start the Umami containers. After deployment, keep these values ready: * public service URL without the port * Umami username, `admin` * Umami password, `umami` Open Umami and sign in [#open-umami-and-sign-in] Open the public service URL without the port in your browser. For example, if Coolify is configured with `http://..sslip.io:3000`, visit `http://..sslip.io`. If you use your own domain and Coolify is configured with `https://analytics.example.com:3000`, visit `https://analytics.example.com`. You should see the Umami login page. Sign in with the default credentials: ```txt username: admin password: umami ``` After the first test works, change the default Umami password before using the service for real traffic. Create a `root` API token for this tutorial. Coolify Cloud already has API access enabled, so Cloud users only need to create the token. On self-hosted Coolify, an administrator must also [enable API access](/api/ip-allowlist#api-access-controls). See [API authorization](/api/authorization) before sending these requests. Set your base URL and token in the terminal where you will run cURL: ```sh export COOLIFY_URL="https://" export COOLIFY_TOKEN="" ``` Coolify Cloud users should set `COOLIFY_URL` to `https://app.coolify.io`. This tutorial uses a `root` token so the same credential works across every read, write, deployment, and sensitive-data request. A `root` token has more access than most integrations need. For production, create a separate token with only the permissions required by that workflow, and revoke the tutorial token when you finish. Create a project and find a server [#create-a-project-and-find-a-server] Create a project, copy its UUID, then list servers and copy the target server UUID: ```sh curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data '{"name":"my-first-project"}' \ "$COOLIFY_URL/api/v1/projects" export PROJECT_UUID="" curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/servers" export SERVER_UUID="" ``` Use `GET /api/v1/projects` if the project already exists. Create and deploy Umami [#create-and-deploy-umami] Create the `umami` one-click service and start it immediately: ```sh curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data "{"type":"umami","name":"my-first-umami","project_uuid":"$PROJECT_UUID","server_uuid":"$SERVER_UUID","environment_name":"production","instant_deploy":true}" \ "$COOLIFY_URL/api/v1/services" ``` Copy the returned service `uuid` and domain: ```sh export SERVICE_UUID="" ``` Verify Umami [#verify-umami] Read the service until its status is `running`: ```sh curl --fail-with-body \ --header "Authorization: Bearer $COOLIFY_TOKEN" \ --header "Accept: application/json" \ "$COOLIFY_URL/api/v1/services/$SERVICE_UUID" ``` Open the returned public domain and sign in with `admin` and `umami`. Change the default password after the test succeeds. [Install the Coolify CLI](/cli/installation), then create a `root` API token for the team that will own the resource. **Coolify Cloud:** API access is already enabled. Save the token in the preconfigured `cloud` context, select it, and verify authentication: ```sh coolify context set-token cloud coolify context use cloud coolify context verify ``` **Self-hosted Coolify:** An administrator must [enable API access](/api/ip-allowlist#api-access-controls) first. Add a context using the full instance URL without `/api/v1`, then verify authentication: ```sh coolify context add --default production https://coolify.example.com coolify context verify ``` A successful verification reports that the connection and authentication are valid. See [CLI authentication](/cli/authentication) for token safety, IP allowlists, and troubleshooting. This tutorial uses a `root` token so the same credential works across every read, write, deployment, and sensitive-data request. A `root` token has more access than most integrations need. For production, create a separate token with only the permissions required by that workflow, and revoke the tutorial token when you finish. Create a project and find a server [#create-a-project-and-find-a-server-1] ```sh coolify project create --name my-first-project coolify server list ``` Copy the project and server UUIDs. Use `coolify project list` if the project already exists. Confirm the service type and deploy Umami [#confirm-the-service-type-and-deploy-umami] List the service types supported by your installed CLI, then create Umami: ```sh coolify service create --list-types coolify service create umami \ --project-uuid \ --server-uuid \ --environment-name production \ --name my-first-umami \ --instant-deploy ``` Copy the service UUID from the response. Verify Umami [#verify-umami-1] ```sh coolify service get coolify service logs --lines 100 ``` Wait for the service status to become `running`. Open its public domain, sign in with `admin` and `umami`, then change the default password. See [`coolify service create`](/cli/command-reference/commands/service/create) for all options. Coolify MCP can inspect and start existing resources, but its current tools cannot create applications, databases, services, or projects. Create the resource with the Dashboard, API, or CLI tab first. You can then use the prompts below to start and verify it without returning to the dashboard. After [setting up Coolify MCP](/mcp/setup), create a `root` token for this end-to-end workflow, then give your client the service UUID or exact name. The prompts need to inspect the service, start it, and inspect it again. A `deploy` token cannot perform the read operations because selecting `deploy` creates a deploy-only token. A `root` token bypasses the `read`, `write`, and `deploy` endpoint checks and can return supported sensitive data. It remains limited to the active team, but it grants more access than routine MCP use requires. Revoke it when you finish this first deployment. Find Umami [#find-umami] ```txt Find the service named my-first-umami in my-first-project. Show me its UUID, current status, public domain, and application components. Do not change anything yet. ``` Confirm that the returned service is the Umami resource you created. Start and verify Umami [#start-and-verify-umami] ```txt Start the Coolify service with UUID . Then check its status and tell me when it is running. Show me the public domain I should open, and do not stop or restart any other resource. ``` Open the returned domain and sign in with the default Umami credentials. The MCP client uses `control` to start the service and the service inspection tools to verify it. *** Common first-deploy issues [#common-first-deploy-issues] Use these checks when Umami deploys but the browser test does not behave as expected. Usually means the generated URL cannot reach the service through your server and proxy, or the URL is being opened with the wrong port behavior. Check: * Umami deployment is in **running** state * the URL field in Coolify still includes the service port, for example `:3000` * you open the public URL in your browser without `:3000` * Coolify proxy is running on the server * your server firewall allows ports `80` and `443` * if using your own domain, DNS points to your server IP address Usually means the credentials do not match what Umami expects. Check: * use `admin` as the username for the first login * use `umami` as the password before changing it * remove accidental spaces before or after either value * if the password was already changed, use the updated Umami credentials Browsers show a site-not-secure warning when you open the service with `http://`. To make the warning go away, open the service with `https://`. For `https://` to work, Coolify needs a TLS certificate from Let's Encrypt. Let's Encrypt can rate-limit shared testing domains like `sslip.io`, so use a real domain. If you are using your own domain, make sure: * DNS is pointed correctly to your server IP * the domain is added in Coolify with `https://`, for example `https://analytics.example.com` * restart the service after changing the domain *** What to do next [#what-to-do-next] Your first service confirms that Coolify can create a one-click service, start its containers, route a URL through the proxy, and load the service in a browser. # Home (/docs) Build & deploy with Coolify [#build--deploy-with-coolify] Your handbook to owning and operating your infrastructure with Coolify. Set up Coolify and deploy your first app in minutes. if Docker can package it, Coolify can run it. If your database has a Docker image, Coolify can deploy it. Deploy **300+** open-source software with our **One-click service** templates. Get help from the community and the Coolify team. # All resources (/docs/integrations/networking/cloudflare/tunnels/all-resource) Access All Resource via Cloudflare Tunnels [#access-all-resource-via-cloudflare-tunnels] Accessing All Resource deployed on Coolify using a Cloudflare Tunnel allows you to securely reach your app without exposing your server’s IP address or without having a Public IP address for the server. Who this is for? [#who-this-is-for] This setup is ideal for people who: * Don't have a public IP for their server (could be a laptop, raspberry pi etc..). * Are unable to port forward (e.g., using home internet or on a private network). * Want to keep their server’s IP address private and avoid exposing it to the public internet. * Have an resource already deployed on Coolify and need an external method to access it securely. Setup Requirements [#setup-requirements] To follow this guide, you'll need: * A free [Cloudflare](https://cloudflare.com) account. * You need a domain that has it's **DNS managed by Cloudflare**. Before We Start [#before-we-start] * We assume you have Coolify running on your server. * This guide uses HTTPS between visitors and Cloudflare, and HTTP between Cloudflare Tunnel and the Coolify proxy. * For HTTPS on both connections, follow the [Full TLS HTTPS guide](/integrations/networking/cloudflare/tunnels/full-tls) instead. How It Works? [#how-it-works] A simple high-level overview diagram to give you a visual idea of how this works: *** The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **Domain Name:** `shadowarcanist.com` *** 1\. Create a Cloudflare Tunnel [#1-create-a-cloudflare-tunnel] To create a Cloudflare Tunnel, first log in to your [Cloudflare dashboard](https://dash.cloudflare.com/) 1. Go to **Networking** in the sidebar. 2. Click on **Tunnels** 3. Click on **Create tunnel** button You will be prompted to enter a tunnel name. Enter a name that you prefer and click on **Create tunnel** button. 1. Select the **Docker** option 2. Copy the docker run command, which contains the token for your tunnel (token starts with "`eyJ`"). Make sure to save only the token, removing the command part before it, and store it in a safe place, as we need it later. 2\. Deploy cloudflared on Coolify [#2-deploy-cloudflared-on-coolify] Go to your project on Coolify dashboard and click the `+ New` button to create a new resource. Search for `Cloudflared` and click on it. Go to the **Environment Variables** page, enter your tunnel token, and deploy the Cloudflared app. Once cloudflared starts running you will be able to see it's status on Cloudflare dashboard Click on continue button to create the tunnel. 3\. Start Coolify Proxy [#3-start-coolify-proxy] 1. In the Coolify dashboard, go to the **Servers** page from the sidebar. 2. Select the server where your application is running, and check if the proxy is showing as running. 4\. Configure tunnel routes [#4-configure-tunnel-routes] 1. Click on your tunnel 2. Click on **Configure** option 1. Select **Routes**. 2. Click **Add route** button 3. Select **Published Application** as the route type 1. **Subdomain** - (Optional) You can make your all of your resource accessible on any subdomain/domain. For this guide, we are using a wildcard subdomain which is `*` 2. **Domain** - Choose the domain you want to use for the tunnel. 3. **Path** - Leave this field empty. 4. **Service URL** - Enter **[http://localhost:80](http://localhost:80)** (this is very important). If `localhost` selects an IPv6 address that the origin cannot accept, use `http://127.0.0.1:80`. See [loopback connection troubleshooting](/integrations/networking/cloudflare/tunnels/single-resource#realtime-or-terminal-connections-fail-with-localhost). 5. After filling in the details, click the **Add route** button. The Coolify proxy (runs on `http://localhost:80`) is used to route traffic to apps running on your server. This eliminates the need to create new routes on the Cloudflare tunnel every time you deploy a new app. 5\. Configure your resource domain [#5-configure-your-resource-domain] Enter the domain you want to use for your resource in Coolify as HTTPS, for example `https://app.shadowarcanist.com`, and deploy your resource. On the resource's **Domains** page, set **Redirect HTTP to HTTPS** to **Disabled**. This is required because the tunnel connects to Coolify using `http://localhost:80`. Cloudflare provides HTTPS to visitors, while Coolify receives HTTP from the tunnel. Leaving the redirect enabled can cause a **TOO\_MANY\_REDIRECTS** error. Keep the redirect enabled for normal Cloudflare orange-cloud proxying when Cloudflare connects to Coolify over HTTPS using **Full** or **Full (Strict)** SSL. To also use HTTPS between Cloudflare Tunnel and Coolify, follow the [Full TLS HTTPS guide](/integrations/networking/cloudflare/tunnels/full-tls) and configure the tunnel with an HTTPS service URL. **Congratulations**! You've successfully set up a resource that can be accessed by anyone on the internet your domain. *** How to use multiple different domains? [#how-to-use-multiple-different-domains] You don't need to create new tunnels for each domain, just create a new routes with the new domain and point it to the `http://localhost:80`. *** Known issues and Solutions [#known-issues-and-solutions] When you create a new route in [Step 4](/integrations/networking/cloudflare/tunnels/all-resource#4-configure-tunnel-routes), Cloudflare will create a DNS record for the hostname. However, if a DNS record for the hostname already exists, Cloudflare won’t update existing record. In this case, your app won’t work. To fix this issue, follow the steps below: 1. Click on your tunnel 2. Click on **Configure** option 3. Copy your tunnel ID from the Tunnels details section. Create a new DNS record with the following details: 1. In the Cloudflare dashboard, go to **DNS**. 2. Select **Records**. 3. Add a **CNAME** record. 4. Enter the name as `*` or the name of your subdomain (this should match the hostname you have for your app on the tunnel). 5. For the **Target**, enter the tunnel ID followed by `.cfargotunnel.com` 6. Set the proxy status to **Proxied**. Now, visit the domain of your application, and it should be accessible there. # Full TLS (/docs/integrations/networking/cloudflare/tunnels/full-tls) Full HTTPS/TLS Setup for All Resources [#full-httpstls-setup-for-all-resources] When tunneling resources with Coolify through Cloudflare, Cloudflare typically handles HTTPS and TLS termination, while Coolify runs your resources over HTTP. This setup works for most users, but some may face issues with URL mismatches, especially for apps that require HTTPS on Coolify to issue JWT tokens or handle callback URLs. This guide solves that issue by configuring your resources to run fully on HTTPS, bypassing Cloudflare's HTTPS handling and ensuring your app functions correctly with secure connections. Who this is for? [#who-this-is-for] This guide is ideal for users who: * Have followed our [Tunnel All Resources Using Cloudflare Tunnel](/integrations/networking/cloudflare/tunnels/all-resource) or [Tunnel Specific Resources Using Cloudflare Tunnel](/integrations/networking/cloudflare/tunnels/single-resource) guide. * Need their resources deployed with Coolify to run on HTTPS for applications requiring HTTPS for JWT issuance, callback functions, or similar features. Setup Requirements [#setup-requirements] To follow this guide, you'll need: * A working Cloudflare tunnel setup as described in the previous guides. * A domain configured in Cloudflare to handle HTTP traffic and redirect to HTTPS. Before We Start [#before-we-start] * If your Coolify instance is on the same tunnel as the domain you want to configure, make sure you can access the Coolify Dashboard using the server IP and port (e.g., **203.0.113.1:8000**) before starting these steps. * The default port is **8000**, but if you’ve changed or disabled it, ensure you can access the Coolify Dashboard through the new port or that port **8000** is re-enabled on the server. *** The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **IPv4 Address of Origin Server:** 203.0.113.1 * **Domain Name:** shadowarcanist.com * **Username:** shadowarcanist 1\. Setup Origin TLS Certificate [#1-setup-origin-tls-certificate] Communication between your server and Cloudflare is encrypted using a TLS certificate. There are two ways to do this: * Use a TLS certificate from Cloudflare * Get your own TLS certificate from a trusted public Certificate Authority (this requires a DNS challenge) Here's a concise comparison table between a **Cloudflare Origin Certificate** and a **Public CA Certificate**: | Feature | Cloudflare Origin Certificate | Public CA Certificate | | --------------------- | --------------------------------------------------- | ----------------------------- | | Trusted By | Cloudflare only | Browsers, OSs, Cloudflare | | Use Case | Cloudflare ↔ Origin only | Any direct client | | Direct Browser Access | Shows certificate errors if users bypass Cloudflare | ✅ Works normally | | Requires CF Proxy | ✅ Yes | ❌ No | | Works Without CF | ❌ No | ✅ Yes | | Issuer | Cloudflare | Public CA (eg: Let's Encrypt) | | Cost | Free | Free | | DNS Challenge | ❌ No | ✅ Yes | If you plan to have Cloudflare always in front of your application, use a Cloudflare Origin Certificate. Otherwise, use a Public CA Cert. There are 2 ways to setup the Origin TLS Certificate so follow one of the methods from below: A simple high-level overview diagram to give you a visual idea of how this works: *** A. Create Cloudflare Origin Certificate [!toc] [#a-create-cloudflare-origin-certificate-toc] 1. In your Cloudflare dashboard, go to **SSL/TLS**. 2. Select **Origin Server**. 3. Select **Origin Certificates** 4. Click the **Create Certificate** button. 1. Choose **RSA (2048)** for the key type. 2. Add the hostnames you want the certificate to cover. 3. Set the certificate validity to **15 years**. 4. Click the **Create** button. * **`shadowarcanist.com`** will cover only the main domain. * **`*.shadowarcanist.com`** will cover all subdomains. On Cloudflare’s free plan, wildcard certificates cover just one level of subdomains For example, it works for **`coolify.shadowarcanist.com`** but not **`www.coolify.shadowarcanist.com`**. To cover multiple levels, you'll need to purchase the [Advanced Certificate Manager ↗](https://www.cloudflare.com/application-services/products/advanced-certificate-manager/) 1. Choose **PEM** as the key format. 2. Copy your **Origin Certificate** and save it somewhere safe 3. Copy your **Private Key** and save it somewhere safe 4. Click the **Ok** button. Next, you'll add these to your server running Coolify and configure Coolify to use this certificate. *** B. Add Certificate to Your Server [!toc] [#b-add-certificate-to-your-server-toc] SSH into your server or use Coolify's terminal feature. For this guide, I’m using my external terminal: ```bash ssh shadowarcanist@203.0.113.1 ``` Once logged in, navigate to the Coolify proxy directory: ```bash $ cd /data/coolify/proxy ``` Certificate locations slightly vary between Caddy and Traefik, so choose the one based on the proxy you are using from the section below. Create the `certs` directory: ```bash $ mkdir certs ``` Verify it was created: ```bash $ ls > acme.json certs docker-compose.yml dynamic ``` Now, navigate into the **certs** directory: ```bash $ cd certs ``` Create the `caddy/data/certs` directory: ```bash $ mkdir -p caddy/data/certs ``` Verify it was created: ```bash $ ls caddy/data > certs ``` Now, navigate into the **certs** directory: ```bash $ cd caddy/data/certs ``` Create two new files for the certificate and private key: ```bash $ touch shadowarcanist.cert shadowarcanist.key ``` Verify the files were created: ```bash $ ls > shadowarcanist.cert shadowarcanist.key ``` Open the **shadowarcanist.cert** file and paste the certificate from the Cloudflare dashboard: ```bash $ nano shadowarcanist.cert ``` Save and exit after pasting the certificate. Do the same for the **shadowarcanist.key** file and paste the private key: ```bash $ nano shadowarcanist.key ``` Save and exit. Now the origin certificate is installed on your server. *** C. Configure Coolify proxy to Use the Origin Certificate [!toc] [#c-configure-coolify-proxy-to-use-the-origin-certificate-toc] 1. Go to the **Server** section in the sidebar. 2. Select **Proxy**. 3. Open the **Dynamic Configuration** page 4. Click **Add** button You will now be prompted to enter the Dynamic Configuration. Dynamic configuration file slightly varies between Caddy and Traefik, so choose the one based on the proxy you are using from the section below. 1. Choose a name for your configuration (must end with `.yaml`). 2. Enter the following details in the configuration field: ```yaml tls: certificates: - certFile: /traefik/certs/shadowarcanist.cert keyFile: /traefik/certs/shadowarcanist.key ``` 3. Save the configuration If you want to add multiple certificates and keys, you can do it like this: ```yaml tls: certificates: - certFile: /traefik/certs/shadowarcanist.cert keyFile: /traefik/certs/shadowarcanist.key - certFile: /traefik/certs/name2.cert keyFile: /traefik/certs/name2.key - certFile: /traefik/certs/name3.cert keyFile: /traefik/certs/name3.key ``` 1. Choose a name for your configuration (must end with `.caddy`). 2. Enter the following details in the configuration field: ```bash *.shadowarcanist.com, shadowarcanist.com { tls /data/certs/shadowarcanist.cert /data/certs/shadowarcanist.key } ``` The wildcard `*.shadowarcanist.com` provides coverage for all subdomains, exclude it if you’re only securing a single domain (i.e, `shadowarcanist.com`). 3. Save the configuration If you want to add multiple certificates and keys, you can do it like this: ```bash *.shadowarcanist.com, shadowarcanist.com { tls /data/certs/shadowarcanist.cert /data/certs/shadowarcanist.key } *.name2.com, name2.com { tls /data/certs/name2.cert /data/certs/name2.key } *.name3.com, name3.com { tls /data/certs/name3.cert /data/certs/name3.key } ``` From now on, Coolify will use the origin certificate for requests matching the hostname. A simple high-level overview diagram to give you a visual idea of how this works: We already have guides to set up DNS challenge for TLS certificates, you can follow them here: * [Traefik DNS challenge](/core/networking/proxy/traefik/dns-challenge) * [Caddy DNS challenge](/core/networking/proxy/caddy/dns-challenge) Come back to this guide after you finish setting up the DNS challenge using the guides above. 2\. Setup TLS Encryption [#2-setup-tls-encryption] To make Cloudflare use stricter encryption when connecting to your server, configure your TLS encryption in Cloudflare: 1. Go to **SSL/TLS** in Cloudflare. 2. Select **Overview**. 3. Click **Configure** button 1. Choose **Full (Strict)** as the encryption mode. 2. Click **Save** button 3\. Setup Always Use HTTPS [#3-setup-always-use-https] To make Cloudflare automatically redirect HTTP requests to HTTPS, configure your redirects in Cloudflare: 1. In Cloudflare, go to **SSL/TLS** 2. Select **Edge Certificates**. 3. Enable **Always Use HTTPS**. 4\. Configure Tunnel to Use HTTPS [#4-configure-tunnel-to-use-https] 1. Click the three dots icon to open the settings menu. 2. Click **Edit route** option Next, update the service URL as follows: Change the type from `http://localhost:80` to `https://localhost:443` Troubleshooting: Bad Gateway (502) after switching to HTTPS [#troubleshooting-bad-gateway-502-after-switching-to-https] If you get a **502 Bad Gateway** after changing the service URL to `https://localhost:443`, check the cloudflared logs for a certificate hostname mismatch. Other origin connection failures can also produce a 502. Your Origin Certificate is issued for your domain (e.g. `shadowarcanist.com` / `*.shadowarcanist.com`), but the tunnel is now connecting to `https://localhost:443`. When `cloudflared` verifies the certificate, it expects the certificate to match `localhost`, but the certificate only covers your domain. Verification fails and Cloudflare returns a 502. **Fix:** tell `cloudflared` which hostname to expect from the certificate. 1. In the Cloudflare dashboard, go to **Networking → Tunnels**, then select your tunnel. 2. On **Routes**, select **Edit route** for the published application. 3. Keep the service URL set to `https://localhost:443`. 4. Expand **Additional application settings**, then **TLS**. 5. Set **Origin Server Name** to a hostname covered by the certificate, for example `coolify.shadowarcanist.com`. Use a concrete hostname, not `*.shadowarcanist.com`. 6. Keep **Disable TLS certificate verification** turned off and save the route. Repeat for other HTTPS routes, using a hostname covered by the certificate their origin serves. For more diagnostics, see [Cloudflare's HTTPS origin troubleshooting guide](https://developers.cloudflare.com/tunnel/troubleshooting/https-origins/). Changing the zone's SSL/TLS mode does not fix a hostname mismatch between cloudflared and the origin. 5\. Update URLs from HTTP to HTTPS [#5-update-urls-from-http-to-https] Now, update all URLs from **HTTP** to **HTTPS** in Coolify, including resources and the instance domain on the settings page.
**Congratulations!** All your resources are now running on HTTPS at all times. # Overview (/docs/integrations/networking/cloudflare/tunnels) Cloudflare Tunnels [#cloudflare-tunnels] [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) allow you to securely expose your local server or applications to the internet without opening ports on your router. This makes them a great option for hosting projects on devices like old laptops or Raspberry Pis. Why Use Cloudflare Tunnels? [#why-use-cloudflare-tunnels] * No need to open or forward ports on your device to the public internet. * Simplifies routing and DNS configuration. * Supports exposing a single application or multiple services. * Hides your server's IP address by routing traffic through a Cloudflare Tunnel, showing only your domain. * Works even if you have a dynamic IP (or) no public IP at all. * Eliminates the hassle of managing and setting up SSL certificates. When Not to Use Cloudflare Tunnels? [#when-not-to-use-cloudflare-tunnels] * If you prefer direct access to your server without a proxy layer. * If you're concerned about routing traffic through Cloudflare's servers. * If you rely on additional firewall tools, as Cloudflare Tunnels bypass all firewall rules. * If you need SSL certificates trusted by entities other than Cloudflare. Ways to Use Cloudflare Tunnels with Coolify [#ways-to-use-cloudflare-tunnels-with-coolify] You can set up Cloudflare Tunnels with Coolify in several ways, depending on your needs. Below are the available options, each linked to a detailed guide for easy setup: 1. [All Resources](/integrations/networking/cloudflare/tunnels/all-resource) -> Use a tunnel for all resources deployed through Coolify. This is the **easiest** and **most recommended** way for beginners. 2. [Single Resource](/integrations/networking/cloudflare/tunnels/single-resource) -> Use a tunnel for a single resource deployed through Coolify. 3. [Server SSH Access](/integrations/networking/cloudflare/tunnels/server-ssh) -> Securely connect your server to Coolify using a domain through Cloudflare Tunnel. 4. [Full HTTPS/TLS](/integrations/networking/cloudflare/tunnels/full-tls) -> Setup always-on **HTTPS** for all domains and subdomains. Normally, Coolify uses **HTTP** while Cloudflare manages **HTTPS**. If certain apps require **HTTPS** directly on Coolify. It’s highly recommended to go with the first option [All Resources](/integrations/networking/cloudflare/tunnels/all-resource) if you're new to Coolify and Cloudflare Tunnels, as it’s much easier to set up and manage. # Server SSH (/docs/integrations/networking/cloudflare/tunnels/server-ssh) Server SSH Access via Cloudflare Tunnels [#server-ssh-access-via-cloudflare-tunnels] Accessing your server using SSH over a Cloudflare Tunnel is a secure and easy way to connect to a remote server while keeping its IP address hidden. Who this is for? [#who-this-is-for] This setup is ideal for people who: * Want to keep their server's IP address private. * Want to close SSH ports on their server. * Don’t want to rely on static public IPs for accessing their remote server. * Don't have a static public IP for the server (only applies if you're doing the [manual setup](#manual-setup)). Before We Start [#before-we-start] * We assume you already have a server running Coolify and you are looking to set up a tunnel to connect a different server to Coolify. * If you are trying to set up a tunnel on the server where Coolify is running and you don’t have any other servers to connect, you don’t need a SSH tunnel. Coolify already has full root access to the server it’s running on, so there’s no need for an SSH tunnel in this case. How It Works? [#how-it-works] A simple high-level overview diagram to give you a visual idea of how this works: *** Setup Methods [#setup-methods] There are two ways to set this up: * Automated * Manual The main difference is that in the manual setup, you install cloudflared yourself, while in the automated setup, Coolify does it for you. To use Coolify's automated setup for a Cloudflare Tunnel: * Your remote server must have a **public IP address** and an **active SSH port** during the initial setup for Coolify to configure the tunnel. After setup, you can close all ports on the server. * If your server doesn’t have a public IP address, then this automated setup is **not for you**. Please follow the Manual setup guide instead. * You need a domain that has it's **DNS managed by Cloudflare**. *** The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **IPv4 Address of Remote Server:** `192.168.1.93` * **SSH Domain Name:** `helixa.shadowarcanist.com` * **Username:** `root` * **SSH Port:** `22` *** 1\. Create a Private SSH Key [!toc] [#1-create-a-private-ssh-key-toc] 1. In your Coolify Dashboard, go to **Keys & Tokens** 2. Open **Private Keys**. 3. Select **New private key**. Choose **Generate ED25519** or **Generate RSA**. Coolify generates and saves the key immediately. 1. Open the saved key's edit icon and enter a name and optional description. 2. Select **Save changes**. 3. Copy **Public key** for the next step. 2\. Add Public Key to Your Server [!toc] [#2-add-public-key-to-your-server-toc] SSH into the server you want to connect to Coolify: ```bash ssh root@192.168.1.93 ``` Once logged in, add your public key to the authorized keys file: ```bash echo "" >> ~/.ssh/authorized_keys ``` 3\. Add your Server to Coolify [!toc] [#3-add-your-server-to-coolify-toc] 1. In your Coolify Dashboard, go to **Servers** 2. Select **New server**, then **IP address or domain**. You will be prompted to enter details about your server. Make sure the information you provide is accurate, as Coolify will use these details to access your server. 1. **Name** - Choose a name to easily identify your server in the dashboard. 2. **Description** - (Optional) Provide a description for your server. 3. **IP address or domain** - Enter the public IP address of your server. 4. Under **Advanced settings**, **Port** - Enter the port number your server uses for SSH connections. 5. Under **Advanced settings**, **User** - Enter the username Coolify will use (it should have root privileges on the server). 6. **Private key** - Select the private key you created in Step 1 7. After filling in the details, click the **Continue** button. 4\. Validate your Server on Coolify [!toc] [#4-validate-your-server-on-coolify-toc] Select **Validate connection** to open the validation panel and follow its checks. During this process, Coolify will log in to your server and set up everything needed for Coolify to use the server. Once the validation is completed, your server page will look like this: 5\. Create a Cloudflare Tunnel [!toc] [#5-create-a-cloudflare-tunnel-toc] To create a Cloudflare Tunnel, first log in to your [Cloudflare dashboard](https://dash.cloudflare.com/) 1. Go to **Networking** in the sidebar. 2. Click on **Tunnels** 3. Click on **Create tunnel** button You will be prompted to enter a tunnel name. Enter a name that you prefer and click on **Create tunnel** button. 1. Select the **Docker** option 2. Copy the docker run command, which contains the token for your tunnel (token starts with "`eyJ`"). Make sure to save only the token, removing the command part before it, and store it in a safe place, as we need it later. 6\. Configure Cloudflare tunnel on Coolify [!toc] [#6-configure-cloudflare-tunnel-on-coolify-toc] 1. Open the server and select **Cloudflare Tunnel** in its sidebar. 2. Under **Automated setup**, enter **Cloudflare token** and **SSH domain**. 3. Select **Configure tunnel**. The Cloudflare token is included in the **docker run command** you copied in the previous step. The token begins with `eyJ`. Once cloudflared starts running you will be able to see it's status on Cloudflare dashboard: Click on continue button to create the tunnel. 7\. Configure tunnel routes [!toc] [#7-configure-tunnel-routes-toc] 1. Click on your tunnel 2. Click on **Configure** option 1. Select **Routes**. 2. Click **Add route** button 3. Select **Published Application** as the route type 1. **Subdomain** - (Optional) You can make your resource accessible on any subdomain/domain. For this guide, we are using the `helixa` subdomain. 2. **Domain** - Choose the domain you want to use for the tunnel. 3. **Path** - Leave this field empty. 4. **Service URL** - Enter **ssh://localhost:22** (this is very important). If your SSH port is different from 22, use that port instead. 5. After filling in the details, click the **Add route** button. Coolify will automatically change the server IP address to the Cloudflare SSH domain once the tunnel is configured. If it doesn’t update automatically then manually change the IP address to the SSH domain here: **Congratulations!** You've successfully set up a server that can be accessed by Coolify over SSH using Cloudflare tunnels via your domain. You can now block your SSH port on the server if you wish. To manually setup Cloudflare Tunnel: * You need access to your remote server to install cloudflared (a public IP for your server is not required). * You need a domain that has it's **DNS managed by Cloudflare**. *** The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **IPv4 Address of Remote Server:** `192.168.1.93` * **SSH Domain Name:** `helixa.shadowarcanist.com` * **Username:** `root` * **SSH Port:** `22` *** 1\. Create a Private SSH Key [!toc] [#1-create-a-private-ssh-key-toc-1] 1. In your Coolify Dashboard, go to **Keys & Tokens** 2. Open **Private Keys**. 3. Select **New private key**. Choose **Generate ED25519** or **Generate RSA**. Coolify generates and saves the key immediately. 1. Open the saved key's edit icon and enter a name and optional description. 2. Select **Save changes**. 3. Copy **Public key** for the next step. 2\. Add Public Key to Your Server [!toc] [#2-add-public-key-to-your-server-toc-1] SSH into the server you want to connect to Coolify: ```bash ssh root@192.168.1.93 ``` Once logged in, add your public key to the authorized keys file: ```bash echo "" >> ~/.ssh/authorized_keys ``` 3\. Add your Server to Coolify [!toc] [#3-add-your-server-to-coolify-toc-1] 1. In your Coolify Dashboard, go to **Servers** 2. Select **New server**, then **IP address or domain**. You will be prompted to enter details about your server. 1. **Name** - Choose a name to easily identify your server in the dashboard. 2. **Description** - (Optional) Provide a description for your server. 3. **IP address or domain** - Enter the SSH domain that you want to acesss the server via Cloudflare tunnels. 4. Under **Advanced settings**, **Port** - Enter the port number your server uses for SSH connections. 5. Under **Advanced settings**, **User** - Enter the username Coolify will use (it should have root privileges on the server). 6. **Private key** - Select the private key you created in Step 1 7. After filling in the details, click the **Continue** button. 4\. Configure Cloudflare tunnel on Coolify [!toc] [#4-configure-cloudflare-tunnel-on-coolify-toc] 1. Open the server and select **Cloudflare Tunnel** in its sidebar. 2. Complete the tunnel installation and route configuration in the following steps before marking the manual setup as complete. 5\. Create a Cloudflare Tunnel [!toc] [#5-create-a-cloudflare-tunnel-toc-1] To create a Cloudflare Tunnel, first log in to your [Cloudflare dashboard](https://dash.cloudflare.com/) 1. Go to **Networking** in the sidebar. 2. Click on **Tunnels** 3. Click on **Create tunnel** button You will be prompted to enter a tunnel name. Enter a name that you prefer and click on **Create tunnel** button. 1. Select the **Docker** option 2. Copy the docker run command, and run it on the server terminal which you want connect to Coolify. By default, the `docker run` command runs in the foreground. This means the `cloudflared` container will stop if you close the terminal. To keep the container running in the background, add the `-d` flag when running the command. For example: `docker run -d cloudflare/...` Once cloudflared starts running you will be able to see it's status on Cloudflare dashboard: Click on continue button to create the tunnel. 6\. Configure tunnel routes [!toc] [#6-configure-tunnel-routes-toc] 1. Click on your tunnel 2. Click on **Configure** option 1. Select **Routes**. 2. Click **Add route** button 3. Select **Published Application** as the route type 1. **Subdomain** - (Optional) You can make your resource accessible on any subdomain/domain. For this guide, we are using the `helixa` subdomain. 2. **Domain** - Choose the domain you want to use for the tunnel. 3. **Path** - Leave this field empty. 4. **Service URL** - Enter **ssh://localhost:22** (this is very important). If your SSH port is different from 22, use that port instead. 5. After filling in the details, click the **Add route** button. 7\. Validate server on Coolify [!toc] [#7-validate-server-on-coolify-toc] Return to the server's **Cloudflare Tunnel** page. For an unvalidated server, select **mark a manual configuration as complete**. If the server is already validated, use **I configured the tunnel manually** under **Manual setup** and complete the confirmation. Open **General**. Select **Validate connection** to open the validation panel and follow its checks. During this process, Coolify will log in to your server and set up everything needed for Coolify to use the server. Once the validation is completed, your server page will look like this: **Congratulations!** You've successfully set up a server that can be accessed by Coolify over SSH using Cloudflare tunnels via your domain. You can now block your SSH port on the server if you wish. *** Known issues and Solutions [#known-issues-and-solutions] When you create a new routes on Tunnel, Cloudflare will create a DNS record for the hostname. However, if a DNS record for the hostname already exists, Cloudflare won’t update existing record. In this case, your app won’t work. To fix this issue, follow the steps below: 1. Click on your tunnel 2. Click on **Configure** option 3. Copy your tunnel ID from the Tunnels details section. Create a new DNS record with the following details: 1. In the Cloudflare dashboard, go to **DNS**. 2. Select **Records**. 3. Add a **CNAME** record. 4. Enter the name as `*` or the name of your subdomain (this should match the hostname you have for your app on the tunnel). 5. For the **Target**, enter the tunnel ID followed by `.cfargotunnel.com` 6. Set the proxy status to **Proxied**. Now, visit the domain of your application, and it should be accessible there. # Single resource (/docs/integrations/networking/cloudflare/tunnels/single-resource) Access Single Resource via Cloudflare Tunnels [#access-single-resource-via-cloudflare-tunnels] Accessing an Resource deployed on Coolify using a Cloudflare Tunnel allows you to securely reach your app without exposing your server’s IP address or without having a Public IP address for the server. Who this is for? [#who-this-is-for] This setup is ideal for people who: * Don't have a public IP for their server (could be a laptop, raspberry pi etc..). * Are unable to port forward (e.g., using home internet or on a private network). * Want to keep their server’s IP address private and avoid exposing it to the public internet. * Have an app already deployed on Coolify and need an external method to access it securely. Setup Requirements [#setup-requirements] To follow this guide, you'll need: * A free [Cloudflare](https://cloudflare.com) account. * You need a domain that has it's **DNS managed by Cloudflare**. * Your Resource has to be deployed and managed with Coolify. Before We Start [#before-we-start] * We assume you have Coolify running and an app already deployed. * If your app requires HTTPS for functionality like cookies or login, then you need to follow the [Full TLS HTTPS guide](/integrations/networking/cloudflare/tunnels/full-tls) after following this guide. This is because in this guide, Cloudflare will manage HTTPS externally, while your app will run over HTTP within Coolify. How It Works? [#how-it-works] A simple high-level overview diagram to give you a visual idea of how this works: *** The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **Domain Name:** shadowarcanist.com * **Ports Exposes:** 80 * **Ports Mapping:** 4477:80 *** 1\. Setup your app for tunneling [#1-setup-your-app-for-tunneling] To setup your app for tunneling, follow these steps: 1. Remove all domains from the **Domains** field. 2. Set the correct port in **Ports Exposed** (the port your app uses). 3. Set the correct ports in **Port Mappings** (left is the host port, right is the app port). 4. Deploy your app by clicking the **Deploy** button. 2\. Create a Cloudflare Tunnel [#2-create-a-cloudflare-tunnel] To create a Cloudflare Tunnel, first log in to your [Cloudflare dashboard](https://dash.cloudflare.com/) 1. Go to **Networking** in the sidebar. 2. Click on **Tunnels** 3. Click on **Create tunnel** button You will be prompted to enter a tunnel name. Enter a name that you prefer and click on **Create tunnel** button. 1. Select the **Docker** option 2. Copy the docker run command, which contains the token for your tunnel (token starts with "`eyJ`"). Make sure to save only the token, removing the command part before it, and store it in a safe place, as we need it later. 3\. Deploy cloudflared on Coolify [#3-deploy-cloudflared-on-coolify] Go to your project on Coolify dashboard and click the `+ New` button to create a new resource. Search for `Cloudflared` and click on it. Go to the **Environment Variables** page, enter your tunnel token, and deploy the Cloudflared app. Once cloudflared starts running you will be able to see it's status on Cloudflare dashboard Click on continue button to create the tunnel. 4\. Set Up TLS Encryption [#4-set-up-tls-encryption] To make Cloudflare use stricter encryption when connecting to your server, configure your TLS encryption in Cloudflare: 1. Go to **SSL/TLS** in Cloudflare. 2. Select **Overview**. 3. Click **Configure** button 1. Choose **Full (Strict)** as the encryption mode. 2. Click **Save** button 5\. Configure tunnel routes [#5-configure-tunnel-routes] 1. Click on your tunnel 2. Click on **Configure** option 1. Select **Routes**. 2. Click **Add route** button 3. Select **Published Application** as the route type 1. **Subdomain** - (Optional) You can make your resource accessible on any subdomain/domain. For this guide, we are using the `helixa` subdomain. 2. **Domain** - Choose the domain you want to use for the tunnel. 3. **Path** - Leave this field empty. 4. **Service URL** - Enter **[http://localhost:4477](http://localhost:4477)** (this is very important). The port 4477 is the one we mapped to the host system in [Step 1](/integrations/networking/cloudflare/tunnels/single-resource#1-setup-your-app-for-tunneling). 5. After filling in the details, click the **Add route** button. **Congratulations**! You've successfully set up a resource that can be accessed by anyone on the internet on your domain. *** Tunnel Multiple Resources [#tunnel-multiple-resources] The easiest way to tunnel multiple resources is by following our [Tunnel All Resources](/integrations/networking/cloudflare/tunnels/single-resource) guide, which uses Coolify's built-in proxy. However, if you prefer not to use the proxy, there are two alternative methods: If you want to expose different apps individually, you can follow our [Tunnel All Resources](/integrations/networking/cloudflare/tunnels/single-resource), or take an alternate approach: 1. Follow [Step 1](/integrations/networking/cloudflare/tunnels/single-resource#1-setup-your-app-for-tunneling) for your new resource. 2. Create a new route on Cloudflare Tunnel as described in [Step 5](/integrations/networking/cloudflare/tunnels/single-resource#5-configure-tunnel-routes). There’s no need to create a separate tunnel for each resources, simply create a new route and point it to the port your app is listening on. You can expose the Coolify dashboard, realtime updates, and terminal connections through a single tunnel route to the Coolify proxy. Make sure the Coolify proxy is running on the server where your Coolify instance is installed. The tunnel connects to this proxy on port `80`. 1\. Set the Coolify instance URL [!toc] [#1-set-the-coolify-instance-url-toc] In Coolify, open **Settings > General** and set [URL](/core/instance-management/instance-settings#url) to your dashboard domain, for example `https://coolify.shadowarcanist.com`. Then disable [Redirect HTTP to HTTPS](/core/instance-management/instance-settings#redirect-http-to-https). Cloudflare Tunnel connects to the proxy over HTTP, so the redirect would create a redirect loop. Coolify uses the instance URL to generate the proxy routes for the dashboard: ```text /app/* -> coolify:6001 /apps/* -> coolify:6001 /terminal/ws -> coolify:6002 /* -> coolify:8080 ``` 2\. Create a route in Cloudflare Tunnel [!toc] [#2-create-a-route-in-cloudflare-tunnel-toc] Follow [Step 5](/integrations/networking/cloudflare/tunnels/single-resource#5-configure-tunnel-routes) and use the following mapping: | Domain | Service | Purpose | | ---------------------------- | --------------------- | ------------------------------------------------- | | `coolify.shadowarcanist.com` | `http://localhost:80` | Coolify dashboard, realtime updates, and terminal | You do not need separate tunnel routes for ports `6001` and `6002`. You also do not need to set `PUSHER_HOST`, `PUSHER_PORT`, `TERMINAL_HOST`, or `TERMINAL_PORT` for this setup. If you are switching from separate routes, remove obsolete `PUSHER_HOST`, `PUSHER_PORT`, `TERMINAL_HOST`, and `TERMINAL_PORT` overrides from `/data/coolify/source/.env`. Existing overrides take precedence over automatic hostname and port detection. After changing `.env`, restart Coolify to apply the changes: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` 3\. Verify the Setup [!toc] [#3-verify-the-setup-toc] 1. Access your Coolify dashboard at `https://coolify.shadowarcanist.com`. 2. Test the realtime functionality by visiting `https://coolify.shadowarcanist.com/realtime` in another browser tab. You should see a notification about a test event. 3. In your browser's network tab, confirm the realtime and terminal WebSocket connections use the Coolify dashboard hostname. Cloudflare Tunnel connects to the Coolify proxy from inside the server. Ports `8000`, `6001`, and `6002` do not need to be exposed publicly. Separate realtime hostname [!toc] [#separate-realtime-hostname-toc] Existing tunnels that route Coolify's realtime and terminal services separately keep working: | Domain / Path | Service | Purpose | | ---------------------------------------- | ----------------------- | ------------------------- | | `coolify.shadowarcanist.com/terminal/ws` | `http://localhost:6002` | WebSocket terminal | | `coolify-realtime.shadowarcanist.com` | `http://localhost:6001` | Realtime updates (Reverb) | | `coolify.shadowarcanist.com` | `http://localhost:8000` | Coolify dashboard | Keep the path-specific terminal route above the dashboard route so Cloudflare matches it first. All three origin ports belong to the `coolify` container. See the [Reverb migration guide](/core/instance-management/reverb-migration) for details. This setup needs a separate realtime hostname in `/data/coolify/source/.env`: ```bash PUSHER_HOST=coolify-realtime.shadowarcanist.com PUSHER_PORT=443 ``` This tells the browser where to open the realtime WebSocket connection. Server-side event delivery stays inside the `coolify` container, so do not set `PUSHER_BACKEND_HOST` to this hostname. After changing `.env`, run the following command to restart Coolify: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` *** Known issues and Solutions [#known-issues-and-solutions] Realtime or terminal connections fail with localhost [#realtime-or-terminal-connections-fail-with-localhost] On some servers, `localhost` resolves to the IPv6 loopback address `::1`, while the origin port is reachable only through IPv4. If the dashboard loads but realtime updates or terminal connections fail, check the cloudflared logs for an origin connection error and try an explicit IPv4 loopback address. For the single-route setup above, change the tunnel service URL from `http://localhost:80` to `http://127.0.0.1:80`. If you use the legacy separate routes, keep their order and change only the origin address: | Route | IPv4 service URL | | :------------------------------------- | :---------------------- | | Dashboard hostname with `/terminal/ws` | `http://127.0.0.1:6002` | | Separate realtime hostname | `http://127.0.0.1:6001` | | Dashboard hostname | `http://127.0.0.1:8000` | For an HTTPS origin, use `https://127.0.0.1:443` and keep **Origin Server Name** set to the certificate's hostname, as described in [HTTPS tunnel troubleshooting](/integrations/networking/cloudflare/tunnels/full-tls#troubleshooting-bad-gateway-502-after-switching-to-https). Save the route, reload Coolify, and test realtime updates and the terminal again. If the connection still fails, inspect the origin listener, tunnel logs, and WebSocket requests. This workaround addresses loopback address selection; other connection failures and gateway timeouts need separate diagnosis. An existing DNS record prevents the route from working [#an-existing-dns-record-prevents-the-route-from-working] When you create a new routes in [Step 5](/integrations/networking/cloudflare/tunnels/single-resource#5-configure-tunnel-routes), Cloudflare will create a DNS record for the hostname. However, if a DNS record for the hostname already exists, Cloudflare won’t update existing record. In this case, your app won’t work. To fix this issue, follow the steps below: 1. Click on your tunnel 2. Click on **Configure** option 3. Copy your tunnel ID from the Tunnels details section. Create a new DNS record with the following details: 1. In the Cloudflare dashboard, go to **DNS**. 2. Select **Records**. 3. Add a **CNAME** record. 4. Enter the name as `*` or the name of your subdomain (this should match the hostname you have for your app on the tunnel). 5. For the **Target**, enter the tunnel ID followed by `.cfargotunnel.com` 6. Set the proxy status to **Proxied**. Now, visit the domain of your application, and it should be accessible there. # Cloudflare DDoS Protection (/docs/integrations/security/cloudflare/ddos-protection) Cloudflare DDoS Protection [#cloudflare-ddos-protection] Cloudflare provides a robust layer of DDoS protection for your server and applications. When using Cloudflare’s Proxy, CDN, and security features, all incoming traffic to your Coolify-hosted apps is shielded from malicious attacks, like DDoS, and secured through Cloudflare’s global network. *** Why Use Cloudflare for DDoS Protection with Coolify? [#why-use-cloudflare-for-ddos-protection-with-coolify] 1. Blocks malicious traffic before it reaches your server. 2. No need to scale server resources during DDoS attacks — Cloudflare absorbs the impact. 3. Hides your server’s real IP address by proxying your application through Cloudflare’s global network. *** When Not to Use Cloudflare for DDoS Protection [#when-not-to-use-cloudflare-for-ddos-protection] 1. You prefer not to route all traffic through Cloudflare’s network. 2. Privacy concerns, Cloudflare terminates TLS, which means they can inspect incoming requests. 3. You need free wildcard support for deep subdomains (more than 1 level subdomains -- e.g., `*.sub.domain.com` which Cloudflare does not offer for free). *** The following data is used as an example in this guide. Please replace it with your actual data when following the steps: * **IPv4 Address of Origin Server:** `203.0.113.1` * **Domain Name:** `shadowarcanist.com` * **Username:** `shadowarcanist` How It Works? [#how-it-works] A simple high-level overview diagram to give you a visual idea of how this works: 1\. Setup Origin TLS Certificate [#1-setup-origin-tls-certificate] Communication between your server and Cloudflare is encrypted using a TLS certificate. There are two ways to do this: * Use a TLS certificate from Cloudflare * Get your own TLS certificate from a trusted public Certificate Authority (this requires a DNS challenge) Here's a concise comparison table between a **Cloudflare Origin Certificate** and a **Public CA Certificate**: | Feature | Cloudflare Origin Certificate | Public CA Certificate | | --------------------- | --------------------------------------------------- | ----------------------------- | | Trusted By | Cloudflare only | Browsers, OSs, Cloudflare | | Use Case | Cloudflare ↔ Origin only | Any direct client | | Direct Browser Access | Shows certificate errors if users bypass Cloudflare | ✅ Works normally | | Requires CF Proxy | ✅ Yes | ❌ No | | Works Without CF | ❌ No | ✅ Yes | | Issuer | Cloudflare | Public CA (eg: Let's Encrypt) | | Cost | Free | Free | | DNS Challenge | ❌ No | ✅ Yes | If you plan to have Cloudflare always in front of your application, use a Cloudflare Origin Certificate. Otherwise, use a Public CA Cert. There are 2 ways to setup the Origin TLS Certificate so follow one of the methods from below: A simple high-level overview diagram to give you a visual idea of how this works: *** A. Create Cloudflare Origin Certificate [!toc] [#a-create-cloudflare-origin-certificate-toc] 1. In your Cloudflare dashboard, go to **SSL/TLS**. 2. Select **Origin Server**. 3. Select **Origin Certificates** 4. Click the **Create Certificate** button. 1. Choose **RSA (2048)** for the key type. 2. Add the hostnames you want the certificate to cover. 3. Set the certificate validity to **15 years**. 4. Click the **Create** button. * **`shadowarcanist.com`** will cover only the main domain. * **`*.shadowarcanist.com`** will cover all subdomains. On Cloudflare’s free plan, wildcard certificates cover just one level of subdomains For example, it works for **`coolify.shadowarcanist.com`** but not **`www.coolify.shadowarcanist.com`**. To cover multiple levels, you'll need to purchase the [Advanced Certificate Manager ↗](https://www.cloudflare.com/application-services/products/advanced-certificate-manager/) 1. Choose **PEM** as the key format. 2. Copy your **Origin Certificate** and save it somewhere safe 3. Copy your **Private Key** and save it somewhere safe 4. Click the **Ok** button. Next, you'll add these to your server running Coolify and configure Coolify to use this certificate. *** B. Add Certificate to Your Server [!toc] [#b-add-certificate-to-your-server-toc] SSH into your server or use Coolify's terminal feature. For this guide, I’m using my external terminal: ```bash ssh shadowarcanist@203.0.113.1 ``` Once logged in, navigate to the Coolify proxy directory: ```bash $ cd /data/coolify/proxy ``` Certificate locations slightly vary between Caddy and Traefik, so choose the one based on the proxy you are using from the section below. Create the `certs` directory: ```bash $ mkdir certs ``` Verify it was created: ```bash $ ls > acme.json certs docker-compose.yml dynamic ``` Now, navigate into the **certs** directory: ```bash $ cd certs ``` Create the `caddy/data/certs` directory: ```bash $ mkdir -p caddy/data/certs ``` Verify it was created: ```bash $ ls caddy/data > certs ``` Now, navigate into the **certs** directory: ```bash $ cd caddy/data/certs ``` Create two new files for the certificate and private key: ```bash $ touch shadowarcanist.cert shadowarcanist.key ``` Verify the files were created: ```bash $ ls > shadowarcanist.cert shadowarcanist.key ``` Open the **shadowarcanist.cert** file and paste the certificate from the Cloudflare dashboard: ```bash $ nano shadowarcanist.cert ``` Save and exit after pasting the certificate. Do the same for the **shadowarcanist.key** file and paste the private key: ```bash $ nano shadowarcanist.key ``` Save and exit. Now the origin certificate is installed on your server. *** C. Configure Coolify proxy to Use the Origin Certificate [!toc] [#c-configure-coolify-proxy-to-use-the-origin-certificate-toc] 1. Go to the **Server** section in the sidebar. 2. Select **Proxy**. 3. Open the **Dynamic Configuration** page 4. Click **Add** button You will now be prompted to enter the Dynamic Configuration. Dynamic configuration file slightly varies between Caddy and Traefik, so choose the one based on the proxy you are using from the section below. 1. Choose a name for your configuration (must end with `.yaml`). 2. Enter the following details in the configuration field: ```yaml tls: certificates: - certFile: /traefik/certs/shadowarcanist.cert keyFile: /traefik/certs/shadowarcanist.key ``` 3. Save the configuration If you want to add multiple certificates and keys, you can do it like this: ```yaml tls: certificates: - certFile: /traefik/certs/shadowarcanist.cert keyFile: /traefik/certs/shadowarcanist.key - certFile: /traefik/certs/name2.cert keyFile: /traefik/certs/name2.key - certFile: /traefik/certs/name3.cert keyFile: /traefik/certs/name3.key ``` 1. Choose a name for your configuration (must end with `.caddy`). 2. Enter the following details in the configuration field: ```bash *.shadowarcanist.com, shadowarcanist.com { tls /data/certs/shadowarcanist.cert /data/certs/shadowarcanist.key } ``` The wildcard `*.shadowarcanist.com` provides coverage for all subdomains, exclude it if you’re only securing a single domain (i.e, `shadowarcanist.com`). 3. Save the configuration If you want to add multiple certificates and keys, you can do it like this: ```bash *.shadowarcanist.com, shadowarcanist.com { tls /data/certs/shadowarcanist.cert /data/certs/shadowarcanist.key } *.name2.com, name2.com { tls /data/certs/name2.cert /data/certs/name2.key } *.name3.com, name3.com { tls /data/certs/name3.cert /data/certs/name3.key } ``` From now on, Coolify will use the origin certificate for requests matching the hostname. A simple high-level overview diagram to give you a visual idea of how this works: We already have guides to set up DNS challenge for TLS certificates, you can follow them here: * [Traefik DNS challenge](/core/networking/proxy/traefik/dns-challenge) * [Caddy DNS challenge](/core/networking/proxy/caddy/dns-challenge) Come back to this guide after you finish setting up the DNS challenge using the guides above. 2\. Set Up DNS Records [#2-set-up-dns-records] To route traffic through Cloudflare, configure your DNS records in Cloudflare: 1. In Cloudflare dashboard, go to **DNS**. 2. Select **Records**. 3. Add 2 A records: 4. Enter name as **`shadowarcanist.com`** and `*` 5. Use the **IP address** of your server as the content for both records. 6. Set the proxy status to **Proxied** for both records. Enabling the "Proxied" (orange cloud) option for both A records: `shadowarcanist.com` and `*` will proxy the root domain and all one-level subdomains via a wildcard. This isn't necessary if you only need to proxy (or protect against DDoS) for a specific domain. In that case, simply enable proxying for the domain you want protection for. 3\. Set Up TLS Encryption [#3-set-up-tls-encryption] To make Cloudflare use stricter encryption when connecting to your server, configure your TLS encryption in Cloudflare: 1. Go to **SSL/TLS** in Cloudflare. 2. Select **Overview**. 3. Click **Configure** button 1. Choose **Full (Strict)** as the encryption mode. 2. Click **Save** button 4\. Set Up Always Use HTTPS [#4-set-up-always-use-https] To make Cloudflare automatically redirect HTTP requests to HTTPS, configure your redirects in Cloudflare: 1. In Cloudflare, go to **SSL/TLS** 2. Select **Edge Certificates**. 3. Enable **Always Use HTTPS**. 5\. Configure Firewall [#5-configure-firewall] This step is completely optional but recommended. Configure your firewall to allow incoming traffic on port **443** only from [Cloudflare’s IP ranges ↗](https://www.cloudflare.com/en-gb/ips/). Block all other inbound traffic, except for your SSH port. This prevents attackers from bypassing Cloudflare and directly targeting your server with traffic on ports 80 or 443. Now you’re done! Your server is set up to use Origin TLS Certificate, and all traffic is proxied through Cloudflare's network so all incoming attacks like DDoS are prevented by Cloudflare before it reaches your server. # DNS Management (/docs/integrations/security/cloudflare/dns-management) Cloudflare DNS management [#cloudflare-dns-management] Coolify can create DNS records for application and service domains using a team's Cloudflare integration tokens. It matches each hostname to an accessible Cloudflare zone and points the record at the resource's server. Add a token [#add-a-token] 1. Create a Cloudflare API token with **Zone > DNS > Edit** and **Zone > Zone > Read** for the zones you want Coolify to manage. 2. In Coolify, open **Keys & Tokens > Integration Tokens** and select **New token**, then choose **Cloudflare** in **Provider**. 3. Enter a **Token name**, paste the **API token**, and select the **DNS** capability. 4. Optionally enable **Automatically configure DNS**. New domains are configured automatically when there is one unambiguous matching credential. 5. Select **Validate and add**. Open the saved token's edit icon to review **Domains this token can manage**. Use **Refresh zones** after changing provider permissions, and **Validate and save** when editing credentials. Integration tokens belong to a team. Add the token to the team that owns the resource. This token workflow is separate from configuring a proxy's DNS challenge for certificate issuance. Manage a domain [#manage-a-domain] Open an application's or service's **Domains** page and add the hostname. Coolify matches it to zones available through the team's tokens and offers DNS configuration for that server. If a record already points elsewhere, review the existing value before using the replace action. Records created through this workflow show **Managed by Coolify**. Removing a managed domain offers deletion of its DNS record after confirmation; review other uses of the hostname before approving deletion. Re-check DNS after changing a record. Coolify replaces the previous check result, including checks for preview domains. IPv6 addresses are compared by value rather than their written form. If no zone matches, check the token's zone scope and permissions, refresh accessible zones, or configure records manually using [DNS](/core/networking/dns). # Secret Manager Credentials (/docs/integrations/security/secret-managers) Secret manager credentials [#secret-manager-credentials] Coolify supports Doppler, Infisical, and HashiCorp Vault. Add credentials under **Keys & Tokens > Integration Tokens**, then choose the token on a resource's **Environment Variables** page. Add credentials in Coolify [#add-credentials-in-coolify] 1. Open **Keys & Tokens > Integration Tokens** and select **New token**. 2. Choose **Doppler**, **Infisical**, or **HashiCorp Vault** in **Provider**. 3. Enter a **Token name** and the provider credentials described below. 4. Select **Validate and add**. To change saved credentials, select the token's edit icon and use **Validate and save**. Doppler [#doppler] Use either credential type: * **Service token:** In Doppler, open the project and config, select **Access**, and create a service token. Its scope fixes the project and config. * **Service account token:** Create a service account, grant it access to the required project/config, and generate a token. You select the project and config in Coolify. Paste the token into **API token** in Coolify. See [Doppler service tokens](https://docs.doppler.com/docs/service-tokens?utm_source=coolify.io) and [service accounts](https://docs.doppler.com/docs/service-accounts?utm_source=coolify.io). Infisical [#infisical] 1. Create a **Machine Identity** in Infisical. 2. Add **Universal Auth** to the identity and generate a client secret. 3. Grant the identity access to the project and environment containing your secrets. 4. In Coolify, enter **Base URL**, **Client ID**, and **Client secret**. For Infisical Cloud, use `https://app.infisical.com`. Self-hosted installations should use their own base URL. See [Infisical Universal Auth](https://infisical.com/docs/documentation/platform/identities/universal-auth?utm_source=coolify.io). HashiCorp Vault [#hashicorp-vault] Create a Vault policy that permits `read` and `list` on the required KV v2 secret path, then issue a token with that policy. In Coolify, enter: * **Base URL**: the Vault instance URL * **Vault token**: the token * **Namespace (optional)**: only for Vault Enterprise or HCP Vault When linking a resource, select the KV v2 mount and secret path. Use the narrowest policy possible. See [Vault tokens](https://developer.hashicorp.com/vault/docs/concepts/tokens?utm_source=coolify.io) and [policies](https://developer.hashicorp.com/vault/docs/concepts/policies?utm_source=coolify.io). Provider credentials can expose multiple secrets. Use least-privilege access, rotate credentials regularly, and do not paste them into environment variables. Next, [use the secret manager with a resource](/integrations/security/using-secret-managers). # Use a Secret Manager (/docs/integrations/security/using-secret-managers) Use a secret manager [#use-a-secret-manager] Secret managers work with applications, Docker Compose services, and standalone databases. Application support includes Git and non-Git deployment methods. 1. Add a supported provider under **Keys & Tokens > Integration Tokens**. 2. Open the resource and select **Environment Variables**. 3. Under **Secret manager**, choose an **Integration token**. For a Doppler service account, enter **Project (required)** and **Config (required)**; a service token fixes these values. For Infisical, enter **Project ID**, **Environment slug**, and **Secret path**. For Vault, enter **KV v2 mount** and **Secret path**. Source fields save when you leave the field. 4. Select **Browse keys**, then **Add as variable** beside a key or **Import all keys**. To refresh the list, select **Reload keys**. You can also add a variable manually with this value: ```dotenv API_KEY={{vault.API_KEY}} ``` 5. Deploy or restart the resource. Always use `{{vault.KEY}}`, regardless of whether the provider is Doppler, Infisical, or HashiCorp Vault. Coolify fetches values during deployment or startup. Values are held in memory and passed to the resource; Coolify does not save the fetched values in its database. A missing source or key stops the operation with a deployment error. Resolved secrets are redacted from deployment logs, including command failures. Refresh a changed secret [#refresh-a-changed-secret] Redeploy or restart the resource after changing a provider value. For application build variables, use a deployment rather than restart. Coolify skips build reuse when build-time secret references may have changed, so a deployment resolves current values rather than relying on a previously built image. Each resource can link one secret-manager source. A Service-level source applies to the whole Compose stack. If you have not created credentials yet, follow [Secret manager credentials](/integrations/security/secret-managers). # Load Balancing on Hetzner (/docs/knowledge-base/hetzner-loadbalancing) Load Balancing on Hetzner [#load-balancing-on-hetzner] Hetzner Cloud is a cloud hosting provider that offers a wide range of services. In this guide, we will show you how to deploy a load-balanced application with Coolify on Hetzner Cloud. Introduction [#introduction] Your application is growing, and you need to scale it. One of the most common ways to scale an application is to use a load balancer. A load balancer distributes incoming traffic across multiple servers, ensuring that no single server is overwhelmed. This can help improve the performance and reliability of your application. In this guide, we will show you how to deploy a load-balanced application with Coolify on Hetzner Cloud. We will use two (or more) servers to host our application and a load balancer to distribute incoming traffic. We will also show you how to set up a database server if you need one. The whole infrastructure costs around \~15€ per month. Requirements [#requirements] * A domain name managed by Hetzner Cloud * 2 (or more) servers on Hetzner Cloud * A load balancer on Hetzner Cloud * Firewall rules to restrict access to your servers * Optional: A database server on Hetzner Cloud Steps [#steps] 1. Buy Servers [#buy-servers] First, you need to buy two (or more) servers on Hetzner Cloud. You can choose the server type and location based on your requirements. Make sure to choose servers with enough resources to run your application. Make sure you create and attach a private network to your servers. This will allow your servers to communicate with each other using a private network. If you don't have an account on Hetzner Cloud, you can sign up with this [referral link](https://coolify.io/hetzner). 2. Add & validate them in Coolify [#add--validate-them-in-coolify] Once you have bought the servers, you need to add them to Coolify. You can do this by clicking on the `Add Server` button in the Coolify dashboard and following the instructions. Coolify will automatically install the necessary software on your servers. 3. Optional: Deploy your database [#optional-deploy-your-database] It is preferable to have a separate database server for your application. Not just for performance reasons, but also for security reasons. Also in this way you can connect your applications to a centralized database server. Skip this step if you don't need a database server or if you already have one hosted elsewhere. Once you have bought the database server, and added it to Coolify, deploy your preferable database type (MySQL, PostgreSQL, etc.) on it. We won't use a reverse proxy in this guide. We will bind the database to the public IP address of the server. We will use a firewall to restrict access to the database server. You can stop them on the `Server` tab and switch to a `None` proxy type. Make sure you set the `Ports Mappings` correctly to allow your application servers to connect to the database server. * PostgreSQL: `5432:5432` * MySQL: `3306:3306` * MariaDB: `3306:3306` * MongoDB: `27017:27017` 4. Deploy your applications [#deploy-your-applications] Now it's time to deploy your application on the app servers. Details of deploying your application will depend on the type of application you are deploying. With Coolify, you can attach more than one server to the same application. This will allow you to deploy your application on multiple servers. We won't use a reverse proxy in this guide. We will bind the application to the public IP address of the server, as the load balancer will handle the routing. You can stop them on the `Server` tab and switch to a `None` proxy type. Make sure you set the `Ports Mappings` correctly to forward your application ports to the public IP address of the server. If your application uses a database, make sure you update the database connection string to point to the database server. Hetzner Cloud has a private network feature that allows you to connect your servers using a private network. This can help improve the security and performance of your application. Make sure you enable the private network feature on your servers and use it in the database connection string. Test if your application is working correctly by accessing the public IP address and port of the server in your browser. 5. Add & configure the loadbalancer [#add--configure-the-loadbalancer] Now it's time to add a load balancer to distribute incoming traffic across your servers. This loadbalancer will do the following: * Distribute incoming traffic across your servers * Terminates TLS connections (makes your application secure with HTTPS and forwards the traffic to your servers over HTTP) * Health checks your servers and routes traffic to healthy servers Your application is running on `port 8000` on both servers and you have a domain name `example.com`. 1. Go to the Hetzner Cloud Console and click on `Load Balancers` in the left sidebar. 2. Click on the `Create Load Balancer` button. 3. Select a region where your servers are located. 4. Select the private network that you have created for your servers. 5. Select all servers in the targets section. **Important: `(use the private network)`.** 6. In the services, delete the default service and add a `TLS Termination` predefined service. 7. As `Destination Port` enter `8000` (source port should be `443`). 8. Add a certificate for your domain name. It will generate a certificate for your domain name using Let's Encrypt. 9. In the `health check` section, configure the health check endpoint to your application health check endpoint. (just an endpoint that returns `200 OK`). 10. Optional: Sticky sessions can be enabled, which will make sure that a user is always routed to the same server for a time period, otherwise, the load balancer will distribute the traffic randomly across your servers. 11. Choose an algorithm. 12. And finally name your load balancer and click on `Create & Buy now`. Wait for the load balancer to be created and healthy. Once it's healthy, you can check if your application is accessible via the loadbalancer's IP address. 6. Setup DNS [#setup-dns] Now it's time to point your domain name to the `load balancer's IP address`. You can do this by adding an `A` record to your domain name provider's DNS settings. 1. Go to your DNS settings. 2. Add an `A` record with the domain name and the value of the load balancer's IP address. 3. Save the changes and wait for the DNS changes to propagate. Once the DNS changes have propagated, you should be able to access your application using your domain name. 7. Setup Firewall [#setup-firewall] Hetzner Cloud offers a firewall feature that allows you to restrict access to your servers. We will use this feature to restrict access to your servers. As the load balancer communicates with your servers over the private network, we only need to add rules for the public IP addresses. The `Inbound` rules includes everything that is allowed. Everything else is blocked by default. 1. Go to the Hetzner Cloud Console and click on `Firewalls` in the left sidebar. 2. Click on the `Create Firewall` button. 3. Add SSH access rule for your IP address to the `Inbound` rules. 4. Add your servers to the `Apply rule` section. 5. Name your firewall and click on `Create Firewall`. Optional: You can add more rules to allow access to specific ports or IP addresses if needed. # macOS using Colima Setup Guide (/docs/knowledge-base/how-to/macos-colima) macOS using Colima Setup Guide [#macos-using-colima-setup-guide] This guide walks you through setting up Coolify on macOS using [Colima](https://github.com/abiosoft/colima?utm_source=coolify.io), a lightweight container runtime for macOS. Prerequisites [#prerequisites] * A Mac (Intel or Apple Silicon) * [Homebrew](https://brew.sh/?utm_source=coolify.io) installed * Remote Login enabled on your Mac — see [Apple's guide to allow remote access](https://support.apple.com/guide/mac-help/mchlp1066/mac?utm_source=coolify.io) to enable SSH in **System Settings > General > Sharing > Remote Login** * An SSH key without a passphrase The SSH key used for Coolify must not have a passphrase or 2FA enabled, otherwise you will not be able to complete the onboarding process. Install Colima [#install-colima] 1. Install Colima and Docker using Homebrew: ```bash brew install colima docker ``` 2. Verify the installation: ```bash colima version ``` Create the Virtual Machine [#create-the-virtual-machine] 1. Start a new Colima VM with the minimum resources: ```bash colima start -c 2 -m 2 -d 30 --ssh-port 2222 --network-address --network-mode bridged --save-config ``` This creates a VM with: * **2 CPU cores** (`-c 2`) * **2 GB of memory** (`-m 2`) * **30 GB of disk space** (`-d 30`) * **SSH on port 2222** (`--ssh-port 2222`) * **Bridged networking** (`--network-address --network-mode bridged`) — the VM gets its own IP from your router * **Save configuration** (`--save-config`) — persists these settings so future `colima start` commands use the same configuration You can adjust these values based on your needs. These are recommended minimums for running Coolify along with a few services. 2. Verify the VM is running: ```bash colima status ``` Networking [#networking] Colima supports two network modes: **bridged** (recommended) and **shared**. Bridged Mode (Default in This Guide) [#bridged-mode-default-in-this-guide] The command above uses `--network-address --network-mode bridged`, which assigns the VM an IP address directly from your router's DHCP server. This makes the VM behave like a separate device on your network, allowing other devices on your LAN to reach Coolify. By default, bridged mode uses the `en0` interface. If your Mac uses a different network interface, specify it with `--network-interface `. You can find the VM's IP address with: ```bash colima list ``` Shared Mode [#shared-mode] If you don't need Coolify to be accessible from other devices on your network — for example, if you plan to use [Tailscale](https://tailscale.com/?utm_source=coolify.io) or only need to access Coolify from your Mac — you can omit the network flags: ```bash colima start -c 2 -m 2 -d 30 --ssh-port 2222 --save-config ``` In shared mode, the VM gets an IP on a private subnet that is only reachable from the host Mac. SSH Configuration [#ssh-configuration] Coolify connects to servers via SSH. Since we specified `--ssh-port 2222` when creating the VM, the SSH port is fixed and won't change between restarts. You can verify the SSH configuration at any time with: ```bash colima ssh-config ``` This outputs the full SSH config, including the **hostname**, **port**, **user**, and **identity file** the VM is configured with. Use the hostname and port from the output when adding the server in Coolify's onboarding or server settings. If you omit `--ssh-port` when creating the VM, Colima assigns a random free port that may change on restart. Use `colima ssh-config` to check the current port. Install Coolify [#install-coolify] 1. SSH into the Colima VM: ```bash colima ssh ``` 2. Inside the VM, proceed with the [Coolify self-hosted setup](/start-with-self-hosted#quick-installation-recommended). 3. Once the installation completes, access the Coolify web interface depending on your network mode: * **Bridged mode**: Open `http://:8000` from any device on your network. * **Shared mode**: Open `http://:8000` from your Mac only (the VM is not reachable from other devices). Find the VM's IP address with `colima list`. 4. In the Coolify web interface, go to your server settings and set the **SSH port** to the port you specified when creating the VM (e.g., `2222`). Coolify uses this port to manage the server via SSH. Starting Fresh [#starting-fresh] If something goes wrong and you want to start over, you can delete the VM and recreate it. * Delete the VM but keep its disk data: ```bash colima delete ``` * Delete the VM and all its data: ```bash colima delete --data ``` After deleting, go back to [Create the Virtual Machine](#create-the-virtual-machine) to set up a new VM. Post-Install Steps [#post-install-steps] Start Colima Automatically on Boot [#start-colima-automatically-on-boot] To have Colima start automatically when your Mac boots: ```bash brew services start colima ``` # Deploy Webstudio Projects to Hetzner with Coolify (/docs/knowledge-base/how-to/webstudio-with-hetzner) Deploy Webstudio Projects using Coolify [#deploy-webstudio-projects-using-coolify] Coolify makes deploying your Webstudio projects to Hetzner as simple as it is powerful. In this guide, you’ll learn how to set up your project, deploy it on a Hetzner server, and keep your infrastructure fully under your control, all with a few straightforward steps. In this guide, we are using servers from Hetzner. However, if you're using a different hosting provider, you can still follow this guide with their servers as well. If you prefer watching a video instead of reading, you can check out the [tutorial video](https://youtu.be/OnHLO2Plt2E?si=yDM77oK7Xd5UsRSP) What You’ll Need [#what-youll-need] Before you start, make sure you have: * A [GitHub account](https://github.com?utm_source=coolify.io) to host your code. * A [Hetzner account](https://coolify.io/hetzner) to provision your server (or an account with any other hosting provider). * The [Webstudio CLI](https://docs.webstudio.is/university/self-hosting/cli?utm_source=coolify.io) installed locally to manage your project exports. 1\. Create Your GitHub Repository [#1-create-your-github-repository] Start by [creating a new repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository) on GitHub where you’ll store your Webstudio project code. Once the repository is created, [clone the repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) to your local machine to start developing locally. 2\. Export Your Webstudio Project [#2-export-your-webstudio-project] Using the Webstudio [CLI](https://docs.webstudio.is/university/self-hosting/cli), export your project and select the "**Docker**" option. This prepares your project for deployment via Coolify without the need for additional dependency installations. 3\. Push Your Code to GitHub [#3-push-your-code-to-github] With your project exported locally, [push your code](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository) to the GitHub repository you created. This makes your project accessible for deployment. 4\. Set Up Your Hetzner Server [#4-set-up-your-hetzner-server] If you already have a server, you don't need to purchase a new one. **Webstudio recommends** that your server should have at least **1 CPU and 2GB of RAM** for smooth operation. Skip to [Step 6](#_6-configure-your-project-on-coolify) if your server is already connected to Coolify. Follow these steps to prepare your Hetzner server: 1. **Create a New Server:** Log into [Hetzner Cloud Dashboard ↗](https://console.hetzner.cloud/) and create a new server. 1. **Choose Your Region:** Select the region that best suits your needs. 1. **Select Ubuntu:** Pick an Ubuntu image (make sure it’s a Docker-supported version, check the [Docker Ubuntu requirements](https://docs.docker.com/engine/install/ubuntu/#os-requirements)). 1. **Configure Resources:** A shared CPU with at least 2 GB RAM is recommended. 1. **Allocate an IPv4 Address:** Make sure your server has a dedicated IPv4 address. 1. **Finalize Setup:** Click **Create and Buy Now** and wait until your server is provisioned. 2. **Save the IP:** Copy your server’s IPv4 address, it will be needed shortly. 5\. Connect Coolify to Your Server [#5-connect-coolify-to-your-server] If your server is already connected to Coolify, skip to the [next step](#_6-configure-your-project-on-coolify). 1. **Add Private Key:** Login to your Coolify account (or create one if you’re new) and Add a new private key
2. **Add a Server:** Navigate to the **Servers** tab and add a new server by entering your Hetzner server’s IPv4 address.
3. **Validate Server:** Click **Validate Server & Install Docker Engine**. Coolify will automatically install all necessary components on your server. 4. **Check Status:** Once finished, you should see a green **Proxy Running** status indicating everything is set up. 6\. Configure Your Project on Coolify [#6-configure-your-project-on-coolify] 1. **Create a New Project:** Head to the **Projects** section and create a new project. 2. **Add a Resource:** Add a new resource, selecting your GitHub repository as the source. 3. **Connect Your Repository:** Use the GitHub app integration to grant access to your repository. 4. **Select Build Pack:** Change the Build Pack to **Dockerfile** and click on continue button. 5. **Configure Domains & Deploy:** Enter your domain in the domains field and Click **Deploy** and wait as Coolify builds and deploys your project. 6. **Successful Deployment:** When deployment is complete, you’ll see a “Deployment is Finished” message. 7. **Access Your Site:** Use the **links** button at the top of the project dashboard to visit your live site. 8. **Optional – Third-Party Domains:** If your project loads images from external sources, add those domains as a comma-separated list under the environment variable `DOMAINS`. (make sure to restart the application after adding the variable) 7\. Update Your Webstudio Site [#7-update-your-webstudio-site] To publish updates and keep your site up to date, follow these steps: 1. **Publish Changes:** In the Webstudio builder, click **Publish** to generate the latest build data. 2. **Sync and Build:** Run the following commands in your terminal: ```bash webstudio sync webstudio build --template docker ``` 3. **Push Updates:** Commit and push your changes to GitHub. Coolify will detect the update and automatically trigger a new deployment. Now you’re all set! # Overview (/docs/knowledge-base) Overview [#overview] **This Knowledge Base sections is in active development, some contents may not be up to date. They will be updated soon.** **Browse through the pages on the sidebar on this knowledge base section for more information.** # Node.js Multi-Core Scaling (/docs/knowledge-base/nodejs-multi-core-scaling) Node.js Multi-Core Scaling [#nodejs-multi-core-scaling] The Problem [#the-problem] JavaScript runtimes execute their event loop on a **single thread per process**. One `node app.js` (or `bun`/`deno`) process saturates **one CPU core**, regardless of host capacity — whether it's serving HTTP, processing queues, running cron jobs, or doing CPU-bound work. This applies to every major JS runtime: | Runtime | Engine | Single-threaded event loop | | ------- | -------------- | -------------------------- | | Node.js | V8 | Yes | | Bun | JavaScriptCore | Yes | | Deno | V8 | Yes | It's a runtime characteristic, not a platform limit — the same constraint applies on bare metal, Docker, Kubernetes, or any PaaS. By default, Coolify does not limit container CPU, so all host cores are available — you only need to tell your runtime to use them. The Fix [#the-fix] Run **multiple worker processes** inside the container. Each runtime has its preferred mechanism: | Runtime | Approach | Code Change | Notes | | ------- | --------------------------------- | ------------------- | ------------------------------------------ | | Node.js | **PM2 cluster mode** | None | Easiest; wraps your existing start command | | Node.js | `node:cluster` module | App-level | Built-in, no extra dependency | | Bun | `Bun.serve({ reusePort: true })` | One-line app change | Kernel load-balances via `SO_REUSEPORT` | | Deno | `Deno.serve({ reusePort: true })` | One-line app change | Same kernel mechanism as Bun | This guide covers **PM2 cluster mode** (Node.js) and **`reusePort`** (Bun, Deno), with examples for the [Dockerfile](/applications/builds/dockerfile) and [Nixpacks](/applications/builds/nixpacks/overview) build packs. Technical Background [#technical-background] * V8's (and JavaScriptCore's) event loop is single-threaded **per process**. * libuv's thread pool (4 threads by default in Node) offloads some I/O work, but your JavaScript still runs on a single core. * To use more than one core you need either multiple processes inside the container, or a runtime that supports multi-process listeners (Bun and Deno via `reusePort`). Dockerfile Example (PM2 Cluster Mode) [#dockerfile-example-pm2-cluster-mode] Use this when your app is built with the [Dockerfile build pack](/applications/builds/dockerfile). ```dockerfile FROM node:lts-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev && npm install -g pm2 COPY . . EXPOSE 3000 CMD ["pm2-runtime", "-i", "max", "dist/index.js"] ``` Key points: * `pm2-runtime -i max` forks one worker per available CPU core and keeps PM2 in the foreground (required because Docker's PID 1 must not exit). * Replace `dist/index.js` with your actual entry file. * Expose the port your app listens on (`3000` here) in your platform's networking settings — in Coolify, this is the **Ports Exposes** field. Nixpacks Example [#nixpacks-example] Use this when your app is built with the [Nixpacks build pack](/applications/builds/nixpacks/overview). Set the following environment variable on your application (in Coolify: open your application → **Environment Variables**): ``` NIXPACKS_START_CMD=pm2-runtime -i max dist/index.js ``` Then add `pm2` to the `dependencies` section of `package.json` so Nixpacks installs it during the build. ```toml [phases.setup] nixPkgs = ["nodejs", "pm2"] [start] cmd = "pm2-runtime -i max dist/index.js" ``` This keeps the multi-core configuration in version control and works across local and remote builds. Bun Alternative (One-Line Multi-Core) [#bun-alternative-one-line-multi-core] Bun's HTTP server can bind the same port across multiple processes using `SO_REUSEPORT`. Run N Bun processes and the kernel load-balances incoming connections between them. App Code [#app-code] ```js Bun.serve({ port: 3000, reusePort: true, fetch(req) { return new Response("Hello from Bun"); }, }); ``` Build configuration [#build-configuration] ```dockerfile FROM oven/bun:alpine WORKDIR /app COPY package.json bun.lock ./ RUN bun install --production COPY . . EXPOSE 3000 # Spawn one Bun process per available core. CMD ["sh", "-c", "for i in $(seq 1 $(nproc)); do bun run server.js & done; wait"] ``` ```toml [phases.setup] nixPkgs = ["bun"] [start] cmd = "sh -c 'for i in $(seq 1 $(nproc)); do bun run server.js & done; wait'" ``` Notes: * `reusePort: true` requires Linux kernel ≥ 3.9 (all modern distros). * Each Bun process is independent — there's no primary/worker IPC, so use Redis or a database for shared state. * Simpler than PM2 but has no built-in auto-restart per worker; pair with Docker's `restart: unless-stopped` (Coolify's default) for crash recovery of the parent shell. Deno Alternative (One-Line Multi-Core) [#deno-alternative-one-line-multi-core] Deno's `Deno.serve` accepts the same `reusePort` flag, so you can spawn N processes that all bind the same port and let the kernel distribute connections. App Code [#app-code-1] ```ts Deno.serve({ port: 3000, reusePort: true }, (_req) => { return new Response("Hello from Deno"); }); ``` Build configuration [#build-configuration-1] ```dockerfile FROM denoland/deno:alpine WORKDIR /app COPY . . RUN deno cache server.ts EXPOSE 3000 # Spawn one Deno process per available core. CMD ["sh", "-c", "for i in $(seq 1 $(nproc)); do deno run --allow-net server.ts & done; wait"] ``` ```toml [phases.setup] nixPkgs = ["deno"] [start] cmd = "sh -c 'for i in $(seq 1 $(nproc)); do deno run --allow-net server.ts & done; wait'" ``` Same caveats as Bun apply: no IPC between processes, no built-in per-worker restart. Caveats [#caveats] Workers do **not** share in-process memory. Sessions, in-memory caches, rate-limit counters, and WebSocket connection maps must move to Redis or another external store. * **WebSockets:** connections are split across workers. Use sticky sessions at the proxy layer, or move pub/sub to Redis so any worker can deliver messages. * **Graceful shutdown:** honor `SIGTERM` in each worker. PM2 does this automatically. * **Memory:** scales roughly linearly — N workers ≈ N × single-process RSS. Size the server accordingly. * **Log output:** PM2 merges logs across workers; with Bun's `reusePort` approach each process writes independently, which may interleave. Prefer structured JSON logs. Verifying Multi-Core Use [#verifying-multi-core-use] After deploying, SSH to the host running the container and inspect the processes: ```bash docker exec -it top ``` You should see multiple `node`, `bun`, or `deno` processes. Hit the app under load (for example with `autocannon -c 200 http://:3000/`) and confirm that `htop`/`top` shows load spread across all host cores, not pegged on one. # Applications (/docs/mcp/capabilities/applications) Applications [#applications] | Tool | Purpose | | :-------------------------- | :------------------------------------------------------------------------------------- | | `list_applications` | List applications with filters for tag, project, environment, server, status, or name. | | `get_application` | Inspect one application by UUID. | | `list_application_previews` | List pull-request preview deployments for an application. | Application details can include configuration metadata. Environment values and other sensitive fields remain subject to token permissions and redaction. # Automation (/docs/mcp/capabilities/automation) Automation [#automation] | Tool | Purpose | | :------------------------------- | :-------------------------------------------------------------------------------------------- | | `list_scheduled_tasks` | List scheduled tasks for an application or service. | | `list_scheduled_task_executions` | List recent executions for a scheduled task. | | `list_unhealthy_resources` | Find resources that appear unhealthy or down; use `sample_only=true` for a cheap first check. | | `get_infrastructure_overview` | Return SQL-based health-hint counts and open deployment counts. | Task command bodies and execution messages require `read:sensitive` and are best-effort redacted. # Databases (/docs/mcp/capabilities/databases) Databases [#databases] | Tool | Purpose | | :----------------------- | :------------------------------------------------------------------------------------- | | `list_databases` | List standalone databases with project, environment, server, status, and name filters. | | `get_database` | Inspect one database by UUID. | | `list_database_backups` | List backup schedules for a database. | | `list_backup_executions` | List executions for a scheduled database backup. | Backup execution messages require `read:sensitive` and are best-effort redacted. # Deployments (/docs/mcp/capabilities/deployments) Deployments [#deployments] | Tool | Permission | Purpose | | :------------------ | :--------- | :-------------------------------------------------------------------------------------------- | | `list_deployments` | `read` | List queued, in-progress, or application deployment history. | | `get_deployment` | `read` | Inspect one deployment; build logs are not returned. | | `deploy` | `deploy` | Queue an application deployment by UUID. Supports force rebuild and preview IDs. | | `cancel_deployment` | `deploy` | Cancel a queued or in-progress deployment. | | `control` | `deploy` | Start, stop, or restart an application, database, or service. `stop` requires `confirm=true`. | Follow [Security](/mcp/security) before granting `deploy`. Preview pull request IDs must be positive integers no greater than `2147483647`. Invalid IDs produce a validation error. See [Preview deployments](/applications/deployments/preview-deployments#manage-previews-through-the-api) for the related API workflow. # Environment and storage (/docs/mcp/capabilities/environment-and-storage) Environment and storage [#environment-and-storage] | Tool | Permission | Purpose | | :--------------------- | :--------- | :-------------------------------------------------------------------------------------------------- | | `list_env_keys` | `read` | List environment-variable key names for an application, database, or service. Never returns values. | | `list_shared_env_keys` | `read` | List shared key names at project or environment scope. Never returns values. | | `list_storages` | `read` | List persistent and file storage mounts. Never returns file contents. | Task command bodies and supported sensitive fields require `read:sensitive`. Environment values are not returned by these tools. # Integrations (/docs/mcp/capabilities/integrations) Integrations [#integrations] | Tool | Purpose | | :------------------------- | :---------------------------------------------------------------- | | `list_github_apps` | List GitHub Apps available to the team without returning secrets. | | `list_github_repositories` | List repositories through a team GitHub App. | | `list_github_branches` | List branches for a repository through a team GitHub App. | Repository and branch tools register only when a usable GitHub App exists. Call `list_github_apps` first. # Logs (/docs/mcp/capabilities/logs) Logs [#logs] | Tool | Permission | Purpose | | :--------------- | :--------------- | :------------------------------------------------------------------------------------------------------- | | `get_logs` | `read:sensitive` | Fetch recent logs for an application, database, service, or service child. | | `get_deployment` | `read:sensitive` | Optionally return a capped, best-effort-redacted deployment log summary with `include_log_summary=true`. | `get_logs` requires a running container on a reachable server. It returns up to 500 lines and may return a structured failure reason with suggested next tools. Log redaction is best effort, not a guarantee. Do not send unrestricted production logs to an AI client unless required. # Overview (/docs/mcp/capabilities/overview) Overview [#overview] Coolify MCP exposes tools, resources, and prompts for the team associated with the API token. Start with these tools [#start-with-these-tools] | Tool | Use | | :---------------------------- | :----------------------------------------------------------------- | | `coolify_help` | Find a tool by intent. | | `get_infrastructure_overview` | Get counts and health hints for the team. | | `search_resources` | Find a resource by name, UUID, or domain when its type is unknown. | | `list_unhealthy_resources` | Find resources that appear unhealthy or down. | Capability pages [#capability-pages] | Page | Covers | | :------------------------------------------------------------------- | :----------------------------------------------------------------------- | | [Teams](/mcp/capabilities/teams) | Current team and team members. | | [Servers](/mcp/capabilities/servers) | Servers, Docker destinations, hosted domains, and server resources. | | [Projects](/mcp/capabilities/projects) | Projects, environments, resources, and tags. | | [Applications](/mcp/capabilities/applications) | Applications and preview deployments. | | [Databases](/mcp/capabilities/databases) | Standalone databases and backup schedules. | | [Services](/mcp/capabilities/services) | Services and their application or database components. | | [Deployments](/mcp/capabilities/deployments) | Deployment history, deploy, cancel, start, stop, and restart operations. | | [Logs](/mcp/capabilities/logs) | Container logs and deployment log summaries. | | [Environment and storage](/mcp/capabilities/environment-and-storage) | Environment-variable names and storage mounts. | | [Integrations](/mcp/capabilities/integrations) | GitHub Apps, repositories, and branches. | | [Automation](/mcp/capabilities/automation) | Scheduled tasks, executions, health hints, and unhealthy resources. | | [Prompts and resources](/mcp/capabilities/prompts-and-resources) | Read-only MCP resources and guided prompts. | | [Pagination](/mcp/capabilities/pagination) | Page arguments and continuation responses. | All list tools return paginated data. Read [Pagination](/mcp/capabilities/pagination) before iterating through large results. # Pagination (/docs/mcp/capabilities/pagination) Pagination [#pagination] List tools accept `page` and `per_page` arguments. | Argument | Default | Maximum | | :--------- | :-----: | :-----: | | `page` | `1` | — | | `per_page` | `50` | `100` | Responses include `_pagination` with totals and a `next` object when another page exists: ```json { "_pagination": { "page": 1, "per_page": 50, "total": 120, "total_pages": 3, "next": { "args": { "page": 2, "per_page": 50 } } } } ``` Use the returned `next.args` values rather than assuming page size or total pages. Some tools use narrower input limits for specific filters. # Projects (/docs/mcp/capabilities/projects) Projects [#projects] | Tool | Purpose | | :------------------- | :----------------------------------------------------------------- | | `list_projects` | List projects with UUID, name, and description. | | `get_project` | Inspect a project, its environments, and resource counts. | | `get_environment` | Find an environment by name or UUID and return resource summaries. | | `list_resources` | List applications, services, and databases together. | | `search_resources` | Fuzzy-search projects and resources by name, UUID, or domain. | | `list_tags` | List team-owned tags. | | `list_resource_tags` | List tags attached to an application, database, or service. | # Prompts and resources (/docs/mcp/capabilities/prompts-and-resources) Prompts and resources [#prompts-and-resources] Resources [#resources] | Resource | Purpose | | :----------------------------- | :-------------------------------------------------- | | `coolify://overview` | Infrastructure overview for the authenticated team. | | `coolify://application/{uuid}` | Summary JSON for a team-owned application. | Prompts [#prompts] | Prompt | Purpose | | :------------------------- | :--------------------------------------------------------------------------------- | | `troubleshoot_application` | Guide an application diagnosis using database-first checks and optional live logs. | | `explain_failed_deploy` | Explain a failed deployment using deployment details and optional log summary. | Prompts do not expand token permissions. The tools they recommend still enforce team scope and token abilities. # Servers (/docs/mcp/capabilities/servers) Servers [#servers] | Tool | Purpose | | :--------------------- | :----------------------------------------------------------------------- | | `list_servers` | List team-visible servers; optionally filter by reachability. | | `get_server` | Inspect one server by UUID. Sensitive connection fields remain redacted. | | `get_server_domains` | List domains hosted on a server. | | `get_server_resources` | List resources defined on a server. | | `list_destinations` | List Docker destinations; optionally filter by server. | | `get_destination` | Inspect one Docker destination by UUID. | Use `get_infrastructure_overview` first for counts and server health hints. # Services (/docs/mcp/capabilities/services) Services [#services] | Tool | Purpose | | :-------------------------- | :----------------------------------------------------------------------------------------- | | `list_services` | List multi-container services with project, environment, server, status, and name filters. | | `get_service` | Inspect one service by UUID. | | `list_service_applications` | List application components in a service. | | `get_service_application` | Inspect one service application component. | | `list_service_databases` | List database components in a service. | | `get_service_database` | Inspect one service database component. | Use `get_logs` with the appropriate child resource when a service has multiple containers. # Teams (/docs/mcp/capabilities/teams) Teams [#teams] Team tools identify the team bound to the API token and list its members. | Tool | Purpose | | :------------------ | :--------------------------------------------------------------- | | `get_current_team` | Return the team associated with the token, including MCP status. | | `list_team_members` | List members of that team. | MCP never switches teams during a request. Create a separate token for each team a client must access. # Claude Code (/docs/mcp/clients/claude-code) Connect Claude Code to MCP [#connect-claude-code-to-mcp] Claude Code can connect directly to Coolify's Streamable HTTP MCP endpoint. Add the Coolify server [#add-the-coolify-server] Run this command from a terminal. Replace the URL and token: ```sh claude mcp add --transport http coolify https://app.coolify.io/mcp \ --header "Authorization: Bearer 67|abcthisisa123dummytoken" ``` Use a token with `read` for inspection. Add `deploy` only when Claude Code must run deployment or lifecycle operations. Verify the connection [#verify-the-connection] Start Claude Code and ask it to call `get_current_team` or `get_infrastructure_overview`. Confirm the result contains only the expected team's resources. Read [Set up MCP](/mcp/setup) for instance and team enablement, token permissions, and security requirements. # Cursor (/docs/mcp/clients/cursor) Connect Cursor to MCP [#connect-cursor-to-mcp] Cursor supports remote MCP servers over Streamable HTTP. Add Coolify in Cursor [#add-coolify-in-cursor] 1. Open Cursor settings. 2. Open **Tools & Integrations** and select **MCP**. 3. Add a new remote MCP server. 4. Set the URL to `https://app.coolify.io/mcp`. 5. Set the Authorization header to `Bearer 67|abcthisisa123dummytoken`. 6. Save the server and enable it. Use a token with `read` for inspection. Add `deploy` only when Cursor must run deployment or lifecycle operations. Verify the connection [#verify-the-connection] Ask Cursor to call `get_current_team` or `get_infrastructure_overview`. Confirm the result contains only the expected team's resources. Read [Set up MCP](/mcp/setup) for instance and team enablement, token permissions, and security requirements. # Other MCP clients (/docs/mcp/clients/other-clients) Connect other MCP clients [#connect-other-mcp-clients] Any MCP client that supports remote Streamable HTTP servers can connect to Coolify. Required configuration [#required-configuration] ```yaml server_url: https://app.coolify.io/mcp transport: streamable-http authorization: Bearer 67|abcthisisa123dummytoken ``` Client configuration formats differ. Follow your client's documentation for adding a remote server and setting HTTP headers. Verify the connection [#verify-the-connection] Call `get_current_team` or `get_infrastructure_overview`. If the client cannot connect, check [Troubleshooting](/mcp/troubleshooting). # How MCP works (/docs/mcp/how-mcp-works) How MCP works [#how-mcp-works] Coolify exposes an MCP server at `/mcp`. An MCP-compatible client sends Streamable HTTP requests to that endpoint with a Coolify API token. Connection flow [#connection-flow] 1. Enable MCP for the Coolify instance. 2. Keep MCP enabled for the team the token belongs to. 3. Create an API token for that team. 4. Configure the client with the endpoint and Bearer token. 5. The client negotiates MCP capabilities and calls tools, reads resources, or uses prompts. Authentication and scope [#authentication-and-scope] The client sends the complete token as a Bearer credential: ```http Authorization: Bearer 67|abcthisisa123dummytoken ``` The token is bound to one Coolify team. MCP only returns resources owned by that team. Create one token per team when a client needs access to multiple teams. The instance MCP setting must be enabled before `/mcp` responds. Team owners can disable MCP for individual teams. A disabled instance returns `404`; a disabled team returns `403`. MCP primitives [#mcp-primitives] Tools perform Coolify queries and operations. Read tools need `read`. Deployment and lifecycle tools need `deploy`. [MCP capabilities](/mcp/capabilities/overview) groups tools by task. Resources are read-only addresses that an MCP client can request directly. Coolify currently exposes an infrastructure overview and application summary resources. Prompts give clients guided workflows. Coolify provides prompts for troubleshooting applications and explaining failed deployments. Response boundaries [#response-boundaries] Coolify returns structured responses with `data` and may include `_pagination`, `_actions`, or failure details. Environment values, configuration snapshots, and full deployment logs are not returned. Log summaries are capped and best-effort redacted. # Overview (/docs/mcp/overview) MCP overview [#mcp-overview] Coolify MCP connects compatible AI clients to your Coolify instance over Streamable HTTP. Read the pages below in order to learn how MCP works, set it up, and connect a client. Start here [#start-here] 1. Read [What is MCP?](/mcp/what-is-mcp) to understand tools, resources, prompts, and scope. 2. Read [How MCP works](/mcp/how-mcp-works) to understand authentication and team boundaries. 3. Follow [Set up MCP](/mcp/setup) to enable the endpoint and create a token. 4. Configure [Claude Code](/mcp/clients/claude-code), [Cursor](/mcp/clients/cursor), or [another MCP client](/mcp/clients/other-clients). Find capabilities [#find-capabilities] After connecting a client, use [MCP capabilities](/mcp/capabilities/overview) to find tools by task. Start with `coolify_help`, `get_infrastructure_overview`, or `search_resources`. Continue learning [#continue-learning] # MCP security (/docs/mcp/security) MCP security [#mcp-security] MCP gives an AI client access to Coolify data and, when permitted, lifecycle operations. Treat the token as a password. Use least privilege [#use-least-privilege] | Need | Permission | | :--------------------------------------------- | :-------------------------------------- | | Inspect resources | `read` | | Read supported sensitive data or log summaries | `read:sensitive` | | Deploy, start, stop, restart, or cancel | `deploy` | | Change the instance MCP setting | `root` token for the enable/disable API | Do not use a `root` token for normal MCP access. Team scope [#team-scope] A token belongs to one team. MCP cannot use that token to read another team's resources. Team owners can disable MCP for their team without disabling the instance endpoint. Protect client configuration [#protect-client-configuration] * Store tokens in the client's secret storage. * Do not commit MCP configuration containing a token. * Do not paste tokens into prompts or chat transcripts. * Restrict access to the machine and user account running the client. * Revoke the token immediately if exposed. MCP responses never return environment values or file contents. Log and deployment summaries can still contain operational data; redaction is best effort. # Set up MCP (/docs/mcp/setup) Set up MCP [#set-up-mcp] Set up Coolify MCP by enabling the instance endpoint, confirming team access, creating a token, and adding the endpoint to your AI client. Before you begin [#before-you-begin] * Use Coolify Cloud or a self-hosted Coolify instance with a public HTTPS URL. * On self-hosted Coolify, enable **API access** in **Settings > Advanced**. * Choose the team whose resources the client must access. * Create an API token with the smallest required permissions. See [API tokens](/core/security/credentials/api-tokens). An MCP client can use every operation allowed by its token. Store the token in the client's secret configuration, never commit it, and revoke it if exposed. Example values [#example-values] This guide uses Coolify Cloud in its examples. If you use a self-hosted Coolify instance, replace `app.coolify.io` with your instance's domain in every URL, and use your own token: * **Coolify URL:** `https://app.coolify.io` * **MCP endpoint:** `https://app.coolify.io/mcp` * **API token:** `67|abcthisisa123dummytoken` Enable MCP [#enable-mcp] Coolify Cloud already has instance MCP enabled. Skip the Dashboard and API tabs, then continue to [Create an MCP token](#create-an-mcp-token). Team access remains enabled by default, but check team settings if a client receives `403`. 1. Open **Settings** in the sidebar. 2. Open **Advanced**. 3. In **API and MCP**, set **MCP server** to **Enabled**. 4. Select **Save changes**. MCP must also be enabled in the current team's settings. Open **Team > General**, set **MCP server** to **Enabled for this team**, then select **Save changes**. On a self-hosted instance, use a `root` API token to enable or disable the instance endpoint. Replace the example URL with your instance's domain: ```sh export COOLIFY_URL="https://coolify.example.com" export COOLIFY_ROOT_TOKEN="67|abcthisisa123dummytoken" curl --fail-with-body --request POST \ --header "Authorization: Bearer $COOLIFY_ROOT_TOKEN" \ "$COOLIFY_URL/api/v1/mcp/enable" ``` The endpoint returns `MCP server enabled.`. Disable it with `POST /api/v1/mcp/disable`. These endpoints require a `root` token. A `read` or `write` token cannot change the instance MCP setting. Create an MCP token [#create-an-mcp-token] Create a token from **Keys & Tokens > API Tokens** while the required team is active. Coolify displays the complete token only once. Copy it into the client's secret configuration before leaving the API Tokens page. * Use `read` for inventory and inspection. * Add `read:sensitive` only for supported sensitive data or log summaries. * Add `deploy` for deploy, start, stop, restart, or cancel operations. * Do not use `root` for normal MCP clients. MCP endpoint URL: ```txt https://app.coolify.io/mcp ``` Connect a client [#connect-a-client] Configure the client with: * **URL:** `https://app.coolify.io/mcp` * **Transport:** Streamable HTTP * **Authorization:** `Bearer 67|abcthisisa123dummytoken` Follow a client guide: * [Claude Code](/mcp/clients/claude-code) * [Cursor](/mcp/clients/cursor) * [Other MCP clients](/mcp/clients/other-clients) Verify access [#verify-access] Ask the client to call `get_current_team` or `get_infrastructure_overview`. The response should contain the team and resources associated with the token. # Troubleshoot MCP (/docs/mcp/troubleshooting) Troubleshoot MCP [#troubleshoot-mcp] Set **MCP server** to **Enabled** in **Settings > Advanced > API and MCP**, then select **Save changes**. The instance endpoint returns `404` while this setting is disabled. Open **Team > General** for the token's team. Set **MCP server** to **Enabled for this team**, then select **Save changes**. Confirm the complete token appears after `Bearer`, has not expired or been revoked, and belongs to a team member. Confirm the client sends the header on every MCP request. Confirm the URL ends with `/mcp`, the instance is reachable from the client machine, HTTPS is valid, and transport is **Streamable HTTP**. Do not configure SSE or stdio for Coolify's remote endpoint. Use `read` for inspection, `read:sensitive` for supported sensitive output, and `deploy` for deployment or lifecycle operations. The token owner must retain the required team role for restricted operations. MCP returns only resources owned by the token's team. Create or use a token for the team that owns the resource. Start with `get_current_team` or `get_infrastructure_overview` to inspect the token's scope. `get_logs` requires `read:sensitive`, a running container, and a reachable server. For a failed deployment, call `get_deployment` first and request an optional log summary only when needed. # What is MCP? (/docs/mcp/what-is-mcp) What is MCP? [#what-is-mcp] Coolify's Model Context Protocol (MCP) server lets compatible AI clients inspect and operate resources in a Coolify team through a standard HTTP connection. MCP gives an AI client structured access to Coolify data. The client can ask about infrastructure, find resources, inspect deployments, read supported logs, and run lifecycle operations allowed by its API token. What MCP provides [#what-mcp-provides] | Capability | Purpose | | :-------------- | :----------------------------------------------------------------------------------------------------------- | | Tools | Let an AI client call Coolify operations such as listing applications or starting a resource. | | Resources | Provide addressable read-only data such as an infrastructure overview or application summary. | | Prompts | Provide guided workflows for tasks such as troubleshooting an application or explaining a failed deployment. | | Streamable HTTP | Connects an MCP client to Coolify at `/mcp` without a local MCP process. | What MCP does not do [#what-mcp-does-not-do] MCP does not bypass Coolify authentication, team scope, API access, token permissions, or sensitive-value redaction. Every request uses an API token and every resource belongs to the team bound to that token. Continue learning [#continue-learning] # Offers (/docs/offers) Offers [#offers] Our partners offer special discounts to the Coolify community to get started. You can find all discounts and offers from all of our partners on this page. *** Hetzner [#hetzner] Use the Coolify promo code below to get **€20** in Hetzner account credit valid for 3 months. **Credit comparison** €20 €50 The Coolify promo code is only available for new Hetzner users. # UI Screenshots (/docs/screenshots) Coolify UI Screenshots [#coolify-ui-screenshots] Below are screenshots of the current Coolify interface. Select a screenshot to zoom in. # ActivePieces (/docs/services/activepieces) What is ActivePieces [#what-is-activepieces] Your friendliest open source all-in-one automation tool, designed to be extensible through a type-safe pieces framework written in Typescript. Visual Demos [#visual-demos]
# Actual Budget (/docs/services/actualbudget) What is Actual Budget? [#what-is-actual-budget] Actual Budget is a super fast and privacy-focused app for managing your finances. At its heart is the well proven and much loved Envelope Budgeting methodology. You own your data and can do whatever you want with it. Featuring multi-device sync, optional end-to-end encryption and so much more. Screenshots [#screenshots] Links [#links] * [The official website](https://actualbudget.org/?utm_source=coolify.io) * [GitHub](https://github.com/actualbudget/actual?utm_source=coolify.io) # Affine (/docs/services/affine) What is Affine? [#what-is-affine] AFFiNE is a workspace with fully merged docs, whiteboards and databases. Get more things done, your creativity isn’t monotone. Screenshots [#screenshots] Links [#links] * [The official website](https://affine.pro/?utm_source=coolify.io) * [GitHub](https://github.com/toeverything/AFFiNE?utm_source=coolify.io) # Alexandrie (/docs/services/alexandrie) Alexandrie [#alexandrie] What is Alexandrie? [#what-is-alexandrie] Alexandrie is a self-hosted Markdown note-taking application designed for speed, offline usage, and long-term knowledge management.\ It focuses on speed, design, fast navigation in large note collections, and explicit links between documents. Features [#features] * Markdown editor with live preview * Fast full-text search, tags based organisation, hierarchy * Advanced management features for handling hundreds of documents * Simple Docker-based deployment Links [#links] * [Website](https://alexandrie-hub.fr?utm_source=coolify.io) * [GitHub](https://github.com/Smaug6739/Alexandrie?utm_source=coolify.io) * [Documentation](https://github.com/Smaug6739/Alexandrie/wiki?utm_source=coolify.io) # All Services (/docs/services/all) All Services [#all-services] Complete directory of all one-click services available in Coolify, organized by category. Administration [#administration] * [Dashy](/services/dashy) - Customizable homepage dashboard for self-hosted services. * [Glance](/services/glance) - All-in-one Home Server Dashboard. * [Heimdall](/services/heimdall) - An elegant solution to organize all your web applications. * [Homarr](/services/homarr) - Customizable browser homepage and dashboard. * [Homepage](/services/homepage) - A modern homepage for your server. * [Organizr](/services/organizr) - Homepage organizer for your server services. AI [#ai] * [AnythingLLM](/services/anythingllm) - An open-source LLM client that empowers developers to build and scale workflows quickly. * [Argilla](/services/argilla) - An open-source platform for building, training, and evaluating conversational AI models. * [Chroma](/services/chroma) - Open-source, AI-native vector database for building applications with embeddings. * [Engram](/services/engram) - Persistent memory sync server for AI coding agents (MCP). * [Flowise](/services/flowise) - Drag & drop UI to build your customized LLM flow. * [Hermes Agent](/services/hermes-agent) - Autonomous AI agent from Nous Research with persistent memory, scheduling, and a web interface. Available as a two-container WebUI stack or a single-container dashboard. * [Label Studio](/services/labelstudio) - Open source data labeling platform. * [Langflow](/services/langflow) - Open source Python-based framework for building AI applications. * [Langfuse](/services/langfuse) - Open source LLM engineering platform. * [LibreChat](/services/librechat) - Self-hosted, powerful, and privacy-focused chat UI for multiple AI models. * [Libretranslate](/services/libretranslate) - Free and open-source machine translation API. * [Litellm](/services/litellm) - Open source LLM Gateway to manage authentication, loadbalancing, and spend tracking across 100+ LLMs. All in the OpenAI format. * [LobeChat](/services/lobe-chat) - Open-source, modern AI chat framework with multi-provider support and knowledge base management. * [MetaMCP](/services/metamcp) - MCP Aggregator, Orchestrator, Middleware, Gateway in one application. * [Mindsdb](/services/mindsdb) - Machine learning platform that brings AI to databases. * [NewAPI](/services/newapi) - The next-generation LLM gateway and AI asset management system supports multiple languages. * [Ollama](/services/ollama) - A lightweight and efficient server for running large language models (LLMs) on your local machine or in the cloud. * [Open Webui](/services/open-webui) - User-friendly WebUI for LLMs, formerly Ollama WebUI. * [OpenClaw](/services/openclaw) - AI-powered coding assistant with multi-provider support and browser automation. * [Qdrant](/services/qdrant) - Open source, AI-native vector database. * [Unstructured](/services/unstructured) - Open-source platform and tools to ingest and process unstructured documents for Retrieval Augmented Generation (RAG) and model fine-tuning. * [Weaviate](/services/weaviate) - Open source, AI-native vector database. Analytics [#analytics] * [GoatCounter](/services/goatcounter) - Web analytics platform offering easy to use and meaningful privacy-friendly web analytics. * [Metabase](/services/metabase) - The simplest, fastest way to share data and analytics inside your company. * [OpenPanel](/services/openpanel) - Open source alternative to Mixpanel and Plausible for product analytics. * [Rybbit](/services/rybbit) - A lightweight, open-source web analytics tool that prioritizes user privacy by not using cookies. * [Sequin](/services/sequin) - The fastest Postgres change data capture. * [Superset](/services/superset) - Open-source data visualization and exploration platform. * [Swetrix](/services/swetrix) - Privacy-friendly and cookieless European web analytics alternative to Google Analytics. * [Umami](/services/umami) - A lightweight, open-source web analytics tool that prioritizes user privacy by not using cookies. Automation [#automation] * [ActivePieces](/services/activepieces) - Open source no-code business automation. * [Cloudflare DDNS](/services/cloudflare-ddns) - Cloudflare DNS updater for dynamic public IP addresses. * [Evolution API](/services/evolution-api) - WhatsApp API service for automation. * [Inngest](/services/inngest) - Durable workflow engine for background jobs, queues, and event-driven systems. * [Mage AI](/services/mage-ai) - Build, run, and manage data pipelines for integrating and transforming data. * [N8N](/services/n8n) - Workflow automation tool. * [Trigger](/services/trigger) - Open-source workflow automation tool. Backup [#backup] * [Databasus](/services/databasus) - A free, open source and self-hosted tool to backup PostgreSQL, MySQL and MongoDB with multiple storage backends. * [Duplicati](/services/duplicati) - A free backup client that securely stores encrypted, incremental, compressed backups on cloud storage services and remote file servers. Bookmarks [#bookmarks] * [Linkding](/services/linkding) - A self-hosted bookmark manager designed to be minimal, fast, and easy to set up. Browser [#browser] * [Firefox](/services/firefox) - Firefox browser in a container. Business [#business] * [Chaskiq](/services/chaskiq) - Open source customer engagement platform. * [Chatwoot](/services/chatwoot) - Open-source customer engagement suite. * [Documenso](/services/documenso) - Open-source DocuSign alternative for document signing. * [Docuseal](/services/docuseal) - Open source DocuSign alternative. * [Dolibarr](/services/dolibarr) - Open-source ERP and CRM software. * [Easyappointments](/services/easyappointments) - Open-source appointment scheduler. * [EspoCRM](/services/espocrm) - A free and open-source CRM platform. * [Fider](/services/fider) - An open platform to collect and organize customer feedback. * [Freescout](/services/freescout) - Help desk and customer support application. * [GLPI (Gestionnaire Libre de Parc Informatique)](/services/glpi) - Free, open-source IT Service Management platform for asset management, helpdesk, and service desk operations. * [Invoice Ninja](/services/invoice-ninja) - Invoice management system. * [Kimai](/services/kimai) - An open-source time-tracking solution for teams of all sizes. * [LimeSurvey](/services/limesurvey) - The most popular FOSS online survey tool on the web. * [Odoo](/services/odoo) - Open source ERP and CRM. * [OrangeHRM](/services/orangehrm) - Free HR management system for businesses. * [Osticket](/services/osticket) - Open-source help desk ticketing system. * [Paymenter](/services/paymenter) - Open-Source Billing, Built for Hosting Providers. * [Snipe-IT](/services/snipe-it) - A free open source IT asset/license management system. * [Twenty](/services/twenty) - Open-source CRM designed to fit your unique business needs. CMS [#cms] * [ClassicPress](/services/classicpress) - A business-focused CMS with a strong community. * [Cockpit](/services/cockpit) - Headless CMS with REST & GraphQL APIs. * [Directus](/services/directus) - An open-source headless CMS and API for custom databases. * [Drupal](/services/drupal) - Open-source content management system. * [Ghost](/services/ghost) - A professional publishing platform. * [Joomla](/services/joomla) - Open-source content management system. * [Strapi](/services/strapi) - Open-source headless CMS. * [WordPress](/services/wordpress) - Website and blogging platform. Communication [#communication] * [GoWa](/services/gowa) - Golang WhatsApp - Built with Go for efficient memory use. * [Matrix](/services/matrix) - Chat securely with your family, friends, community. * [Mattermost](/services/mattermost) - Open-source messaging platform for teams. * [Once Campfire](/services/once-campfire) - Web-based chat application. * [Rocket.Chat](/services/rocketchat) - Open source team chat software. * [Soju](/services/soju) - User-friendly IRC bouncer with modern features. Crypto [#crypto] * [Bitcoin Core](/services/bitcoin-core) - Bitcoin Core full node software. Database [#database] * [Autobase](/services/autobase) - Open-source alternative to cloud-managed databases for PostgreSQL (self-hosted DBaaS). * [ElectricSQL](/services/electricsql) - Sync shape-based subsets of your Postgres data over HTTP * [InfluxDB](/services/influxdb) - Open-source time series database for metrics, events, and IoT data. * [NocoDB](/services/nocodb) - Open Source Airtable Alternative. * [PG Back Web](/services/pgbackweb) - Effortless PostgreSQL backups with a user-friendly web interface. * [Teable](/services/teable) - No-code database built on PostgreSQL. Design [#design] * [Penpot](/services/penpot) - Open Source design & prototyping platform. Development [#development] * [Apprise API](/services/apprise-api) - RESTful API for Apprise notification library. * [Appsmith](/services/appsmith) - A low-code application platform for building internal tools. * [Appwrite](/services/appwrite) - A backend-as-a-service platform that simplifies the web & mobile app development. * [Browserless](/services/browserless) - Headless Chrome as a service. * [Budibase](/services/budibase) - Low-code platform for building internal tools and business apps. * [Bugsink](/services/bugsink) - Self-hosted Error Tracking * [Cloudbeaver](/services/cloudbeaver) - Universal database tool with web interface. * [Code Server](/services/code-server) - Run VS Code on any machine anywhere and access it in the browser. * [Convex](/services/convex) - Backend platform for web developers. * [Denokv](/services/denokv) - Deno's built-in key-value database service. * [Docker Registry](/services/docker-registry) - A Docker registry to store and manage your Docker images. * [Dozzle](/services/dozzle) - Realtime log viewer for docker containers. * [Drizzle Gateway](/services/drizzle-gateway) - Drizzle Studio for exploring SQL databases. * [Flipt](/services/flipt) - Open-source feature flag management platform. * [Forgejo](/services/forgejo) - A self-hosted Git service fork of Gitea. * [Formbricks](/services/formbricks) - A form builder for static sites. * [Gitea](/services/gitea) - A painless self-hosted Git service. * [GitHub Runner](/services/github-runner) - A GitHub Actions runner for Docker. * [GitLab](/services/gitlab) - DevOps lifecycle tool. * [Glitchtip](/services/glitchtip) - An open-source error tracking tool. * [Gotenberg](/services/gotenberg) - A Docker-powered stateless API for PDF files. * [Hatchet](/services/hatchet) - Platform for running background tasks and durable workflows built on Postgres. * [Heyform](/services/heyform) - Open-source form builder for conversational forms. * [Hoppscotch](/services/hoppscotch) - Open-source API development ecosystem. * [It Tools](/services/it-tools) - Collection of handy online tools for developers. * [Jenkins](/services/jenkins) - Open-source automation server. * [Jupyter Notebook Python](/services/jupyter-notebook-python) - Interactive computing environment for Python. * [Kuzzle](/services/kuzzle) - A powerful backend that enables you to build modern apps faster. * [Lowcoder](/services/lowcoder) - Open-source low-code platform for building internal tools. * [Mailpit](/services/mailpit) - Self-hosted email and SMTP testing tool. * [Marimo](/services/marimo) - Open-source reactive notebook for Python. * [Martin](/services/martin) - PostGIS vector tile server. * [Neon Ws Proxy](/services/neon-ws-proxy) - WebSocket proxy for Neon database. * [Next Image Transformation](/services/next-image-transformation) - Image transformation service for Next.js. * [Nitropage](/services/nitropage) - Nitropage is an extensible, drag-and-drop website builder based on SolidStart, completely free and open source. * [NocoBase](/services/nocobase) - The most extensible AI-powered no-code platform with total control and infinite extensibility. * [Onedev](/services/onedev) - Self-hosted Git server with integrated CI/CD and kanban. * [OpnForm](/services/opnform) - Open-source form builder that lets you create beautiful forms and share them anywhere. * [pgAdmin](/services/pgadmin) - A web-based database management tool for administering your PostgreSQL databases through a user-friendly interface. * [phpMyAdmin](/services/phpmyadmin) - MySQL database management tool. * [PocketBase](/services/pocketbase) - Open Source backend for your next SaaS and Mobile app. * [Portainer](/services/portainer) - Container management platform. * [Prefect](/services/prefect) - Open source workflow management platform. * [Privatebin](/services/privatebin) - Minimalist, open-source online pastebin. * [Proxyscotch](/services/proxyscotch) - Tiny open-source CORS proxy made by Hoppscotch. * [RabbitMQ](/services/rabbitmq) - Open source message broker. * [Redis Insight](/services/redis-insight) - Official Redis GUI that lets you do both GUI- and CLI-based interactions in a fully-featured desktop GUI client. * [Rivet Engine](/services/rivet-engine) - Backend engine for running stateful actors at scale with automatic scaling and distributed state management. * [Shlink](/services/shlink) - The open source URL shortener. * [Soketi](/services/soketi) - Open-source WebSocket server. * [Soketi App Manager](/services/soketi-app-manager) - Manage Soketi apps with application configuration and WebSocket server administration interface. * [Sonatype Nexus](/services/nexus) - A repository manager that allows you to store, manage, and distribute your software artifacts. * [Supabase](/services/supabase) - Open source Firebase alternative. * [Tolgee](/services/tolgee) - Open source localization platform. * [TrailBase](/services/trailbase) - Blazingly fast Rust/SQLite/Wasmtime app server with type-safe APIs. * [Unleash](/services/unleash) - Open-source feature management platform. * [Vvveb](/services/vvveb) - Powerful website builder with drag and drop functionality. * [Wakapi](/services/wakapi) - Open-source coding activity tracker. * [Web Check](/services/web-check) - All-in-one website analysis tool. * [Weblate](/services/weblate) - Web-based translation tool. * [Windmill](/services/windmill) - Open-source developer platform. * [Zero](/services/zero) - Query-driven sync engine for TypeScript apps backed by Postgres. Documentation [#documentation] * [Bookstack](/services/bookstack) - Self-hosted wiki-style documentation platform. * [Docmost](/services/docmost) - Open-source document collaboration platform. * [DokuWiki](/services/dokuwiki) - A simple to use and highly versatile Open Source wiki software that doesn't require a database. * [Mediawiki](/services/mediawiki) - A free and open-source wiki software package. * [Paperless](/services/paperless) - Document management system that transforms physical documents into searchable online archives. * [Stirling PDF](/services/stirling-pdf) - Powerful PDF manipulation tool. * [Wikijs](/services/wikijs) - Modern and powerful wiki software built on Node.js. Education [#education] * [Moodle](/services/moodle) - Open-source learning platform. Email [#email] * [Bulwark](/services/bulwark) - Modern webmail client for Stalwart Mail Server built on the JMAP protocol. * [Open Archiver](/services/open-archiver) - Self-hosted, open-source email archiving solution with full-text search. * [Sessy](/services/sessy) - Email observability platform for monitoring Amazon SES deliveries, bounces, and more. * [Stalwart](/services/stalwart) - All-in-one mail server with SMTP, IMAP, POP3, JMAP, Sieve, built-in anti-spam, and a web admin interface. * [Usesend](/services/usesend) - Open-source email recall service. Family [#family] * [Gramps Web](/services/gramps-web) - The free, open-source genealogy system. File Management [#file-management] * [Chibisafe](/services/chibisafe) - A beautiful and performant vault to save all your files in the cloud. * [Filebrowser](/services/filebrowser) - A file manager for the web. * [FileFlows](/services/fileflows) - A automatic file processing service. * [SFTPGo](/services/sftpgo) - Event-driven SFTP, FTP/S, HTTP/S and WebDAV server. * [Syncthing](/services/syncthing) - Open Source Continuous File Synchronization. * [Zipline](/services/zipline) - Next generation ShareX / File upload server File Sharing [#file-sharing] * [Pairdrop](/services/pairdrop) - Local file sharing in your browser. * [Pydio Cells](/services/pydio-cells) - File sharing platform for organizations. * [Snapdrop](/services/snapdrop) - Local file sharing in your browser. Finance [#finance] * [Actual Budget](/services/actualbudget) - A local-first personal finance tool based on zero-based budgeting. * [BudgE](/services/budge) - A budgeting personal finance app. * [Firefly III](/services/firefly) - A personal finances manager. * [Sure](/services/sure) - An all-in-one personal finance platform. Forum [#forum] * [Nodebb](/services/nodebb) - Node.js based forum software. Gaming [#gaming] * [Foundryvtt](/services/foundryvtt) - Virtual tabletop for tabletop role-playing games. * [Minecraft](/services/minecraft) - Minecraft game server. * [Palworld](/services/palworld) - Dedicated server for Palworld multiplayer survival game with creature collection and base building. * [Satisfactory](/services/satisfactory) - Game server for Satisfactory open-world factory building game with a dash of exploration and combat. * [Terraria Server](/services/terraria-server) - Docker multi-arch image for Terraria game server. * [Wings](/services/wings) - Pterodactyl server control daemon for standalone game server node deployments. Health [#health] * [BabyBuddy](/services/babybuddy) - It helps parents track their baby's daily activities, growth, and health with ease. * [SparkyFitness](/services/sparkyfitness) - A comprehensive fitness app that helps users track nutrition, exercise, and body metrics. Home [#home] * [Grocy](/services/grocy) - A self-hosted groceries & household management solution for your home. * [Home Assistant](/services/home-assistant) - Open-source home automation platform focused on local control and privacy. * [Homebox](/services/homebox) - Inventory and organization system built for the Home User. * [Mealie](/services/mealie) - Self-hosted recipe manager and meal planner. IoT [#iot] * [EMQX Enterprise](/services/emqx-enterprise) - Scalable, distributed MQTT messaging platform for IoT. * [ESPHome](/services/esphome) - Open-source firmware framework for WiFi-enabled microcontrollers. * [Mosquitto](/services/mosquitto) - Open-source MQTT broker. * [Traccar](/services/traccar) - Open-source GPS tracking platform. Marketing [#marketing] * [Listmonk](/services/listmonk) - Self-hosted newsletter and mailing list manager. * [Plunk](/services/plunk) - Self-hosted email marketing platform. Media [#media] * [Audiobookshelf](/services/audiobookshelf) - Self-hosted audiobook and podcast server. * [Calibre Web](/services/calibre-web) - Web app for browsing, reading and downloading eBooks from a Calibre database. * [Calibre Web Automated with Downloader](/services/calibre-web-automated-with-downloader) - Intuitive web interface for searching and requesting book downloads with Calibre-Web-Automated. * [Cap](/services/cap) - Cap is the open source alternative to Loom. Lightweight, powerful, and cross-platform. Record and share in seconds. * [Castopod](/services/castopod) - Open-source podcast hosting platform. * [Emby](/services/emby) - A media server to organize, play, and stream audio and video to a variety of devices. * [Emby Stat](/services/embystat) - A simple and easy-to-use Emby statistics dashboard. * [Grimmory](/services/grimmory) - A self-hosted ebook library manager and reader, successor to Booklore. * [Imgcompress](/services/imgcompress) - Image tool for compression, format conversion, and AI background removal * [Immich](/services/immich) - Self-hosted photo and video backup solution. * [Jellyfin](/services/jellyfin) - The Free Software Media System. * [Lidarr](/services/lidarr) - Music collection manager for Usenet and BitTorrent users. * [Metube](/services/metube) - A self-hosted video sharing platform. * [Navidrome](/services/navidrome) - Modern music server and streamer compatible with Subsonic/Airsonic. * [Overseerr](/services/overseerr) - A request management and media discovery tool built to work with your existing Plex ecosystem. * [Plex](/services/plex) - Media server software. * [Prowlarr](/services/prowlarr) - A free and open source BitTorrent client. * [Qbittorrent](/services/qbittorrent) - Free and open-source BitTorrent client. * [Radarr](/services/radarr) - A Media server software. * [Sonarr](/services/sonarr) - A internet PVR for Usenet and Torrents. * [Transmission](/services/transmission) - Fast, easy, and free BitTorrent client. * [Yamtrack](/services/yamtrack) - Self-hosted music scrobble database. Messaging [#messaging] * [Buzz](/services/buzz) - Workspace where humans and AI agents collaborate on a self-hosted Nostr relay. Monitoring [#monitoring] * [Beszel](/services/beszel) - Lightweight server monitoring hub with historical data, docker stats, and alerts. * [Change Detection](/services/changedetection) - Website change detection monitor and notifications. * [Checkmate](/services/checkmate) - Website monitoring and uptime service. * [Diun](/services/diun) - Docker Image Update Notifier. * [Glances](/services/glances) - Cross-platform system monitoring tool. * [Grafana](/services/grafana) - The open platform for beautiful analytics and monitoring. * [Healthchecks](/services/healthchecks) - Open-source cron job and background task monitoring service. * [Observium](/services/observium) - Low-maintenance auto-discovering network monitoring platform. * [OpenObserve](/services/openobserve) - Observability platform for logs, metrics, traces, RUM, and session replays. * [SigNoz](/services/signoz) - Open source observability platform native to OpenTelemetry with logs, traces, and metrics. * [Statusnook](/services/statusnook) - A status page system for your website. * [Uptime Kuma](/services/uptime-kuma) - A fancy self-hosted monitoring tool. Networking [#networking] * [Cloudflared](/services/cloudflared) - Cloudflare Tunnel client. * [Librespeed](/services/librespeed) - Deploy Librespeed on Coolify for self-hosted lightweight speed test. * [Netbird-Client](/services/netbird-client) - Connect your devices into a secure WireGuard-based mesh network. * [Newt-Pangolin](/services/newt-pangolin) - User space WireGuard tunnel client and TCP/UDP proxy for securely exposing private resources. * [Tailscale Client](/services/tailscale-client) - Zero-config WireGuard VPN client for secure mesh networking and encrypted connections. Notifications [#notifications] * [Gotify](/services/gotify) - Open-source push notifications for web and mobile apps. * [Ntfy](/services/ntfy) - Simple HTTP-based pub-sub notification service. Productivity [#productivity] * [Affine](/services/affine) - Open-source knowledge base and workspace combining docs, whiteboards, and databases. * [Alexandrie](/services/alexandrie) - Markdown note-taking app focused on performance, local data, and knowledge graph navigation. * [AppFlowy](/services/appflowy) - Open-source alternative to Notion with workspaces for docs, wikis, and project management. * [BentoPDF](/services/bento-pdf) - Process PDFs entirely in your browser. No uploads. No servers. Complete privacy. * [CodiMD](/services/codimd) - Realtime collaborative markdown notes on all platforms. * [Ente](/services/ente-photos) - A fully open-source, end-to-end encrypted platform for you to store data in the cloud without needing to trust the service provider. * [Excalidraw](/services/excalidraw) - Virtual whiteboard for sketching hand-drawn like diagrams. * [Grist](/services/grist) - Modern relational spreadsheet combining flexibility and database robustness. * [Joplin](/services/joplin) - Open-source note taking and to-do application. * [KaraKeep](/services/karakeep) - Self-hostable bookmark-everything app with AI-based automatic tagging. * [Libreoffice](/services/libreoffice) - Free and open-source office suite. * [Memos](/services/memos) - Open-source, self-hosted memo hub with knowledge management. * [Obsidian](/services/obsidian) - A note-taking app that lets you create, link, and organize your notes with hundreds of plugins and themes. * [Outline](/services/getoutline) - Open-source collaboration tool. * [Rallly](/services/rallly) - Open-source meeting scheduling tool. * [Reactive Resume](/services/reactive-resume) - A free and open source resume builder. * [Readeck](/services/readeck) - Web article reader and bookmark manager. * [Ryot](/services/ryot) - Self-hosted platform for tracking various facets of your life. * [SilverBullet](/services/silverbullet) - An open source personal productivity platform built on Markdown. * [Siyuan](/services/siyuan) - A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. * [Slash](/services/slash) - Open-source, self-hosted links and notes manager. * [TriliumNext](/services/triliumnext) - Build your personal knowledge base with TriliumNext Notes. * [Vikunja](/services/vikunja) - The open-source to-do app. Project Management [#project-management] * [Fizzy](/services/fizzy) - Kanban tracking tool for issues and ideas by 37signals. * [Leantime](/services/leantime) - Lean project management system for innovators. * [Plane](/services/plane) - Open source project planning tool. * [Redmine](/services/redmine) - Flexible project management web application. RSS [#rss] * [Freshrss](/services/freshrss) - Free, self-hostable RSS feed aggregator. * [Miniflux](/services/miniflux) - Minimalist and opinionated feed reader. Search [#search] * [Elasticsearch](/services/elasticsearch) - Free and Open Source, Distributed, RESTful Search Engine. * [Meilisearch](/services/meilisearch) - A powerful, fast, open-source, easy to use, and deploy search engine. * [SearXNG](/services/searxng) - Open source search engine. * [Typesense](/services/typesense) - Open source alternative to Algolia and easier-to-use alternative to ElasticSearch. * [Whoogle](/services/whoogle) - Self-hosted, ad-free, privacy-respecting metasearch engine. Security [#security] * [Authentik](/services/authentik) - An open-source Identity Provider, focused on flexibility and versatility. * [Cap (CAPTCHA)](/services/cap-captcha) - The self-hosted CAPTCHA for the modern web. * [Cryptgeon](/services/cryptgeon) - Secure note sharing service with self-destructing messages. * [Cyberchef](/services/cyberchef) - Data analysis and manipulation tool for cybersecurity. * [Faraday](/services/faraday) - Collaborative penetration testing and vulnerability management platform. * [Infisical](/services/infisical) - Open source secret management platform. * [Keycloak](/services/keycloak) - Open-source identity and access management solution. * [Logto](/services/logto) - Logto is an Auth0 alternative designed for modern apps and SaaS products. * [Onetime Secret](/services/onetimesecret) - Share secrets securely with self-destructing links that can only be viewed once. * [Passbolt](/services/passbolt) - Open source password manager for teams. * [Pi-hole](/services/pi-hole) - Network-wide ad blocker that acts as a DNS sinkhole. * [Pocket ID](/services/pocket-id) - A simple OIDC provider for passwordless authentication with passkeys. * [Supertokens](/services/supertokens) - Open-source authentication solution. * [Vaultwarden](/services/vaultwarden) - Unofficial Bitwarden compatible server. * [Wireguard Easy](/services/wireguard-easy) - Easy-to-use WireGuard VPN server. Social Media [#social-media] * [Bluesky PDS](/services/bluesky-pds) - Bluesky PDS (Personal Data Server) for decentralized social networking. * [Mixpost](/services/mixpost) - Self-hosted social media management software (Buffer alternative). * [Postiz](/services/postiz) - Social media scheduling and analytics tool. * [Redlib](/services/redlib) - Private front-end for Reddit. Storage [#storage] * [Cloudreve](/services/cloudreve) - A self-hosted file management and sharing system. * [Garage](/services/garage) - S3-compatible distributed object storage service designed for self-hosting. * [NextCloud](/services/nextcloud) - A safe home for all your data. * [Obsidian LiveSync](/services/obsidian-livesync) - Self-hosted sync backend for the Obsidian LiveSync plugin using CouchDB. * [Owncloud](/services/owncloud) - File synchronization and sharing platform. * [Seafile](/services/seafile) - High-performance file syncing and sharing with knowledge management features. * [SeaweedFS](/services/seaweedfs) - Simple and highly scalable distributed file system compatible with S3. Utilities [#utilities] * [Convertx](/services/convertx) - File conversion service supporting multiple formats. * [Vert](/services/vert) - Self-hosted file converter. *** Looking for a searchable interface? Visit our [interactive services search](/services/overview) page. To request a new service, please check our [contribution guide](https://github.com/coollabsio/coolify/blob/v4.x/CONTRIBUTING.md). # AnythingLLM (/docs/services/anythingllm) AnythingLLM [#anythingllm] What is AnythingLLM? [#what-is-anythingllm] AnythingLLM is the easiest to use, all-in-one AI application that can do RAG, AI Agents, and much more with no code or infrastructure headaches. Screenshots [#screenshots] Links [#links] * [The official website](https://anythingllm.com/) * [GitHub](https://github.com/Mintplex-Labs/anything-llm?utm_source=coolify.io) # AppFlowy (/docs/services/appflowy) What is AppFlowy? [#what-is-appflowy] AppFlowy is the AI collaborative workspace where you achieve more without losing control of your data. It's a leading open-source alternative to Notion, bringing together projects, wikis, and teams with AI capabilities. Built with Flutter and Rust, AppFlowy offers: * **Data Privacy First** - 100% control of your data with self-hosting capabilities * **Native Experience** - Reliable cross-platform performance with a single codebase * **AI Integration** - Built-in AI features to enhance productivity * **Flexible Workspace** - Combines documents, databases, kanban boards, and more * **Community-Driven** - Open-source and extensible platform Perfect for individuals seeking Notion's functionality with enhanced data security, or enterprises needing customizable collaboration tools with complete data ownership. Screenshots [#screenshots] Links [#links] * [The official website](https://www.appflowy.com/?utm_source=coolify.io) * [GitHub](https://github.com/AppFlowy-IO/AppFlowy?utm_source=coolify.io) * [Documentation](https://docs.appflowy.io/?utm_source=coolify.io) * [Self-hosting Guide](https://appflowy.com/docs/self-host-appflowy-overview?utm_source=coolify.io) # Apprise API (/docs/services/apprise-api) What is Apprise API? [#what-is-apprise-api] [Apprise-api](https://github.com/caronc/apprise-api) Takes advantage of [Apprise](https://github.com/caronc/apprise) through your network with a user-friendly API. * Send notifications to more than 100 services. * An incredibly lightweight gateway to Apprise. * A production ready micro-service at your disposal. * A Simple Website to verify and test your configuration with. Apprise API was designed to easily fit into existing (and new) eco-systems that are looking for a simple notification solution. Screenshots [#screenshots]
Links [#links] * [The official website](https://hub.docker.com/r/caronc/apprise/?utm_source=coolify.io) * [GitHub](https://github.com/caronc/apprise-api?utm_source=coolify.io) # Appsmith (/docs/services/appsmith) Appsmith [#appsmith] What is Appsmith [#what-is-appsmith] Organizations build internal applications such as dashboards, database GUIs, admin panels, approval apps, customer support tools, etc. to help improve their business operations. Appsmith is an open-source developer tool that enables the rapid development of these applications. You can drag and drop pre-built widgets to build UI. Connect securely to your databases & APIs using its datasources. Write business logic to read & write data using queries & JavaScript. Why Appsmith [#why-appsmith] Appsmith makes it easy to build a UI that talks to any datasource. You can create anything from simple CRUD apps to complicated multi-step workflows with a few simple steps: * Connect Datasource: Integrate with a database or API. Appsmith supports the most popular databases and REST APIs. * Build UI: Use built-in widgets to build your app layout. * Write Logic: Express your business logic using queries and JavaScript anywhere in the editor. * Collaborate, Deploy, Share: Appsmith supports version control using Git to build apps in collaboration using branches to track and roll back changes. Deploy the app and share it with other users. Learning Resources [#learning-resources] * [Documentation](https://docs.appsmith.com?utm_source=coolify.io) * [Tutorials](https://docs.appsmith.com/getting-started/tutorials?utm_source=coolify.io) * [Videos](https://www.youtube.com/appsmith?utm_source=coolify.io) * [Templates](https://www.appsmith.com/templates?utm_source=coolify.io) Need Help? [#need-help] * [Discord](https://discord.gg/rBTTVJp?utm_source=coolify.io) * [Community Portal](https://community.appsmith.com/?utm_source=coolify.io) * [support@appsmith.com](mailto:support@appsmith.com) Links [#links] * [The official website](https://www.appsmith.com?utm_source=coolify.io) * [GitHub](https://github.com/appsmithorg/appsmith?utm_source=coolify.io) # Appwrite (/docs/services/appwrite) Appwrite [#appwrite] What is Appwrite? [#what-is-appwrite] Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster. Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs?utm_source=coolify.io). Links [#links] * [The official website](https://appwrite.io?utm_source=coolify.io) * [GitHub](https://github.com/appwrite/appwrite?utm_source=coolify.io) # Argilla (/docs/services/argilla) What is Argilla? [#what-is-argilla] Argilla is a collaboration tool for AI engineers and domain experts to build high-quality datasets. Screenshots [#screenshots] Links [#links] * [The official website](https://argilla.io/?utm_source=coolify.io) * [GitHub](https://github.com/argilla-io/argilla?utm_source=coolify.io) # Audiobookshelf (/docs/services/audiobookshelf) Audiobookshelf [#audiobookshelf] What is Audiobookshelf [#what-is-audiobookshelf] Self-hosted audiobook, ebook, and podcast server Links [#links] * [Official Documentation](https://www.audiobookshelf.org/?utm_source=coolify.io) # Authentik (/docs/services/authentik) What is authentik? [#what-is-authentik] Authentik is an open-source Identity Provider that emphasizes flexibility and versatility. It can be seamlessly integrated into existing environments to support new protocols. Authentik is also a great solution for implementing sign-up, recovery, and other similar features in your application, saving you the hassle of dealing with them. Screenshots [#screenshots] | Light | Dark | | -------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | | | | | | Links [#links] * [The official website](https://goauthentik.io?utm_source=coolify.io) * [GitHub](https://github.com/goauthentik/authentik?utm_source=coolify.io) # Autobase (/docs/services/autobase) Autobase [#autobase] What is Autobase? [#what-is-autobase] **Autobase for PostgreSQL®** is an open-source alternative to cloud-managed databases (DBaaS) such as Amazon RDS, Google Cloud SQL, Azure Database, and others. This automated database platform enables you to create and manage production-ready, highly available PostgreSQL clusters. It simplifies the deployment process, reduces operational costs, and makes database management accessible even for teams without specialized expertise. *Automate deployment, failover, backups, restore, upgrades, scaling, and more with ease.* Say goodbye to manual database management 👋 Demo [#demo] [https://demo.autobase.tech/](https://demo.autobase.tech/?utm_source=coolify.io) Note: use the token *demo* to access. Links [#links] * [Official Website](https://autobase.tech/?utm_source=coolify.io) * [Documentation](https://autobase.tech/docs?utm_source=coolify.io) * [GitHub](https://github.com/vitabaks/autobase?utm_source=coolify.io) # BabyBuddy (/docs/services/babybuddy) What is BabyBuddy? [#what-is-babybuddy] A buddy for babies! Helps caregivers track sleep, feedings, diaper changes, tummy time and more to learn about and predict baby's needs without (*as much*) guess work. Screenshots [#screenshots] Demo [#demo] A [demo of Baby Buddy](https://demo.baby-buddy.net?utm_source=coolify.io) is available. The demo instance resets every hour. Login credentials are: * Username: `admin` * Password: `admin` Links [#links] * [The official website](https://docs.baby-buddy.net?utm_source=coolify.io) * [GitHub](https://github.com/babybuddy/babybuddy?utm_source=coolify.io) # BentoPDF (/docs/services/bento-pdf) BentoPDF [#bentopdf] What is BentoPDF? [#what-is-bentopdf] The PDF Toolkit built for privacy. * No Signup * Start instantly, no accounts or emails. * No Uploads * 100% client-side, your files never leave your device. * Forever Free * All tools, no trials, no paywalls. * No Limits * Use as much as you want, no hidden caps. * Batch Processing * Handle unlimited PDFs in one go. * Lightning Fast * Process PDFs instantly, without waiting or delays. Links [#links] * [Official website](https://www.bentopdf.com?utm_source=coolify.io) * [Documentation](https://bentopdf.com/docs?utm_source=coolify.io) * [GitHub](https://github.com/alam00000/bentopdf?utm_source=coolify.io) # Beszel (/docs/services/beszel) What is Beszel? [#what-is-beszel] Lightweight server monitoring hub with historical data, docker stats, and alerts. Setup [#setup] 1\. Deploy Beszel [#1-deploy-beszel] Create a new resource on Coolify and search for `Beszel` and select the template `Beszel` (you can select `Beszel Agent` if you only want to deploy the agent) Then click the deploy button and wait for it to deploy. When you deploy Beszel with Agent for first time the beszel-agent will be unhealthy and be in restarting state, this is normal and expected because it needs some additional steps to setup which are explained below. 2\. Add System on Beszel dashboard [#2-add-system-on-beszel-dashboard] Visit the Beszel URL and create your first admin account on the Beszel dashboard. After creating the account, click the "**Add a new System**" button in the top corner.
* Give a name for the Agent * Enter `beszel-agent` as the Host/IP if you are using the **Beszel** template; if you are using the **Beszel Agent** template, then enter the IP address of the server where the agent is deployed * Copy the value of `Public Key` and `Token`, then click on "Add system" 3\. Set KEY and TOKEN environment variables on Coolify [#3-set-key-and-token-environment-variables-on-coolify] Go to the **Environment Variables** on Coolify and enter the value for `KEY` and `TOKEN` variables. These are the Public Key and Token you copied from the Beszel dashboard in the previous step. 4\. Restart Beszel [#4-restart-beszel] After you set the environment variables (previous step), restart Beszel by clicking the restart button. Once it’s restarted, the `beszel-agent` service will become healthy and the Beszel dashboard will start showing data. If you are using Coolify version below v4.0.0-beta.452, disable gzip compression in the hub service settings. Go to the Beszel service in Coolify, click "settings", and uncheck the `gzip compression` option. Links [#links] * [Official Website](https://beszel.dev?utm_source=coolify.io) * [GitHub](https://github.com/henrygd/beszel?utm_source=coolify.io) # Bitcoin Core (/docs/services/bitcoin-core) Bitcoin Core [#bitcoin-core] What is Bitcoin Core [#what-is-bitcoin-core] A self-hosted Bitcoin Core full node. Public Node vs. Private Use [#public-node-vs-private-use] By default, Coolify’s Bitcoin Core service is configured for private/internal use. This means it is intended for connecting wallets or apps from the same server or private network, and **does not accept inbound P2P connections from the public internet**. This is a security-conscious default to help reduce the attack surface, especially for new users. How to Run a Public Node [#how-to-run-a-public-node] If you want your Bitcoin node to be a fully public peer (accepting inbound connections from other nodes): 1. **Expose the P2P port in your Compose file:**\ Add the following under your `bitcoin-core` service: ```text ports: - "8333:8333" ``` 2. **Open port 8333 in your server’s firewall:** * On Ubuntu with UFW: ```bash sudo ufw allow 8333/tcp ``` * On CentOS with firewalld: ```bash sudo firewall-cmd --add-port=8333/tcp --permanent sudo firewall-cmd --reload ``` * For cloud servers, update your provider’s security group or firewall rules to allow inbound TCP on port 8333. Considerations [#considerations] * **Default Behavior:**\ Without the `ports` section, your node will not accept inbound P2P connections, but can still make outbound connections and fully sync the blockchain. * **Security:**\ Not exposing 8333 by default helps protect users who may not understand the implications of running a public Bitcoin node. * **Advanced Users:**\ If you understand the risks and want to contribute more fully to the Bitcoin network, follow the steps above to run a public node. Links [#links] * [Official Documentation](https://hub.docker.com/r/ruimarinho/bitcoin-core/?utm_source=coolify.io) # Bluesky PDS (/docs/services/bluesky-pds) Bluesky PDS [#bluesky-pds] What is a Bluesky PDS? [#what-is-a-bluesky-pds] Bluesky PDS (Personal Data Server) is a self-hosted data server that stores your data in the AT Protocol network. It allows you to control your own social media data and identity while still participating in the AT Protocol network. The PDS handles user accounts, posts, followers, and other social data in a decentralized manner. Setting a domain with https if already not set [#setting-a-domain-with-https-if-already-not-set] Pdsadmin requires you to have https in your Bluesky PDS, make sure you have set a domain with https in the Coolify UI and check the environment variables so it matches it. Creating an account in your PDS [#creating-an-account-in-your-pds] To create an account and start using your PDS, you can use the following pdsadmin commands in the Terminal tab of the Coolify UI: ```bash pdsadmin create-invite-code ``` or ```bash pdsadmin account create ``` To check for other available commands in pdsadmin, you can simply run `pdsadmin` Setting up mail [#setting-up-mail] Mailing is important for a Bluesky PDS, it's needed to confirm email, and other things! You need to edit 2 environment variables in the Coolify UI, head to the Environment Variables tab and look for the `PDS_EMAIL_FROM_ADDRESS`, what you need to fill here is pretty much self explanatory, is the email address that's going to be used when sending an email, for example: `user@domain.com` The next environment variable is `PDS_EMAIL_SMTP_URL`, this one is not very self explanatory, but here's how to fill it: There are many ways to fill this variable, here are some examples: `smtps://user%40example.com:password@mail.example.com:465` (SMTP with SSL) `smtp://user%40example.com:password@mail.example.com:587` (SMTP without SSL) `smtps://resend:@smtp.resend.com:465` (Resend) You might need to URL-encode your username and password for the Mail Setup to work. And that's it, your PDS should be ready for you to use, it will work like any other PDS! Links [#links] * [The official website](https://blueskyweb.xyz?utm_source=coolify.io) * [GitHub](https://github.com/bluesky-social/pds?utm_source=coolify.io) # Booklore (/docs/services/booklore) Booklore [#booklore] This service has been removed from Coolify. BookLore is no longer maintained by its authors and removed by the authors from GitHub. What is Booklore? [#what-is-booklore] Booklore is an open-source library management system that gives you complete control over your digital book collection. Your books and data stay on your own server, ensuring privacy and independence. # Bookstack (/docs/services/bookstack) Bookstack [#bookstack] What is Bookstack [#what-is-bookstack] BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information Links [#links] * [Official Documentation](https://www.bookstackapp.com/docs/?utm_source=coolify.io) # Browserless (/docs/services/browserless) What is Browserless [#what-is-browserless] Browserless is a platform that provides headless browser automation and management services. It allows developers to run automated browser tasks without the need for manual intervention, making it ideal for web scraping, testing, and rendering tasks. Example use cases [#example-use-cases] * Web Scraping: Automate the collection of data from websites, such as product prices, news articles, or social media content, without worrying about CAPTCHAs, JavaScript rendering, or rate limits. * Automated Testing: Run browser-based tests for web applications using tools like Puppeteer or Selenium to check functionality, compatibility, and performance across different browsers. * PDF Generation: Convert webpages or HTML content into PDFs automatically, which is useful for invoicing, reporting, or archiving purposes. * Website Monitoring: Automate the monitoring of websites for uptime, broken links, or content changes, ensuring everything is functioning as expected without manually visiting the site. * SEO Audits: Use Browserless to run scripts that crawl your website, analyzing metadata, tags, and other factors that impact SEO, ensuring your site follows best practices. Key Features [#key-features] * Headless Browser Automation: Supports running headless browsers, automating tasks with Puppeteer, Playwright, and Selenium without manual browser operation. * Cloud-Based Infrastructure: Run scripts in the cloud, reducing the need to manage your own browser environments and infrastructure. * Pre-Built APIs: Offers APIs for common tasks like screenshotting, PDF generation, and web scraping, simplifying integration. * Scalability: Easily scale automation tasks across many concurrent browser sessions. * Logging & Debugging Tools: Detailed logging and debugging tools for tracking and troubleshooting automated browser sessions. Images [#images] Links [#links] * [The official website](https://www.browserless.io?utm_source=coolify.io) * [Documentation](https://docs.browserless.io?utm_source=coolify.io) * [GitHub](https://github.com/browserless?utm_source=coolify.io) * [Api Documentation](https://docs.browserless.io/docs/api.html?utm_source=coolify.io) * [Pricing](https://www.browserless.io/pricing?utm_source=coolify.io) # BudgE (/docs/services/budge) What is BudgE? [#what-is-budge] BudgE (pronounced "budgie", like the bird) is an open source "budgeting with envelopes" personal finance app, taking inspiration from other tools such as [Aspire Budgeting](https://www.aspirebudget.com?utm_source=coolify.io), [budgetzero](https://budgetzero.io?utm_source=coolify.io), and [Buckets](https://www.budgetwithbuckets.com/?utm_source=coolify.io). Current Features [#current-features] * Multi user support * Envelope budgeting with monthly rollover * Transaction management for accounts * Standard bank account management * Credit card management with payment handling * Tracking accounts * Export account transactions * CSV transaction import Screenshots [#screenshots] Support [#support] * [Discord](https://discord.gg/hKJWjDqCBz) Links [#links] * [GitHub](https://github.com/linuxserver/budge?utm_source=coolify.io) # Budibase (/docs/services/budibase) Budibase [#budibase] What is Budibase [#what-is-budibase] Low code platform for building business apps and workflows in minutes. Supports PostgreSQL, MySQL, MSSQL, MongoDB, Rest API, Docker, K8s, and more. Links [#links] * [Official Documentation](https://docs.budibase.com/docs/docker-compose?utm_source=coolify.io) # Bugsink (/docs/services/bugsink) What is Bugsink? [#what-is-bugsink] [Bugsink](https://www.bugsink.com/?utm_source=coolify.io) offers [error tracking](https://www.bugsink.com/error-tracking/?utm_source=coolify.io) for your applications with full control through self-hosting. * [Built to self-host](https://www.bugsink.com/built-to-self-host/?utm_source=coolify.io) * [Sentry-SDK compatible](https://www.bugsink.com/sentry-sdk-compatible/?utm_source=coolify.io) * [Scalable and reliable](https://www.bugsink.com/scalable-and-reliable/?utm_source=coolify.io) Screenshots [#screenshots] Links [#links] * [The official website](https://www.bugsink.com/?utm_source=coolify.io) * [GitHub](https://github.com/bugsink/bugsink/?utm_source=coolify.io) # Bulwark (/docs/services/bulwark) What is Bulwark? [#what-is-bulwark] Bulwark is a modern, open-source webmail client built for [Stalwart Mail Server](https://stalw.art?utm_source=coolify.io) using the [JMAP protocol](https://jmap.io/). It provides email, calendar, contacts, and file storage behind a single login. Prerequisites [#prerequisites] Before deploying Bulwark, you need a running JMAP-compatible mail server. Stalwart is the primary tested backend and is recommended. If you don't have one yet, deploy the [Stalwart](/services/stalwart) service on Coolify first and come back. For the full feature set (account settings, app passwords, Sieve filters, admin dashboard), Stalwart **0.16 or newer** is required. Configuring Bulwark [#configuring-bulwark] The following steps will guide you through the configuration of Bulwark once you have created the service in Coolify. JMAP server URL [#jmap-server-url] Set the `JMAP_SERVER_URL` environment variable to the URL of your JMAP server before the first deployment. This is a required variable, the service will not start without it. If you run the [Stalwart](/services/stalwart) service on Coolify, this is the same as the Stalwart service URL, for example `https://mail.yourdomain.com`. Bulwark probes the `/.well-known/jmap` endpoint under this URL to find your JMAP server. To connect Bulwark to multiple JMAP servers, set `JMAP_SERVER_URL` to a comma-separated list of URLs. The login form automatically picks the server based on the email domain when possible. Session secret [#session-secret] The `SESSION_SECRET` environment variable is auto-generated by Coolify, so no action is needed. It is used to encrypt persistent sessions, settings sync data, and multi-account state. Accessing the webmail [#accessing-the-webmail] After deployment, the webmail interface is available at the service URL generated from `SERVICE_URL_BULWARK_3000`. Log in with the credentials of a mailbox on your JMAP server. Stalwart-specific features [#stalwart-specific-features] When connected to Stalwart 0.16 or newer, Bulwark enables additional features that depend on Stalwart's JMAP `x:` methods: * Change your password from account settings * Enable TOTP two-factor authentication with recovery codes * Generate per-app passwords (e.g. for IMAP/SMTP clients) * Manage Sieve filters server-side * Configure a vacation responder * View your storage quota and sync identities with the server Troubleshooting [#troubleshooting] If Bulwark cannot connect to your mail server: * Verify the JMAP endpoint is reachable by running `curl https:///.well-known/jmap` and confirming a JMAP session resource is returned. * If Bulwark runs on a different domain than your mail server, make sure CORS is enabled on the mail server: * In the Stalwart admin panel, go to **Settings** > **Network** > **HTTP** > **Security** and set `Permissive CORS policy` to `enabled`. * After saving, restart the Stalwart service in Coolify for the change to take effect (or reload the configuration from **Management** > **Actions** > **Reload** > **Server Settings**). Links [#links] * [GitHub](https://github.com/bulwarkmail/webmail?utm_source=coolify.io) * [Documentation](https://bulwarkmail.org/docs?utm_source=coolify.io) # Buzz (/docs/services/buzz) Buzz [#buzz] What is Buzz? [#what-is-buzz] Buzz is a self-hostable workspace where humans and AI agents share the same rooms. Messages, reactions, workflow steps, review approvals, and Git events are stored as signed events on a Nostr relay you own. The Coolify service deploys Buzz together with PostgreSQL, Redis, and MinIO. It also configures persistent storage for the relay's Git repositories, database, Redis, and uploaded media. Connect a Buzz client [#connect-a-buzz-client] After deploying the service, copy its public URL and change the scheme from `https://` to `wss://`. Use that WebSocket URL as the relay URL in a [Buzz desktop client](https://github.com/block/buzz/releases/latest?utm_source=coolify.io) or set it through the client's `BUZZ_RELAY_URL` environment variable. For example, a Coolify service URL of `https://buzz.example.com` corresponds to the relay URL `wss://buzz.example.com`. Links [#links] * [GitHub](https://github.com/block/buzz?utm_source=coolify.io) * [Architecture](https://github.com/block/buzz/blob/main/ARCHITECTURE.md?utm_source=coolify.io) * [Latest desktop client](https://github.com/block/buzz/releases/latest?utm_source=coolify.io) # Calcom (/docs/services/calcom) Calcom [#calcom] This service has been removed from Coolify’s one-click service catalog. More info on [https://github.com/coollabsio/coolify/pull/9776](https://github.com/coollabsio/coolify/pull/9776) What is Calcom [#what-is-calcom] Scheduling infrastructure for everyone. Deploying on x86 (amd64) [#deploying-on-x86-amd64] You need to change default docker compose to the following to make cal.com work on x86 (amd64): ```yaml services: calcom: image: 'calcom/cal.com: platform: linux/amd64 (... same ...) ``` You can check the latest amd64 compatible version [here](https://hub.docker.com/r/calcom/cal.com/tags). Example: ```yaml services: calcom: image: 'calcom/cal.com:v5.9.0 platform: linux/amd64 (... same ...) ``` Links [#links] * [Official Documentation](https://cal.com/docs/developing/introduction?utm_source=coolify.io) # Calibre Web Automated with Downloader (/docs/services/calibre-web-automated-with-downloader) What is Calibre Web Automated with Downloader [#what-is-calibre-web-automated-with-downloader] Calibre Web Automated [#calibre-web-automated] Calibre, while a fantastic tool for its age, has several problems when containerised, including its reliance on a KasmVNC server instance for the UI, which is near impossible to use on mobile and is relatively resource-heavy if you're running a small, lower power server like I am. Links [#links] * [GitHub](https://github.com/crocodilestick/Calibre-Web-Automated) Downloader [#downloader] An intuitive web interface for searching and requesting book downloads, designed to work seamlessly with Calibre-Web-Automated. This project streamlines the process of downloading books and preparing them for integration into your Calibre library. Links [#links-1] * [GitHub](https://github.com/calibrain/calibre-web-automated-book-downloader) # Calibre Web (/docs/services/calibre-web) Calibre Web [#calibre-web] What is Calibre Web [#what-is-calibre-web] Calibre web is a web app providing a clean interface for browsing, reading and downloading eBooks. Links [#links] * [Official Documentation](https://github.com/linuxserver/docker-calibre-web?utm_source=coolify.io) # Cap (CAPTCHA) (/docs/services/cap-captcha) Cap [#cap] What is Cap? [#what-is-cap] [Cap](https://capjs.js.org/?utm_source=coolify.io) is a modern, lightweight, and self-hosted CAPTCHA alternative using SHA-256 proof-of-work and JavaScript instrumentation challenges. Screenshots [#screenshots] Links [#links] * [Official website](https://capjs.js.org/?utm_source=coolify.io) * [GitHub](https://github.com/tiagozip/cap?utm_source=coolify.io) # Cap (/docs/services/cap) What is Cap? [#what-is-cap] Cap is the open source alternative to Loom. Lightweight, powerful, and cross-platform. Record and share in seconds. How to self-host [#how-to-self-host] There are two storage options: you can store the video data on a remote storage service like S3 or R2, or you can choose the less recommended option of storing it directly on the local VPS (or another VPS) via a MinIO service. Option 1: Remote S3-compatible storage (AWS S3, Cloudflare R2, etc.) [#option-1-remote-s3-compatible-storage-aws-s3-cloudflare-r2-etc] Set these environment variables: * `CAP_AWS_ACCESS_KEY`: Your S3/R2 access key * `CAP_AWS_SECRET_KEY`: Your S3/R2 secret key * `CAP_AWS_BUCKET`: Your S3/R2 bucket name * `CAP_AWS_REGION`: Your S3/R2 region (e.g., us-east-1, auto for R2) * `CAP_AWS_ENDPOINT`: Your S3/R2 endpoint URL * `S3_PUBLIC_ENDPOINT`: Public endpoint for your bucket (same as CAP\_AWS\_ENDPOINT for most cases) * `S3_INTERNAL_ENDPOINT`: Internal endpoint (same as CAP\_AWS\_ENDPOINT for most cases) * `S3_PATH_STYLE`: true for R2/most S3-compatible, false for AWS S3 virtual-hosted style Option 2: Local MinIO storage [#option-2-local-minio-storage] Deploy MinIO as a separate service in the same network and set: * `CAP_AWS_ACCESS_KEY`: MinIO root user * `CAP_AWS_SECRET_KEY`: MinIO root password * `CAP_AWS_BUCKET`: Your bucket name (e.g., capso) * `CAP_AWS_REGION`: us-east-1 (or any region) * `CAP_AWS_ENDPOINT`: [http://minio:9000](http://minio:9000) (internal MinIO endpoint) * `S3_PUBLIC_ENDPOINT`: [http://your-minio-domain:9000](http://your-minio-domain:9000) (public MinIO endpoint) * `S3_INTERNAL_ENDPOINT`: [http://minio:9000](http://minio:9000) (internal MinIO endpoint) * `S3_PATH_STYLE`: true Email Login Links [#email-login-links] If the `RESEND_API_KEY` and `RESEND_FROM_DOMAIN` environment variables are not set, login links will be written to the server logs. To send login links via email, you'll need to configure [Resend](https://resend.com): 1. Create an account at [Resend](https://resend.com) 2. Connect a domain and set it as `RESEND_FROM_DOMAIN` 3. Generate an API key and set it as `RESEND_API_KEY` How to unlock limits (organization seats and recordings) [#how-to-unlock-limits-organization-seats-and-recordings] 1. Open the terminal of the MySQL service 2. Connect to the database: `mysql -u root -p planetscale` and use the `MYSQL_ROOT_PASSWORD` when prompted 3. Run the SQL command below, replacing `your-user-id` with your actual user ID ```sql UPDATE users SET inviteQuota = 100, stripeSubscriptionId = '12345', subscriptionStatus = 'active' WHERE id = 'your-user-id'; ``` 4. You can verify the changes by running the following command: ```sql SELECT * FROM users WHERE id = 'your-user-id'; ``` Screenshots [#screenshots] Links [#links] * [The official website ›](https://cap.so/) * [GitHub ›](https://github.com/CapSoftware/Cap) # Castopod (/docs/services/castopod) Castopod [#castopod] What is Castopod [#what-is-castopod] Castopod is a free & open-source hosting platform made for podcasters who want to engage and interact with their audience. Links [#links] * [Official Documentation](https://docs.castopod.org/main/en/?utm_source=coolify.io) # Change Detection (/docs/services/changedetection) What is Change Detection? [#what-is-change-detection] Detect website content changes and perform meaningful actions - trigger notifications via Discord, Email, Slack, Telegram, API calls and many more. Live your data-life pro-actively. Example use cases [#example-use-cases] * Products and services have a change in pricing * *Out of stock notification* and *Back In stock notification* * Monitor and track PDF file changes, know when a PDF file has text changes. * Governmental department updates (changes are often only on their websites) * New software releases, security advisories when you're not on their mailing list. * Festivals with changes * Discogs restock alerts and monitoring * Realestate listing changes * Know when your favourite whiskey is on sale, or other special deals are announced before anyone else * COVID related news from government websites * University/organisation news from their website * Detect and monitor changes in JSON API responses * JSON API monitoring and alerting * Changes in legal and other documents * Trigger API calls via notifications when text appears on a website * Glue together APIs using the JSON filter and JSON notifications * Create RSS feeds based on changes in web content * Monitor HTML source code for unexpected changes, strengthen your PCI compliance * You have a very sensitive list of URLs to watch and you do *not* want to use the paid alternatives. (Remember, *you* are the product) * Get notified when certain keywords appear in Twitter search results * Proactively search for jobs, get notified when companies update their careers page, search job portals for keywords. * Get alerts when new job positions are open on Bamboo HR and other job platforms * Website defacement monitoring * Pokémon Card Restock Tracker / Pokémon TCG Tracker * RegTech - stay ahead of regulatory changes, regulatory compliance Key Features [#key-features] * Lots of trigger filters, such as "Trigger on text", "Remove text by selector", "Ignore text", "Extract text", also using regular-expressions! * Target elements with xPath(1.0) and CSS Selectors, Easily monitor complex JSON with JSONPath or jq * Switch between fast non-JS and Chrome JS based "fetchers" * Track changes in PDF files (Monitor text changed in the PDF, Also monitor PDF filesize and checksums) * Easily specify how often a site should be checked * Execute JS before extracting text (Good for logging in, see examples in the UI!) * Override Request Headers, Specify `POST` or `GET` and other methods * Use the "Visual Selector" to help target specific elements * Configurable [proxy per watch](https://github.com/dgtlmoon/changedetection.io/wiki/Proxy-configuration?utm_source=coolify.io) * Send a screenshot with the notification when a change is detected in the web page. Links [#links] * [The official website](https://changedetection.io?utm_source=coolify.io) * [GitHub](https://github.com/dgtlmoon/changedetection.io?utm_source=coolify.io) # Chaskiq (/docs/services/chaskiq) What is Chaskiq? [#what-is-chaskiq] Chaskiq is an open source chat platform that allows you to chat with your customers. Links [#links] * [The official website](https://chaskiq.io?utm_source=coolify.io) * [GitHub](https://github.com/chaskiq/chaskiq?utm_source=coolify.io) # Chatwoot (/docs/services/chatwoot) What is Chatwoot? [#what-is-chatwoot] Chatwoot gives you all the tools to manage conversations, build relationships and delight your customers from one place. Links [#links] * [The official website](https://www.chatwoot.com?utm_source=coolify.io) * [GitHub](https://github.com/chatwoot/chatwoot?utm_source=coolify.io) # Checkmate (/docs/services/checkmate) Checkmate [#checkmate] What is Checkmate [#what-is-checkmate] An open source server monitoring application Links [#links] * [Official Website](https://checkmate.so/?utm_source=coolify.io) # Chibisafe (/docs/services/chibisafe) Chibisafe [#chibisafe] What is Chibisafe? [#what-is-chibisafe] Chibisafe is a beautiful and performant vault to save all your files in the cloud. A modern and self-hosted take on file uploading services that can handle anything you throw at it thanks to it's robust and fast API, chunked uploads support and more. Links [#links] * [Official website](https://chibisafe.app/?utm_source=coolify.io) * [Documentation](https://chibisafe.app/docs/intro?utm_source=coolify.io) * [GitHub](https://github.com/chibisafe/chibisafe?utm_source=coolify.io) # Chroma (/docs/services/chroma) Chroma [#chroma] What is Chroma? [#what-is-chroma] Chroma is an open-source, AI-native vector database designed for building applications with embeddings. It provides a simple way to store, retrieve, and search vector embeddings for machine learning applications, particularly those involving large language models (LLMs) and semantic search. Chroma handles the complexities of vector operations, similarity search, and metadata filtering, making it ideal for retrieval-augmented generation (RAG) systems and other AI applications. Links [#links] * [The official website](https://www.trychroma.com?utm_source=coolify.io) * [GitHub](https://github.com/chroma-core/chroma?utm_source=coolify.io) # ClassicPress (/docs/services/classicpress) What is ClassicPress? [#what-is-classicpress] ClassicPress is a community-led open source content management system for creators. It is a fork of WordPress 6.2 that preserves the TinyMCE classic editor as the default option. It is half the size of WordPress, contains less bloat improving performance, and has no block editor (Gutenberg/Full Site Editing). Deployment Variants [#deployment-variants] ClassicPress is available in two deployment configurations in Coolify: ClassicPress with MariaDB [#classicpress-with-mariadb] * **Database:** MariaDB * **Use case:** Production deployments with MariaDB preference (recommended for most users) * **Components:** * ClassicPress container * MariaDB container * Automatic database configuration and health checks ClassicPress with MySQL [#classicpress-with-mysql] * **Database:** MySQL * **Use case:** Production deployments with MySQL preference * **Components:** * ClassicPress container * MySQL container * Automatic database configuration and health checks Both variants provide equivalent functionality - choose based on your database preference or existing infrastructure. For more information, see: * [The official website](https://www.classicpress.net?utm_source=coolify.io) * [The ClassicPress documentation](https://docs.classicpress.net?utm_source=coolify.io) * [The ClassicPress governance](https://www.classicpress.net/governance?utm_source=coolify.io) * [Suggest features](https://github.com/ClassicPress/ClassicPress/issues?utm_source=coolify.io) # Cloudbeaver (/docs/services/cloudbeaver) Cloudbeaver [#cloudbeaver] What is Cloudbeaver [#what-is-cloudbeaver] CloudBeaver is a lightweight web application designed for comprehensive data management. Links [#links] * [Official Documentation](https://dbeaver.com/docs/cloudbeaver/?utm_source=coolify.io) # Cloudflare DDNS (/docs/services/cloudflare-ddns) Cloudflare DDNS [#cloudflare-ddns] What is Cloudflare DDNS? [#what-is-cloudflare-ddns] Cloudflare DDNS detects changes to the server's public IPv4 or IPv6 address and updates selected DNS records through the Cloudflare API. Links [#links] * [GitHub repository](https://github.com/favonia/cloudflare-ddns) # Cloudflared (/docs/services/cloudflared) What is Cloudflared? [#what-is-cloudflared] Cloudflare Tunnel is tunneling software that lets you quickly secure and encrypt application traffic to any type of infrastructure, so you can hide your web server IP addresses, block direct attacks, and get back to delivering great applications. Links [#links] * [The official website](https://www.cloudflare.com/products/tunnel?utm_source=coolify.io) * [GitHub](https://github.com/cloudflare/cloudflared?utm_source=coolify.io) # Cloudreve (/docs/services/cloudreve) Cloudreve [#cloudreve] What is Cloudreve? [#what-is-cloudreve] Cloudreve enables you to quickly set up a cloud storage system that serves both public and private needs. Cloudreve supports different cloud storage platforms at its core, and users don't need to worry about the physical storage method during actual use. You can use Cloudreve to build a personal cloud drive, file sharing system, or even a public cloud system for small to large organizations. Links [#links] * [Official website](https://cloudreve.org/?utm_source=coolify.io) * [Documentation](https://docs.cloudreve.org/en/?utm_source=coolify.io) * [GitHub](https://github.com/cloudreve/Cloudreve?utm_source=coolify.io) # Cockpit (/docs/services/cockpit) Cockpit [#cockpit] What is Cockpit [#what-is-cockpit] Cockpit is a headless content platform that is lightweight, fast and ready for takeoff. Links [#links] * [Official Documentation](https://getcockpit.com/documentation/?utm_source=coolify.io) # Code Server (/docs/services/code-server) Code Server [#code-server] What is Code Server? [#what-is-code-server] Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and access it in the browser. Highlights [#highlights] * Code on any device with a consistent development environment * Use cloud servers to speed up tests, compilations, downloads, and more * Preserve battery life when you're on the go; all intensive tasks run on your server Requirements [#requirements] See [requirements](https://coder.com/docs/code-server/latest/requirements?utm_source=coolify.io) for minimum specs **TL;DR:** Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs Questions? [#questions] See answers to [frequently asked questions](https://coder.com/docs/code-server/latest/FAQ?utm_source=coolify.io). Links [#links] * [The official website](https://coder.com/docs/code-server/?utm_source=coolify.io) * [GitHub](https://github.com/coder/code-server?utm_source=coolify.io) # CodiMD (/docs/services/codimd) What is CodiMD? [#what-is-codimd] CodiMD lets you collaborate in real-time with markdown. Built on HackMD source code, CodiMD lets you host and control your team's content with speed and ease. Screenshots [#screenshots] Links [#links] * [The official website](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-documentation?utm_source=coolify.io) * [GitHub](https://github.com/hackmdio/codimd?utm_source=coolify.io) # Docker Compose (/docs/services/configuration/docker-compose) Docker Compose [#docker-compose] Every Service is based on a Docker Compose definition stored in Coolify. A one-click Service starts with a copied template; a user-defined Service starts with the YAML you enter through **Docker Compose Empty**. Open **Configuration > General** and select **Edit Compose File** to review or change the definition. Source and deployable Compose [#source-and-deployable-compose] | View | Purpose | Editable | | :--------------------- | :---------------------------------------------------------------------------------------------------------- | :-------------------------------------------------: | | **Source Compose** | The definition stored on the Service and reparsed when you save. | Yes | | **Deployable Compose** | The generated definition Coolify writes to the Service configuration directory and sends to Docker Compose. | No | Coolify can add or normalize container names, labels, volume names, networks, environment references, and proxy configuration in the deployable definition. When troubleshooting, confirm the intended setting exists in the source definition, then use the deployable view to see the actual Docker Compose input. Edit a user-defined Service [#edit-a-user-defined-service] 1. Open **Configuration > General > Edit Compose File**. 2. Change **Source Compose**. 3. Select **Validate** to check a Service created with **Docker Compose Empty**. 4. Select **Save**. 5. Review the updated component cards, environment variables, storage, and **Deployable Compose**. 6. Deploy or restart the Service. 7. Follow the deployment output and verify every required component. Saving reparses the definition. Removing or renaming a Compose service changes how Coolify identifies its components, so back up its data and inspect storage names before the change. Environment references [#environment-references] Reference a value with Compose interpolation to manage it under **Configuration > Environment Variables**: ```yaml services: api: image: example/api:1.0 environment: DATABASE_URL: ${DATABASE_URL:?} LOG_LEVEL: ${LOG_LEVEL:-info} ``` `${DATABASE_URL:?}` marks the value as required. Coolify prevents deployment while a required Service variable is empty. `${LOG_LEVEL:-info}` supplies `info` as the initial fallback. Hard-coded values remain in the Compose definition. Coolify can display them for reference, but change them in **Source Compose**. Generated Service values [#generated-service-values] Coolify recognizes `SERVICE__` variable names in Compose and can generate reusable URLs, domains, usernames, passwords, and random values. `` identifies the value and lets you reuse it. For URL and FQDN variables, use the Compose service name as the ID. Replace hyphens and dots in the service name with underscores in the variable name. Reusing the same complete variable name returns the same stored value throughout the Service. All magic environment variables [#all-magic-environment-variables] | Pattern | Generated value | Size | | :-------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :------------------------------- | | `SERVICE_NAME_` | Compose service name. Coolify creates this variable automatically for every Compose service. | Not applicable | | `SERVICE_URL_` | URL with a scheme for the matching Compose service. | Not applicable | | `SERVICE_URL__` | URL with a scheme, routed to the specified internal port. | Not applicable | | `SERVICE_FQDN_` | Hostname for the matching Compose service, without the scheme. | Not applicable | | `SERVICE_FQDN__` | Hostname without the scheme, paired with the URL routed to the specified internal port. | Not applicable | | `SERVICE_USER_` | Random alphanumeric username. | 16 characters | | `SERVICE_LOWERCASEUSER_` | Random lowercase alphanumeric username. | 16 characters | | `SERVICE_PASSWORD_` | Random password without symbols. | 32 characters | | `SERVICE_PASSWORD_64_` | Random password without symbols. | 64 characters | | `SERVICE_PASSWORDWITHSYMBOLS_` | Random password with symbols. | 32 characters | | `SERVICE_PASSWORDWITHSYMBOLS_64_` | Random password with symbols. | 64 characters | | `SERVICE_BASE64_` or `SERVICE_BASE64_32_` | Random alphanumeric string. Despite its name, the value is not Base64-encoded. | 32 characters | | `SERVICE_BASE64_64_` | Random alphanumeric string, not Base64-encoded. | 64 characters | | `SERVICE_BASE64_128_` | Random alphanumeric string, not Base64-encoded. | 128 characters | | `SERVICE_REALBASE64_` or `SERVICE_REALBASE64_32_` | Base64 encoding of random bytes. | 32 random bytes before encoding | | `SERVICE_REALBASE64_64_` | Base64 encoding of random bytes. | 64 random bytes before encoding | | `SERVICE_REALBASE64_128_` | Base64 encoding of random bytes. | 128 random bytes before encoding | | `SERVICE_HEX_32_` | Random hexadecimal string. | 32 characters | | `SERVICE_HEX_64_` | Random hexadecimal string. | 64 characters | | `SERVICE_HEX_128_` | Random hexadecimal string. | 128 characters | | `SERVICE_SUPABASEANON_` | Supabase JWT with the `anon` role, signed with `SERVICE_PASSWORD_JWT`. | JWT | | `SERVICE_SUPABASESERVICE_` | Supabase JWT with the `service_role` role, signed with `SERVICE_PASSWORD_JWT`. | JWT | The Supabase-specific variables are generated only when the Service also defines `SERVICE_PASSWORD_JWT`. Underscores in variable names [#underscores-in-variable-names] Ordinary variable names such as `DATABASE_PASSWORD` can contain underscores. For generated usernames, passwords, and random values, keep `` as one token: use `SERVICE_PASSWORD_DBPASSWORD` or `SERVICE_PASSWORD_64_DBPASSWORD`, not `SERVICE_PASSWORD_DB_PASSWORD`. URL/FQDN variables use the normalized Compose service name, so `my-api` becomes `MY_API`. Their final numeric segment represents an internal port, as in `SERVICE_URL_API_3000`. See the [annotated naming examples](/applications/builds/docker-compose#naming-generated-variables) for the differences between types, identifiers, sizes, and ports. Use the same complete name in several components to reuse one stored value: ```yaml services: database: image: postgres:17 environment: POSTGRES_USER: ${SERVICE_USER_POSTGRES} POSTGRES_PASSWORD: ${SERVICE_PASSWORD_64_POSTGRES} api: image: example/api:1.0 environment: DATABASE_USER: ${SERVICE_USER_POSTGRES} DATABASE_PASSWORD: ${SERVICE_PASSWORD_64_POSTGRES} ``` Generated values persist between deployments and appear under **Environment Variables**. Passwords and random values can be edited there. Coolify manages URL, FQDN, and service-name variables from the Service definition and domain configuration. Domains and internal ports [#domains-and-internal-ports] Declare `SERVICE_URL_` or `SERVICE_FQDN_` on the component that needs a generated domain. Add a numeric port suffix when the proxy must route to a specific internal port: ```yaml services: api: image: example/api:1.0 environment: SERVICE_URL_API_3000: /v1 PUBLIC_URL: ${SERVICE_URL_API_3000} ``` Coolify associates the generated domain with the `api` component, routes it to port `3000`, and appends `/v1` to the URL value. You can also set a component's **Domains** field after parsing. Review the generated variable after changing a domain. Storage is Compose-owned [#storage-is-compose-owned] Define Service volumes and bind mounts in the source definition: ```yaml services: app: image: example/app:1.0 volumes: - app-data:/app/data volumes: app-data: ``` Coolify prefixes managed volume names to avoid collisions and displays the parsed result under **Configuration > Persistent Storages**. The storage view is read-only for Service components; edit the Compose definition to change a mount. Health checks are Compose-owned [#health-checks-are-compose-owned] Services do not have the standalone Application or Database health-check configuration page. Define health checks in the image or Compose service: ```yaml services: api: image: example/api:1.0 healthcheck: test: ["CMD", "wget", "--spider", "http://127.0.0.1:3000/health"] interval: 30s timeout: 5s retries: 3 ``` Use `exclude_from_hc: true` for a one-time or optional Compose service that should not determine the overall Service health. Networking [#networking] Components in the same stack can use their Compose service names on the Service-specific network. Do not publish `ports:` for internal-only components. Enable **Connect To Predefined Network** when the stack must communicate with other resources on the selected destination. Read [Networking in Coolify](/core/networking-in-coolify) before relying on host ports or cross-resource DNS names. Update a one-click Service [#update-a-one-click-service] A one-click template is copied at resource creation. Coolify does not merge future template changes into the saved Service. Before updating: 1. Read the upstream release notes and the individual Service guide. 2. Back up persistent data and test its restore path. 3. Compare the current source definition with the newer template or upstream Compose changes. 4. Apply required image, variable, mount, and migration changes deliberately. 5. Save, review the deployable definition, and deploy during a maintenance window. 6. Verify every component and application workflow. Use **Pull Latest Images & Restart** only when pulling the tags already stored in Compose is the intended update. A mutable tag such as `latest` can change without showing which version will run, so pin production images when the upstream project supports versioned tags. # Environment Variables (/docs/services/configuration/environment-variables) Environment variables [#environment-variables] Service environment variables supply values used when Coolify renders the stack's `.env` file and deployable Compose definition. Open the Service, then select **Configuration > Environment Variables**. Understand the source of a variable [#understand-the-source-of-a-variable] | Source | Where to change it | | :----------------------------------------------------- | :---------------------------------------------------------------------------------- | | `${VARIABLE}` reference in Compose | **Environment Variables** | | Hard-coded value in a Compose `environment:` entry | **Edit Compose File** | | `SERVICE_URL_*`, `SERVICE_FQDN_*`, or `SERVICE_NAME_*` | The matching domain or Compose service; Coolify manages these variables. | | Generated credential such as `SERVICE_PASSWORD_*` | **Environment Variables**, unless the field is locked by the template or your role. | | Shared-variable reference | The shared-variable scope and the Service variable that references it. | Coolify shows hard-coded Compose values separately and filters generated URL, FQDN, and service-name values from that list. Add and edit values [#add-and-edit-values] Use **Normal view** to manage one variable at a time. Service variables can be multiline or literal: * enable **Is Multiline?** for a certificate, private key, or configuration value with line breaks * enable **Is Literal?** when a `$` reference must remain text instead of being expanded Use **Developer view** to edit several entries in `.env` format: ```dotenv APP_ENV=production DATABASE_URL=postgresql://app:password@database:5432/app LOG_LEVEL=info ``` Saving Developer view creates, updates, and removes managed variables to match the text. Locked secrets and multiline values cannot be changed from Developer view. Required values and defaults [#required-values-and-defaults] The Compose expression determines the initial requirement: | Syntax | Coolify behavior | | :--------------------- | :---------------------------------------------------------------------- | | `${VARIABLE}` | Creates an editable value that can be empty. | | `${VARIABLE:-default}` | Creates the variable with the fallback as its initial value. | | `${VARIABLE:?}` | Marks the variable as required and blocks deployment while it is empty. | For example: ```yaml services: app: environment: APP_SECRET: ${APP_SECRET:?} LOG_LEVEL: ${LOG_LEVEL:-info} ``` After saving the Compose definition, enter **APP\_SECRET** before deploying. Reuse values across components [#reuse-values-across-components] Reference one variable from every component that needs it: ```yaml services: api: environment: DATABASE_URL: ${DATABASE_URL:?} worker: environment: DATABASE_URL: ${DATABASE_URL:?} ``` Coolify stores one **DATABASE\_URL** value for the Service and writes it into the `.env` file used by Docker Compose. Use a shared variable when several Coolify resources need the same value: ```dotenv DATABASE_URL={{environment.DATABASE_URL}} ``` Read [Shared variables](/core/team/shared-variables) for team, project, environment, and server scopes. External secret managers [#external-secret-managers] Link Doppler, Infisical, or HashiCorp Vault and reference a remote value with `{{vault.KEY}}`. The source applies to the whole Service stack. Follow [Use a secret manager](/integrations/security/using-secret-managers). Generated domains and credentials [#generated-domains-and-credentials] Variables that start with `SERVICE_` can instruct Coolify to generate a value. URL and FQDN variables are tied to the matching Compose service and its domain configuration. Password, username, and random-value variables persist with the Service so components can share them. Read [Docker Compose generated Service values](/services/configuration/docker-compose#generated-service-values) before renaming or deleting one. Coolify prevents deleting a managed variable while the Compose definition still uses it; remove the reference from Compose first. Apply and verify changes [#apply-and-verify-changes] 1. Save the variable. 2. Confirm every required value is filled. 3. Restart or deploy the Service so Coolify rewrites `.env` and recreates the containers. 4. Inspect the deployment output and component logs. 5. Verify the behavior that consumes the value. Do not paste production secrets into support messages or screenshots. Team members can have restricted access to secret values even when they can view the Service. # General (/docs/services/configuration/general) General settings [#general-settings] Open a Service and select **Configuration > General**. This page combines settings for the complete stack with cards for every application and database component detected in the Compose definition. Service Stack [#service-stack] Use the tab that matches the setting you need to change. Resource details [#resource-details] **Service Name** identifies the resource in its project and environment. Changing the display name does not rename the Compose services or their running containers. Use **Description** to record the stack's purpose, owner, or environment. It does not affect the deployment. Predefined network [#predefined-network] By default, the Service components use only the stack's resource-specific network. Enable **Connect To Predefined Network** when they must also communicate through the predefined network selected for the Service. On the default destination, this is the shared Docker network named `coolify`. Coolify attaches each Service component to that network and adds an alias based on its Compose service name and Service UUID. Components inside the same stack should continue to use the Compose service name and internal port. Do not enable this setting merely to expose an HTTP component. Configure a domain on the component and let the Coolify Proxy route public traffic. Read [Service networking](/services/configuration/networking) for the `coolify` network, custom destination networks, cross-server communication, domains, and published ports. Service Specific Configuration [#service-specific-configuration] Some one-click templates place generated credentials or application-specific values under **Service Specific Configuration**. Review each field's helper text and the individual Service guide before changing it. Coolify saves the value in the Service environment and reparses the Compose definition. Compose editor [#compose-editor] Select **Edit Compose File** to open the definition stored on the Service. | Control | Purpose | | :--------------------------------------- | :------------------------------------------------------------------- | | **Show Source Compose** | Returns to the editable Compose definition. | | **Show Deployable Compose** | Shows the generated definition Coolify sends to Docker Compose. | | **Validate** | Checks a user-defined Service created with **Docker Compose Empty**. | | **Escape special characters in labels?** | Controls whether label characters such as `$` are escaped. | Read [Docker Compose](/services/configuration/docker-compose) before changing images, volumes, environment references, networks, or proxy-related values. Service components [#service-components] Each component card represents one entry parsed from the Compose `services:` map. Use the tab that matches the component or action you need. Component cards [#component-cards] A card shows the component name, image, status, and configured domain when applicable. | Action | Purpose | | :----------- | :------------------------------------------------------------------------ | | **Settings** | Opens the component-specific General and Advanced pages. | | **Restart** | Restarts only that running component container. | | **Backups** | Opens backup controls for a recognized database component when supported. | Restart one component only when its dependencies can tolerate the interruption. Deploy or restart the complete Service when a Compose or shared environment change affects several components. General [#general] | Setting | Behavior | | :-------------- | :---------------------------------------------------------------------------------------------------------------------------- | | **Name** | Sets a human-readable component name without changing its Compose service name. | | **Description** | Records component-specific context. | | **Domains** | Routes one or more HTTP URLs through the Coolify Proxy. Add the internal port when the process does not listen on port `80`. | | **Image** | Changes the image reference written to the generated Compose definition. Review the upstream upgrade path before changing it. | For example, use `https://app.example.com:3000` when the component listens on port `3000`. Visitors still use normal HTTPS; the suffix selects the port inside the container. Advanced [#advanced] The **Advanced** page can configure: * **Enable Gzip Compression** * **Strip Prefixes** * **Exclude from service status** * **Drain Logs**, when a log drain is enabled on the server General [#general-1] The General page can change the database component's human-readable name, description, and image. It can also enable **Make it publicly available** and select a **Public Port** for the database TCP proxy. Expose a database only when a client outside the Service networks must connect. Restrict the public port with the server or provider firewall, use engine-supported encryption, and do not reuse a generated credential outside its intended environment. Advanced and data operations [#advanced-and-data-operations] The **Advanced** page can exclude the component from the Service's aggregate status and enable a server log drain. Recognized database components can also show **Backups** and **Import Backup** pages when the underlying engine is supported. Changing a database image tag is not a database upgrade procedure. Create and verify a compatible backup before changing a production image. Convert a component [#convert-a-component] Use **Convert to Database** or **Convert to Application** only when Coolify classified the Compose service incorrectly. Conversion preserves the Compose service entry and image while changing the component controls shown by Coolify. After conversion, review domains, public ports, storage, backups, health status, and log settings before redeploying. Save and verify changes [#save-and-verify-changes] 1. Save the stack or component setting. 2. Review **Show Deployable Compose** when the change affects generated Compose. 3. Restart or deploy the Service. 4. Follow the deployment output. 5. Confirm that every required component is running and healthy. 6. Open configured domains and test internal dependencies. If one component fails, inspect **Logs** for that container and compare the source and deployable Compose definitions. # Networking (/docs/services/configuration/networking) Configure Service networking [#configure-service-networking] Every Service has a resource-specific Docker network for the components in its Compose definition. Coolify also creates a shared Docker network named `coolify` on each connected server. By default, Service components use only their resource-specific network. Enable **Connect To Predefined Network** when they must also join the predefined Docker network selected for the Service. On a standard installation, that network is `coolify`. Understand the two Service networks [#understand-the-two-service-networks] | Network | Purpose | | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Service network | A private network created for one Service stack. Its name is based on the Service UUID. Components in the stack use it automatically. | | Coolify network | The shared, attachable network named `coolify` that Coolify creates on the server. Applications, standalone Databases, the Coolify Proxy, and Services that enable **Connect To Predefined Network** can use it. | The `coolify` network lets separate Coolify resources on the same server communicate without publishing host ports. It does not extend to another server. The default destination uses the Docker network named `coolify`. If an administrator creates another destination and selects it for the Service, **Connect To Predefined Network** attaches the Service components to that selected network instead. The setting attaches one predefined network; it does not connect the Service to every destination or Docker network on the server. Choose the connection target [#choose-the-connection-target] Components in one Compose definition communicate over the Service network. Use the Compose `services:` key as the hostname and the port where the dependency listens inside its container: ```yaml services: api: image: example/api:1.0 environment: DATABASE_URL: postgresql://app:password@database:5432/app database: image: postgres:17 ``` In this example, `api` connects to `database:5432`. It must not use `localhost`, a public domain, or a published host port. Inside `api`, `localhost` refers to the `api` container itself. You do not need `ports:` or a domain for this private connection. A Compose `depends_on` entry can control startup order, but the calling component must still tolerate the dependency taking time to become ready. Use the `coolify` network when the Service must privately reach an Application, standalone Database, or another Service attached to that network on the same server. 1. Confirm that both resources run on the same server. 2. Confirm that the other resource is attached to the `coolify` network. 3. Confirm that the Service's predefined destination network is `coolify`. 4. Open the Service and select **Configuration > General**. 5. Enable **Connect To Predefined Network**. 6. Restart or deploy the Service. 7. Use the other resource's internal hostname and internal port. 8. Test the connection from the calling Service component. Coolify attaches every Service component to the predefined network and adds an alias based on the Compose service name and Service UUID. With the default destination, the predefined network is `coolify`. Use the deployed container name or alias shown by Coolify when another resource must call that component. Do not assume that the unsuffixed Compose service name is unique outside its own stack. For a standalone Database, use the **Internal URL** shown by Coolify. For another Service, identify its deployed component name and the port where that component listens. The Coolify Proxy joins the Service network when Coolify starts the stack. A component with a configured domain can therefore receive proxied traffic without enabling **Connect To Predefined Network**. Enable the setting for private communication with other resources, not merely to publish a domain. Resources on separate Docker networks cannot resolve or connect to each other by container name unless they also share a network. **Connect To Predefined Network** joins the Service only to its predefined destination network, normally `coolify`. It does not join every network on the server. Choose one of these approaches: 1. **Use one shared network.** This is the simplest option when the resources are intended to communicate privately. For an existing Service, clone it to the required destination and migrate its data separately. [Clone or move a Service](/services/operations/resource-operations) explains the data boundary. 2. **Use a domain or another routed endpoint.** This preserves network isolation and works well for HTTP APIs. The request travels through the proxy instead of Docker's private DNS. 3. **Manage an external Docker network in Compose.** Use this only when you own the Compose definition and the network already exists on the same server. ```yaml services: api: image: example/api:1.0 networks: - shared networks: shared: external: true name: existing-shared-network ``` Coolify does not create or manage an external network declared this way. The network must exist on the selected server, and deleting or renaming it breaks the connection. Declaring an external Compose network also does not change the Service's predefined destination in the dashboard. A Docker bridge network and its container DNS exist on one Docker host. The `coolify` network on one server does not route traffic to the `coolify` network on another server. Use a network path that is routable between the servers: * an HTTP or HTTPS domain routed through the Coolify Proxy * private server addresses supplied by your hosting provider * a VPN or overlay network such as WireGuard or Tailscale * a secured TCP endpoint for a database, queue, or other non-HTTP protocol * an application-level API, tunnel, or broker designed for remote communication The receiving component must listen on an address reachable through that path. Configure firewalls to allow only the required source, destination, and port. Add protocol-level TLS and authentication when traffic leaves a trusted private network. Do not use a Service component's container name as a cross-server hostname. Container names and Docker network aliases are local to their Docker host. HTTP domains [#http-domains] Configure **Domains** on the application component. When the process listens on an internal port other than `80`, include that internal port in the Coolify domain value, for example `https://api.example.com:3000`. Visitors still connect over standard HTTPS. The `:3000` tells the Coolify Proxy which port to use inside the component container. You normally do not need a Compose `ports:` mapping for domain-based routing. DNS must point the hostname to the server, and the server proxy must be running and reachable on its public HTTP and HTTPS ports. Read [Networking in Coolify](/core/networking-in-coolify) for the complete DNS, server, proxy, Docker network, and container path. Host ports [#host-ports] A Compose `ports:` entry publishes a component port on a server interface: ```yaml services: api: image: example/api:1.0 ports: - "8080:3000" ``` This maps server port `8080` to container port `3000`. Unless the binding specifies a host address, Docker can listen on all server interfaces. The port can bypass domain-based proxy routing and expose the component directly. Use a published port only when an external client requires direct TCP or UDP access. Restrict it with the hosting-provider and server firewalls, avoid common host-port collisions, and secure the application protocol itself. To bind only on the server loopback interface, declare the address explicitly: ```yaml ports: - "127.0.0.1:8080:3000" ``` A loopback binding is reachable only from the server itself unless another local process forwards it. Verify the connection [#verify-the-connection] After changing networking configuration: 1. Save the setting or Compose definition, then restart or deploy the Service. 2. Review **Show Deployable Compose** and confirm each component has the intended networks and ports. 3. Open **Terminal** on the calling component and resolve the intended internal hostname using a tool available in that image. 4. Connect to the dependency's internal port and verify an application-level response, not only DNS resolution. 5. For a domain, make an HTTPS request from an external client and confirm it reaches the intended component. 6. For a published port, test from an allowed client and confirm the port is blocked from networks that should not reach it. If private communication fails, first confirm that both containers run on the same server and share at least one Docker network. Matching project or environment names do not create network connectivity. Networking boundaries [#networking-boundaries] * A project or environment organizes resources; it is not a network boundary. * Coolify creates a separate `coolify` network on each connected server. * A Service uses its resource-specific network even when another resource has the same project or environment. * **Connect To Predefined Network** joins the Service to its one predefined destination network, normally `coolify`. * Docker service names resolve only on networks shared by the relevant containers. * Domains provide routed application access; they do not merge Docker networks. * Published ports expose server interfaces and require firewall and protocol security. # Overview (/docs/services/configuration/overview) Configure a Service [#configure-a-service] Open a Service and select **Configuration** to change the stack, its Compose components, environment values, storage, automation, and organization. A Service has two configuration levels: * stack settings apply to the complete Docker Compose resource * component settings apply to one detected application or database container Stack configuration pages [#stack-configuration-pages] | Configuration page | What it controls | Guide | | :---------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- | | **General** | Service name, description, predefined network access, service-specific fields, Compose definition, and component list. | [Review General settings](/services/configuration/general) | | **Networking** | Communication inside the stack, through the `coolify` network, across servers, and through domains or published ports. | [Configure Service networking](/services/configuration/networking) | | **Environment Variables** | Values used when Coolify renders the Service `.env` file and Compose definition. | [Configure environment variables](/services/configuration/environment-variables) | | **Persistent Storages** | Parsed volumes, directories, and files grouped by component. | [Review persistent storage](/services/configuration/persistent-storage) | | **Scheduled Tasks** | Commands that Coolify runs inside one Service container on a schedule. | [Configure scheduled tasks](/services/operations/scheduled-tasks) | | **Webhooks** | Authenticated requests for Service lifecycle operations. | [Use deploy webhooks](/core/automation/deploy-webhooks) | | **Resource Operations** | Clone the Service to another destination or move it between projects and environments. | [Clone or move a Service](/services/operations/resource-operations) | | **Tags** | Team-level labels used to organize and automate resources. | [Organize resources with tags](/core/automation/tags/overview) | | **Danger Zone** | Permanent Service deletion and optional Docker cleanup actions. | [Delete a Service](/services/operations/danger-zone) | Component settings [#component-settings] Select **Settings** on a component card under **Configuration > General**. Application component settings can include: * display name, description, image, and domains * gzip compression and path-prefix stripping * aggregate-status exclusion and log drain Database component settings can include: * display name, description, and image * public TCP proxy and public port * aggregate-status exclusion and log drain * supported backups and import controls Coolify detects common database images while parsing Compose. If a component is classified incorrectly, its settings provide **Convert to Application** or **Convert to Database**. Conversion changes how Coolify presents and operates that component; it does not change the image into another database or application. Apply configuration changes [#apply-configuration-changes] Saving a setting updates Coolify's stored configuration. It does not always recreate the running containers immediately. Use: * **Deploy** for the first deployment or a stopped Service * **Restart** to recreate the stack without first pulling newer images * **Pull Latest Images & Restart** to pull the saved image tags and recreate the stack Review the configuration-change indicator after saving. Verify every component after a restart, especially after changing Compose, images, variables, domains, networks, or mounts. An image, volume, credential, or Compose change can make a stateful component unavailable or incompatible with its existing data. Create a verified backup and read the component's upgrade instructions before changing a production Service. Continue with configuration guides [#continue-with-configuration-guides] # Persistent Storage (/docs/services/configuration/persistent-storage) Configure persistent storage [#configure-persistent-storage] Service containers are replaceable. Store required files and database data outside the container filesystem with mounts declared in the Service's Docker Compose definition. Open **Configuration > Persistent Storages** to review parsed mounts grouped by application and database component. Storage parsed from a Service is read-only on the Persistent Storages page. Add, change, or remove its mount under **Configuration > General > Edit Compose File**, then save and review the parsed result. Choose a mount [#choose-a-mount] | Compose mount | Use it when | | :--------------------- | :----------------------------------------------------------------- | | Named volume | Docker should manage the server-side storage location. | | Bind-mounted directory | The stack must use a specific directory on the Service server. | | Bind-mounted file | A component needs one configuration or data file at an exact path. | Every mount has a source and a destination inside the container. The destination must match the path where the component actually writes or reads data. Read [Storage mount types](/core/persistent-storage/storage-mounts/overview#choose-a-storage-mount) before choosing a source path. Define a named volume [#define-a-named-volume] ```yaml services: database: image: postgres:17 volumes: - database-data:/var/lib/postgresql/data volumes: database-data: ``` Coolify prefixes the deployed volume name with a resource identifier to prevent collisions. Review **Show Deployable Compose** or **Persistent Storages** for the actual name used on the server. Define a directory or file [#define-a-directory-or-file] A relative bind source is stored under the Service configuration directory. Coolify supports Compose extensions that mark a relative source as a directory or provide managed file content. ```yaml services: app: image: example/app:1.0 volumes: - type: bind source: ./data target: /app/data is_directory: true - type: bind source: ./config/app.yaml target: /app/config.yaml content: | logLevel: info ``` Use an absolute source path only when you intend to depend on that exact path on the selected server. The path must exist with permissions suitable for the container user. Change a mount safely [#change-a-mount-safely] Changing a source or destination does not move the existing files. The container can start with an empty volume or different directory while the previous data remains elsewhere on the server. 1. Identify the component and the exact container destination that contains required data. 2. Back up the source and test the restore path. 3. Stop application writes when changing a database or shared writable mount. 4. Edit the Compose definition. 5. Save and review **Show Deployable Compose** and **Persistent Storages**. 6. Deploy or restart the Service. 7. Verify the component can read and write the expected files before removing the previous source. Back up Service data [#back-up-service-data] Persistent storage survives normal container recreation; it is not a backup. Use the backup method appropriate for each component: * use a database-aware dump for database data * use [storage mount backups](/core/persistent-storage/storage-mounts/backups) when the parsed mount and interface support them * use an external backup tool for a mount without a Coolify backup control Keep at least one tested copy outside the Service server. A local archive on the same disk does not protect against server or disk loss. Important boundaries [#important-boundaries] * A mount cannot recover data that was written only to a removed container filesystem. * A server path is not automatically available on another server when you clone the Service. * Sharing one writable mount between components requires application support for concurrency and file locking. * Removing a mount from Compose can remove its Coolify storage record; do not treat that record as the only inventory of important data. # Convertx (/docs/services/convertx) Convertx [#convertx] What is Convertx [#what-is-convertx] A self-hosted online file converter. Supports over a thousand different formats. Links [#links] * [Official Documentation](https://github.com/C4illin/ConvertX?utm_source=coolify.io) # Convex (/docs/services/convex) Convex [#convex] What is Convex [#what-is-convex] Convex is the open-source reactive database for app developers. How to Generate an Admin Key [#how-to-generate-an-admin-key] To generate an admin key for your Convex application in Coolify, follow these steps: 1. Go to the Coolify dashboard. 2. Select your Convex application. 3. Open the Terminal tab. 4. Connect to the backend terminal. 5. In the terminal, execute the following command: `./generate_admin_key.sh` 6. Copy the generated admin key for your records. Links [#links] * [Official Documentation](https://docs.convex.dev/?utm_source=coolify.io) # Cryptgeon (/docs/services/cryptgeon) Cryptgeon [#cryptgeon] What is Cryptgeon [#what-is-cryptgeon] Secure note / file sharing service inspired by PrivNote. Links [#links] * [Official Documentation](https://github.com/cupcakearmy/cryptgeon?utm_source=coolify.io) # Cyberchef (/docs/services/cyberchef) Cyberchef [#cyberchef] What is Cyberchef [#what-is-cyberchef] The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis Links [#links] * [Official Documentation](https://github.com/gchq/CyberChef?utm_source=coolify.io) # Dashboard (/docs/services/dashboard) This service is currently not available in Coolify's service catalog. What is Dashboard? [#what-is-dashboard] Dashboard is just that - a dashboard. It's inspired by [SUI](https://github.com/jeroenpardon/sui) and has all the same features as SUI, such as simple customization through JSON-files and a handy search bar to search the internet more efficiently. Features [#features] So what makes this project different from (or even better than) SUI? * "Display URL" functionality (The URL displayed for apps can differ from the actual URL) * Categorization for apps * Themes and search providers can be changed using JSON * Imprint functionality Links [#links] * [GitHub](https://github.com/phntxx/dashboard?utm_source=coolify.io) # Dashy (/docs/services/dashy) Dashy [#dashy] What is Dashy [#what-is-dashy] A self-hostable personal dashboard built for you. Includes status-checking, widgets, themes, icon packs, a UI editor and tons more! Links [#links] * [Official Documentation](https://dashy.to/docs?utm_source=coolify.io) # Databasus (/docs/services/databasus) Databasus [#databasus] What is Databasus? [#what-is-databasus] Databasus is a free, open source and self-hosted tool to backup databases like PostgreSQL, MySQL and MongoDB. Make backups with different storages (S3, Google Drive, FTP, etc.) and notifications about progress (Slack, Discord, Telegram, etc.). Previously known as Postgresus. Screenshots [#screenshots] Links [#links] * [The official website](https://databasus.com/?utm_source=coolify.io) * [Documentation](https://databasus.com/installation?utm_source=coolify.io) * [GitHub](https://github.com/databasus/databasus?utm_source=coolify.io) # Denokv (/docs/services/denokv) Denokv [#denokv] What is Deno KV [#what-is-deno-kv] Deno KV is a self-hosted, JavaScript-first key-value database built directly into the Deno runtime. It provides a robust, high-performance data storage solution powered by FoundationDB and SQLite, designed for modern edge computing and serverless applications. Key features include: * **ACID Transactions**: Guaranteed data consistency with full ACID transaction support, preventing partial writes and data corruption * **Built on FoundationDB**: Enterprise-grade backend capable of handling millions of operations per second * **Real-time Watch API**: Monitor database changes in real-time for building reactive applications, notifications, and live updates * **Zero Configuration**: Works out of the box with the Deno runtime, no complex setup required * **JavaScript Native**: Store any JavaScript value directly without manual serialization * **Hierarchical Keys**: Organize data with structured, REST-like key patterns for intuitive data modeling * **Multiple Consistency Levels**: Balance between performance and consistency based on your application needs * **Self-hosted & Open Source**: MIT licensed with full control over your infrastructure Links [#links] * [Official Website](https://deno.com/kv?utm_source=coolify.io) * [Official Documentation](https://docs.deno.com/deploy/kv/manual/?utm_source=coolify.io) * [GitHub Repository](https://github.com/denoland/denokv?utm_source=coolify.io) # Directus (/docs/services/directus) What is Directus? [#what-is-directus] Directus is a real-time API and App dashboard for managing SQL database content. * **Open Source.** No artificial limitations, vendor lock-in, or hidden paywalls. * **REST & GraphQL API.** Instantly layers a blazingly fast Node.js API on top of any SQL database. * **Manage Pure SQL.** Works with new or existing SQL databases, no migration required. * **Choose your Database.** Supports PostgreSQL, MySQL, SQLite, OracleDB, CockroachDB, MariaDB, and MS-SQL. * **On-Prem or Cloud.** Run locally, install on-premises, or use our [self-service Cloud service](https://directus.io/pricing?utm_source=coolify.io). * **Completely Extensible.** Built to white-label, it is easy to customize our modular platform. * **A Modern Dashboard.** Our no-code Vue.js app is safe and intuitive for non-technical users, no training required. Deployment Variants [#deployment-variants] Directus is available in two deployment configurations in Coolify: Directus (Default) [#directus-default] * **Database:** SQLite3 (file-based) * **Use case:** Development, testing, or small-scale deployments * **Components:** Single Directus container with embedded SQLite database Directus with PostgreSQL [#directus-with-postgresql] * **Database:** PostgreSQL + Redis * **Use case:** Production deployments requiring better performance, scalability, and caching * **Components:** * Directus container * PostgreSQL 16 container * Redis 7 container for caching * Automatic database configuration and health checks Community Help [#community-help] [The Directus Documentation](https://docs.directus.io?utm_source=coolify.io) is a great place to start, or explore these other channels: * [Discord](https://directus.chat?utm_source=coolify.io) (Questions, Live Discussions) * [GitHub Issues](https://github.com/directus/directus/issues?utm_source=coolify.io) (Report Bugs) * [GitHub Discussions](https://github.com/directus/directus/discussions?utm_source=coolify.io) (Feature Requests) * [Twitter](https://twitter.com/directus?utm_source=coolify.io) (Latest News) * [YouTube](https://www.youtube.com/c/DirectusVideos/featured?utm_source=coolify.io) (Video Tutorials) Links [#links] * [The official website](https://directus.io?utm_source=coolify.io) * [GitHub](https://github.com/directus/directus?utm_source=coolify.io) # Diun (/docs/services/diun) What is Diun? [#what-is-diun] Docker Image Update Notifier is a CLI application written in Go and delivered as a single executable (and a Docker image) to receive notifications when a Docker image is updated on a Docker registry. Links [#links] * [The official website](https://crazymax.dev/diun/?utm_source=coolify.io) * [GitHub](https://github.com/crazy-max/diun?utm_source=coolify.io) # Docker Registry (/docs/services/docker-registry) What is Docker Registry? [#what-is-docker-registry] Docker Registry is a stateless, highly-available server side application that stores and distributes Docker images. Links [#links] * [The official website](https://hub.docker.com?utm_source=coolify.io) * [GitHub](https://github.com/docker/distribution?utm_source=coolify.io) # Docmost (/docs/services/docmost) What is Docmost? [#what-is-docmost] Docmost is an open-source collaborative wiki and documentation software. Screenshots [#screenshots] Links [#links] * [The official website](https://www.docmost.com?utm_source=coolify.io) * [GitHub](https://github.com/docmost/docmost?utm_source=coolify.io) # Documenso (/docs/services/documenso) Documenso [#documenso] What is Documenso [#what-is-documenso] Document signing, finally open source Links [#links] * [Official Documentation](https://docs.documenso.com/?utm_source=coolify.io) # Docuseal (/docs/services/docuseal) What is Docuseal? [#what-is-docuseal] Document Signing for Everyone free forever for individuals, extensible for businesses and developers. Open Source Alternative to DocuSign, PandaDoc and more. Deployment Variants [#deployment-variants] DocuSeal is available in two deployment configurations in Coolify: DocuSeal (Default) [#docuseal-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or low-volume document signing * **Components:** Single DocuSeal container with built-in SQLite database DocuSeal with PostgreSQL [#docuseal-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring better performance, scalability, and concurrent access * **Components:** * DocuSeal container * PostgreSQL container * Automatic database configuration and health checks Screenshots [#screenshots] Links [#links] * [The official website](https://www.docuseal.co?utm_source=coolify.io) * [GitHub](https://github.com/docusealco/docuseal?utm_source=coolify.io) # DokuWiki (/docs/services/dokuwiki) What is DokuWiki? [#what-is-dokuwiki] DokuWiki is a simple to use and highly versatile Open Source wiki software that doesn't require a database. It is loved by users for its clean and readable syntax. The ease of maintenance, backup and integration makes it an administrator's favorite. Built in access controls and authentication connectors make DokuWiki especially useful in the enterprise context and the large number of plugins contributed by its vibrant community allow for a broad range of use cases beyond a traditional wiki. Why DokuWiki? [#why-dokuwiki] DokuWiki is a popular choice when choosing a Wiki software and has many advantages over similar software. * Easy to install and use * Low system requirements * Built-in Access Control Lists * Large variety of extensions * Over 50 languages supported * Device independent * Open Source Use Cases [#use-cases] DokuWiki are quick to update and new pages are easily added. Designed for collaboration while maintaining a history of every change, DokuWiki could be used as: * Corporate Knowledge Base * Private notebook * Software manual * Project workspace * CMS – intranet Links [#links] * [The official website](https://www.dokuwiki.org?utm_source=coolify.io) * [GitHub](https://github.com/splitbrain/DokuWiki?utm_source=coolify.io) # Dolibarr (/docs/services/dolibarr) Dolibarr [#dolibarr] What is Dolibarr [#what-is-dolibarr] Dolibarr is a modern software package to manage your organization's activity (contacts, quotes, invoices, orders, stocks, agenda, hr, expense reports, accountancy, ecm, manufacturing, ...). Links [#links] * [Official Documentation](https://www.dolibarr.org/documentation-home.php?utm_source=coolify.io) # Dozzle (/docs/services/dozzle) What is Dozzle? [#what-is-dozzle] Dozzle is an open-source project sponsored by Docker OSS. It is a log viewer designed to simplify monitoring and debugging containers. This lightweight, web-based application offers real-time log streaming, filtering, and searching capabilities through an intuitive user interface. Users can quickly access logs generated by their Docker containers, making it an essential tool for debugging and troubleshooting applications in a Docker environment. By default, Dozzle supports JSON logs with intelligent color coding. Dozzle is easy to install and configure, making it an ideal solution for developers and system administrators seeking an efficient, user-friendly log viewer for their Docker environment. The tool is available under the MIT license and is actively maintained by its developer, Amir Raminfar. Deployment Variants [#deployment-variants] Dozzle is available in two deployment configurations in Coolify: Dozzle (Default) [#dozzle-default] * **Authentication:** No authentication (open access) * **Use case:** Development environments, trusted networks, or single-user setups * **Components:** Single Dozzle container with Docker socket access Dozzle with Authentication [#dozzle-with-authentication] * **Authentication:** Built-in authentication with user management * **Use case:** Production environments, multi-user access, or security-sensitive deployments * **Components:** * Dozzle container with authentication enabled * User credential management * Docker socket access Links [#links] * [The official website](https://dozzle.dev/guide/getting-started#running-with-docker?utm_source=coolify.io) * [GitHub](https://github.com/amir20/dozzle?utm_source=coolify.io) # Drizzle Gateway (/docs/services/drizzle-gateway) Drizzle Gateway [#drizzle-gateway] What is Drizzle Gateway? [#what-is-drizzle-gateway] Drizzle Studio is a new way for you to explore SQL database on Drizzle ORM project. Links [#links] * [The official website](https://orm.drizzle.team/docs/get-started/postgresql-new?utm_source=coolify.io) * [GitHub](https://github.com/drizzle-team/drizzle-orm?utm_source=coolify.io) # Drupal (/docs/services/drupal) Drupal [#drupal] What is Drupal [#what-is-drupal] Drupal is a free and open-source web content management system written in PHP and distributed under the GNU General Public License. Links [#links] * [Official Documentation](https://www.drupal.org/about?utm_source=coolify.io) # Duplicati (/docs/services/duplicati) What is Duplicati? [#what-is-duplicati] Free backup software to store encrypted backups online for Windows, macOS and Linux. Links [#links] * [The official website](https://www.duplicati.com?utm_source=coolify.io) * [GitHub](https://github.com/duplicati/duplicati?utm_source=coolify.io) # Easyappointments (/docs/services/easyappointments) Easyappointments [#easyappointments] What is Easyappointments [#what-is-easyappointments] Schedule Anything. Let's start with easy! Get the best free online appointment scheduler on your server, today. Links [#links] * [Official Documentation](https://easyappointments.org/?utm_source=coolify.io) # Elasticsearch (/docs/services/elasticsearch) Elasticsearch [#elasticsearch] What is Elasticsearch? [#what-is-elasticsearch] Elasticsearch is an open-source search and analytics engine designed for fast, scalable data retrieval—ideal for handling large volumes of both structured and unstructured data. How to Deploy Elasticsearch on Coolify [#how-to-deploy-elasticsearch-on-coolify] There are two ways to deploy Elasticsearch on Coolify: * **Elasticsearch as a standalone service** (no GUI) * **Elasticsearch with Kibana** (GUI) *** Elasticsearch as a Standalone Service [#elasticsearch-as-a-standalone-service] 1. Create a new resource on Coolify and select **Elasticsearch with Kibana** from the service list. 2. Click the **Deploy** button to pull the Docker images and start the containers. 3. Once the `Elasticsearch` service shows as healthy, you can access it via its assigned domain. > ⚠️ Note: This version does not include a GUI—you’ll need to interact with it via CLI tools or APIs. *** Deploy Elasticsearch with Kibana [#deploy-elasticsearch-with-kibana] 1. Create a new resource on Coolify and select **Elasticsearch with Kibana** from the service list. 2. Click the **Deploy** button to pull the Docker images and start the containers. 3. Once the `Elasticsearch` service is running and the `Kibana Token Generator` shows an **exited** status: * Open the logs of the `Kibana Token Generator` service. * Copy the **Service Token** from the logs. * Paste the token into the `ELASTICSEARCH_SERVICEACCOUNTTOKEN` environment variable. * Restart the service (click the **Restart** button). 4. After both `Elasticsearch` and `Kibana` services are running healthy, visit the domain assigned to the service. * You’ll be presented with the Elastic login page. * **Username:** `elastic`\ **Password:** value of the `SERVICE_PASSWORD_ELASTICSEARCH` environment variable. If any of the above steps are unclear, you can refer to [this Pull Request](https://github.com/coollabsio/coolify/pull/6470), which includes a video walkthrough of the entire deployment process. *** Notes for Elasticsearch with Kibana [#notes-for-elasticsearch-with-kibana] 1. It can take over **2 minutes** for all services to fully start (depending on your server’s performance). 2. The JVM heap size is set to **512MB** by default to prevent Elasticsearch from exhausting server memory. > To increase this value, modify the environment variable:\ > `ES_JAVA_OPTS=-Xms512m -Xmx512m` in the Docker Compose file. 3. The `Kibana Token Generator` service is designed to **run once and then exit**. This is expected behavior and does not impact the health of the Elastic or Kibana services. 4. Clustering is **disabled by default** via the `discovery.type=single-node` environment variable. > Update this setting if clustering is required. *** Useful Links [#useful-links] * [Official Website](https://www.elastic.co/?utm_source=coolify.io) * [Official Documentation](https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-kibana-with-docker?utm_source=coolify.io) # ElectricSQL (/docs/services/electricsql) ElectricSQL [#electricsql] What is ElectricSQL? [#what-is-electricsql] ElectricSQL allows developers to build fast, modern, collaborative apps without changing their stack Notes on deployment [#notes-on-deployment] When creating the postgresql database, make sure to enable logical replication: adding `wal_level = logical` to your postgresql config should do it. Environment Variables [#environment-variables] * SERVICE\_URL\_ELECTRIC\_3000: exposes port 3000 of electricsql: this is where your clients would connect * DATABASE\_URL: url of the postgresql database (with logical replication enabled) * ELECTRIC\_SECRET: secret electricsql will use to authenticate requests (more info [here](https://electric-sql.com/docs/guides/security#api-token)) * ELECTRIC\_STORAGE\_DIR: electric needs to store some data, cache etc. This is where it'll go * ELECTRIC\_USAGE\_REPORTING: allows configuration of anonymous usage data reporting back to [https://electric-sql.com](https://electric-sql.com) Links [#links] * [Official documentation](https://electric-sql.com/docs) * [GitHub](https://github.com/electric-sql/electric?utm_source=coolify.io) # Emby (/docs/services/emby) What is Emby? [#what-is-emby] Emby is a free personal media server. It is built with a number of popular open source technologies. Requirements [#requirements] Windows, Mac, Linux, or FreeBSD computer Minimum Requirements — no transcoding [#minimum-requirements--no-transcoding] * Intel Core 2 Duo processor 1.6 GHz or better * At least 1GB RAM for Windows/Mac OS X * At least 512MB RAM for Linux * Windows: Vista or later * OS X: MacOS 10.13 or later * Ubuntu, Debian, Fedora, CentOS or SuSE Linux Recommended Configuration — transcoding HD Content [#recommended-configuration--transcoding-hd-content] * Intel Core 2 Duo processor 2.4 GHz or better * If transcoding for multiple devices, a faster CPU may be required * At least 2GB RAM * Windows: Vista or later * OS X: MacOS 10.13 or later * Ubuntu, Debian, Fedora, CentOS or SuSE Linux Community [#community] * [The official website](https://emby.media?utm_source=coolify.io) * [The Emby community](https://emby.media/community?utm_source=coolify.io) # Emby Stat (/docs/services/embystat) What is Emby Stat? [#what-is-emby-stat] EmbyStat is a personal web server that can calculate all kinds of statistics from your (local) Emby or Jellyfin server. Just install this on your server and let him calculate all kinds of fun stuff. Links [#links] * [The official website](https://github.com/mregni/EmbyStat?utm_source=coolify.io) # EMQX Enterprise (/docs/services/emqx-enterprise) What is EMQX Enterprise? [#what-is-emqx-enterprise] EMQX Enterprise is a scalable, distributed MQTT broker built for IoT, Industrial IoT (IIoT), connected vehicles, and AI agent communication. It delivers real-time pub/sub messaging at massive scale, supporting millions of concurrent connections per cluster, sub-millisecond message fan-out, durable message queues with replay, and native integrations with databases, data warehouses, and cloud services such as Snowflake, Google BigQuery, Amazon Redshift, and Amazon S3 Tables. Starting with version 5.9, EMQX unified the previous Open Source and Enterprise editions into a single platform under the Business Source License (BSL) 1.1. All advanced features — including multi-tenancy, fine-grained security (SSO, RBAC, audit logs), geo-replication, session persistence, file transfer, message codec and validation, and 40+ native data integrations — are now available in one product. Under the BSL Additional Use Grant, EMQX remains free for non-production environments, testing, and single-node production deployments, with paid licenses and commercial support for larger production clusters; educational institutions and non-profits can request a free license key. Links [#links] * [The official website](https://www.emqx.com/en/products/emqx) * [Documentation](https://docs.emqx.com/en/enterprise/latest/) * [GitHub](https://github.com/emqx/emqx) # Engram (/docs/services/engram) Engram [#engram] What is Engram? [#what-is-engram] Engram is a persistent memory system for AI coding agents. It is an agent-agnostic Go binary that records decisions, conventions, bug fixes, and discoveries, then exposes them back to agents through an MCP server, an HTTP API, a CLI, and a terminal UI. Locally it keeps memories in SQLite with full-text search, so context survives across sessions instead of being lost when a conversation ends. This one-click template deploys Engram Cloud, the opt-in replication server that runs `engram cloud serve`. Local Engram installs sync their project memory to it, which makes the same memories available across several machines or shared between teammates. The template runs the server together with a PostgreSQL container that stores the replicated data. The server serves both the dashboard and the API on the same port. Coolify generates the API token, the dashboard admin token, and the JWT signing secret automatically at deploy time, so the stack boots authenticated without manual configuration. `ENGRAM_CLOUD_ALLOWED_PROJECTS` defaults to `*`, which accepts any project name while access stays gated by the generated API token. Set it to a comma-separated list to restrict the server to specific projects. Links [#links] * [GitHub](https://github.com/Gentleman-Programming/engram?utm_source=coolify.io) * [Documentation](https://github.com/Gentleman-Programming/engram/blob/main/DOCS.md?utm_source=coolify.io) * [Engram Cloud docs](https://github.com/Gentleman-Programming/engram/blob/main/docs/engram-cloud/README.md?utm_source=coolify.io) # Ente (/docs/services/ente-photos) Ente [#ente] What is Ente? [#what-is-ente] Ente is a service that provides a fully open-source, end-to-end encrypted platform for you to store your data in the cloud without needing to trust the service provider. On top of the platform, Ente has built two apps so far: Ente Photos (an alternative to Apple and Google Photos) and Ente Auth (a 2FA alternative to the deprecated Authy). Learn more at [help.ente.io](https://help.ente.io/). Configuring Object Store [#configuring-object-store] * Once you have selected your service. You will need to set up of some environment variables for your S3 bucket or substitute like MinIO. 1\. Remote S3 bucket [#1-remote-s3-bucket] * For AWS S3 you can create a bucket and allow access via IAM Roles/User Permissions. Which will generate an access key and secret key for your S3 Bucket. * For the S3 bucket, apply the following CORS policy for proper access control from the museum service. ```json [ { "AllowedOrigins": ["*"], "AllowedHeaders": ["*"], "AllowedMethods": ["GET", "HEAD", "POST", "PUT", "DELETE"], "MaxAgeSeconds": 3000, "ExposeHeaders": ["Etag"] } ] ``` * Fill the credentials like `endpoint`, `region`, `bucket`, `access key`, `secret key`. * Deploy the Service and you are good to go. 2\. Coolify minio bucket. [#2-coolify-minio-bucket] * Minio is expected to be exposed over HTTPS and needs SSL/TLS, so make sure your proxies are setup properly. Here is a useful [link](https://selfhostschool.com/minio-self-hosted-s3-storage-guide/) for set up and configuration. * Once you have deployed the Minio service from Coolify you can login to the service from the console URL and use the same username and password as set in the environment variables user the API URL for backend or shell based usecases. ```bash # Set Alias mc alias set # List buckets (same us used in coolify to validate S3) minio/mc ls myminio ``` * Once logged in, create a bucket for your use in Ente. * The default region for Minio is `us-east-1`, so you can use the same. * Use the API endpoint as bucket endpoint for Ente config. **Note**: Additional details are available [here](https://help.ente.io/self-hosting/administration/object-storage). Environment Variables [#environment-variables] | Variable Name | Service | Description | Default Value | Required | Prefilled | | ------------------------------------- | -------- | ------------------------------------------------------------------------------------------- | ------------------ | -------- | --------- | | `SERVICE_URL_MUSEUM_8080` | museum | URL for the museum service on port 8080 | - | Yes | Yes | | `ENTE_HTTP_USE_TLS` | museum | Enable/disable TLS for HTTP connections | `false` | No | Yes | | `SERVICE_URL_WEB_3002` | museum | URL for the web albums service | - | Yes | Yes | | `SERVICE_URL_WEB_3004` | museum | URL for the web cast service | - | Yes | Yes | | `SERVICE_URL_WEB_3001` | museum | URL for the web accounts service | - | Yes | Yes | | `ENTE_DB_HOST` | museum | PostgreSQL database host | `postgres` | No | Yes | | `ENTE_DB_PORT` | museum | PostgreSQL database port | `5432` | No | Yes | | `ENTE_DB_NAME` | museum | PostgreSQL database name | `ente_db` | No | Yes | | `SERVICE_USER_POSTGRES` | museum | PostgreSQL database username | `pguser` | No | Yes | | `SERVICE_PASSWORD_POSTGRES` | museum | PostgreSQL database password | - | Yes | Yes | | `SERVICE_REALBASE64_ENCRYPTION` | museum | Base64 encoded encryption key | - | Yes | Yes | | `SERVICE_REALBASE64_64_HASH` | museum | Base64 encoded hash key | - | Yes | Yes | | `SERVICE_REALBASE64_JWT` | museum | Base64 encoded JWT secret | - | Yes | Yes | | `ENTE_INTERNAL_ADMIN` | museum | Internal admin user ID | `1580559962386438` | No | Yes | | `ENTE_INTERNAL_DISABLE_REGISTRATION` | museum | Disable user registration | `false` | No | Yes | | `PRIMARY_STORAGE_ARE_LOCAL_BUCKETS` | museum | Use local buckets for primary storage (false unless you are connecting to bucket over http) | `false` | No | Yes | | `PRIMARY_STORAGE_USE_PATH_STYLE_URLS` | museum | Use path-style URLs for storage | `true` | No | Yes | | `S3_STORAGE_KEY` | museum | S3 storage access key | - | Yes | No | | `S3_STORAGE_SECRET` | museum | S3 storage secret key | - | Yes | No | | `S3_STORAGE_ENDPOINT` | museum | S3 storage endpoint URL | - | Yes | No | | `S3_STORAGE_REGION` | museum | S3 storage region | `us-east-1` | No | Yes | | `S3_STORAGE_BUCKET` | museum | S3 storage bucket name | - | Yes | No | | `SERVICE_URL_WEB_3000` | web | URL for the main web service | - | Yes | Yes | | `SERVICE_URL_MUSEUM` | web | URL for the museum service | - | Yes | Yes | | `SERVICE_URL_WEB_3002` | web | URL for the albums service | - | Yes | Yes | | `SERVICE_USER_POSTGRES` | postgres | PostgreSQL username | `pguser` | No | Yes | | `SERVICE_PASSWORD_POSTGRES` | postgres | PostgreSQL password | - | Yes | Yes | | `SERVICE_DB_NAME` | postgres | PostgreSQL database name | `ente_db` | No | Yes | Links [#links] * [The official website](https://ente.io?utm_source=coolify.io) * [Documentation](https://help.ente.io?utm_source=coolify.io) * [GitHub](https://github.com/ente-io/ente?utm_source=coolify.io) # ESPHome (/docs/services/esphome) ESPHome [#esphome] What is ESPHome? [#what-is-esphome] ESPHome is an open-source firmware framework that simplifies the process of creating custom firmware for popular WiFi-enabled microcontrollers. Links [#links] * [Official website](https://esphome.io/?utm_source=coolify.io) * [Documentation](https://esphome.io/guides/getting_started_command_line/?utm_source=coolify.io) * [GitHub](https://github.com/esphome/esphome?utm_source=coolify.io) # EspoCRM (/docs/services/espocrm) What is EspoCRM? [#what-is-espocrm] EspoCRM is an open-source customer relationship management (CRM) system for managing sales, marketing, and customer support in one place. Lightweight and flexible, it gives organizations full control over their data. Use cases: * Managing leads, contacts, and sales pipelines * Automating business processes with workflows * Tracking customer communication and activities * Handling support tickets and service requests * Generating reports and analytics for business insights * Integrating with email and third-party services Why EspoCRM? [#why-espocrm] * **Open-source and transparent.** EspoCRM is open source, so you can inspect the code and understand exactly how your data is handled. * **Highly customizable.** You can add custom entities, fields, relationships, and buttons to match your workflows. EspoCRM works as both a CRM and a platform for custom business apps. * **Simple, fast interface.** The UI is clean and easy to navigate, which helps teams get started quickly. * **Easy integration.** EspoCRM provides a straightforward REST API for connecting with external tools and services. Credentials [#credentials] After deploying the service, you can log in with the following credentials: * **Username:** admin * **Password:** is autogenerated and available in the *Service Specific Configuration* Links [#links] * [Official website](https://www.espocrm.com/?utm_source=coolify) * [Documentation](https://docs.espocrm.com/?utm_source=coolify) * [GitHub](https://github.com/espocrm/espocrm?utm_source=coolify) # Evolution API (/docs/services/evolution-api) What is Evolution API? [#what-is-evolution-api] Evolution API is a robust platform devoted to empowering small businesses, entrepreneurs, freelancers, and individuals with limited resources—offering more than just a basic WhatsApp™ messaging solution. What I need to configure to make Coolify work with Evolution API? [#what-i-need-to-configure-to-make-coolify-work-with-evolution-api] The docker-compose available in Coolify should be able to install everything you need to start with the Evolution API + Postgres + Redis + Evolution Manager. Once everything is running, you can access your [https://url/manager](https://url/manager). Screenshots [#screenshots] SCR-20250314-ojnw Links [#links] * [GitHub](https://github.com/EvolutionAPI/evolution-api?utm_source=coolify.io) * [Official Documentation](https://docs.evolutionfoundation.com.br/) # Excalidraw (/docs/services/excalidraw) Excalidraw [#excalidraw] What is Excalidraw? [#what-is-excalidraw] Excalidraw is a virtual whiteboard for sketching hand-drawn like diagrams. It's a collaborative drawing tool that allows you to create diagrams that feel hand-drawn. Excalidraw is perfect for wireframing, brainstorming, creating flowcharts, and collaborative design sessions. It supports real-time collaboration, exports to various formats, and has an intuitive interface that makes digital sketching feel natural. Links [#links] * [The official website](https://excalidraw.com?utm_source=coolify.io) * [GitHub](https://github.com/excalidraw/excalidraw?utm_source=coolify.io) # Faraday (/docs/services/faraday) Faraday [#faraday] What is Faraday [#what-is-faraday] Faraday is a powerful, open-source, web-based vulnerability management tool. Links [#links] * [Official Documentation](https://faradaysec.com/?utm_source=coolify.io) # Fider (/docs/services/fider) What is Fider? [#what-is-fider] Fider is a feedback portal for feature requests and suggestions. Give your customers a voice and let them tell you what they need. Spend less time guessing and more time building the right product. How to setup [#how-to-setup] See the official [Fider + Coolify guide](https://docs.fider.io/hosting-coolify?utm_source=coolify.io) Links [#links] * [The official website](https://fider.io?utm_source=coolify.io) # Filebrowser (/docs/services/filebrowser) What is Filebrowser? [#what-is-filebrowser] Filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app. Setup [#setup] * Deploy Filebrowser using Coolify template * In the Filebrowser UI login with credentials: * Username: `admin` * Password: randomly generated, viewable in the logs Screenshots [#screenshots] Links [#links] * [The official Filebrowser website](https://filebrowser.org?utm_source=coolify.io) * [GitHub](https://github.com/filebrowser/filebrowser?utm_source=coolify.io) # FileFlows (/docs/services/fileflows) What is FileFlows? [#what-is-fileflows] Are you tired of manually managing your files? Meet FileFlows — the ultimate solution for automatic file processing! FileFlows lets you monitor and process any file type with custom flows. Videos, audio, images, archives, comics, eBooks—you name it! Installation [#installation] 1. Create the service within Coolify. 2. If your device supports it, enable hardware transcoding by uncommenting this section in the compose file: ```yaml #devices: # - "/dev/dri:/dev/dri" ``` Screenshots [#screenshots] Links [#links] * [The official website](https://fileflows.com/) * [Doc](https://fileflows.com/docs) # Firefly III (/docs/services/firefly) What is Firefly III? [#what-is-firefly-iii] "Firefly III" is a (self-hosted) manager for your personal finances. It can help you keep track of your expenses and income, so you can spend less and save more. Firefly III supports the use of budgets, categories and tags. Using a bunch of external tools, you can import data. It also has many neat financial reports available. Firefly III should give you insight into and control over your finances. Money should be useful, not scary. You should be able to see where it is going, to feel your expenses and to... wow, I'm going overboard with this aren't I? But you get the idea: this is your money. These are your expenses. Stop them from controlling you. I built this tool because I started to dislike money. Having money, not having money, paying bills with money, you get the idea. But no more. I want to feel "safe", whatever my balance is. And I hope this tool can help you. I know it helps me. Screenshots [#screenshots] Links [#links] * [The official website](https://firefly-iii.org?utm_source=coolify.io) * [GitHub](https://github.com/firefly-iii/firefly-iii?utm_source=coolify.io) # Firefox (/docs/services/firefox) Firefox [#firefox] What is Firefox [#what-is-firefox] Fast, private, and self-hosted secure browser for browsing without limits. Links [#links] * [Official Documentation](https://github.com/jlesage/docker-firefox?utm_source=coolify.io) # Fizzy (/docs/services/fizzy) Fizzy [#fizzy] What is Fizzy? [#what-is-fizzy] Fizzy is a lightweight Kanban board tool developed by 37signals for tracking issues and ideas. Links [#links] * [Official website](https://www.fizzy.do/?utm_source=coolify.io) * [GitHub](https://github.com/basecamp/fizzy?utm_source=coolify.io) # Flipt (/docs/services/flipt) Flipt [#flipt] What is Flipt [#what-is-flipt] Flipt is a fully managed feature flag solution that enables you to keep your feature flags and remote config next to your code in Git. Links [#links] * [Official Documentation](https://docs.flipt.io/v2/introduction?utm_source=coolify.io) # Flowise (/docs/services/flowise) Flowise [#flowise] What is Flowise [#what-is-flowise] Flowise is an open source low-code tool for developers to build customized LLM orchestration flows & AI agents. Deployment Variants [#deployment-variants] Flowise is available in two deployment configurations in Coolify: Flowise (Default) [#flowise-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or personal AI workflow development * **Components:** Single Flowise container with built-in SQLite database Flowise with Databases [#flowise-with-databases] * **Database:** PostgreSQL + Redis * **Use case:** Production deployments requiring better performance, caching, and scalability * **Components:** * Flowise container * PostgreSQL container for data persistence * Redis container for caching and session management * Automatic database configuration and health checks Links [#links] * [Official Documentation](https://docs.flowiseai.com/?utm_source=coolify.io) # Forgejo (/docs/services/forgejo) What is Forgejo? [#what-is-forgejo] Forgejo is a self-hosted lightweight software forge. It's easy to install and low maintenance, it just does the job. Deployment Variants [#deployment-variants] Forgejo is available in four deployment configurations in Coolify: Forgejo (Default) [#forgejo-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or personal Git hosting * **Components:** Single Forgejo container with built-in SQLite database Forgejo with PostgreSQL [#forgejo-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring better performance and scalability * **Components:** * Forgejo container * PostgreSQL container * Automatic database configuration and health checks Forgejo with MySQL [#forgejo-with-mysql] * **Database:** MySQL * **Use case:** Production deployments with MySQL preference * **Components:** * Forgejo container * MySQL container * Automatic database configuration and health checks Forgejo with MariaDB [#forgejo-with-mariadb] * **Database:** MariaDB * **Use case:** Production deployments with MariaDB preference * **Components:** * Forgejo container * MariaDB container * Automatic database configuration and health checks Forgejo Actions Runner [#forgejo-actions-runner] Forgejo has available a first party "actions runner" to [execute task jobs on a repository](https://forgejo.org/docs/latest/user/actions/), much like [GitHub Actions](https://docs.github.com/en/actions) or [GitLab CI](https://docs.gitlab.com/ee/ci/index.html). Coolify includes Forgejo services with a single runner, using [Docker-in-Docker](https://hub.docker.com/_/docker) to handle and report task jobs. Due to the alpha status of the Forgejo runner, rebooting the Forejo application container after the initial setup is required to fully register the shared secret into Forejo for runners to validate: 1. In the **Environment Variables** section of the service configuration, you may set as `RUNNER_SHARED_SECRET` a random 40-character hexagesimal string. The command `openssl rand -hex 20` creates something you can copy and paste. 2. After successfully setting up Forejo, **reboot the `forgejo` service** and wait some seconds until the runner appears in Forgejo *Actions* Configuration section. Forejo is also compatible with third-party CI apps and platforms. Forgejo is a Gitea-fork, so instructions to incorporate these CI may be the same for both. Demo [#demo] * [Demo](https://next.forgejo.org/) Links [#links] * [The official website](https://forgejo.org/) * [Codeberg](https://codeberg.org/forgejo/forgejo) # Formbricks (/docs/services/formbricks) What is Formbricks? [#what-is-formbricks] Formbricks provides a free and open source surveying platform. Gather feedback at every point in the user journey with beautiful in-app, website, link and email surveys. Build on top of Formbricks or leverage prebuilt data analysis capabilities. Screenshots [#screenshots] Links [#links] * [The official website](https://formbricks.com?utm_source=coolify.io) * [GitHub](https://github.com/formbricks/formbricks?utm_source=coolify.io) # Foundryvtt (/docs/services/foundryvtt) Foundryvtt [#foundryvtt] What is Foundryvtt [#what-is-foundryvtt] Foundry Virtual Tabletop is a self-hosted & modern roleplaying platform Links [#links] * [Official Documentation](https://foundryvtt.com/kb/?utm_source=coolify.io) # Freescout (/docs/services/freescout) Freescout [#freescout] What is Freescout [#what-is-freescout] FreeScout is the super lightweight and powerful free open source help desk and shared inbox written in PHP (Laravel framework). Links [#links] * [Official Documentation](https://github.com/freescout-help-desk/freescout/wiki/?utm_source=coolify.io) # Freshrss (/docs/services/freshrss) Freshrss [#freshrss] What is Freshrss [#what-is-freshrss] A free, self-hostable feed aggregator. Deployment Variants [#deployment-variants] FreshRSS is available in four deployment configurations in Coolify: FreshRSS (Default) [#freshrss-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or personal RSS feed reading * **Components:** Single FreshRSS container with built-in SQLite database FreshRSS with PostgreSQL [#freshrss-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring better performance and scalability * **Components:** * FreshRSS container * PostgreSQL container * Automatic database configuration and health checks FreshRSS with MySQL [#freshrss-with-mysql] * **Database:** MySQL * **Use case:** Production deployments with MySQL preference * **Components:** * FreshRSS container * MySQL container * Automatic database configuration and health checks FreshRSS with MariaDB [#freshrss-with-mariadb] * **Database:** MariaDB * **Use case:** Production deployments with MariaDB preference * **Components:** * FreshRSS container * MariaDB container * Automatic database configuration and health checks Links [#links] * [Official Documentation](https://freshrss.org/index.html?utm_source=coolify.io) # Garage (/docs/services/garage) Garage [#garage] What is Garage? [#what-is-garage] Garage is a lightweight geo-distributed data store that implements the Amazon S3 object storage protocol. It enables applications to store large blobs such as pictures, video, images, documents, etc., in a redundant multi-node setting. S3 is versatile enough to also be used to publish a static website. Links [#links] * [Official website](https://garagehq.deuxfleurs.fr/?utm_source=coolify.io) * [Documentation](https://garagehq.deuxfleurs.fr/documentation/quick-start/?utm_source=coolify.io) * [GitLab](https://git.deuxfleurs.fr/Deuxfleurs/garage?utm_source=coolify.io) # Outline (/docs/services/getoutline) What is Outline? [#what-is-outline] Outline is an open-source collaboration tool that allows you to create and share documents with your team. Screenshots [#screenshots] Links [#links] * [The official website](https://getoutline.com/?utm_source=coolify.io) * [GitHub](https://github.com/outline/outline?utm_source=coolify.io) # Ghost (/docs/services/ghost) What is Ghost? [#what-is-ghost] Ghost is a powerful app for professional publishers to create, share, and grow a business around their content. It comes with modern tools to build a website, publish content, send newsletters & offer paid subscriptions to members. Links [#links] * [The official website](https://ghost.org/) * [GitHub](https://github.com/TryGhost/Ghost) # Gitea (/docs/services/gitea) What is Gitea? [#what-is-gitea] Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD. Deployment Variants [#deployment-variants] Gitea is available in four deployment configurations in Coolify: Gitea (Default) [#gitea-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, personal projects, or testing * **Components:** Single Gitea container with built-in SQLite database Gitea with PostgreSQL [#gitea-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring PostgreSQL compatibility and better performance * **Components:** * Gitea container * PostgreSQL 16 container * Automatic database configuration and health checks Gitea with MySQL [#gitea-with-mysql] * **Database:** MySQL * **Use case:** Production deployments with MySQL preference * **Components:** * Gitea container * MySQL container * Automatic database configuration and health checks Gitea with MariaDB [#gitea-with-mariadb] * **Database:** MariaDB * **Use case:** Production deployments with MariaDB preference * **Components:** * Gitea container * MariaDB container * Automatic database configuration and health checks Links [#links] * [The official website](https://gitea.com) * [GitHub](https://github.com/go-gitea/gitea) # GitHub Runner (/docs/services/github-runner) GitHub Runner [#github-runner] What is GitHub Runner? [#what-is-github-runner] GitHub Runner is a self-hosted runner for GitHub Actions that allows you to run CI/CD workflows on your own infrastructure. This Docker-based solution provides more control over the execution environment, better security for private repositories, and can be more cost-effective for heavy workloads. It supports running workflows for multiple repositories and organizations. Links [#links] * [The official GitHub Actions documentation](https://docs.github.com/en/actions/hosting-your-own-runners?utm_source=coolify.io) * [GitHub](https://github.com/myoung34/docker-github-actions-runner?utm_source=coolify.io) # GitLab (/docs/services/gitlab) What is GitLab? [#what-is-gitlab] GitLab is a web-based DevOps lifecycle tool that provides a Git-repository manager providing wiki, issue-tracking and CI/CD pipeline features, powered by Ruby on Rails framework. Demo [#demo] * [Demo](https://gitlab.com/) Links [#links] * [The official website](https://about.gitlab.com) * [GitLab](https://gitlab.com/gitlab-org/gitlab) # Glance (/docs/services/glance) Glance [#glance] A self-hosted dashboard that puts all your feeds in one place. Screenshots [#screenshots] Links [#links] * [The official website](https://github.com/glanceapp/glance) # Glances (/docs/services/glances) What is Glances? [#what-is-glances] Glances is a cross-platform monitoring tool which aims to provide a simple yet efficient and straightforward way to access and display system information. Links [#links] * [The official website](https://nicolargo.github.io/glances/) * [GitHub](https://github.com/nicolargo/glances) # Glitchtip (/docs/services/glitchtip) What is Glitchtip? [#what-is-glitchtip] Track errors, uptime, and performance. An open source reimplementation of Sentry error tracking platform. Links [#links] * [The official website](https://glitchtip.com/) * [GitHub](https://gitlab.com/glitchtip) # GLPI (Gestionnaire Libre de Parc Informatique) (/docs/services/glpi) GLPI [#glpi] What is GLPI [#what-is-glpi] GLPI (Gestionnaire Libre de Parc Informatique) is a free, open-source IT Service Management (ITSM) platform used for IT asset management, helpdesk, and service desk operations, helping organizations inventory hardware/software, manage incidents, track requests, and streamline IT support with features like CMDB, ticketing, and automation. Initial Setup [#initial-setup] After deploying the template, GLPI will automatically complete an installation process, please allow four \~5 mins for full start up. You can then log in with: ```bash # User glpi # password glpi ``` Links [#links] * [Official website](https://glpi-project.org/?utm_source=coolify.io) * [Official Documentation](https://help.glpi-project.org/documentation/?utm_source=coolify.io) * [GitHub](https://github.com/glpi-project/glpi?utm_source=coolify.io) # GoatCounter (/docs/services/goatcounter)
What is GoatCounter? [#what-is-goatcounter] GoatCounter is an open source web analytics platform. It aims to offer easy to use and meaningful privacy-friendly web analytics. * Privacy-aware; doesn’t track users with unique identifiers and doesn't need a GDPR notice. Fine-grained control over which data is collected. * Lightweight and fast; adds just \~3.5K of extra data to your site. Also has JavaScript-free "tracking pixel" option, or you can use it from your application's middleware or import from logfiles. * Identify unique visits without cookies using a non-identifiable hash. * Keeps useful statistics such as browser information, location, and screen size. Keep track of referring sites and campaigns. * Easy; if you've been confused by the myriad of options and flexibility of Google Analytics and Matomo that you don't need then GoatCounter will be a breath of fresh air. * Accessibility is a high-priority feature, and the interface works well with assistive technology such as screen readers. Links [#links] * [The official website](https://www.goatcounter.com?utm_source=coolify.io) * [Documentation](https://www.goatcounter.com/help/start?utm_source=coolify.io) * [GitHub](https://github.com/arp242/goatcounter?utm_source=coolify.io) # Gotenberg (/docs/services/gotenberg) What is Gotenberg? [#what-is-gotenberg] Gotenberg provides a developer-friendly API to interact with powerful tools like Chromium and LibreOffice for converting numerous document formats (HTML, Markdown, Word, Excel, etc.) into PDF files, and more! Gotenberg **has no UI**. Head to the [documentation](https://gotenberg.dev/docs/getting-started/introduction) to learn how to interact with it 🚀. Links [#links] * [Official Website](https://gotenberg.dev) * [GitHub](https://github.com/gotenberg/gotenberg) # Gotify (/docs/services/gotify) What is Gotify? [#what-is-gotify] Gotify is a simple server for sending and receiving messages in real-time per WebSocket. It includes a sleek web UI for managing notifications and provides complete control over your notification data. Features [#features] * **Self-Hosted & Privacy-Focused:** Complete control over your data with no reliance on third-party services * **REST API:** Send messages through a simple and powerful REST API * **WebSocket:** Receive messages in real-time using WebSocket connections * **Cross-Platform:** Written in Go, works on multiple platforms including Docker * **Android & iOS Support:** Native mobile apps available for push notifications * **User Management:** Manage multiple users, clients, and applications * **Lightweight:** Efficient server that doesn't consume excessive resources * **Open Source:** MIT licensed and community-maintained * **Easy Integration:** Simple API makes it easy to integrate with existing applications and services Use Cases [#use-cases] Perfect for receiving notifications from: * Monitoring systems and alerts * CI/CD pipelines * Home automation services * Custom scripts and applications * Server and application monitoring * Backup notifications Screenshots [#screenshots] Links [#links] * [The official website](https://gotify.net/) * [GitHub](https://github.com/gotify/server) * [Documentation](https://gotify.net/docs/) * [Android App (Google Play)](https://play.google.com/store/apps/details?id=com.github.gotify) * [Android App (F-Droid)](https://f-droid.org/de/packages/com.github.gotify/) # GoWa (/docs/services/gowa) GoWa [#gowa] What is GoWa? [#what-is-gowa] GoWa (Golang WhatsApp) is a WhatsApp Web API service built with Go for efficient memory usage and performance. It provides multi-device support and allows you to integrate WhatsApp functionality into your applications through a REST API. GoWa is designed to be lightweight and scalable, making it ideal for businesses that need WhatsApp automation and integration capabilities. Links [#links] * [GitHub](https://github.com/aldinokemal/go-whatsapp-web-multidevice?utm_source=coolify.io) # Grafana (/docs/services/grafana) What is Grafana? [#what-is-grafana] The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more. Deployment Variants [#deployment-variants] Grafana is available in two deployment configurations in Coolify: Grafana (Default) [#grafana-default] * **Database:** Embedded (SQLite) * **Use case:** Simple monitoring setups, testing, or temporary dashboards * **Components:** Single Grafana container with built-in database Grafana with PostgreSQL [#grafana-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring persistent data storage, high availability, and better performance * **Components:** * Grafana container * PostgreSQL 16 container * Automatic database configuration and health checks Features [#features] Grafana allows you to query, visualize, alert on and understand your metrics no matter where they are stored. Create, explore, and share dashboards with your team and foster a data-driven culture: * **Visualizations:** Fast and flexible client side graphs with a multitude of options. Panel plugins offer many different ways to visualize metrics and logs. * **Dynamic Dashboards:** Create dynamic & reusable dashboards with template variables that appear as dropdowns at the top of the dashboard. * **Explore Metrics:** Explore your data through ad-hoc queries and dynamic drilldown. Split view and compare different time ranges, queries and data sources side by side. * **Explore Logs:** Experience the magic of switching from metrics to logs with preserved label filters. Quickly search through all your logs or streaming them live. * **Alerting:** Visually define alert rules for your most important metrics. Grafana will continuously evaluate and send notifications to systems like Slack, PagerDuty, VictorOps, OpsGenie. * **Mixed Data Sources:** Mix different data sources in the same graph! You can specify a data source on a per-query basis. This works for even custom datasources. Links [#links] * [The official website](https://grafana.com/) * [GitHub](https://github.com/grafana/grafana) # Gramps Web (/docs/services/gramps-web) Gramps Web [#gramps-web] What is Gramps Web? [#what-is-gramps-web] The free, open-source genealogy system for building your family tree – together. Use it standalone or as a companion to Gramps Desktop, with full control over your data and privacy as the top priority. Screenshots [#screenshots] Links [#links] * [Official website](https://www.grampsweb.org/?utm_source=coolify.io) * [GitHub](https://github.com/gramps-project/gramps-web?utm_source=coolify.io) # Grimmory (/docs/services/grimmory) Grimmory [#grimmory] Grimmory Logo What is Grimmory? [#what-is-grimmory] Grimmory is a self-hosted ebook library manager and reader, and the successor to Booklore. It allows you to organize, manage, and read your ebook collection from a clean web interface, with support for auto-importing books via a bookdrop folder. Links [#links] * [Official website](https://grimmory.org/) * [GitHub](https://github.com/grimmory-tools/grimmory?utm_source=coolify.io) * [Docker Hub](https://hub.docker.com/r/grimmory/grimmory?utm_source=coolify.io) # Grist (/docs/services/grist) What is Grist? [#what-is-grist] Grist is a modern relational spreadsheet. It combines the flexibility of a spreadsheet with the robustness of a database. Links [#links] * [The official website](https://getgrist.com/?utm_source=coolify.io) * [GitHub](https://github.com/gristlabs/grist-core?utm_source=coolify.io) # Grocy (/docs/services/grocy) What is Grocy? [#what-is-grocy] Grocy is a web-based self-hosted groceries & household management solution for your home. After installation your default credentials will be username: `admin`, password: `admin`. Make sure to update these ASAP by logging in and editing the `admin` user in the settings, which can be found in the top right of your screen. Links [#links] * [The official website](https://grocy.info) * [GitHub](https://github.com/grocy/grocy) # Hatchet (/docs/services/hatchet) Hatchet [#hatchet] What is Hatchet? [#what-is-hatchet] Hatchet is a platform for running background tasks and durable workflows, built on top of Postgres. It bundles a durable task queue, observability, alerting, a dashboard, and a CLI into a single platform. Links [#links] * [Official website](https://hatchet.run/?utm_source=coolify.io) * [Documentation](https://docs.hatchet.run/self-hosting/docker-compose?utm_source=coolify.io) * [GitHub](https://github.com/hatchet-dev/hatchet?utm_source=coolify.io) # Healthchecks (/docs/services/healthchecks) Healthchecks [#healthchecks] What is Healthchecks? [#what-is-healthchecks] Healthchecks monitors cron jobs and scheduled tasks by waiting for HTTP requests or email messages. It sends an alert when an expected ping does not arrive on time. Create the first account [#create-the-first-account] After deployment, create an account through an emailed magic link or run the Healthchecks `manage.py` command in the application container to create a superuser. Magic-link authentication requires working email configuration. Read the [Healthchecks Docker documentation](https://healthchecks.io/docs/self_hosted_docker/) for the supported account-creation commands and email settings. Screenshot [#screenshot] Links [#links] * [Official website](https://healthchecks.io/) * [Documentation](https://healthchecks.io/docs/) * [GitHub repository](https://github.com/healthchecks/healthchecks) # Heimdall (/docs/services/heimdall) What is Heimdall? [#what-is-heimdall] As the name suggests Heimdall Application Dashboard is a dashboard for all your web applications. It doesn't need to be limited to applications though, you can add links to anything you like. Heimdall is an elegant solution to organise all your web applications. It’s dedicated to this purpose so you won’t lose your links in a sea of bookmarks. Why not use it as your browser start page? It even has the ability to include a search bar using either Google, Bing or DuckDuckGo. Screenshots [#screenshots] Links [#links] * [The official website](https://heimdall.site/) * [GitHub](https://github.com/linuxserver/Heimdall) # Hermes Agent (/docs/services/hermes-agent) Hermes Agent [#hermes-agent] What is Hermes Agent? [#what-is-hermes-agent] Hermes Agent is an open-source autonomous AI agent runtime built by [Nous Research](https://nousresearch.com?utm_source=coolify.io). It runs persistently as a gateway process - always available to receive messages, execute scheduled tasks, and reason over its accumulated memory and task history. Unlike stateless chat interfaces, Hermes Agent retains a persistent world model: memory is stored and searchable across sessions, tasks are tracked on a built-in kanban board, and cron jobs fire on schedule regardless of whether a browser is open. It connects to 20+ messaging platforms (Telegram, Discord, Slack, Teams, and more) through a unified gateway, integrates with 60+ built-in tools, and supports Model Context Protocol (MCP) for extending capabilities further. Hermes Agent works with any major LLM provider - OpenRouter, Anthropic, OpenAI, or Google. Nous Portal subscribers can use `hermes setup --portal` for one-shot authentication that also opts into the Tool Gateway. At least one provider API key is required. Coolify offers two deployment templates suited to different use cases. See [Deployment Variants](#deployment-variants) below to choose the right one. Deploy on Coolify [#deploy-on-coolify] Both templates use the same `nousresearch/hermes-agent` image and store all agent state in persistent volumes. The difference is how the web interface is delivered: as a separate companion container (WebUI), or built into the agent process itself (Dashboard). Neither template exposes the raw gateway port externally. Coolify's reverse proxy routes only the web interface port - 8787 for the WebUI variant, 9119 for the Dashboard variant. The gateway process itself is inaccessible from outside the Docker network. Hermes Agent (with WebUI) [#hermes-agent-with-webui] Deploys two containers: | Container | Image | Purpose | | -------------- | ------------------------------- | --------------------------------- | | `hermes-agent` | `nousresearch/hermes-agent` | Gateway process and agent runtime | | `hermes-webui` | `ghcr.io/nesquena/hermes-webui` | Web chat interface (port 8787) | Coolify auto-generates the following - no manual configuration needed: * `SERVICE_USER_HERMESWEBUI` - WebUI login username * `SERVICE_PASSWORD_HERMESWEBUI` - WebUI login password * `SERVICE_URL_HERMESWEBUI_8787` - Public URL for the chat interface Uses four named volumes: `hermes-home`, `hermes-skills`, `hermes-agent-src`, `hermes-workspace`. The WebUI shares the `hermes-home` and `hermes-workspace` volumes with the agent for direct access to memory and the workspace directory. Hermes Agent (Dashboard) [#hermes-agent-dashboard] Deploys a single container with the built-in dashboard activated: | Container | Image | Purpose | | -------------- | --------------------------- | ---------------------------------------------- | | `hermes-agent` | `nousresearch/hermes-agent` | Agent runtime + built-in dashboard (port 9119) | Coolify auto-generates the following - no manual configuration needed: * `SERVICE_USER_HERMESAGENT` - Dashboard login username * `SERVICE_PASSWORD_HERMESAGENT` - Dashboard login password * `SERVICE_BASE64_64_HERMESAGENT` - Session signing secret (64-character random string) * `SERVICE_URL_HERMESAGENT_9119` - Public URL for the dashboard Uses a single named volume (`hermes-home`) that covers all persistent state: agent config, API keys, auth tokens, memory, kanban board, profiles, cron jobs, logs, hooks, plans, skins, skills, workspace files, SSH keys, and pip-installed packages. Deployment Variants [#deployment-variants] | | Hermes Agent (with WebUI) | Hermes Agent (Dashboard) | | --------------------- | ----------------------------- | ------------------------ | | **Containers** | 2 (agent + webui) | 1 | | **Web interface** | hermes-webui (separate image) | Built-in dashboard | | **Port** | 8787 | 9119 | | **Volumes** | 4 | 1 | | **Min agent version** | Any | v0.16.0+ | **Choose Hermes Agent (with WebUI)** when you want a dedicated web chat interface. The `hermes-webui` container provides a chat-first experience and releases independently from the agent, so you can update the UI without touching the agent process. **Choose Hermes Agent (Dashboard)** when you want the simplest possible deployment, or when running the agent that manages your Coolify setup. All state is in one volume, there are no inter-container dependencies to manage, and the dashboard surfaces memory, the task board, cron jobs, and installed skills in one place. This is the recommended option for self-hosting Hermes as a Coolify automation agent. Environment Variables [#environment-variables] LLM Providers [#llm-providers] At least one provider key is required for the agent to function. The agent selects the active provider from your config at runtime. | Variable | Default | Description | | -------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `OPENROUTER_API_KEY` | *(empty)* | [OpenRouter](https://openrouter.ai?utm_source=coolify.io) - single key access to hundreds of models. Recommended if you want to switch models without redeploying. | | `ANTHROPIC_API_KEY` | *(empty)* | API key from [console.anthropic.com](https://console.anthropic.com?utm_source=coolify.io). | | `OPENAI_API_KEY` | *(empty)* | API key from [platform.openai.com](https://platform.openai.com?utm_source=coolify.io). | | `GOOGLE_API_KEY` | *(empty)* | API key for Google Gemini models. | Web Search (Optional) [#web-search-optional] | Variable | Default | Description | | ------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `FIRECRAWL_API_KEY` | *(empty)* | Enables web search and full-page extraction via the `web` tool. Free tier: 500 pages/month at [firecrawl.dev](https://firecrawl.dev?utm_source=coolify.io). Leave blank to disable. | | `FIRECRAWL_API_URL` | `https://api.firecrawl.dev` | Override to point at your self-hosted Firecrawl instance. Requires `HERMES_ALLOW_PRIVATE_URLS=true` if the instance is on a Docker-internal or Tailscale address. | Agent Behavior [#agent-behavior] | Variable | Default | Description | | ------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `HERMES_ENABLE_PROJECT_PLUGINS` | `true` | Loads plugins from the `plugins/` subdirectory inside the data volume. Set to `false` to disable auto-loading. | | `HERMES_ALLOW_PRIVATE_URLS` | `false` | Allows the agent to fetch Docker-internal URLs and Tailscale addresses (e.g., a self-hosted Firecrawl or a local Ollama instance). Set to `false` to restrict to public URLs only. | | `HERMES_REDACT_SECRETS` | `true` | Prevents API keys and secrets from appearing in logs and tool output. Recommended: leave enabled. | | `GATEWAY_ALLOW_ALL_USERS` | `true` | Allows any user to message the gateway. Safe for personal deployments where the gateway port is not mapped externally. If you connect messaging platforms (Telegram, Slack, Discord), set to `false` and configure per-platform allowed-user lists instead (e.g., `TELEGRAM_ALLOWED_USER_IDS`). | | `HERMES_UID` / `HERMES_GID` | `1000` | The UID/GID the agent drops to after chowning the volume on first start. Matches Coolify's default host UID so volume-mounted files have sensible ownership. | WebUI Variant - Additional Variables [#webui-variant---additional-variables] | Variable | Default | Description | | ------------------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `HERMES_OPTIONAL_SKILLS` | *(empty)* | Comma-separated list of official skills to auto-install on first run (e.g., `official/communication/one-three-one-rule`). Leave blank to skip. | | `SERVICE_USER_HERMESWEBUI` | *(auto-generated)* | WebUI login username. Find it in the **Environment Variables** tab after deploying. | | `SERVICE_PASSWORD_HERMESWEBUI` | *(auto-generated)* | WebUI login password. Find it in the **Environment Variables** tab after deploying. | Dashboard Variant - Additional Variables [#dashboard-variant---additional-variables] | Variable | Default | Description | | ------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `HERMES_DASHBOARD` | `1` | Activates the built-in dashboard. Do not change this value. | | `HERMES_DASHBOARD_HOST` | `0.0.0.0` | Dashboard bind address. Binding to `0.0.0.0` is correct - Coolify's reverse proxy handles TLS termination and the auth gate protects the endpoint. | | `HERMES_DASHBOARD_PORT` | `9119` | Dashboard listen port. | | `SERVICE_USER_HERMESAGENT` | *(auto-generated)* | Dashboard login username. Find it in the **Environment Variables** tab after deploying. | | `SERVICE_PASSWORD_HERMESAGENT` | *(auto-generated)* | Dashboard login password. Find it in the **Environment Variables** tab after deploying. | | `SERVICE_BASE64_64_HERMESAGENT` | *(auto-generated)* | Session signing secret. Managed by Coolify - do not set this manually. | Do not add `HERMES_DASHBOARD_INSECURE=1` to the environment. That flag disables all dashboard authentication regardless of the credentials above. It is a break-glass override and has no place in an internet-facing deployment. What to do after deploying [#what-to-do-after-deploying] Coolify deploys the containers, but the agent still needs a one-time configuration step before it can respond to messages. You run this from the container terminal in Coolify. For the WebUI variant, open the terminal for the **`hermes-agent`** container - not `hermes-webui`. For the Dashboard variant, open the terminal for the single `hermes-agent` container. Step 1 - Open the web interface [#step-1---open-the-web-interface] Click **Open** in Coolify to open the interface. For the WebUI variant this is the hermes-webui chat interface on port 8787; for the Dashboard variant it is the built-in dashboard on port 9119. Log in with the auto-generated credentials from the **Environment Variables** tab: * WebUI: `SERVICE_USER_HERMESWEBUI` and `SERVICE_PASSWORD_HERMESWEBUI` * Dashboard: `SERVICE_USER_HERMESAGENT` and `SERVICE_PASSWORD_HERMESAGENT` Step 2 - Run the setup wizard [#step-2---run-the-setup-wizard] Open a terminal into the `hermes-agent` container from Coolify's **Terminal** tab and run: ```bash hermes setup ``` The wizard walks you through selecting an LLM provider and model, configuring optional tools, and setting up messaging platform integrations. This is the recommended starting point for every fresh deploy. **OpenRouter model format:** If you use OpenRouter, models must be specified as `provider/model-name` (e.g., `anthropic/claude-sonnet-4-5`, `moonshotai/kimi-k2.6`). Using a bare model name causes HTTP 404 errors from OpenRouter. If you are a Nous Portal subscriber, you can skip the individual provider prompts entirely: ```bash hermes setup --portal ``` This authenticates via OAuth, sets Nous as the inference provider, and opts into the Tool Gateway in a single step. After any setup command, **restart the `hermes-agent` container** - the gateway reads `config.yaml` only at startup. Step 3 - Run the doctor check [#step-3---run-the-doctor-check] ```bash hermes doctor --fix ``` This auto-repairs common configuration issues. Two warnings are expected in a Docker environment and can be ignored: * *"Add \~/.local/bin to your PATH"* - the symlink is created but the PATH fix does not persist across container restarts. The `hermes` command still works. * *"Run hermes setup to configure missing API keys"* - fires if any optional tool keys (EXA, Tavily) are unset. If Firecrawl is configured, web search is fully functional. Step 4 - Enable Firecrawl web search (optional) [#step-4---enable-firecrawl-web-search-optional] Firecrawl gives Hermes the ability to search the web and extract full page content from URLs, including JavaScript-rendered pages. Without it, the `web` tool is unavailable. 1. Sign up at [firecrawl.dev](https://firecrawl.dev?utm_source=coolify.io) - the free tier includes 500 pages/month. 2. Add `FIRECRAWL_API_KEY` to the **Environment Variables** tab in Coolify and redeploy, or configure it interactively from the terminal: ```bash hermes setup tools ``` To use a self-hosted Firecrawl instance on your Docker network, set `FIRECRAWL_API_URL` to `http://:3002` and ensure `HERMES_ALLOW_PRIVATE_URLS=true`. Step 5 - Connect a messaging platform (optional) [#step-5---connect-a-messaging-platform-optional] Hermes connects to Telegram, Discord, Slack, Microsoft Teams, and more. To configure any messaging integration, run the gateway setup wizard from the container terminal: ```bash hermes gateway setup ``` The wizard prompts you for the platform-specific credentials and configures the integration. For Telegram specifically, you will need: 1. A bot token from **@BotFather** on Telegram - send `/newbot`, follow the prompts, copy the token. 2. Your Telegram user ID from **@userinfobot** - send any message to it and it returns a plain number like `987654321`. After running `hermes gateway setup`, add your user ID restriction to Coolify's **Environment Variables** tab: | Variable | Value | | --------------------------- | ------------------------------------------------------------------------ | | `TELEGRAM_ALLOWED_USER_IDS` | Your user ID (e.g., `987654321`) - restricts the bot to authorized users | Then redeploy. Your Telegram bot token is stored in the persistent volume by the setup wizard - it does not need to go in Coolify's environment variables. Telegram webhooks require a publicly accessible HTTPS URL. If your Coolify server is on a private network (e.g., Tailscale-only), use Tailscale Funnel (`tailscale funnel 8787` for WebUI, `tailscale funnel 9119` for Dashboard) or a Cloudflare Tunnel to expose it. Plugins [#plugins] Hermes ships with opt-in bundled plugins. Nothing loads until you explicitly enable it. Manage plugins from the container terminal: ```bash hermes plugins # interactive UI - toggle with SPACE, confirm with ENTER hermes plugins list # show all plugins and their current state hermes plugins enable hermes plugins disable ``` Notable bundled plugins: | Plugin | What it does | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `disk-cleanup` | Auto-tracks ephemeral files (test scripts, temp outputs) and removes them at session end. Adds `/disk-cleanup` slash command for manual control. Recommended for all deployments. | | `security-guidance` | Pattern-matches dangerous code patterns during file writes and surfaces a guidance note. | | `hermes-achievements` | Steam-style collectible badges generated from session history. | | `kanban/dashboard` | Kanban board UI tab for multi-agent task management (Dashboard variant). | | `observability/langfuse` | Traces turns and LLM calls to a Langfuse observability instance. | Enable disk-cleanup: ```bash hermes plugins enable disk-cleanup ``` Plugin settings are written to the persistent volume and survive container restarts. Persistent Memory (optional) [#persistent-memory-optional] Hermes supports external memory providers that build a cross-session user model and inject it at the start of each conversation. Several providers are available: Honcho, mem0, Hindsight, and others. Configure any provider from the terminal: ```bash hermes memory setup # interactive provider selection and configuration hermes memory status # show active provider and connection status ``` See the [memory providers documentation](https://hermes-agent.nousresearch.com/docs?utm_source=coolify.io) for provider-specific setup guides. Troubleshooting [#troubleshooting] **The agent starts but never responds to messages** The agent requires `hermes setup` to be run at least once to configure an LLM provider and model. Open a terminal in the `hermes-agent` container and run `hermes setup`. Restart the container after completing the wizard. **HTTP 404 errors from OpenRouter** The model name is in the wrong format. OpenRouter requires `provider/model-name` (e.g., `anthropic/claude-sonnet-4-5`, `moonshotai/kimi-k2.6`). Run `hermes model` in the container terminal to update the model selection, then restart. **`config.yaml` changes not persisting / "Permission denied" errors** Coolify's container terminal opens a root shell. If you run `hermes` commands without the agent being accessible as the correct user, config files may be written as root and become unreadable by the agent process. Run this to fix ownership, then restart: ```bash chown -R 1000:1000 /home/hermes/.hermes # WebUI variant # or chown -R 1000:1000 /opt/data # Dashboard variant ``` **API keys returning 401 after setting them in Coolify** A stale `.env` file on the volume may be overriding Coolify's environment variables. Check for and remove stale values: ```bash cat /home/hermes/.hermes/.env # WebUI variant # or cat /opt/data/.env # Dashboard variant ``` Remove any API key lines that conflict with what Coolify is injecting. **The `hermes-webui` container exits immediately (WebUI variant)** The webui depends on `hermes-agent` passing its healthcheck (verifying the agent home directory exists). On first boot this takes 10-30 seconds. Docker restarts it automatically - this is normal. If it keeps failing, check the `hermes-agent` logs for startup errors. **Dashboard login fails / 401 errors (Dashboard variant)** Retrieve your credentials from the **Environment Variables** tab - `SERVICE_USER_HERMESAGENT` and `SERVICE_PASSWORD_HERMESAGENT`. If `SERVICE_BASE64_64_HERMESAGENT` is missing or was deleted, let Coolify regenerate it and redeploy. **CSP violation warnings in logs when using Cloudflare Tunnel (WebUI variant)** Cloudflare Tunnel injects an analytics beacon script that the hermes-webui Content Security Policy blocks. This is harmless - `disposition: report` means the interface is still fully functional - but the logs fill up. To stop it, disable Cloudflare Web Analytics injection for the Hermes WebUI hostname in your Cloudflare Zero Trust dashboard under **Networks - Tunnels - \[your tunnel] - Additional application settings**. **Compression threshold warning in logs** Open `/home/hermes/.hermes/config.yaml` (or `/opt/data/config.yaml` for the Dashboard variant) in the container terminal and add: ```yaml compression: threshold: 0.20 ``` Restart the container. **"Skills Hub not initialized" warning** Run once to initialize: ```bash hermes skills list ``` **The "Open" button in Coolify leads to an error page** The **Open** button resolves to the first exposed URL. For the WebUI variant that is port 8787; for the Dashboard variant it is port 9119. Wait for the healthcheck on that port's container to pass, then refresh. **Firecrawl requests fail with connection errors** If pointing `FIRECRAWL_API_URL` at a self-hosted Firecrawl on a Docker-internal hostname or Tailscale address, ensure `HERMES_ALLOW_PRIVATE_URLS=true` is set. Key Files (inside the container) [#key-files-inside-the-container] | Path (WebUI variant) | Path (Dashboard variant) | Purpose | | ---------------------------------- | ------------------------ | --------------------------------------------------------- | | `/home/hermes/.hermes/config.yaml` | `/opt/data/config.yaml` | Main config - model, provider, settings | | `/home/hermes/.hermes/.env` | `/opt/data/.env` | Legacy env overrides - can shadow Coolify env vars | | `/home/hermes/.hermes/wiki/` | `/opt/data/wiki/` | Agent knowledge base (markdown files) | | `/home/hermes/.hermes/honcho.json` | `/opt/data/honcho.json` | Memory provider config (created by `hermes memory setup`) | Config changes require a container restart to take effect. Links [#links] * [GitHub - Hermes Agent](https://github.com/NousResearch/hermes-agent?utm_source=coolify.io) * [GitHub - Hermes WebUI](https://github.com/nesquena/hermes-webui?utm_source=coolify.io) * [Documentation](https://hermes-agent.nousresearch.com/docs?utm_source=coolify.io) * [Nous Research](https://nousresearch.com?utm_source=coolify.io) * [Firecrawl](https://firecrawl.dev?utm_source=coolify.io) * [OpenRouter](https://openrouter.ai?utm_source=coolify.io) # Heyform (/docs/services/heyform) Heyform [#heyform] What is Heyform [#what-is-heyform] Allows anyone to create engaging conversational forms for surveys, questionnaires, quizzes, and polls. No coding skills required. Links [#links] * [Official Documentation](https://docs.heyform.net/open-source/self-hosting?utm_source=coolify.io) # Hoarder (/docs/services/hoarder) This service is currently not available in Coolify's service catalog. Hoarder [#hoarder] What is Hoarder [#what-is-hoarder] an open source "Bookmark Everything" app that uses AI for automatically tagging the content you throw at it. Links [#links] * [Official Documentation](https://docs.hoarder.app/?utm_source=coolify.io) # Homarr (/docs/services/homarr) Homarr [#homarr] What is Homarr [#what-is-homarr] Homarr is a self-hosted homepage for your services. Links [#links] * [Official Documentation](https://homarr.dev?utm_source=coolify.io) # Home Assistant (/docs/services/home-assistant) Home Assistant [#home-assistant] What is Home Assistant? [#what-is-home-assistant] Home Assistant is an open‑source home automation platform focused on local control and privacy. It connects lights, sensors, cameras, media players, and more—so you can automate routines, build dashboards, and control everything from a single place. Features [#features] * **1,000+ Integrations**: Support for thousands of smart home devices and services * **Local Control**: Runs privately in your environment without cloud dependencies * **Powerful Automations**: Create complex routines with YAML configuration or visual UI * **Multi-Platform Access**: Mobile apps, web dashboards, voice control, and remote access * **Privacy-Focused**: Your data stays on your server with no tracking or telemetry * **Extensible**: Add-ons, custom integrations, and active community support Links [#links] * [Official Website](https://www.home-assistant.io/?utm_source=coolify.io) * [Documentation](https://www.home-assistant.io/docs/?utm_source=coolify.io) * [GitHub](https://github.com/home-assistant/core?utm_source=coolify.io) * [Community Forums](https://community.home-assistant.io/?utm_source=coolify.io) # Homebox (/docs/services/homebox) Homebox [#homebox] What is Homebox? [#what-is-homebox] Homebox is an inventory and organization system built specifically for home users. It allows you to catalog and track your belongings, create locations and categories, manage warranties and receipts, and keep detailed records of your household items. Homebox is perfect for insurance purposes, organizing collections, and general home inventory management with features like photo attachments, search functionality, and reporting capabilities. Configuration [#configuration] In order to create your first account you will have to head to the environment variables for Homebox and set `HBOX_OPTIONS_ALLOW_REGISTRATION` to true and restart your docker for the change to take effect. You are now able to create your first account, after which you can set `HBOX_OPTIONS_ALLOW_REGISTRATION` to false again to prevent new registrations, or keep them opened for other users to join your homebox. Links [#links] * [GitHub](https://github.com/hay-kot/homebox?utm_source=coolify.io) # Homepage (/docs/services/homepage) What is Homepage? [#what-is-homepage] A modern, fully static, fast, secure fully proxied, highly customizable application dashboard Screenshots [#screenshots] Links [#links] * [The official website](https://gethomepage.dev/) # Hoppscotch (/docs/services/hoppscotch) Hoppscotch [#hoppscotch] What is Hoppscotch [#what-is-hoppscotch] The Open Source API Development Platform Links [#links] * [Official Documentation](https://docs.hoppscotch.io?utm_source=coolify.io) # How Services Work (/docs/services/how-services-work) How Services work [#how-services-work] Coolify combines a Service definition in the control plane with a Docker Compose project on one connected server. The Service definition stores the raw Compose YAML, generated environment values, selected destination, component settings, and operational configuration. Docker stores the images, networks, containers, and persistent volumes used by the running stack. From creation to a running Service [#from-creation-to-a-running-service] 1. You select a one-click template or **Docker Compose Empty** in a project and environment. 2. Coolify stores the selected template or pasted Compose definition on the new Service resource. 3. Coolify parses each Compose service, identifies common database images, creates component records, and generates referenced values such as domains and credentials. 4. You review the stack, required variables, domains, and storage under **Configuration**. 5. When you select **Deploy**, Coolify saves a generated `.env` file and deployable `docker-compose.yml` in the Service configuration directory on the selected server. 6. Coolify pulls the configured images, creates the resource network when required, and runs `docker compose up` with the saved project name and configuration. 7. Docker starts the component containers and runs health checks defined by the images or Compose definition. 8. The Coolify proxy routes configured domains to the appropriate application components. Raw and deployable Compose [#raw-and-deployable-compose] The **Source Compose** is the definition stored on the Service. It is the copy you edit. The **Deployable Compose** is the generated definition Coolify sends to Docker Compose. It can include normalized volume names, container names, labels, networks, environment references, and proxy configuration. Do not copy generated names back into the source definition unless the stack genuinely requires them. Review both views from **Configuration > General > Edit Compose File**. Components belong to one stack [#components-belong-to-one-stack] Coolify shows each parsed Compose service as a component card under **Configuration > General**: * application components can have domains and proxy behavior * database components can have public proxy settings and supported backup controls * every component can show its image and container status The Service status aggregates its non-excluded components. An optional or one-time component can be excluded from the aggregate status from its **Advanced** settings. A component can be restarted separately, but **Deploy**, **Restart**, **Stop**, and **Pull Latest Images & Restart** act on the Service stack. Networking [#networking] Coolify creates a resource-specific Docker network for the Service. Components in the same Compose definition communicate by Compose service name and internal port. Coolify creates a shared Docker network named `coolify` on each connected server. Enable **Connect To Predefined Network** when the stack must privately communicate with resources on its predefined network, which is `coolify` for the default destination. Other Docker networks remain isolated, and the `coolify` network does not extend across servers. Use a domain for public HTTP traffic. Publish a host port only when an external client requires direct TCP or UDP access. Read [Service networking](/services/configuration/networking) for same-stack connections, the `coolify` network, other Docker networks, cross-server paths, domains, and published ports. Configuration changes and redeployment [#configuration-changes-and-redeployment] Saving a value updates the Service definition. Changes that affect container configuration do not necessarily change a running container immediately. Deploy or restart the Service after changing: * the Compose definition or an image reference * environment variables * domains, ports, proxy behavior, or networks * persistent storage * component logging or status settings **Restart** recreates the stack without first pulling newer images. **Pull Latest Images & Restart** pulls the image tags stored in the current Compose definition, then recreates the stack. Coolify can refresh the template catalog used to create new resources. An existing one-click Service keeps its saved Compose definition. Review the upstream release and edit the Service definition when an upgrade requires new Compose settings, migrations, or image tags. Persistent data [#persistent-data] Containers are replaceable. Store required data in volumes, directories, file mounts, or external services declared by the Compose definition. Parsed mounts appear under **Configuration > Persistent Storages** for the component that uses them. For a Service, change Compose-owned mount definitions in **Edit Compose File**, not in the read-only storage view. Control plane and Service server [#control-plane-and-service-server] The Coolify instance stores configuration and coordinates operations. The connected server stores the Service configuration directory and runs its Docker resources. Already-running containers can continue operating while the Coolify control plane is unavailable, as long as Docker, the server, its networks, the proxy, and the containers remain healthy. New Coolify operations require the control plane to be available. Continue learning [#continue-learning] # Imgcompress (/docs/services/imgcompress) Imgcompress [#imgcompress] What is Imgcompress? [#what-is-imgcompress] Imgcompress is a self-hosted image processing toolbox that handles compression, format conversion, and AI background removal in a single web interface. It supports over **70 input formats** (including PSD, HEIC, and RAW) and can output common formats or generate PDFs, all without sending files to external services. Key capabilities: * **Format conversion**: PSD, HEIC, RAW, and 70+ other formats converted in one place * **Image compression**: Reduce file sizes for photos and screenshots without quality loss * **PDF export**: Convert images to PDF directly from the browser * **AI background removal**: Remove backgrounds locally, keeping files private Links [#links] * [The official website](https://imgcompress.karimzouine.com?utm_source=coolify.io) * [GitHub](https://github.com/karimz1/imgcompress?utm_source=coolify.io) # Immich (/docs/services/immich) Immich [#immich] What is Immich [#what-is-immich] Self-hosted photo and video management solution. Links [#links] * [Official Documentation](https://immich.app/docs/overview/introduction?utm_source=coolify.io) # Services (/docs/services) Services [#services] Coolify deploys a Service as a Docker Compose stack on one connected server and network destination. Start from a ready-made one-click template, or select **Docker Compose Empty** and provide your own Compose definition. Each Service can contain several application and database containers. Coolify parses the Compose definition, creates controls for the detected components, generates required values, configures domains and storage, and runs the stack with Docker Compose. Use an [Application](/applications) when the deployment should follow source code in a Git repository or use one existing Docker image. Use a [standalone Database](/databases) when you need Coolify's engine-specific database defaults. Use a Service for a multi-container stack or a Compose definition stored directly in Coolify. Find the right section [#find-the-right-section] | If you want to | Start here | | :------------------------------------------------------------------------------- | :------------------------------------------------------- | | Learn what a Service contains and when to use one | [What is a service](/services/what-is-a-service) | | Follow the path from a template or Compose definition to running containers | [How services work](/services/how-services-work) | | Browse ready-made templates | [One-click service catalog](/services/overview) | | Configure the stack, its components, domains, variables, and storage | [Configuration](/services/configuration/overview) | | Edit and understand the stored Compose definition | [Docker Compose](/services/configuration/docker-compose) | | Inspect logs, update images, schedule commands, clone, move, or delete a Service | [Operations](/services/operations/overview) | Deploy a Service [#deploy-a-service] 1. Open a project and environment, then select **Create New Resource**. 2. Select a one-click Service, or select **Docker Compose Empty**. 3. Choose the server and network destination where the stack should run. 4. For **Docker Compose Empty**, paste the Compose definition and save it. 5. Review **Configuration > General**, **Environment Variables**, and **Persistent Storages**. 6. Fill every required environment variable, then select **Deploy**. 7. Follow the deployment output and verify every required component is running and healthy. For a complete first deployment, follow [Deploy your first service](/deploy-your-first-service). Understand one-click Services [#understand-one-click-services] A one-click Service starts from a Compose template maintained in Coolify's service library. Coolify copies the template into the new resource and generates its initial values. The deployed Service keeps its own Compose definition. Later library changes do not rewrite that definition. **Pull Latest Images & Restart** pulls images for the tags currently saved in the Service; it does not replace the stored template with a newer version. Open the [searchable catalog](/services/overview) to find a Service, then read its individual guide for service-specific setup, credentials, or limitations. Service resource navigation [#service-resource-navigation] | Area | Use it to | Guide | | :---------------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------ | | **Configuration** | Change the stack, components, variables, storage, automation, and organization. | [Configuration overview](/services/configuration/overview) | | **Logs** | Read stdout and stderr from the Service's containers. | [Operate services](/services/operations/overview) | | **Terminal** | Open a shell in a selected running container when terminal access is allowed. | [Operate services](/services/operations/overview) | | **Scheduled Tasks** | Run a recurring command inside one component container. | [Scheduled tasks](/services/operations/scheduled-tasks) | | **Resource Operations** | Clone the Service to another destination or move it between projects and environments. | [Clone or move a Service](/services/operations/resource-operations) | | **Danger Zone** | Permanently delete the Service and choose which related Docker resources to remove. | [Delete a Service](/services/operations/danger-zone) | Continue with Services [#continue-with-services] # Infisical (/docs/services/infisical) What is Infisical? [#what-is-infisical] Infisical is the open source security infrastructure platform that engineers use for secrets management, internal PKI, key management, and SSH workflow orchestration. * Secrets Management: Infisical's secrets management module lets developers centralize and securely manage application configuration, API keys, database credentials, and other sensitive data. * Public Key Infrastructure (PKI): Infisical PKI lets you operate an internal certificate authority and manage the full X.509 certificate lifecycle for services, applications, and devices. * Key Management System (KMS): Infisical KMS helps you generate and securely manage encryption keys to encrypt/decrypt data. * SSH Certificate Management: Infisical SSH lets you provision engineers short-lived, secure SSH access to infrastructure by replacing traditional static SSH keys with ephemeral certificate-based authentication. Screenshots [#screenshots] Links [#links] * [The official website](https://infisical.com/?utm_source=coolify.io) * [GitHub](https://github.com/Infisical/infisical?utm_source=coolify.io) # InfluxDB (/docs/services/influxdb) InfluxDB [#influxdb] What is InfluxDB? [#what-is-influxdb] InfluxDB is an open-source time series database built for storing and analyzing timestamped data. It is commonly used for monitoring, observability, IoT applications, and real-time analytics. Features [#features] * Optimized for time series data * High-performance data ingestion * InfluxQL and Flux query support * REST API * Integrates with Grafana, Telegraf, and Prometheus Links [#links] * [Official website](https://www.influxdata.com/?utm_source=coolify.io) * [GitHub](https://github.com/influxdata/influxdb?utm_source=coolify.io) * [Documentation](https://docs.influxdata.com/influxdb/?utm_source=coolify.io) # Inngest (/docs/services/inngest) Inngest [#inngest] What is Inngest? [#what-is-inngest] Inngest is an open-source durable workflow engine for background jobs, queues, scheduled work, and event-driven functions. Applications send events over HTTP, and Inngest manages execution, retries, and individual workflow steps. Links [#links] * [Official website](https://www.inngest.com/) * [Documentation](https://www.inngest.com/docs/) * [GitHub repository](https://github.com/inngest/inngest) # Invoice Ninja (/docs/services/invoice-ninja) Invoice Ninja [#invoice-ninja] A self-hosted invoicing platform for small businesses. Screenshots [#screenshots] Links [#links] * [The official website](https://www.invoiceninja.com/) # It Tools (/docs/services/it-tools) It Tools [#it-tools] What is It Tools [#what-is-it-tools] IT Tools is a self-hosted solution for managing various IT tasks. Links [#links] * [Official Documentation](https://github.com/corentinth/it-tools?utm_source=coolify.io) # Jellyfin (/docs/services/jellyfin) What is Jellyfin? [#what-is-jellyfin] Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest! Links [#links] * [The official website](https://jellyfin.org/) * [GitHub](https://github.com/jellyfin/jellyfin) # Jenkins (/docs/services/jenkins) What is Jenkins? [#what-is-jenkins] Jenkins is a popular open-source automation server used for continuous integration and continuous delivery (CI/CD). It allows developers to build, test, and deploy software projects reliably. Links [#links] * [The official website](https://www.jenkins.io/) * [GitHub](https://github.com/jenkinsci/jenkins) # Joomla (/docs/services/joomla) Joomla [#joomla] What is Joomla [#what-is-joomla] Joomla! is the mobile-ready and user-friendly way to build your website. Choose from thousands of features and designs. Joomla! is free and open source. Links [#links] * [Official Documentation](https://joomla.org?utm_source=coolify.io) # Joplin (/docs/services/joplin) Joplin [#joplin] What is Joplin [#what-is-joplin] Self-hosted sync server for Joplin Links [#links] * [Official Documentation](https://github.com/laurent22/joplin/blob/dev/packages/server/README.md?utm_source=coolify.io) # Jupyter Notebook Python (/docs/services/jupyter-notebook-python) Jupyter Notebook Python [#jupyter-notebook-python] What is Jupyter Notebook Python [#what-is-jupyter-notebook-python] Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations, and narrative text. Links [#links] * [Official Documentation](https://jupyter.org/?utm_source=coolify.io) # KaraKeep (/docs/services/karakeep) KaraKeep [#karakeep] What is KaraKeep? [#what-is-karakeep] KaraKeep is a self-hostable bookmark-everything app with AI-based automatic tagging. It serves as a comprehensive read-it-later service and alternative to Pocket or Omnivore. KaraKeep can automatically categorize and tag your saved content using AI, making it easy to organize and rediscover articles, videos, and other web content you want to save for later. Links [#links] * [The official website](https://docs.karakeep.app?utm_source=coolify.io) * [GitHub](https://github.com/karakeep-app/karakeep?utm_source=coolify.io) # Keycloak (/docs/services/keycloak) Keycloak [#keycloak] What is Keycloak [#what-is-keycloak] Keycloak is an open-source Identity and Access Management tool. Deployment Variants [#deployment-variants] Keycloak is available in two deployment configurations in Coolify: Keycloak (Default) [#keycloak-default] * **Database:** Embedded H2 (development) * **Use case:** Development, testing, or evaluation purposes * **Components:** Single Keycloak container with built-in H2 database Keycloak with PostgreSQL [#keycloak-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring reliability, performance, and data persistence * **Components:** * Keycloak container * PostgreSQL container * Automatic database configuration and health checks Links [#links] * [Official Documentation](https://www.keycloak.org?utm_source=coolify.io) # Kimai (/docs/services/kimai) What is Kimai? [#what-is-kimai] Kimai makes time-tracking easy. An open-source solution for teams of all sizes. Screenshots [#screenshots] Links [#links] * [The official website](https://www.kimai.org/?utm_source=coolify.io) * [GitHub](https://github.com/kimai/kimai) # Kuzzle (/docs/services/kuzzle) What is Kuzzle? [#what-is-kuzzle] Kuzzle is a generic backend offering the basic building blocks common to every application. Rather than developing the same standard features over and over again each time you create a new application, Kuzzle proposes them off the shelf, allowing you to focus on building high-level, high-value business functionalities. Features [#features] Kuzzle enables you to build modern web applications and complex IoT networks in no time. * API First: use a standardised multi-protocol API. * Persisted Data: store your data and perform advanced searches on it. * Realtime Notifications: use the pub/sub system or subscribe to database notifications. * User Management: login, logout and security rules are no more a burden. * Extensible: develop advanced business feature directly with the integrated framework. * Client SDKs: use our SDKs to accelerate the frontend development. Links [#links] * [The official website](https://kuzzle.io/) * [GitHub](https://github.com/kuzzleio/kuzzle) # Label Studio (/docs/services/labelstudio) What is Label Studio? [#what-is-label-studio] Label Studio is an open-source data labeling platform that streamlines the process of annotating and labeling data for machine learning and AI applications. Screenshots [#screenshots]

Links [#links] * [The official website](https://labelstud.io/) # Langflow (/docs/services/langflow) Langflow [#langflow] What is Langflow? [#what-is-langflow] Langflow is an open-source Python-based framework for building AI applications. It combines a visual authoring experience with full programmatic access, enabling teams to prototype, test, and deploy AI-powered agents and workflows. It accelerates development by providing a **drag-and-drop interface** while maintaining the flexibility of **custom Python components** for advanced use cases. Credentials [#credentials] After deploying Langflow on Coolify you can login to the dashboard with the autogenerated credentials stored in the following environment variables: | Variable | Description | | ----------------------------- | ------------------------------ | | `LANGFLOW_SUPERUSER` | Username for the admin account | | `LANGFLOW_SUPERUSER_PASSWORD` | Password for the admin account | Links [#links] * [Langflow Website](https://www.langflow.org/?utm_source=coolify.io) * [Documentation](https://docs.langflow.org/?utm_source=coolify.io) * [GitHub Repository](https://github.com/langflow-ai/langflow) # Langfuse (/docs/services/langfuse) What is Langfuse? [#what-is-langfuse] [Langfuse](https://langfuse.com/) is an **[open-source](https://github.com/langfuse/langfuse) LLM engineering platform** that empowers teams to collaboratively **debug**, **analyze**, and **iterate** on their LLM applications. It accelerates the development workflow by providing tools for **observability**, **tracing**, **prompt management**, **evaluation**, and **analytics**. Key Features [#key-features] Observability and Tracing [#observability-and-tracing] * **Insights**: Gain a granular understanding of your LLM's behavior with detailed tracing capabilities. * **Integrations**: Seamlessly integrate with popular frameworks like [LangChain](https://langfuse.com/docs/integrations/langchain), [Llama Index](https://langfuse.com/docs/integrations/llama-index), and [OpenAI](https://langfuse.com/docs/integrations/openai). Prompt Management [#prompt-management] * **Linked Tracing**: Connect prompt versions with tracing data for a holistic view of interactions. * **Zero Latency**: Experience prompt management without added latency in your applications. * **Efficient Management**: Organize and version your prompts to optimize model performance. Evaluation and Analytics [#evaluation-and-analytics] * **Model-Based Evaluations**: Utilize built-in tools or integrate external pipelines like [UpTrain](https://langfuse.com/guides/cookbook/evaluation_with_uptrain) and [Ragas](https://langfuse.com/guides/cookbook/evaluation_of_rag_with_ragas). * **Custom Metrics**: Define and track custom scores and annotations to measure performance. * **Analytics Dashboard**: Access visualizations and reports to monitor usage, costs, and model effectiveness. Get Started [#get-started] * Visit the [Langfuse docs](https://langfuse.com/docs) to get started. * # Leantime (/docs/services/leantime) What is Leantime? [#what-is-leantime] Leantime is a goals focused project management system for non-project managers. Building with ADHD, Autism, and dyslexia in mind. Screenshots [#screenshots] Links [#links] * [The official website](https://leantime.io?utm_source=coolify.io) * [GitHub](https://github.com/leantime/leantime?utm_source=coolify.io) # LibreChat (/docs/services/librechat) LibreChat [#librechat] What is LibreChat? [#what-is-librechat] LibreChat is a self-hosted, powerful, and privacy-focused chat UI for multiple AI models including OpenAI GPT, Anthropic Claude, Azure OpenAI, and many others. It provides a unified interface to interact with various AI providers while keeping your conversations private and under your control. LibreChat supports conversation threading, message editing, plugin integration, and customizable presets. Links [#links] * [The official website](https://librechat.ai?utm_source=coolify.io) * [GitHub](https://github.com/danny-avila/LibreChat?utm_source=coolify.io) # Libreoffice (/docs/services/libreoffice) Libreoffice [#libreoffice] What is Libreoffice [#what-is-libreoffice] LibreOffice is a free and powerful office suite. Links [#links] * [Official Documentation](https://docs.linuxserver.io/images/docker-libreoffice/?utm_source=coolify.io) # Librespeed (/docs/services/librespeed) Librespeed [#librespeed] What is Librespeed [#what-is-librespeed] Self-hosted lightweight speed test implemented in Javascript, using XMLHttpRequest and Web Workers. Links [#links] * [GitHub](https://github.com/librespeed/speedtest) # Libretranslate (/docs/services/libretranslate) Libretranslate [#libretranslate] What is Libretranslate [#what-is-libretranslate] Free and open-source machine translation API, entirely self-hosted. Links [#links] * [Official Documentation](https://libretranslate.com/docs/?utm_source=coolify.io) # Lidarr (/docs/services/lidarr) What is Lidarr? [#what-is-lidarr] Lidarr is a music collection manager that helps you monitor artists, find releases, and organize your library. It can search for releases and send them to configured Usenet or BitTorrent download clients. Screenshots [#screenshots] Links [#links] * [The official website](https://lidarr.audio/) * [GitHub](https://github.com/Lidarr/Lidarr) # LimeSurvey (/docs/services/limesurvey) What is LimeSurvey? [#what-is-limesurvey] A powerful, open-source survey platform. A free alternative to SurveyMonkey, Typeform, Qualtrics, and Google Forms, making it simple to create online surveys and forms with unmatched flexibility. Links [#links] * [The official website](https://www.limesurvey.org/?utm_source=coolify.io) * [GitHub](https://github.com/LimeSurvey/LimeSurvey?utm_source=coolify.io) # Linkding (/docs/services/linkding) Linkding [#linkding] What is Linkding? [#what-is-linkding] Linkding is a minimalist, self-hosted bookmark manager that focuses on simplicity and performance. It provides a clean interface for saving, organizing, and searching your bookmarks. Different Versions of Linkding [#different-versions-of-linkding] Linkding is available in two versions: | Version | Description | | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `latest` | Provides the basic functionality of linkding | | `plus` | Includes feature for archiving websites as HTML snapshots. Note: This version has a significantly larger image size as it includes a Chromium installation, requires more runtime memory to run Chromium, and requires more disk space for storing HTML snapshots | Links [#links] * [Official website](https://linkding.link/?utm_source=coolify.io) * [Documentation](https://linkding.link/installation/) * [GitHub](https://github.com/sissbruecker/linkding?utm_source=coolify.io) # Listmonk (/docs/services/listmonk) What is Listmonk? [#what-is-listmonk] Self-hosted newsletter and mailing list manager. Screenshots [#screenshots] Links [#links] * [The official website](https://listmonk.app/) * [GitHub](https://github.com/knadh/listmonk) # Litellm (/docs/services/litellm) What is Litellm? [#what-is-litellm] LiteLLM is an open-source LLM Gateway to manage authentication, loadbalancing, and spend tracking across 100+ LLMs. All in the OpenAI format. Screenshots [#screenshots]


Links [#links] * [The official website](https://docs.litellm.ai?utm_source=coolify.io) # Litequeen (/docs/services/litequeen) This service has been removed from Coolify’s one-click service catalog. More info on [https://github.com/coollabsio/coolify/pull/10006](https://github.com/coollabsio/coolify/pull/10006) Litequeen [#litequeen] What is Litequeen [#what-is-litequeen] Lite Queen is an open-source SQLite database management software that runs on your server. # LobeChat (/docs/services/lobe-chat) LobeChat [#lobechat] What is LobeChat? [#what-is-lobechat] LobeChat is an open-source, modern AI chat framework built for everyone. It supports multi AI providers, knowledge base management, and plugin system to provide a comprehensive AI chat experience. Features [#features] * **Multi-Provider Support**: Compatible with OpenAI, Claude, Gemini, and many other AI providers * **Knowledge Base**: Built-in knowledge base management for enhanced AI responses * **Plugin System**: Extensible plugin architecture for custom functionality * **Modern UI**: Beautiful and responsive user interface * **Self-Hosted**: Full control over your data and privacy * **Multi-Modal**: Support for text, image, and file inputs Links [#links] * [Official Website](https://lobehub.com/?utm_source=coolify.io) # Logto (/docs/services/logto) What is Logto? [#what-is-logto] Logto is an Auth0 alternative designed for modern apps and SaaS products. It offers a seamless developer experience and is well-suited for individuals and growing companies. 🧑‍💻 **Comprehensive frontend-to-backend identity solution** * Enables OIDC-based authentication with Logto SDKs. * Supports passwordless sign-in, along with various options like email, phone number, username, Google, Facebook, and other social sign-in methods. * Offers beautiful UI components with customizable CSS to suit your business needs. 📦 **Out-of-the-box infrastructure** * Includes a ready-to-use Management API, serving as your authentication provider, thus eliminating the need for extra implementation. * Provides SDKs that seamlessly integrate your apps with Logto across multiple platforms and languages, tailored to your development environment. * Offers flexible connectors that can be scaled with community contributions and customized with SAML, OAuth, and OIDC protocols. 💻 **Enterprise-ready solutions** * Implements role-based access control (RBAC) for scalable role authorization, catering to a wide range of use cases. * Facilitates user management and provides audit logs for understanding identity-related user information and maintaining security. * Enables single sign-on (SSO) and multi-factor authentication (MFA) without extra coding. * Leverages Logto Organizations to build multi-tenancy apps with ease. In a more approachable way, we refer to this solution as "[Customer Identity Access Management (CIAM)](https://en.wikipedia.org/wiki/Customer_identity_access_management)" or simply, the "Customer Identity Solution." Links [#links] * [The official website](https://logto.io) * [GitHub](https://github.com/logto-io/logto) # Lowcoder (/docs/services/lowcoder) Lowcoder [#lowcoder] What is Lowcoder [#what-is-lowcoder] Lowcoder (forked from OpenBlocks) is a self-hosted, open-source, low-code platform for building internal tools. Links [#links] * [Official Documentation](https://docs.lowcoder.cloud/?utm_source=coolify.io) # Mage AI (/docs/services/mage-ai) What is Mage AI? [#what-is-mage-ai] Mage AI (Mage OSS) is a self-hosted development environment designed to help teams create production-grade data pipelines with confidence. Ideal for automating ETL tasks, architecting data flow, or orchestrating transformations — all in a fast, notebook-style interface powered by modular code. Default Credentials [#default-credentials] On a fresh deployment, you can log in with the following details: ``` USERNAME: admin@admin.com PASSWORD: admin ``` Issue with Older CPUs [#issue-with-older-cpus] Mage AI requires modern CPU features to be available. On older devices, you may see the error: ``` The following required CPU features were not detected: sse4.2, popcnt, avx, avx2, fma, bmi1, bmi2, lzcnt, pclmulqdq ``` For more details, refer to the [following issue](https://github.com/pola-rs/polars/issues/15404). Links [#links] * [Official website](https://mage.ai/?utm_source=coolify.io) * [GitHub](https://github.com/mage-ai/mage-ai?utm_source=coolify.io) # Mailpit (/docs/services/mailpit) What is Mailpit? [#what-is-mailpit] Mailpit is a self-hosted email and SMTP testing tool with a web interface. Screenshots [#screenshots] Links [#links] * [The official website](https://mailpit.axllent.org) * [GitHub](https://github.com/axllent/mailpit) # Marimo (/docs/services/marimo) What is Marimo? [#what-is-marimo] Marimo is an open-source reactive notebook for Python — reproducible, git-friendly, SQL built-in, executable as a script, and shareable as an app. Links [#links] * [The official website](https://marimo.io/?utm_source=coolify.io) * [GitHub](https://github.com/marimo-team/marimo?utm_source=coolify.io) # Martin (/docs/services/martin) Martin [#martin] What is Martin [#what-is-martin] Martin is a tile server able to generate and serve vector tiles on the fly from large PostGIS databases, PMTiles (local or remote), and MBTiles files, allowing multiple tile sources to be dynamically combined into one. Links [#links] * [Official Documentation](https://maplibre.org/martin/?utm_source=coolify.io) # Matrix (/docs/services/matrix) Matrix (Synapse) [#matrix-synapse] What is Matrix? [#what-is-matrix] Matrix is an open-source, decentralized communication protocol that enables secure, real-time communication. It provides end-to-end encrypted messaging, voice and video calls, file sharing, and room-based conversations. Matrix serves as an excellent alternative to proprietary platforms like Slack or Discord, offering federation capabilities that allow different Matrix servers to communicate with each other. What is Synapse? [#what-is-synapse] Synapse is a [Matrix homeserver](https://matrix.org/ecosystem/servers/) written in Python/Twisted, [developed and maintained](https://github.com/element-hq/synapse) by the team [Element](https://element.io/), creators of Matrix. Deployment Variants [#deployment-variants] Synapse Matrix server is available in two deployment configurations in Coolify: Synapse with SQlite [#synapse-with-sqlite] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or personal Matrix hosting * **Components:** Single Synapse container with built-in SQLite database Synapse with PostgreSQL (recommended) [#synapse-with-postgresql-recommended] * **Database:** PostgreSQL * **Use case:** Production deployments requiring better performance and scalability * **Components:** * Synapse container * PostgreSQL container * Automatic database configuration and health checks Installation Steps [#installation-steps] For all deployment variants the installation steps are the same. Matrix domain setup (important) [#matrix-domain-setup-important] Matrix uses a value called the **server name** to generate user IDs and room aliases. * Server name `example.org` results in: * `@user:example.org` * `#room:example.org` The Matrix server itself can run on a different domain, for example `matrix.example.org`. Recommended setup [#recommended-setup] * Matrix server name: `example.org` * Matrix Synapse server service domain: `matrix.example.org` This allows users and rooms to use `:example.org` while hosting Synapse on a subdomain. Coolify configuration [#coolify-configuration] Domains [#domains] In the service configuration, set the domain to `matrix.example.org:8008` Environment variables [#environment-variables] Set the following environment variable: * `SYNAPSE_SERVER_NAME=example.org` Delegation (required) [#delegation-required] Because Synapse runs on `matrix.example.org` but identifies as `example.org`, [delegation](https://element-hq.github.io/synapse/latest/delegate.html) is required. On `https://example.org`, serve the following files: * `/.well-known/matrix/client` for server delegation ```json { "m.homeserver": { "base_url": "https://matrix.example.org" } } ``` * `/.well-known/matrix/server` for Federation discovery ```json { "m.server": "matrix.example.org:443" } ``` Links [#links] * [The official website](https://matrix.org?utm_source=coolify.io) * [GitHub](https://github.com/matrix-org/synapse?utm_source=coolify.io) * [Docker image](https://hub.docker.com/r/matrixdotorg/synapse?utm_source=coolify.io) * [Matrix Federation Tester](https://federationtester.matrix.org?utm_source=coolify.io) # Mattermost (/docs/services/mattermost) Mattermost [#mattermost] What is Mattermost [#what-is-mattermost] Mattermost is an open source, self-hosted Slack-alternative. Links [#links] * [Official Documentation](https://docs.mattermost.com?utm_source=coolify.io) # Mautic (/docs/services/mautic) Mautic [#mautic] This service has been removed from Coolify’s one-click service catalog because the official Docker images no longer include AMQP transport, so RabbitMQ integration does not work with our template. More info on [https://github.com/coollabsio/coolify/pull/8088](https://github.com/coollabsio/coolify/pull/8088) What is Mautic [#what-is-mautic] Mautic is the world's largest open-source marketing automation project, trusted by over 200,000 organizations worldwide. It provides a privacy-focused, fully customizable marketing automation platform that gives you complete control over your data and marketing infrastructure. Key features include: * **Multi-channel Marketing**: Manage email campaigns, SMS, web notifications, and social media from one platform * **Campaign Builder**: Create complex automation workflows with an intuitive drag-and-drop interface * **Lead Management**: Track contacts, score leads, and segment audiences based on behavior and attributes * **Self-hosted & Privacy-focused**: Full data sovereignty with compliance-ready features for GDPR and other regulations * **Unlimited & Customizable**: No restrictions on users, contacts, or campaigns - extend functionality through plugins * **CRM Integration**: Native integrations with HubSpot, Salesforce, Zoho CRM, Microsoft Dynamics, and more * **API-driven**: Comprehensive REST API for automation and custom integrations Links [#links] * [Official Website](https://www.mautic.org/?utm_source=coolify.io) * [Official Documentation](https://docs.mautic.org/?utm_source=coolify.io) * [GitHub Repository](https://github.com/mautic/mautic?utm_source=coolify.io) # Maybe (/docs/services/maybe) Maybe [#maybe] This service has been removed from Coolify’s one-click service catalog because the service is no longer maintained by the original authors. More info on [https://github.com/coollabsio/coolify/pull/8167#issuecomment-3858014514](https://github.com/coollabsio/coolify/pull/8167#issuecomment-3858014514) What is Maybe [#what-is-maybe] Maybe: The OS for your personal finances. Links [#links] * [Official Documentation](https://github.com/maybe-finance/maybe?utm_source=coolify.io) # Mealie (/docs/services/mealie) Mealie [#mealie] What is Mealie [#what-is-mealie] A recipe manager and meal planner. Links [#links] * [Official Documentation](https://docs.mealie.io/?utm_source=coolify.io) # Mediawiki (/docs/services/mediawiki) What is Mediawiki? [#what-is-mediawiki] Free and open source collaborative space for managing and sharing knowledge. Installation Steps [#installation-steps] 1. Comment out the shared volume for LocalSettings in your configuration. 2. Start the container. 3. Go to `http(s)://your-domain` to access the MediaWiki installation wizard. 4. Configure MediaWiki according to your needs through the wizard. 5. Download the generated `LocalSettings.php` file. 6. Stop the container. 7. Move the downloaded `LocalSettings.php` file to the specified file mount path on your server. 8. Uncomment the shared volume configuration to mount the `LocalSettings.php` file to the specified file mount path on your server. 9. Restart the container. Links [#links] * [The official website](https://www.mediawiki.org/wiki/MediaWiki) * [GitHub](https://github.com/wikimedia/mediawiki) # Meilisearch (/docs/services/meilisearch) What is Meilisearch? [#what-is-meilisearch] A lightning-fast search engine that fits effortlessly into your apps, websites, and workflow Meilisearch helps you shape a delightful search experience in a snap, offering features that work out-of-the-box to speed up your workflow. Screenshot [#screenshot] ✨ Features [#-features] * **Search-as-you-type:** find search results in less than 50 milliseconds * **[Typo tolerance](https://www.meilisearch.com/docs/learn/configuration/typo_tolerance?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** get relevant matches even when queries contain typos and misspellings * **[Filtering](https://www.meilisearch.com/docs/learn/fine_tuning_results/filtering?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features) and [faceted search](https://www.meilisearch.com/docs/learn/fine_tuning_results/faceted_search?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** enhance your users' search experience with custom filters and build a faceted search interface in a few lines of code * **[Sorting](https://www.meilisearch.com/docs/learn/fine_tuning_results/sorting?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** sort results based on price, date, or pretty much anything else your users need * **[Synonym support](https://www.meilisearch.com/docs/learn/configuration/synonyms?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** configure synonyms to include more relevant content in your search results * **[Geosearch](https://www.meilisearch.com/docs/learn/fine_tuning_results/geosearch?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** filter and sort documents based on geographic data * **[Extensive language support](https://www.meilisearch.com/docs/learn/what_is_meilisearch/language?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** search datasets in any language, with optimized support for Chinese, Japanese, Hebrew, and languages using the Latin alphabet * **[Security management](https://www.meilisearch.com/docs/learn/security/master_api_keys?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** control which users can access what data with API keys that allow fine-grained permissions handling * **[Multi-Tenancy](https://www.meilisearch.com/docs/learn/security/tenant_tokens?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** personalize search results for any number of application tenants * **Highly Customizable:** customize Meilisearch to your specific needs or use our out-of-the-box and hassle-free presets * **[RESTful API](https://www.meilisearch.com/docs/reference/api/overview?utm_campaign=oss\&utm_source=github\&utm_medium=meilisearch\&utm_content=features):** integrate Meilisearch in your technical stack with our plugins and SDKs * **Easy to install, deploy, and maintain** Links [#links] * [The official website](https://www.meilisearch.com) * [GitHub](https://github.com/meilisearch/meilisearch) # Memos (/docs/services/memos) What is Memos? [#what-is-memos] An open-source, lightweight note-taking solution. The pain-less way to create your meaningful notes. Your Notes, Your Way. Screenshots [#screenshots] Links [#links] * [The official website](https://usememos.com/?utm_source=coolify.io) * [GitHub](https://github.com/usememos/memos?utm_source=coolify.io) # Metabase (/docs/services/metabase) What is Metabase? [#what-is-metabase] Metabase is the easy, open-source way for everyone in your company to ask questions and learn from data. Features [#features] * [Set up in five minutes](https://www.metabase.com/docs/latest/setting-up-metabase.html) (we're not kidding). * Let anyone on your team [ask questions](https://www.metabase.com/docs/latest/users-guide/04-asking-questions.html) without knowing SQL. * Use the [SQL editor](https://www.metabase.com/docs/latest/questions/native-editor/writing-sql) for more complex queries. * Build handsome, interactive [dashboards](https://www.metabase.com/docs/latest/users-guide/07-dashboards.html) with filters, auto-refresh, fullscreen, and custom click behavior. * Create [models](https://www.metabase.com/learn/getting-started/models) that clean up, annotate, and/or combine raw tables. * Define canonical [segments and metrics](https://www.metabase.com/docs/latest/administration-guide/07-segments-and-metrics.html) for your team to use. * Send data to Slack or email on a schedule with [dashboard subscriptions](https://www.metabase.com/docs/latest/users-guide/dashboard-subscriptions). * Set up [alerts](https://www.metabase.com/docs/latest/users-guide/15-alerts.html) to have Metabase notify you when your data changes. * [Embed charts and dashboards](https://www.metabase.com/docs/latest/administration-guide/13-embedding.html) in your app, or even [your entire Metabase](https://www.metabase.com/docs/latest/enterprise-guide/full-app-embedding.html). Links [#links] * [The official website](https://www.metabase.com/) * [Github](https://github.com/metabase/metabase) # MetaMCP (/docs/services/metamcp) What is MetaMCP? [#what-is-metamcp] MetaMCP is an MCP aggregator/orchestrator that lets you group multiple MCP servers into namespaces, apply middleware, and expose a single unified endpoint. It supports SSE and Streamable HTTP transports (plus OpenAPI), works with popular MCP clients, and is built to simplify composing tools and hosting them behind API key or OAuth-based access. Links [#links] * Official documentation › [https://docs.metamcp.com](https://docs.metamcp.com?utm_source=coolify.io) * GitHub › [https://github.com/metatool-ai/metamcp](https://github.com/metatool-ai/metamcp?utm_source=coolify.io) # Metube (/docs/services/metube) What is Metube? [#what-is-metube] Web GUI for youtube-dl (using the yt-dlp fork) with playlist support. Allows you to download videos from YouTube and dozens of other sites. Links [#links] * [GitHub](https://github.com/alexta69/metube) # Mindsdb (/docs/services/mindsdb) Mindsdb [#mindsdb] What is Mindsdb [#what-is-mindsdb] MindsDB is the platform for building AI from enterprise data, enabling smarter organizations. Links [#links] * [Official Documentation](https://docs.mindsdb.com/what-is-mindsdb?utm_source=coolify.io) # Minecraft (/docs/services/minecraft) What is Minecraft? [#what-is-minecraft] Minecraft is a sandbox video game developed by Mojang Studios. The game was created by Markus "Notch" Persson in the Java programming language. It is a single-player and multiplayer game that allows players to explore, build, and mine in a procedurally generated world. Links [#links] * [GitHub](https://github.com/itzg/docker-minecraft-server) # Miniflux (/docs/services/miniflux) Miniflux [#miniflux] What is Miniflux? [#what-is-miniflux] Miniflux is a minimalist and opinionated feed reader that focuses on simplicity and performance. It supports RSS, Atom, and JSON feeds with features like full-text search, keyboard shortcuts, mobile-responsive design, and integration with read-it-later services. Miniflux is designed to be fast, lightweight, and distraction-free, making it perfect for users who want a clean RSS reading experience. Links [#links] * [The official website](https://miniflux.app?utm_source=coolify.io) * [GitHub](https://github.com/miniflux/v2?utm_source=coolify.io) # MinIO (/docs/services/minio-community-edition) MinIO Community Edition [#minio-community-edition] This service has been removed from Coolify’s one-click service catalog because it is no longer maintained by its original author. The community-maintained MinIO service on Coolify was an effort by the Coolify team to automatically build Docker images and publish them to both GitHub Container Registry and Docker Hub, using the official MinIO codebase on GitHub as the source. However, since the original upstream repository is no longer actively maintained, this community service will not receive any further updates. What is MinIO? [#what-is-minio] MinIO is a high-performance, distributed object storage system compatible with Amazon S3 APIs. It is software-defined, runs on industry-standard hardware, and is 100% open source under the AGPL v3.0 license. MinIO delivers high-performance, Kubernetes-native object storage that is designed for large scale AI/ML, data lake and database workloads. Links [#links] * [The official website](https://min.io?utm_source=coolify.io) * [MinIO GitHub](https://github.com/minio/minio?utm_source=coolify.io) * [Community Edition Github](https://github.com/coollabsio/minio?utm_source=coolify.io) FAQ [#faq] Invalid login credentials [#invalid-login-credentials] You need to run MinIO on `https` (not self-signed) to avoid this issue. MinIO doesn't support http based authentication. # MinIO (/docs/services/minio) MinIO Community Edition [#minio-community-edition] This service has been removed from Coolify’s one-click service catalog because it is no longer maintained by its original author. More info on [https://github.com/minio/minio/blob/master/README.md](https://github.com/minio/minio/blob/master/README.md) What is MinIO? [#what-is-minio] MinIO is a high-performance, distributed object storage system compatible with Amazon S3 APIs. It is software-defined, runs on industry-standard hardware, and is 100% open source under the AGPL v3.0 license. MinIO delivers high-performance, Kubernetes-native object storage that is designed for large scale AI/ML, data lake and database workloads. Links [#links] * [The official website](https://min.io?utm_source=coolify.io) * [Documentation](https://min.io/docs/minio/linux/index.html?utm_source=coolify.io) * [GitHub](https://github.com/minio/minio?utm_source=coolify.io) * [Community Edition Info](https://github.com/coollabsio/minio?utm_source=coolify.io) FAQ [#faq] Invalid login credentials [#invalid-login-credentials] You need to run MinIO on `https` (not self-signed) to avoid this issue. MinIO doesn't support http based authentication. # Mixpost (/docs/services/mixpost) What is Mixpost? [#what-is-mixpost] Self-hosted social media management software (Buffer alternative). Links [#links] * [The official Mixpost website](https://mixpost.app/) * [GitHub](https://github.com/inovector/mixpost) # Moodle (/docs/services/moodle) What is Moodle? [#what-is-moodle] Moodle is an open-source learning platform that provides a secure and private alternative to popular cloud storage services like Google Drive and Dropbox. It allows you to store, sync, and share files, photos, and videos across multiple devices, and offers features like file versioning, password-protected sharing, and collaboration tools. Links [#links] * [The official website](https://moodle.com/) * [GitHub](https://github.com/moodle/moodle) # Mosquitto (/docs/services/mosquitto) What is Mosquitto? [#what-is-mosquitto] Mosquitto is an open-source MQTT (Message Queuing Telemetry Transport) broker that facilitates communication between IoT devices by implementing the lightweight MQTT protocol. It's designed to provide reliable message delivery in scenarios with limited bandwidth or unstable networks, making it a key component for IoT and home automation systems. Links [#links] * [The official website](https://mosquitto.org/) * [GitHub](https://github.com/eclipse/mosquitto) # N8N (/docs/services/n8n) What is N8N? [#what-is-n8n] N8N is an open-source workflow automation tool that allows you to connect different applications and services together. It is an open-source alternative to tools like Zapier or Make. Deployment Variants [#deployment-variants] N8N is available in three deployment configurations in Coolify: n8n (Default) [#n8n-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or low-volume workflows * **Components:** Single n8n container with built-in SQLite database n8n with PostgreSQL [#n8n-with-postgresql] * **Database:** PostgreSQL (external) * **Use case:** Production deployments requiring better performance, scalability, and data persistence * **Components:** * n8n container * PostgreSQL 16 container * Automatic database configuration and health checks n8n with PostgreSQL and Worker [#n8n-with-postgresql-and-worker] * **Database:** PostgreSQL + Redis * **Use case:** High-volume production deployments with queue-based execution and parallel workflow processing * **Components:** * n8n main container * n8n-worker container for distributed execution * PostgreSQL 16 container * Redis container for queue management * Automatic database configuration and health checks Screenshots [#screenshots] Extending n8n with custom dependencies [#extending-n8n-with-custom-dependencies] To extend n8n with custom dependencies, you can add them following the example below to your Dockerfile: ```dockerfile ... RUN apk add --no-cache ffmpeg ... ``` Example Dockerfile [#example-dockerfile] ```dockerfile FROM n8nio/n8n:latest # Switch to root user to install packages and modify system directories USER root # Install necessary system packages using apk # build-base, python3-dev, geoip-dev are needed for potential native dependencies # wget for downloading, git for source control (might be needed by Go), bash (useful shell) RUN apk update && \ apk add --no-cache \ wget \ ffmpeg ENV N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME} ENV N8N_PORT=5678 ENV N8N_PROTOCOL=https ENV NODE_ENV=production ENV WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/ # Switch back to the non-root user that n8n runs as (typically 'node') USER node ``` Links [#links] * [The official website](https://n8n.io/) * [GitHub](https://github.com/n8n-io/n8n) # Navidrome (/docs/services/navidrome) What is Navidrome? [#what-is-navidrome] Navidrome is an open source web-based music collection server and streamer. It gives you freedom to listen to your music collection from any browser or mobile device. Screenshots [#screenshots] Links [#links] * [The official website](https://www.navidrome.org/?utm_source=coolify.io) * [GitHub](https://github.com/navidrome/navidrome/?utm_source=coolify.io) # Neon Ws Proxy (/docs/services/neon-ws-proxy) Neon Ws Proxy [#neon-ws-proxy] What is Neon Ws Proxy [#what-is-neon-ws-proxy] The database you love, on a serverless platform designed to help you build reliable and scalable applications faster. Links [#links] * [Official Documentation](https://neon.tech?utm_source=coolify.io) # Netbird-Client (/docs/services/netbird-client) What is Netbird-Client? [#what-is-netbird-client] Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls. Links [#links] * [The official website](https://netbird.io/?utm_source=coolify.io) * [GitHub](https://github.com/netbirdio/netbird?utm_source=coolify.io) # NewAPI (/docs/services/newapi) NewAPI [#newapi] What is NewAPI? [#what-is-newapi] The next-generation LLM gateway and AI asset management system supports multiple languages. Links [#links] * [Official website](https://docs.newapi.pro/en/docs?utm_source=coolify.io) * [GitHub](https://github.com/QuantumNous/new-api?utm_source=coolify.io) # Newt-Pangolin (/docs/services/newt-pangolin) Newt Pangolin What is Newt? [#what-is-newt] Newt is a fully user space WireGuard tunnel client and TCP/UDP proxy, designed to securely expose private resources controlled by Pangolin. By using Newt, you don't need to manage complex WireGuard tunnels and NATing. Env Variables [#env-variables] | Name | Description | Required | Default Value | | ----------------- | ----------- | -------- | ------------- | | NEWT ID | - | yes | | | NEWT SECRET | - | yes | | | PANGOLIN ENDPOINT | - | yes | domain.tld | Links [#links] * [The official website](https://docs.fossorial.io/Newt/overview?utm_source=coolify.io) * [GitHub](https://github.com/fosrl/newt?utm_source=coolify.io) # Next Image Transformation (/docs/services/next-image-transformation) Next Image Transformation [#next-image-transformation] What is Next Image Transformation [#what-is-next-image-transformation] Drop-in replacement for Vercel's Nextjs image optimization service. Links [#links] * [Official Documentation](https://github.com/coollabsio/next-image-transformation?utm_source=coolify.io) # NextCloud (/docs/services/nextcloud) What is NextCloud? [#what-is-nextcloud] NextCloud is an open-source productivity platform that provides a secure and private alternative to popular cloud storage services like Google Drive and Dropbox. It allows you to store, sync, and share files, photos, and videos across multiple devices, and offers features like file versioning, password-protected sharing, and collaboration tools. Deployment Variants [#deployment-variants] Nextcloud is available in four deployment configurations in Coolify: Nextcloud (Default) [#nextcloud-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or personal file storage * **Components:** Single Nextcloud container with built-in SQLite database Nextcloud with PostgreSQL [#nextcloud-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring better performance and scalability * **Components:** * Nextcloud container * PostgreSQL container * Automatic database configuration and health checks Nextcloud with MySQL [#nextcloud-with-mysql] * **Database:** MySQL * **Use case:** Production deployments with MySQL preference * **Components:** * Nextcloud container * MySQL container * Automatic database configuration and health checks Nextcloud with MariaDB [#nextcloud-with-mariadb] * **Database:** MariaDB * **Use case:** Production deployments with MariaDB preference (recommended for most users) * **Components:** * Nextcloud container * MariaDB container * Automatic database configuration and health checks Screenshots [#screenshots] Links [#links] * [The official website](https://nextcloud.com/) * [GitHub](https://github.com/nextcloud/server) # Sonatype Nexus (/docs/services/nexus) What is Sonatype Nexus [#what-is-sonatype-nexus] Sonatype Nexus is a repository manager that allows you to store, manage, and distribute your software artifacts. It supports multiple package formats including Maven, npm, Docker, PyPI, and more. Versions Available [#versions-available] Coolify offers two versions of Nexus: * **Nexus (Standard)**: The official x86\_64 architecture version * **Nexus ARM**: Community Edition for ARM64 architecture, maintained and synced with the official repository Setup [#setup] * The setup relies on starting as default user "admin" with password "admin123". * Once the service is running, login with the default credentials and change the password. * After that, delete `NEXUS_SECURITY_RANDOMPASSWORD=false` line from the compose file and restart the service to apply the changes. Minimum requirements: * 4 vCPU * 3 GB RAM Screenshots [#screenshots] Links [#links] * [The official website](https://help.sonatype.com/en/sonatype-nexus-repository.html?utm_source=coolify.io) * [GitHub](https://github.com/sonatype/docker-nexus3?utm_source=coolify.io) # Nitropage (/docs/services/nitropage) What is Nitropage? [#what-is-nitropage] Nitropage is an extensible, visual website builder based on SolidStart, offering a growing library of versatile building blocks. Deployment Variants [#deployment-variants] Nitropage is available in two deployment configurations in Coolify: Nitropage (Default) [#nitropage-default] * **Database:** SQLite (embedded) * **Use case:** Simple deployments, testing, or small websites * **Components:** Single Nitropage container with built-in SQLite database Nitropage with PostgreSQL [#nitropage-with-postgresql] * **Database:** PostgreSQL * **Use case:** Production deployments requiring better performance and scalability * **Components:** * Nitropage container * PostgreSQL container * Automatic database configuration and health checks Features [#features] * Reusable element **Presets** and **Layouts** * Publishing workflow with **Revisions** * Starter kit with dozens of Blueprints * Multiple websites on a single instance * Image optimization with **focal point** cropping * API for your custom [SolidJS](https://www.solidjs.com/?utm_source=coolify.io) page elements * Powerful developer architecture with [Vite](https://vitejs.dev/?utm_source=coolify.io) * Automatic sitemap.xml and Atom-feed handling Video [#video]