Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Self-hosting

Recipes for running inkwell as a long-lived service — docker-compose, a reverse proxy for TLS, admin access control, backups, and upgrades.

docker-compose

services:
  inkwell:
    image: inkwell:latest
    build: .
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./config.yaml:/app/config.yaml:ro
      - inkwell-data:/data

volumes:
  inkwell-data:

Place config.yaml next to the compose file (start from config.example.yaml), then:

docker compose up -d

The reader is reachable at http://<host>:8080/. The inkwell-data volume holds the article cache, image cache, bookmarks, and admin-edited feed list, and persists across container recreation.

Reverse proxy

To serve over HTTPS, place a reverse proxy in front of the container.

Caddy

inkwell.example.com {
    reverse_proxy localhost:8080
}

Caddy provisions and renews TLS certificates automatically.

nginx

server {
    listen 443 ssl http2;
    server_name inkwell.example.com;

    ssl_certificate     /etc/letsencrypt/live/inkwell.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/inkwell.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Admin access control

The /admin route is unauthenticated. When the reader is exposed beyond a trusted network, gate /admin/* at the reverse proxy — HTTP Basic auth in nginx or Caddy is enough, or use an external identity provider such as authelia or Authentik.

To sign a new Kindle in without typing a password on the device, see authenticating your e-reader.

Backups

All persistent state lives in the inkwell-data volume. Back it up with a periodic SQLite .backup to a path inside the volume, then copy the resulting file off-host:

docker compose exec inkwell sqlite3 /data/reader_cache.sqlite \
  ".backup '/data/backup-$(date +%Y%m%d).sqlite'"

Upgrades

docker compose pull   # or: docker compose build --pull
docker compose up -d

Schema migrations run on startup.