# Installation

To run an agent, one single Docker container has to be started. The container image to be used is identical to the Connectware’s *protocol-mapper* image. The image tag (i.e. the version) of that container must be the exact same version as the Connectware, otherwise the agent cannot start to communicate with the Connectware. In the examples below the image tag (version) is stored as IMAGE\_TAG= 1.6.2

## Orchestration

Starting the container is accomplished by the chosen orchestration tool. The container can be started either by executing a `docker run` command, or by using `docker-compose` with a corresponding `docker-compose.yml` file, or by creating a deployment in a Kubernetes cluster, see examples below.

In either case the agent must be configured through environment variables made available to the container.

The following environment variables are **required**:

* `CYBUS_AGENT_MODE=distributed` (switches *protocol-mapper* to run in agent mode)
* `CYBUS_AGENT_NAME=<agentName>` (unique name identifying this agent instance)
* `CYBUS_MQTT_HOST=<connectwareHost>` (the IP/hostname of Connectware)

The following environment variables are optional:

* `CYBUS_MQTT_USERNAME=<userName>` Username for authentication in Connectware (default is `<agentName>`)
* `CYBUS_MQTT_SCHEME=<scheme>` (`mqtts` or `mqtt`, default: `mqtt`)
* `CYBUS_MQTT_PORT=<port>` (default: `1883`)

Additionally, it is *recommended* to persist the data (credentials) of the agent, guaranteeing unsupervised and automatic availability, even after power cycles. To achieve this persistency, a docker *volume mount* must be added for the container. The volume must be mounted to */data* in the container. The agent will automatically store the credentials on that volume and re-use them on subsequent start-up.

{% hint style="warning" %}
If multiple agents will be run on the same computer, each agent must use its own volume mount, as otherwise agents would overwrite each other’s data, including username and password credentials.
{% endhint %}

As an alternative to locally generated credentials, it is also possible to specify a password for this protocol-mapper agent directly by an additional environment variable `CYBUS_PROTOCOL_MAPPER_PASSWORD`. This might be useful in scenarios where the agent deployment is controlled by the same orchestration tool as the central Connectware instance. In most other cases it is recommended to let the agent generate local credentials, stored in a volume, and authorized to Connectware through the [client registration](https://docs.cybus.io/1-7-2/documentation/client-registry/granting-access) workflow.

It may also be useful to set the `hostname` property of the docker container to the local host’s hostname, because this name will be displayed in the [Admin-UI overview page](https://docs.cybus.io/1-7-2/documentation/agents/monitoring). If it is not set, the local docker container ID will be displayed instead (e.g. `d172c8c3667b`), which might look rather confusing in this overview page. Depending on the operating system, the suitable value for the hostname may be available as an environment variable `${HOSTNAME}` or it must be specified manually, as noted in the example below.

Agents use an unprivileged user by default. Some protocols or features need root permissions (for example USB access or promiscuous network mode). If you want to use a feature that requires root access, you simply need to execute the agent as user root.

In case of mutual TLS, first you need to enable it for the Broker:

* `CYBUS_BROKER_USE_MUTUAL_TLS="yes"` (default: `no`)

Some additional configuration is necessary on the agent:

* `CYBUS_MQTT_SCHEME` should be set to `mqtts`
* `CYBUS_MQTT_PORT` should target the appropriate port of the Broker, which listens for mqtts messages on `8883` by default
* `USE_MUTUAL_TLS=true` (default: `false`)
* You should mount your certificates as regular volumes. By default Connectware will look for the certifcates specified in these environment variables:
  * `AGENT_KEY=<key>` (default: `/connectware/certs/client/tls.key`)
  * `AGENT_CERT=<cert>` (default: `/connectware/certs/client/tls.crt`)
  * `CA=<caChain>` (default: `/connectware/certs/ca/ca-chain.pem`)

### **Example 1: docker-compose**

```yaml
version: '2.0'
services:
    protocol-mapper-agent:
        image: registry.cybus.io/cybus/protocol-mapper:${IMAGE_TAG}
        environment:
            CYBUS_AGENT_MODE: distributed
            CYBUS_AGENT_NAME: myAgent
            CYBUS_MQTT_HOST: 10.11.12.13
        volumes:
            - protocol-mapper-agent:/data
        restart: unless-stopped
        network_mode: host
        hostname: <some-suitable-hostname>
volumes:
    protocol-mapper-agent:
```

To start, create a new directory (e.g. `myAgent`). Inside, create a new file called `docker-compose.yml` with the above content and finally run:

```yaml
docker-compose up -d
```

Again it is noted that if multiple agents should run on the same computer, each agent must have defined its own docker volume, otherwise different agents would overwrite each other’s persisted data, including username and password credentials.

To execute the agent with root permission add `user: root` to the docker compose service:

```yaml
version: '2.0'
services:
  protocol-mapper-agent:
    user: root
    image: registry.cybus.io/cybus/protocol-mapper:${IMAGE_TAG}
    [...]
```

### **Example 2: docker run**

Using the environment variable IMAGE\_TAG= 1.6.2, the following command will run the agent directly (but with the comment lines removed):

```yaml
# The docker run command
docker run \
    # Make it run as an agent
  -e CYBUS_AGENT_MODE=distributed \
    # Set the name of the agent. This must match the agentName used in the commissioning file.
  -e CYBUS_AGENT_NAME=myAgent \
    # The IP address where Connectware is running.
  -e CYBUS_MQTT_HOST=10.11.12.13 \
    # Attach a volume so the agent can store data across restarts
  -v /tmp/cybus:/data \
    # Upon failures, restart the container
  --restart unless-stopped \
    # Run it in host mode networking
  --net=host \
    # Some suitable hostname of the container.
  --hostname=${HOSTNAME} \
    # The image to use
  registry.cybus.io/cybus/protocol-mapper:${IMAGE_TAG}
```

This will start an agent named `myAgent` that persists data to `/tmp/cybus` on the host OS.

To execute the agent with root permission add `--user=root` to the parameters of the docker run command.

### **Example 3: Kubernetes**

{% hint style="warning" %}
To run Connectware agents on Kubernetes we recommend to use our `connectware-agent` Helm chart. Learn how to use it in this [Cybus Learn article](https://www.cybus.io/learn/installing-connectware-agents-using-the-connectware-agent-helm-chart/).
{% endhint %}

If you prefer manual orchestration over using the Helm chart, you can use the following yaml manifest file, to run an agent on a Kubernetes cluster. You only need to configure the same parameters used by the others types of deployments.

This example only stores the agent data using an `emptyDir`. Replace this with a persistent volume for production use.

Additionally you will need to create a Kubernetes secret to store the Cybus registry credentials needed to fetch the Connectware container images. To create a secret like this, use the secret name `cybus-docker-registry` with the following command:

```yaml
kubectl create secret docker-registry cybus-docker-registry \
--docker-server=registry.cybus.io \
--docker-username=john.doe \
--docker-password=abcd123 \
--docker-email=john.doe@example.org
```

The username and password should be your Cybus Portal username and password. Alternatively, when using the Connectware license key, the username is `license` and the password is your Connectware license key.

The manifest file can be created from this example:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
    # The id for this kubernetes object
    name: connectware-agent-deployment
    labels:
        # Attach labels for easy group selection
        app: protocol-mapper-agent
spec:
    replicas: 1
    selector:
        matchLabels:
            app: protocol-mapper-agent
    template:
        metadata:
            labels:
                app: protocol-mapper-agent
        spec:
            # Configure volumes used by the agent to store data across restarts
            volumes:
                - name: agent-data-volume
                  emptyDir: {}
            containers:
                - name: protocol-mapper-agent
                  # Container image. Watch out: Must use identical version tag to current Connectware version!
                  image: registry.cybus.io/cybus/protocol-mapper:1.0.32
                  env:
                      # Make the protocol-mapper runs as an agent
                      - name: CYBUS_AGENT_MODE
                        value: 'distributed'
                        # Set the name of the agent. This must match the agentName used in the commissioning file.
                      - name: CYBUS_AGENT_NAME
                        value: 'myAgent'
                        # The IP address or hostname where the Connectware is running
                      - name: CYBUS_MQTT_HOST
                        value: '10.11.12.13'
                  ports:
                      # Expose the ports used by the agent.
                      - containerPort: 443
                  # Configure mount points
                  volumeMounts:
                      - mountPath: /data
                        name: agent-data-volume
                  # Configure resource limits
                  resources:
                      limits:
                          cpu: 4000m
                          memory: 4Gi
            # Kubernetes secret used to pull the images from the Cybus registry
            imagePullSecrets:
                - name: cybus-docker-registry
```

Manifest file for download:

{% file src="<https://4142639966-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7fj06nwrOaOPonB577Xs%2Fuploads%2Fgit-blob-07db084247a7b974b2a93068ae15e346858dcb84%2Fagent-deployment.yaml?alt=media>" %}

### **Example 4: Mutual TLS Agent**

```yaml
version: '2.0'
services:
    protocol-mapper-agent:
        image: registry.cybus.io/cybus/protocol-mapper:${IMAGE_TAG}
        environment:
            CYBUS_AGENT_MODE: distributed
            CYBUS_AGENT_NAME: myAgent
            CYBUS_MQTT_SCHEME: mqtts
            CYBUS_MQTT_HOST: 10.11.12.13
            CYBUS_MQTT_PORT: '8883'
            USE_MUTUAL_TLS: true
        volumes:
            - protocol-mapper-agent:/data
            - /mycerts:/connectware/certs/client
            - /myca:/connectware/certs/ca
        restart: unless-stopped
        network_mode: host
        hostname: <some-suitable-hostname>
volumes:
    protocol-mapper-agent:
```

## Network Requirements

For the configured agent container, no *incoming* TCP/IP port permissions are needed. All communication will be handled by *outgoing* connections.

In order for the agent container to reach the central Connectware, the following incoming TCP/IP ports are needed for the central Connectware. In other words, the agent must be able to initiate connections to the central Connectware via the following ports:

* 443/tcp (https), and
* 1883/tcp (mqtt) or 8883/tcp (mqtts), whichever is chosen in *CYBUS\_MQTT\_SCHEME*
