Commit Graph
38 Commits
Author SHA1 Message Date
e3d4411ff2 chore: merge main into release/v4.5 (#12192)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Furox <177975472+Furox-Art@users.noreply.github.com>
Co-authored-by: johandenhollander <johan.den.hollander@finalist.nl>
Co-authored-by: João Cruz <161638790+SrJooJ@users.noreply.github.com>
Co-authored-by: Saim Hashmi <hashmisaim037@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-18 23:43:20 +02:00
Andras BacsaiandClaude Opus 5.5 7c14c0098e feat(server-transfer): run instance migration as a background job (#12180)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:03:45 +02: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 e755f4c9e0 fix(webhooks): always verify manual webhook signatures
GitHub, Gitea and Bitbucket manual webhooks accepted any signature when
APP_ENV=local. GitLab and the GitHub App webhook already did not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 10:13:20 +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 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
Andras Bacsai 87685d1e09 chore: align control-plane behavior 2026-09-24 15:46:04 +02:00
Andras Bacsai bfb732bbe8 fix(webhooks): validate preview repository metadata 2026-09-21 16:53:50 +02:00
Andras Bacsai 29c122b31a fix(api): return deployment UUID strings directly 2026-07-03 11:31:49 +02:00
Andras Bacsai 062ad57740 fix(security): enforce team access on mutable actions
Authorize cloud provider token access, audit sensitive operations, and
standardize public IDs across deployment and resource flows.
2026-06-04 11:03:06 +02:00
Andras BacsaiandClaude Opus 4.7 c1518ba1c0 fix(webhook): match manual webhook repositories exactly
The manual webhook handlers selected target applications with a
`git_repository LIKE %full_name%` substring query, so a payload
repository name could match unintended applications when repository
names overlap.

Add a `MatchesManualWebhookApplications` trait that validates the
incoming `owner/repo` value and matches `Application.git_repository`
by exact normalized path. Github, Gitlab, Gitea and Bitbucket manual
handlers now use it, reject invalid repository input early, and return
a consistent generic webhook failure payload.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:32:44 +02:00
Andras Bacsai 46180dbbf9 feat(webhook): skip deployment on [skip ci]/[skip cd] commit markers
Add DetectsSkipDeployCommits trait with two strategies: shouldSkipDeploy
(all commits must contain the marker) for push events, and
shouldSkipDeployAny (any single marker triggers skip) for PR/MR titles
and latest-commit signals.

Apply trait to Bitbucket, Gitea, GitHub, GitLab webhook controllers and
ProcessGithubPullRequestWebhook job. PRs pass pullRequestTitle through
to the job constructor for evaluation.
2026-04-29 09:12:24 +02:00
Andras BacsaiandClaude Opus 4.7 a2096c6f68 feat(observability): add structured audit log channel for API and webhook events
Introduce a dedicated `audit` log channel (daily rotation, configurable retention via
LOG_AUDIT_DAYS) and a small `auditLog()` / `auditLogWebhookFailure()` helper used to
record state-changing API operations and webhook events.

Instrumented:

- API mutation endpoints (create / update / delete / start / stop / restart) across
  applications, services, databases (incl. backups, env vars, storage), servers,
  projects + environments, scheduled tasks, private keys, GitHub apps, cloud provider
  tokens, Hetzner server provisioning, instance enable/disable.
- Webhook signature verification outcomes for GitHub, GitLab, Bitbucket, Gitea and
  Stripe, plus the Sentinel push endpoint.
- Authentication and authorization outcomes via the global exception handler and
  the `ApiAbility` middleware (unauthenticated, ability-denied, policy-denied).

The helper is wrapped in try/catch so logging failures never affect the request
path. Successful operations log at `info`; suspicious/denied requests log at
`warning`. Operators wanting a failures-only feed can set `LOG_AUDIT_LEVEL=warning`.

Includes a feature test suite covering the helper, the webhook providers and the
new auth/authorization log paths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 14:50:37 +02:00
Andras BacsaiandClaude Opus 4.7 bafb9a5a8b refactor(webhook): encrypt manual webhook secrets and tighten HMAC verification
- Auto-generate a 40-char random secret for each manual_webhook_secret_* column on Application creation so new apps are never left with an empty secret.
- Add encrypted cast for the four webhook-secret columns; backfill migration re-encrypts existing plaintext values and fills missing ones.
- Reject webhook deliveries when the stored secret is empty (GitHub, GitLab, Bitbucket, Gitea manual endpoints).
- Bitbucket: require the sha256 algorithm prefix on X-Hub-Signature instead of trusting the client-supplied algo.
- GitLab: drop the ?? '' fallback on the token comparison.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-19 12:52:23 +02:00
Andras Bacsai 1a603a10ed fix(models): replace forceFill/forceCreate with fill/create and add fillable guards
Replace all uses of `forceFill`, `forceCreate`, and `forceFill` with their
non-force equivalents across models, actions, controllers, and Livewire
components. Add explicit `$fillable` arrays to all affected Eloquent models
to enforce mass assignment protection.

Add ModelFillableCreationTest and ModelFillableRegressionTest to verify that
model creation respects fillable constraints and prevent regressions.
2026-03-31 13:45:31 +02:00
Andras Bacsai 1da1f32f0e refactor: use forceCreate() for internal model creation
Replace create() with forceCreate() across internal model creation operations to bypass mass assignment protection. This is appropriate for internal code that constructs complete model state without user input.

Add InternalModelCreationMassAssignmentTest to ensure internal model creation behavior is properly tested. Optimize imports by using shortened Livewire attribute references and removing unused imports.
2026-03-30 13:04:11 +02:00
Andras Bacsai 700550b26f Fix: Concurrent builds ignored & add deployment queue limit (#7488) 2025-12-11 11:03:02 +01:00
Andras BacsaiandClaude d019553809 Add Retry-After header to 429 rate limit responses
Adds Retry-After: 60 header to all deployment queue full responses,
helping webhook clients know when to retry their requests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 11:02:29 +01:00
Andras BacsaiandClaude d27070b215 fix: Add comprehensive PR cleanup to GitLab, Bitbucket, and Gitea webhooks
Create a shared CleanupPreviewDeployment action that unifies PR cleanup logic across all Git providers. Previously, GitHub had comprehensive cleanup (cancels active deployments, kills helper containers, removes all PR containers), while GitLab, Bitbucket, and Gitea only did basic cleanup (delete preview record and remove one container by name).

This fix ensures all providers properly clean up orphaned PR containers when a PR is closed/merged, preventing security issues and resource waste. Also fixes early return bug in GitLab webhook handler.

Fixes #2610

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 17:10:39 +01:00
Andras BacsaiandClaude 6d16f52143 Add deployment queue limit to prevent queue bombing
- Add configurable deployment_queue_limit server setting (default: 25)
- Check queue size before accepting new deployments
- Return 429 status for webhooks/API when queue is full (allows retry)
- Show error toast in UI when queue limit reached
- Add UI control in Server Advanced settings

Fixes #6708

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:52:27 +01:00
Andras BacsaiandClaude 158d54712f Remove webhook maintenance mode replay feature
This feature stored incoming webhooks during maintenance mode and replayed them
when maintenance ended. The behavior adds unnecessary complexity without clear
value. Standard approach is to let webhooks fail during maintenance and let
senders retry.

Removes:
- Listener classes that handled maintenance mode events and webhook replay
- Maintenance mode checks from all webhook controllers (Github, Gitea, Gitlab, Bitbucket, Stripe)
- webhooks-during-maintenance filesystem disk configuration
- Feature mention from CHANGELOG

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 13:36:32 +01:00
Andras Bacsai 5bdf2e8481 refactor(previews): move preview domain generation logic to ApplicationPreview model for better encapsulation and consistency across webhook handlers 2025-07-14 19:12:57 +02:00
Andras Bacsai d075241289 feat(Deployment): enhance queue_application_deployment to handle existing deployments and return appropriate status messages 2025-04-11 15:27:56 +02:00
Andras Bacsai 27e4882d57 feat(core): You can validate compose files with docker compose config
fix(core): labels are now accepted with both compose styles
refactor: remove lots of ray's
2025-02-27 11:29:04 +01:00
Islam Adel 672a5d0bc5 fix: Handle pullrequest:updated for reliable preview deployments
The repo:push payload lacks the destination branch name, using push.changes.0.new.name instead. While sufficient for updates, this causes failures in preview deployments when a PR receives new commits—Coolify looks for git_branch in the applications table but finds the source branch instead.

By also processing pullrequest:updated, we ensure preview deployments remain in sync. However, this event triggers on various actions (e.g., PR title changes, reviewer updates), causing extra redeploys. Since Coolify doesn’t store commit hashes for preview deployments, handling these extra redeploys is our best workaround for Bitbucket.
2025-02-01 12:24:23 +02:00
Lucas Michot d557a22b91 Remove all ray() calls 2024-10-28 13:51:23 +01:00
andrasbacsai 96c4f5b8da Fix styling 2024-07-25 11:31:59 +00:00
Andras Bacsai 6a4aa492c0 fix: random generated uuid will be full length (not 7 characters) 2024-07-25 13:31:01 +02:00
andrasbacsai 2e01665340 Fix styling 2024-06-12 10:21:47 +00:00
Andras Bacsai 019cdd2b3a fix: compose generator 2024-06-12 12:20:58 +02:00
Thijmen d86274cc37 Fix styling 2024-06-10 20:43:34 +00:00
Andras Bacsai c3da3f11d9 fix: Update error message for invalid token to mention invalid signature 2024-05-23 11:30:08 +02:00
Andras Bacsai 1e09b2bbd8 fix: use commit hash on webhooks 2024-05-15 10:44:45 +02:00
Andras Bacsai 54923b7640 feat: collect webhooks during maintenance 2024-03-01 14:04:29 +01:00