K8S Helm Longhorn WP Setup
✅ Step 1: Install RKE2 (Kubernetes)
RKE2 is a lightweight, CNCF-certified Kubernetes distribution.
1.1 Install RKE2
curl -sfL https://get.rke2.io | sh –
1.2 Enable and Start RKE2 Server
systemctl enable rke2-server.service
systemctl start rke2-server.service
1.3 Add kubectl to your path and set kubeconfig
echo ‘export PATH=$PATH:/var/lib/rancher/rke2/bin’ >> ~/.bashrc
source ~/.bashrc
mkdir -p ~/.kube
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
chown $(id -u):$(id -g) ~/.kube/config
✅ Step 2: Install Helm
2.1 Download Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version
✅ Step 3: Install Longhorn (Storage Management)
3.1 Add the Longhorn Helm repo
helm repo add longhorn https://charts.longhorn.io
helm repo update
3.2 Create a namespace and install
kubectl create namespace longhorn-system
helm install longhorn longhorn/longhorn \
–namespace longhorn-system \
–set defaultSettings.defaultReplicaCount=1
3.3 Optional (UI Access via NodePort): Expose Longhorn using NodePort (by default it does):
kubectl get svc -n longhorn-system | grep longhorn-frontend
kubectl patch svc longhorn-frontend \
-n longhorn-system \
-p ‘{“spec”: {“type”: “NodePort”}}’
kubectl get svc longhorn-frontend -n longhorn-system
4. Install Rancher with Ingress
Step 4.1: Add Helm repo
helm repo add rancher-latest https://releases.rancher.com/server-charts/latest
helm repo update
Step 4.2: Create Namespace
kubectl create namespace cattle-system
Step 4.3: Install Cert Manager (optional if using Let’s Encrypt)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.3/cert-manager.yaml
Output:
namespace/cert-manager created
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created
serviceaccount/cert-manager-cainjector created
serviceaccount/cert-manager created
serviceaccount/cert-manager-webhook created
clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrole.rbac.authorization.k8s.io/cert-manager-cluster-view created
clusterrole.rbac.authorization.k8s.io/cert-manager-view created
clusterrole.rbac.authorization.k8s.io/cert-manager-edit created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
role.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
role.rbac.authorization.k8s.io/cert-manager:leaderelection created
role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
rolebinding.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
service/cert-manager created
service/cert-manager-webhook created
deployment.apps/cert-manager-cainjector created
deployment.apps/cert-manager created
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
Wait until pods are running:
kubectl get pods -n cert-manager
Output:
NAME READY STATUS RESTARTS AGE
cert-manager-777f759894-bwczl 1/1 Running 0 50s
cert-manager-cainjector-6fdf5f5cd6-lkbvd 1/1 Running 0 50s
cert-manager-webhook-55c7b766bd-f2hx6 1/1 Running 0 50s
Step 4.4: Install Rancher
helm install rancher rancher-latest/rancher \
–namespace cattle-system \
–set hostname=rancher.lintsawa.com \
–set replicas=1 \
–set ingress.tls.source=letsEncrypt \
–set letsEncrypt.email=admin@lintsawa.com \
–set letsEncrypt.ingress.class=nginx
Output
NAME: rancher
LAST DEPLOYED: Sat Jun 14 19:16:18 2025
NAMESPACE: cattle-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Rancher Server has been installed.
NOTE: Rancher may take several minutes to fully initialize. Please standby while Certificates are being issued, Containers are started and the Ingress rule comes up.
Check out our docs at https://rancher.com/docs/
If you provided your own bootstrap password during installation, browse to https://rancher.lintsawa.com to get started.
If this is the first time you installed Rancher, get started by running this command and clicking the URL it generates:
“`
echo https://rancher.lintsawa.com/dashboard/?setup=$(kubectl get secret –namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}’)
“`
To get just the bootstrap password on its own, run:
“`
kubectl get secret –namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{ “\n” }}’
“`
Happy Containering!
⚠️ Ensure rancher.lintsawa.com points to your server IP in DNS.
5. Setup Ingress Controller
RKE2 already includes nginx-ingress.
Check:
kubectl get pods -n kube-system | grep ingress
You can create an Ingress rule for WordPress and Rancher. You don’t need to install anything extra unless you want a different ingress controller.
6. Deploy MySQL (for WordPress)
Step 6.1: Create Namespace
kubectl create namespace wp
Step 6.2: Add Bitnami Repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
Step 6.3: Install MySQL
helm install wp-mysql bitnami/mysql \
–namespace wp \
–set auth.rootPassword=rootpass123 \
–set auth.database=wordpress \
–set primary.persistence.storageClass=longhorn \
–set primary.persistence.size=10Gi
Watch :
kubectl get pods -w –namespace wp
Output:
NAME: wp-mysql
LAST DEPLOYED: Sat Jun 14 19:26:41 2025
NAMESPACE: wp
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 13.0.2
APP VERSION: 9.3.0
Did you know there are enterprise versions of the Bitnami catalog? For enhanced secure software supply chain features, unlimited pulls from Docker, LTS support, or application customization, see Bitnami Premium or Tanzu Application Catalog. See https://www.arrow.com/globalecs/na/vendors/bitnami for more information.
** Please be patient while the chart is being deployed **
Tip:
Watch the deployment status using the command: kubectl get pods -w –namespace wp
Services:
echo Primary: wp-mysql.wp.svc.cluster.local:3306
Execute the following to get the administrator credentials:
echo Username: root
MYSQL_ROOT_PASSWORD=$(kubectl get secret –namespace wp wp-mysql -o jsonpath=”{.data.mysql-root-password}” | base64 -d)
To connect to your database:
1. Run a pod that you can use as a client:
kubectl run wp-mysql-client –rm –tty -i –restart=’Never’ –image docker.io/bitnami/mysql:9.3.0-debian-12-r2 –namespace wp –env MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD –command — bash
2. To connect to primary service (read/write):
mysql -h wp-mysql.wp.svc.cluster.local -uroot -p”$MYSQL_ROOT_PASSWORD”
WARNING: There are “resources” sections in the chart not set. Using “resourcesPreset” is not recommended for production. For production installations, please set the following values according to your workload needs:
– primary.resources
– secondary.resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
7. Deploy WordPress (Helm)
helm install wp bitnami/wordpress \
–namespace wp \
–set wordpressUsername=admin \
–set wordpressPassword=adminpass123 \
–set wordpressBlogName=”Kube WP” \
–set mariadb.enabled=false \
–set externalDatabase.host=wp-mysql.wp.svc.cluster.local \
–set externalDatabase.user=root \
–set externalDatabase.password=rootpass123 \
–set externalDatabase.database=wordpress \
–set persistence.storageClass=longhorn \
–set ingress.enabled=true \
–set ingress.hostname=kube-wp.lintsawa.com
Output:
NAME: wp
LAST DEPLOYED: Sat Jun 14 19:32:47 2025
NAMESPACE: wp
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: wordpress
CHART VERSION: 24.2.10
APP VERSION: 6.8.1
Did you know there are enterprise versions of the Bitnami catalog? For enhanced secure software supply chain features, unlimited pulls from Docker, LTS support, or application customization, see Bitnami Premium or Tanzu Application Catalog. See https://www.arrow.com/globalecs/na/vendors/bitnami for more information.
** Please be patient while the chart is being deployed **
Your WordPress site can be accessed through the following DNS name from within your cluster:
wp-wordpress.wp.svc.cluster.local (port 80)
To access your WordPress site from outside the cluster follow the steps below:
1. Get the WordPress URL and associate WordPress hostname to your cluster external IP:
export CLUSTER_IP=$(minikube ip) # On Minikube. Use: `kubectl cluster-info` on others K8s clusters
echo “WordPress URL: http://kube-wp.lintsawa.com/”
echo “$CLUSTER_IP kube-wp.lintsawa.com” | sudo tee -a /etc/hosts
2. Open a browser and access WordPress using the obtained URL.
3. Login with the following credentials below to see your blog:
echo Username: admin
echo Password: $(kubectl get secret –namespace wp wp-wordpress -o jsonpath=”{.data.wordpress-password}” | base64 -d)
WARNING: There are “resources” sections in the chart not set. Using “resourcesPreset” is not recommended for production. For production installations, please set the following values according to your workload needs:
– resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
⚠️ Make sure kube-wp.lintsawa.com points to your server IP.
8. Final DNS Setup
Go to your DNS provider and add these records:
| Type | Name | Value (IP) |
| A | kube-wp.lintsawa.com | <your-server-ip> |
| A | rancher.lintsawa.com | <your-server-ip> |
9. Access Interfaces
| Tool | URL |
| WordPress | https://kube-wp.lintsawa.com |
| Rancher UI | https://rancher.lintsawa.com |
| Longhorn | http://<your-ip>:<NodePort> |
======================================================================
Step-by-Step Guide to Enable SSL for kube-wp.lintsawa.com
✅ Prerequisites
- Your domain kube-wp.lintsawa.com must already resolve to your server’s public IP.
- cert-manager must be installed and running.
- You’re using RKE2’s built-in ingress-nginx controller, which is sufficient.
1. Install cert-manager (if not yet installed)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.3/cert-manager.yaml
Wait until pods are ready:
kubectl get pods -n cert-manager
Output:
NAME READY STATUS RESTARTS AGE
cert-manager-777f759894-8g65w 1/1 Running 0 20m
cert-manager-cainjector-6fdf5f5cd6-5gbfr 1/1 Running 0 20m
cert-manager-webhook-55c7b766bd-k5hsl 1/1 Running 0 20m
2. Create a ClusterIssuer for Let’s Encrypt
kubectl apply -f – <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: admin@lintsawa.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
solvers:
– http01:
ingress:
class: nginx
EOF
Output:
clusterissuer.cert-manager.io/letsencrypt-prod created
3. Upgrade WordPress with SSL enabled
We’ll upgrade the existing wp release to enable TLS and point to Let’s Encrypt issuer.
helm upgrade wp bitnami/wordpress \
–namespace wp \
–set wordpressUsername=admin \
–set wordpressPassword=adminpass123 \
–set wordpressBlogName=”Kube WP” \
–set mariadb.enabled=false \
–set externalDatabase.host=wp-mysql.wp.svc.cluster.local \
–set externalDatabase.user=root \
–set externalDatabase.password=rootpass123 \
–set externalDatabase.database=wordpress \
–set persistence.storageClass=longhorn \
–set ingress.enabled=true \
–set ingress.hostname=kube-wp.lintsawa.com \
–set ingress.tls=true \
–set ingress.annotations.”kubernetes\.io/ingress\.class”=nginx \
–set ingress.annotations.”cert-manager\.io/cluster-issuer”=letsencrypt-prod
4. Check Certificate Issuance
kubectl describe certificate -n wp
Wait for it to be ready:
kubectl get certificate -n wp
Also check ingress:
kubectl get ingress -n wp
✅ Access
Visit:
https://kube-wp.lintsawa.com
✔️ You should see a valid SSL certificate from Let’s Encrypt.


Great Kubernetes setup article thanks.
This has been covered well. Super easy to follow up.