Skip to content

Install it on a host

This page puts ZFM on a prepared host: the account it runs as, the directories it lives in, and a built installation artifact in place. It serves nothing yet, and no facility exists at the end of it.

Send the release to the host

The build left /tmp/zfm-<version>.tar.gz and its checksum on the build and test host. Send both, with the script that installs them:

# on the build and test host
export VER=$(git describe --tags --always --dirty)
scp /tmp/zfm-$VER.tar.gz* deploy/install-release.sh <production-host>:/tmp/

Install it

# on the production host
ls /tmp/zfm-*.tar.gz
sudo bash /tmp/install-release.sh /tmp/zfm-<version>.tar.gz

One command puts a release on the host, naming each thing as it does it:

  • The account and the directories, if they are not already there. The servers run as a zfm system account with no login shell, so a fault in the application reaches only what that account owns. /srv/zfm/releases holds one directory per release, and /srv/zfm/facilities one directory per facility — both world-readable, because Caddy reads a release's web client and tests for a facility's closed marker as its own account.
  • This host's Node, against the line the release needs. A release states the major version of Node it runs on, and a host on another line serves nothing, so it is refused here rather than at the first start of the first facility, where the fault would read as a broken release.
  • The release, checked against its checksum, then unpacked into a directory named by its own version.
  • The host's settings file, /etc/zfm/zfm.conf, if it is not already there, copied from the release's template and readable by the zfm account alone. It holds the template's values until somebody gives it this host's, which is the next page. A file that is already there was filled in by somebody and is never written over.
  • The service template, zfm-server@.service, if it is not already there. systemd starts one server per facility, and every one of them starts from this one unit. It names no release: each facility is pointed at the release it runs, and the unit resolves that pointer when the service starts, so two facilities on one host can be on different releases and a facility that crashes comes back on the release it is pointed at. Because every facility on the host starts from it, a unit the host already has is left alone even when the release carries a different one. The difference is reported, with the commands that adopt the release's copy, so that change is made by a person on purpose.

Nothing else changes. No facility moves onto this release, nothing restarts, and nothing is served differently afterwards. That is deliberate: a release on disk is inert, so you can install one while every facility on the host is serving, and choose a separate moment to move facilities onto it. A facility moves when you upgrade that facility, one facility at a time, with upgrade-facilities.sh.

It refuses rather than guesses: a checksum that does not match, or a release directory that already exists, stops it with a sentence saying which.

Nothing is compiled or resolved on the host: the installation artifact arrives with the server's dependencies in it, the migration tool among them.

Am I ready to move on?

Name the release you just installed, and look inside it:

RELEASE=/srv/zfm/releases/<version>

ls -ld $RELEASE
ls $RELEASE/zf-server/dist/main.js $RELEASE/zf-server/dist/scripts/
ls $RELEASE/node_modules/typeorm/cli.js
ls $RELEASE/zf-react-client/dist/index.html
ls $RELEASE/deploy/
ls -ld /srv/zfm/facilities
sudo ls -l /etc/zfm/zfm.conf
systemctl cat 'zfm-server@.service'

Those lines say that the release directory is owned by zfm, that the compiled server and its operator scripts are in it, that the migration tool came with them, that the web client is in place for Caddy to serve, and that the deployment scripts a host runs are there too. The last three are about the host rather than this release: /srv/zfm/facilities is where each facility's own pointer and closed marker will go, the settings file belongs to zfm and nobody else can read it, and the unit systemd prints names /srv/zfm/facilities/%i/current/zf-server as its working directory, %i being whatever follows the @ in a service name.

ls /srv/zfm/releases lists the releases this host holds, and the one you installed is named by the artifact you installed it from. Keep that path: the next page uses it, and so does every command that is about the host rather than about one facility.

Does this release use the settings the host states?

A release can stop using a setting. A server refuses a settings file that states a key its release does not use, so a key left behind by an earlier release stops every facility on the host from starting — and it stops them at the moment you move them onto the new release, not now. Ask this release what it makes of the host's own file:

sudo node $RELEASE/zf-server/dist/scripts/check-config-syntax.js --system

no faults means every key in /etc/zfm/zfm.conf is one this release uses and every value is the kind of value it should be. A fault that names a key as not allowed is a setting this release no longer has: delete that line from the file. The same check reads a facility's own settings, which is how a facility is checked before it is moved onto a release.

Do not try to start the server to check it: starting one means starting it for a facility, and no facility exists yet. The version an installation artifact reports comes from a running facility, on GET /health.