Setup guide

Get Skint running in about ten minutes

Install Docker, unzip Skint, and open it at localhost:8080. Each step stands on its own, so jump straight to where you are.

  • About 10 minutes
  • Needs Docker
  • Opens on port 8080

What you need

  • A computer or home server with Docker and Docker Compose
  • Your Expenditure spreadsheet, if you want to import existing figures

1. Install Docker

Skint runs in Docker. Pick the option for your system. You only need one.

macOS or Windows

Docker Desktop

  1. Download it from docker.com and install.
  2. On Windows it uses WSL 2. If prompted, enable it and restart.
  3. Open Docker Desktop and wait until it says it's running.

macOS

OrbStack

  1. Download it from orbstack.dev and open it.
  2. Finish setup. It installs the docker and docker compose commands for you.

A lighter alternative to Docker Desktop.

Linux

Docker Engine

On Ubuntu or Debian, install from Docker's repository. Other distros are in Docker's guide.

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USER

Sign out and back in after the last line so the group change applies.

Check it works

docker --version
docker compose version
docker run --rm hello-world

Use docker compose with a space. The older docker-compose command isn't needed.

2

Download and unzip

Get the single zip. It contains the app source, the Dockerfile, docker-compose.yml and .env.example.

Download skint.zip

Unzip it into a new folder, then open a terminal in that folder for the next steps.

3

Configure

Copy the example settings file, then edit it in any text editor.

cp .env.example .env
SettingWhat it does
APP_PASSWORDTurns on the sign-in screen. Leave it empty to run without one.
APP_USERThe username for the sign-in screen. Defaults to admin.
ALLOWED_HOSTSDomain names the app answers to, such as skint.example.com,localhost. Empty accepts any address.
MFA_REMEMBER_DAYSDays a trusted browser stays signed in without a code. Defaults to 7. Set 0 to ask every time.
Tip: if you set ALLOWED_HOSTS, include localhost too if you'll open Skint from the same machine.
4

Start it

Run this in the folder with docker-compose.yml. The first build takes a minute or two.

docker compose up -d --build

Then open http://localhost:8080 in your browser.

Useful commands

docker compose ps             # check the container is running
docker compose logs -f skint  # follow the app's log
docker compose restart skint  # restart after changing .env
docker compose down           # stop the app (your data is kept)
5

Load your figures

On the first run the dashboard offers Import spreadsheet. Choose your Expenditure.xlsx in Settings and the data loads.

Heads up: importing replaces everything stored. Download a backup first if you already have data.

Prefer to start fresh? Skip the import and add bills from the Bills page.

6

Add the household

Add each person in Settings → People. Everyone then sets up two-step sign-in: they scan a QR code with an authenticator app, enter the first code, and save their eight recovery codes.

Behind a reverse proxy

Skint listens on port 8000 inside its container. The default setup publishes that as port 8080. If you already run Traefik or nginx, put Skint on your proxy network instead and let the proxy handle HTTPS. Replace skint.example.com with your domain in each example.

Traefik

docker-compose.yml with Traefik labels

Assumes Traefik has a websecure entrypoint, a letsencrypt certificate resolver, and an external Docker network called proxy. The app's own compose file is not in the download.

services:
  skint:
    build: .
    container_name: skint
    restart: unless-stopped
    networks:
      - proxy
    environment:
      APP_USER: ${APP_USER:-admin}
      APP_PASSWORD: ${APP_PASSWORD:-}
      ALLOWED_HOSTS: skint.example.com
      MFA_REMEMBER_DAYS: ${MFA_REMEMBER_DAYS:-7}
    volumes:
      - skint-data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.skint.rule=Host(`skint.example.com`)"
      - "traefik.http.routers.skint.entrypoints=websecure"
      - "traefik.http.routers.skint.tls.certresolver=letsencrypt"
      - "traefik.http.services.skint.loadbalancer.server.port=8000"

networks:
  proxy:
    external: true

volumes:
  skint-data:

nginx

docker-compose.yml with nginx in front

Skint and nginx share a private network. Skint publishes no port, so only nginx can reach it. Put your certificate and key where the paths in nginx.conf point.

services:
  skint:
    build: .
    container_name: skint
    restart: unless-stopped
    networks:
      - web
    environment:
      APP_USER: ${APP_USER:-admin}
      APP_PASSWORD: ${APP_PASSWORD:-}
      ALLOWED_HOSTS: skint.example.com
      MFA_REMEMBER_DAYS: ${MFA_REMEMBER_DAYS:-7}
    volumes:
      - skint-data:/data

  nginx:
    image: nginx:stable
    container_name: skint-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/skint.conf:ro
      - ./certs:/etc/nginx/certs:ro
    networks:
      - web
    depends_on:
      - skint

networks:
  web:

volumes:
  skint-data:

nginx.conf

server {
    listen 80;
    server_name skint.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name skint.example.com;

    ssl_certificate     /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/privkey.pem;

    location / {
        proxy_pass http://skint:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Keep your data safe

Back up regularly

Download a JSON backup from Settings and keep a copy off the machine.

Keep the volume

Don't run docker compose down -v. The -v flag deletes the data volume.

Go online safely

If you open Skint beyond your own network, set a password and put it behind HTTPS.