Introduction
In this post, I’ll walk you through how I deployed Odoo using the Bitnami Helm chart on my on-premises Kubernetes cluster hosted on Proxmox, while connecting it to an external PostgreSQL database running on a separate Proxmox VM.
Architecture Overview
vm-k8s-dev-01-cp-01] WK[Worker Node
vm-k8s-dev-01-wk-01] subgraph Odoo_Deployment[Odoo Deployment (Bitnami Helm)] Odoo1[Odoo Pod 1] Odoo2[Odoo Pod 2] PVC[Persistent Volume
/bitnami/odoo] end end DBVM[PostgreSQL VM
vm-pgsql-dev-01] end Odoo1 --- PVC Odoo2 --- PVC Odoo1 --- DBVM Odoo2 --- DBVM CP --- WK
My Environment
Proxmox Cluster:
vm-k8s-dev-01-cp-01: Kubernetes control-plane node (Ubuntu 22.04)vm-k8s-dev-01-wk-01: Kubernetes worker nodevm-pgsql-dev-01: PostgreSQL VM
Kubernetes:
- Version:
1.30.x - Networking: Calico CNI
- Version:
PostgreSQL:
- Version:
15.x - Hosted on dedicated Proxmox VM
- Version:
Helm:
- Version:
v3.15.x
- Version:
Bitnami Odoo Chart:
- Chart:
odoo - Source: https://bitnami.com/stack/odoo/helm
- Chart:
Step 1 — Preparing PostgreSQL
On my PostgreSQL VM (vm-pgsql-dev-01):
sudo -u postgres psql
Create the Odoo database and user:
CREATE DATABASE odoo_db;
CREATE USER odoo_user WITH PASSWORD 'SuperSecretPassword';
GRANT ALL PRIVILEGES ON DATABASE odoo_db TO odoo_user;
Allow connections from Kubernetes nodes in pg_hba.conf:
# Example: allow all K8s subnet (adjust CIDR)
host odoo_db odoo_user 10.244.0.0/16 md5
In postgresql.conf, listen on all interfaces:
listen_addresses = '*'
Restart PostgreSQL:
sudo systemctl restart postgresql
Test from a Kubernetes node:
psql -h vm-pgsql-dev-01 -U odoo_user -d odoo_db
Step 2 — Creating a Kubernetes Namespace
kubectl create namespace odoo
Step 3 — Adding the Bitnami Helm Repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
Step 4 — Creating the values.yaml
# values.yaml
image:
repository: bitnami/odoo
tag: 17-debian-12
pullPolicy: IfNotPresent
postgresql:
enabled: false
externalDatabase:
host: vm-pgsql-dev-01
port: 5432
user: odoo_user
password: SuperSecretPassword
database: odoo_db
service:
type: LoadBalancer
port: 80
persistence:
enabled: true
size: 10Gi
storageClass: nfs-client # adjust for your storage provisioner
ingress:
enabled: true
hostname: odoo.local
ingressClassName: nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
tls: []
Step 5 — Deploying Odoo
helm install odoo bitnami/odoo -f values.yaml -n odoo
Check:
kubectl get pods -n odoo
kubectl get svc -n odoo
Step 6 — Accessing Odoo
If using LoadBalancer (MetalLB):
kubectl get svc -n odoo
Open the assigned IP in your browser.
If using Ingress, make sure DNS or /etc/hosts points odoo.local to your ingress controller.
Step 7 — Persistent Volumes & Backups
The Bitnami chart stores uploaded files and modules in /bitnami/odoo (persistent).
For PostgreSQL backups:
pg_dump -h vm-pgsql-dev-01 -U odoo_user -d odoo_db > odoo_backup.sql
Step 8 — Scaling & Updates
Scale app layer:
kubectl scale deployment odoo -n odoo --replicas=3
Update Odoo:
helm upgrade odoo bitnami/odoo -f values.yaml -n odoo
Conclusion
Separating Odoo and PostgreSQL provides:
- Independent DB maintenance
- Easier backups
- Safer upgrades
Running both on Proxmox keeps full control in your hands while staying on-premises.
References: