Backup tar files currently use a filename that only encodes a
timestamp and the leader's IP, e.g.
caprover-backup-2026_04_10-19_30_00-1744312200000-ip-1_2_3_4.tar
When you run several CapRover instances behind a NAT or with
similar IPs, that filename is not enough to tell the backups apart
after downloading them.
This appends the swarm leader's hostname to the existing filename:
caprover-backup-...-ip-1_2_3_4-host-captain-prod.tar
The hostname is sanitized to a portable charset ([A-Za-z0-9._-]) so
it is safe in filesystems and HTTP Content-Disposition headers, and
the segment is omitted entirely when the leader has no hostname, so
existing single-node setups see no change beyond an additional
suffix when one is available.
The sanitization step is exposed as a small static helper
(`BackupManager.sanitizeHostnameForFilename`) so it can be unit
tested in isolation. Top-level cleanup hooks in the existing test
file are now gated on `process.env.CI`, matching how the
integration tests in the same file are gated, so the new pure
helper tests can run on a developer workstation.
Closes#1257
The existing POST /update/ replaces all fields — omitted fields are
reset to defaults (e.g. envVars becomes [], instanceCount becomes 0).
This makes simple operations like scaling dangerous: sending only
{appName, instanceCount} wipes all environment variables.
The new PATCH /update/ endpoint fetches the existing app definition
and merges only the explicitly provided fields. Omitted fields retain
their current values.
Example — scale without touching env vars:
PATCH /api/v2/user/apps/appDefinitions/update/
{"appName": "my-app", "instanceCount": 1}
The POST endpoint is unchanged — full backward compatibility.
- Introduced CertbotCertCommandRule for dynamic command generation
- Refactored CertbotManager to utilize a CertCommandGenerator
- Added new tests for the CertCommandGenerator logic