# Coolify Admin Guide

This guide is the operational and architectural reference for **Coolify** — an open-source, self-hostable Platform-as-a-Service. It is written for the administrators, DevOps engineers, and architects who run a Coolify instance: how it is built, how to configure every knob, how to secure it, how to operate it day to day, and how its deployment engine works internally. End-user, task-oriented documentation (deploying apps, creating databases, using services) lives in the companion **User Guide**.

---

## 1. Executive Summary

Coolify is a **control plane** that turns one or more Linux servers into a private application platform. It connects to servers over SSH, manages a reverse proxy on each, and runs user workloads (applications, databases, and pre-packaged services) as Docker containers. It provides Git-push deployments, automatic Let's Encrypt TLS, scheduled backups, preview environments, a full REST API, and an MCP server for AI agents.

| Attribute | Value |
|-----------|-------|
| Product | Coolify (`coollabsio/coolify`) |
| License | Apache-2.0 |
| Version line | v4 (`config/constants.php` → `version` `4.1.1`) |
| Language / runtime | PHP **8.4** |
| Framework | Laravel **12**, Livewire **3** |
| Queue/worker | Laravel **Horizon** on Redis |
| Real-time | `coolify-realtime` (Soketi-compatible Pusher server + node-pty terminal) |
| Metadata store | PostgreSQL (`coolify-db`) |
| Cache / queue broker | Redis (`coolify-redis`) |
| Remote execution | SSH (phpseclib) + Docker on managed servers |
| Default proxy | Traefik (Caddy / Nginx / none also supported) |
| Companion images | `coolify-helper` `1.0.14`, `coolify-realtime` `1.0.15`, Railpack `0.23.0` |
| Source size | ~2,700 files, ~9.1M chars |
| Documented commit | `5a27427` (2026-05-27) |

> [!NOTE]
> Coolify is a **mixed PHP/Laravel monolith** plus a small Node.js real-time sidecar. The Laravel app serves both the Livewire dashboard and the JSON REST API; background work (deployments, backups, health checks) runs as queued jobs under Horizon.

---

## 2. Architecture

### 2.1 Runtime topology

```text
                          ┌──────────────────────────────────────────────┐
   Browser / API client   │            Coolify host (control plane)       │
        │  HTTPS           │                                              │
        ▼                  │   ┌─────────────┐   ┌────────────────────┐   │
   ┌──────────┐  :8000     │   │  coolify    │   │ coolify-realtime   │   │
   │  proxy   │───────────▶│   │ (PHP-FPM +  │   │ (websockets +      │   │
   │ (Traefik)│            │   │  nginx,     │   │  in-browser term., │   │
   └──────────┘  :6001/2   │   │  Laravel 12)│   │  node-pty)         │   │
                ──────────▶│   │  + Horizon  │   └────────────────────┘   │
                           │   │  + scheduler│                            │
                           │   └─────┬───────┘                            │
                           │         │                                    │
                           │   ┌─────▼──────┐   ┌───────────────┐         │
                           │   │ coolify-db │   │ coolify-redis │         │
                           │   │ (Postgres) │   │ (queue+cache) │         │
                           │   └────────────┘   └───────────────┘         │
                           └──────────────────────┬───────────────────────┘
                                                  │ SSH (phpseclib, mux)
                              ┌───────────────────┼────────────────────┐
                              ▼                   ▼                    ▼
                       ┌────────────┐      ┌────────────┐      ┌────────────┐
                       │ Managed    │      │ Managed    │      │ Managed    │
                       │ server #1  │      │ server #2  │ ...  │ server #N  │
                       │  Docker +  │      │  Docker +  │      │  Docker +  │
                       │  proxy +   │      │  proxy +   │      │  proxy +   │
                       │  workloads │      │  workloads │      │  Sentinel  │
                       └────────────┘      └────────────┘      └────────────┘
```

The control-plane host can also be a managed server (the "localhost" destination), so a single-box install is fully functional.

### 2.2 Control-plane containers

| Container | Image | Role |
|-----------|-------|------|
| `coolify` | `ghcr.io/coollabsio/coolify:latest` | The Laravel app (dashboard + REST API), Horizon workers, and the scheduler, supervised by **s6-overlay**. Serves on `:8080` → published `:8000`. |
| `coolify-db` | PostgreSQL | Coolify's own metadata database. |
| `coolify-redis` | Redis | Queue broker (db 0) and cache (db 1). |
| `coolify-realtime` (`soketi`) | `ghcr.io/coollabsio/coolify-realtime:1.0.15` | Pusher-compatible websocket server (`:6001`) and the in-browser terminal backend via `node-pty` (`:6002`). |

> [!IMPORTANT]
> A single `coolify` container runs PHP-FPM, Horizon queue workers, and the Laravel scheduler together, orchestrated by **s6-overlay** service definitions (`db-migration`, `init-seeder`, `horizon`, `scheduler-worker`, `nightwatch-agent`). This is why the container does meaningful work even with no inbound requests.

### 2.3 Host data layout

All persistent state lives under `/data/coolify` (configurable via `BASE_CONFIG_PATH`) and is bind-mounted into the container:

| Path | Contents |
|------|----------|
| `/data/coolify/source/.env` | The instance's environment file (secrets). |
| `/data/coolify/ssh` | SSH keys and multiplex sockets used to reach managed servers. |
| `/data/coolify/applications` | Per-application working data. |
| `/data/coolify/databases` | Managed-database data. |
| `/data/coolify/services` | Service stack data. |
| `/data/coolify/backups` | Local database backups. |

### 2.4 Source-tree map

| Directory | Responsibility |
|-----------|----------------|
| `app/Models/` | Eloquent domain models (Application, Server, Service, 8 Standalone\* databases, Project, Team, …). |
| `app/Jobs/` | Background work — the deployment engine and all async operations. |
| `app/Livewire/` | Dashboard UI components (server-rendered, reactive). |
| `app/Http/Controllers/Api/` | REST API controllers (one per resource family). |
| `app/Http/Controllers/Webhook/` | Git provider + Stripe webhook receivers. |
| `app/Http/Middleware/` | API ability gating, terminal access, maintenance, CSRF, etc. |
| `app/Actions/` | Reusable operations (Docker, Server, Application, Service, Proxy, Database, Stripe, Fortify). |
| `app/Services/` | Stateless helpers (config generation, container-status aggregation, Hetzner client, proxy cache, log parsing). |
| `app/Notifications/` | Notification channels and message DTOs. |
| `app/Policies/` | Authorization policies per model. |
| `app/Enums/` | Status and type enumerations. |
| `app/Mcp/` | Coolify's own Model Context Protocol server. |
| `config/` | Laravel + Coolify configuration files. |
| `database/migrations/` | Schema migrations (331 files). |
| `templates/compose/` | 360 one-click service Compose templates. |
| `routes/` | `web.php`, `api.php`, `webhooks.php`, `channels.php`, `ai.php` (MCP). |
| `docker/` | Production/development Dockerfiles, s6 service definitions, nginx/php configs, the realtime service. |

---

## 3. Requirements

| Component | Requirement |
|-----------|-------------|
| Host OS | 64-bit Linux. |
| Docker (host **and** every managed server) | **24.0+** (`config/constants.php` → `docker.minimum_required_version`). |
| Privileges | `root` or passwordless `sudo` SSH. |
| Ports | `8000` (dashboard/API), `6001`/`6002` (realtime/terminal), `80`/`443` (workload traffic). |
| PHP (when building from source) | `^8.4`. |
| Node (realtime sidecar build) | Node 24-alpine base. |

---

## 4. Configuration Mastery

Coolify is configured through environment variables (read in `config/*.php`) plus instance settings stored in the database and editable from **Settings**. This section enumerates the configuration surface from source.

### 4.1 Core application (`config/app.php`)

| Variable | Default | Purpose |
|----------|---------|---------|
| `APP_ID` | — | Unique instance identifier. |
| `APP_NAME` | `Coolify` | Display name. |
| `APP_ENV` | `production` | Environment. |
| `APP_DEBUG` | `false` | Detailed error pages (keep **off** in production). |
| `APP_URL` | `http://localhost` | Base URL for generated links. |
| `APP_PORT` | `8000` | Published dashboard port. |
| `APP_KEY` | — | **Required.** Laravel encryption key (`AES-256-CBC`). |

Timezone is fixed to `UTC` at the app level; per-server timezones are stored in settings. Maintenance mode uses the `cache` driver backed by Redis.

### 4.2 Coolify constants (`config/constants.php`)

| Variable | Default | Purpose |
|----------|---------|---------|
| `SELF_HOSTED` | `true` | Self-hosted vs. cloud mode. |
| `AUTOUPDATE` | — | Enable automatic updates. |
| `BASE_CONFIG_PATH` | `/data/coolify` | Root of host data. |
| `REGISTRY_URL` | `ghcr.io` | Registry for Coolify images. |
| `HELPER_IMAGE` | `ghcr.io/coollabsio/coolify-helper` | Helper container image. |
| `REALTIME_IMAGE` | `ghcr.io/coollabsio/coolify-realtime` | Realtime image. |
| `CDN_URL` | `https://cdn.coollabs.io` | CDN for versions/upgrade scripts. |
| `VERSIONS_URL` | `…/coolify/versions.json` | Version manifest. |
| `UPGRADE_SCRIPT_URL` | `…/coolify/upgrade.sh` | Upgrade script. |
| `IS_WINDOWS_DOCKER_DESKTOP` | `false` | Windows Docker Desktop mode. |

Pinned component versions (in-source): Coolify `4.1.1`, helper `1.0.14`, realtime `1.0.15`, Railpack `0.23.0`.

### 4.3 SSH tuning (`config/constants.php` → `ssh`)

| Variable | Default | Purpose |
|----------|---------|---------|
| `SSH_MUX_ENABLED` / `MUX_ENABLED` | `true` | Reuse SSH connections (multiplexing) for speed. |
| `SSH_MUX_PERSIST_TIME` | `3600` | Mux socket lifetime (seconds). |
| `SSH_MAX_RETRIES` | `3` | Retry attempts on transient SSH failures. |
| `SSH_RETRY_BASE_DELAY` | `2` | Base backoff (seconds). |
| `SSH_RETRY_MAX_DELAY` | `30` | Max backoff (seconds). |
| `SSH_RETRY_MULTIPLIER` | `2` | Exponential backoff multiplier. |
| (fixed) `connection_timeout` | `10` | Connect timeout. |
| (fixed) `command_timeout` | `3600` | Per-command timeout. |

> [!TIP]
> If you see intermittent SSH or "command execution failed" errors on a flaky network, the retry knobs above give you exponential-backoff headroom. As a last resort, multiplexing can be disabled per server (or globally via `ConfigurationRepository::disableSshMux()`).

### 4.4 Database (`config/database.php`)

The default connection is PostgreSQL (`coolify-db`):

| Variable | Default | Purpose |
|----------|---------|---------|
| `DB_CONNECTION` | `pgsql` | Driver. |
| `DB_HOST` | `coolify-db` | Host. |
| `DB_PORT` | `5432` | Port. |
| `DB_DATABASE` | `coolify` | Database name. |
| `DB_USERNAME` | `coolify` | User. |
| `DB_PASSWORD` | — | **Required.** |
| `DB_DISABLE_PREPARES` | `false` | Disable PDO prepared statements. |

**Read/write splitting** is opt-in: set `DB_READ_HOST` (and optionally `DB_WRITE_HOST`, `DB_READ_PORT`, `DB_STICKY`) to route reads to replicas. Hosts may be comma-separated; Laravel random-picks one. When unset, behavior is identical to a single primary.

### 4.5 Redis, cache, and broadcasting

| Variable | Default | Purpose |
|----------|---------|---------|
| `REDIS_HOST` | `coolify-redis` | Redis host. |
| `REDIS_PORT` | `6379` | Port. |
| `REDIS_PASSWORD` | — | **Required** in production. |
| `REDIS_DB` | `0` | Queue/default DB. |
| `REDIS_CACHE_DB` | `1` | Cache DB. |
| `CACHE_DRIVER` | `redis` | Cache store. |
| `BROADCAST_DRIVER` | `pusher` | Broadcasting driver. |
| `PUSHER_APP_ID` / `PUSHER_APP_KEY` / `PUSHER_APP_SECRET` | `coolify` | Realtime credentials. |
| `PUSHER_BACKEND_HOST` | `coolify-realtime` | Realtime backend host. |
| `PUSHER_BACKEND_PORT` | `6001` | Realtime backend port. |

### 4.6 Queues and scheduler (`config/horizon.php`, `config/constants.php`)

| Variable | Default | Purpose |
|----------|---------|---------|
| `HORIZON_ENABLED` | `true` | Run Horizon workers. |
| `SCHEDULER_ENABLED` | `true` | Run the Laravel scheduler. |
| `HORIZON_QUEUES` | `high,default` | Queues served. |
| `HORIZON_MIN_PROCESSES` | `1` | Min worker processes. |
| `HORIZON_MAX_PROCESSES` | `4` | Max worker processes (autoscaled by queue size). |
| `HORIZON_TIMEOUT` | `36000` | Worker timeout. |
| `HORIZON_BALANCE` | `false` | Balancing strategy toggle. |
| `MIGRATION_ENABLED` | `true` | Run migrations on boot. |
| `SEEDER_ENABLED` | `true` | Run seeders on boot. |

Horizon trims recent jobs after 60 minutes and failed jobs after 7 days (`10080` minutes). The Horizon dashboard is available at `/horizon` (web-guarded).

### 4.7 Mail (`config/mail.php` + `ConfigurationRepository`)

Mail is configured at runtime from instance settings, not just `.env`. Two paths:

- **Resend** — when `resend_enabled`, Coolify sets `mail.default=resend` and uses the configured `resend_api_key`.
- **SMTP** — when `smtp_enabled`, Coolify builds the SMTP mailer from `smtp_host`, `smtp_port`, `smtp_username`, `smtp_password`, `smtp_encryption` (`tls`/`starttls`/`none`), and `smtp_from_*`.

Configure these under **Settings → Email**.

### 4.8 Filesystems (`config/filesystems.php`)

| Disk | Driver | Path / use |
|------|--------|-----------|
| `local` | local | `storage/app`. |
| `public` | local | `storage/app/public`. |
| `ssh-keys` | local | `storage/app/ssh/keys` (private). |
| `ssh-mux` | local | `storage/app/ssh/mux` (private). |
| `deployments` | local | `storage/app/deployments`. |
| `backups` | local | `storage/app/backups`. |
| `s3` | s3 | Off-host backups (`AWS_*` vars). |

### 4.9 API, rate limits, CORS

| Variable | Default | Purpose |
|----------|---------|---------|
| `API_RATE_LIMIT` | `200` | Requests/min for the API. |

CORS (`config/cors.php`) allows all origins/methods/headers on `api/*` and `sanctum/csrf-cookie` with credentials disabled — tighten via a reverse proxy if you expose the API publicly.

### 4.10 Sentinel, proxy, and monitoring intervals

| Variable | Default | Purpose |
|----------|---------|---------|
| `SENTINEL_PUSH_FORCE_INTERVAL_SECONDS` | `300` | Force a server-state push even when unchanged. |
| `PROXY_CONNECT_NETWORKS_INTERVAL_SECONDS` | `3600` | Periodically reconnect the proxy to Docker networks. |
| `NIGHTWATCH_ENABLED` | `false` | Laravel Nightwatch agent. |
| `SENTRY_DSN` | — | Error reporting to Sentry. |

### 4.11 Authentication features (`config/fortify.php`)

Laravel Fortify provides authentication. Enabled features: **registration**, **password reset**, **profile updates**, **password updates**, and **two-factor authentication** (with password confirmation). Login throttling defaults to 5 attempts/min per email+IP. Email verification is available but commented off by default.

---

## 5. The Deployment Engine (Internals)

The heart of Coolify is `app/Jobs/ApplicationDeploymentJob.php` (~4,800 lines). It is a queued job (`ShouldQueue`, `ShouldBeEncrypted`) that runs on the `deployment` queue, with `tries = 1` and a server-configurable timeout.

### 5.1 Lifecycle

1. **Construct** — load the `ApplicationDeploymentQueue` record, the `Application`, its settings, source (GitHub/GitLab/other), destination, and target server; compute container name, working directories, and flags (rollback, force-rebuild, restart-only, preview).
2. **`handle()`** —
   - Abort early if the deployment was cancelled.
   - Mark the queue row `in_progress` and record the worker host.
   - Verify the server is **functional**; fail fast if not.
   - Store the server's private key on disk and build a custom host↔IP map of sibling containers.
   - Select a **build server** if build-server mode is enabled (else build on the deploy server).
   - **Detect BuildKit/buildx capabilities** (and Docker build-secret support).
   - Dispatch to the right build path via `decide_what_to_do()`.
3. **`finally`** — record `finished_at`, write deployment configuration, gracefully shut down the build container, and broadcast a status-changed event.

### 5.2 Build-path dispatch (`decide_what_to_do()`)

| Condition | Path |
|-----------|------|
| `restart_only` | `just_restart()` |
| build pack `dockerimage` | `deploy_dockerimage_buildpack()` |
| pull-request deploy | `deploy_pull_request()` (preview env) |
| inline `dockerfile` set | `deploy_simple_dockerfile()` |
| build pack `dockercompose` | `deploy_docker_compose_buildpack()` |
| build pack `dockerfile` | `deploy_dockerfile_buildpack()` |
| build pack `static` | `deploy_static_buildpack()` (serves via `nginx:alpine`) |
| build pack `nixpacks` | `deploy_nixpacks_buildpack()` |
| build pack `railpack` | `deploy_railpack_buildpack()` |
| otherwise | throws `Unsupported build pack` |

After the build path, `post_deployment()` marks the deployment **finished first** (so status is correct even if side effects fail), refreshes container status, updates the PR status on GitHub, and runs the post-deployment command.

### 5.3 Build artifacts and capabilities

- Build scripts and plans live under `/artifacts` in the build container (`build.sh`, `build-time.env`, Nixpacks `thegameplan.json`).
- Railpack reads `railpack.json` from the repo and writes `.coolify/railpack.generated.json`.
- BuildKit is required for Docker ≥ 18.09; buildx is expected on Docker 24.0+. When build secrets are enabled and supported, secrets are passed via `--secret` rather than build args.

### 5.4 Health checks and rolling updates

The job starts the new container, polls the configured health check, and only cuts traffic over when healthy — otherwise it rolls back to the previous container. Pre- and post-deployment commands run inside designated containers and fail the deploy if the target container can't be found.

### 5.5 Other background jobs

| Group | Jobs |
|-------|------|
| Deployment | `ApplicationDeploymentJob`, `ApplicationPullRequestUpdateJob`, `ProcessGithubPullRequestWebhook` |
| Databases | `DatabaseBackupJob` (local + S3), `VolumeCloneJob` |
| Servers | `ServerCheckJob`, `ServerManagerJob`, `ServerConnectionCheckJob`, `ServerLimitCheckJob`, `ServerPatchCheckJob`, `ServerStorage{Check,Save}Job`, `ValidateAndInstallServerJob`, `ServerCleanupMux` |
| Proxy | `RestartProxyJob`, `ConnectProxyToNetworksJob`, `RegenerateSslCertJob` |
| Cleanup | `DockerCleanupJob`, `CleanupHelperContainersJob`, `CleanupOrphanedPreviewContainersJob`, `CleanupInstanceStuffsJob` |
| Scheduling | `ScheduledJobManager`, `ScheduledTaskJob`, `CheckAndStartSentinelJob` |
| Updates | `CheckForUpdatesJob`, `UpdateCoolifyJob`, `PullTemplatesFromCDN`, `PullChangelog`, `CheckHelperImageJob`, `CheckTraefikVersion*Job` |
| Notifications | `SendMessageTo{Discord,Slack,Telegram,Pushover}Job`, `SendWebhookJob`, `ApiTokenExpirationWarningJob` |
| Billing (cloud) | `StripeProcessJob`, `SyncStripeSubscriptionsJob`, `VerifyStripeSubscriptionStatusJob`, `SubscriptionInvoiceFailedJob`, `UpdateStripeCustomerEmailJob` |

---

## 6. Security

### 6.1 Authentication

- **Session auth** (`web` guard) for the dashboard, via Fortify, with optional **two-factor authentication** and rate-limited login.
- **OAuth SSO** via Socialite providers: Google, Microsoft/Azure, Authentik, Discord, Zitadel, Clerk, Infomaniak (configured in **Settings → OAuth**).
- **API tokens** via Laravel **Sanctum** (personal access tokens) for the REST API and MCP.

### 6.2 API authorization model

API routes (`routes/api.php`) are layered:

- `auth:sanctum` authenticates the token.
- `ApiAllowed` middleware enforces that the API is enabled for the instance.
- `api.ability:{read|write|deploy}` (custom `ApiAbility` middleware) gates each route by token ability.
- `api.sensitive` (`ApiSensitiveData` middleware) masks secret fields in responses unless permitted.
- The instance API can be toggled at runtime: `GET /api/v1/enable` / `GET /api/v1/disable` (write ability). The MCP server is toggled via `POST /api/v1/mcp/enable` / `/disable`.

> [!IMPORTANT]
> Treat API tokens like passwords. Scope them to the **minimum ability** (`read` for monitoring, `deploy` for CI that only triggers deploys, `write` only when managing resources). `ApiTokenExpirationWarningJob` proactively warns before tokens lapse.

### 6.3 Authorization (policies)

Every model has a Laravel **Policy** (`app/Policies/`): `ApplicationPolicy`, `DatabasePolicy`, `ServerPolicy`, `ServicePolicy`, `ProjectPolicy`, `TeamPolicy`, `PrivateKeyPolicy`, `S3StoragePolicy`, and more. Combined with team **roles** (member < admin < owner), these enforce who can view, create, update, or delete each resource. Web routes add guards like `can.update.resource`, `can.create.resources`, and `can.access.terminal`.

### 6.4 Secrets at rest

- The Laravel `APP_KEY` encrypts sensitive model attributes. Migrations explicitly **encrypt** existing private keys, ClickHouse admin passwords, and webhook secrets (e.g. `EncryptExistingPrivateKeys`, `BackfillAndEncryptWebhookSecrets`).
- Deployment jobs implement `ShouldBeEncrypted`, so queued payloads are encrypted in Redis.
- SSH private keys live on a private-visibility disk under `storage/app/ssh/keys`.

### 6.5 Input validation and SSRF protection

Custom validation rules (`app/Rules/`) defend the deployment surface: `SafeExternalUrl`, `SafeWebhookUrl` (SSRF guards), `ValidGitRepositoryUrl`, `ValidGitBranch`, `DockerImageFormat`, `ValidServerIp`, `ValidIpOrCidr`, `ValidHostname`, `ValidDnsServers`, `ValidCloudInitYaml`, and `ValidProxyConfigFilename`. The deployment job additionally validates path fields and Docker build targets against strict patterns and escapes shell arguments.

### 6.6 Transport security

- Automatic Let's Encrypt certificates via the proxy; renewals are managed (`RegenerateSslCertJob`). Custom CA certificates are supported for internal TLS (`SslHelper`, per-server CA cert).
- SSH to managed servers uses phpseclib with multiplexing and retry/backoff.
- Optional **Cloudflare Tunnel** per server avoids exposing inbound ports.
- HMAC-verified inbound webhooks (Git providers, Stripe).

> [!CAUTION]
> The in-browser **terminal** grants real shell access to servers and containers. It is disabled per server by default (**Server → Security → Terminal Access**) and gated by `CanAccessTerminal`. Enable it only where every terminal-permitted user is trusted.

### 6.7 Malicious-input posture

Coolify deploys arbitrary user-supplied code and Compose files. Treat every managed server as capable of running untrusted workloads: isolate networks, apply resource limits, keep Docker patched, and avoid co-locating sensitive data on servers that run untrusted services.

---

## 7. Operations

### 7.1 Artisan / console commands (`app/Console/Commands/`)

Run inside the `coolify` container (`docker exec -it coolify php artisan <command>`):

| Command | Purpose |
|---------|---------|
| `app:init` (`Init`) | Bootstrap/seed instance state on startup. |
| `root:change-email` / `root:reset-password` | Recover the root account. |
| `app:delete-user` (`AdminDeleteUser`) | Remove a user. |
| `horizon:manage` (`HorizonManage`) | Manage Horizon workers. |
| `run:scheduled-jobs-manually` | Force-run scheduled jobs. |
| `scheduled-job:diagnostics` (`ScheduledJobDiagnostics`) | Inspect scheduler health. |
| `view:scheduled-logs` | Read scheduler logs. |
| `check:deployment-queue` / `cleanup:deployment-queue` | Inspect/clean the deployment queue. |
| `cleanup:database` / `cleanup:redis` / `cleanup:stucked-resources` / `cleanup:unreachable-servers` / `cleanup:names` | Housekeeping. |
| `services:delete` | Remove orphaned services. |
| `update:service-versions` / `sync:bunny` | Refresh the service template catalog from the CDN. |
| `emails:*` (`Emails`) | Send/test transactional emails. |
| `check:traefik-version` | Check the proxy version. |
| `clear:global-search-cache` | Reset search caches. |

### 7.2 Queue & scheduler operations

- **Horizon** runs under s6 inside the container; monitor it at `/horizon`. Workers autoscale between `HORIZON_MIN_PROCESSES` and `HORIZON_MAX_PROCESSES` by queue depth.
- The **scheduler** dispatches periodic work via `ScheduledJobManager`. Skips and runs are logged to `storage/logs/scheduled-*.log` and parsed by `SchedulerLogParser` for the **Settings → Scheduled Jobs** UI.
- `CleanupApplicationDeploymentQueue` / `CleanupStuckedResources` recover deployments and resources stuck in a transient state.

### 7.3 Backups

- Coolify's **own** metadata DB is backed up from **Settings → Backup**.
- Managed-database backups (`DatabaseBackupJob`) run on cron schedules, store locally and/or to S3, and record per-execution results downloadable from the UI.

### 7.4 Updating

- **Settings → Updates** triggers `UpdateCoolifyJob`; `CheckForUpdatesJob` polls `versions.json`. Auto-update is gated by `AUTOUPDATE`.
- Re-running the installer (`curl … install.sh | bash`) is the supported manual upgrade.
- Database migrations run automatically on boot when `MIGRATION_ENABLED=true`.

### 7.5 Monitoring

- **Sentinel** is an on-server agent that pushes container state and metrics to `POST /api/v1/sentinel/push`; `CheckAndStartSentinelJob` keeps it running and `PushServerUpdateJob` is force-dispatched at least every `SENTINEL_PUSH_FORCE_INTERVAL_SECONDS`.
- Server CPU/memory/disk charts come from Sentinel. `ServerStorageCheckJob` watches disk; `ServerPatchCheckJob` surfaces OS updates.
- Optional **Sentry** error reporting (`SENTRY_DSN`) and **Nightwatch** (`NIGHTWATCH_ENABLED`).

### 7.6 Container status semantics

`ContainerStatusAggregator` (a priority state machine) collapses many container states into one string (`running:healthy`, `degraded:unhealthy`, `starting:unknown`, `paused:unknown`, `exited`, …). Highest priority wins: degraded → restarting → crash-loop (exited with restarts) → mixed running/exited → mixed running/starting → running (by health) → dead → paused → starting → exited. Understanding this helps interpret the dashboard's status badges.

---

## 8. Data Model Reference

Coolify's domain is a set of Eloquent models, most extending a `BaseModel` that adds UUIDs and team scoping.

### 8.1 Core entities

| Model | Role |
|-------|------|
| `Team`, `User`, `TeamInvitation`, `Subscription` | Tenancy, membership, billing. |
| `Project`, `Environment`, `ProjectSetting` | Logical grouping of resources. |
| `Server`, `ServerSetting` | Managed hosts and their configuration. |
| `StandaloneDocker`, `SwarmDocker` | Deployment destinations (Docker networks). *(Swarm deprecated.)* |
| `Application`, `ApplicationSetting`, `ApplicationDeploymentQueue`, `ApplicationPreview` | Deployable apps, their settings, deployment records, and PR previews. |
| `Service`, `ServiceApplication`, `ServiceDatabase` | Multi-container service stacks and their sub-resources. |
| `Standalone{Postgresql,Mysql,Mariadb,Mongodb,Redis,Keydb,Dragonfly,Clickhouse}` | The 8 managed database engines. |
| `EnvironmentVariable`, `SharedEnvironmentVariable` | Per-resource and reusable variables. |
| `PrivateKey`, `CloudProviderToken`, `CloudInitScript` | SSH keys, cloud API tokens, first-boot scripts. |
| `GithubApp`, `GitlabApp` | Git source integrations. |
| `S3Storage`, `LocalFileVolume`, `LocalPersistentVolume` | Storage targets and volumes. |
| `ScheduledDatabaseBackup(+Execution)`, `ScheduledTask(+Execution)` | Backup and cron task definitions and runs. |
| `InstanceSettings`, `OauthSetting`, `SslCertificate` | Instance-wide config, OAuth config, certs. |
| `{Email,Discord,Slack,Telegram,Pushover,Webhook}NotificationSettings` | Per-channel notification config. |
| `PersonalAccessToken` | Sanctum API tokens. |

### 8.2 Key enumerations (`app/Enums/`)

| Enum | Values |
|------|--------|
| `BuildPackTypes` | `nixpacks`, `static`, `dockerfile`, `dockercompose`, `railpack` |
| `NewDatabaseTypes` | `postgresql`, `mysql`, `mongodb`, `redis`, `mariadb`, `keydb`, `dragonfly`, `clickhouse` |
| `NewResourceTypes` | the above plus `public`, `private-gh-app`, `private-deploy-key`, `dockerfile`, `dockercompose`, `docker-image`, `service` |
| `ProxyTypes` | `NONE`, `TRAEFIK`, `NGINX`, `CADDY` |
| `ApplicationDeploymentStatus` | `queued`, `in_progress`, `finished`, `failed`, `cancelled-by-user` |
| `ProcessStatus` | `queued`, `in_progress`, `finished`, `error`, `killed`, `cancelled`, `closed` |
| `ContainerStatusTypes` | `paused`, `restarting`, `removing`, `running`, `dead`, `created`, `exited` |
| `RedirectTypes` | `both`, `www`, `non-www` |
| `Role` | `member` (1), `admin` (2), `owner` (3) |

### 8.3 Application configuration model

`app/Services/ConfigurationGenerator.php` exports an application's full config (and is the best single reference for what an Application stores): build settings (`build_pack`, `static_image`, `base_directory`, `publish_directory`, `dockerfile*`, `docker_compose*`, `install/build/start_command`, `watch_paths`), source (`git_repository`, `git_branch`, `git_commit_sha`), domains (`fqdn`, `ports_exposes`, `ports_mappings`, `redirect`, `custom_nginx_configuration`), environment variables (production + preview), health-check fields, pre/post-deployment commands, per-provider webhook secrets, resource limits, and Swarm settings. This config is serialized to JSON/YAML and written alongside each deployment.

---

## 9. REST API Reference (Admin View)

Base: `/api/v1`. Auth: `Authorization: Bearer <token>` (Sanctum). Abilities: `read`, `write`, `deploy`.

| Resource family | Representative routes |
|-----------------|-----------------------|
| Instance | `GET /health` (unauth), `GET /version`, `GET /enable`\|`/disable`, `POST /mcp/enable`\|`/disable`, `POST /feedback`, `POST /sentinel/push` |
| Teams | `GET /teams`, `/teams/current`, `/teams/current/members`, `/teams/{id}`, `/teams/{id}/members` |
| Projects | `GET/POST/PATCH/DELETE /projects[/{uuid}]`, `…/environments` |
| Servers | `GET/POST/PATCH/DELETE /servers[/{uuid}]`, `/servers/{uuid}/domains`, `/resources`, `/validate`; `POST /servers/hetzner`; `GET /hetzner/{locations,server-types,images,ssh-keys}` |
| Applications | `GET /applications`; `POST /applications/{public,private-github-app,private-deploy-key,dockerfile,dockerimage}`; `GET/PATCH/DELETE /applications/{uuid}`; `…/envs`, `…/logs`, `…/storages`, `…/scheduled-tasks`; `POST …/{start,restart,stop}` |
| Databases | `GET /databases`; `POST /databases/{engine}`; `GET/PATCH/DELETE /databases/{uuid}`; `…/backups[/…/executions]`, `…/envs`, `…/storages`; `POST …/{start,restart,stop}` |
| Services | `GET/POST /services`; `GET/PATCH/DELETE /services/{uuid}`; `…/envs`, `…/storages`, `…/scheduled-tasks`; `POST …/{start,restart,stop}` |
| Deployments | `POST /deploy`; `GET /deployments[/{uuid}]`; `POST /deployments/{uuid}/cancel`; `GET /deployments/applications/{uuid}` |
| Security | `GET/POST /security/keys`, `GET/PATCH/DELETE /security/keys/{uuid}` |
| Cloud tokens | `GET/POST /cloud-tokens`, `…/{uuid}[/validate]` |
| GitHub apps | `GET/POST /github-apps`, `…/{id}[/repositories[/{owner}/{repo}/branches]]` |
| Resources | `GET /resources` |

A full **OpenAPI** specification is generated by the instance (`zircote/swagger-php`) and served for client generation. Unknown API paths return `404` with a pointer to `https://coolify.io/docs`.

> [!NOTE]
> Webhook receivers live outside `/api/v1` (`routes/webhooks.php`): `/source/{github,gitlab,bitbucket,gitea}/events[...]` for Git auto-deploy, and `/payments/stripe/events` for cloud billing.

---

## 10. Troubleshooting (Operator View)

### `Server is not functional.`
Validation failed or connectivity dropped. Re-run **Validate & Install**; confirm SSH credentials, Docker ≥ 24.0, and that the proxy container is up. Check `ServerConnectionCheckJob` results and server reachability notifications.

### `Command execution failed (exit code N): … Error: …`
A remote SSH command failed during deployment (raised by `ExecuteRemoteCommand`). The redacted command and stderr are logged. Inspect server load/disk, then tune SSH retries (`SSH_MAX_RETRIES`, backoff) for flaky links.

### Deployment stuck `in_progress`
Run `php artisan cleanup:stucked-resources` (and `cleanup:deployment-queue`). Check Horizon (`/horizon`) for failed/long jobs and confirm `HORIZON_ENABLED=true`.

### `StandaloneDocker with id=0 is required before running … Seeder`
A required base destination is missing (typically a fresh/partial install). Ensure seeders ran (`SEEDER_ENABLED=true`) and re-run `php artisan app:init`.

### Realtime/terminal not connecting
Verify the `coolify-realtime` container is healthy on `:6001`/`:6002`, that `PUSHER_*` values match across containers, and that ports are reachable. The terminal also requires per-server **Terminal Access** to be enabled.

### Emails not sending
Confirm SMTP or Resend is configured in **Settings → Email**; test with the `emails` artisan command. SMTP encryption must be one of `tls`/`starttls`/`none`.

### Disk filling on a server
Build caches and old images accumulate. Run/schedule **Docker Cleanup** (`DockerCleanupJob`); `ServerStorageCheckJob` reports usage. Consider a dedicated build server.

### After upgrade, UI is blank with a yellow loading bar
Stale front-end assets. Hard-refresh the browser; if needed restart the `coolify` container so assets are republished.

---

## 11. Quick Reference

### Containers
`coolify` (app + Horizon + scheduler, s6) · `coolify-db` (Postgres) · `coolify-redis` (queue+cache) · `coolify-realtime` (websockets+terminal)

### Key paths
`/data/coolify/{source/.env, ssh, applications, databases, services, backups}`

### Required env
`APP_KEY`, `APP_ID`, `DB_USERNAME`, `DB_PASSWORD`, `REDIS_PASSWORD`, `PUSHER_APP_{ID,KEY,SECRET}`

### Ports
`8000` dashboard/API · `6001`/`6002` realtime/terminal · `80`/`443` workloads

### Essential commands
```bash
# Health
curl http://127.0.0.1:8000/api/health
# Recover root
docker exec -it coolify php artisan root:reset-password
# Inspect scheduler
docker exec -it coolify php artisan scheduled-job:diagnostics
# Unstick deployments
docker exec -it coolify php artisan cleanup:stucked-resources
# Refresh service catalog
docker exec -it coolify php artisan update:service-versions
```

### Dashboards
`/` dashboard · `/horizon` queues · `/admin` instance admin · `/mcp` AI agent endpoint (when enabled)

### Build packs
`nixpacks` (default) · `railpack` (needs buildx) · `dockerfile` · `dockercompose` · `static` (nginx:alpine) · `dockerimage`

### Proxies
`TRAEFIK` (default) · `CADDY` · `NGINX` · `NONE`

### Databases
PostgreSQL · MySQL · MariaDB · MongoDB · Redis · KeyDB · Dragonfly · ClickHouse

---

_Generated June 2026 from coollabsio/coolify at 5a27427. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
