Deploy applications on Kubernetes without the complexity.
KubOps is an open-core, Kubernetes-native PaaS operator. It lets developers deploy and manage applications using simple custom resources — no Deployments, Services, or Ingress manifests to write.
Open Core — this repository is the free, Apache 2.0 core.
Most PaaS tools either run on Docker/VPS (Coolify, Dokploy) or are locked to clouds (Porter, Qovery). KubOps is:
- Kubernetes-native — runs on any cluster (EKS, GKE, AKS, on-premise, k3s)
- Declarative by nature — your entire platform is defined as Kubernetes CRDs
- Self-hosted first — install on your own cluster via Helm, zero vendor lock-in
- Developer-friendly —
kubectl applyanAppand get a running deployment with Ingress and TLS
- Project / Environment / App model — organize applications by project and environment (dev, staging, prod)
- Shared namespaces per environment — all apps in the same environment share a namespace, enabling simple service-to-service communication (
http://backend:3000) - Automatic Ingress — define a hostname and TLS is handled automatically via cert-manager
- Cascade deletion — delete a Project and everything underneath (Environments, Apps, namespaces) is cleaned up automatically
- KubOpsConfig — global operator configuration (IngressClass, cert-manager issuer) with per-app overrides
- Go 1.25+ (for building from source)
- Kubernetes 1.31+ (tested on 1.31, built against client-go v0.35 / K8s 1.35)
- cert-manager (for automatic TLS certificates)
- An Ingress controller (e.g. ingress-nginx)
helm repo add kubops https://charts.kubops.com
helm install kubops kubops/kubops-operator -n kubops-system --create-namespacegit clone https://github.com/KubOpsCloud/kubops-operator
cd kubops-operator
make install # installs CRDs into the cluster
make run # runs the operator locally against your current kubeconfig1. Configure the operator (optional but recommended):
apiVersion: core.kubops.com/v1alpha1
kind: KubOpsConfig
metadata:
name: kubops
spec:
ingress:
className: nginx
certIssuer: letsencrypt-prod2. Create a Project:
apiVersion: core.kubops.com/v1alpha1
kind: Project
metadata:
name: my-app
spec:
displayName: "My App"3. Create an Environment:
apiVersion: core.kubops.com/v1alpha1
kind: Environment
metadata:
name: my-app-prod
spec:
project: my-app
type: prodThis automatically creates the Kubernetes namespace my-app-prod.
4. Deploy an App:
apiVersion: core.kubops.com/v1alpha1
kind: App
metadata:
name: frontend
spec:
project: my-app
environment: my-app-prod
source:
image:
repository: nginx
tag: "latest"
replicas: 2
port: 80
ingress:
host: myapp.example.com
tls:
enabled: trueThis creates a Deployment, Service, ServiceAccount, and Ingress in the my-app-prod namespace.
kubectl get apps
# NAME PROJECT ENVIRONMENT IMAGE REPLICAS PHASE AGE
# frontend my-app my-app-prod nginx 2 Running 30sLogical grouping of environments and apps. No Kubernetes resources are created — it is a pure organizational construct.
| Field | Type | Required | Description |
|---|---|---|---|
spec.displayName |
string | ✅ | Human-readable name (1-64 chars) |
spec.description |
string | Optional description |
Status phases: Active · Terminating
Represents a deployment environment (dev, staging, prod). Creates and owns a shared Kubernetes namespace used by all Apps in this environment.
| Field | Type | Required | Description |
|---|---|---|---|
spec.project |
string | ✅ | Parent Project name |
spec.type |
string | ✅ | Environment type — e.g. dev, staging, prod |
Namespace naming: {project}-{type} → my-app-prod
Status phases: Active · Failed · Terminating
A web application (HTTP service). Deployed into the Environment's shared namespace.
| Field | Type | Required | Description |
|---|---|---|---|
spec.project |
string | ✅ | Parent Project name |
spec.environment |
string | ✅ | Target Environment name |
spec.source.image.repository |
string | ✅ | Docker image repository |
spec.source.image.tag |
string | ✅ | Docker image tag |
spec.source.image.pullSecret |
string | Name of a docker-registry Secret |
|
spec.replicas |
integer | Number of replicas (default: 1) |
|
spec.port |
integer | ✅ | Container port |
spec.ingress.host |
string | Public hostname — creates an Ingress | |
spec.ingress.className |
string | IngressClass override (falls back to KubOpsConfig) | |
spec.ingress.tls.enabled |
bool | Enable TLS on the Ingress | |
spec.ingress.tls.certIssuer |
string | cert-manager ClusterIssuer override (falls back to KubOpsConfig) | |
spec.env |
EnvVar[] | Environment variables injected into the container |
Status phases: Pending · Running · Failed · Terminating
Kubernetes resources created: ServiceAccount · Deployment · Service · Ingress (only if spec.ingress is set)
Singleton cluster-scoped resource (name must be kubops) that sets global operator defaults.
| Field | Type | Description |
|---|---|---|
spec.ingress.className |
string | Default IngressClass for all Ingress resources |
spec.ingress.certIssuer |
string | Default cert-manager ClusterIssuer for TLS |
Per-app values in App.spec.ingress always take precedence over KubOpsConfig.
kubectl apply (App YAML)
↓
Kubernetes API — CRDs core.kubops.com/v1alpha1
↓
KubOps Operator (this repo)
↓
Kubernetes native resources
(Namespace, Deployment, Service, Ingress, ServiceAccount)
Cascade deletion chain:
Project deleted
└─→ Environments deleted
└─→ Apps deleted (Deployment, Service, SA, Ingress removed)
└─→ Namespace deleted
# Install CRDs and run the operator locally
make install
make run
# Apply sample resources
kubectl apply -f config/samples/core_v1alpha1_kubopsconfig.yaml
kubectl apply -f config/samples/core_v1alpha1_project.yaml
kubectl apply -f config/samples/core_v1alpha1_environment.yaml
kubectl apply -f config/samples/core_v1alpha1_app.yaml
# Run tests
make test
# Regenerate CRD manifests after changing types
make manifests
# Regenerate DeepCopy methods after changing types
make generateNote: Always scaffold new API types with
kubebuilder create apito ensureconfig/crd/kustomization.yamlis updated automatically.
- Project, Environment, App controllers
- KubOpsConfig (global Ingress defaults)
- Worker (CronJob / background worker)
- Database (PostgreSQL, MySQL, Redis)
- HelmRelease
- Helm chart
- UI
- CLI
Contributions are welcome! Please open an issue before submitting a pull request for significant changes.
Copyright 2026 KubOps.
Licensed under the Apache License, Version 2.0. See LICENSE for details.