Self-hosted accountancy with Firefly III
Keep track of expenses and stuff is hard, thankless work.
Over the years I've done it, with varying degrees of success, using a variety of solutions including my first ever LAMP project, right after learning PHP and MySQL, and once my bank's own built-in solutions until they unceremonously took it away with no notice.
After this last disappointment, I decided to go the self-hosted way taking inspiration from the list of Money, Budgeting & Management solutions by Awesome-Selfhosted. Based on comments in several forums, I decided to first try with Firefly III.
Deployment
Before deploying this applications, persistant storage needs to be prepared for the database and the application itself:
# mkdir -p /home/k8s/firefly-iii/mysql /home/k8s/firefly-iii/upload
# chown -R 33.33 /home/k8s/firefly-iii/mysql
# chown -R www-data.www-data /home/k8s/firefly-iii/upload
# ls -ln /home/k8s/firefly-iii
total 0
drwxr-xr-x 1 100 101 390 May 19 19:49 mysql
drwxrwxr-x 1 33 33 0 May 19 16:18 upload
Note
User and groupd IDs are enforced by the docker images. Enforcing different users seems to be too much of a headache.
Firefly III on Kubernetes. includes deployments for each component, of which I will be using the most basic ones:
mysql.yamlfor the database.firefly-iii.yamlfor the web application.ingress-firefly-iii.yamlfor the ingress.
While these are meant to be used with kustomize, I will keep it
simpler by putting it all together in my own firefly-iii.yaml:
Kubernetes deployment: firefly-iii.yaml
| firefly-iii.yaml | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
Note
The APP_KEY value must have exactly 32 characters, as noted in
#2193: Can't get started - hitting an "encryption key not specified error",
also better explained in
monicahq/monica #6449.
$ kubectl apply -f firefly-iii.yaml
namespace/firefly-iii created
persistentvolume/firefly-iii-pv-mysql created
persistentvolumeclaim/firefly-iii-pvc-mysql created
deployment.apps/firefly-iii-mysql created
service/firefly-iii-mysql-svc created
persistentvolume/firefly-iii-pv-upload created
persistentvolumeclaim/firefly-iii-pvc-upload created
service/firefly-iii-svc created
deployment.apps/firefly-iii created
ingress.networking.k8s.io/firefly-iii-ingress created
$ kubectl -n firefly-iii get all
NAME READY STATUS RESTARTS AGE
pod/cm-acme-http-solver-vfwlp 1/1 Running 0 16s
pod/firefly-iii-6c8dbdd45f-jqdsv 1/1 Running 0 16s
pod/firefly-iii-mysql-68f59d48f-chhbw 1/1 Running 0 16s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/firefly-iii-mysql-svc NodePort 10.97.148.234 <none> 3306:30306/TCP 16s
service/firefly-iii-svc NodePort 10.99.161.143 <none> 8080:30080/TCP 16s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/firefly-iii 1/1 1 1 16s
deployment.apps/firefly-iii-mysql 1/1 1 1 16s
NAME DESIRED CURRENT READY AGE
replicaset.apps/firefly-iii-6c8dbdd45f 1 1 1 16s
replicaset.apps/firefly-iii-mysql-68f59d48f 1 1 1 16s
Once the service has started up, initialized the database and everything else, one can finally visit https://ffi.ssl.uu.am/ to create an account and get started:
Note
The cm-acme-http-solver is responsible for obtaining
a valid certificated for this service; the HTTPS connection will
be secure only after this pod has finished its job.
Note
The password must have at least 16 characters, which is more than Chrome will use when suggesting a strong password.
From this point on, RTFM will be probably the best way to go.
