- Require write access on the target environment to clone or move a resource
- Check read access on shared variables before a reference is added or resolved
- Limit team credentials, git sources, and imports of other backups to team-wide writers
- Require the delete level for backup, volume, storage, and task deletes
- Require create access for previews, new projects, and git sources
- Use the token team for the access scope, and check team-wide access on Livewire updates
- Require instance admin to toggle the API and MCP server
- Hide server pickers and broadcast details from members without access
Sentry self-hosted (getsentry/self-hosted 26.8.0) could not be deployed
as a Docker Compose application. Three separate problems blocked it:
- YAML collection aliases: the first fix raised the limit to 256 only in
Application::oldRawParser(). The safety check added in v4.4.0
(validateDockerComposeForInjection) and all other Compose parse calls
still used the Symfony default of 128, so the Sentry file (133 aliases)
failed with "Maximum number of collection aliases (128) exceeded".
Add parseDockerComposeYaml() and use it for every Compose parse.
- Argument list too long: the deployment job sent the generated Compose
file as base64 inside the SSH command. Linux limits one argument to
128 KiB, and the Sentry file is about 370 KB. execute_remote_command()
now accepts an 'input' key that streams content over SSH stdin, and
the job writes the Compose file with it.
- A list-style build arg without a value (build.args: [SENTRY_IMAGE])
merged into a map environment kept its numeric key, so Docker Compose
rejected the file with "non-string key in ...environment: 0". It now
becomes NAME with no value, as in Compose.
Closes#11725
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
A renamed template keeps its old key as an alias, so API callers and
services stored with the old key still find the template.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Write remote secret values as exact dotenv literals in the service .env
file and escape "$" where they go directly into a generated compose file
(environment, start commands, healthchecks).
- Resolve remote secrets before a service or database restart stops the
running resource, and show the secret manager error instead of a generic
start failure (new RemoteSecretException).
- Cache fetched key names for the autocomplete and rate limit how often a
user can contact the secret manager.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A non-root SSH user cannot open redirects, expand globs, or cd into
/data/coolify (9999:root 0700). Several remote commands relied on that
and failed on non-root servers.
- Write README files with `tee` instead of shell redirects in database
starts and application deployments
- Clear Postgres init scripts with `find` instead of a glob
- Split the proxy config backfill if/else so each branch gets sudo
- Start the log drain with `docker compose -f` instead of `cd`
- Wrap the preserved-repository compose start in `sh -c` for non-root
- Stage clone archives outside /data/coolify via StagesCloneArchives
- Extend the sudo parser and add non-root command tests
Switching an external volume from the old <uuid>_<name> volume to the
declared external volume on redeploy could make an app look as if it
lost its data (for example a database that initializes a new, empty
data directory).
- If a resource already has the storage entry with the old generated
name, the parsers keep using that volume and show a warning in the
deployment log and the service start log, with the steps to switch.
- Without that entry (new resources, or external volumes added later)
the external volume is used as declared.
- Deleting the old storage entry (storage page) switches to the
external volume on the next deployment; the storage entry shows a
note about it.
- Legacy Compose applications (parser versions 1 and 2) never stored
their volumes, so they keep the old volume names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 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
Add Doppler, Infisical, and Vault integrations with per-resource secret links, autocomplete, and deploy-time resolution for applications, services, and databases without persisting remote values.
Register the jean-server compose template, logo, and catalog entries,
and expose token and allowed-origins settings on the service form.
Sort extra fields by sortOrder and omit empty service-name prefixes.
Surface unset required service env vars in the configuration checker
popup and sidebar, refresh on env updates, and keep the env table
horizontally scrollable with correct managed/hardcoded pagination order.
Flagged domains are served with X-Robots-Tag: noindex, nofollow via
Traefik and Caddy routing labels, so an auto-generated technical domain
can be excluded from indexing while the production domain on the same
resource stays indexable.
Privileged API tokens can read hidden resource fields in environment and
resource responses, including instance-admin team tokens with team_id 0.
Configuration hashes now include hidden environment variable values so
secret edits trigger restart detection.