7 Commits
Author SHA1 Message Date
Andras BacsaiandClaude Opus 5.5 80ce0efe7e fix(api): use the Cloudflare client IP for allowed IPs and audit logs
Closes #12301

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:47:39 +01:00
Andras Bacsai 554bd354bf fix: support host storage paths and clean up cancelled deployments
Allow validated host file and directory mounts outside resource directories
while protecting external paths from deletion.

Clean up cancelled deployment containers and clear tracked process IDs.
Preserve legacy KeyDB and Dragonfly password parsing, accept server backup
paths without extension restrictions, and allow Compose variable proxy ports.
2026-10-05 11:08:52 +02:00
Andras Bacsai f95ddd97fa fix: enforce webhook lockouts and stop cancelled runner provisioning
- Manual webhooks (GitHub, GitLab, Gitea, Bitbucket) now reject all
  deliveries for a locked-out scope before reading secrets or verifying
  signatures, including correctly signed ones, until the window expires.
- ProvisionGithubRunnerJob checks whether the execution has already
  finished before and after each provisioning step, and only sets
  ready_at or Failed while it is still occupying/provisioning. A runner
  that is cancelled, timed out or completed mid-provisioning is no longer
  started, retried or overwritten.
- VolumeCloneJob creates bind-volume clones as plain local volumes
  without the source driver options, so the clone never mounts the
  source host directory.
- Image pulls for additional servers no longer ignore docker pull errors.
- Add tests for each change.
2026-10-02 18:24:52 +02:00
Andras Bacsai 13a57cc059 fix(webhooks): never lock out manual webhook deliveries with a valid signature
The failed-authentication lockout for manual webhooks was checked before
the signature, and the bucket used the client IP from X-Forwarded-For.
An unauthenticated client could send failed attempts with the Git host's
address for a public repository and branch, and correctly signed
deliveries then got 429, so deployments were lost.

The lockout now applies only to deliveries that fail authentication; a
delivery with a valid secret for a matched application is always
processed. Failures are counted per connection address (REMOTE_ADDR, or
CF-Connecting-IP on cloud), so rotating X-Forwarded-For no longer gives
a new bucket.
2026-10-01 07:16:27 +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 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 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