> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chainstack.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Quick start
> Complete walkthrough from a fresh Ubuntu installation to a running Chainstack Self-Hosted Control Panel
This guide walks you through a complete installation of Chainstack Self-Hosted on a dedicated server, from a fresh Ubuntu installation to a running Control Panel.
## Overview
By the end of this guide, you will have:
* A Kubernetes cluster running on your server
* The Chainstack Self-Hosted Control Panel deployed and accessible
* The ability to deploy blockchain nodes through the web interface
## Prerequisites
Before starting, ensure you have:
* A dedicated server or virtual machine meeting the [system requirements](/docs/self-hosted/requirements)
* Root or sudo access to the server
* A stable internet connection
## End-to-end example
This example uses a dedicated server from Contabo running Ubuntu 22.04, but the steps apply to any compatible server.
Connect to your server via SSH and install the required dependencies:
```bash theme={"system"}
# Update package lists
apt update
# Install prerequisites
apt install curl gpg wget apt-transport-https --yes
# Install Helm
curl -fsSL https://packages.buildkite.com/helm-linux/helm-debian/gpgkey | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/helm.gpg] https://packages.buildkite.com/helm-linux/helm-debian/any/ any main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
apt update
apt install helm
# Install yq (mikefarah version)
wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
chmod +x /usr/local/bin/yq
# Verify installations
helm version
yq --version
```
k3s is a lightweight Kubernetes distribution that's easy to install and suitable for single-server deployments:
```bash theme={"system"}
# Install k3s
curl -sfL https://get.k3s.io | sh -
# Configure kubectl to use k3s
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# Make the configuration persistent
echo 'KUBECONFIG=/etc/rancher/k3s/k3s.yaml' >> /etc/environment
# Verify the cluster is running
kubectl cluster-info
kubectl get nodes
```
You should see output indicating the cluster is running and your node is in Ready state.
If you have multiple disks available for blockchain node data, set up LVM and TopoLVM for dynamic storage provisioning:
```bash theme={"system"}
# Install LVM tools
apt install lvm2
# Find your disk devices (paths vary by provider)
lsblk
ls -la /dev/disk/by-id/
# Create physical volumes (replace with your actual disk devices)
pvcreate /dev/sdb /dev/sdc /dev/sdd
# Create volume group
vgcreate myvg1 /dev/sdb /dev/sdc /dev/sdd
```
Device paths vary by provider. The paths `/dev/sdb`, `/dev/sdc`, `/dev/sdd` are examples from Contabo. On DigitalOcean, volumes appear under `/dev/disk/by-id/`. On AWS, they may be `/dev/nvme1n1`, `/dev/nvme2n1`, etc. Always verify your actual device paths with `lsblk` before creating physical volumes.
```bash theme={"system"}
# Install TopoLVM for Kubernetes storage provisioning
helm repo add topolvm https://topolvm.github.io/topolvm
helm repo update
# Create namespace and install cert-manager (required by TopoLVM)
kubectl create namespace topolvm-system
CERT_MANAGER_VERSION=v1.17.4
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.crds.yaml
# Install TopoLVM
helm install --namespace=topolvm-system topolvm topolvm/topolvm --set cert-manager.enabled=true
# Check storage classes
kubectl get storageclass
```
If using TopoLVM, set it as the default storage class:
```bash theme={"system"}
# Remove default from local-path
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
# Set TopoLVM as default
kubectl patch storageclass topolvm-provisioner -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
# Verify
kubectl get storageclass
```
If you're using the default k3s local-path storage class (single disk), you can skip this step.
Get the installer by [joining the beta](https://chainstack.com/self-hosted/).
Run the installer with your desired version and storage class:
```bash theme={"system"}
./cpctl install -v v1.0.0 -s topolvm-provisioner
```
The installer will:
1. Check prerequisites (kubectl, helm, yq, openssl, cluster access)
2. Generate secure passwords for all services
3. Save the credentials to `~/.config/cp-suite/values/`
4. Deploy the full stack (PostgreSQL, Temporal, Keycloak, Control Panel services)
5. Prompt for the backend API URL. Use the default (`http://cp-cp-deployments-api`) for in-cluster access, or specify an external URL (e.g., `http://:8081`) if accessing from outside the cluster.
The installation typically takes 5–10 minutes. You'll see output similar to:
```text theme={"system"}
==> Checking prerequisites...
[OK] Helm v3 found
[OK] yq v4+ found
[OK] Cluster access verified
[OK] All prerequisites met
[INFO] Generating secure passwords...
[INFO] Generating RSA keys for JWT authentication...
[OK] Generated password values and RSA keys
[OK] Values saved to: /root/.config/cp-suite/values/cp-control-panel-20260108-113656.yaml
[WARN] Keep this file secure - it contains passwords
==> Installing Control Panel
[INFO] Chart: oci://asia-southeast1-docker.pkg.dev/prod-chainstack/public-cp-helm-charts/cp-distributed
[INFO] Version: v1.0.0
[INFO] Release: cp
[INFO] Namespace: control-panel
...
[OK] Control Panel installed successfully!
[INFO] Run 'cp-install.sh status' to check deployment status
```
Check that all pods are running:
```bash theme={"system"}
./cpctl status
```
All pods should show `Running` or `Completed` status:
```text theme={"system"}
==> Pod Status
NAME READY STATUS RESTARTS AGE
cp-cp-auth-78954d5689-879xg 1/1 Running 0 5m
cp-cp-deployments-api-7f9f79d6d9-97v49 1/1 Running 0 5m
cp-cp-ui-77d857d877-rx55q 1/1 Running 0 5m
cp-cp-workflows-8c9c94966-pvnnd 1/1 Running 0 5m
cp-keycloak-0 1/1 Running 0 5m
cp-pg-pgpool-7df85c9c48-qkqwx 1/1 Running 0 5m
cp-pg-postgresql-0 1/1 Running 0 5m
cp-temporal-admintools-7b47497b94-z47rz 1/1 Running 0 5m
cp-temporal-frontend-845cfd4764-t9q8p 1/1 Running 0 5m
cp-temporal-history-69858cdd5d-kv6hl 1/1 Running 0 5m
cp-temporal-matching-5c486486f5-7zrbw 1/1 Running 0 5m
cp-temporal-web-67b7976d8f-c4sgk 1/1 Running 0 5m
cp-temporal-worker-695f948b96-t5p5x 1/1 Running 0 5m
```
Expose the Control Panel for external access. If you specified an external backend URL during installation, expose both the UI and the deployments API:
```bash theme={"system"}
# Expose UI as LoadBalancer
kubectl expose service cp-cp-ui --type=LoadBalancer --name=cp-ui-external -n control-panel
# Expose deployments API as LoadBalancer (if using external backend URL)
kubectl expose service cp-cp-deployments-api --type=LoadBalancer --name=cp-api-external -n control-panel
# Check assigned external IPs
kubectl get svc cp-ui-external cp-api-external -n control-panel
```
For testing, use port forwarding:
```bash theme={"system"}
kubectl port-forward svc/cp-cp-ui 8080:80 -n control-panel --address 0.0.0.0 &
kubectl port-forward svc/cp-cp-deployments-api 8081:8080 -n control-panel --address 0.0.0.0 &
```
Open your browser and navigate to:
* **LoadBalancer:** `http://`
* **Port forward:** `http://:8080`
You should see the Chainstack Self-Hosted login page.
Your initial login credentials were generated during installation and saved to the values file:
```bash theme={"system"}
# Find the saved values file
ls ~/.config/cp-suite/values/
# View the bootstrap password
cat ~/.config/cp-suite/values/cp-control-panel-*.yaml | grep CP_AUTH_BOOTSTRAP_PASSWORD
```
Look for these values:
* **Username:** `admin` (default)
* **Password:** Value of `CP_AUTH_BOOTSTRAP_PASSWORD`
## Next steps
Congratulations! You now have Chainstack Self-Hosted running. Continue with:
1. [First login](/docs/self-hosted/first-login) — First login and initial configuration
2. [Deploying nodes](/docs/self-hosted/deploying-nodes) — Deploy your first blockchain node
3. [Troubleshooting](/docs/self-hosted/troubleshooting) — If you encounter any issues
## Useful kubectl commands
Set the default namespace to avoid typing `-n control-panel` every time:
```bash theme={"system"}
kubectl config set-context --current --namespace=control-panel
```
Common commands for managing your installation:
```bash theme={"system"}
# View all pods
kubectl get pods
# View all services
kubectl get svc
# View persistent volume claims
kubectl get pvc
# View logs for a specific pod
kubectl logs
# Describe a deployment for troubleshooting
kubectl describe deployment cp-cp-deployments-api
# Restart a deployment
kubectl rollout restart deployment cp-cp-ui
```