Running Liferay on any Kubernetes Cluster for Cloud 2025.Q4 and Earlier Versions
This guide covers the Kubernetes toolkit version used throughout 2025.Q4 and earlier. Starting in 2026.Q1, the toolkit has been redesigned into a streamlined experience.
These instructions are purposefully generic. They install a cluster that works on any Kubernetes implementation, but additional work is needed to make that cluster production-ready. Please review your cloud provider’s documentation for details on deploying a production-ready environment.
Before you start, you should have several prerequisites installed:
- Git CLI version >=
2.40.1 - kubectl CLI version >=
1.25.2 - Helm CLI version >=
3.18.6 - Docker engine version >=
v20.10.21 - K3D version >=
5.8.3
This example uses K3D, but you can use any Kubernetes cluster implementation (e.g., kind, Docker Desktop, etc.).
Create Kubernetes Cluster
First, create a Kubernetes cluster called playground which maps machine port 80 to port 80 on the internal k3d load balancer and creates a local image registry to build and deploy other container images if needed.
-
Run this command:
k3d cluster create playground \ --port 80:80@loadbalancer \ --registry-create registry:5000
If running rootless docker, change the line --port 80:80@loadbalancer to use an available unprivileged port (> 1024) instead of port 80. For example,
--port 8182:80@loadbalancer
This change requires modifying the Liferay portal property below to use the port you selected (8182 in the example above):
web.server.http.port=8182
-
Verify the cluster exists by running the two commands below:
kubectl config current-context kubectl cluster-info
Configure Helm Chart Values
-
Create a file a
values-custom.yamlfile with the configuration below:customInitContainers: x-liferay-prewipe-hypersonic: containerTemplate: | command: - bash - -c - | FLAGFILE=/opt/liferay/data/.hypersonic.prewiped if [ ! -e "${FLAGFILE}" ] then rm -rf /opt/liferay/data/hypersonic fi touch "${FLAGFILE}" image: {{ printf "%s:%s" .image.repository (.image.tag | toString) }} imagePullPolicy: {{ .image.pullPolicy }} name: liferay-prewipe-hypersonic volumeMounts: - mountPath: /opt name: liferay-persistent-volume image: tag: [Your Liferay Version Tag Here] ingress: enabled: true rules: - host: "*.dxp.localtest.me" http: paths: - backend: service: name: liferay-default port: name: http path: / pathType: ImplementationSpecific portalProperties: | company.default.virtual.host.name=main.dxp.localtest.me company.default.web.id=main.dxp.localtest.me include-and-override=portal-developer.properties web.server.protocol=http -
Replace
[Your Liferay Version Tag Here]above with the appropriate Liferay tag from Docker Hub. -
If you configured an unprivileged port, add the below property to
portalProperties:web.server.http.port=[port]For example,
web.server.http.port=8182
You can learn more about these values in Liferay Helm Values Reference. To learn more about Helm values files see the Helm documentation.
The configuration above specifies
- Your specific Liferay image version
- An ingress load balancer to expose the Liferay service locally
- Custom Liferay portal properties
- An init container to pre-wipe the included HSQL database to use a custom
company.default.web.idportal property
Note that because HSQL is the configured database, this instance is for testing purposes as initially configured.
Launch Liferay
-
Create an environment variable to hold the chart URL:
export CHART_URL=oci://us-central1-docker.pkg.dev/liferay-artifact-registry/liferay-helm-chart/liferay-default -
Install the Liferay Helm chart to your cluster:
helm upgrade liferay "${CHART_URL}" \ --install \ --values values-custom.yaml
Access Liferay
-
Check to see if the Liferay workload is ready:
kubectl rollout status statefulset liferay-default -
Navigate to http://main.dxp.localtest.me on your local machine’s web browser to access Liferay. If you modified the web server port, append the port number: http://main.dxp.localtest.me:8182.
-
Retrieve your admin password for Liferay:
kubectl get secret liferay-default \ --output jsonpath='{.data.LIFERAY_DEFAULT_PERIOD_ADMIN_PERIOD_PASSWORD}' \ | base64 --decode -
Log into Liferay:
- Email: test@main.dxp.localtest.me
- Password: [password retrieved in previous step]
Excellent! You’ve just deployed a “playground” Liferay Kubernetes cluster! Read on to learn how to make it more robust.