kosync-dotnet is a self-hostable implementation of the KOReader sync server built with .NET. It aims to extend the existing functionality of the official koreader-sync-server.
Users of KOReader can register a user on this synchronisation server and use the inbuilt Progress sync plugin to keep all reading progress synchronised between devices.
All data is stored inside a LiteDB database file.
The recommendation is to use Docker with Docker Compose.
version: "3"
services:
kosync:
container_name: kosync
image: ghcr.io/jberlyn/kosync-dotnet:latest
restart: unless-stopped
volumes:
- </path/to/data>:/app/data
environment:
- ADMIN_PASSWORD=<super-strong-password>
- REGISTRATION_DISABLED=false
user: 1000:1000
/app/data
will contain the database, which stores user and document progress information.
An admin user with the username admin
will be created when the server first starts. If you provide the ADMIN_PASSWORD
environment variable, the password for this admin user will be changed to the value provided. If you do not provide a value, the password for this user will be set to admin
. The recommendation is to set this to a strong password generated with a password manager like Bitwarden. This admin user can be used to interact with the management API.
If the REGISTRATION_DISABLED
environment variable is set to true
, the sync server will respond with an User registration is disabled
error message when trying to create a new user. This is useful if you expose your sync server to the public internet, but don't want anyone to be able to register a user. This is a feature that is not available in the official sync server.
Mapping user to 1000:1000
is just a way to ensure the database files are created using your own user, rather than root. If your operating system user ID is different from 1000:1000
, change it to yours.
This example doesn't expose any ports for the container, however the sync server is accessible via port 80 inside the container. The recommendation is to expose the server via a reverse proxy such as Nginx Proxy Manager.
There are some management API endpoints you can interact with using a tool like Postman.
Only the admin user can make requests to these API endpoints.
All requests to these API endpoints require the following headers.
{
"x-auth-user": "admin"
"x-auth-key": "<MD5 hash of your admin password>"
}
Since we reuse the existing user structure used for KOReader, unfortunately we are stuck using MD5 hashes for passwords instead of something more secure.
Returns a list of all users.
Example Response
[
{
"id": 1,
"username": "admin",
"isAdministrator": true,
"isActive": true,
"documentCount": 0
},
{
"id": 1,
"username": "jberlyn",
"isAdministrator": false,
"isActive": true,
"documentCount": 1
}
]
Creates a new user. This endpoint circumvents the REGISTRATION_DISABLED
environment variable.
Request Body
{
"username": "jberlyn",
"password": "super-strong-password"
}
Example Response
{
"message": "User created successfully"
}
Returns a list of documents for a user and their sync status. The username for the user must be passed via a query parameter.
Example Response
[
{
"documentHash": "b8a9c5b494e7c91ece4cb8407e746ec7",
"progress": "/body/DocFragment[28]/body/div/section/h1[1]/a/span/text().0",
"percentage": 0.3186,
"device": "Kobo_nova",
"deviceId": "F47D5CA7123A4ABEAB90E8BF6F836356",
"timestamp": "2023-05-23T11:43:00.225+10:00"
},
{
"documentHash": "b1e5b67d6b0fe57ce9893d08dce65406",
"progress": "/body/DocFragment[10]/body/div/h1/text().0",
"percentage": 0.0166,
"device": "Kobo_nova",
"deviceId": "F47D5CA7123A4ABEAB90E8BF6F836356",
"timestamp": "2023-05-23T11:44:34.165+10:00"
}
]
Toggles the active status of a user. The username for the user must be passed via a query parameter. Users that are marked as inactive will not be able to login or push sync progress.
Example Response
{
"message": "User marked as inactive"
}
Updates the password for a user. The username for the user must be passed via a query parameter.
Request Body
{
"password": "super-strong-password"
}
Example Response
{
"message": "Password changed successfully"
}