Initial setup

The BlueRange server and additional services required for logging, updating and monitoring are installed from the setup package available at BlueRange Setup@GitHub. Following is a walk-through of the installation steps outlined in the Readme.

Clone the setup

The installation files are downloaded:

$ cd /opt
$ sudo git clone https://github.com/bluerange-io/bluerange-setup.git
Cloning into 'bluerange-setup'...
[..]
$ cd bluerange-setup/docker

Further steps are carried out in the folder /opt/bluerange-setup/docker.

Configuring the server

Edit the configuration file:

$ hostname
my.bluerange.io
$ pwd
/opt/bluerange-setup/docker
$ sudo editor server.env

The server.env file consists of a number of KEY=VALUE pairs. As a minimum the hostname must be set as HOST variable. Ideally the server properly displays its name:[1]

$ hostname --all-fqdns
my.bluerange.io localhost.localdomain
$ hostname --fqdn
my.bluerange.io

The name given as e.g. HOST=my.bluerange.io must match the server certificate.

Check if the host is reachable by its name. Ping the host, for example, 'ping my.bluerange.io'. On local machines it can sometimes happen that the shown hostname is not part of your (local) DNS. In this case use the ip address instead (for test installations only).

For some features like requesting a password reset the server requires access to an SMTP email server:

SMTP_HOST=smtp-machine.my-domain.me
SMTP_PORT=25
SMTP_USERNAME=smtp-username
SMTP_PASSWORD=XXXXXXXX

The SMTP configuration is recommended but not strictly required. When omitted features depending on it may not be available.

By default, the installation picks up the passwords defined in the .env file:

$ cat .env
COMPOSE_PROJECT_NAME=bluerange
SYSTEM_ADMIN_PASSWORD=admin123
ORGA_ADMIN_PASSWORD=iot12345
ROOT_DATABASE_PWD=root-database-pwd-change-me
BLUERANGE_DATABASE_PASSWORD=bluerange-database-pwd-change-me
MONGO_PASSWORD=bluerange-mongodb-pwd-change-me
GRAFANA_DATABASE_PASSWORD=grafana-database-pwd-change-me
MINIO_ACCESS_KEY=mender-deployments
MINIO_SECRET_KEY=minio-secret-change-me

Please keep the COMPOSE_PROJECT_NAME as is. The remaining passwords should be overwritten in the server.env. Passwords may be generated using the command:

$ pwgen -snc 48 5
a0bYPrcyE7wOSFtYzKWBh1IJJBI2XqnqvTLli02Konep6FTq
S2u5hPTJFycERRcEOf08Aiqvkz3bslXjx8R7JWgWy80uoFrs
0WDNDk8gDGDVWirpxClwMA3oRvKbjIwfZ6Oqey8REHoR6Ykw
Xx9CDrSSRuchTI9anFiLEBrihf6Jpntjh3rb1WuEEuMwPEtE
cSfn7EzlD1UWXJd9ugJYM2UaLE7tBtHzVaZzxunKjM2pNFFS
The file uses shell escaping so that special characters in passwords may need to be escaped!

The minimal server.env file should look like this:

$ sudo cat server.env
HOST=my.bluerange.io
ROOT_DATABASE_PWD=a0bYPrcyE7wOSFtYzKWBh1IJJBI2XqnqvTLli02Konep6FTq
BLUERANGE_DATABASE_PASSWORD=S2u5hPTJFycERRcEOf08Aiqvkz3bslXjx8R7JWgWy80uoFrs
MONGO_PASSWORD=0WDNDk8gDGDVWirpxClwMA3oRvKbjIwfZ6Oqey8REHoR6Ykw
GRAFANA_DATABASE_PASSWORD=Xx9CDrSSRuchTI9anFiLEBrihf6Jpntjh3rb1WuEEuMwPEtE
MINIO_SECRET_KEY=cSfn7EzlD1UWXJd9ugJYM2UaLE7tBtHzVaZzxunKjM2pNFFS
Except the organization administrator’s password these passwords do not need to be entered by a human so there is no reason to use weak passwords.

The SYSTEM_ADMIN_PASSWORD=admin123 and ORGA_ADMIN_PASSWORD=iot12345 are used for initialization only and may be changed at any time later on in the UI of the server. The MINIO_ACCESS_KEY=mender-deployments may be chosen arbitrarily and need not be changed.

Configure certificates

The installation expects the following certificate-related files to be provided:

  • server.pem: certificate used for HTTPS which must match the HOST variable setting being the host machine name registered with DNS

  • server.key: private key for issuing the HTTPS certificate

  • ca.pem: additional CA certificate(s) used for signing the server.pem so that all of those PEMs form a full chain of trust

For using self-signed certificates the bluerange-compose.sh command discussed below provides provisioning that commences automatically when the certificate files above are not found. Following is a walk-through of the self-signed certificate provisioning process for demonstration purposes only that should be skipped when using your own certificates:

$ sudo ./bluerange-compose.sh
$ openssl genrsa -out ca.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
..............+++++
.......................................................+++++
e is 65537 (0x010001)
$ openssl req -new -x509 -key ca.key -out ca.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:DE
State or Province Name (full name) []:Germany
Locality Name (eg, city) [Default City]:Stuttgart
Organization Name (eg, company) [Default Company Ltd]:MWAY DIGITAL GmbH
Organizational Unit Name (eg, section) []:BlueRange
Common Name (eg, your name or your server's hostname) []:CA
Email Address []:
$ openssl x509 -in ca.crt -out ca.pem
$ openssl req -new -out cert.csr -config cert.conf
Generating a RSA private key
............................................................................+++++
..............+++++
writing new private key to 'cert.key'
-----
$ openssl ca -config ca.conf -extfile cert.conf -out cert.crt -infiles cert.csr
Using configuration from ca.conf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'DE'
stateOrProvinceName   :ASN.1 12:'Germany'
localityName          :ASN.1 12:'Stuttgart'
organizationName      :ASN.1 12:'MWAY DIGITAL GmbH'
organizationalUnitName:ASN.1 12:'BlueRange'
commonName            :ASN.1 12:'my.bluerange.io'
Certificate is to be certified until Apr  8 07:31:10 2022 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
$ openssl x509 -in newcerts/01.pem -out cert.pem
$ openssl verify -CAfile ca.crt cert.crt
cert.crt: OK
$ openssl rsa -inform PEM -in server.key -out server.rsa
writing RSA key

The certificate files generated are:

$ cat ca.pem
-----BEGIN CERTIFICATE-----
MIIDyTCCArGgAwIBAgIUPJnMsxqyEeyQJYz2Lq0TPkU2VqgwDQYJKoZIhvcNAQEL
[..]
U1hLGto0C/RumIUTOA==
-----END CERTIFICATE-----
$ cat server.pem
-----BEGIN CERTIFICATE-----
MIIDsjCCApqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJERTEQ
[..]
bMR4sZVaDzYN7u/IZTCBkO9ACVv5vNwUjlv2f8OiK1zZz5RTuxE=
-----END CERTIFICATE-----
$ cat server.key
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDbtvfMNCCzcI+j
[..]
9uIvu/UgwUJqfMi7RMwLyqk=
-----END PRIVATE KEY-----

The use of self-signed certificates is strongly discourages as it requires installation of the ca.pem CA certificate as a root certification authority on every client connecting to the server, incl. the BlueRange App and BlueRange Gateways.

The auto-provisioning above serves demonstration purposes only. If you already ran the commands above, in order to use your own certificates, firstly clean up the files created above:

$ sudo rm -rf ca.* cert.* serial* fullchain.pem newcerts anchors/* server.pem server.key server.rsa index.txt*

Now place the files ca.pem, server.pem and server.key in X.509 PEM format as shown above. Notice, the server.rsa and fullchain.pem files are generated by the script on first startup automatically for you.

Start BlueRange

This compose file defines the services: bluerange, database, mongodb, nginx, mosquitto, nodered, prometheus and grafana. The nodered service serves as an example of an IoT add-on middleware service and may be removed for production purposes.

To start BlueRange you can now use bluerange-compose.sh to start all the Docker containers defined in the yaml file:

$ sudo ./bluerange-compose.sh
-> docker-compose -p bluerange -f docker-compose.yml -f docker-compose.elasticsearch.yml -f docker-compose.mender.yml up -d
Creating network "bluerange_default" with the default driver
Creating volume "bluerange_mysql" with default driver
Creating volume "bluerange_mongodb" with default driver
Creating volume "bluerange_nodered" with default driver
Creating volume "bluerange_elasticsearch" with default driver
Creating volume "bluerange_redis" with default driver
Creating volume "bluerange_mender-artifacts" with default driver
Pulling mender-gui (mendersoftware/gui:1.7.0)...
[..]
Pulling elasticsearch (amazon/opendistro-for-elasticsearch:1.1.0)...
[..]
Pulling database (mariadb:10.4.8)...
[..]
Pulling minio (minio/minio:RELEASE.2018-09-25T21-34-43Z)...
[..]
Pulling mongodb (mongo:latest)...
[..]
Pulling bluerange (bluerange/bluerange:latest)...
[..]
Pulling mosquitto (relution/relution-mosquitto:latest)...
[..]
Pulling nginx (nginx:latest)...
[..]
Creating bluerange_database_1      ... done
Creating bluerange_mongodb_1       ... done
[..]
Creating bluerange_bluerange_1          ... done
Creating bluerange_mosquitto_1          ... done
[..]
Creating bluerange_nginx_1              ... done

-> mender-useradm$ useradm create-user --username=admin@my.bluerange.io --password=admin123
9d1982c8-5ab9-44a1-9abb-e7649d3be4ae

    BlueRange: https://my.bluerange.io:443  (admin / admin123)
       Mender: https://my.bluerange.io:444  (admin@my.bluerange.io / admin123)
      Grafana: https://my.bluerange.io:3000 (admin / admin123)
       Kibana: https://my.bluerange.io:5602 (admin / admin)
        Minio: https://my.bluerange.io:9000 (mender-deployments / cSfn7EzlD1UWXJd9ugJYM2UaLE7tBtHzVaZzxunKjM2pNFFS)
   Prometheus: http://my.bluerange.io:9090
ElasticSearch: https://my.bluerange.io:9201 (admin / admin)

This will download the Docker image of each service defined in the docker-compose.yml file before starting a Docker container for each service. Images are cached on the local machine, so future starts will be faster.

The compose files force using bluerange-compose.sh as a replacement of docker-compose. Running docker-compose directly will not work and issue an error instead.

It will take some time for the services to start up once the downloads complete. To see the log output of a specific container use the following command:

$ sudo ./bluerange-compose.sh logs --follow bluerange
Attaching to bluerange_bluerange_1
bluerange_1 Certificate was added to keystore
bluerange_1 Temp directory does not exist. It will be created.
bluerange_1 Expected configuration found in './application.yml' or environment variables
bluerange_1  ________  ___       ___  ___  _______   ________  ________  ________   ________  _______           ___  ___  ___
bluerange_1 |\   __  \|\  \     |\  \|\  \|\  ___ \ |\   __  \|\   __  \|\   ___  \|\   ____\|\  ___ \         |\  \|\  \|\  \
bluerange_1 \ \  \|\ /\ \  \    \ \  \\\  \ \   __/|\ \  \|\  \ \  \|\  \ \  \\ \  \ \  \___|\ \   __/|        \ \  \ \  \ \  \
bluerange_1  \ \   __  \ \  \    \ \  \\\  \ \  \_|/_\ \   _  _\ \   __  \ \  \\ \  \ \  \  __\ \  \_|/__       \ \  \ \  \ \  \
bluerange_1   \ \  \|\  \ \  \____\ \  \\\  \ \  \_|\ \ \  \\  \\ \  \ \  \ \  \\ \  \ \  \|\  \ \  \_|\ \       \/  /\/  /\/  /|
bluerange_1    \ \_______\ \_______\ \_______\ \_______\ \__\\ _\\ \__\ \__\ \__\\ \__\ \_______\ \_______\      /  ///  ///  //
bluerange_1     \|_______|\|_______|\|_______|\|_______|\|__|\|__|\|__|\|__|\|__| \|__|\|_______|\|_______|     /_ ///_ ///_ //
bluerange_1                                                                                                    |__|/|__|/|__|/
[..]

The log output can be stopped by pressing Ctrl-C.

After first startup, please check your container is all fine by rerunning the bluerange-compose.sh command. The command will retry restarting any failed containers. If all is well no container should be restarted:

$ sudo ./bluerange-compose.sh
$ docker-compose -p bluerange -f docker-compose.yml -f docker-compose.elasticsearch.yml -f docker-compose.mender.yml up -d
bluerange_elasticsearch_1 is up-to-date
bluerange_mongodb_1 is up-to-date
bluerange_minio_1 is up-to-date
bluerange_mender-redis_1 is up-to-date
bluerange_database_1 is up-to-date
bluerange_mender-gui_1 is up-to-date
bluerange_logagent_1 is up-to-date
bluerange_kibana_1 is up-to-date
bluerange_mender-useradm_1 is up-to-date
bluerange_mender-inventory_1 is up-to-date
bluerange_mender-device-auth_1 is up-to-date
bluerange_mender-deployments_1 is up-to-date
bluerange_mender-conductor_1 is up-to-date
bluerange_bluerange_1 is up-to-date
bluerange_mosquitto_1 is up-to-date
bluerange_nginx_1 is up-to-date
bluerange_mender-api-gateway_1 is up-to-date

mender-useradm$ useradm create-user --username=admin@my.bluerange.io --password=admin123
creating user failed: user with a given email already exists

    BlueRange: https://my.bluerange.io:443  (admin / admin123)
       Mender: https://my.bluerange.io:444  (admin@my.bluerange.io / admin123)
       Kibana: https://my.bluerange.io:5602 (admin / admin)
        Minio: https://my.bluerange.io:9000 (mender-deployments / cSfn7EzlD1UWXJd9ugJYM2UaLE7tBtHzVaZzxunKjM2pNFFS)
ElasticSearch: https://my.bluerange.io:9201 (admin / admin)

In case of any failed container, try the log command above to find out why things went wrong. A common source of issues is in DNS and HTTPS certificates which can be checked for validity, e.g.:

$ openssl s_client -connect my.bluerange.io:443
CONNECTED(00000003)
depth=1 C = DE, ST = Germany, L = Stuttgart, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = CA
verify error:num=19:self signed certificate in certificate chain
verify return:1
depth=1 C = DE, ST = Germany, L = Stuttgart, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = CA
verify return:1
depth=0 C = DE, ST = Germany, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = my.bluerange.io
verify return:1
---
Certificate chain
 0 s:C = DE, ST = Germany, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = my.bluerange.io
   i:C = DE, ST = Germany, L = Stuttgart, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = CA
 1 s:C = DE, ST = Germany, L = Stuttgart, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = CA
   i:C = DE, ST = Germany, L = Stuttgart, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDsjCCApqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJERTEQ
[..]
bMR4sZVaDzYN7u/IZTCBkO9ACVv5vNwUjlv2f8OiK1zZz5RTuxE=
-----END CERTIFICATE-----
subject=C = DE, ST = Germany, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = my.bluerange.io

issuer=C = DE, ST = Germany, L = Stuttgart, O = MWAY DIGITAL GmbH, OU = BlueRange, CN = CA

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2587 bytes and written 406 bytes
Verification error: self signed certificate in certificate chain
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: F63586BD4D75D65DF7FC1154AEB7440AE588488925F86B2FFC960BBD91B16331
    Session-ID-ctx:
    Master-Key: 899DA4E9386093FC55064056A2D5BD48468CBA2C6DADA798AF437B4C572C45A1D83E1EDB132CECA0136F1BEFE3029AC0
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - ce 31 29 2f 28 04 3a 69-02 ca 8e 36 27 c3 45 6d   .1)/(.:i...6'.Em
[..]
    00b0 - ef 08 99 63 09 61 a6 43-ab 81 d8 43 12 dc 05 5a   ...c.a.C...C...Z

    Start Time: 1617874016
    Timeout   : 7200 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
    Extended master secret: yes
---

As can be seen from the output above, the self-signed certificate from the previous chapter is in use. For a public certificate the return code reported should be 0, of course. The SSL check can be done for each of the services listed by bluerange-compose.sh as all of them are set up to TLS.

As a final check of the BlueRange server the health status can be queried:

$ curl --cacert ca.pem https://my.bluerange.io/actuator/health
{"status":"UP"}

The health status endpoint is available for integration into monitoring systems.

When fetching the health status providing server administrator credentials using basic-auth or an api-key further details are made available.

As a last step in server installation rebooting the host machine is recommended ensuring a properly configured networking environment and that all the services come up automatically.

Stopping the server

For maintenance, it might become necessary to stop all the services temporarily. This can be done by shutting down the composition without destroying volumes:

$ sudo ./bluerange-compose.sh down
Stopping bluerange_nginx_1              ... done
[..]
Stopping bluerange_mosquitto_1          ... done
Stopping bluerange_bluerange_1          ... done
[..]
Stopping bluerange_mongodb_1            ... done
Stopping bluerange_database_1           ... done
Removing bluerange_nginx_1              ... done
[..]
Removing bluerange_mosquitto_1          ... done
Removing bluerange_bluerange_1          ... done
[..]
Removing bluerange_mongodb_1            ... done
Removing bluerange_database_1           ... done
Removing network bluerange_default

This will not remove the downloaded images and preserves database data.

When you shut down a Docker container, data inside the container is potentially lost. This means data that needs to be persisted must be stored outside the container (e.g. on a mounted volume). The default configuration maps the data directories of MariaDB and MongoDB to Docker volumes named mysql and mongodb respectively.

BlueRange stores all of its data in the database, so no additional configuration should be needed. Make sure to include MariaDB and MongoDB in your backup strategy though.


1. In case hostname --fqdn does not display the correct hostname, chances are that DNS is not set up correctly.