Setting up Firefly3#
*Kanboard is a lightweight, self-hosted Kanban-style project management tool.
It lets you organize tasks on boards with columns (e.g., To Do → Doing → Done), focusing on simplicity, minimal dependencies, and low resource usage.*
I wanted to show a few services, but for the most part after K3s is up and online the services are self explanitory through code. Each service is likely to vary in its own way, but I wanted to present a few.
hostPath v Local#
One of the biggest differences between this service and the others is the use of hostPath within the PersistentVolume.
Below is one of the better explanations I have seen with a table explaining the differences:
hostPath is a simple, node-specific mount that bypasses scheduler awareness, so Kubernetes does not enforce where Pods land relative to the data.
In contrast, a local PersistentVolume is modeled as a node-bound resource, requiring node affinity so the scheduler can place Pods on the correct node.
This makes local suitable for multi-node clusters, while hostPath is primarily a single-node or development convenience.
| Aspect | hostPath | local PersistentVolume |
|---|---|---|
| Scheduler awareness | No | Yes |
| Node affinity required | No | Yes |
| Multi-node safety | No | Yes (with constraints) |
| Typical usage | Dev / single-node / debugging | Production local storage |
| Data locality handling | Manual | Enforced by scheduler |
Based on the above information I will likely swap the other PersistentVolumes to this configuration as this setup will only be running on one host.
To Note and To Fix#
One of the things I want to fix is environment settings for the domain name. I need to be able to pass in the variables for the domain.
This will be something to fix in the near future.
# -------------------------------------------------------------------
# 1. STORAGE: PV and PVC (Points to /var/lib/kanboard)
# -------------------------------------------------------------------
apiVersion: v1
kind: PersistentVolume
metadata:
name: kanboard-pv
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
storageClassName: kanboard-local
local:
path: /var/lib/nik3sx/kanboard
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- l-nodet
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: kanboard-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: kanboard-local
resources:
requests:
storage: 2Gi
---
# -------------------------------------------------------------------
# 2. DATABASE: MariaDB Deployment & Internal Service
# -------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
spec:
selector:
matchLabels:
app: kanboard
tier: db
template:
metadata:
labels:
app: kanboard
tier: db
spec:
containers:
- name: mariadb
image: mariadb:latest
args: ["--default-authentication-plugin=mysql_native_password"]
env:
- name: MYSQL_ROOT_PASSWORD
value: "secret"
- name: MYSQL_DATABASE
value: "kanboard"
- name: MYSQL_USER
value: "kb"
- name: MYSQL_PASSWORD
value: "kb-secret"
- name: MARIADB_MYSQL_LOCALHOST_USER
value: "1"
ports:
- containerPort: 3306
volumeMounts:
- name: storage
mountPath: /var/lib/mysql
subPath: database # Maps to /var/lib/kanboard/database
volumes:
- name: storage
persistentVolumeClaim:
claimName: kanboard-pvc
---
apiVersion: v1
kind: Service
metadata:
name: db
spec:
selector:
app: kanboard
tier: db
ports:
- protocol: TCP
port: 3306
targetPort: 3306
---
# -------------------------------------------------------------------
# 3. APPLICATION: Kanboard Deployment & External Service
# -------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: kanboard
spec:
selector:
matchLabels:
app: kanboard
tier: frontend
template:
metadata:
labels:
app: kanboard
tier: frontend
spec:
containers:
- name: kanboard
image: kanboard/kanboard:latest
env:
- name: DATABASE_URL
value: "mysql://kb:kb-secret@db/kanboard"
ports:
- containerPort: 80
volumeMounts:
- name: storage
mountPath: /var/www/app/data
subPath: data # Maps to /var/lib/kanboard/data
- name: storage
mountPath: /var/www/app/plugins
subPath: plugins # Maps to /var/lib/kanboard/plugins
- name: storage
mountPath: /etc/nginx/ssl
subPath: ssl # Maps to /var/lib/kanboard/ssl
volumes:
- name: storage
persistentVolumeClaim:
claimName: kanboard-pvc
---
apiVersion: v1
kind: Service
metadata:
name: kanboard
spec:
type: ClusterIP
selector:
app: kanboard
tier: frontend
ports:
- port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kanboard
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
tls:
- hosts:
- test-kb.jmoore53.dev
secretName: boot-unlock-tls
rules:
- host: test-kb.jmoore53.dev
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kanboard
port:
number: 80