Commit Graph
913 Commits
Author SHA1 Message Date
Andras BacsaiandClaude Opus 5.5 7c60ccda0d fix: restore config diff, error text, delete handler, webhook id and danger zone fixes
- Configuration diff: report all settings when an app has no earlier
  snapshot, so older apps show "configuration changed" again (#11430).
- DigitalOcean/Vultr: do not repeat the "API error:" prefix.
- HasSecretManager: the deleting listener returns nothing, so later
  deleting listeners still run.
- GitLab webhook: use new_public_id() like the other webhooks.
- Team danger zone: show the link and open the page only for the team owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 09:35:32 +02:00
Andras BacsaiandClaude Opus 5.5 178e6665f8 fix: restore security and broken-feature fixes lost in the revert
Security:
- Settings email: authorize the SMTP and Resend toggles.
- Server navbar: show Sentinel status only to users who can view Sentinel.
- GitHub source: permission gates on Sync name and Delete.

Broken features:
- Profile: avatar upload (missing import and file uploads trait).
- API tokens: keep the "Never" expiry choice.
- Environment variables: show validation errors instead of a generic error.
- Servers API: read the server uuid from the route in domains_by_server,
  so ?uuid=<application> filters instead of returning 404.
- Cloud servers: Power On for stopped Hetzner, DigitalOcean and Vultr servers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 08:40:01 +02:00
Andras BacsaiandClaude Opus 5.5 a6a3b1d26b revert: undo the app changes from the test clean-up
Revert the app code changes of d666a0a95, 69eeb2f62, 1e66c9f9b and
a32082b03, so login, registration, OAuth, team danger zone, service
templates, and the other touched files are back to their earlier state.
Keep the removal of unused components and markup-only tests (d666a0a95
also contained those deletions by mistake).

StartupExecutionCleanupTest now fakes the template CDN with the current
file content, so app:init in the test no longer empties
templates/service-templates-latest.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 08:06:34 +02:00
Andras BacsaiandClaude Opus 5.5 a32082b03f fix: regressions found by the test suite
- TrustHosts: validate the Host header also when the FQDN cache is cold.
- Settings email: authorize the SMTP and Resend toggles.
- Server navbar: show Sentinel status only to users who can view Sentinel.
- GitHub source: restore permission gates on Sync name and Delete, and the
  Test connection button.
- Profile: make avatar upload work (missing import and file uploads trait).
- API tokens: keep the "Never" expiry choice.
- Environment variables: show validation errors instead of a generic error.
- Servers API: read the server uuid from the route in domains_by_server.
- Configuration diff: report all settings when no earlier snapshot exists.
- Cloud servers: restore Power On for stopped servers; do not repeat the
  provider error prefix.
- HasSecretManager: do not stop later deleting listeners.
- GitLab webhook: use new_public_id() like the other webhooks.
- Dev: show the Lima VM start command on the localhost server page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 00:18:09 +02:00
Andras Bacsai d88d6408e2 Merge remote-tracking branch 'origin/main' 2026-09-27 20:35:59 +02:00
Andras BacsaiandClaude Opus 5.5 2063e84d7c fix(dns): release managed records when a domain edit removes a hostname
- Editing a domain (UI application, service and preview domains, the
  General form, API application, preview, service, and service
  application updates) now releases the hostnames that the edit
  removed, like removing a domain does. Records that another live
  resource still uses are kept.
- A per-hostname lock (managed-dns:{team}:{hostname}) now covers the
  release (re-check, Cloudflare delete, row delete) and the create
  paths. A release can no longer delete a record that is being added
  again; a busy lock makes the release retry and the create wait or
  retry, and a create after a release makes the record again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 18:06:37 +02:00
peaklabs-dev 2aef5ab459 feat(database): let docker compose applications mount the sqlite volume 2026-09-27 18:00:34 +02:00
Andras BacsaiandClaude Opus 5.5 a77fe4d4ed fix(webhooks): deploy Gitea pull requests at their head commit
The Gitea handler read the pull request commit from a top-level
head.sha that Gitea does not send, so preview deployments always used
HEAD. It now reads pull_request.head.sha, with the top-level after of
newer Gitea versions as a fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 16:26:56 +02:00
Andras BacsaiandClaude Opus 5.5 eeda90a8a4 fix(webhooks): reject malformed payload values without a 500
Every webhook handler (GitHub, GitLab, Gitea, Bitbucket, GitHub App,
GitLab App) now reads the fields it uses through typed readers: refs,
titles, and actions must be strings, ids positive integers, commit
SHAs 7-64 hex characters, and URLs http(s). An invalid value returns
"Nothing to do. Invalid '<field>' in the request." without a
deployment. Signature checks and the failure lockout are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 14:37:21 +02:00
Andras BacsaiandClaude Opus 5.5 aabd127374 fix(compose): keep content files inside the resource directory
- A Compose bind volume with a Coolify `content:` block could make
  Coolify write any host file (for example /root/.ssh/authorized_keys)
  when the file was loaded. Content sources must now be inside the
  resource directory (./ paths); other sources get a clear validation
  error for services and applications (UI, API, load, deployment),
  and every content write is confined again on the server. Bind
  mounts without content are unchanged. All 94 template content
  volumes use ./ paths and still work.
- Quote container names in scheduled tasks and in the stop actions for
  applications, previews, and services.
- Fix a development-only crash when a preview with a bind mount was
  parsed (the preview suffix returned a plain string).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 14:37:21 +02:00
Andras BacsaiandClaude Opus 5.5 ebfee2ec3f fix(webhooks): handle pushes without commits and count only distinct failures
- GitLab, GitHub, and Gitea crashed with a 500 on push payloads without
  a commit list, and other malformed payloads (missing repository,
  project, ref, Bitbucket changes, non-string values, unsupported
  Gitea events) also returned 500. They now get a clean response; a
  push with an unknown file list still deploys, and a branch deletion
  does not deploy.
- The manual webhook lockout counts only distinct failed attempts: the
  same wrong GitLab token, or an identical HMAC redelivery, counts
  once, so a misconfigured hook no longer locks out a valid one. Every
  new guess still counts (30 per scope and minute). Attempts are
  stored only as HMAC hashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:47:01 +02:00
Andras BacsaiandClaude Opus 5.5 5b2724621a fix(compose): validate Git-based Docker Compose applications
Git-based Docker Compose applications skipped the Compose injection
validation that services use. It now runs when the file is loaded or
reloaded, when the raw Compose is saved (UI and API create), and at
deployment before any command uses the file; an unsafe file is not
saved, and a deployment stops with a clear log line.

- All 371 service templates and realistic Compose files still pass.
- Network names may now mix text with $VAR, ${VAR}, ${VAR:-default},
  or ${VAR-default} (for example ${COMPOSE_PROJECT_NAME}_default), so
  such existing applications keep deploying; command substitution and
  unsafe defaults stay rejected.
- Quote the preserved-repository path in a stat command.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:47:01 +02:00
peaklabs-dev a52cafb2db Merge branch 'main' into feat/add-sqlite-database 2026-09-26 23:22:49 +02:00
Andras BacsaiandClaude Opus 5.5 8246492bb9 fix(databases): stop and clean up interrupted or stale imports
- Imports store their cleanup data (names and paths, no credentials)
  on the activity. When Coolify fails an import after a restart or as
  stale, it queues a stop of the restore inside the database container
  (only processes of that operation and their children, bottom-up so
  the database server is not affected) and the normal cleanup.
- The cleanup runs once per import, and a stopped CoolifyTask does
  not run again when the queue retries it.
- The stop message stays on the activity: RunRemoteProcess saves the
  process id at start from the stored properties and keeps a stop
  status at the end, and CoolifyTask::failed() keeps the message.
- Regenerate the OpenAPI spec (409 for database start, restart, and
  import, plus earlier API changes that were missing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 22:18:17 +02:00
🏔️ Peak edcb884266 Merge branch 'main' into feat/add-sqlite-database 2026-09-26 21:32:43 +02:00
Andras BacsaiandClaude Opus 5.5 fbfe342f89 fix(databases): reserve start and restart atomically
Two parallel start requests both passed the in-progress check and got
200, because the start activity is created later by the queued action.
A per-database reservation (Cache::add, 600 s) is now taken before the
check, so the second request gets 409. The action releases it when it
creates its activity, skips, or fails. Restart, import, the deploy
API, MCP, and Livewire use the same reservation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 21:19:14 +02:00
peaklabs-dev 0687d1f55f feat(database): unlink applications from sqlite and protect connected volumes 2026-09-26 20:39:07 +02:00
Andras BacsaiandClaude Opus 5.5 a8117f9114 fix(databases): unblock interrupted imports and prevent double starts
- A Coolify restart now fails queued or running database imports, so
  they no longer block all later imports with 409.
- An import without progress for the SSH command timeout plus 30
  minutes (at least 2 hours) is stale and no longer blocks.
- The import sets its operation property when the activity is created,
  so a worker cannot save the activity without it.
- Start and restart refuse a second operation while a start, restart,
  or import is in progress, in the UI, the API (409), and actions.
- DatabaseStartJob runs only while its activity is still queued and
  the newest one, and holds a lock per database during the commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:40:53 +02:00
Andras BacsaiandClaude Opus 5.5 bbee57a81a fix(webhooks): scope manual webhook lockouts to repository and branch
Failed manual webhook deliveries were counted per provider and source
IP. On Coolify Cloud many customers share the Git provider IP, so one
repository with a wrong secret locked out valid deliveries of all
other repositories for 60 seconds.

The failure key now also contains the repository and branch. Guessing
the secret of one application stays limited to 30 tries per minute,
and a lockout rejects all deliveries in that scope, also correct ones.
A GitLab request without a token no longer counts as a failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:40:53 +02:00
Andras BacsaiandClaude Opus 5.5 e17b15f5f1 fix(sources): allow private networks for self-hosted Git sources
Since GitHub App and GitLab API calls use the outbound URL guard,
GitHub Enterprise or GitLab on a private network failed with "Webhook
URL resolved to an unsafe IP address" unless an admin allow-listed it.

On self-hosted instances, Git source URLs and requests now allow
private (RFC 1918), CGNAT (100.64/10, Tailscale), and IPv6 unique local
addresses, plus internal hostnames such as .internal, .local, and
container names. Loopback, localhost, link-local (cloud metadata),
0.0.0.0, and other reserved targets stay blocked. Redirects stay off
and DNS stays pinned. Coolify Cloud and all other outbound URLs keep
the strict rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 23:52:01 +02:00
peaklabs-dev 5261785c69 Merge remote-tracking branch 'origin/next' into feat/add-sqlite-database 2026-09-25 22:47:29 +02:00
Andras Bacsai 554b79e8dd feat: add Traefik ACME cert UI and shared managed DNS record ownership
- Proxy: list and delete Traefik ACME certificates from the server proxy
  page via new TraefikAcmeService and Get/DeleteTraefikCertificate actions
- DNS: track ownership and cross-resource references for managed DNS
  records so records are only deleted when no longer referenced; release
  records asynchronously on resource deletion via ReleaseManagedDnsRecordsJob
  and ManagedDnsRecordCleanup; harden Cloudflare provider deletion results
- Databases: fail closed on start when prerequisites or the CA certificate
  are missing (DatabaseStartException, Server::ensureCaCertificate) and
  clean up stale start activities via ResourceStartActivity
- Webhooks: throttle repeated manual webhook signature failures for
  GitHub, GitLab, Gitea and Bitbucket
- Deployments: improve compose build-context handling and compose file
  load error reporting
- Install scripts: rework terminal UI output in install.sh (stable and
  nightly)
- Misc: settings sidebar accordion fixes, log drain toggle rollback,
  add Serverside to README sponsors
- Add migrations and tests covering the above
2026-09-25 19:00:00 +02:00
Andras BacsaiandClaude Opus 5.5 60bac941ea fix(servers): build only on dedicated build servers
The server role migration gives every normal server the combined role, and
the build server queries counted combined servers as build servers.
"Use a build server" then built on a random production server, the resource
picker listed each server twice, and "Deployments only" did not stop builds.

- Build server selection and the picker use only "Builds only" servers.
  A null role falls back to the legacy is_build_server flag.
- Without a dedicated build server, builds fall back to the deployment
  server, never to another combined server.
- A "Deployments only" server always builds on a build server and needs a
  Docker image name. It never builds itself, except for restarts. Docker
  image and Compose applications are not affected.
- Setting "Deployments only" requires a dedicated build server.
- The API keeps is_build_server in sync with the role for downgrades.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:54:00 +02:00
peaklabs-dev 032ea6498c feat(api): support sqlite databases in the databases API 2026-09-24 22:15:08 +02:00
Andras Bacsai 87685d1e09 chore: align control-plane behavior 2026-09-24 15:46:04 +02:00
Andras Bacsai 3f47bae0b6 fix(service): save switches without saving pending Compose edits (#11985) 2026-09-24 13:43:37 +02:00
Andras Bacsai 74cc617a4c Keep API deployment behavior consistent (#11969) 2026-09-24 08:22:51 +02:00
Andras Bacsai 40b31b4a57 Align API deployment permissions 2026-09-24 08:19:02 +02:00
Andras Bacsai 2a3061adf5 Keep server creation consistent across entry points 2026-09-24 08:06:25 +02:00
Andras Bacsai d071a5df81 Improve Git source HTTP handling 2026-09-23 23:09:04 +02:00
Andras Bacsai 4b7ccfe9cd fix: align application image validation 2026-09-23 21:45:06 +02:00
Andras Bacsai 7c86e53422 fix(service): support metadata-only deletion on unreachable servers
Add a Coolify-only deletion path, improve Docker cleanup handling, and notify teams when service deletion fails.
2026-09-23 10:50:31 +02:00
Andras Bacsai 99dd634ba3 Improve file storage handling 2026-09-22 21:13:39 +02:00
Andras Bacsai bfb732bbe8 fix(webhooks): validate preview repository metadata 2026-09-21 16:53:50 +02:00
Andras Bacsai 19f0ae9a7d fix(webhooks): reject incomplete Stripe configuration (#11915) 2026-09-21 15:36:20 +02:00
Andras Bacsai 735187868c fix(webhooks): reject incomplete Stripe configuration 2026-09-21 15:35:31 +02:00
Andras Bacsai 865ebe0bdd fix(auth): improve OAuth sign-in handling 2026-09-21 14:00:14 +02:00
Andras Bacsai 1c408fb408 feat(audit): expand event tracking and remove scheduled job monitoring
Add audit levels and record user, OAuth, DNS, notification, and settings changes while removing the obsolete scheduled job monitoring UI and services.
2026-09-21 12:23:42 +02:00
Andras Bacsai a29f02fbb1 Merge remote-tracking branch 'origin/main' into pr-11443-next
# Conflicts:
#	openapi.json
#	openapi.yaml
#	resources/views/livewire/project/application/heading.blade.php
#	resources/views/livewire/project/service/heading.blade.php
2026-09-19 17:44:44 +02:00
Andras Bacsai 383a5a742f feat(servers): add configurable deployment and build roles
Introduce deployment, build, and dual-purpose server roles, with API and UI support, build-server fallback controls, and role-aware resource hosting.
2026-09-19 17:22:13 +02:00
Andras Bacsai 23f24f8425 feat(api): expose runtime logs for preview deployments (#11884) 2026-09-18 14:41:55 +02:00
Andras Bacsai ebfd4d0c1c Merge remote-tracking branch 'origin/main' into pr-11443-next
# Conflicts:
#	app/Actions/Server/StartSentinel.php
#	app/Livewire/Server/Sentinel.php
#	resources/views/livewire/project/shared/storages/all.blade.php
#	resources/views/livewire/project/shared/storages/show.blade.php
2026-09-18 12:00:04 +02:00
Andras Bacsai 128939b062 fix(storages): remove host path from storage configuration 2026-09-16 14:24:52 +02:00
Andras Bacsai 16b092336e feat(sentinel): track synchronization state and refresh status UI
Add sentinel waiting-state tracking, synchronization broadcasts, and restore
status handling across server and application interfaces.
2026-09-16 12:51:27 +02:00
Andras Bacsai 2c1744fbd2 Merge remote-tracking branch 'origin/next' into pr-11784-automation/sync-main-to-next 2026-09-14 13:30:17 +02:00
Andras Bacsai 6a8cee4630 Merge remote-tracking branch 'origin/next' into automation/sync-main-to-next 2026-09-14 13:26:19 +02:00
Andras Bacsai 7d11bc92f7 feat(logs): accept all for log lines and keep -1
API log endpoints and the GetLogs UI now treat `all` as unbounded
output, with `-1` remaining as a compatibility alias. MCP still
falls back to a positive default. Traefik version checks run from
CheckForUpdatesJob instead of a weekly schedule.
2026-09-13 15:25:20 +02:00
Andras Bacsai fc9e61b7b4 feat(services): open resource settings in a modal with restart limits
Move service application and database settings into an embedded modal with a footer, subtitle helper, and Docker restart-count control. Accept max_restart_count on the service applications API, cap compose YAML collection aliases, and tighten status, backup, and database sidebar layouts.
2026-09-10 17:39:56 +02:00
peaklabs-dev 9faa4f4b7c Merge branch 'main' into next 2026-09-09 15:32:27 +02:00
peaklabs-dev 0d8ef9411f feat(api): allow setting the container name prefix 2026-09-09 15:01:57 +02:00