New: an SSL page, replacing a client's API key, and changing a repository's passphrase. Plus fixes for two ways a job could sit doing nothing without saying so.
SSL certificate settings
A new page under Settings shows the certificate this server presents: the names it covers, who issued it, when it expires, and how many days are left. It also shows whether certbot's renewal timer is armed — that is the part that fails silently, and a certificate only expires after nothing renews it for three months.
Renew and Force renew are there too. Certbot declines while more than 30 days remain and says so; its output is shown as it comes back.
The contact address Let's Encrypt sends expiry warnings to can be set here. Installations made before this release registered with a guessed admin@<hostname> that usually does not receive mail, so those warnings went nowhere. New installs take --email on the installer, and the setup wizard now sends the admin address you enter to Let's Encrypt.
Over the API: GET /api/v1/ssl, POST /api/v1/ssl/renew, PUT /api/v1/ssl/email.
Replace a client's API key (#433)
A key was issued once, when the client was created, and nothing could change it. Revoking a leaked one meant deleting the client and adding it back, losing its plans, schedules, repositories and file catalogue.
Replace key on a client's Install tab issues a new key and stops accepting the old one straight away. Nothing else about the client changes. The client cannot report until the new key is on the machine, so the page says where to put it before you commit to it. Also POST /api/v1/clients/{id}/rotate-key.
Change a repository's passphrase (#412)
Imported repositories kept whatever passphrase they arrived with. The passphrase row on a repository now has a pencil beside it on the install tab, offering a generated passphrase you can replace with your own. borg re-encrypts the repository key in place, so every archive stays where it is, and clients need no change — they are given the passphrase with each job.
Refused while any job is queued or running against the repository. Also POST /api/v1/repositories/{id}/passphrase.
Select all when restoring (#437)
Taking a whole archive meant ticking every top-level entry by hand. A Select all link in the Browse Archive header ticks them all, and turns into Clear all. Each entry is added separately, so you can still drop the two directories you do not want.
Offsite sync could hang instead of failing (#438)
rclone was run with no timeout flags. An endpoint that drops packets rather than refusing them — a tunnel that went down, a firewall blackhole — left rclone waiting with no output beyond a stats line reading 0 B/s, and the job sat in "running" until somebody noticed. One report had a sync in that state for a day.
Connect and idle timeouts are now set on every rclone call. A transfer that is still moving is unaffected; one getting nowhere gives up and the job fails and notifies.
Jobs left behind by a restart (#438)
Prunes, syncs and catalog rebuilds run in their own process. If one was killed — the container restarted, the machine rebooted mid-prune — the job stayed "running" for good. That held its repository, so every backup to it queued behind work nobody was doing.
The scheduler now releases a job whose process is gone, and says so in the log. It checks whether the process exists rather than how long the job has taken, because a large offsite sync and a big catalog rebuild are both legitimately slow.
Server health showed the wrong CPU load in LXC (#430)
Inside an LXC container the CPU dial showed the host's load, often pinned near 100% while the container was idle. Load is now read from /proc/loadavg, which lxcfs virtualises, rather than through a syscall it cannot reach. Memory was always read this way and was correct.
Thanks to @alglyzin for the diagnosis.
Installer
The installer refused to run on IPv6-only servers, behind NAT gateways, and anywhere DNS did not resolve to the machine's own public IPv4 — it compared the two and stopped on a mismatch, which is not a test of whether Let's Encrypt can reach you. That check is gone. Whether a certificate can be issued is now settled by asking certbot, after Apache is serving, and a failure leaves you with a working HTTP install and the reason rather than no install at all.
It also says at the start when another web server already holds port 80, instead of letting that surface later as a confusing certbot error.
Thanks to @katsaroskwide for both.
Smaller things
GET /api/v1/clients/{id}/jobsreturnshad_warnings, so a job that finished with warnings can be told from a clean one without fetching each job (#435).- The Updates page keeps the release notes to the height of the column beside them and scrolls, instead of running the page on past everything else. Images in release notes render, and issue numbers, commit hashes and @mentions are links.
WEB_PORTandSSH_PORTset the host side of the Docker port mapping and always have; the documentation now says so, and the container warns whenAPP_URLnames a different port from the one the web UI is published on (#436).