Why Minikube on a dedicated VPS
Local Minikube on a laptop is fine for experiments, but it is still a lab box: no public IP, no real DNS/TLS muscle memory, no remote API habit. A cheap dedicated VPS with Minikube is a compromise — one control-plane/node, the same manifests, Ingress, cert-manager and kubectl flow as “real” Kubernetes, plus a domain such as vault.by.
This is not a replacement for managed Kubernetes (EKS/GKE/AKS) and not HA production. For side projects, demos and CI/CD practice the stack is already close: Deployment → Service → Ingress → Certificate.
Hardware baseline
- VPS: from 2 vCPU / 4–8 GB RAM / 40+ GB SSD (the Docker driver is memory-hungry).
- OS: Ubuntu 22.04/24.04 LTS.
- Open ports: 22, 80, 443 (plus NodePort range if needed).
- DNS: A record for
vault.by(and preferablywww.vault.by) → VPS public IP.
Install Minikube and start
sudo apt update && sudo apt install -y docker.io curl
sudo usermod -aG docker $USER
# re-login, then:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start --driver=docker --cpus=2 --memory=3900 --addons=ingress
minikube addons enable ingress
minikube addons enable metrics-server
kubectl get nodes
To expose Ingress from the internet on a Docker-driver Minikube you usually forward host ports to the ingress controller (or keep minikube tunnel running). A practical single-VPS option:
kubectl -n ingress-nginx get svc
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 \
-j DNAT --to-destination $(minikube ip):80
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 \
-j DNAT --to-destination $(minikube ip):443
# plus MASQUERADE for replies; or nginx on the host → $(minikube ip)
Often simpler to operate: nginx/Caddy on the host as a reverse proxy to the Minikube Ingress IP, while 80/443 listen only on the host.
Hello World: Deployment + Service
# hello-world.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
labels:
app: hello-world
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: web
image: hashicorp/http-echo:1.0
args: ["-text=Hello from Minikube on VPS"]
ports:
- containerPort: 5678
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
selector:
app: hello-world
ports:
- port: 80
targetPort: 5678
kubectl apply -f hello-world.yaml
kubectl get pods,svc
kubectl port-forward svc/hello-world 8080:80
# curl http://127.0.0.1:8080
Ingress for vault.by
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- vault.by
- www.vault.by
secretName: vault-by-tls
rules:
- host: vault.by
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world
port:
number: 80
- host: www.vault.by
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world
port:
number: 80
SSL with cert-manager (Let's Encrypt)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml
kubectl -n cert-manager rollout status deploy/cert-manager
# cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: admin@vault.by
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginx
kubectl apply -f cluster-issuer.yaml
kubectl apply -f ingress.yaml
kubectl describe certificate vault-by-tls
kubectl get secret vault-by-tls
curl -I https://vault.by
If DNS does not point at the VPS or port 80 is unreachable from the internet, the HTTP-01 challenge fails and the certificate stays Pending/False. Verify curl http://vault.by first, then TLS.
What feels production-like — and what does not
- Similar: manifests, probes (add them), Ingress, TLS, namespaces, ResourceQuota, GitOps-style apply from CI.
- Not prod: single node, no HA etcd/API, weaker isolation, Minikube addons, VPS uptime = cluster uptime.
- Next step: k3s/k0s on the same VPS or managed K8s when you need multiple nodes and an SLA.
Checklist before a vault.by demo
- Domain A record → VPS IP.
minikube start+ ingress addon.- Forward 80/443 to Ingress.
- Hello World Deployment/Service.
- cert-manager + ClusterIssuer + TLS Ingress.
curl -I https://vault.by→ 200 and a valid certificate.
Takeaway
Minikube on a dedicated VPS is a training cluster that already feels grown-up: the same Kubernetes objects, a public domain, and real Let's Encrypt. For Hello World on vault.by you only need Deployment, Service, Ingress and cert-manager. It will not replace a production cluster — but it is the best bridge from a laptop sandbox to real K8s practice.
