Service compose and .env content was sent inline in the SSH command.
Linux limits one argument to 128 KiB, so a service with a generated
compose over about 96 KB failed to save or start with "Argument list
too long".
- Add instant_remote_write_file(), which streams content to a remote
tee over SSH stdin (sudo tee for non-root SSH users)
- Add SshMultiplexingHelper::generateSshStdinCommand() with the same
SSH options as generateSshCommand()
- Write the service compose and .env with the new helper
Server certificates now use a prime256v1 (P-256) EC key. The CA keeps
secp521r1. BoringSSL-based Electron clients such as MongoDB Compass
cannot use a P-521 server key.
Add a feature test that checks the CA stays on P-521 and the server
certificate uses P-256. It also checks that the server key matches its
certificate and that the CA signature verifies.
- Regenerate SSL Certificates now writes server.crt/server.key for every
engine except MongoDB, which keeps the combined server.pem. Before, the
button always wrote server.pem, so Postgres, MySQL, MariaDB, Redis, KeyDB
and Dragonfly failed to start after a regenerate.
- The certificate renewal job uses the same rule, so MongoDB no longer
switches to server.crt/server.key on renewal and fails on restart.
- Starting an SSL database writes the CA that signs its certificate to
/data/coolify/ssl/coolify-ca.crt, so a stale CA file (for example one
written by another server entry for the same host) no longer causes
"certificate signature failure".
- Saving a custom CA certificate that does not match the stored CA
private key is rejected.
- The CA file write commands live in SslHelper::caCertificateFileCommands().
Fixes#10388Fixes#6771Fixes#11926
SSH: sshd runs the remote command with the user's login shell, which
can be fish or csh/tcsh. Those shells cannot parse POSIX `if ... fi`, so
the bash/sh fallback wrapper now runs inside `sh -c "..."`. Unit tests
run the wrapper under every login shell that is installed and check that
it stays one simple sh command.
Secret managers: the SecretManagerLinks component now lists and resolves
tokens by the resource's team instead of the session team. A team switch
in another tab can no longer link a token from a different team.
SecretManagerLink::fetchSecrets() also throws when the linked token does
not belong to the resource's team, so no request is sent with it.
Also adds a lesson note: remove the SSH mux file before live SSH or
login-shell tests.
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.
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.
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.
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.
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
- Log warnings instead of silently failing when chmod 0600 fails
- Remove redundant refresh() call before SSH key validation
- Remove storeInFileSystem() call from updatePrivateKey() transaction
- Remove @unlink() of lock file after filesystem store
- Refactor unit tests to use real temp disk and anonymous class stub
instead of reflection-only checks
The root cause of sporadic "Permission denied (publickey)" errors was
that validateSshKey() only checked if the key file existed on disk,
never verifying its content matched the database. When keys were rotated
or updated, the stale file persisted and SSH used the wrong key.
Changes:
- validateSshKey() now refreshes key from DB and compares file content
- Server saved event detects private_key_id changes to invalidate mux
- PrivateKey storeInFileSystem() uses file locking to prevent races
- PrivateKey saved event auto-resyncs file on key content changes
- Enforces 0600 permissions on key files
Fixescoollabsio/coolify#7724
When multiple scheduled tasks or database backups run concurrently on
the same server, they compete for the same SSH multiplexed connection
socket, causing race conditions and SSH exit code 255 errors.
This fix adds a `disableMultiplexing` parameter to bypass SSH
multiplexing for jobs that may run concurrently:
- Add `disableMultiplexing` param to `generateSshCommand()`
- Add `disableMultiplexing` param to `instant_remote_process()`
- Update `ScheduledTaskJob` to use `disableMultiplexing: true`
- Update `DatabaseBackupJob` to use `disableMultiplexing: true`
- Add debug logging to track execution without multiplexing
- Add unit tests for the new parameter
Each backup and scheduled task now gets an isolated SSH connection,
preventing contention on the shared multiplexed socket.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore(version): update coolify-realtime to version 1.0.9 in docker-compose and versions files
* feat(migration): add is_sentinel_enabled column to server_settings with default true
* fix(migration): update default value handling for is_sentinel_enabled column in server_settings
* feat(seeder): dispatch StartProxy action for each server in ProductionSeeder
* feat(seeder): add CheckAndStartSentinelJob dispatch for each server in ProductionSeeder
* fix(seeder): conditionally dispatch CheckAndStartSentinelJob based on server's sentinel status
* feat(seeder): conditionally dispatch StartProxy action based on proxy check result
* refactor(ui): terminal
* refactor(ui): remove terminal header from execute-container-command view
* refactor(ui): remove unnecessary padding from deployment, backup, and logs sections
* fix(service): disable healthcheck logging for Gotenberg (#6005)
* fix(service): Joplin volume name (#5930)
* chore(version): update coolify version to 4.0.0-beta.420 and nightly version to 4.0.0-beta.421
* fix(server): update sentinelUpdatedAt assignment to use server's sentinel_updated_at property
* feat(service): update Changedetection template (#5937)
* chore(service): changedetection remove unused code
* fix(service): audiobookshelf healthcheck command (#5993)
* refactor(service): update Hoarder to their new name karakeep (#5964)
* fix(service): downgrade Evolution API phone version (#5977)
* feat(service): add Miniflux service (#5843)
* refactor(service): karakeep naming and formatting
* refactor(service): improve miniflux
- improve DB url
- add depends_on
- formatting, naming & order
* feat(service): add Pingvin Share service (#5969)
* fix(service): pingvinshare-with-clamav
- add platform to make clamav work
- formatting
* feat(auth): Add Discord OAuth Provider (#5552)
* feat(auth): Add Clerk OAuth Provider (#5553)
* feat(auth): add Zitadel OAuth Provider (#5490)
* Update composer.lock
* fix(ssh): scp requires square brackets for ipv6 (#6001)
* refactor(core): rename API rate limit ENV
* refactor(ui): simplify container selection form in execute-container-command view
* chore(service): Update Evolution API image to the official one (#6031)
* chore(versions): bump coolify versions to v4.0.0-beta.420 and v4.0.0-beta.421
* fix(github): changing github app breaks the webhook. it does not anymore
* feat(service): enhance service status handling and UI updates
* fix(parser): improve FQDN generation and update environment variable handling
* fix(ui): enhance status refresh buttons with loading indicators
* fix(ui): update confirmation button text for stopping database and service
* fix(routes): update middleware for deploy route to use 'api.ability:deploy'
* fix(ui): refine API token creation form and update helper text for clarity
* fix(ui): adjust layout of deployments section for improved alignment
* chore(dependencies): update composer dependencies to latest versions including resend-laravel to ^0.19.0 and aws-sdk-php to 3.347.0
* refactor(email): streamline SMTP and resend settings logic for improved clarity
* fix(ui): adjust project grid layout and refine server border styling for better visibility
* fix(ui): update border styling for consistency across components and enhance loading indicators
* feat(cleanup): add functionality to delete teams with no members or servers in CleanupStuckedResources command
* refactor(invitation): rename methods for consistency and enhance invitation deletion logic
* refactor(user): streamline user deletion process and enhance team management logic
* fix(ui): add padding to section headers in settings views for improved spacing
* fix(ui): reduce gap between input fields in email settings for better alignment
* fix(docker): conditionally enable gzip compression in Traefik labels based on configuration
* fix(parser): enable gzip compression conditionally for Pocketbase images and streamline service creation logic
* fix(ui): update padding for trademarks policy and enhance spacing in advanced settings section
* feat(ui): add heart icon and enhance popup messaging for sponsorship support
* feat(settings): add sponsorship popup toggle and corresponding database migration
* fix(ui): correct closing tag for sponsorship link in layout popups
* fix(ui): refine wording in sponsorship donation prompt in layout popups
* fix(ui): update navbar icon color and enhance popup layout for sponsorship support
* Update resources/views/livewire/project/shared/health-checks.blade.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Update app/Livewire/Subscription/Index.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* fix(ui): add target="_blank" to sponsorship links in layout popups for improved user experience
* fix(models): refine comment wording in User model for clarity on user deletion criteria
* Update app/Providers/RouteServiceProvider.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* fix(models): improve user deletion logic in User model to handle team member roles and prevent deletion if user is alone in root team
* fix(ui): update wording in sponsorship prompt for clarity and engagement
---------
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com>
Co-authored-by: Carsten <BanditsBacon@users.noreply.github.com>
Co-authored-by: Alberto Rizzi <48057685+albertorizzi@users.noreply.github.com>
Co-authored-by: Jonas Klesen <deklesen@gmail.com>
Co-authored-by: Stew Night. <22344601+stewnight@users.noreply.github.com>
Co-authored-by: Jeffer Marcelino <jeffersunde72@gmail.com>
Co-authored-by: Lucas Eduardo <lucas59356@gmail.com>
Co-authored-by: CrazyTim71 <118295691+CrazyTim71@users.noreply.github.com>
Co-authored-by: Yassir Elmarissi <yassir.elmarissi@hm.edu>
Co-authored-by: Hauke Schnau <hauke@schnau-lilienthal.de>
Co-authored-by: Darren Sisson <74752850+djsisson@users.noreply.github.com>
Co-authored-by: Alkesh Das <67038642+smad-bro@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- set default country to XX
- fix array handling of the subjectAlternativeNames so that no indexes are added or skipped
- add extendedKeyUsage to server certs to make them more secure
- add keyAgreement to server certs
- remove authorityKeyIdentifier as it caused the following issue: unable to get local issuer certificate
- removed duplicated distinguished_name entries
- improved formatting
- rename some variables for better clarity
- format subjectAltNames correctly
- setup extensions more securely and improve them a lot
- use finally block to remove tempConfig
- If SSL is disabled, delete the SSL crt and file mounts in the DB
- If SSL is disabled, delete the SSL folder
- If SSL is enabled, make sure the file mounts are added inside the helper
- remove old file mounts first to make sure the ssl crt content is always up to date and no duplicates are added
- add default state and country
- rename parameters for more clarity
- set subjectAltName
- delete old certificate before creating new one
- Set CN and subjectAltNames in DB for automatic renewal
- improve function parameters
- set default validity to 1 year as resources need to be manually restarted to use the new certificates
- use the CA cert to sign certificates
- improve security by making certificates valid for only 90 days instead of 10 years
- add SubjectAltName
- remove unnecessary parameters
- use carbon immutable to make sure expiration date stays the same