Uptime Kuma
Self-hosted uptime monitoring with a modern web UI. Uptime Kuma checks HTTP, TCP, DNS, Ping, Docker, WebSocket, and 20+ other monitor types on configurable intervals, sends alerts via 90+ notification services (Telegram, Discord, Slack, email, and more), and publishes customizable public status pages.
Uptime Kuma manages WebSocket connections and monitor state in-process. Running multiple replicas causes monitor duplication and inconsistent alerts. Keep the deployment at 1 replica regardless of the database backend used.
Key Features
- 20+ monitor types — HTTP(s), TCP, Ping, DNS, Docker, WebSocket, Steam, MQTT, and more
- 90+ notification services — Telegram, Discord, Slack, Email, Pushover, Gotify, and more
- Public status pages — customizable status pages with custom domains
- Two-factor authentication — built-in 2FA for the admin account
- SQLite or MariaDB — embedded SQLite (default) or MariaDB-compatible subchart
- External database — connect to an existing MariaDB/MySQL instance
- Smart S3 backup —
tarfor SQLite mode,mysqldumpfor MariaDB mode - Custom CA certificates — monitor internal HTTPS services with private CA
- Gateway API and Ingress — expose the UI with classic Ingress or HTTPRoute
- External Secrets Operator — source database and S3 credentials from external providers
- Dual-stack Services — optional
ipFamilyPolicyandipFamiliescontrols - Secure runtime defaults — seccomp, dropped capabilities, read-only root filesystem, and no API token mount
- Availability controls — optional PodDisruptionBudget and NetworkPolicy
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install uptime-kuma helmforge/uptime-kuma -f values.yaml
OCI registry:
helm install uptime-kuma oci://ghcr.io/helmforgedev/helm/uptime-kuma -f values.yaml
After deploying with default values, access the setup wizard to create the admin account:
kubectl port-forward svc/<release>-uptime-kuma 3001:80
# Open http://localhost:3001 in your browser
Deployment Examples
# values.yaml — Uptime Kuma with SQLite (default, no database configuration needed)
persistence:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: status.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: uptime-kuma-tls
hosts:
- status.example.com# values.yaml — Uptime Kuma with bundled MariaDB subchart
database:
type: mariadb
mysql:
enabled: true
auth:
password: 'mariadb-password'
persistence:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: status.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Uptime Kuma with external MariaDB/MySQL
database:
type: mariadb
external:
host: mariadb.database.svc.cluster.local
port: '3306'
name: uptime_kuma
username: uptime_kuma
existingSecret: uptime-kuma-db-credentials
existingSecretPasswordKey: password
mysql:
enabled: false
persistence:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: status.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Monitor internal HTTPS services with a private CA certificate
# The CA certificate must be stored in the /app/data PVC at /app/data/ca.pem
uptimeKuma:
extraEnv:
- name: NODE_EXTRA_CA_CERTS
value: /app/data/ca.pem
persistence:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: status.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Daily S3 backup
# Backup strategy is automatic: tar for SQLite mode, mysqldump for MariaDB mode
backup:
enabled: true
schedule: '0 2 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-uptime-kuma-backups
prefix: uptime-kuma
existingSecret: uptime-kuma-s3-credentials
persistence:
enabled: true
size: 2Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: status.example.com
paths:
- path: /
pathType: Prefix# values.yaml — expose Uptime Kuma through Gateway API
persistence:
enabled: true
size: 2Gi
gatewayAPI:
enabled: true
httpRoutes:
- name: uptime-kuma
spec:
parentRefs:
- name: public-gateway
namespace: gateway-system
hostnames:
- status.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /# values.yaml — external database and S3 credentials managed by External Secrets Operator
database:
type: mariadb
external:
host: mariadb.database.svc.cluster.local
username: uptime_kuma
existingSecret: uptime-kuma-db
existingSecretPasswordKey: password
backup:
enabled: true
s3:
endpoint: https://s3.amazonaws.com
bucket: my-uptime-kuma-backups
existingSecret: uptime-kuma-s3
externalSecrets:
enabled: true
apiVersion: external-secrets.io/v1
refreshInterval: 1h
items:
- name: database
spec:
secretStoreRef:
name: platform-secrets
kind: ClusterSecretStore
target:
name: uptime-kuma-db
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: uptime-kuma/database
property: password
- name: s3
spec:
secretStoreRef:
name: platform-secrets
kind: ClusterSecretStore
target:
name: uptime-kuma-s3
creationPolicy: Owner
data:
- secretKey: access-key
remoteRef:
key: uptime-kuma/s3
property: accessKey
- secretKey: secret-key
remoteRef:
key: uptime-kuma/s3
property: secretKeyArchitecture and Production Boundaries
One Uptime Kuma pod receives traffic from a ClusterIP Service and optional
Ingress or HTTPRoute. The pod stores state either on /app/data in SQLite mode
or in a bundled/external MariaDB-compatible database. An optional CronJob reads
that same data path and uploads a tar archive or database dump to S3-compatible
storage.
Uptime Kuma must remain single-replica because monitor execution and WebSocket state are not coordinated between application processes. The optional PodDisruptionBudget protects against voluntary disruption, but it does not make the application highly available.
Empty ingress or egress rule lists deny all traffic in that direction. Allow the ingress controller, cluster DNS, monitor targets, notification endpoints, database, and S3 service required by your deployment.
Security Defaults
Application, database-wait, and backup containers deny privilege escalation,
drop all Linux capabilities, use runtime-default seccomp, and keep the image root
filesystem read-only. Writable temporary state uses bounded emptyDir volumes.
Service-account API token mounting is disabled by default, and database contract
changes trigger a workload rollout through a checksum annotation.
The official standard Uptime Kuma image starts as UID 0, so this chart does not claim a non-root runtime. Platform admission controls, node isolation, explicit resources, tested backups, and network policy remain operator responsibilities.
Configuration Reference
Core
| Parameter | Type | Default | Description |
|---|---|---|---|
nameOverride |
string | "" |
Override the chart name. |
fullnameOverride |
string | "" |
Override the full release name. |
commonLabels |
object | {} |
Extra labels added to all resources. |
Image
| Parameter | Type | Default | Description |
|---|---|---|---|
image.repository |
string | docker.io/louislam/uptime-kuma |
Uptime Kuma container image. |
image.tag |
string | "2.5.6" |
Image tag. |
image.pullPolicy |
string | IfNotPresent |
Image pull policy. |
imagePullSecrets |
array | [] |
Pull secrets for private registries. |
Uptime Kuma Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
uptimeKuma.port |
integer | 3001 |
Internal HTTP port. |
uptimeKuma.disableFrameSameOrigin |
boolean | false |
Allow embedding the status page in iframes from other origins. |
uptimeKuma.extraEnv |
array | [] |
Extra environment variables. Use for NODE_EXTRA_CA_CERTS and advanced settings. |
Status pages can be embedded in dashboards such as Heimdall or Homarr. Set uptimeKuma.disableFrameSameOrigin: true
to allow cross-origin iframe embedding. By default, the X-Frame-Options: SAMEORIGIN header prevents embedding from
other domains.
To monitor internal HTTPS endpoints using a self-signed or private CA certificate, place the CA certificate file in
the PVC at /app/data/ca.pem and set NODE_EXTRA_CA_CERTS via uptimeKuma.extraEnv. Node.js will then trust that CA
for all outgoing HTTPS requests made by the monitor checks.
Database
| Parameter | Type | Default | Description |
|---|---|---|---|
database.type |
string | sqlite |
Database backend: sqlite or mariadb. |
database.external.host |
string | "" |
External MariaDB/MySQL hostname. |
database.external.port |
string | "3306" |
External MariaDB/MySQL port. |
database.external.name |
string | uptime_kuma |
Database name on the external server. |
database.external.username |
string | uptime_kuma |
Username for the external database. |
database.external.password |
string | "" |
Password for the external database (prefer existingSecret). |
database.external.existingSecret |
string | "" |
Existing secret containing the database password. |
database.external.existingSecretPasswordKey |
string | password |
Key inside the existing secret for the password. |
Database — MySQL Subchart
The subchart is named mysql in the values, but Uptime Kuma uses it as a MariaDB-compatible backend. Set
database.type: mariadb alongside mysql.enabled: true to activate this mode. The bundled dependency is the
HelmForge MySQL chart 2.1.1.
| Parameter | Type | Default | Description |
|---|---|---|---|
mysql.enabled |
boolean | false |
Deploy a bundled MySQL/MariaDB subchart. |
mysql.architecture |
string | standalone |
Database architecture. |
mysql.auth.database |
string | uptime_kuma |
Database name created by the subchart. |
mysql.auth.username |
string | uptime_kuma |
Database user created by the subchart. |
mysql.auth.password |
string | "" |
Database password (required when using the subchart). |
Persistence
| Parameter | Type | Default | Description |
|---|---|---|---|
persistence.enabled |
boolean | true |
Enable a PVC for /app/data (SQLite, config, and CA certificates). |
persistence.size |
string | 2Gi |
PVC size. |
persistence.storageClass |
string | "" |
StorageClass for the PVC. |
persistence.accessModes |
array | ["ReadWriteOnce"] |
PVC access modes. |
persistence.existingClaim |
string | "" |
Use an existing PVC instead of creating one. |
Backup
The backup strategy adapts to the configured database mode automatically:
- SQLite mode — archives the full
/app/datadirectory usingtar. - MariaDB mode — runs
mysqldumpagainst the database and uploads the SQL dump.
| Parameter | Type | Default | Description |
|---|---|---|---|
backup.enabled |
boolean | false |
Enable scheduled S3 backup CronJob. |
backup.schedule |
string | "0 2 * * *" |
Cron schedule for backups. |
backup.suspend |
boolean | false |
Suspend the CronJob without deleting it. |
backup.concurrencyPolicy |
string | Forbid |
CronJob concurrency policy. |
backup.successfulJobsHistoryLimit |
integer | 3 |
Number of successful Job records to keep. |
backup.failedJobsHistoryLimit |
integer | 3 |
Number of failed Job records to keep. |
backup.backoffLimit |
integer | 1 |
Job retry limit. |
backup.archivePrefix |
string | uptime-kuma |
Prefix for backup archive filenames. |
backup.resources |
object | {} |
Resources for backup containers. |
backup.podSecurityContext |
object | RuntimeDefault seccomp | Pod-level backup security context. |
backup.securityContext |
object | Restricted defaults | Backup container security context. |
backup.tmpSizeLimit |
string | 64Mi |
Writable backup temporary-storage limit. |
backup.images.uploader.repository |
string | docker.io/helmforge/mc |
S3 uploader image repository. |
backup.images.uploader.tag |
string | "1.0.0" |
S3 uploader image tag. |
backup.images.mysql.repository |
string | docker.io/library/mysql |
mysqldump image repository (MariaDB mode). |
backup.images.mysql.tag |
string | "8.4" |
mysqldump image tag. |
backup.s3.endpoint |
string | "" |
S3-compatible endpoint URL. |
backup.s3.bucket |
string | "" |
Target bucket name. |
backup.s3.prefix |
string | uptime-kuma |
Key prefix within the bucket. |
backup.s3.createBucketIfNotExists |
boolean | true |
Create the bucket automatically if it does not exist. |
backup.s3.existingSecret |
string | "" |
Existing secret containing S3 access and secret keys. |
backup.s3.existingSecretAccessKeyKey |
string | access-key |
Key in the existing secret for the S3 access key. |
backup.s3.existingSecretSecretKeyKey |
string | secret-key |
Key in the existing secret for the S3 secret key. |
backup.s3.accessKey |
string | "" |
Inline S3 access key (ignored when existingSecret is set). |
backup.s3.secretKey |
string | "" |
Inline S3 secret key (ignored when existingSecret is set). |
Service
| Parameter | Type | Default | Description |
|---|---|---|---|
service.type |
string | ClusterIP |
Kubernetes service type. |
service.port |
integer | 80 |
Service port exposed to the cluster. |
service.annotations |
object | {} |
Annotations for the Service. |
service.ipFamilyPolicy |
string | omitted | Service IP family policy: SingleStack, PreferDualStack, or RequireDualStack. |
service.ipFamilies |
array | omitted | Ordered Service IP families such as IPv4 and IPv6. |
Ingress
| Parameter | Type | Default | Description |
|---|---|---|---|
ingress.enabled |
boolean | false |
Enable an Ingress resource. |
ingress.ingressClassName |
string | traefik |
Ingress class name. |
ingress.annotations |
object | {} |
Annotations for the Ingress (e.g. cert-manager). |
ingress.hosts |
array | [] |
Ingress host and path rules. |
ingress.tls |
array | [] |
TLS configuration (secret name and hosts). |
Gateway API
Use Gateway API when your cluster standardizes HTTP routing through Gateway resources. The chart renders HTTPRoutes that target the Uptime Kuma Service by default.
| Parameter | Type | Default | Description |
|---|---|---|---|
gatewayAPI.enabled |
boolean | false |
Enable HTTPRoute resources. |
gatewayAPI.httpRoutes |
array | [] |
HTTPRoute definitions to render. |
External Secrets Operator
External Secrets can materialize database, S3, or integration credentials without storing them directly in Helm values.
| Parameter | Type | Default | Description |
|---|---|---|---|
externalSecrets.enabled |
boolean | false |
Render ExternalSecret resources. |
externalSecrets.apiVersion |
string | external-secrets.io/v1 |
ExternalSecret API version. |
externalSecrets.refreshInterval |
string | 1h |
Default refresh interval for items that do not set one. |
externalSecrets.items |
array | [] |
ExternalSecret definitions. Each item requires a full spec. |
Probes
| Parameter | Type | Default | Description |
|---|---|---|---|
probes.startup.enabled |
boolean | true |
Enable startup probe. |
probes.startup.initialDelaySeconds |
integer | 10 |
Startup probe initial delay. |
probes.startup.periodSeconds |
integer | 5 |
Startup probe period. |
probes.startup.timeoutSeconds |
integer | 3 |
Startup probe timeout. |
probes.startup.failureThreshold |
integer | 30 |
Startup probe failure threshold. |
probes.liveness.enabled |
boolean | true |
Enable liveness probe. |
probes.liveness.initialDelaySeconds |
integer | 0 |
Liveness probe initial delay. |
probes.liveness.periodSeconds |
integer | 15 |
Liveness probe period. |
probes.liveness.timeoutSeconds |
integer | 5 |
Liveness probe timeout. |
probes.liveness.failureThreshold |
integer | 3 |
Liveness probe failure threshold. |
probes.readiness.enabled |
boolean | true |
Enable readiness probe. |
probes.readiness.initialDelaySeconds |
integer | 0 |
Readiness probe initial delay. |
probes.readiness.periodSeconds |
integer | 10 |
Readiness probe period. |
probes.readiness.timeoutSeconds |
integer | 5 |
Readiness probe timeout. |
probes.readiness.failureThreshold |
integer | 3 |
Readiness probe failure threshold. |
Resources and Security
| Parameter | Type | Default | Description |
|---|---|---|---|
resources |
object | {} |
CPU and memory requests and limits. |
podSecurityContext |
object | RuntimeDefault seccomp | Pod-level security context. |
securityContext |
object | Restricted defaults | Container-level security context. |
runtimeStorage.tmpSizeLimit |
string | 256Mi |
Writable application temporary-storage cap. |
Service Account
| Parameter | Type | Default | Description |
|---|---|---|---|
serviceAccount.create |
boolean | false |
Create a dedicated ServiceAccount. |
serviceAccount.name |
string | "" |
Override the ServiceAccount name. |
serviceAccount.annotations |
object | {} |
Annotations for the ServiceAccount. |
serviceAccount.automountServiceAccountToken |
boolean | false |
Mount the Kubernetes API token in application and backup pods. |
Availability and Network Isolation
| Parameter | Type | Default | Description |
|---|---|---|---|
podDisruptionBudget.enabled |
boolean | false |
Render a PodDisruptionBudget for voluntary disruptions. |
podDisruptionBudget.minAvailable |
integer/string | 1 |
Minimum available pod count or percentage. |
podDisruptionBudget.maxUnavailable |
integer/string | null |
Maximum unavailable count or percentage; mutually exclusive. |
networkPolicy.enabled |
boolean | false |
Render an application NetworkPolicy. |
networkPolicy.ingress |
array | [] |
Complete ingress rules; empty denies all ingress. |
networkPolicy.egress |
array | [] |
Complete egress rules; empty denies all egress. |
Scheduling
| Parameter | Type | Default | Description |
|---|---|---|---|
nodeSelector |
object | {} |
Node selector for scheduling. |
tolerations |
array | [] |
Tolerations for scheduling. |
affinity |
object | {} |
Affinity rules. |
topologySpreadConstraints |
array | [] |
Topology spread constraints. |
priorityClassName |
string | "" |
PriorityClass for the pod. |
terminationGracePeriodSeconds |
integer | 30 |
Termination grace period. |
podLabels |
object | {} |
Extra labels for the pod. |
podAnnotations |
object | {} |
Extra annotations for the pod. |
Extra
| Parameter | Type | Default | Description |
|---|---|---|---|
extraVolumes |
array | [] |
Extra volumes to attach to the pod. |
extraVolumeMounts |
array | [] |
Extra volume mounts for the container. |
extraManifests |
array | [] |
Extra Kubernetes manifests deployed alongside the chart. |
Upgrade Notes
Uptime Kuma 2.5.6 fixes average-response badge calculations and updates
security-sensitive dependencies. The container and storage contracts are
unchanged. Review the
upstream 2.5.6 release
and back up the /app/data PVC before upgrading.
After each backup or chart upgrade, restore the newest backup in a disposable
namespace and verify monitor history, status pages, and notification settings.
For Helm upgrades, prefer a reviewed values file with
--reset-then-reuse-values so new security defaults are adopted without losing
intentional overrides.