/Website

Primary LanguageRustGNU General Public License v3.0GPL-3.0

Ryot Logo

A self hosted platform for tracking various facets of your life - media, fitness etc.

Ryot (Roll Your Own Tracker), pronounced "riot", aims to be the only self hosted tracker you will ever need!

NOTE FOR EXISTING USERS

The first public release includes huge code changes. If you were running the v1.0.0-beta.* versions, then please follow the migration notes for the latest release here. Please be warned that failing to do so WILL result in data loss.

πŸ’» Demo

You can use the demo instance hosted on Fly.io. Login and register with the username demo and password demo-password. This instance is automatically deployed from the latest release.

NOTE: The data in this instance can be deleted randomly.

πŸ“ ELI5

Imagine you have a special notebook where you can write down all the media you have consumed, like books you've read, shows you have watched, video games you have played or workouts you have done. Now, imagine that instead of a physical notebook, you have a special tool on your computer or phone that lets you keep track of all these digitally.

πŸ’‘ Why?

  • Existing solutions do not have very good UI.
  • Pretty graphs and summaries make everyone happy. Ryot aims to have a lot of them.
  • There is a lack of a good selfhosted fitness and health tracking solution.
  • Ryot consumes very little memory (around 10MB idle eyeballing docker stats), something that is significantly useful in RAM constrained environments.

πŸš€ Features

  • βœ… Supports tracking media and fitness.
  • βœ… Import data
    • Goodreads
    • MediaTracker
  • βœ… Self-hosted
  • βœ… Documented GraphQL API
  • βœ… Easy to understand UI
  • βœ… Lightning fast (written in Rust BTW)
  • βœ… Free and open-source

πŸ“– Guides

Some things might not be obvious on how to setup or get working. I have written a number of guides to make thing easier.

⌨️ How to use?

NOTE: The first user you register is automatically set as admin of the instance.

🐳 Option 1: Use Docker

To get a demo server running, use the docker image:

$ docker run \
  --detach \
  --name ryot \
  --pull always \
  --publish 8000:8000 \
  --env "WEB_INSECURE_COOKIE=true" \
  ghcr.io/ignisda/ryot:latest

NOTE: The WEB_INSECURE_COOKIE is only required if you are not running HTTPs.

In addition to the latest tag, we also publish an unstable tag from the latest pre-release (or release, whichever is newer).

πŸ“¦ Option 2: Quick-run a release

Each release has an installation script that can be used to install the ryot binary. Follow the instructions in the release to use this script.

Alternatively using eget:

$ eget ignisda/ryot

πŸ§‘β€πŸ’»Option 3: Compile and run from source

# Build the frontend
$ moon run frontend:build

# Run it
$ cargo run --bin ryot --release

πŸ‘€ Production

You will have to mount a directory to the /data, giving it the 1001:1001 permissions. It is also recommended to use PostgreSQL or MySQL in production.

πŸ”§ Configuration options

You can specify configuration options via files (loaded from config/ryot.json, config/ryot.toml, config/ryot.yaml) or via environment variables.

To set the equivalent environment variables, join keys by _ (underscore) and UPPER_SNAKE_CASE the characters. For example, the key audio_books.audible.url corresponds to the environment variable AUDIO_BOOKS_AUDIBLE_URL.

Ryot serves the final configuration loaded at the /config endpoint as JSON (example).

Note: You can see the defaults in the config builder. A minimal example configuration is in ryot.example.json.

Key Description
{anime,manga}.anilist.url The url to make requests for getting metadata about anime/manga.
audio_books.audible.url The url to make requests for getting metadata from Audible.
books.openlibrary.url The url to make requests for getting metadata from Openlibrary.
books.openlibrary.cover_image_url The url for getting images from Openlibrary.
books.openlibrary.cover_image_size The image sizes to fetch from Openlibrary.
database.url The database connection string. Supports SQLite, MySQL and Postgres.
database.scdb_url The path where SCDB will persist its storage.
file_storage.s3_access_key_id The access key ID for the S3 compatible file storage. Required to enable file storage.
file_storage.s3_bucket_name The name of the S3 compatible bucket. Required to enable file storage.
file_storage.s3_secret_access_key The secret access key for the S3 compatible file storage. Required to enable file storage.
file_storage.s3_region The region for the S3 compatible file storage.
file_storage.s3_url The URL for the S3 compatible file storage.
{movies,shows}.tmdb.url The url to make requests for getting metadata about shows/movies.
{movies,shows}.tmdb.access_token The access token for the TMDB API.
podcasts.listennotes.url The url to make requests for getting metadata about podcasts.
podcasts.listennotes.api_token The access token for the Listennotes API. Required to enable podcasts tracking.
scheduler.database_url The url to the SQLite database where job related data needs to be stored.
scheduler.user_cleanup_every Deploy a job every x hours that performs user cleanup and summary calculation.
scheduler.rate_limit_num The number of jobs to process every 5 seconds when updating metadata in the background.
video_games.twitch.client_id The client ID issues by Twitch. Required to enable video games tracking. More information
video_games.twitch.client_secret The client secret issued by Twitch. Required to enable video games tracking.
video_games.twitch.access_token_url The endpoint that issues access keys for IGDB.
video_games.igdb.url The url to make requests for getting metadata about video games.
video_games.igdb.image_url The url for getting images from IGDB.
video_games.igdb.image_size The image sizes to fetch from IGDB.
users.allow_changing_username Whether users will be allowed to change their username in their profile settings.
users.allow_registration Whether new users will be allowed to sign up to this instance.
users.token_valid_for_days The number of days till login auth token is valid.
web.cors_origins An array of URLs for CORS.
web.insecure_cookie This will make auth cookies insecure and should be set to true if you are running the server on localhost. More information

πŸ€“ Developer notes

In production, the frontend is a pre-rendered Nextjs app served statically by the Axum backend server.

In development, both servers are started independently running on :3000 and :8000 respectively. To get them running, install mprocs, and run mprocs in the project root. If you do not want to install mprocs, take a look at mproc.yaml to see what all commands are needed to get it working.

Unless it is a very small change, I prefer creating a separate branch and merging it via an MR when it is done. The changelog is generated using git-chglog. Once all changes are done, run the following command to update the changelog.

$ git-chglog --next-tag <tag-name> -o CHANGELOG.md

πŸ™ Acknowledgements

It is highly inspired by MediaTracker. Moreover thanks to all those people whose stuff I have used.

The logo is taken from Flaticon.