Getting started
Upgrading
This page explains how to upgrade the scalws package, what the upgrade does to running services and configuration files, and how to go back if something goes wrong.
Before you upgrade: back up
Take a backup of the configuration first:
sudo scalwsctl backup /var/backups/scalws-$(date +%F)It copies /etc/scalws/scalws.yaml, its site files and the certificate and key files they
reference into a new directory. It does not contain controller.yaml, the ACME account
and certificates, or the console’s state and credentials; archive those directories as
well:
sudo tar -C / -czf /var/backups/scalws-files-$(date +%F).tar.gz \
etc/scalws var/lib/scalws var/lib/scalws-consoleNote the version you are running, so you can return to it:
scalwsd --versionDetails: Files and services and scalwsctl backup.
Upgrade the package
From the apt repository:
sudo apt update && sudo apt upgradesudo apt install scalws upgrades only ScalWS.
From the dnf repository (RHEL family, Fedora):
sudo dnf upgrade scalwsFrom the same repository with zypper (openSUSE Leap, SLES):
sudo zypper up scalwsFrom the apk repository (Alpine Linux; OpenRC services, see Alpine Linux):
doas apk upgrade scalwsFrom a package file, install the newer file the same way as the first one (Installation).
What happens to running services
The package scripts (preinstall.sh, postinstall.sh, preremove.sh) do the following on
an upgrade, with apt, dnf and zypper:
- Binaries, systemd unit files, shell completions and
/usr/lib/sysctl.d/90-scalws-adaptive-runtime.confare replaced. systemd re-reads the unit files and the sysctl setting is applied again. - Ownership is set again on
/etc/scalws(root:scalws, mode 0750),/etc/scalws/scalws.yamland/etc/scalws/controller.yaml(root:scalws). - scalwsd.service, if it is running, is restarted onto the new binary. The old process
drains its connections and exits; the new one checks the configuration
(
ExecStartPre=... --check) and starts. While one has stopped and the other has not yet started, no process accepts connections. If the new version refuses the configuration, the unit does not start. - scalws-controller.service, if it is running, is restarted. This restarts only the
controller (
KillMode=process): itsscalwsdinstances keep serving on the old binary while the new controller adopts them. The new controller then rolls them onto the new binary by itself, one at a time, unlessinstances.roll_on_upgradeisfalseor every instance slot up toinstances.maxis taken. With systemd before 254 (EL8, EL9, Debian 12, Ubuntu 22.04) the restart stops the instances too and starts new ones on the new binary: a short interruption instead of the handover (systemd before 254). - Where SELinux is enabled (RHEL family, Fedora, openSUSE Leap 16, SLES 16), a changed SELinux policy module is loaded and the package’s files
are relabelled before the services restart. Coming from an
.rpmwithout the module, the controller’s instances run unconfined, so the package restarts them in their confined domain (they drain for up to 30 seconds). - scalws-console.service, if it is running, is restarted. Then the scripts run
systemctl enable --now scalws-consoleon every install and upgrade, so the console is enabled and started even if you had disabled it; the output then says so (scalws-console was disabled and is enabled again ...) and that the console listens on port 8090. To keep it off, mask it:sudo systemctl mask --now scalws-console; a masked console is never enabled or mentioned by an upgrade. Console sessions end; history and audit log stay. - A unit that was not running is not started (except the console, as above).
- The console’s credentials file is created only if it does not exist.
A failed restart does not make the package installation fail, so check the services afterwards:
systemctl status scalwsd scalws-controller scalws-console
journalctl -u scalwsd -n 50Configuration files are kept
/etc/scalws/scalws.yaml and /etc/scalws/controller.yaml are configuration files of the
package (config|noreplace):
- On Debian and Ubuntu they are dpkg conffiles. A file you changed is kept. If the package ships a changed version of a file you also changed, dpkg asks what to do; keeping your version is the default. A file you never changed is replaced by the new packaged version.
- On RPM systems (
%config(noreplace)) a file you changed is kept and the new packaged version is written next to it as<file>.rpmnew. A file you never changed is replaced. When the package is removed, a file you changed is saved as<file>.rpmsave.
The package’s scripts edit scalws.yaml only on a first install: they add sandbox: on
(sandbox.md) and, on a host without IPv6, comment out the IPv6 listeners. An
upgrade or a reinstall never edits it, so an existing installation keeps the sandbox mode it
has. dpkg and rpm treat a file edited that way like one you changed.
Files the package does not ship are never touched: the site files in /etc/scalws/sites.d/,
the console credentials in /etc/scalws/console/, your certificates, and everything under
/var/lib/scalws, /var/lib/scalws-controller and /var/lib/scalws-console.
Unit files in /usr/lib/systemd/system are replaced. Keep your changes in drop-ins
(sudo systemctl edit scalwsd), which upgrades leave alone.
New defaults in the packaged configuration are not merged into a file you changed. Compare
your file with the commented example in /usr/share/doc/scalws/examples/scalws.yaml after
an upgrade, then validate it:
sudo scalwsctl checkSite files on older installations
Installations that predate site files have no include: line, and scalwsctl site add and
scalwsctl migrate stop with:
/etc/scalws/scalws.yaml has no `include:` for site files; add `include: sites.d/*.yaml` and create /etc/scalws/sites.dThe package creates /etc/scalws/sites.d (root:scalws, mode 0750). If it is missing,
create it:
sudo install -d -m 0750 -o root -g scalws /etc/scalws/sites.dThen add the line at the top level of /etc/scalws/scalws.yaml (under scalws-controller:
the file named by controller.config, which
is the same file by default):
include: sites.d/*.yamlCheck and reload:
sudo scalwsctl check
sudo scalwsctl reloadThe rules for site files and the directory are in Sites and
include.
Roll the instances onto the new binary
Under scalws-controller, the restarted controller adopts the running instances, which still
run the previous scalwsd (their /proc/<pid>/exe is the deleted file that
controller.webd_binary named). It
then rolls them onto the binary on disk by itself. It creates a new generation that is a
copy of the current one. The configuration file is not read again, so edits you have not
applied stay unapplied. The instances are replaced one at a time: a new instance becomes
active before an old one drains, so capacity does not drop.
The first new instance needs a free slot: the controller rolls only while fewer instances
run than instances.max. When every slot is taken (for example min: 1, max: 1, or two
instances with max: 2), it does not roll, because it would have to stop a serving
instance before the new binary has proved it can start. It logs a warning instead
(not rolled: instances.max leaves no spare slot). Raise instances.max by one, or roll
them yourself with sudo scalws-controller reload (which replaces an instance in place, so
capacity dips by one while it does).
scalws-controller status shows "binary": "replaced" for an instance that still runs the
old file and "binary": "current" for one that runs the new file. It also shows the phases
and the active generation:
sudo scalws-controller statusIf the new binary cannot become ready, the controller goes back to the older generation (see below) and the old instances keep serving from the old, deleted file. An old instance that crashes meanwhile is replaced by an instance started from the new file.
To turn the automatic roll off, set roll_on_upgrade: false in the instances section of
/etc/scalws/controller.yaml. The controller then only logs a warning that names the
instances. Roll them yourself with a reload, which also retries a roll that went back:
sudo scalws-controller reload
sudo scalws-controller statusThis reload reads the configuration file again, so it applies your pending edits too. Each instance’s version is the first line of its status view:
sudo scalwsctl --socket /run/scalws/web-0/admin.sock statusIf an instance of the new generation fails to start while an older one still serves, the
controller returns to the older generation by itself and reports it as last_rollback in
status. Check the instance log in /var/lib/scalws-controller/logs/web-<n>.log.
scalwsctl reload does the same while the controller runs. See
scalws-controller.
The standalone scalwsd.service is not affected by this: it still restarts with the short
gap described above.
Rollback
Going back to an earlier configuration
On scalwsd.service, scalwsctl rollback re-applies the configuration before the active
one, or --generation G. It uses the configurations the running process keeps in memory
(at most 10, since it started), so after an upgrade, which restarts the process, it cannot
reach configurations from before the upgrade. It also does not change the file on disk: the
next reload reads the file again. To return to the configuration of your backup:
sudo scalwsctl restore /var/backups/scalws-2026-10-05 # dry run: what would change
sudo scalwsctl restore /var/backups/scalws-2026-10-05 --apply
sudo scalwsctl reloadscalws-controller has no rollback command. Restore the files from a backup (or restore an
entry of the console’s history) and run
sudo scalws-controller reload; this makes a new generation with the earlier content. The
generations it applied are kept in /var/lib/scalws-controller/generations/<n>/scalws.yaml,
readable by root, with the site files expanded into them, which helps to compare what
changed.
Going back to an earlier package version
Install the earlier version again, from the repository if it still offers it, or from the package file:
apt list -a scalws # versions the repository offers
sudo apt install scalws=<version> # apt asks you to confirm the downgradeWith dnf:
dnf --showduplicates list scalws # versions the repository offers
sudo dnf downgrade scalws-<version>With zypper:
zypper search -s scalws # versions the repository offers
sudo zypper install --oldpackage scalws-<version>The package scripts restart the running services as on an upgrade. A downgrade also
replaces the binary, so under scalws-controller the restarted controller rolls the
instances back onto the earlier binary by itself, when a slot is free as described above.
Otherwise, or with roll_on_upgrade: false, run sudo scalws-controller reload to put them
there.
Every section of the configuration rejects unknown keys, so a configuration that uses settings added in the newer version is refused by the older one. Restore the backup you took before the upgrade first, then downgrade.