Installation

Once the prerequisites are in place (Ansible, Docker Swarm, and cluster initialization), you can customize the INFRA deployment using Ansible variables. These options allow you to configure user portals, the database, signal servers, SSL certificates, etc.

Tip

Installation parameters must be defined before running the final installation command.

Important

Before the final installation of the INFRA environment, all target machines must be able to access the images required for their deployment.
For Docker image management, refer to the Registry and Image Management documentation of the INFRA environment.

Create a minimal playbook

For the rest of the installation, create a playbook named reemo-infra.yml as referenced in this documentation.

- name: Installation Reemo Infra Server
    hosts: infra_manager
    gather_facts: yes

    roles:
        - reemo-infra

Minimal inventory file

For the rest of the installation, create an inventory file named inventory.yml as referenced in this documentation. This minimal file is described in the Prerequisites page of the INFRA environment.

It contains the server infrastructure description and the Reemo license key in base64 format.

Single server example:

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="

    infra_manager:
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"

SSL Certificates

All user connections go through a Traefik service. The infrastructure uses SSL certificates for exposing the Portal through Traefik as well as for internal communications between platform services.

Important

It is recommended to use a different PKI for internal communications than the one used for Traefik.

Traefik

Three modes are available:

Default certificate

By default, a self-signed certificate is automatically generated when creating the Traefik container. This mode is suitable for test environments but not recommended for production.

Local certificate

You can provide a certificate and key stored on the Ansible machine. The reemo-infra role deploys these files on the servers hosting Traefik.

Inventory example:

TRAEFIK_SSL_CERTS:
    - cert_file: "/localpath/to/cert.crt"
      key_file: "/localpath/to/key.key"

Certificate already present on the server

If certificates are already installed on the target servers, you can specify their local paths. They will then be mounted directly into the Traefik container.

Inventory example:

TRAEFIK_SSL_CERTS_REMOTE:
    - cert_file_remotepath: "/remotepath/to/cert.crt"
      key_file_remotepath: "/remotepath/to/key.key"

Internal communications

All micro-services communicate with each other using mTLS, which requires certificate management.
You have 3 options:

Default PKI

The reemo-infra Ansible role includes a complete, ready-to-use dedicated PKI. It enables a simple deployment with encrypted and authenticated internal communications.

Automatically generated CA

You can use a Certification Authority (CA) generated automatically when running the reemo-infra role.

Steps:

  1. Create a local directory on the Ansible machine, writable by the user running Ansible.

  2. Add the required options in the inventory file to enable this feature.

all:
    vars:
        LOCAL_PATH: "/opt/reemo/ssl"
        INITCA_ENABLE: "true"
    infra_manager:
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"
            infra_manager2:
                ansible_host: "10.0.0.2"
            infra_manager3:
                ansible_host: "10.0.0.3"

When the role starts, a CA will be created automatically in this directory. The associated keys and certificates will then be exported to the Docker Swarm cluster as Secrets and mounted into the containers that need them.

Manual configuration

You can also generate the SSL certificates yourself for the URLs:

  • reemo_portal

  • reemo_portaladmin

  • reemo_api

  • reemo_proapi

  • reemo_signal

  • reemo_provision

  • reemo_prorelayapi

  • reemo_procloudapi

  • reemo_relayws

Then specify in the Ansible inventory the local paths of the keys and certificates. They will be copied automatically to the Docker Swarm cluster by the reemo-infra role.

Example:

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        ...
    infra_manager:
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"
            infra_manager2:
                ansible_host: "10.0.0.2"
            infra_manager3:
                ansible_host: "10.0.0.3"
        vars:
            CA_SSL_CRT_LOCALPATH: "/local/path/ca.crt"
            API_SSL_CRT_LOCALPATH: "/local/path/reemo_api.crt"
            API_SSL_KEY_LOCALPATH: "/local/path/reemo_api.key"
            PROAPI_SSL_CRT_LOCALPATH: "/local/path/reemo_proapi.crt"
            PROAPI_SSL_KEY_LOCALPATH: "/local/path/reemo_proapi.key"
            PRORELAYAPI_SSL_CRT_LOCALPATH: "/local/path/reemo_prorelayapi.crt"
            PRORELAYAPI_SSL_KEY_LOCALPATH: "/local/path/reemo_prorelayapi.key"
            SIGNAL_SSL_CRT_LOCALPATH: "/local/path/reemo_signal.crt"
            SIGNAL_SSL_KEY_LOCALPATH: "/local/path/reemo_signal.key"
            PORTAL_SSL_CRT_LOCALPATH: "/local/path/reemo_portal.crt"
            PORTAL_SSL_KEY_LOCALPATH: "/local/path/reemo_portal.key"
            TRAEFIK_SSL_CERTS:
                - cert_file: "/local/path/domain.crt"
                  key_file: "/local/path/domain.key"

Managing User and Administrator Portals

Portal URLs

By default the Infra and Portal servers respond to all requests with a self-signed certificate.

If you need to set a specific URL for the User Portal, use the following variable:

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        ...
    infra_manager:
        vars:
            PORTAL_URL: "url.domain.tld"
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"
            infra_manager2:
                ansible_host: "10.0.0.2"
            infra_manager3:
                ansible_host: "10.0.0.3"

If you need to set a specific URL for the Administrator Portal, use the following variable:

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        ...
    infra_manager:
        vars:
            PORTAL_URL: "url.domain.tld"
            PORTALADMIN_URL: "urladmin.domain.ltd"
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"
            infra_manager2:
                ansible_host: "10.0.0.2"
            infra_manager3:
                ansible_host: "10.0.0.3"

Important

It is recommended not to expose the Administrator Portal to an external network. This portal is intended to be used within your internal network.

Warning

With PORTALADMIN_URL enabled, administrators can no longer log in via the User Portal URL.

IP filtering

You can enable IP filtering on both User and Administrator portals.

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        ...
    infra_manager:
        vars:
            PORTAL_URL: "url.domain.tld"
            PORTAL_URL_RESTRICT_IP: "10.1.1.1,10.2.2.0/24"
            PORTALADMIN_URL: "urladmin.domain.ltd"
            PORTALADMIN_URL_RESTRICT_IP: "10.3.1.2,10.3.2.0/24"
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"
            infra_manager2:
                ansible_host: "10.0.0.2"
            infra_manager3:
                ansible_host: "10.0.0.3"

Port management

By default the User Portal listens on port 443 with automatic redirection from port 80 to 443 over SSL.

For the Administrator Portal you can specify the port:

PORTALADMIN_URL_PORT: "8444"

Warning

The port must be different from 80, 443, and 8443 which are already used by other services.

Physical separation of Portals

The reemo-infra Ansible role lets you physically separate the User Portal and the Administrator Portal.

Portal dedicated to instance administrators

../../_static/images/infra/archi_infra_multidmz.png

To do this, create an inventory by replacing the infra_manager group with two groups: api_manager and portal_manager.

Note

You must set a HMACSECRET in the variables, shared between the two portals and the API. This secret is used to sign requests from the portals to the API.

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        HMACSECRET: "U6US67D70409RFAGQH5ZIWBFV8HX0UCZ"
portal_manager:
        children:
            portaluser_manager:
                vars:
                    PORTAL_URL: "url.domain.tld"
                    TRAEFIK_SSL_CERTS:
                        - cert_file: "/localpath/to/cert.crt"
                          key_file: "/localpath/to/key.key"
                    API_IP:
                        - ip: "10.3.1.1"
                        - ip: "10.3.1.2"
                        - ip: "10.3.1.3"
                hosts:
                    portaluser1:
                        ansible_host: "10.0.0.1"
                    portaluser2:
                        ansible_host: "10.0.0.2"
                    portaluser3:
                        ansible_host: "10.0.0.3"
            portaladmin_manager:
                vars:
                    PORTAL_URL: "admin.domain.tld"
                    TRAEFIK_SSL_CERTS:
                        - cert_file: "/localpath/to/cert.crt"
                          key_file: "/localpath/to/key.key"
                    API_IP:
                        - ip: "10.3.1.1"
                        - ip: "10.3.1.2"
                        - ip: "10.3.1.3"
                hosts:
                    portaladmin1:
                        ansible_host: "10.0.0.4"
                    portaladmin2:
                        ansible_host: "10.0.0.5"
                    portaladmin3:
                        ansible_host: "10.0.0.6"
api_manager:
        hosts:
            api1:
                ansible_host: "10.3.1.1"
            api2:
                ansible_host: "10.3.1.2"
            api3:
                ansible_host: "10.3.1.3"^

Warning

Note that in the example above, the URLs use the PORTAL_URL variable, even for the administrator portal. Use this value when only one portal is declared on a specific server.

Portal dedicated to an SSO

In addition to physical separation you can also restrict SSO connectors per portal.

../../_static/images/infra/onprem_multiconnector.png

When creating a connector you obtain a GUID which must then be entered in the inventory in the targeted portal section using the variable PORTAL_LDAP_CONNECTORS for LDAP connectors and PORTAL_SAML_CONNECTORS for SAML connectors.

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        HMACSECRET: "..."
portal_manager:
        children:
            portalsso_manager:
                vars:
                    PORTAL_URL: "urlsso.domain.tld"
                    TRAEFIK_SSL_CERTS:
                        - cert_file: "/localpath/to/cert.crt"
                          key_file: "/localpath/to/key.key"
                    PORTAL_LDAP_CONNECTORS:
                        - ldapid: "3182932d-9ee1-4c06-a4cf-c13c25f2ee93"
                    PORTAL_SAML_CONNECTORS:
                        - samlid: "692469bd-cb28-8332-aa65-9c95451c1a0e"
                hosts:
                    portalsso1:
                        ansible_host: "10.0.0.7"
                    portalsso2:
                        ansible_host: "10.0.0.8"
                    portalsso3:
                        ansible_host: "10.0.0.9"    

If you have multiple connectors to set on the same portal, add multiple ldapid or samlid lines.

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        HMACSECRET: "..."
portal_manager:
        children:
            portalsso_manager:
                vars:
                    PORTAL_URL: "urlsso.domain.tld"
                    TRAEFIK_SSL_CERTS:
                        - cert_file: "/localpath/to/cert.crt"
                          key_file: "/localpath/to/key.key"
                    PORTAL_LDAP_CONNECTORS:
                        - ldapid: "3182932d-9ee1-4c06-a4cf-c13c25f2ee93"
                        - ldapid: "9c713681-b758-4179-b9a2-13618a7b804e"
                    PORTAL_SAML_CONNECTORS:
                        - samlid: "692469bd-cb28-8332-aa65-9c95451c1a0e"
                        - samlid: "4418cfb9-52c5-4d7c-88d1-7660e7809d23"
                hosts:
                    portalsso1:
                        ansible_host: "10.0.0.7"
                    portalsso2:
                        ansible_host: "10.0.0.8"
                    portalsso3:
                        ansible_host: "10.0.0.9"

Signal Server per Portal

To fully separate the portals, you can assign specific Signal servers to them. These servers will be used by the containers launched from these portals.

portal_manager:
    vars:
        API_IP:
            - ip: "10.0.0.1"
    children:
        portal1_user:
            hosts:
                portal1_user1:
                ansible_host: "10.0.0.2"
                PORTAL_URL: "portal1.domain.tld"
                PROVISION_SIGNAL_IP:
                    - ip: "10.0.0.2"
        portal2_user:
            hosts:
                portal2_user1:
                ansible_host: "10.0.0.3"
                PORTAL_URL: "portal2.domain.tld"
                PROVISION_SIGNAL_IP:
                    - ip: "10.0.0.3"

Filtering user roles on a Portal

You can restrict the type of users allowed to connect to a specific portal. Filtering is based on the user role.

  • Instance Administrator

  • Organization Administrator

  • Organization Member

Main Portal

By default, all users can authenticate on a portal, but with PORTAL_TYPE you can restrict access to a specific user type.

PORTAL_TYPE

default

user

admin

orgadmin

instadmin

orguser

Instance Administrator

Organization Administrator

Organization Member

Admin Portal

The secondary portal is configured by default as a portal dedicated to administrators. You can specify which types of administrators can log in using PORTALADMIN_TYPE.

PORTALADMIN_TYPE

default

orgadmin

instadmin

Instance Administrator

Organization Administrator

Organization Member

Example with a portal dedicated to users and the admin portal dedicated only to instance administrators:

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        HMACSECRET: "..."
portal_manager:
    children:
        portaluser_manager:
            vars:
                PORTAL_URL: "url.domain.tld"
                PORTAL_TYPE: "user"
                TRAEFIK_SSL_CERTS:
                    - cert_file: "/localpath/to/cert.crt"
                        key_file: "/localpath/to/key.key"
            hosts:
                portaluser1:
                    ansible_host: "10.0.0.1"
                portaluser2:
                    ansible_host: "10.0.0.2"
                portaluser3:
                    ansible_host: "10.0.0.3"
        portaladmin_manager:
            vars:
                PORTAL_URL: "admin.domain.tld"
                PORTAL_TYPE: "instadmin"
                TRAEFIK_SSL_CERTS:
                    - cert_file: "/localpath/to/cert.crt"
                        key_file: "/localpath/to/key.key"
            hosts:
                portaladmin1:
                    ansible_host: "10.0.0.4"
                portaladmin2:
                    ansible_host: "10.0.0.5"
                portaladmin3:
                    ansible_host: "10.0.0.6"
api_manager:
    hosts:
        api1:
            ansible_host: "10.3.1.1"
        api2:
            ansible_host: "10.3.1.2"
        api3:
            ansible_host: "10.3.1.3"

Signaling Services

Signaling services are used for registering Reemo Agents on the platform, and for exchanging information required to establish a connection between the user and their resources. These services are unique, and in a Docker Swarm environment you will see, depending on your architecture, several Signaling services but always with a single replica.

Example:

ID             NAME            MODE        REPLICAS  IMAGE
...
 g8hmzpicyq2o   reemo_signal1   replicated  1/1      registry.reemo.io/reemoinfrasignal                   
 s105if31h6l0   reemo_signal2   replicated  1/1      registry.reemo.io/reemoinfrasignal

Tip

Signaling services will always be named reemo_signal followed by a number.

Ports

By default Signaling services listen on port 8443 through the Traefik service which holds the SSL certificate. This port is accessible by Reemo Agents. Users will reach it via the Portal service on port 443.

SSL

Certificates are managed the same way as for the portals: one certificate for Traefik, and a second for communication between Traefik/Portal and Signaling services.

Multi-signal

In a standard installation, Reemo agents register with the signaling services that are shared by the different user access portals. For a complete separation of portals and agents, it is possible to configure a multi-signal installation. Each portal and provisioning environment will use its own signaling services to ensure a complete separation of user environments.

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
        HMACSECRET: "..."
portal_manager:
    vars:
        API_IP:
            - ip: "10.0.0.3"
    children:
        portal1_user:
            hosts:
                portal1_user1:
                    ansible_host: "10.0.0.1"
                    PORTAL_URL: "portal1.domain.tld"
                    PROVISION_SIGNAL_IP:
                        - ip: "10.0.0.1"
        portal2_user:
            hosts:
                portal2_user1:
                    ansible_host: "10.0.0.2"
                    PORTAL_URL: "portal2.domain.tld"
                    PROVISION_SIGNAL_IP:
                        - ip: "10.0.0.2"

CRON

Several CRON services are used in a Reemo platform.

Important

These services must be unique. When using multiple infra or API servers/clusters, choose the server/cluster that will run these services and disable them on others with CRON_ENABLE: “false”.

APICRON

This service manages the platform’s general tasks.

Available option:

  • API_cronGhostContainersMinutes: sets the expiration time for containers that remain UP in the PROVISION environment but are no longer known to the interface, also called Ghost Containers.

APICRONLOG

Service that deletes logs and events exceeding the configured retention period.

Available options:

  • API_CRONLOG_INTERVAL: Interval in hours between two log deletion requests (default 24 hours)

  • API_CRONLOG_RETENTION: Log retention time in months (default 12 months)

APICRONLDAP

Service for synchronization with an LDAP server.

Available option:

  • API_CRONLDAP_INTERVAL: Interval in minutes between each synchronization with the LDAP server (default 60 minutes)

Database

The INFRA environment requires a database which can be internal or external to Docker Swarm.

External database

To configure access to an external database, set the following variables depending on the database engine:

MySQL

DB_USER: "< Username to authenticate to the database >"
DB_USER_PASSWORD: "< Password to authenticate to the database >"
DB_NAME: "< Database name >"
DB_HOST: "< IP >"
DB_DIALECT: "mysql"

PostgreSQL

DB_USER: "< Username to authenticate to the database >"
DB_USER_PASSWORD: "< Password to authenticate to the database >"
DB_NAME: "< Database name >"
DB_HOST: "< IP >"
DB_DIALECT: "postgresql"

Add SSL support

To add SSL support for the database connection, use the following options in the Ansible inventory:

DB_SSL_REQUIRE: "true"
DB_SSL_CERT_LOCALPATH: "/local/path/cert.crt"
DB_SSL_KEY_LOCALPATH: "/local/path/key.key"
DB_SSL_CA_LOCALPATH: "/local/path/ca.crt"

Internal database

By default a MySQL server is included in the reemo-infra role. It will be deployed and configured automatically if an external database is not provided.

MySQL

By default a MySQL database is deployed in the Docker Swarm environment.

On a single-server architecture, the local directory /opt/reemo will be mounted into the MySQL container to store the database.

Warning

If you do not plan to use MySQL NDBCLUSTER, you must replicate the /opt/reemo directories so the MySQL container can restart on another node in case of failure and retain all existing database data.

MySQL NDBCLUSTER

To enable MySQL NDBCLUSTER, add DB_DIALECT=NDBCLUSTER in the inventory, and the hostnames of the nodes in your Swarm cluster:

all:
    vars:
        API_LICENSE: "ewogICAg ... Uw5NXhGVDF0NFU2TkxOdjQvZU53PT0iCiAgICC9Cn0="
    infra_manager:
        vars:
            DB_DIALECT: "NDBCLUSTER"
            MYSQL_CLUSTER_DataMemory: 2G # increase DB memory (default 2G)
            MYSQL_CLUSTER_PATH: "/data/mysqlcluster" # Path for NDBCLUSTER services data (default "/data/mysqlcluster")
            MYSQL_NODE_HOSTNAME_DB1: "infra1"
            MYSQL_NODE_HOSTNAME_DB2: "infra2"
            MYSQL_NODE_HOSTNAME_DB3: "infra3"
        hosts:
            infra_manager1:
                ansible_host: "10.0.0.1"
            infra_manager2:
                ansible_host: "10.0.0.2"
            infra_manager3:
                ansible_host: "10.0.0.3"

Tip

NDBCLUSTER requires at least 8 GB of RAM per node.

Warning

Recommended latency is under 1 ms between nodes. Between 1 and 5 ms performance may drop. Above 5 ms there is risk of slowdowns and instability.

Database initialization

Before it can be used, the database must be initialized.
Database initialization also initializes the default values of the Reemo instance, which are then stored in the database.

Here are the default variables you can set during database initialization:

INIT_MINIMUM_PASSWORD_LENGTH: "8"
INIT_PASSWORD_REQUIRE_LETTERS: "false"
INIT_PASSWORD_REQUIRE_DIGITS: "false"
INIT_PASSWORD_REQUIRE_SPECIALCHAR: "false"

Database initialization occurs during the final installation using INIT_DB=true.

Note

Database initialization must be performed only once.

Final installation

Once your inventory is ready, run the final installation of the INFRA environment and initialize the database with the reemo-infra Ansible role.

ansible-playbook -i inventory.yml playbooks/reemo-infra.yml --extra-vars "INIT_DB=true"

Warning

This command installs the environment and initializes the database. Run it only once.