Ultra-lightweight, zero-dependency sync server for KOReader devices. Self-host your reading progress sync on any PHP host with SQLite — no Docker, no Redis, no Lua required.
- Minimal:
<300lines of PHP, 5 files, single SQLite database - Fully compatible with the official koreader-sync-server API
- Built-in web interface for registration, login, and progress overview
- Delete reading progress entries from the web UI
- Supports the
metadatafield (shows document titles/filenames in the web UI) - Runs on PHP's built-in server, Apache, or nginx
| Method | Path | Description |
|---|---|---|
GET |
/healthcheck |
Health check |
POST |
/users/create |
Register a user |
GET |
/users/auth |
Authenticate (via x-auth-user / x-auth-key headers) |
PUT |
/syncs/progress |
Update document progress |
GET |
/syncs/progress/{hash} |
Get document progress |
GET |
/ |
Web interface |
php -S 0.0.0.0:8080 index.phpOpen http://localhost:8080 in your browser for the web interface.
The included .htaccess handles URL rewriting. Just point a virtual host to the project directory.
server {
listen 443 ssl;
server_name sync.example.com;
root /path/to/phpkoreadersync;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}A complete example is in nginx.example.conf.
Edit config.php:
define('DB_PATH', __DIR__ . '/data/kosync.sqlite');
define('ENABLE_USER_REGISTRATION', true); // set to false to disable registrationIn KOReader, go to Settings → Progress sync:
- Set Custom sync server to
https://your-server.com - Register or log in with a username and password
- Enable Automatically keep documents in sync
If you want document titles to show in the web interface, enable Send document metadata in the progress sync settings.
- Passwords are stored as MD5 hashes (matching the KOReader client convention)
- The
data/directory should be blocked from public access (see nginx config example) - For production, always run behind HTTPS (the KOReader client uses HTTPS by default)
- Consider putting the server behind a reverse proxy with TLS termination
Requests to /v1/healthcheck, /v1/users/create, etc. are also supported for setups that expect versioned paths.