- Database variants: use the same database name in Forgejo and the database
container (`forgejo` by default); Postgres stayed unhealthy and MySQL/MariaDB
installs failed with access denied.
- SSH: publish ${FORGEJO_SSH_PORT:-22222} and set SSH_PORT, DOMAIN and
SSH_DOMAIN, so clone URLs are correct and several instances fit on a server.
- Runner variants: start Forgejo from /usr/bin/s6-svscan, lock the install
with a generated admin, register runner 13.2.0 with a generated shared
secret, and enable the templates.
Closes#11924
oldRawParser made the bind directory of a long-syntax source like
../data at {workdir}./data, next to the path that Docker Compose uses.
Resolve the source with replaceLocalSource(), as the compose parsers do,
so Coolify makes the directory that the container mounts. A source that
resolves above / now stops the deployment before remote work.
Closes#4055
ServiceParserReferenceTest parses reference fixtures for serviceParser and
applicationParser (one service per feature, with setting variations and error
cases) and every template, and compares the output with expected files.
scripts/parser-snapshot-diff shows how a code change alters the output of all
cases (save / baseline). Template expected files are gitignored.
A service that declares SERVICE_FQDN_X_PORT while the named service declares
SERVICE_URL_X_PORT (same value) now counts as a copy, like an exact copy, so it
does not take the named service's domain. Also replace the Postgres-only
regex in the magic variable loop with the same check in PHP.
Generate now stores the new secret at once. The unsaved bar compares
fields with the saved secrets, so other drafts stay marked as unsaved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Call updateCompose() after saving an application's fqdn in the services
API urls handler so the domain is written back to the compose file.
Without this, StartService re-parsing the compose before deploy would
drop the domain and its SERVICE_URL_*/SERVICE_FQDN_* variables.
Add a feature test covering persistence after a second parse.
The template port 3003 sent API and realtime traffic to a port that the
containers do not listen on (502). Use port 80 as upstream does, update
images and env to the official 2.5.0 compose, drop the removed assistant
service, and default _APP_OPTIONS_FORCE_HTTPS to disabled (upstream
default) so installs on http domains reach the API.
When a compose service copies another service's SERVICE_URL_/SERVICE_FQDN_
declaration (old Twenty template: worker repeats SERVICE_URL_TWENTY_3000),
the parser and updateCompose wrote the variable from the copier's generated
domain, so a custom domain on the named service was lost on every deploy.
Skip exact copies; declarations with another path or port are unchanged.
Closes#11924
GNU tar exits with 1 when a file changes while it is read. The archive
is still valid, so only exit codes above 1 fail the backup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All instances share the same default update cron, so they request the
CDN at the same second and Cloudflare rejects the burst (error 1200).
Queue the CDN fetching jobs with a random 0-600s delay to spread the load.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add a per-task overlap lock to ScheduledTaskJob that outlives the worker
timeout, so a long or killed run cannot overlap the next cron run.
- Mark the dropped occurrence as skipped instead of releasing the job.
Closes#11648
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single service deploy with an unchanged config keeps the running
container, which is already on the network. The connect then logged a
false "already exists" error and a warning. Check the container's
networks first.
Closes#11295
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A custom config file written with tee gets the server umask. With umask
027 or 077 the file is not readable by the container user, so MySQL and
MariaDB ignored the whole config without an error.
- Set mode 644 on the MySQL, MariaDB, PostgreSQL, and MongoDB custom
config files after each write.
- Close the multiplexed SSH connection when the server user, IP, or port
changes, so the next command does not run as the old user.
Closes#11600
Docker Engine 27.0 to 28.0.0 reports an IPv6 network gateway with its
prefix length (fd00::1/64) until the daemon restarts (moby/moby#49520).
The Docker CLI 29 and Compose 5 in the helper image reject it, so
deployments failed and the upgrade left Coolify stopped.
- Stop the upgrade before it changes containers when the coolify network
has such a gateway, and tell the user to restart or upgrade Docker.
- Create a new coolify network again without IPv6 when Docker reports
its gateway with a prefix.
- Report an error, not "Upgrade complete", when the new Coolify
containers do not start.
- Add the fix to deployment errors that contain this ParseAddr failure.
Fixes#11583
Merge log rotation and the network pool into the existing daemon.json
instead of overwriting it. Skip the change and the Docker restart when
containers are running, unless DOCKER_POOL_FORCE_OVERRIDE=true.
Closes#11221
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Create the containers with --no-start, connect them to the destination
network, then start them. A container that crashed before the late
connect was restarting, the connect failed silently, and it never
joined the network.
Closes#11371
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The executions list polled with the task stored as a model, so a poll
after the delete failed to load it and showed a 404. Load the task by id
on each request and skip the refresh when it is gone. Return true from
delete so the confirmation modal does not refresh the deleted task.
Closes#11814
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Skip the pre-stop pull when a custom build command runs without a build server, and pull only services whose image does not come from a build, including services that reuse the image of a build service.
Closes#11773
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Image CDN URL help text said an empty value uses the S3 endpoint.
Since #11865, an empty value serves profile pictures and project icons
through Coolify, because private buckets and Cloudflare R2 reject
anonymous browser requests (#11806).
install.sh created the resource directories and ran chown -R and
chmod -R on source, ssh, and images before step 1. When a check or a
CDN download failed, the changed owners and modes stayed although
nothing was installed.
Create only /data/coolify and source (for the log and the downloads)
at the start. Create the other directories and set the permissions in
the SSH key step, after the checks and downloads succeed.
Closes#11973
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hatchet leaves new signups unverified unless SMTP is set up, which
blocked users after signup. Default SERVER_AUTH_SET_EMAIL_VERIFIED to
true so operators can still opt out.
DATABASE_URL used $POSTGRES_DB without a default, so fresh deploys
connected to a database named after the user and the migration failed.
Also align setup-config volume names with the other services.
Closes#12106
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>