Tracking your bank accounts with a Raspberry Pi: Kresus
Posted on July 24, 2017 in DIY • 5 min read
I always had troubles tracking expenses on my bank accounts. You never have the correct password or login when you want to check your bank account status, you have to log into every bank website when you have multiple bank accounts, bank interfaces are super painful and so on. I recently discovered Kresus, a nice app to selfhost on one of your servers and centralize in a single interface all your bank accounts, while offering advanced features to ease tracking expenses. For instance you can enter check expenses when you are making the check, and this “virtual” transaction can be merged with the real transaction when the check is taken to the bank, thus ending “Check number XXX” unknown transactions on your operations list.
As I consider banking information very sensitive, I decided to host the app on
a dedicated Raspberry Pi on my local network, quite isolated and controlled. I
am assuming you start with a lite version of Raspbian
. You can have a look
at my Raspberry pi post-install
checklist.
Note: This post is about a quite cutting-edge setup, using nightly
versions of Kresus (instead of stable tagged versions) and Python 3 instead of
Python 2. Python 3 support is still very experimental as of writing this
blogpost, but the instructions should work by cloning a git tag of Kresus
(instead of using the master
branch) and replacing python3
by python2
.
Install NodeJS
First, you should install NodeJS
. NodeJS
is sadly only available in a very
old version in Raspbian
repositories, and NodeJS
official repositories and
install script does not yet support the ARM platform, so you will have to
install it by hand.
The easiest way to get it is to wget
the LTS version available on the
official website on your Raspberry Pi (take care in
downloading the correct ARM build) and inflating it to /usr
. As of writing
this blog post, this can be done with
pi@raspberry ~ $ wget https://nodejs.org/dist/v6.11.1/node-v6.11.1-linux-armv6l.tar.xz
pi@raspberry ~ $ tar xvf node-v6.11.1-linux-armv6l.tar.xz
pi@raspberry ~ $ sudo cp -R node-v6.11.1-linux-armv6l/* /usr/
pi@raspberry ~ $ rm -r node-v6.11.1-linux-armv6l*
If everything went smoothly, node
and npm
commands should be available.
Install Weboob
Weboob is a dependency of Kresus, it is the free software powering the backend and actually fetching data from your bank website. You should install it before installing Kresus.
First, install Weboob dependencies:
pi@raspberry ~ $ sudo apt-get update && sudo apt-get install git python3 python3-dev python3-pip libffi-dev libxml2-dev libxslt-dev libyaml-dev libtiff-dev libjpeg-dev zlib1g-dev libfreetype6-dev libwebp-dev build-essential gcc g++ wget python3-imaging python3-lxml
Then, clone the Weboob git repository and install it:
pi@raspberry ~ $ git clone https://git.weboob.org/weboob/devel/ weboob
pi@raspberry ~ $ cd weboob && sudo pip3 install .
You should cd ~pi/weboob && git pull origin master
periodically to ensure
that Weboob modules (the code actually scraping data from your bank website)
are up to date. This is best done in a daily crontask.
Add a dedicated Kresus user
Let us add a new user, without password and with /bin/false
as shell:
pi@raspberry ~/weboob $ sudo adduser kresus --disabled-password
pi@raspberry ~/weboob $ sudo chsh kresus
[…] Type "/bin/false"
This will be the user with restricted privileges that will be used to clone
and run Kresus. To su
as this user, use
pi@raspberry ~ $ sudo su kresus -s /bin/bash
Note: When doing a su
like this, you cannot use screen
afterwards, you
should use script /dev/null
before, see this SO
thread.
Install Kresus
We can now clone Kresus Git repository
kresus@raspberry ~ $ cd && git clone https://framagit.org/kresusapp/kresus/
and install required NPM packages
kresus@raspberry ~ $ cd kresus && npm install
This will take quite a long time, especially the pouchdb
build as there are
not any prebuilt binary for Raspberry Pi. I had a problem with leveldown
dependency on my Raspberry Pi, it was not installing its dependency prebuild
and build was failing with a prebuild command not found
error. If you have
any such issue, just npm install prebuild
and re-run npm install
.
Note: Make sure that as less stuff as possible is running on your Raspberry
Pi when running npm install
, or the process might get killed due to an out
of memory error. In case you have a problem with a given module and npm
install
does not want to reinstall it, just delete the associated folder
under kresus/node_modules
and rerun npm install
.
Finally, build the Kresus production files:
kresus@raspberry ~/kresus $ NODE_ENV=production make build
Check that Kresus is working
kresus@raspberry /home/kresus/kresus $ NODE_ENV=production KRESUS_PYTHON_EXEC=python3 KRESUS_WEBOOB_DIR=/home/pi/weboob node bin/kresus.js
It should be starting and giving you access to the web interface on port
9876
, giving Kresus server is listening on port 9876...
and info - init |
Server is ready, let's start the show!
in the logs. Attention, by default
Kresus will not listen on anything else than localhost
so you will have to
proxy (typically with ssh
SOCKS
) on your Raspberry Pi to try it in your browser.
Launch on start
Let us use Systemd to start automatically Kresus on boot
$ cat /etc/systemd/system/kresus.service
[Unit]
Description=Personal finance manager
After=network.target
[Service]
WorkingDirectory=/home/kresus/kresus
Environment=NODE_ENV=production
Environment=KRESUS_PYTHON_EXEC=python3
Environment=KRESUS_WEBOOB_DIR=/home/pi/weboob
ExecStart=/usr/bin/node bin/kresus.js
Type=simple
Restart=always
User=kresus
StandardOutput=journal
StandardError=inherit
SyslogIdentifier=kresus
[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl start kresus.service
And if everything works fine,
sudo systemctl enable kresus.service
to automatically start your Kresus at every boot.
Nginx
Now, we would like our Kresus to be accessible from the rest of our local network, with an authentication layer on top. We will use Nginx for this, here is a sample configuration file:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /home/kresus/kresus/build/client;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# Only proxy the API calls
location /api {
proxy_pass http://127.0.0.1:9876;
proxy_set_header Host $host;
proxy_set_header Proxy "";
# Longer timeouts on my (slow) Raspberry Pi
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
}
deny all;
allow 192.168.0.0/24;
}
# HTTP Authentication
auth_basic "Restricted";
auth_basic_user_file /home/kresus/kresus/.htpasswd;
# Security headers
add_header x-xss-protection "1; mode=block";
add_header x-frame-options "DENY";
add_header X-Content-Type-Options "nosniff";
add_header Content-Security-Policy "default-src 'self'; child-src 'none'; object-src 'none'; img-src 'self' data:;";
add_header Referrer-Policy "no-referrer";
# If using HTTPS, enable the following line
# add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
}
It is really important you add HTTP Authentication on top of it and configure your firewall to limit access to certain IPs (mine is only accessible from local network). Indeed, out of the box, Kresus does not provide any form of authentication (to avoid risking to make it wrong). Then, the HTTP Authentication layer from your webserver is the only authentication layer across your install.
As my Raspberry Pi is not web-accessible this alternative DNS method for Let’s Encrypt was useful to get a certificate anyways.
Hope this helps tracking your expenses ! :)
Bonus part: putting Kresus’ db in RAM
Kresus is quite slow on a Raspberry Pi v1, even using a good class 10 SD card
and a bit of overclocking. An easy trick to improve this is to put the
database in RAM, mounted through tmpfs
.
$ # First, create a mount point
$ mkdir /home/kresus/kresus_vram && chown kresus:kresus /home/kresus/kresus_vram
$ # Then, mount the tmpfs endpoint
$ cat /etc/fstab
[…]
tmpfs /home/kresus/kresus_vram tmpfs defaults,size=32M,uid=kresus,gid=kresus 0 0
$ # Set up a crontask to backup to the SD card often (tmpfs is erased after a reboot)
$ sudo crontab -u kresus -l
*/5 * * * * /usr/bin/rsync -ar /home/kresus/kresus_vram/ /home/kresus/.kresus/
Then, just edit the systemd
unit to sync in the other way at startup:
Environment=KRESUS_DIR=/home/kresus/kresus_vram
ExecStartPre=/usr/bin/rsync -ar /home/kresus/.kresus/ /home/kresus/kresus_vram/
And you are all set :)