46 Commits
Author SHA1 Message Date
peaklabs-dev 32574d76b1 Merge remote-tracking branch 'origin/main' into next 2026-11-02 16:12:51 +01:00
Andras BacsaiandClaude Opus 5.5 bc855fdc68 fix(transfer): resolve IPv6-only server host names
The domain check of the transfer checklist resolved the server host name
with gethostbynamel(), which returns IPv4 only, so a domain that points to
an IPv6-only server was reported as pointing to another address. Resolve A
and AAAA records and compare normalized addresses. The Cloud SSH probe now
also resolves AAAA records when a host name has no A record.

Closes #12397

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:46:19 +01:00
github-actions[bot] 71f1c33bf1 Merge remote-tracking branch 'origin/main' into next 2026-10-28 11:27:20 +00:00
Andras Bacsai 2dcf8eeca3 fix(previews): keep production values for previews from before the upgrade
Public pull request previews no longer get production values, and no
preview falls back to production variables. Existing previews were
deployed with these values; for example, their databases were
initialized with the production password, so they broke on redeploy.

Previews that exist at the upgrade get keeps_production_values and
keep the earlier behavior. Previews created later do not. Server
transfer moves the flag.
2026-10-28 12:10:27 +01:00
62b2a99a70 chore: merge main into next (#12351)
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Co-authored-by: Aditya Tripathi <aditya@climactic.co>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 22:25:43 +01:00
fe6c73726d chore: merge main into next (#12344)
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Co-authored-by: Aditya Tripathi <aditya@climactic.co>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 20:25:53 +01:00
Andras Bacsai 1039368491 fix(s3): support virtual-hosted-style URLs for S3 storages
Add a "Use path-style URLs" setting to S3 storages. It is detected from
the endpoint (Alibaba OSS, Tencent COS, Volcengine/BytePlus TOS), and the
connection test switches to virtual-hosted style when the provider
rejects path-style requests. Backups pass `--path off` to mc.

Closes #10347
2026-10-27 15:53:16 +01:00
Andras Bacsai 1a2a5362ad fix(security): secure remote command secrets and clone volume data 2026-10-27 09:47:18 +01:00
Andras Bacsai 2be4f259b8 Merge remote-tracking branch 'origin/main' into automation/sync-main-to-next 2026-10-26 12:41:43 +01:00
Andras Bacsai 8eb33ddf31 Merge remote-tracking branch 'origin/next' into automation/sync-main-to-next 2026-10-26 12:12:20 +01:00
Andras Bacsai 7b83fa72eb feat(git): add HTTPS credentials for private repositories on custom Git hosts (#12328) 2026-10-26 10:50:24 +01:00
Andras BacsaiandClaude Opus 5.5 9db8d55473 feat(canvas): let admins drag server zones on the servers and dashboard canvases
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:13:29 +02:00
Andras BacsaiandClaude Opus 5.5 c6fbeb84eb Merge branch 'fix/server-transfer-cloud-hardening' into main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:25:28 +02:00
Andras BacsaiandClaude Opus 5.5 9e52c6a140 fix(server-transfer): accept legacy database port values and allow the kit VM network
- Do not check database port mappings in a bundle: the UI checks them
  only since March 2026, so older servers could not be transferred, and
  the values stay on the server owner's own host.
- The dev .env runs Cloud mode, where the import check refuses private
  addresses. reset.sh now allows the VM network of A on both instances.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:23:40 +02:00
Andras BacsaiandClaude Opus 5.5 cf9f254507 fix(server-transfer): close security holes in import, claim, and archives
Import:
- Check every uuid in a bundle against a strict id format before any
  write, and quote the SSH mux socket and key paths in local shell
  commands. A bundle uuid could run commands in the Coolify container.
- Validate bundle fqdns, git source URLs, paths, networks, cron
  expressions, and database ports; cap the number of items.
- Do not confirm that another team has a uuid.
- Refuse a project icon path with a uuid that is not a plain id.

Claim, finish, and migrate:
- Pass checklist step keys to wire:click with Js::from (stored XSS).
- Link only to https target server URLs.
- Validate target_instance_url in /transfer/complete; never prefill an
  unverified URL for a transfer back; scope the transfer-back token to
  write+deploy for 1 hour.
- Release on an owner marker only when it is newer than the own claim.
- Do not touch apps that only use the server as an additional
  destination when an archive is released or deleted.
- Give Sentinel a new token on claim.
- Add a checklist step to remove the previous instance's SSH key.
- Block a transfer while backups or scheduled tasks run.
- Authorize refreshMigration and PrivateKey checkConnection, clear
  tokens from Livewire state, hide migration log/error from members.

Archives:
- Refuse ip, user, port, private key, and Cloudflare tunnel changes.
- Throttle Enable management and require a free server slot for it and
  for a transfer back.
- Skip cloud provider calls.
- Re-read force_disabled before each SSH command, so running jobs stop.
- Probe the import check target at the resolved address only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:02:32 +02:00
Andras BacsaiandClaude Opus 5.5 7fa3110f0b feat(canvas): let admins drag project zones on the projects canvas
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 20:57:56 +02:00
Andras BacsaiandClaude Opus 5.5 95a3a22fdf fix(server-transfer): harden import on Cloud and stop archives from using server slots
- Rate limit the import check probe and refuse private, loopback, and
  link-local targets on Cloud.
- Rate limit the SSH validation that an import starts, like other
  server validations.
- Count only managed servers for the server limit, the limit check job,
  and the subscription page. Archives of transferred servers are left out.
- Do not show the name of another team's archived server in the import check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 20:12:59 +02:00
Andras Bacsai c454f84545 fix(server-transfer): keep imported data exact and guard archived servers
- Skip TrimStrings and ConvertEmptyStringsToNull on the import route; an empty shared variable failed the whole import
- Keep compose parser versions, static ports, legacy variable keys, and only the bundle's variables and destinations
- Give the transfer back token the deploy permission that the import needs
- Move the Cloudflare tunnel DNS record with the server and park it on the source
- Refuse cloud server deletes, power on, tunnel and DNS changes, and scp for archives; skip their backup alerts and provider polling
- Add a column-level round-trip test, archive guard tests, and a live full-coverage transfer test
- Advance the GitLab App sequence in the dev seeder
2026-10-22 15:52:20 +02:00
Andras Bacsai 0732e74553 fix(server-transfer): require deploy permission for import checks
Require write and deploy abilities on the import check endpoint, and clarify the target token permissions in transfer messages and UI.
2026-10-20 14:15:30 +02:00
Andras Bacsai cf71fda5c1 feat(gitea): add Gitea App sources and private repo deployments (#12234) 2026-10-19 21:58:30 +02:00
Andras BacsaiandClaude Opus 5.5 6806ed31fa feat(patches): save check results and run checks in a queued job
- server_settings gets patch_check_result (JSON), patch_check_error,
  patch_checked_at, and patch_check_frequency.
- The patches page shows the saved result and "Last checked" on load.
  "Check for updates" queues ServerPatchCheckJob (manual) instead of
  running SSH in the Livewire request. The job saves the result and
  broadcasts ServerPatchCheckFinished on the server team channel; the
  page reloads the saved result (with a 10 s poll as a fallback).
- A finished package update (callEventOnFinish) queues a new check on
  the server side, so the page no longer depends on the browser.
  ServerPackageUpdated is removed.
- The check frequency is a server setting (cron or preset, at most once
  per hour). Empty keeps the staggered weekly default.
- The failure notification is sent only when the state changes from ok
  to error, not on every check.
- Page access needs viewSecurity and every action needs update on the
  loaded server; a member gets 403. Updates accept only a package from
  the saved result.
- Server transfer: the frequency moves, the last result stays on the
  source (runtime).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:28:51 +02:00
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 448dc8ea0a feat(logging): strengthen secret redaction and add admin controls (#12151) 2026-10-13 20:43:19 +02:00
Andras Bacsai 83384a7b95 Merge remote-tracking branch 'origin/release/v4.5' into automation/sync-main-to-release-v4.5 2026-10-12 22:30:41 +02:00
Andras Bacsai 200af07225 Merge remote-tracking branch 'origin/release/v4.5' into automation/sync-main-to-release-v4.5 2026-10-12 21:38:45 +02:00
Andras BacsaiandClaude Opus 5.5 213a61b7ab fix(env): pass exact env values to containers, keep old escaping for existing variables (#12024)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:06:45 +02:00
Andras Bacsai 1e42284db0 feat(proxy): override the Traefik certificate resolver per resource
Applications and service applications can now use the server resolver,
no resolver ("none"), or a custom resolver name. This allows servers
that mix Let's Encrypt domains with domains that use their own
certificates, such as Cloudflare Origin CA. The setting is available in
the UI and the API.

Closes #12138
2026-10-11 19:01:27 +02:00
Andras Bacsai f39c884cc7 fix(servers): support IPv6 server addresses everywhere
Store server IPs in one form (no brackets, short lower-case IPv6) and
write each address in the form its context needs:

- URLs and host:port (Sentinel, database URLs, SFTP backup download,
  DNS servers, SMTP, webhook base URLs, links, health checks) get
  brackets through formatHostForUrl().
- Traefik Host() rules use the address without brackets, so IPv6
  domains no longer return 404; saved labels are fixed at deploy.
  Caddy keeps the brackets.
- SSH keeps the plain address.
- Hetzner gives an IPv6 /64 network; IPv6-only servers now get the
  server address (prefix::1) instead of the unusable prefix::64.
- sslip labels, registry image names with an IPv6 host, the API domain
  list, allowlist matching and duplicate checks handle IPv6.

A migration normalizes stored IPv6 server addresses, repairs Hetzner
servers saved as ::64 that are not reachable, and adds brackets to
saved Sentinel URLs.
2026-10-09 13:50:28 +02:00
Andras BacsaiandClaude Opus 5.5 d4d8bba514 docs(backups): add multi-destination S3 planning notes (#11789)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:10:34 +02:00
Andras Bacsai 0da202b39d fix: protect restores, preview imports, and analytics access 2026-10-05 17:02:56 +02:00
Andras Bacsai d1cf3e6ef1 fix(secrets): keep the secret manager source when cloning resources
Cloning an application, database, service or environment did not copy
the secret manager link, so variables with remote secret references
failed on the next deployment with "no secret manager source is
configured".

Clones now get a copy of the link when the integration token belongs to
the clone's team. Server transfer does not export integration tokens or
links; the export now warns which resources need the token and link
again on the target instance.
2026-10-01 07:16:45 +02:00
Andras Bacsai 8144b1cbc1 fix(transfer): keep SQLite volume links during server transfer
The server transfer bundle did not include the standalone_sqlite_id of
persistent volumes, so after an import an application's mount of a
SQLite data volume was no longer linked to the database. The shared
volume checks then failed: deleting the SQLite database, or the
application with its volumes, could remove the SQLite data.

The exporter now sends the SQLite database uuid with each volume, and
the importer links the volume again after all databases are imported
(with a warning when the database is not in the bundle). As a backstop,
StandaloneSqlite::deleteVolumes() skips volumes that another resource
uses, like Application already does.
2026-10-01 07:16:35 +02:00
Andras Bacsai 5921fb2958 fix(compose): keep name-only declaration for pre-existing volumes
Before Coolify kept `driver`, `driver_opts` and `labels` of renamed
Compose volumes, Docker created those volumes without them. Applying the
options now would make Docker Compose ask to recreate the volumes on
every deployment.

- Add `ignores_compose_driver_options` column to local_persistent_volumes
  and mark all volumes that exist at upgrade time
- Parsers now use composeRenamedVolumeDeclarationFor() so flagged volumes
  keep the old name-only top-level declaration
- Legacy application parsers (v1/v2) always emit name-only declarations
- Reset the flag when a volume is replicated, since a clone is a new
  Docker volume
- Include the flag in server transfer export/import; bundles without it
  default to true
- Storages UI shows which volumes ignore driver options and allows
  deleting them so the options apply on recreation
- Add tests for parsers, cloning and server transfer
2026-09-30 14:31:33 +02:00
Andras Bacsai a599c9e8b7 fix(server): keep data directory commands working for non-root SSH users
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
2026-09-29 20:46:54 +02:00
Andras BacsaiandClaude Opus 5.5 3d763c1577 refactor(server-transfer): always claim on import and drop remote claim file
Import now always claims the server and rebinds Sentinel. Remove the
SSH-written ownership file, the write_remote/rebind_sentinel/claim
options, and the POST /servers/{uuid}/claim endpoint. The migrator now
fails when the target cannot take management. Disabling management
records transfer.management_disabled so the server shows as
transferable, and the transfer and import pages are simplified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:56:11 +02:00
Andras Bacsai 4ab0e89e24 feat(server): add dev-only toggle for server management ownership
Add a Management ownership switch to the server page, shown only in
development, that lets a user with update permission release or claim
control of a server from this Coolify instance. Claiming is blocked for
localhost and when the team is over its server limit. Both actions are
recorded in the audit log.

When ServerTransferClaimer claims a server, it now clears force_disabled
if the team is within its server limit, and it always saves settings,
not only when the sentinel is rebound.
2026-09-28 12:14:56 +02:00
Andras BacsaiandClaude Opus 5.5 1712fb393a fix(transfer): reuse or create the private key in the target team only
The import looked up the key in all teams and stopped with "already exists
on another team", which also told the user that another team has the key.
Keys are unique per team, so reuse a key of the target team or create one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:02:19 +02:00
peaklabs-dev 5261785c69 Merge remote-tracking branch 'origin/next' into feat/add-sqlite-database 2026-09-25 22:47:29 +02:00
Andras Bacsai 5721266010 fix(server-transfer): allow local peer targets in development
Route localhost targets through host.docker.internal in containers while continuing to reject other private targets.
2026-09-24 21:28:52 +02:00
peaklabs-dev 2cb4c3b501 feat(database): support sqlite in migration, cloning and server transfer 2026-09-24 19:03:42 +02:00
Andras Bacsai 87685d1e09 chore: align control-plane behavior 2026-09-24 15:46:04 +02:00
Andras Bacsai 2a3061adf5 Keep server creation consistent across entry points 2026-09-24 08:06:25 +02:00
Andras Bacsai 383a5a742f feat(servers): add configurable deployment and build roles
Introduce deployment, build, and dual-purpose server roles, with API and UI support, build-server fallback controls, and role-aware resource hosting.
2026-09-19 17:22:13 +02:00
Andras Bacsai 424dbd36ff feat(sentinel): make sentinel mandatory on regular servers
Remove the enable/disable toggle from the server UI, logs page, and
Sentinel API so is_sentinel_enabled is derived and read-only. Enable
existing regular servers via migration, start Sentinel after validate-
and-install, and drop the daily ServerManagerJob restart.
2026-09-09 06:30:32 +02:00
Andras Bacsai f9caa5250d feat(servers): add cross-instance server migration (#11075) 2026-08-07 23:07:55 +02:00