How to create and install an on-premises HOP Application
This guide describes how to carry on the creation and first installation of an On-premises HOP Application. There are two parts, firstly, it will describe how to generate a new project with On-premises deployment characteristics. Secondly, how to deploy/install the final artifact on your on-premises infrastructure.
While reading this guide, you will see the terms “deployment machine” or “installation machine”. They refer to where the final artificat will be deployed and run. Although you can do the installation on your development machine, this guide commands assumes a completely new GNU/Linux machine.
Requirements
Apart of having HOP CLI installed, as explained on the Installation tutorial, you will need the following tools to complete this guide steps on your development machine.
Docker and Docker Compose for running and building your project.
yq YAML, JSON and XML processor to help merging Docker Compose files.
tar to bundle the final artifact that you will deploy.
sha256sum to generate the hash of final artifact bundle.
Generate a new project using On-premises deployment target
First, you need to create a new project using the On-premises as profile and deployment target. To do that, you need to create a settings file that the HOP Command Line Interface tool (from now on HOP CLI) can use. In order to create the settings file, open the HOP CLI Settings Editor by running the following command on your terminal console:
$ hop bootstrap open-settings-editor
After running the command, it will output the URL to access the Settings Editor.
Settings Editor running at http://localhost:8090
This guide assumes the following profiles selection:
Core.
Frontend.
CI/CD.
On-premises.
Persistence - SQL.
As a reference, this guide assumes the following configuration in each profile:
Core.
With the setting
project -> docker -> registry
set toCustom Registry Provider
Frontend.
CI/CD.
With the setting
project -> profiles -> ci -> provider
set toCustom
.With the setting
project -> profiles -> ci -> continuous-deployment -> provider
set toOn-premises
.
On-premises.
With the settings
project -> profiles -> on-premises -> persistent-data-dir
set to/usr/local/hop/<your-project-name>/persistent-data-dir
.You can set the folder of your choice but to make this guide simpler we recommend that you use the same setting. Just do not forget to put your project name (the same you configured in
project -> name
) after/usr/local/hop/
.
With the settings
project -> profiles -> on-premises -> ssl-termination
set toNGINX configuration file
Persistence - SQL.
Also do not forget to select On-premises
as the deployment target.
Note
The notation used above is simply the path to a setting on the Settings Editor. If use the sidebar you can easily track the sections described above.
Note
You can optionally select more profiles such as Business Intelligence - Grafana and Authentication - Keycloak (which are suitable for On-premises deployment), but you have to do extra steps to finish their production setup such as creating a Keycloak realm.
Once you have configured the settings to fit your needs export it and run the following command to create the new project:
$ hop bootstrap new-project \
--settings-file-path <the-path-to-the-exported-settings-file> \
--target-project-dir <the-directory-path-of-your-new-project>
Warning
Make sure the project folder you pass to --target-project-dir
does not exist or the HOP CLI will error out.
Once you execute the command, HOP CLI will create the project files in the directory you specified. It will also print out some steps that you need to do during the on-premises installation. Save that output somewhere from where you can refer to them later on this guide.
Among all the files HOP CLI generated take special notice at the file
.env.test
. Save this file somewhere safe as it is the environment
variables required to run the application on your deployment machine.
With that out of the way, you can go to the project’s directory and run the following script to start the development environment:
$ ./start-dev.sh
That script will run your development, basically running
docker-compose up
using the development YAML files. If you want to
test the web application, you can connect to a nREPL running on
localhost:4001
and do:
user> (dev)
And then:
dev> (go)
That will endup running a web server on the port 3000
on
localhost
but since the setup uses a reverse proxy, you actually
have to go to localhost:8081
to view the web application.
You can turn down the environment at any moment by running the
stop-dev.sh
script.
Note
If you want to execute any other docker-compose
commands (such
as showing the logs) please use the dc.sh
script to do so. That
script will tell docker-compose
which YAML files to use in
order to run the commands. So, if you want to show the logs for
example, you can run ./dc.sh logs -tf
.
As you may have noticed, Unlike the Amazon Web Services
deployment
target, the On-premises
one does not provision the infrastructure
for you when generating the project. It provides you with the
necessary files and script for deploying and installing the final
artifact.
Creating the application bundle
Regardless of your Continuous Integration provider of choice (Github
Actions, Bitbucket Pipelines or Custom) there is an important detail
about the Continuous Delivery side of it. Because HOP does not assume
your deployment methodology and infrastructure, it only provides you
with a script to create the application bundle
(ci/on-premises/create-app-bundle.sh
). And optionally you have a
deploy.sh
script which is just a placeholder for you to implement
your own deployment strategy.
The create-app-bundle.sh
script bundles all the necessary
files for deployment and installation into a TAR
file. It also
provides you the sha256sum
of the TAR
file in case you need it.
The bundle is not the only thing you have to care of. You will also have to make sure to build and store your application on a Docker Registry that is accesible later on when deploying the final artifact. HOP assumes the deployment machine will have internet connectivity which is required to download the required Docker images.
The scripts ci/build-app-prod-docker-image.sh
and
ci/publish-app-prod-docker-image.sh
is what you need to build and
publish the application’s Docker image. Those scripts use
configuration variables from ci/common-vars.sh
where you can find
DOCKER_IMAGE_REPOSITORY
value. The value of this variable is what
you configured on the Settings Editor project -> docker -> registry
-> custom -> app-repository-url
.
So in order to proceed to the next step which is doing the
installation and first deployment you will need to bundle the
application. To do so, first you need to create your local git
repository and do your initial commit:
$ git init --initial-branch=<the-branch-you-chose-in-the-settings-editor>
$ git add .
$ git commit -m "Initial commit"
Note
When running the first command git init
the
--initial-branch
value should be what you chose while editing
the settings on the Settings Editor. If you did not change the
default value, then it should be main
. If you are unsure about
your decision, you can either take a look at ci/common-vars.sh
and look for DEPLOYMENT_BRANCH
, or import your settings file on
the Settings Editor and check the value there.
Once you have done that, run the create-app-bundle.sh
script from
the project root directory:
$ ./ci/on-premises/create-app-bundle.sh
The script will create two files in your project’s root directory, the
TAR
file and a file containing the sha256sum
of the
bundle. Now you will proceed to do the installation on your deployment
machine.
Installing On-premises
This guide is going to use a Debian 11 virtual machine to carry on with the installation. So beware that some commands, such as package manager commands, will have to be adjusted to work on your distribution of choice.
Before starting this section make sure you have the following tools installed on your deployment machine.
Docker and Docker Compose.
systemd
Warning
Having a GNU/Linux distribution running with systemd
is strictly
mandatory to complete the installation.
Setting up tools, users and groups
Warning
All the steps starting from here, assumes a GNU/Linux based machine.
First you have to install the necessary tools for this part of the
guide. All the following commands should be executed as the root
user of your system and you should only change users when requested by
the guide. So make sure you are logged in as root
before starting:
$ su -
If you are going to do the installation on a Debian 11 machine, as in this guide, you can run the following commands to install the packages:
# apt-get install -y docker
HOP minimum version requirement for docker-compose
is
1.27.x
. As of the time of writing, Debian 11 default repository
has an older version of docker-compose
, 1.25.0
. Therefore, to
install a newer version you have to use Debian backports. To do so,
use the following commands:
# echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list
# apt-get update
# apt-get install -y docker-compose/bullseye-backports
That should install a newer docker-compose
version, higher than or
equal to 1.27.4
.
The next step to create the docker group. Use the following command to do so:
# sudo groupadd docker
After that, enable the docker
service so it starts automatically
if the machine restarts. Then restart the service.
# systemctl enable docker
# systemctl restart docker
You should also check for the docker
service status and make sure
it is active and running.
# systemctl status docker
Now you will need to create the user that will run and own the application files. The user and group name must be the same value as the name of your project. That is, the same value you configured in the Settings Editor.
# useradd -d /usr/local/hop/<your-project-name>/ -m -U -G docker -s /bin/bash <your-project-name>
Installing application
Now that you have installed the required packages and set up the user and group, the next step is to prepare the application files directories for installation.
First you have to create the application files folder where all the files to run the system will reside:
# mkdir -p /usr/local/hop/<your-project-name>/app-files
Apart from the app-files
folder we need to create another very
important folder which is the persistent-data-dir
folder. This
folder is where any of your application’s system persistent data will
be stored. For example, you will need it to store the database
files. Make sure it is the same path you specified in the Settings
Editor when configuring the On-premises
settings.
# mkdir -p <your-persistence-data-dir>
Since this setup is using a PostgreSQL database we need to create its
folder inside the persistent-data-dir
as well:
# mkdir -p <your-persistence-data-dir>/postgres-data-dir
Warning
If you choose HTTPS Portal container
as the SSL termination
option, you will also have to create the
<your-persistent-data-dir>/https-portal-data-dir
. And please
refer to the HTTPS Portal section
at the end of this guide.
Once you have done that, change directory to the application files
app-files
folder.
# cd /usr/local/hop/<your-project-name>/app-files
Now you need to bring the application bundle you created previously
using the create-app-bundle.sh
script to your installation
machine. Move the .tar
file to
/usr/local/hop/<your-project-name>/app-files
. And extract it with
the command:
# tar xf <your-tar-file-name>
After extracting the file you will need to copy to the same directory
the .env.test
file mentioned at the beginning of this guide. Move
it to the /usr/local/hop/<your-project-name>/app-files
and at the
same time rename the file name to just .env
:
# mv <path-to-your-dot-env-file>/.env.test .env
Next, copy both start-app.sh
and stop-app.sh
from the
on-premises-files
folder to the root app-files
folder:
# cp on-premises-files/usr/local/hop/<your-project-name>/bin/{start-app.sh,stop-app.sh} .
Now change the permissions of the files in the directory to be owned by the application’s user and group. You created them in a previous step. If you followed the guide, both user and group should have the same name. That is, the name of your project.
# chown -R <your-project-name>:<your-project-name> * .??*
Next step is to setup the systemd
files. Assuming you are in the
same folder as in the previous command, copy the file in
on-premises-files/etc/systemd/system/<your-project-name>-app.service
to /etc/systemd/system/
:
# cp on-premises-files/etc/systemd/system/<your-project-name>-app.service /etc/systemd/system/
The next steps requires you to login as the application user. So login as the application user first and then proceed with the next steps:
# su - <your-project-name>
If you type pwd
on your console you should be in
/usr/local/hop/<your-project-name>
, your home folder. With that in
mind, copy the files .bashrc
and .profile
from
~/app-files/on-premises-files/usr/local/hop/<your-project-name>/{.bashrc,.profile}
to your home folder:
$ cp ~/app-files/on-premises-files/usr/local/hop/<your-project-name>/{.bashrc,.profile} ~/
Now create the a bin
folder in your home directory and copy the
script that will run the application with healthchecks:
$ mkdir -p ~/bin
$ cp ~/app-files/on-premises-files/usr/local/hop/<your-project-name>/bin/app-with-healthchecks.sh ~/bin
$ chmod 755 ~/bin/app-with-healthchecks.sh
At this point you can already run the application. As it is the first time, you have to run the application and do the steps listed in the output of the HOP CLI when you generated the project. In the case of this guide, our single post-installation step is to create the database schema and users. To do so, you need to run the application environment and connect to the database to execute the SQL statements that appear in the post-installation steps.
But before you do it, logout and login back so the changes you made to
the files .bashrc
and .profile
take effect. More importantly,
it will set an environment variable required to run the
app-with-healthchecks.sh
script.
$ logout
# su - <your-project-name>
Now run the following to start the application:
$ ~/bin/app-with-healthchecks.sh start
This might take a bit depending on your internet connection as it has
to download the required Docker images to run the environment. Once it
finishs downloading the images, it will print out the logs. Do not
worry if you see any errors in the app
logs, that is because the
database is not configured yet. To do so, go to ~/app-files
and
use docker-compose
to access the psql
shell:
$ cd ~/app-files
$ docker-compose exec psql --user <admin-user> <the-database-name-you-chose>
This will open the psql
shell. Now execute the SQL statements that
appear in the HOP CLI post-installation steps and then exit.
Now stop the application service:
$ ~/bin/app-with-healthchecks.sh stop
The remaining tasks will require you be a root user again, so logout:
$ logout
Finally you have to enable and run your application service:
# systemctl enable <your-project-name>-app.service
# systemctl start <your-project-name>-app.service
If everything works as expected you should see that the application service is up and running using the following command:
# systemctl status <your-project-name>-app.service
If it says the service is active and running, you have installed the application successfully!
SSL Termination
Now, the system is running but it is still available only on localhost and with no SSL termination. HOP offers two ways of achieving this:
Configuration for NGINX reverse proxy.
HTTPS Portal which automatically issues certificates with Let’s Encrypt.
NGINX
The NGINX reverse proxy configuration option which only provides a
.conf
file with the necessary configuration to do SSL termination
using NGINX. The file can be found in
/usr/local/hop/<your-project-name>/app-files/on-premises-files/etc/nginx/nginx.conf
. However
how you install NGINX and generate the certificates is up to you.
From this file point of view, you would only need to change the lines
68 and 69 to point to your certificate PEM and key file. The rest of
the configuration is ready to send the plain HTTP traffic to the
application’s reverse proxy sitting on 127.0.0.1:8081
.
HTTPS Portal
If you choose HTTPS Portal, this is the easiest way to setup SSL termination for your application. It uses Let’s Encrypt to get the SSL certificates for your domain and checks if they are expired every week and renew them 30 days before they expire.
HOP CLI will add to the generated project a docker-compose
file
named docker-compose.https-portal.to-deploy.yml
which is only used
for test and production environments (i.e., it will not run on
development). There is one important setting in that YAML file that
you need to change when going live which is the STAGE
environment
variable.
By default HOP sets it to staging
, which is also the default value
on HTTPS Portal. This means, HTTPS Portal will get test (untrusted)
certificates from Let’s Encrypt. When you are ready to go live, please
change that value in the .env
file located in the app-files
folder. Look for the HTTPS_PORTAL_STAGE
environment variable and
change its value to production
. For this change to take effect,
you will have to stop and start the application service:
# systemctl stop <your-project-name>-app.service
# systemctl start <your-project-name>-app.service
Now the application should be back up and running with new trusted Let’s Encrypt certificates.
Warning
It is extremely important that you know about Let’s Encrypt rate limits and how HTTPS Portal works in order to avoid hitting any road blocks when testing or setting up the production configuration.