Setting up Firefly3#
*Firefly III is a self-hosted personal finance manager.
It helps you track expenses, income, budgets, and accounts, giving you detailed insight into your spending while keeping all financial data under your control.*
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.
#
# NAMESPACE
#
apiVersion: v1
kind: Namespace
metadata:
name: firefly
---
#
# VOLUMES
#
apiVersion: v1
kind: PersistentVolume
metadata:
name: firefly-upload-pv
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /var/lib/firefly-iii/upload
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: firefly-db-pv
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /var/lib/firefly-iii/db
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: firefly-upload-pvc
namespace: firefly
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: firefly-db-pvc
namespace: firefly
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
#
# MARIADB
#
---
apiVersion: v1
kind: Service
metadata:
name: firefly-db
namespace: firefly
spec:
clusterIP: None
selector:
app: firefly-db
ports:
- port: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: firefly-db
namespace: firefly
spec:
replicas: 1
selector:
matchLabels:
app: firefly-db
template:
metadata:
labels:
app: firefly-db
spec:
containers:
- name: mariadb
image: mariadb:lts
env:
- name: MYSQL_RANDOM_ROOT_PASSWORD
value: "yes"
- name: MYSQL_USER
value: "firefly"
- name: MYSQL_PASSWORD
value: "secret_firefly_password"
- name: MYSQL_DATABASE
value: "firefly"
ports:
- containerPort: 3306
volumeMounts:
- name: db-data
mountPath: /var/lib/mysql
volumes:
- name: db-data
persistentVolumeClaim:
claimName: firefly-db-pvc
#
# FIREFLY III
#
---
apiVersion: v1
kind: Service
metadata:
name: firefly
namespace: firefly
spec:
type: ClusterIP
selector:
app: firefly
ports:
- port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: firefly
namespace: firefly
spec:
replicas: 1
selector:
matchLabels:
app: firefly
template:
metadata:
labels:
app: firefly
spec:
containers:
- name: firefly
image: fireflyiii/core:latest
env:
- name: DB_DATABASE
value: "firefly"
- name: DB_USERNAME
value: "firefly"
- name: DB_PASSWORD
value: "secret_firefly_password"
- name: DB_HOST
value: "firefly-db"
- name: APP_KEY
value: "app_key_here_pretty_sure_this_has_to_be_32"
- name: APP_URL
value: "https://test-f3.jmoore53.dev:10443"
- name: TRUSTED_PROXIES
value: "**"
- name: COOKIE_SECURE
value: "true"
ports:
- containerPort: 8080
volumeMounts:
- name: upload
mountPath: /var/www/html/storage/upload
volumes:
- name: upload
persistentVolumeClaim:
claimName: firefly-upload-pvc
#
# CRON
#
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: firefly-cron
namespace: firefly
spec:
schedule: "0 3 * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: cron
image: alpine
command:
- sh
- -c
- |
apk add --no-cache tzdata wget &&
ln -sf /usr/share/zoneinfo/$TZ /etc/localtime &&
wget -qO- http://firefly:8080/api/v1/cron/v62pmPVSqUd26YceR87xHjYJMklyHdEX
#
# MIDDLEWARE
#
#apiVersion: traefik.io/v1alpha1
#kind: Middleware
#metadata:
# name: https-redirect
# namespace: firefly
#spec:
# redirectScheme:
# scheme: https
# permanent: true
#
# INGRESS
#
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: firefly
namespace: firefly
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls:
"true"
# traefik.ingress.kubernetes.io/router.middlewares: firefly-https-redirect@kubernetescrd
spec:
tls:
- hosts:
- test-f3.jmoore53.dev
secretName: boot-unlock-tls
rules:
- host: test-f3.jmoore53.dev
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: firefly
port:
number: 8080