Files

Donetick Helm Chart

A Helm chart for deploying the Donetick task management application on Kubernetes.

Introduction

This chart deploys Donetick on a Kubernetes cluster using the Helm package manager.

Source code can be found here:

Prerequisites

  • Kubernetes 1.19+
  • Helm 3.0+
  • PV provisioner support in the underlying infrastructure (if persistence is needed)

Installing the Chart

To install the chart with the release name donetick:

$ helm repo add donetick-chart https://rtomik.github.io/helm-charts
$ helm install donetick donetick-chart/donetick

Tip

: List all releases using helm list

Configuration Examples

Basic Installation with SQLite (Default)

helm install donetick donetick-chart/donetick

Installation with External PostgreSQL

Create a values file for PostgreSQL configuration:

# values-postgres.yaml
config:
  database:
    type: "postgres"
    host: "postgresql.database.svc.cluster.local"
    port: 5432
    user: "donetick"
    password: "your-secure-password"
    name: "donetick"
    migration: true

  # Update JWT secret for production
  jwt:
    secret: "your-secure-jwt-secret-at-least-32-characters-long"

  # Configure server settings
  server:
    cors_allow_origins:
      - "https://your-domain.com"
      - "http://localhost:5173"

  # Enable features as needed
  features:
    notifications: true
    realtime: true
    oauth: false

# Enable ingress for external access
ingress:
  enabled: true
  className: "nginx"
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: donetick.your-domain.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: donetick-tls
      hosts:
        - donetick.your-domain.com

# Configure persistence
persistence:
  enabled: true
  storageClass: "fast-ssd"
  size: "5Gi"

Install with PostgreSQL configuration:

helm install donetick donetick-chart/donetick -f values-postgres.yaml

Production Installation with External Secrets

For production deployments, use Kubernetes secrets for sensitive data:

# values-production.yaml
config:
  database:
    type: "postgres"
    host: "postgresql.database.svc.cluster.local"
    port: 5432
    name: "donetick"

  # Use existing secret for postgres credentials
  database:
    type: "postgres"
    host: "postgresql.database.svc.cluster.local"
    port: 5432
    name: "donetick"
    secrets:
      existingSecret: "donetick-postgres-secret"
      userKey: "username"
      passwordKey: "password"

  # Use existing secret for JWT
  jwt:
    existingSecret: "donetick-jwt-secret"
    secretKey: "jwt-secret"
    session_time: "168h"
    max_refresh: "168h"

  # OAuth2 configuration with secrets
  oauth2:
    existingSecret: "donetick-oauth-secret"
    clientIdKey: "client-id"
    clientSecretKey: "client-secret"
    auth_url: "https://your-oauth-provider.com/auth"
    token_url: "https://your-oauth-provider.com/token"
    user_info_url: "https://your-oauth-provider.com/userinfo"
    redirect_url: "https://donetick.your-domain.com/auth/callback"

  # Production server settings
  server:
    cors_allow_origins:
      - "https://donetick.your-domain.com"
    rate_limit: 100
    rate_period: "60s"

  # Enable production features
  features:
    notifications: true
    realtime: true
    oauth: true

# Security context for production
podSecurityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000

# Resource limits for production
resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 128Mi

# Ingress with TLS
ingress:
  enabled: true
  className: "nginx"
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: donetick.your-domain.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: donetick-tls
      hosts:
        - donetick.your-domain.com

Create the required secrets:

# Postgres secret
kubectl create secret generic donetick-postgres-secret \
  --from-literal=username='donetick' \
  --from-literal=password='your-secure-db-password'

# JWT secret
kubectl create secret generic donetick-jwt-secret \
  --from-literal=jwt-secret='your-very-secure-jwt-secret-at-least-32-characters-long'

# OAuth secret (if using OAuth)
kubectl create secret generic donetick-oauth-secret \
  --from-literal=client-id='your-oauth-client-id' \
  --from-literal=client-secret='your-oauth-client-secret'

Install with production configuration:

helm install donetick donetick-chart/donetick -f values-production.yaml

Uninstalling the Chart

To uninstall/delete the donetick deployment:

helm uninstall donetick

Parameters

Global parameters

Name Description Value
nameOverride String to partially override the release name ""
fullnameOverride String to fully override the release name ""

Image parameters

Name Description Value
image.repository Donetick image repository donetick/donetick
image.tag Donetick image tag v0.1.60
image.pullPolicy Donetick image pull policy IfNotPresent
imagePullSecrets Global Docker registry secret names as an array []

Secret Management

Name Description Value
config.jwt.existingSecret Name of existing secret for JWT token ""
config.jwt.secretKey Key in the existing secret for JWT token "jwtSecret"
config.oauth2.existingSecret Name of existing secret for OAuth2 credentials ""
config.oauth2.clientIdKey Key in the existing secret for OAuth2 client ID "client-id"
config.oauth2.clientSecretKey Key in the existing secret for OAuth2 client secret "client-secret"
config.database.secrets.existingSecret Name of existing secret for postgres credentials ""
config.database.secrets.userKey Key in the existing secret for postgres username "username"
config.database.secrets.passwordKey Key in the existing secret for postgres password "password"

Deployment parameters

Name Description Value
replicaCount Number of Donetick replicas 1
revisionHistoryLimit Number of revisions to retain for rollback 3
podSecurityContext.runAsNonRoot Run containers as non-root user true
podSecurityContext.runAsUser User ID for the container 1000
podSecurityContext.fsGroup Group ID for the container filesystem 1000
containerSecurityContext Security context for the container See values.yaml
nodeSelector Node labels for pod assignment {}
tolerations Tolerations for pod assignment []
affinity Affinity for pod assignment {}

Service parameters

Name Description Value
service.type Kubernetes Service type ClusterIP
service.port Service HTTP port 2021
service.annotations Additional annotations for Service {}

Pod Configuration

Name Description Value
podAnnotations Additional annotations for pods {}

Ingress parameters

Name Description Value
ingress.enabled Enable ingress record generation true
ingress.className IngressClass name "traefik"
ingress.annotations Additional annotations for the Ingress resource See values.yaml
ingress.hosts Array of host and path objects See values.yaml
ingress.tlsSecretName Global TLS secret name for all hosts ""
ingress.tls TLS configuration See values.yaml
ingress.tls[].secretName Host-specific TLS secret name (overrides global) ""

Persistence parameters

Name Description Value
persistence.enabled Enable persistence using PVC false
persistence.storageClass PVC Storage Class ""
persistence.accessMode PVC Access Mode ReadWriteOnce
persistence.size PVC Size 1Gi

Health Checks

Name Description Value
probes.startup.enabled Enable startup probe true
probes.startup.initialDelaySeconds Initial delay for startup probe 10
probes.startup.periodSeconds Period for startup probe 10
probes.startup.failureThreshold Failure threshold for startup probe 30
probes.liveness.enabled Enable liveness probe true
probes.liveness.initialDelaySeconds Initial delay for liveness probe 30
probes.liveness.periodSeconds Period for liveness probe 10
probes.readiness.enabled Enable readiness probe true
probes.readiness.initialDelaySeconds Initial delay for readiness probe 5
probes.readiness.periodSeconds Period for readiness probe 5

Application Configuration

Name Description Value
config.name Application name selfhosted
config.is_done_tick_dot_com Enable donetick.com features false
config.is_user_creation_disabled Disable user registration false

Real-time Configuration

Name Description Value
config.realtime.max_connections Maximum WebSocket connections 100
config.realtime.ping_interval WebSocket ping interval 30s
config.realtime.pong_wait WebSocket pong wait timeout 60s
config.realtime.write_wait WebSocket write timeout 10s
config.realtime.max_message_size Maximum WebSocket message size 512

Database Configuration

Name Description Value
config.database.type Database type (sqlite or postgres) sqlite
config.database.migration Enable database migrations true
config.database.host PostgreSQL host (when type=postgres) ""
config.database.port PostgreSQL port (when type=postgres) 5432
config.database.user PostgreSQL user (when type=postgres) ""
config.database.password PostgreSQL password (when type=postgres) ""
config.database.name PostgreSQL database name (when type=postgres) ""

JWT Configuration

Name Description Value
config.jwt.secret JWT signing secret changeme-this-secret-should-be-at-least-32-characters-long
config.jwt.session_time JWT session duration 168h
config.jwt.max_refresh JWT maximum refresh duration 168h

Server Configuration

Name Description Value
config.server.port Server port 2021
config.server.read_timeout Server read timeout 10s
config.server.write_timeout Server write timeout 10s
config.server.rate_period Rate limiting period 60s
config.server.rate_limit Rate limiting requests per period 300
config.server.serve_frontend Serve frontend files true

Feature Flags

Name Description Value
config.features.notifications Enable notifications true
config.features.realtime Enable real-time features true
config.features.oauth Enable OAuth authentication false

Database Setup

PostgreSQL Requirements

When using PostgreSQL, ensure you have:

  1. Database Created: Create a database for Donetick
CREATE DATABASE donetick;
CREATE USER donetick WITH PASSWORD 'your-secure-password';
GRANT ALL PRIVILEGES ON DATABASE donetick TO donetick;
  1. Network Access: Ensure Donetick can reach your PostgreSQL instance
  2. Proper Credentials: Configure database credentials in values or secrets

Database Migration

Donetick automatically runs database migrations on startup when config.database.migration: true. For production:

  1. Review Migrations: Check what migrations will be applied
  2. Backup Database: Always backup before running migrations
  3. Monitor Startup: Watch pod logs during initial deployment

Troubleshooting

Common Issues

1. Real-time Configuration Panic

Error: Invalid real-time configuration: maxConnections must be positive, got 0

Solution: Ensure the real-time configuration is properly set:

config:
  realtime:
    max_connections: 100  # Must be > 0

2. Database Connection Issues

Error: Database connection failures

Solutions:

  • Verify PostgreSQL is running and accessible
  • Check database credentials in secrets
  • Ensure database name exists
  • Verify network policies allow connection

3. JWT Secret Issues

Error: JWT authentication failures

Solution: Ensure JWT secret is at least 32 characters:

config:
  jwt:
    secret: "your-very-secure-jwt-secret-at-least-32-characters-long"

4. CORS Issues

Error: Cross-origin request blocked

Solution: Configure CORS origins:

config:
  server:
    cors_allow_origins:
      - "https://your-domain.com"
      - "http://localhost:5173"

Debugging

Check application logs:

kubectl logs deployment/donetick -f

Check configuration:

kubectl get configmap donetick-configmap -o yaml

Verify secrets:

kubectl get secret donetick-secrets -o yaml

Contributing

Please feel free to contribute by opening issues or pull requests at: https://github.com/rtomik/helm-charts

License

This Helm chart is licensed under the MIT License.