<a id="install-c3-single-node"></a>

# Single-Node Installation

You can install Control Center with Confluent Platform on a single node using archives. For a
quick development setup, see [Quick Start for Control Center with Docker](../quickstart.md#c3-quickstart-docker). For production, see
[Multi-Node Installation for Production](multi-node.md#install-c3-multi-node-manual).

Considerations:
: - Control Center introduces a new directory structure that differs from the directory structure used with Control Center (Legacy).
  - In earlier versions of the Confluent Platform, there was a single main directory, commonly referenced as `CONFLUENT_HOME`
    and all components, including Control Center (Legacy), were inside this main directory (that is, `CONFLUENT_HOME/control-center`).
  - Control Center now has its own top-level directory, `CONTROL_CENTER_HOME`.
  - `CONTROL_CENTER_HOME` is placed at the same hierarchical level as `CONFLUENT_HOME`, not inside it.
  - The steps below offer the optimal order in which to install Confluent Platform with Control Center.

Prerequisites:
: - Provision a new virtual machine (VM) for Control Center on the same network as the Confluent Platform clusters that you want to monitor.
  - For VM sizing recommendations, see [System requirements](system-requirements.md#install-c3-system-reqs).
  - Install the same version of openjdk that is on your existing Control Center (Legacy) (openjdk-8-jdk, openjdk-11-jdk, or openjdk-17-jdk).
  - On the Control Center VM, open ports 9090 (Control Center) and 9021 (Control Center user interface).
  - On every broker or KRaft controller, ensure that you can send outgoing http traffic to port 9090 on the Control Center VM.

### KRaft

### Confluent Platform 8.1+

Considerations:
: - With local installations, the default port settings are as follows: Alertmanager uses port 9098 and controllers in KRaft mode use port 9093.

1. Download the Confluent Platform archive 8.2 and run these commands:
   ```bash
   wget https://packages.confluent.io/archive/8.2/confluent-8.2.0.tar.gz
   ```

   ```bash
   tar -xvf confluent-8.2.0.tar.gz
   ```

   ```bash
   cd confluent-8.2.0
   ```

   ```bash
   export CONFLUENT_HOME=`pwd`
   ```
2. Download the Control Center archive and run these commands:
   ```bash
   wget https://packages.confluent.io/confluent-control-center-next-gen/archive/confluent-control-center-next-gen-2.5.0.tar.gz
   ```

   ```bash
   tar -xvf confluent-control-center-next-gen-2.5.0.tar.gz
   ```

   ```bash
   cd confluent-control-center-next-gen-2.5.0
   ```

   ```bash
   export CONTROL_CENTER_HOME=`pwd`
   ```
3. Change directory to the `$CONFLUENT_HOME/bin` directory:
   ```none
   export PATH=$PATH:$CONFLUENT_HOME/bin
   ```
4. Use the Confluent CLI to run the following command:
   ```bash
   confluent local services start
   ```

### Confluent Platform 7.7 - 8.0

Considerations:
: - You must use a special command to start Prometheus on MacOS.
  - By default Alertmanager and controllers in KRaft mode use port 9093. To run Prometheus and Alertmanager and KRaft mode controllers
    on the same host, you must manually edit the provided Control Center scripts.

1. Download the Confluent Platform archive (7.7 to 8.0 supported) and run these commands:
   ```bash
   wget https://packages.confluent.io/archive/8.0/confluent-8.0.0.tar.gz
   ```

   ```bash
   tar -xvf confluent-8.0.0.tar.gz
   ```

   ```bash
   cd confluent-8.0.0
   ```

   ```bash
   export CONFLUENT_HOME=`pwd`
   ```
2. Update the broker and controller configurations to emit metrics to Prometheus by adding
   the following configurations to: `etc/kafka/controller.properties` and `etc/kafka/broker.properties`

   The fifth line (`confluent.telemetry.exporter._c3.metrics.include=<value>`) is very long. Simply copy
   the code block as provided and append it to the end of the properties files. Pasting the fifth line results in a single line,
   even though it shows as wrapped in the documentation.
   ```properties
   metric.reporters=io.confluent.telemetry.reporter.TelemetryReporter
   confluent.telemetry.exporter._c3.type=http
   confluent.telemetry.exporter._c3.enabled=true
   confluent.telemetry.exporter._c3.metrics.include=io.confluent.kafka.server.request.(?!.*delta).*|io.confluent.kafka.server.server.broker.state|io.confluent.kafka.server.replica.manager.leader.count|io.confluent.kafka.server.request.queue.size|io.confluent.kafka.server.broker.topic.failed.produce.requests.rate.1.min|io.confluent.kafka.server.tier.archiver.total.lag|io.confluent.kafka.server.request.total.time.ms.p99|io.confluent.kafka.server.broker.topic.failed.fetch.requests.rate.1.min|io.confluent.kafka.server.broker.topic.total.fetch.requests.rate.1.min|io.confluent.kafka.server.partition.caught.up.replicas.count|io.confluent.kafka.server.partition.observer.replicas.count|io.confluent.kafka.server.tier.tasks.num.partitions.in.error|io.confluent.kafka.server.broker.topic.bytes.out.rate.1.min|io.confluent.kafka.server.request.total.time.ms.p95|io.confluent.kafka.server.controller.active.controller.count|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.total|io.confluent.kafka.server.request.total.time.ms.p999|io.confluent.kafka.server.controller.active.broker.count|io.confluent.kafka.server.request.handler.pool.request.handler.avg.idle.percent.rate.1.min|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.rate.1.min|io.confluent.kafka.server.controller.unclean.leader.elections.rate.1.min|io.confluent.kafka.server.replica.manager.partition.count|io.confluent.kafka.server.controller.unclean.leader.elections.total|io.confluent.kafka.server.partition.replicas.count|io.confluent.kafka.server.broker.topic.total.produce.requests.rate.1.min|io.confluent.kafka.server.controller.offline.partitions.count|io.confluent.kafka.server.socket.server.network.processor.avg.idle.percent|io.confluent.kafka.server.partition.under.replicated|io.confluent.kafka.server.log.log.start.offset|io.confluent.kafka.server.log.tier.size|io.confluent.kafka.server.log.size|io.confluent.kafka.server.tier.fetcher.bytes.fetched.total|io.confluent.kafka.server.request.total.time.ms.p50|io.confluent.kafka.server.tenant.consumer.lag.offsets|io.confluent.kafka.server.session.expire.listener.zookeeper.expires.rate.1.min|io.confluent.kafka.server.log.log.end.offset|io.confluent.kafka.server.broker.topic.bytes.in.rate.1.min|io.confluent.kafka.server.partition.under.min.isr|io.confluent.kafka.server.partition.in.sync.replicas.count|io.confluent.telemetry.http.exporter.batches.dropped|io.confluent.telemetry.http.exporter.items.total|io.confluent.telemetry.http.exporter.items.succeeded|io.confluent.telemetry.http.exporter.send.time.total.millis|io.confluent.kafka.server.controller.leader.election.rate.(?!.*delta).*|io.confluent.telemetry.http.exporter.batches.failed
   confluent.telemetry.exporter._c3.client.base.url=http://localhost:9090/api/v1/otlp
   confluent.telemetry.exporter._c3.client.compression=gzip
   confluent.telemetry.exporter._c3.api.key=dummy
   confluent.telemetry.exporter._c3.api.secret=dummy
   confluent.telemetry.exporter._c3.buffer.pending.batches.max=80
   confluent.telemetry.exporter._c3.buffer.batch.items.max=4000
   confluent.telemetry.exporter._c3.buffer.inflight.submissions.max=10
   confluent.telemetry.metrics.collector.interval.ms=60000
   confluent.telemetry.remoteconfig._confluent.enabled=false
   confluent.consumer.lag.emitter.enabled=true
   ```
3. Download the Control Center archive and run these commands:
   ```bash
   wget https://packages.confluent.io/confluent-control-center-next-gen/archive/confluent-control-center-next-gen-2.5.0.tar.gz
   ```

   ```bash
   tar -xvf confluent-control-center-next-gen-2.5.0.tar.gz
   ```

   ```bash
   cd confluent-control-center-next-gen-2.5.0
   ```

   ```bash
   export C3_HOME=`pwd`
   ```
4. Start Prometheus and Alertmanager

   To start Control Center, you must have three dedicated command windows: one for Prometheus, another for the Control Center process,
   and a third dedicated command window for Alertmanager. Run the following commands from `$C3_HOME` in all command windows.
   1. Open `etc/confluent-control-center/prometheus-generated.yml` and change `localhost:9093` to `localhost:9098`
      ```yaml
      alerting:
         alertmanagers:
            - static_configs:
               - targets:
                  - localhost:9098
      ```
   2. Start Prometheus.

      All operating systems except MacOS:
      ```bash
      bin/prometheus-start
      ```

      MacOS:
      ```bash
      bash bin/prometheus-start
      ```

      #### NOTE
      Prometheus runs but does not output any information to the screen.
   3. Start Alertmanager.
      1. Run this command:
         ```bash
         export ALERTMANAGER_PORT=9098
         ```
      2. All operating systems except MacOS:
         ```bash
         bin/alertmanager-start
         ```

         MacOS
         ```bash
         bash bin/alertmanager-start
         ```
5. Start Control Center.
   1. Open `etc/confluent-control-center/control-center-dev.properties` and update port `9093` to `9098`:
      ```properties
      confluent.controlcenter.alertmanager.url=http://localhost:9098
      ```
   2. Run this command:
      ```bash
      bin/control-center-start etc/confluent-control-center/control-center-dev.properties
      ```
6. Start Confluent Platform.

   To start Confluent Platform, you must have two dedicated command windows, one for the controller and another for the broker process. All
   the following commands are meant to be run from `CONFLUENT_HOME` in both command windows. The Confluent Platform start sequence requires
   you to generate a single random ID and use that *same* ID for both the controller and the broker process.
   1. In the command window dedicated to running the controller, change directories into `CONFLUENT_HOME`.
      ```bash
      cd $CONFLUENT_HOME
      ```
   2. Generate a random value for `KAFKA_CLUSTER_ID`.
      ```bash
      KAFKA_CLUSTER_ID="$(bin/kafka-storage random-uuid)"
      ```
   3. Use the following command to get the random ID and save the output. You need this value to start the controller *and*
      the broker.
      ```bash
      echo $KAFKA_CLUSTER_ID
      ```
   4. Format the log directories for the controller:
      ```bash
      bin/kafka-storage format --cluster-id $KAFKA_CLUSTER_ID -c etc/kafka/kraft/controller.properties --standalone
      ```
   5. Start the controller:
      ```bash
      bin/kafka-server-start etc/kafka/kraft/controller.properties
      ```
   6. Open a command window for the broker and navigate to `CONFLUENT_HOME`.
      ```bash
      cd $CONFLUENT_HOME
      ```
   7. Set the `KAFKA_CLUSTER_ID` variable to the random ID you generated earlier with `kafka-storage random-uuid`.
      ```bash
      export KAFKA_CLUSTER_ID=<KAFKA-CLUSTER-ID>
      ```
   8. Format the log directories for this broker:
      ```bash
      bin/kafka-storage format --cluster-id $KAFKA_CLUSTER_ID -c etc/kafka/kraft/broker.properties
      ```
   9. Start the broker:
      ```bash
      bin/kafka-server-start etc/kafka/kraft/broker.properties
      ```

### ZooKeeper

Considerations:
: - You must use a special command to start Prometheus on MacOS.

1. Download the Confluent Platform archive (7.7 to 7.9 supported) and run these commands:
   ```bash
   wget https://packages.confluent.io/archive/7.9/confluent-7.9.0.tar.gz
   ```

   ```bash
   tar -xvf confluent-7.9.0.tar.gz
   ```

   ```bash
   cd confluent-7.9.0
   ```

   ```bash
   export CONFLUENT_HOME=`pwd`
   ```
2. Update broker configurations to emit metrics to Prometheus by adding
   the following configurations to: `etc/kafka/server.properties`
   ```bash
   metric.reporters=io.confluent.telemetry.reporter.TelemetryReporter
   confluent.telemetry.exporter._c3.type=http
   confluent.telemetry.exporter._c3.enabled=true
   confluent.telemetry.exporter._c3.metrics.include=io.confluent.kafka.server.request.(?!.*delta).*|io.confluent.kafka.server.server.broker.state|io.confluent.kafka.server.replica.manager.leader.count|io.confluent.kafka.server.request.queue.size|io.confluent.kafka.server.broker.topic.failed.produce.requests.rate.1.min|io.confluent.kafka.server.tier.archiver.total.lag|io.confluent.kafka.server.request.total.time.ms.p99|io.confluent.kafka.server.broker.topic.failed.fetch.requests.rate.1.min|io.confluent.kafka.server.broker.topic.total.fetch.requests.rate.1.min|io.confluent.kafka.server.partition.caught.up.replicas.count|io.confluent.kafka.server.partition.observer.replicas.count|io.confluent.kafka.server.tier.tasks.num.partitions.in.error|io.confluent.kafka.server.broker.topic.bytes.out.rate.1.min|io.confluent.kafka.server.request.total.time.ms.p95|io.confluent.kafka.server.controller.active.controller.count|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.total|io.confluent.kafka.server.request.total.time.ms.p999|io.confluent.kafka.server.controller.active.broker.count|io.confluent.kafka.server.request.handler.pool.request.handler.avg.idle.percent.rate.1.min|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.rate.1.min|io.confluent.kafka.server.controller.unclean.leader.elections.rate.1.min|io.confluent.kafka.server.replica.manager.partition.count|io.confluent.kafka.server.controller.unclean.leader.elections.total|io.confluent.kafka.server.partition.replicas.count|io.confluent.kafka.server.broker.topic.total.produce.requests.rate.1.min|io.confluent.kafka.server.controller.offline.partitions.count|io.confluent.kafka.server.socket.server.network.processor.avg.idle.percent|io.confluent.kafka.server.partition.under.replicated|io.confluent.kafka.server.log.log.start.offset|io.confluent.kafka.server.log.tier.size|io.confluent.kafka.server.log.size|io.confluent.kafka.server.tier.fetcher.bytes.fetched.total|io.confluent.kafka.server.request.total.time.ms.p50|io.confluent.kafka.server.tenant.consumer.lag.offsets|io.confluent.kafka.server.session.expire.listener.zookeeper.expires.rate.1.min|io.confluent.kafka.server.log.log.end.offset|io.confluent.kafka.server.broker.topic.bytes.in.rate.1.min|io.confluent.kafka.server.partition.under.min.isr|io.confluent.kafka.server.partition.in.sync.replicas.count|io.confluent.telemetry.http.exporter.batches.dropped|io.confluent.telemetry.http.exporter.items.total|io.confluent.telemetry.http.exporter.items.succeeded|io.confluent.telemetry.http.exporter.send.time.total.millis|io.confluent.kafka.server.controller.leader.election.rate.(?!.*delta).*|io.confluent.telemetry.http.exporter.batches.failed
   confluent.telemetry.exporter._c3.client.base.url=http://localhost:9090/api/v1/otlp
   confluent.telemetry.exporter._c3.client.compression=gzip
   confluent.telemetry.exporter._c3.api.key=dummy
   confluent.telemetry.exporter._c3.api.secret=dummy
   confluent.telemetry.exporter._c3.buffer.pending.batches.max=80
   confluent.telemetry.exporter._c3.buffer.batch.items.max=4000
   confluent.telemetry.exporter._c3.buffer.inflight.submissions.max=10
   confluent.telemetry.metrics.collector.interval.ms=60000
   confluent.telemetry.remoteconfig._confluent.enabled=false
   confluent.consumer.lag.emitter.enabled=true
   ```
3. Download the Control Center archive and run these commands:
   ```bash
   wget https://packages.confluent.io/confluent-control-center-next-gen/archive/confluent-control-center-next-gen-2.5.0.tar.gz
   ```

   ```bash
   tar -xvf confluent-control-center-next-gen-2.5.0.tar.gz
   ```

   ```bash
   cd confluent-control-center-next-gen-2.5.0
   ```
4. Start Control Center.

   To start Control Center, you must have three dedicated command windows: one for Prometheus, another for the Control Center process,
   and a third for Alertmanager. Run the following commands from `CONTROL_CENTER_HOME` in all command windows.
   1. Start Prometheus.
      ```bash
      bin/prometheus-start
      ```
   2. Start Alertmanager.
      ```bash
      bin/alertmanager-start
      ```
   3. Start Control Center.
      ```bash
      bin/control-center-start etc/confluent-control-center/control-center-dev.properties
      ```
5. Start Confluent Platform.

   Start ZooKeeper.
   ```bash
   bin/zookeeper-server-start etc/kafka/zookeeper.properties
   ```

   Start Kafka.
   ```bash
   bin/kafka-server-start etc/kafka/server.properties
   ```

## Secure your deployment

To secure Control Center, including TLS, SASL, authentication, RBAC, and securing the
Prometheus and Alertmanager components, see [Control Center Security on Confluent Platform](../security/overview.md#security-control-center).

## Verify Control Center is running

After the installation is complete, visit `http(s)://<c3-url>:9021` and wait for the metrics to start showing up in Control Center. It may take
a couple of minutes. Control Center looks exactly like Control Center (Legacy).

To confirm Control Center is running, use the following steps:

1. Open the network tab in Control Center.
2. Reload Control Center.
3. Locate the following API call: `/2.0/feature/flags`
4. Verify the following key is present in the response: `confluent.controlcenter.prometheus.enable: true`

## Related content

- [Quick Start for Control Center with Docker](../quickstart.md#c3-quickstart-docker)
- [Multi-Node Installation for Production](multi-node.md#install-c3-multi-node-manual)
- [Control Center Configuration Reference for Confluent Platform](configuration.md#controlcenter-configuration)
- [Control Center Security on Confluent Platform](../security/overview.md#security-control-center)
