Commit graph

727 commits

Author SHA1 Message Date
Andras Bacsai
0c6a233b27 fix(deployment): unregister Livewire morph hook on teardown
Store the morph.updated cleanup callback and invoke it during Alpine destroy so deployment log search hooks do not survive component teardown.
2026-05-26 14:57:20 +02:00
Andras Bacsai
b751628545 fix(database): normalize read/write host lists
Trim comma-separated database host values and fall back to DB_HOST or the default host when write hosts are empty. Add unit coverage for read/write host parsing.
2026-05-26 14:52:25 +02:00
Andras Bacsai
8e033c5bc3 fix(destination): promote networks atomically
Wrap destination promotion in a transaction so the main destination swap and additional network updates stay consistent. Add coverage for promoting an owned team network while preserving the previous main destination as an additional network.
2026-05-26 14:50:29 +02:00
Andras Bacsai
f44ace3965 fix(destination): validate network server pairing
Ensure destination attach and promote operations only accept networks that belong to the selected server, preventing mismatched same-team server/network pairs.
2026-05-26 14:48:36 +02:00
Andras Bacsai
097efd14ce fix(storage): clear stale disk usage cache
Forget cached storage threshold state when reported disk usage drops below the alert threshold, allowing future threshold crossings to dispatch a fresh storage check.
2026-05-26 14:45:49 +02:00
Andras Bacsai
43884823c6 chore(ssh): remove stale mux cleanup job
Drop the scheduled stale multiplexed connection cleanup job, its SSH mux
health/orphan config, and the tests that covered that cleanup path.
2026-05-26 14:40:38 +02:00
Andras Bacsai
b5be9fe9e8 fix(sentinel): lock push dedupe decisions
Guard Sentinel push hash checks and cache updates with a server-scoped atomic cache lock to prevent concurrent duplicate dispatches.
2026-05-26 14:12:56 +02:00
Andras Bacsai
7677fac2f5 fix(sentinel): validate push containers payload
Reject malformed sentinel push payloads before updating heartbeat state,
dispatching jobs, or writing deduplication cache entries.
2026-05-26 14:07:41 +02:00
Andras Bacsai
ed3780b2a7 fix(schedule): run stale multiplex cleanup on crons queue
Dispatch CleanupStaleMultiplexedConnections through the crons queue and
cover the scheduled job queue assignment with a feature test.
2026-05-26 13:51:22 +02:00
Andras Bacsai
ebf23f4874 fix(ssh): escape scp source and destination
Quote SCP operands when building commands to prevent shell injection through source or destination paths, and cover the escaping behavior in the SSH command injection tests.
2026-05-26 13:48:10 +02:00
Andras Bacsai
8a40c4e348 chore(sync-bunny): remove GitHub release sync paths
Drop the unused GitHub release and version sync options from sync:bunny,
leaving the command focused on BunnyCDN template, release, and nightly syncs.
Update the nightly test to assert it does not invoke gh or git.
2026-05-26 11:51:38 +02:00
Andras Bacsai
21db1fd374 fix(sync-bunny): sync nightly CDN files to nested paths
Write nightly versions and releases under json/nightly in the CDN repo, and cover both release and versions-only sync flows with feature tests.
2026-05-26 11:41:04 +02:00
Andras Bacsai
8e6e3551f3
fix(ui): improve configuration changes modal values, colors and spacing (#10365) 2026-05-26 11:09:54 +02:00
Andras Bacsai
27b76a4e97 Merge remote-tracking branch 'origin/next' into fix/form-state 2026-05-25 16:08:19 +02:00
Andras Bacsai
33e172ac24 fix(backups): revalidate S3 storage on scheduled backup submit
Check the selected S3 storage against the database at submit time so
stale Livewire state cannot schedule backups with storage that was
reassigned or marked unusable after the component mounted.
2026-05-23 21:06:22 +02:00
Andras Bacsai
a4d75ff0e2 fix(backups): validate S3 storage before backup scheduling
Prevent scheduled database backups from enabling S3 uploads without a valid team-owned storage configuration, and preserve the previous S3 storage ID in missing-storage error messages.

Add coverage for backup edit/create validation and S3 upload failure messaging.
2026-05-23 13:06:36 +02:00
Andras Bacsai
ffe8cfd76f fix(changelog): use configurable GitHub releases source
Default changelog pulls to the GitHub raw releases JSON and cover the
configured URL, file writing, and draft-release filtering with feature tests.
2026-05-22 18:39:37 +02:00
Andras Bacsai
a058786509 fix(ssh): remove mux first-use lock wrapper
Rely on OpenSSH lazy multiplexing directly for SSH and SCP commands,
removing the shell lock wrapper and related readiness checks.
2026-05-22 18:27:40 +02:00
Andras Bacsai
a13fb3cf00 fix(ssh): verify mux readiness before reusing socket
Use ssh -O check in the first-use mux lock flow so commands only reuse a multiplexed socket after the control master is actually ready.
2026-05-22 18:22:22 +02:00
Andras Bacsai
5c67766f41 fix(ssh): serialize initial mux connection creation
Wrap first-use SSH and SCP multiplexed commands with a lock to avoid racing while the control socket is created. Also detect native OpenSSH mux master process names during stale connection cleanup and cover both orphaned and duplicate mux processes with tests.
2026-05-22 18:17:37 +02:00
Andras Bacsai
54a020cf1b fix(ssh): rely on lazy multiplexed connections
Remove explicit SSH master pre-warming and lock handling so OpenSSH manages ControlMaster creation lazily from real ssh/scp commands. Add cleanup for duplicate mux processes and update coverage around mux command options and stale process cleanup.
2026-05-22 18:01:53 +02:00
ShadowArcanist
bd744eb8dd
fix(ui): configuration changes modal values, colors and spacing 2026-05-22 21:22:50 +05:30
Andras Bacsai
57d879263d fix(ssh): prevent orphaned multiplexed connections
Serialize multiplexed SSH master creation per server to avoid concurrent workers spawning orphaned processes. Enable scheduled cleanup for stale mux connections and add guarded orphan process reaping with tests.
2026-05-22 17:31:38 +02:00
Andras Bacsai
b35524bdf8 Merge remote-tracking branch 'origin/next' into improve-github-app-setup-flow 2026-05-22 17:04:47 +02:00
Andras Bacsai
182df1cb07 fix(logs): keep stream polling active without collapsible panel
Move log stream polling off the loading indicator so non-collapsible log panels continue polling while streaming, and cover the behavior with a Livewire feature test.
2026-05-22 17:00:08 +02:00
Andras Bacsai
5a7408a919 fix(github): improve GitHub App setup and installation flow
- resolve the GitHub App by a stable identifier during installation
  callbacks so installing and re-installing keeps working over the
  full lifetime of the App
- verify the installation id received from the callback against the
  GitHub API before persisting it
- support re-installing an already configured GitHub App instead of
  blocking it
- require an authenticated session and rate limit the setup callback
  routes
- extend manifest setup state validity to match GitHub's manifest
  code lifetime

Adds feature coverage for the GitHub App setup and installation
callbacks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 16:34:36 +02:00
Andras Bacsai
fcd63f40eb fix(queue): route scheduled jobs through crons helper
Centralize scheduled job queue selection with crons_queue() and use it for scheduler, task, and database backup jobs so cloud runs on crons while self-hosted stays on high.
2026-05-22 16:26:15 +02:00
Andras Bacsai
e2199f1223 fix(queue): route cloud jobs to dedicated queues
Use config-based queue selection for deployment and scheduled jobs so cloud dispatches deployments to `deployments` and scheduled jobs to `crons`, while self-hosted keeps using `high`.

Add coverage for deployment queue helper, start action routing, and scheduled job manager routing.
2026-05-22 16:11:24 +02:00
Andras Bacsai
809d9b21fa fix(webhook): match manual webhook repositories case-insensitively
Git hosts treat owner/repo names case-insensitively, but the exact
repository match used a case-sensitive comparison, so a payload whose
casing differed from the stored git remote would fail to match and
skip a legitimate deployment.

Lowercase both canonical repository paths before comparing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:59:20 +02:00
Andras Bacsai
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
00ce43a9d0
Refine service resource routing (#10358) 2026-05-22 13:40:18 +02:00
Andras Bacsai
beaad0a722 Refine service resource routing 2026-05-22 13:39:26 +02:00
Andras Bacsai
7f135e0f6d Harden token permission handling 2026-05-22 13:12:17 +02:00
Andras Bacsai
e9b8320d5f Fix source selection flow 2026-05-22 13:00:53 +02:00
Andras Bacsai
783344c875
fix(environment): scope DeleteEnvironment lookups to current team (#10349) 2026-05-22 12:57:57 +02:00
Andras Bacsai
59111e8cf3 fix(destination): scope server and network selection to current team
Resolve the server and network in Destination::addServer() and
::promote() through ownedByCurrentTeam() before use, authorize the
update against the resource, and pass the validated IDs into
attach()/detach()/update(). Errors are routed through handleError()
to match the sibling removeServer() method.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:53:14 +02:00
Andras Bacsai
36526928df feat(sentinel): deduplicate metrics push processing
Move Sentinel push handling into a controller and dispatch server update jobs only when container state changes or the force interval elapses. Add opt-in PostgreSQL read/write replica configuration and tune periodic proxy network and storage checks to reduce unnecessary work.

Add feature coverage for replica config, Sentinel push deduplication, deployment log scrolling, and server update job optimizations.
2026-05-22 12:48:48 +02:00
Andras Bacsai
df166ac689 fix(environment): scope DeleteEnvironment lookups to current team
Scope DeleteEnvironment::mount() and delete() lookups through
Environment::ownedByCurrentTeam() so an environment_id that belongs to
another team resolves to a 404 instead of loading the foreign record.
Mark $environment_id as #[Locked] so the public Livewire property can no
longer be reassigned from the client.

Add tests/Feature/DeleteEnvironmentTeamScopingTest.php covering mount,
delete, the #[Locked] guard, and the team-scoped helper for both the
cross-team and own-team cases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:37:48 +02:00
Andras Bacsai
5dda39e588 fix(source): scope private key and source selection to current team
The Source component now resolves the supplied private key and Git
source IDs through team-scoped queries before persisting them, so a
selection can only ever reference a resource owned by the current
team. The source type is additionally restricted to the supported
GitHub/GitLab app classes.

The privateKeyId property is marked #[Locked] so it can only change
through the dedicated handler rather than a direct property update.

Adds feature tests covering team-scoped selection of private keys and
Git sources.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:30:00 +02:00
Andras Bacsai
b124397613 fix(schedule): prevent duplicate SSL certificate regeneration
Run RegenerateSslCertJob on one server only and add coverage to ensure scheduled production jobs use onOneServer.
2026-05-21 19:19:43 +02:00
Aditya Tripathi
7a3fcd37d5 fix(livewire): scope DatabaseProxyStopped to proxy fields, harden status trait
Clickhouse, Dragonfly, and Keydb still called syncData() inside the
DatabaseProxyStopped broadcast handler, clobbering in-progress edits to
name/description/credentials. Refresh only is_public/public_port/
public_port_timeout instead, matching the pattern used elsewhere.

Also null-guard HasDatabaseStatusInfo::getListeners() against an absent
Auth::user()/currentTeam(), add explicit return types on getListeners()
and render(), and convert inline comments in the SSL refresh test to a
PHPDoc block.
2026-05-21 10:24:49 +00:00
Aditya Tripathi
e7e65831a7 fix(livewire): preserve wire:dirty across DB status broadcasts
The earlier refreshStatus fix kept user-typed values intact but Livewire still
absorbed deferred wire:model values into the snapshot on every broadcast-
triggered roundtrip, clearing the unsaved-changes indicator and making the form
look auto-saved. Move all status-derived display (DB URLs, SSL toggle/mode,
cert expiry) out of each DB General form into a sibling StatusInfo Livewire
component, so the form never roundtrips on broadcasts.

Shared scaffolding lives in App\Traits\HasDatabaseStatusInfo plus an x-database-
status-info Blade component, leaving each per-DB StatusInfo class as a ~20-50
line declaration of label, SSL mode options, and SSL save hooks. Parents
dispatch databaseUpdated from save methods so the sibling refreshes after writes.

Tests cover the architecture (no DB form subscribes to status broadcasts) and
the sibling's refresh-on-status-change behavior.
2026-05-21 08:31:08 +00:00
Aditya Tripathi
b9f773c1d9 fix(livewire): stop broadcast handlers from wiping in-progress form input 2026-05-20 19:04:43 +00:00
Andras Bacsai
65c0c92c02 fix(destinations): handle empty and server-scoped destinations
Build the global destinations list from actual destination records so empty
servers do not render duplicate empty states. Allow creating Docker destinations
for a selected team server outside the global usable list, authorize swarm
creation correctly, and store discovered swarm network names from the selected
network. Add feature coverage for empty states, selected-server mounting, and
swarm destination creation.
2026-05-19 12:50:08 +02:00
Andras Bacsai
fde500a347 fix(templates): require Docmost mail driver
Require MAIL_DRIVER to be set before Docmost starts and add a unit test to keep the compose template and generated service templates in sync.
2026-05-15 13:36:02 +02:00
Andras Bacsai
d1126c02a9 fix(deployments): filter generated compose service env vars
Exclude generated Docker Compose SERVICE_FQDN, SERVICE_URL, and SERVICE_NAME variables from runtime, build-time, and build arg environments so stale stored values cannot override generated service names for preview deployments.
2026-05-13 11:59:45 +02:00
Andras Bacsai
a54e70b4e0 fix(deployments): skip registry image tag for previews
Only push the configured Docker registry image tag for production deployments, and cover preview and missing-tag cases with unit tests.
2026-05-13 11:49:15 +02:00
Andras Bacsai
4ff3e4b2be
feat(deployments): track application configuration diffs (#10183) 2026-05-13 10:49:53 +02:00
Andras Bacsai
1522c510cf fix(api-tokens): mark expiration warning after notification
Ensure failed token expiration warning notifications do not persist the warning marker, allowing the job to retry later.
2026-05-13 10:28:32 +02:00
Andras Bacsai
df4d9f8069 fix(applications): use preview environment variable query
Call the preview environment variable relationship as a query when building the legacy configuration hash, and cover preview deployments with a regression test.
2026-05-13 10:28:18 +02:00
Andras Bacsai
3911a0305c fix(api-tokens): persist expiration warning state
Track when expiration warnings are sent on personal access tokens so repeated job runs or cache flushes do not send duplicate notifications.
2026-05-13 10:11:40 +02:00
Andras Bacsai
0ecd488d6a fix(applications): refresh pending configuration changes
Dispatch configuration change events after saving application source and advanced settings, and refresh the configuration checker before showing redeploy diffs.
2026-05-13 10:04:17 +02:00
Andras Bacsai
f8849aba73 feat(deployments): track application configuration diffs
Store deployment configuration snapshots on application deployment queues and compare them against the current application state. Surface grouped pending changes in the configuration checker and use build-impact diffs to decide when an existing image can skip the build step.
2026-05-13 09:58:58 +02:00
Andras Bacsai
63c2d31ca0 feat(applications): add configurable stop grace period
Add centralized stop grace period resolution for application settings and use it across manual stops, preview stops, and deployments. Validate the Livewire advanced setting against shared min/max constants and cover persistence, fillable creation, and fallback behavior with tests.
2026-05-11 23:43:53 +02:00
Andras Bacsai
d1220895d9 Merge remote-tracking branch 'origin/next' into feat/configurable-stop-grace-period 2026-05-11 23:20:31 +02:00
Andras Bacsai
6f3bb47682
fix(applications): decode custom nginx API payloads (#10067) 2026-05-11 22:24:55 +02:00
Andras Bacsai
a42613168d fix(applications): store custom nginx config from API correctly
Decode base64 custom_nginx_configuration before model assignment so it is not double-encoded, and allow null values when clearing the setting. Add API coverage for create, update, invalid input, and clearing behavior.
2026-05-11 22:22:01 +02:00
Andras Bacsai
9bb40f3ccb fix(deployment): avoid shared preview tags for HEAD commits
Use the deployment UUID when preview deployments are built from HEAD so each deployment gets distinct production and build image tags.
2026-05-11 22:11:08 +02:00
Andras Bacsai
2253c40e01 fix(deployment): include commit in preview image tags
Generate pull request preview image tags with both the PR id and commit
so different commits on the same PR do not reuse the same image tag. Sanitize
and truncate generated tags to stay within Docker tag limits.
2026-05-11 22:05:07 +02:00
Andras Bacsai
ab1958d741 fix(railpack): fail fast when buildx is unavailable
Require Docker buildx before Railpack builds, normalize environment
variable keys before validation, and align private deploy key API docs with
the supported dockerfile build pack.
2026-05-11 17:31:29 +02:00
Andras Bacsai
0395db30f0 fix(railpack): align example ports and smoke checks
Update Railpack seed examples to use the expected Flask start command and Go/Rust exposed ports. Adjust smoke coverage to run Symfony by default and accept reachable 4xx responses, and extend seeder tests for per-example branch and port assertions.
2026-05-11 17:13:55 +02:00
Andras Bacsai
0f904d792b Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-11 17:03:25 +02:00
Andras Bacsai
ff149b8daa fix(stripe): ignore missing subscriptions in webhook jobs
Avoid failing Stripe webhook processing when local subscriptions are missing, and cover ignored invoice/payment/subscription events with feature tests.
2026-05-11 16:56:00 +02:00
Andras Bacsai
db7d0f0bfb Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-11 16:26:50 +02:00
Andras Bacsai
d96e253230 fix(ui): align deployment indicator with collapsed sidebar
Move the deployments indicator inside the app layout state scope so it can react to the sidebar collapsed state, and add a layout test covering the responsive positioning.
2026-05-11 16:25:15 +02:00
Andras Bacsai
b5ff124446 fix(env): validate Docker-compatible variable keys
Add shared environment variable key validation and normalization for Livewire forms and models, allowing Docker-compatible keys while rejecting invalid entries such as keys containing equals signs. Also quote Railpack build environment and secret arguments safely.
2026-05-11 15:43:09 +02:00
Andras Bacsai
d5946dcfca fix(railpack): include scoped env vars in builds
Build Railpack variables from generic build-time vars plus Railpack-specific vars, filter unrelated buildpack control vars, and ensure curl/wget deploy apt packages are present. Add coverage for standard and preview deployments.
2026-05-11 13:29:21 +02:00
Andras Bacsai
6ee75cfa65 fix(api): remove deprecated docker compose application endpoint
Drop the unstable applications/dockercompose route and controller path now that
service creation is handled by POST /api/v1/services. Add coverage to ensure the
deprecated endpoint stays unregistered while the services endpoint remains
available.
2026-05-11 13:20:05 +02:00
Andras Bacsai
9f380b8495 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-11 10:58:13 +02:00
Andras Bacsai
c6ac52dc38 fix(env): generate encoded secrets from raw random bytes
Use random_bytes before hex and base64 encoding so generated env values
match the expected decoded byte lengths. Add Pest coverage for HEX and
REALBASE64 magic variables.
2026-05-09 14:49:39 +02:00
Andras Bacsai
fe934dd139 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-06 14:33:22 +02:00
Andras Bacsai
29d41ba041 Merge remote-tracking branch 'origin/next' into 9916-investigate-undefined-relationship 2026-05-06 14:32:16 +02:00
Andras Bacsai
45f65481e6 fix(mcp): change enable/disable endpoints from GET to POST and fix service/app listing
- `/mcp/enable` and `/mcp/disable` now use POST (state-mutating ops)
- `ListServices` queries DB directly instead of loading all projects into memory
- `ListApplications` validates tag arg rejects empty string (not just falsy)
2026-05-05 22:07:58 +02:00
Andras Bacsai
22a2c05a1d test(railpack): add API, Livewire UI tests and e2e smoke script
Add feature tests covering railpack build pack via REST API and
Livewire UI components, plus a bash smoke test that deploys seeded
railpack-* example apps against the local dev stack and verifies
COOLIFY_*, SOURCE_COMMIT, and RAILPACK_* env vars land correctly.
2026-05-05 15:32:43 +02:00
Andras Bacsai
1849b5903e refactor(scheduled-task): simplify server() with nullsafe operators and add return type
Replace nested null checks with nullsafe operator chains, add ?Server
return type, drop unreachable database branch, and cover all paths with
feature tests.
2026-05-04 12:26:15 +02:00
Andras Bacsai
b6ca6b1b20 feat(railpack): expose COOLIFY_* vars at build time and generalize buildpack control flag
Mirrors Nixpacks behavior: inject COOLIFY_* and SOURCE_COMMIT into
railpack build variables so apps (e.g. SPAs baking public URLs) can
read them via /run/secrets/<KEY>.

Rename is_nixpacks → is_buildpack_control to cover both NIXPACKS_ and
RAILPACK_ prefixed keys. Update the env variable view and appends list
accordingly.

Promote generate_coolify_env_variables to protected for testability.
2026-04-30 18:31:41 +02:00
Andras Bacsai
ace643d3d8 fix(railpack): query buildtime env vars directly instead of via computed attribute
Replace `railpack_environment_variables_collection()` helper (which returned
pre-filtered Eloquent attribute collections) with inline queries on
`environment_variables()` / `environment_variables_preview()` filtered by
`is_buildtime`. This ensures Railpack build variables are sourced from the
same query path as the rest of the deployment pipeline and avoids relying on
a now-removed accessor that silently included all railpack vars regardless of
build context.
2026-04-30 16:38:58 +02:00
Andras Bacsai
ec71d33f5e fix(railpack): pin frontend image version via config constant
Remove RAILPACK_FRONTEND_IMAGE env var from helper Dockerfile and resolve
the image ref at runtime using a new `railpack_version` constant in config.
Eliminates Docker build-time env interpolation for BUILDKIT_SYNTAX arg.
2026-04-30 16:27:08 +02:00
Andras Bacsai
a51f114a70 fix(standalone-docker): include keydb, dragonfly, clickhouse in databases()
Add missing DB types to StandaloneDocker::databases() concat chain and
cover all 8 standalone database types with feature tests.
2026-04-30 15:01:48 +02:00
Andras Bacsai
79174b749d refactor(helpers): extract STANDALONE_DATABASE_MODELS registry, add tests
Replace 8× repeated per-type if-blocks in `queryDatabaseByUuidWithinTeam`
and `queryResourcesByUuid` with a single loop over the new
`STANDALONE_DATABASE_MODELS` constant.

Add unit tests to guard the registry against drift (keys mirror
`DATABASE_TYPES`, every entry is a valid Eloquent model with `team()`),
and feature tests covering team-ownership, wrong-team, and unknown-UUID
cases for `queryDatabaseByUuidWithinTeam`.
2026-04-30 14:48:48 +02:00
Andras Bacsai
0f830b31f3 Merge remote-tracking branch 'origin/next' into mcp-server-instance-toggle 2026-04-30 14:48:35 +02:00
Andras Bacsai
8e91d627a3 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-30 11:47:06 +02:00
Andras Bacsai
f9b3f89757 Merge remote-tracking branch 'origin/next' into suppress-horizon-job-failures 2026-04-30 11:42:52 +02:00
Andras Bacsai
d057ce5172 Merge remote-tracking branch 'origin/next' into mcp-server-instance-toggle 2026-04-30 11:30:45 +02:00
Andras Bacsai
4575106f53 feat(sentinel): embed server UUID in encrypted sentinel token
Replace random string with encrypted JSON payload containing
server_uuid, binding token to its server for validation.
Remove double-encrypt test no longer relevant to new token format.
2026-04-30 08:21:30 +02:00
Andras Bacsai
00d6e83e7f fix(sentinel): auto-regenerate invalid or undecryptable tokens
Replace hard validation error with self-healing token logic. Tokens that
are null, empty, or fail decryption are now regenerated automatically
rather than crashing sentinel startup or metrics reads.

Token format changed from encrypted JSON payload to a plain 64-char
random string (Str::random), eliminating double-encryption issues and
simplifying the validation regex to cover the new character set.

New `ensureValidSentinelToken()` method on ServerSetting centralises
the get-or-regenerate contract; both StartSentinel and HasMetrics now
delegate to it. HasMetrics logs a warning when regeneration occurs so
operators know a sentinel container restart is required.

`isValidSentinelToken()` now accepts `?string` (null → false).

Adds feature tests covering: null/empty/undecryptable stored values,
idempotent return of valid tokens, RuntimeException only when
regeneration itself produces an invalid token, no double-encryption of
newly generated tokens, and cast round-trip consistency.
2026-04-29 16:44:12 +02:00
Andras Bacsai
fc3ce85f88 feat(horizon): suppress failed job entries for deployment/timeout errors on cloud
On cloud, DeploymentException and TimeoutExceededException are expected
failure modes that pollute the Horizon failed jobs UI. Listen to JobFailed
events and scrub the entry via JobRepository::deleteFailed so operators
are not alerted for noise failures. Self-hosted instances are unaffected.
2026-04-29 15:40:01 +02:00
Andras Bacsai
b8e311622a Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-29 15:22:47 +02:00
Andras Bacsai
6d1d699595 fix(deployments): resolve commit from app git_commit_sha when not explicitly set
Change `commit` param from `string 'HEAD'` default to `?string null`, then
resolve priority: explicit param > app `git_commit_sha` > `'HEAD'` fallback.

Add feature tests covering all four resolution paths.
2026-04-29 10:59:32 +02:00
Andras Bacsai
7ab16ad7b5 feat(mcp): add MCP server with read-only tools for Coolify resources
Add Model Context Protocol server exposing Coolify infrastructure data
to AI assistants. Includes tools for listing/fetching servers, projects,
applications, databases, and services, scoped to authenticated team tokens.

- Add CoolifyServer with 10 read-only tools (list/get for all resource types)
- Add BuildsResponse and ResolvesTeam traits for shared tool logic
- Add EnsureMcpEnabled middleware guarding /mcp routes
- Add enable/disable MCP API endpoints (root-only)
- Add is_mcp_server_enabled toggle in instance settings and advanced UI
- Add migration for is_mcp_server_enabled column
- Add feature tests for MCP endpoints and toggle API
- Scrub sensitive keys (passwords, tokens, raw IDs) from all responses
2026-04-29 10:30:43 +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 Bacsai
9717d9ff5a Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-29 08:56:23 +02:00
Andras Bacsai
eaaf258f25 fix(service): block UI editing of file volumes exceeding 5 MiB
Large host files mounted via Docker volumes caused the storages page to
become unusable — full file content was stored in the encrypted mediumText
column and serialised into the Livewire payload, crashing the browser.

- Add MAX_CONTENT_SIZE (5 MiB), BINARY_PLACEHOLDER, and TOO_LARGE_PLACEHOLDER
  constants to LocalFileVolume
- Check remote file size via stat/wc before cat in loadStorageOnServer and
  saveStorageOnServer; store placeholder instead of content when limit exceeded
- Expose is_too_large computed attribute (appended for Livewire serialisation)
- Guard submit, instantSave, and syncData in FileStorage Livewire component
- Truncate oversized content in Storage::refreshStorages to prevent payload bloat
- Show distinct warning banner in file-storage blade; mark textarea readonly and
  hide Save/Convert buttons for too-large files
- Add unit tests covering constants, computed flags, and toArray serialisation

Fixes #4701
2026-04-28 22:36:56 +02:00
Andras Bacsai
19994a0a13 test(api): add feature tests for server connection_timeout API
Tests cover PATCH update success, out-of-range, above-max, and
non-integer validation for the connection_timeout field.
2026-04-28 22:20:15 +02:00
Andras Bacsai
6293b14586 feat(server): add configurable SSH connection timeout per server
Add `connection_timeout` field to server settings, allowing per-server
override of the global SSH connection timeout constant.

- Migration adds `connection_timeout` integer column (default 10s)
- `ServerSetting` model exposes and casts the new field
- `SshMultiplexingHelper::getConnectionTimeout()` resolves per-server
  value with fallback to `constants.ssh.connection_timeout`
- All SSH/SCP command builders use the new resolver instead of the
  global config directly
- Livewire `Show` component binds `connectionTimeout` with validation
  (1–300 seconds) and syncs to/from the model
- UI input added to server settings form with helper text
- Feature tests cover default, persistence, resolver, and fallback
2026-04-28 15:39:36 +02:00
Andras Bacsai
b8226be774 refactor(server): dispatch event for reachability notifications, drop retry loop
Move reachability notification triggering out of isReachableChanged into
a dedicated ServerReachabilityChanged event dispatched by
ServerConnectionCheckJob. Remove the blocking 3-attempt sleep loop from
isReachableChanged — unreachable_count threshold alone now gates the
Unreachable notification. Add feature and unit tests covering all
notification dispatch paths.
2026-04-28 15:28:22 +02:00
Andras Bacsai
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 Bacsai
b3339d1034 feat(railpack): add buildpack control var filtering and dev seeder
Extract NIXPACKS_/RAILPACK_ prefix filtering into a reusable
`scopeWithoutBuildpackControlVariables` query scope on EnvironmentVariable.
Apply scope consistently to runtime vars, runtime preview vars, and
buildtime var generation in ApplicationDeploymentJob.

Refactor `generate_railpack_env_variables` to return a Collection.
Add `RAILPACK_FRONTEND_IMAGE` constant and bake it into the
coolify-helper Dockerfile as a build arg.

Add DevelopmentRailpackExamplesSeeder (dev/local env only) for
seeding example Railpack apps, wired into DatabaseSeeder.

Add tests:
- ApplicationDeploymentControlVarFilteringTest: verifies control vars
  are excluded from runtime and buildtime envs
- DevelopmentRailpackExamplesSeederTest: verifies seeder behavior
- ApplicationDeploymentRailpackEnvParityTest: parity checks for env
  handling across build/runtime paths
2026-04-28 14:37:31 +02:00
Andras Bacsai
5cef7cc092 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-28 14:36:54 +02:00
Andras Bacsai
cabcd8f699 fix(terminal): add idle timeout, reconnect replay, and scrollback preservation
- Kill PTY and notify client after 30 min of inactivity (IDLE_TIMEOUT_MS)
- Buffer client messages during async auth/IP fetch to prevent race-condition
  message loss on fast reconnects
- Replay last sent command after transient reconnect so PTY respawns without
  user interaction
- Preserve scrollback on disconnect/reconnect; write visible timestamp markers
  instead of wiping term state
- Handle idle-timeout sentinel on client with user-facing error message
2026-04-28 12:26:31 +02:00