Serve a dev facility
This page puts a dev facility on the air at its own address: its server running as a service, the web client's bundler running beside it, and the web server joining the two at the address written in the facility's settings. At the end of this page you sign in to it in a browser.
Prerequisites
Done already, on the pages before this one:
- the facility's database and settings exist, from Build a dev facility
- the services are installed and the web server reads
/etc/caddy/conf.d, from First time setup
Every command on this page uses three things about the facility: its name as <facility>, the
port its server listens on as <port>, and its host name as <hostname>, such as zri.test,
with no http:// and no port. The name is the one you built. The other two were written into
zf-server/environments/<facility>.env by the rebuild, the port as PORT and the host name as
the part of FACILITY_URL after http://:
cd "$ZFM_ROOT_DIR"
grep -E 'FACILITY_URL|PORT' zf-server/environments/<facility>.env
Make the host name resolve
A dev facility's host name ends in .test, a name reserved for exactly this use, and nothing
resolves it for you. The machine that runs the browser has to be told which machine answers
to that name. When the browser runs on this machine:
echo '127.0.0.1 <hostname>' | sudo tee -a /etc/hosts
getent hosts <hostname>
When the browser is on another machine, the line goes in that machine's hosts file, with this
machine's IP address in place of 127.0.0.1.
Give the web server the facility
A facility's web server configuration is one file in /etc/caddy/conf.d, which the host's own
Caddyfile reads. It has three jobs: pass the client's requests for data, which all begin
/zf-server, to this facility's server on its port, with that prefix removed; serve the usage
guide, which the facility's users reach at /usage-guide/; and serve the web client itself for
everything else. On a production host the client and the guide come from the release. On a
development machine the guide comes from the checkout's last documentation build, and the client
is bundled as its source changes, so the file passes everything else to that bundler instead.
The file is rendered from the facility's settings, the same way a production host renders it, so the host name and the port are never typed a second time:
cd "$ZFM_ROOT_DIR/zf-server"
FACILITY=<facility> npm run --silent render-caddy-site -- --dev | sudo tee /etc/caddy/conf.d/<facility>.caddy > /dev/null
# a fault in the new file is shown here, before the reload; at the reload Caddy would refuse the
# configuration, keep the one it had, and serve every facility but this one
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
Read the file it wrote, /etc/caddy/conf.d/<facility>.caddy, once; its comments say what each
part does. A change to the port or the host name is made in the facility's settings and the file
rendered again, because an edit made to the file is lost the next time somebody renders it.
Caddy automatically obtains a certificate for an https:// site and serves an http:// site
without one. This is why FACILITY_URL in the dev version of a facility's settings file begins
http:// and the production version begins https://.
Start the facility's server
systemctl --user enable --now zfm-server@<facility>
journalctl --user -u zfm-server@<facility> -f
The service runs the server from its source and rebuilds it as the source changes, so the journal
is where every compile and every request's errors go. enable makes it start at your next login.
Am I ready to move on?
systemctl --user status zfm-server@<facility> # active (running)
curl -s localhost:<port>/health # {"status":"ok","facility":"<facility>","version":"..."}
The facility named in the answer proves the server read the settings file you think it did.
Start the bundler
The web client is one program for every facility on this machine. It runs as its own service, and is started when you want it rather than at login, because a bundler left broken at the end of a session is better not running than restarting itself:
systemctl --user start zfm-client
journalctl --user -u zfm-client -f
The first start takes a minute to bundle. Waiting on http://localhost:8081 in the journal means
it is ready.
Am I ready to move on?
Open http://<hostname>/ in the browser whose hosts file you edited. ZFM's sign-in screen is the
answer. Sign in as the platform owner with the password you collected, or, on gui_test, as
test-admin.
Then ask for a password reset for any account from the sign-in screen, and read the message at http://localhost:8025. The link in it begins with the facility's address, which is the only way to see that the address in its settings is the one the facility builds links from.
The client as it ships
What Metro serves and what a facility is deployed with are not the same bundle. The deployed one is
an export, which goes through different processing, and a fault can live in one and not the
other. A second address serves the export against the gui_test facility's server, so that the
browser walk in Testing can check what ships:
cd "$ZFM_ROOT_DIR/zf-react-client" && npm run export:web
echo '127.0.0.1 gui-test-built.test' | sudo tee -a /etc/hosts
sudo tee /etc/caddy/conf.d/gui-test-built.caddy > /dev/null <<EOF
# The exported web client, served as a production host serves it, against the gui_test facility's
# server. Written by hand. npm run export:web in zf-react-client writes the directory this serves.
http://gui-test-built.test {
handle_path /zf-server/* {
reverse_proxy localhost:3100
}
# Static files, with every address that is not a file falling back to the single page so the
# client's own router can take it. Inside a handle block so that the fallback cannot touch a
# request for data.
handle {
root * $ZFM_ROOT_DIR/zf-react-client/dist
try_files {path} /index.html
file_server
}
}
EOF
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
Caddy runs as its own account and reads that directory on every request, so it has to be able to pass through your home directory:
sudo usermod -aG "$USER" caddy
sudo systemctl restart caddy
Open http://gui-test-built.test/. The same sign-in screen, from the export rather than from Metro.
Export again after a change to the client to see it here; nothing watches for you.