19 KiB
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:
- 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;
- Network Access: Ensure Donetick can reach your PostgreSQL instance
- 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:
- Review Migrations: Check what migrations will be applied
- Backup Database: Always backup before running migrations
- 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.