# CMA Deployment

> For an overview of CMA components, communication model, and network requirements, see the [CMA Deployment Architecture Overview](cma-deployment-architecture.md).

There are three ways a Cloudera Migration Assistant (CMA) server can be deployed:
- [Local Deployment Mode](#local-deployment)
- [Docker Deployment Mode](#docker-deployment)
- [Parcel Deployment Mode](#parcel-deployment)

You can deploy cma-server to any of your source cluster nodes, or in the case of local or docker mode, to an external node that has visibility to the cluster. It requires 1.5 GB of extra memory.

## Dependencies

Ensure that these components are installed on cma-server host :
- [Python 3.11](https://www.python.org/downloads/release/python-3110/)
- In local and parcel mode : [JDK17](https://jdk.java.net/archive/) (with JAVA_HOME set)
- In docker mode : [docker 20](https://docs.docker.com/engine/install/) or higher

### Python Packages

CMA downloads and installs the following Python packages at startup. In airgapped environments these must be pre-bundled in the CMA extras tarball.

#### Control Node

| Package | Version |
|---------|---------|
| ansible | 12.3.0 |
| ansible-core | 2.19.9 |
| certifi | 2026.4.22 |
| cffi | 2.0.0 |
| charset-normalizer | 3.4.7 |
| cryptography | 47.0.0 |
| idna | 3.13 |
| jinja2 | 3.1.6 |
| jmespath | 1.1.0 |
| markupsafe | 3.0.3 |
| packaging | 26.2 |
| pycparser | 3.0 |
| pyyaml | 6.0.3 |
| requests | 2.33.1 |
| resolvelib | 1.2.1 |
| urllib3 | 2.6.3 |

#### Remote Nodes

| Package | Version |
|---------|---------|
| pexpect | 4.9.0 |
| psycopg2-binary | 2.9.9 |
| ptyprocess | 0.7.0 |
| pymysql | 0.10.1 |

### Custom PyPI Repository

By default, CMA downloads Python packages from the public PyPI index. In airgapped or corporate
environments with internal PyPI mirrors (Artifactory, Nexus, devpi), you can configure CMA to use
a custom repository URL.

**Parcel deployment (Cloudera Manager):**

Set the **PyPI Index URL** (`cma_pip_index_url`) parameter in the CMA Master or CMA Agent service
configuration. For example: `https://nexus.corp.com/repository/pypi/simple/`

**Local deployment (CLI):**

```shell
cma-4.1.0-b5/bin/cma local start --pip-index-url='https://nexus.corp.com/repository/pypi/simple/'
```

**Agent deployment (CLI):**

```shell
cma-4.1.0-b5/bin/cma agent start --pip-index-url='https://nexus.corp.com/repository/pypi/simple/'
```

When a custom index URL is configured, CMA automatically passes `--trusted-host` to pip, so
self-signed certificates or internal CAs work without additional system trust store configuration.

Leave the setting empty to use the default public PyPI.

In case you have no JDK 17+ you can get it and install with these commands:

```shell
wget https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz 
tar xzf openjdk-17.0.2_linux-x64_bin.tar.gz -C /usr/java/
ln -s /usr/java/jdk-17.0.2 /usr/java/jdk-17
```
You can skip specify CMA Java Home when it is located on any of the  default paths :

- `/usr/java/jdk-17`
- `/usr/lib/jvm/java-17`
- `/usr/lib/jvm/jdk-17`
- `/usr/lib64/jvm/jdk-17`
- `/usr/lib/jvm/zulu-17`
- `/usr/lib/jvm/zulu17`
- `/usr/lib/jvm/java-17-oracle`
- `/usr/lib/jvm/java-17-openjdk`

## Local Deployment

### Download

Download the required binaries of the CMA tool into its own directory from https://archive.cloudera.com/cma/4.1.0-b5/.

```shell
wget https://archive.cloudera.com/cma/4.1.0/tars/cma-4.1.0-b5-bin.tar.gz
```
or
```shell
curl https://archive.cloudera.com/cma/4.1.0/tars/cma-4.1.0-b5-bin.tar.gz --output cma-4.1.0-b5-bin.tar.gz
```
Extract the downloaded file.
```shell
tar xzf cma-4.1.0-b5-bin.tar.gz
```

### Start

The preferred way of running CMA server is using docker,
however if you have constraints on docker you can install it directly on any host.

> **_NOTE:_** The script will create a python virtual environment in the top-level folder where the dependencies will be installed.
> Additionally, the script provides the following operations to manage the CMA locally:
> **start**,**stop**,**restart**,**rebuild**. If you want to know what other options are available, please see the help.
> ```cma-4.1.0-b5/bin/cma local --help```

Run the _cma_ script in the untarred top-level folder and follow its instructions to launch the CMA server locally.
```shell
cma-4.1.0-b5/bin/cma start
```

After around half a minute CMA server (aka control node) is reachable at _http://localhost:8090_ in a browser like Chrome
or Firefox.

On accessing CMA server it is redirected to the CMA Auth Server Sign In page (by default _http://localhost:8090/login_).

![CMA Log-in Page](../images/cma_log_in.png)

The default user password pair is admin-admin, but you can change your password and modify access on [CMA Auth Server](cma-role-access.md).

You  also need to make sure you that CMA host has a line of sight to the cluster nodes, by configuring _/etc/hosts_ or _/etc/resolv.conf_ files.

## Docker Deployment

### Download

Download CMA from arhive.cloudera.com same ways as  described in [Local Deployment](#local-deployment).

### Start

Make sure that docker 20+ is installed on the host. For more information, see [installing docker engine](https://docs.docker.com/engine/install/) documentation. Python 3.11 is also required.

In case you do not define the python executable when running the script, you will
be prompted to enter the python executable path.

> **_NOTE:_** The script will automatically create the docker image if necessary.
> Additionally, the script provides the following operations to manage the CMA docker container:
> **start**,**stop**,**restart**,**rebuild**. If you want to know what other options are available, please see the help.
> ```cma-4.1.0-b5/bin/cma docker --help```

Run the _cma_ script in the untarred top-level folder to launch the CMA server in a docker container.
```shell
cma-4.1.0-b5/bin/cma docker start
```

After around half a minute CMA server (aka control node) is reachable at _http://localhost:8090_ in a browser like Chrome
or Firefox.

On accessing CMA server it is redirected to the CMA Auth Server Sign In page (by default _http://localhost:8090/login_).

![CMA Log-in Page](../images/cma_log_in.png)

The default user password pair is admin-admin, but you can change your password and modify access on [CMA Auth Server](cma-role-access.md).

You also need to make sure that the CMA host has a line of sight to the cluster nodes, by configuring _/etc/hosts_ or _/etc/resolv.conf_ files.

## Parcel Deployment

CMA can be an add-on service in CM, and the generic way a service can be added is described in the its documentation in [Extending Cloudera Manager->Add-on Services](https://docs.cloudera.com/cdp-private-cloud-base/7.1.9/managing-clusters/topics/cm-add-on-services.html)

### Steps

1. Copy the CMA CSD files to `/opt/cloudera/csd/` directory on the Cloudera Manager node:
```shell
wget -P /opt/cloudera/csd/ https://archive.cloudera.com/cma/4.1.0-b5/csd/CMA-4.1.0-b5.jar
```
Cloudera Manager automatically detects the CSD files.

2. Change the ownership of the CSD files.
```shell
chown cloudera-scm:cloudera-scm /opt/cloudera/csd/CMA-4.1.0-b5.jar
```
3. Restart Cloudera Manager for the changes to take effect.
```shell
systemctl restart cloudera-scm-server
```
4. Log into Cloudera Manager
5. Restart Cloudera Management Service
6. Select **Hosts > Parcels** in the left navigation bar.
7. Search for CMA, and click **Download** to download the parcel to the local repository.
![Parcel Activation](../images/cma_parcel_distribution.png)
8. After the download is completed, click **Distribute** to distribute the parcel to all clusters.
9. After the parcel is distributed, click **Activate** to activate the parcel.
10. Click **OK** when confirmation is required.
11. Click **Clusters** on the left navigation pane.
12. Select the drop-down menu to the right of your cluster.
13. Select **Add Service**.
14. From the list, select the CMA service type to add, then click **Continue**. The single CMA parcel provides two service types:

    | Service | Description |
    |---------|-------------|
    | **CMA_MASTER** | The central control node (includes Gateway Server, Auth Server, Master Server roles). Deploy once, typically on a dedicated host or on the target cluster. |
    | **CMA_AGENT** | The cluster-side executor (includes Agent Server role). Deploy on each source and target cluster that participates in the migration. |

    You can deploy both services on the same cluster if needed (e.g., the target cluster runs both CMA Master and CMA Agent).

    The **Add Service wizard** opens.
15. Assign the service roles to the hosts where Python 3.11 and JDK 17+ are installed, and click **Continue**.
16. Click **Continue** after reviewing the configurations of the service.
![Add CMA Service](../images/cma_parcel_add_service.png)

    The first run of the service starts. When the command finishes, the service is added to the cluster.
![CMA Started](../images/cma_parcel_started.png)
17. Repeat steps 13–16 to add the other CMA service type if needed (e.g., add CMA_AGENT after CMA_MASTER, or vice versa).
18. Access the CMA User Interface (UI).

    After going back to the homepage of your cluster, open the CMA Master service page, and click on the **CMA Server UI** tab that opens the CMA UI.

![Landing Page](../images/cma_landing.png)

Clusters are registered automatically when CMA Agents are deployed and started. See [Registering Clusters](../migration/cma-cluster-registration.md) for details.

> **Agent configuration:** When the CMA Agent is deployed on a **different cluster** from the CMA Master, you must:
> 1. Set the **CMA Master** service dependency to **none** in the CMA Agent service configuration in Cloudera Manager (since CM cannot auto-discover the Master across clusters).
> 2. Set the **Gateway URL** (`cma_gateway_url`) in the CMA Agent service configuration.
>
> The agent uses the Gateway URL to automatically discover the Master host, gRPC port, and Auth Server URI via the discovery endpoint (`GET /api/agent/config`).
>
> **To find the Gateway URL:** In Cloudera Manager on the Master's cluster, open the **CMA Master** service and click the **CMA UI** link. The URL in your browser (up to the port) is the Gateway URL — typically `https://<master-host>:8093` (HTTPS) or `http://<master-host>:8090` (HTTP). You can verify it from the agent host with:
> ```shell
> curl -sk https://<master-host>:8093/api/agent/config
> ```
>
> For local or Docker deployments, use the `--gateway-url` flag. You can still override individual values (`--master-host`, `--grpc-port`, `--auth-server-uri`) if needed.

You can set up a local Vault instance to store secrets. Follow the instructions described [here](cma-vault-setup.md).

By default, CMA uses an embedded H2 database. A database password is **mandatory** for all database types, including H2. CMA generates credential files (`db.properties` and `auth-db.properties`) automatically during startup:

- **Parcel deployment**: Cloudera Manager generates the credential files from the CSD service descriptor at deploy time.
- **Local / Docker deployment**: The startup scripts (`common.sh`) generate the credential files when `CMA_DBA_PASS` is set.

For production deployments, CMA supports **PostgreSQL** as an external database. See [Configuring CMA with PostgreSQL](cma-postgresql-configuration.md) for setup instructions.

### OAuth2 Client Credentials

CMA uses two sets of OAuth2 client credentials for trusted communication between its components:

**Master credentials** (`cma_client_id` / `cma_client_secret`) — used by the Gateway Server to authenticate with the Auth Server. Configured on the CMA Master service.

**Agent credentials** (`cma_agent_client_id` / `cma_agent_client_secret`) — used by CMA Agents to authenticate to the Master's gRPC server. These values **must match** on both the CMA Master and every CMA Agent.

| Parameter | Default | Description |
|-----------|---------|-------------|
| `cma_client_id` | `cma` | OAuth2 client ID for Gateway ↔ Auth Server |
| `cma_client_secret` | — | OAuth2 client secret for Gateway ↔ Auth Server (**required**) |
| `cma_agent_client_id` | `cma-agent` | OAuth2 client ID for Agent ↔ Master gRPC |
| `cma_agent_client_secret` | — | OAuth2 client secret for Agent ↔ Master gRPC |

- **Parcel deployment**: Set these in Cloudera Manager under the CMA Master and CMA Agent service configurations. The CSD generates the credential files (`master-auth.properties`, `agent-auth.properties`) automatically.
- **Local / Docker deployment**: Use the `--client-secret` and `--agent-client-secret` flags, or set the `CMA_CLIENT_SECRET` and `CMA_AGENT_CLIENT_SECRET` environment variables. The startup scripts prompt interactively if they are not set.
