| cmd/kosync | ||
| model | ||
| server | ||
| store | ||
| .gitignore | ||
| AGENTS.md | ||
| api.yml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| Makefile | ||
| README.md | ||
| spec.md | ||
| todo.md | ||
kosync
A small KOReader-compatible sync server written in Go. It implements user registration, user authentication, reading progress push, and reading progress pull using the standard net/http server and SQLite persistence.
Features
- KOReader sync API compatible routes; see
api.yml. - SQLite storage for users and reading progress.
- Registration enabled by default, with flag/env opt-out.
- CLI powered by
kong. - Structured logging through Go
slog, with configurable log level. - Graceful HTTP shutdown and sensible server timeouts.
- Lean multi-stage Docker image running as a non-root user.
Requirements
- Go 1.26+
make- Docker, only for container builds/runs
Build, test, and run
make fmt
make vet
make test
make build
make run
The compiled binary is written to bin/kosync.
Direct usage:
bin/kosync serve --addr :8437 --db kosync.db
Makefile commands
| Command | Description |
|---|---|
make help |
Show available targets |
make fmt |
Format Go code |
make vet |
Run go vet |
make test |
Run all tests |
make test-race |
Run tests with race detector |
make build |
Build bin/kosync |
make run |
Run kosync serve locally |
make clean |
Remove build artifacts |
make docker-build |
Build kosync:latest image |
make docker-run |
Run the Docker image on port 8437 |
CLI configuration
kosync serve [flags]
| Flag | Environment Variable | Default | Description |
|---|---|---|---|
--addr |
KOSYNC_ADDR |
:8437 |
HTTP listen address |
--db |
KOSYNC_DB |
kosync.db |
SQLite database path |
--disable-registration |
KOSYNC_DISABLE_REGISTRATION |
false |
Disable new user registration |
--log-level |
KOSYNC_LOG_LEVEL |
info |
Log level: debug, info, warn, or error |
At --log-level debug, the server logs each request URL and request payload, plus handler/store trace messages for the resulting operations. Sensitive fields such as passwords and authentication keys are redacted and x-auth-key headers are not logged.
Registration is enabled by default. Disable it with either:
kosync serve --disable-registration
KOSYNC_DISABLE_REGISTRATION=true kosync serve
API summary
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST |
/users/create |
No | Register user |
GET |
/users/auth |
Yes | Check credentials |
PUT |
/syncs/progress |
Yes | Store progress |
GET |
/syncs/progress/{document} |
Yes | Fetch progress |
Authentication uses headers:
x-auth-user: alice
x-auth-key: 3858f62230ac3c915f300c664312c63f
Example KOReader sync server URL:
http://your-server:8437
curl examples
curl -i -X POST http://localhost:8437/users/create \
-H 'Content-Type: application/json' \
-d '{"username":"alice","password":"3858f62230ac3c915f300c664312c63f"}'
curl -i http://localhost:8437/users/auth \
-H 'x-auth-user: alice' \
-H 'x-auth-key: 3858f62230ac3c915f300c664312c63f'
curl -i -X PUT http://localhost:8437/syncs/progress \
-H 'Content-Type: application/json' \
-H 'x-auth-user: alice' \
-H 'x-auth-key: 3858f62230ac3c915f300c664312c63f' \
-d '{"document":"22b3308b1618273ad77a98fe29ca4600","percentage":0.4045,"progress":"/body/DocFragment[26]","device":"Kindle","device_id":"device-1"}'
curl -i http://localhost:8437/syncs/progress/22b3308b1618273ad77a98fe29ca4600 \
-H 'x-auth-user: alice' \
-H 'x-auth-key: 3858f62230ac3c915f300c664312c63f'
SQLite persistence and backups
The SQLite database path defaults to kosync.db. The server enables foreign keys and WAL mode for file-backed databases. Back up the database file together with its WAL/SHM sidecar files when the server is running, or stop the server before copying the database.
Docker
Build and run:
make docker-build
make docker-run
Equivalent direct command:
docker run --rm \
-p 8437:8437 \
-v kosync-data:/data \
kosync:latest
The image defaults to:
KOSYNC_ADDR=:8437KOSYNC_DB=/data/kosync.db
The container runs as a non-root user and stores SQLite data under /data.
Security notes
KOReader sends an MD5 password string as x-auth-key; this server stores and compares that value directly for compatibility. Do not expose the service over an untrusted network without TLS. Use a reverse proxy such as Caddy, nginx, or Traefik to provide HTTPS and normal network access controls.