# Installing Enterprise Agents on Cisco Routers with Docker

{% hint style="warning" %}
Due to recent platform-wide naming, navigation, and URL changes in the product, you may notice some discrepancies between the product and the screenshots displayed in our technical documentation. The instructions and actual pages in the product are still valid and haven’t changed. Please bear with us as we update our screenshots to better match the in-product experience. See the full scope of changes on [Naming and Navigation Menu changes - Summary List](https://docs.thousandeyes.com/whats-new/naming-and-nav-phase-2-changes).
{% endhint %}

This article provides a walkthrough for installing a ThousandEyes Enterprise Agent on a supported Cisco router. The agent is included in a ThousandEyes Docker image packaged in a signed tar file specific for installation using Cisco application hosting.

{% hint style="info" %}
As a part of container package best practices, we recommend updating your container regularly.
{% endhint %}

## Prerequisites

Review the supported devices and hardware requirements before continuing with the installation instructions:

* [Catalyst Routers](https://docs.thousandeyes.com/product-documentation/global-vantage-points/enterprise-agents/installing/cisco-devices/catalyst-routers)
* [Industrial Routers](https://docs.thousandeyes.com/product-documentation/global-vantage-points/enterprise-agents/installing/cisco-devices/industrial-routers)

{% hint style="info" %}
Both SD-WAN and Autonomous mode are supported.
{% endhint %}

{% hint style="warning" %}
The ThousandEyes for Government instance has additional requirements for Cisco Application Hosting installations. Refer to the [ThousandEyes for Government - FedRAMP® Moderate](https://docs.thousandeyes.com/product-documentation/thousandeyes-for-government#cisco-application-hosting) documentation for prerequisites and configuration requirements **before** continuing.
{% endhint %}

## Installation Steps

Deploying an Enterprise Agent on a Cisco router requires the completion of three steps. These steps are detailed in the sections below:

1. Install the Enterprise Agent on the Cisco router, using one of three available methods (bootflash, direct, via local machine).
2. Configure the container's networking and account information.
3. Verify the agent is running.

For Cisco routers purchased before August 15th, 2021, the Docker image can be installed either directly from the ThousandEyes download servers, or by downloading the container image to a local machine and uploading it to the router via SCP, FTP, TFTP, or USB storage, depending on whether the router has direct Internet access or not.

Routers purchased after August 15th, 2021, can, in addition to the previous methods, install the Enterprise Agent via bootflash.

### Install the Docker Image from Bootflash

If the router was purchased after August 15th, 2021, the router has the ThousandEyes Enterprise Agent available in bootflash.

{% hint style="info" %}
To verify if it is available, use the following command: `Dut1#dir bootflash:/apps`.

{% hint style="info" %}
The filename structure for ThousandEyes agent images is `thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar`. The two versions available and their corresponding md5 checksums are:

* thousandeyes-enterprise-agent-x86\_64-5.0.1.cisco.tar
  * md5sum: e8e04b77483d1338d15b4acbb88f9761
* thousandeyes-enterprise-agent-aarch64-5.0.1.cisco.tar
  * md5sum: 773fb8b365ec37fd36d6809c8ce81199

Older routers may have multiple image files installed in the `bootflash:/apps` folder, including 4.x images that use a different file structure. Make sure that the image file you use in the commands below is the newest one.

ThousandEyes also recommends deleting older agent images to free up additional bootflash space.
{% endhint %}
{% endhint %}

1. Run the following command to install via bootflash, replacing `<app-name>` with your application identifier and `<ARCH>-<VERSION>` with the router architecture and the current agent version:

   ```
   #app-hosting install appid <app-name> package bootflash:apps/thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar
   ```

### Install the Docker Image to the Router Directly

If the Cisco router has direct internet access, follow the steps below to install the Enterprise Agent:

1. Run the following command to install the image, replacing `<app-name>` with your application identifier and `<ARCH>-<VERSION>` with the router architecture and the current agent version:

   ```
   router#app-hosting install appid <app-name> package https://downloads.thousandeyes.com/enterprise-agent/thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar
   ```
2. Your application should now be installed. You can check on it by running the following:

   ```
   router#sh app-hosting list
   App id State
   thousandeyes_enterprise_agent DEPLOYED
   ```

   The output looks like:

   ```
   App id                                   State
   ---------------------------------------------------------
   thousandeyes_enterprise_agent            DEPLOYED
   ```

### Install the Docker Image via a Local Machine

If the Cisco router does not have direct access to the Internet, follow the steps in the sections below to install the Enterprise Agent.

#### Download the Docker Image to a Local Machine

Download the Docker image from the ThousandEyes dashboard and copy it to your Cisco router using SCP, FTP, TFTP, or USB storage.

1. On your local machine, log into the ThousandEyes platform using a login belonging to the account group that will be associated with the appliance.
2. Navigate to **Network & App Synthetics > Agent Settings** and click **Add New Enterprise Agent**; then navigate to **Cisco Application Hosting > Routers**.
3. Download the .tar file matching the router architecture.
4. Use SCP, FTP, TFTP, or USB storage to copy the signed Docker image to the router's flash: directory.
5. Run the following command, replacing `<ARCH>-<VERSION>` with the router architecture and the current agent version:

   ```
   copy scp://<username>@<host>/thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar flash:
   ```

{% hint style="info" %}
If the router is behind a http proxy, configure the following to allow the image to be downloaded and installed: `ip http client proxy-server <name> proxy-port <port>`
{% endhint %}

6. Run a checksum (md5) command to verify that the package transfer was successful, replacing `<ARCH>-<VERSION>` with the router architecture and the current agent version. The md5 output should match the latest md5sum. For example, the checksum for version 5.0.1 is `e8e04b77483d1338d15b4acbb88f9761`.

   ```
   router#verify /md5 bootflash:thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar
   ```

#### Install the Docker Image from a Local Machine

1. Enable the IOx framework on the router. Enter one configuration command per line, and end with CNTL/Z:

   ```
   router(config)#iox
   router(config)#end
   ```
2. Wait until all the services are running:

   ```
   show iox-service
   IOx Infrastructure Summary:
   IOx service (CAF)          	: Running
   IOx service (HA)           	: Not Supported
   IOx service (IOxman)       	: Running
   IOx service (Sec storage)  	: Not Supported
   Libvirtd 5.5.0             	: Running
   ```
3. Run the installation command, replacing `<app-name>` with your desired app name, `<ARCH>-<VERSION>` with the router architecture and the current agent version, and specifying the location of the image file you want to use. In this example, we use **thousandeyes\_enterprise\_agent**:

   ```
   app-hosting install appid <app-name> package bootflash:thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar
   ```
4. If the image is hosted on an HTTPS server, you can run the following command to download the image, replacing `<ARCH>-<VERSION>` with the router architecture and the current agent version:

   ```
   app-hosting install appid <app-name> package https://downloads.thousandeyes.com/enterprise-agent/thousandeyes-enterprise-agent-<ARCH>-<VERSION>.cisco.tar
   ```
5. Your application should now be installed. You can check on it by running the following:

   ```
   sh app-hosting list
   App id State
   thousandeyes_enterprise_agent DEPLOYED
   ```

## Configuration

Docker supports both static IP address assignment and dynamic IP address assignment. You must configure a single virtual network interface card (vNIC) for the appliance using either a management interface or virtual port group interface.

There are two available configuration paths, detailed in the sections below:

### Option One: VirtualPortGroup Interface

1. Configure the VirtualPortGroup interface with a private IP address and use as NAT inside:

   ```
   (config)interface VirtualPortGroup0
   (config)ip address 10.100.152.100 255.255.255.0
   (config)ip nat inside
   ```
2. Configure NAT outside on the physical port interface:

   ```
   (config)interface GigabitEthernet0/0/3
   (config) ip nat outside
   ```
3. Create NAT rule:

   ```
   (config)ip nat inside source list NAT interface GigabitEthernet0/0/3 overload
   (config)ip access-list extended NAT
   (config)10 permit ip 10.100.152.0 0.0.0.255 any
   ```
4. Configure the application, either with a static IP or with DHCP IP:

   a. Configuration with Static IP:

   Use a guest IP address to assign a static IP address. In this example, assign 10.100.152.120/24 from VirtualPortGroup 0 and use Google resolver:

   ```
   (config)#app-hosting appid thousandeyes-enterprise-agent
   (config-app-hosting)#app-vnic gateway0 virtualportgroup 0 guest-interface 0
   (config-app-hosting-gateway0)#guest-ipaddress 10.100.152.120 netmask 255.255.255.0
   (config-app-hosting-gateway0)#app-default-gateway 10.100.152.100 guest-interface 0
   (config-app-hosting-docker)#name-server0 8.8.8.8
   (config-app-hosting)#end
   ```

   Next, set up the required Docker run options to specify account token. If you want to specify a hostname other than the router's name, do this here as well:

   ```
   router(config-app-hosting)#app-resource docker
   router(config-app-hosting-docker)#prepend-pkg-opts
   router(config-app-hosting-docker)#run-opts 1 "-e TEAGENT_ACCOUNT_TOKEN=<Token>"
   router(config-app-hosting-docker)#run-opts 2 "--hostname Cisco-Docker"
   router(config-app-hosting)#start
   router(config-app-hosting)#end
   ```

   b. Configuration with DHCP IP:

   Make sure the DHCP server is running on the VirtualPortGroup interface.

   ```
   (config)#app-hosting appid thousandeyes-enterprise-agent
   (config-app-hosting)#app-vnic gateway0 virtualportgroup 0 guest-interface 0
   (config-app-hosting-docker)#name-server0 8.8.8.8
   (config-app-hosting)#end
   ```

   Next, set up the required Docker run options to specify the account token same as the static IP assignment example above.

   For a full list of the Docker configuration options, see [Docker Agent Configuration Options](https://docs.thousandeyes.com/product-documentation/global-vantage-points/enterprise-agents/installing/docker-agent-config-options).
5. Exit three times to completely exit out of config mode.
6. Use **wr mem** to ensure that your configuration changes have persisted across reboots:

   ```
   router#wr mem
   Building configuration...
   [OK]
   ```

### Option Two: Management Interface Configuration

1. Configure the management interface:

   ```
   interface GigabitEthernet0
      vrf forwarding Mgmt-intf
      ip address 10.82.139.212 255.255.255.0
      negotiation auto
   ```
2. Configure the application, either with a static IP or with DHCP IP:

   a. **Configuration with Static IP**:

   1. Use a guest IP address to assign a static IP address. In this example, assign `10.82.139.211/24` from GigabitEthernet 0 and use the Google resolver:

      ```
      (config)#app-hosting appid thousandeyes-enterprise-agent
      (config-app-hosting)#app-vnic management guest-interface 0
      (config-app-hosting-gateway0)#guest-ipaddress 10.82.139.211 netmask 255.255.255.0
      (config-app-hosting-gateway0)#app-default-gateway 10.82.139.212 guest-interface 0
      (config-app-hosting-docker)#name-server0 8.8.8.8
      (config-app-hosting)#end
      ```
   2. Set up the required Docker run options to specify the account token. If you want to specify a hostname other than the router's name, do this here as well:

      ```
      router(config-app-hosting)#app-resource docker
      router(config-app-hosting-docker)#prepend-pkg-opts
      router(config-app-hosting-docker)#run-opts 1 "-e TEAGENT_ACCOUNT_TOKEN=<Token>"
      router(config-app-hosting-docker)#run-opts 2 "--hostname Cisco-Docker"
      router(config-app-hosting)#start
      router(config-app-hosting)#end
      ```

      For a full list of the Docker configuration options, see [Docker Agent Configuration Options](https://docs.thousandeyes.com/product-documentation/global-vantage-points/enterprise-agents/installing/docker-agent-config-options).

   b. **Configuration with DHCP IP**:

   1. Make sure the DHCP server is running on the management interface:

      ```
      (config)#app-hosting appid thousandeyes-enterprise-agent
      (config-app-hosting)#app-vnic management guest-interface 0
      (config-app-hosting-docker)#name-server0 8.8.8.8
      (config-app-hosting)#end
      ```
   2. Set up the required Docker run options to specify the account token. If you want to specify a hostname other than the router's name, do this here as well:

      ```
      router(config-app-hosting)#app-resource docker
      router(config-app-hosting-docker)#prepend-pkg-opts
      router(config-app-hosting-docker)#run-opts 1 "-e TEAGENT_ACCOUNT_TOKEN=<Token>"
      router(config-app-hosting-docker)#run-opts 2 "--hostname Cisco-Docker"
      router(config-app-hosting)#start
      router(config-app-hosting)#end
      ```
3. Exit three times to completely exit out of config mode.
4. Use **wr mem** to ensure that your configuration changes have persisted across reboots:

   ```
   router#wr mem
   Building configuration...
   [OK]
   ```

## Verification

With the `(config-app-hosting)#start` command, the Docker container should have been started and should be running. You can verify this through the following options:

```
router# sh app-hosting list
App id                                   State
thousandeyes_enterprise_agent            RUNNING
```

Verify the Docker container’s details:

```
router#sh app-hosting detail appid thousandeyes_enterprise_agent
App id : thousandeyes-enterprise-agent
Owner : iox
State : RUNNING
Application
  Type : docker
  Name : ThousandEyes Enterprise Agent
  Version : 5.0.1
  Description : Perform active synthetic measurements to your business-critical applications. Get started at https://docs.thousandeyes.com/product-documentation/getting-started
  Author : ThousandEyes support@thousandeyes.com
  Path : https://downloads.thousandeyes.com/enterprise-agent/thousandeyes-enterprise-agent-x86_64-5.0.1.cisco.tar
  URL Path : bootflash:./thousandeyes-enterprise-agent-x86_64-5.0.1.cisco.tar
Activated profile name : custom

Resource reservation
  Memory : 500 MB
  Disk : 1 MB
  CPU : 1850 units
  CPU-percent : 9 %
  VCPU : 1

Platform resource profiles
  Profile Name                  CPU(unit) CPU(percent)  Memory(MB)  Disk(MB)
  ---------------------------------------------------------------------------

Attached devices
  Type              Name               Alias
  ---------------------------------------------
  serial/shell     iox_console_shell   serial0
  serial/aux       iox_console_aux     serial1
  serial/syslog    iox_syslog          serial2
  serial/trace     iox_trace           serial3

Network interfaces
   ---------------------------------------
eth0:
   MAC address         : 52:54:dd:e9:9e:9f
   IPv4 address        : 172.29.1.11
   IPv6 address        : ::
   Network name        : VPG0
```

In the ThousandEyes platform, go to **Network & App Synthetics > Agent Settings** and verify the Docker container’s IP address.

## Modify the Docker Container

1. Stop the application:

   ```
   router# app-hosting stop appid thousandeyes_enterprise_agent 
   thousandeyes_enterprise_agent stopped successfully
   Current state is: STOPPED
   ```
2. De-activate the application:

   ```
   router# app-hosting deactivate appid thousandeyes_enterprise_agent 
   thousandeyes_enterprise_agent deactivated successfully
   Current state is: DEPLOYED
   ```
3. Modify the Docker options, and exit three times:

   ```
   router(config)#app-hosting appid thousandeyes_enterprise_agent 
   router(config-app-hosting)#app-resource docker
   router(config-app-hosting-docker)#prepend-pkg-opts
   router(config-app-hosting-docker)#<run-opts command>
   router(config-app-hosting-docker)#exit
   router(config-app-hosting)#exit
   router(config)#exit
   ```
4. Reactivate the application, and confirm that it’s activated:

   ```
   router# app-hosting activate appid thousandeyes_enterprise_agent 
   thousandeyes_enterprise_agent activated successfully
   Current state is: ACTIVATED
   ```

   ```
   router#sh app-hosting list
   App id                                   State
   ---------------------------------------------------------
   thousandeyes-enterprise-agent            DEPLOYED
   ```
5. Start the application, and confirm that it is running:

   ```
   router# app-hosting start appid thousandeyes_enterprise_agent 
   thousandeyes_enterprise_agent started successfully
   Current state is: RUNNING
   ```

## Frequently Asked Questions

**What is the expected NTP behavior for a Catalyst 8000 series deployed Enterprise agent?**

The enterprise agent on a Catalyst 8000 series switch uses the host system kernel clock. It also sends packets to **pool.ntp.org** to determine any clock offset. It does not try to adjust the host or container clock but will adjust measurement timestamps based on the clock offset.

**Can the default external NTP source (pool.ntp.org) be changed to a customer's internal NTP source?**

No. The agent uses **pool.ntp.org** to determine clock offset by default; this is currently not configurable.

**How do I connect to the agent shell for Cisco agents?**

To access the agent shell of a Cisco Enterprise Agent that is actively running, use the following command, replacing `<app-name>` with your application identifier:

```
router#app-hosting connect appid <app-name> session
#
```

Once inside the agent shell, you can refer to the agent log for any further troubleshooting:

```
# tail /var/log/agent/te-agent.log
```

{% hint style="info" %}
If connection or DNS resolution errors are found in the log file, your agent cannot connect to the ThousandEyes platform. Check your app-vnic configuration and make sure the agent IP can reach the internet.
{% endhint %}

For more information on configuration options, see [Docker Agent Config Options](https://docs.thousandeyes.com/product-documentation/global-vantage-points/enterprise-agents/installing/docker-agent-config-options).

**Can I use ThousandEyes troubleshooting utilities?**

From Agent 4.0.2 onwards, `te-agent-utils` are pre-installed on Cisco Enterprise Agents. For more information on the available utilities, see [CLI Network Troubleshooting Utilities](https://docs.thousandeyes.com/product-documentation/internet-and-wan-monitoring/troubleshooting/cli-network-troubleshooting-utilities).

**What are the default trusted default root certificates used by the Enterprise Agent Docker container when communicating with ThousandEyes services?**

* issuer=O = Cisco, CN = Cisco Licensing Root CA
* issuer=O = Cisco, CN = Cisco Basic Assurance Root CA 2099
* issuer=O = Cisco, CN = Cisco ECC Root CA
* issuer=O = Cisco Systems, CN = Cisco Root CA 2048
* issuer=O = Cisco, CN = Cisco Root CA 2099
* issuer=O = Cisco, CN = Cisco Root CA M1
* issuer=O = Cisco, CN = Cisco Root CA M2
* issuer=C = US, O = Cisco Systems, CN = Cisco RXC-R2
* issuer=C = US, O = Amazon, CN = Amazon Root CA 1
* issuer=C = US, O = Amazon, CN = Amazon Root CA 2
* issuer=C = US, O = Amazon, CN = Amazon Root CA 3
* issuer=C = US, O = Amazon, CN = Amazon Root CA 4
* issuer=C = NO, O = Buypass AS-983163327, CN = Buypass Class 2 Root CA
* issuer=C = US, O = DigiCert Inc, OU = [www.digicert.com](http://www.digicert.com), CN = DigiCert Global Root CA
* issuer=C = US, O = Internet Security Research Group, CN = ISRG Root X1
* issuer=C = US, O = IdenTrust, CN = IdenTrust Commercial Root CA 1
* issuer=C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
* issuer=C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust ECC Certification Authority
* issuer=C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
* issuer=C = US, O = Google Trust Services LLC, CN = GTS Root R1
* issuer=C = US, O = Google Trust Services LLC, CN = GTS Root R2
* issuer=C = US, O = Google Trust Services LLC, CN = GTS Root R3
* issuer=C = US, O = Google Trust Services LLC, CN = GTS Root R4

**How do I install CA certificates on Cisco devices?**

For CA certificate installation instructions, see [Installing CA Certificates on Enterprise Agents](https://docs.thousandeyes.com/product-documentation/global-vantage-points/enterprise-agents/troubleshooting/installing-ca-certificates-on-enterprise-agents#installing-on-cisco-docker-devices).
