The network of databases buildingenvelopedata.org is based on databases and one metabase. This repository can be used to set up the machine either to deploy a database or to deploy the metabase.
The machine has two ext4 disks namely one root disk running Debian
bookworm and one initially empty
data disk. The data disk is partitioned, formatted, and mounted to /app/data
as described below. There is a Debian user cloud with superuser privileges
and a corresponding group cloud. The machine setup is mostly done by running
the Ansible playbook ./setup.yaml with make setup as the user cloud. The
machine runs two instances of the application, one for staging in
/app/staging and the other for production in /app/production. Using
NGINX as reverse proxy it directs traffic coming from the
sub-domain staging or www to the staging or production instance.
Note that the network of databases buildingenvelopedata.org and the TestLab Solar Facades product-data server both run on machines provided by Fraunhofer Cloud and some of the set-up information below may still be Fraunhofer Cloud specific. If you find that that is the case, please report it on GitHub and we will try to generalize it.
This project follows the
GitHub Flow, in particular, the
branch main is always deployable.
- If there is a firewall, configure it such that it allows secure shell (ssh) access on port 22. And if there are explicit port forwardings, forward the public port 22 to port 22.
- Enter a shell on the production machine using
sshas the usercloud. - Install
GNU Make,
Git,
pipx,
scsitools,
GNU Parted, and
e2fsprogs
by running
sudo apt-get install make git pipx scsitools parted e2fsprogs, and install Ansible and Ansible Development Tools by runningpipx ensurepath && pipx install --include-deps ansible && pipx inject --include-deps --include-apps ansible python-debian ansible-dev-tools. - Create a symbolic link from
/appto~by runningsudo ln --symbolic ~ /app. - Change into the app directory by running
cd /app. - Clone the repository by running
git clone git@github.com:building-envelope-data/machine.git. - Change into the clone by running
cd ./machine. - Prepare the machine environment by running
cp ./.env.sample ./.env && chmod 600 ./.env(orcp ./.env.buildingenvelopedata.sample ./.env && chmod 600 ./.envorcp ./.env.solarbuildingenvelopes.sample ./.env && chmod 600 ./.env) and adapt the.envfile as needed for example insidevi ./.envornano ./.env. The.envvariablesHOSTis the domain name without sub-domain;PRODUCTION_SUBDOMAIN,STAGING_SUBDOMAIN,TELEMETRY_SUBDOMAINare the sub-domains of the production instance/app/production, staging instance/app/staging, and the telemetry serviceslogs, andmetrics. Note that none of these sub-domains can be empty. The reverse proxy NGINX redirects requests to${HOST}without a sub-domain to such with the sub-domain${PRODUCTION_SUBDOMAIN}. If the domain name is too long, then NGINX will fail to start, for example, with the error message"Could not build the server_names_hash. You should increase server_names_hash_bucket_size."and it becomes necessary to tune theserver_names_hash_max_sizeorserver_names_hash_bucket_sizedirectives, in the above example just increaseserver_names_hash_bucket_sizeto the next power of two;EXTRA_HOSTis an extra domain name for which the TLS certificate fetched from Let's Encrypt shall also be valid apart from${HOST},${PRODUCTION_SUBDOMAIN}.${HOST},${STAGING_SUBDOMAIN}.${HOST}, and${TELEMETRY_SUBDOMAIN}.${HOST}(it is used in./init-tls.sh);HTTP_PORTandHTTPS_PORTare the HTTP and HTTPS ports on which the NGINX reverse proxy is listening;PRODUCTION_HTTP_PORTorSTAGING_HTTP_PORTis the HTTP port on which the production instance/app/productionor staging instance/app/stagingis listening;MONITOR_HTTP_PORT,LOGS_HTTP_PORT, orMETRICS_HTTP_PORTis the HTTP port on which the monitoring utility Monit, the logs service VictoriaLogs, and the metrics service VictoriaMetrics is listening;TELEMETRY_GPRC_PORTorTELEMETRY_HTTP_PORTis the gPRC and HTTP port on which the observability pipelines tool Vector listens for OpenTelemetry Protocol data;EMAIL_ADDRESSis the email address of the person to be notified when there is some system-administration issue (for example Monit sends such notifications)SMTP_HOSTandSMTP_PORTare host and port of the message transfer agent to be used to send emails through the Simple Mail Transfer Protocol (SMTP);NETWORK_INTERFACEis the network interface to monitor with Monit (list all with./tools.mk network-interfacesor simplyip link);
- Prepare your remote controls GNU Make and Docker Compose by running
ln --symbolic ./docker-compose.production.yaml ./docker-compose.yamlandln --symbolic ./docker.mk ./Makefile.
- If there is a firewall, configure it such that it allows the protocol TCP for ports 80 and 443.
- If the HTTP and HTTPS port configured in
.envare not 80 and 443, then the public ports 80 and 443 must be forwarded to the configured ports${HTTP_PORT}and${HTTPS_PORT}. - Format and mount hard disk for data to the directory
/app/dataas follows:- Create the directory
/app/databy runningmkdir /app/data. - Scan for the data disk by running
./tools.mk scan. - Figure out its name and size by running
lsblk, for example,sdband50G, and use this name and size instead ofsdxandXGbelow. - Partition the hard disk
/dev/sdxby runningsudo parted --align=opt /dev/sdx mklabel gptandsudo parted --align=opt /dev/sdx mkpart primary 0 XGor, if the command warns you that resulting partition is not properly aligned for best performance: 1s % 4096s != 0s,sudo parted --align=opt /dev/sdx mkpart primary 4096s XG. If the number of sectors, 4096 above, is not correct, consult How to align partitions for best performance using parted for details on how to compute that number. - Format the partition
/dev/sdx1of hard disk/dev/sdxby runningsudo mkfs.ext4 -L data /dev/sdx1and mount it permanently by addingUUID=XXXX-XXXX-XXXX-XXXX-XXXX /app/data ext4 errors=remount-ro 0 1to the file/etc/fstaband runningsudo mount --all && sudo systemctl daemon-reload, where the UUID is the one reported bysudo blkid | grep /dev/sdx1. Note that to list block devices and whether and where they are mounted runlsblkand you could mount partitions temporarily by runningsudo mount /dev/sdx1 /app/data. - Change owner and group of
/app/datato user and groupcloudby runningsudo chown cloud:cloud /app/data. - Create the directory
/app/data/backupsby runningmkdir /app/data/backups.
- Create the directory
- Set-up everything else with Ansible by running
make setup. - Before you try to interact with Docker in any way, log-out and log-in again
such that the system knows that the user
cloudis in the groupdocker(this was taken care of by Ansible). You could for example exit the SSH session by runningexitand start a fresh one as you did in the beginning. If you do not do that, you will encounter a permission denied error. For example, when runningdocker psthe error reads "Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied". - Fetch Transport Security Protocol (TLS) certificates from Let's
Encrypt used for HTTPS by running
./init-tls.sh(if you are unsure whether the script will work, set the variablestaginginside that script to1for a trial run). - Start all services by running
make dotenv pull up. On subsequent deployments just runmake deployto also rerunsetup. - Continue with the second step of setting up a Debian production machine of the metabase or setting up a Debian production machine of a product-data database.
Security upgrades are installed automatically and unattendedly by
unattended-upgrades
as configured in the Ansible playbook ./setup.yaml. Non-security upgrades should
be done weekly by running ./maintenance.mk upgrade. If the command asks you
to reboot, then please do so and run ./maintenance.mk end afterwards. Only
run the possibly destructive command ./maintenance.mk dist-upgrade when you
know what you are doing. See the entries upgrade and dist-upgrade in the
apt-get manual man apt-get.
To install security upgrades in Docker services, redeploy the production and
staging environments as described in
Deploying a release of the metabase
or
Deploying a release of the database.
Rebuilding the image and recreating the services are the important steps here,
which can also be done in /app/production and /app/staging by running
./deploy.mk begin-maintenance services end-maintenance.
Additionally, to keep HTTPS, that is, HTTP over TLS, secure, regularly fetch SSL configuration and Diffie–Hellman parameters from certbot as explained in issue #5.
Before the installed version of Debian reaches its end of life, upgrade to the
next major version. Enter a shell on the production machine using ssh. Print
which Debian version is installed by running lsb_release --all. Consult Long
Term Support for when it reaches its end of life.
If it is to be soon, then perform an
upgrade.
Our machines run Debian 12 "Bookworm" which reaches its end of life on June
30th, 2028.
In the Ansible playbook ./setup.yaml, periodic jobs are set-up.
- System logs are are vacuumed daily keeping logs of the latest seven days.
- The Transport Layer Security (TLS) certificates used by HTTPS, that is, HTTP over TLS, are renewed daily if necessary.
- The database is backed-up daily keeping the latest seven backups. To do so,
the production GNU Make target
backupof themetabase'sdeploy.mkanddatabase'sdeploy.mkare used. - The docker system is pruned daily without touching anything that is younger than one day.
- Logs in
/var/log/are rotated daily by the Debian-default Cron job/etc/cron.daily/logrotate. It's configured in/etc/logrotate.conf.
If a job fails, Cron sends an email to ${EMAIL_ADDRESS} set in ./.env.
For logs of periodic jobs see above.
- Docker services logs are collected and stored by
journaldand can be followed by runningmake logs. - Docker daemon logs are collected and stored by
journaldand can be followed by running./logs.mk daemon. - Cron logs are collected and stored by
journaldand can be followed by running./logs.mk cron. - Monitoring logs are collected and stored by
journaldand can be followed by running./logs.mk monit. - SMTP client logs are collected and stored by
journaldand can be followed by running./logs.mk msmtp. - Certbot logs are written to
/certbot/logs/*.log.*and the latest log-files can be followed by running./logs.mk certbot.
If the website is not reachable, then check whether the reverse proxy is up and
healthy by running make list.
- If not, identify the reason by studying the logs printed by
make logs, fix any issues if necessary, and redeploy the reverse proxy. - If yes, check whether the reverse proxy receives requests by studying the
logs printed by
make logs.- If not, there may be an issue with the mapping
of the URL to the server managed by
Fraunhofer ISE
(you can find out more as elaborated in
Linux troubleshooting commands: 4 tools for DNS name resolution problems)
or an issue with the firewall settings or port forwardings configured in
the network settings for the public IP addresses in the
Fraunhofer cloudportal (the firewall
must allow the protocol TCP for ports 80 and 443 and the public ports 80
and 443 must be forwarded to the HTTP and HTTPS ports configured in
.env; note that for secure shell access port 22 must be allowed and forwarded to 22). - If yes, the reverse proxy may not be configured properly, for example, the
ports of the production and staging web servers may not match the ones
configured in
.envin/app/productionand/app/staging, or the production and staging web servers may be down or unhealthy, which you can check by runningmake listin/app/productionand/app/stagingand troubleshoot as elaborated in the READMEs of the metabase and database projects.
- If not, there may be an issue with the mapping
of the URL to the server managed by
Fraunhofer ISE
(you can find out more as elaborated in
Linux troubleshooting commands: 4 tools for DNS name resolution problems)
or an issue with the firewall settings or port forwardings configured in
the network settings for the public IP addresses in the
Fraunhofer cloudportal (the firewall
must allow the protocol TCP for ports 80 and 443 and the public ports 80
and 443 must be forwarded to the HTTP and HTTPS ports configured in
- Fetch and checkout the latest version by running
git fetchandgit checkout --force main. - Deploy the new version by running
make deploy. - Check that everything works by scanning the output of
make logs.