LibRate
LibRate is a project that aims to provide a free, federated service for tracking, reviewing, sharing and discovering films, books, music, games and other culture texts.
This project is currently in early beta stage, bugs are expected and PRs are very welcome.
You can donate to it's development via LiberaPay Monero or BLIK (contact me on Matrix for the latter two).
The only public beta instance can be found at librate.club. Federation is currently work in progress. Bleeding edge branch can be found here
Table of contents
Roadmap:
Social features
- Basic registration support
- User profile cards
- Full profile pages
- Tagging and mentions
- (WIP) Advanced profile and UI customization
- Groups
- Direct messages (E2EE)
- Group chats, more group-friendly design, like Lemmy or Kbin
- (WIP) User-generated content tagging and categorization
- (WIP) Following
- Sharing
- (WIP) ActivityPub support, with selective federation
- Album cards
- Carousels showing random media
- Relevant DB setup
- Film and series cards
- Trailers and stills support
- Release notifications
- Sending them as DMs to federated service accounts
- Content filters
- Book cards and pages
- Anime and manga cards/pages
- Games support
- Customizable, shareable media collections and logging
- (WIP) Convenient submission form, with decentralized deduplication and POW-based anti-spam (a bit similar to Bookwyrm)
- Automated imports from 3rd party sources
- Scrobbling
- Decentralized subtitle repository
- DRM-free audio hosting and streaming(?)
- Artwork galleries for visual artists(?)
Reviews
- Basic review form
- Backend logic for submission and fetching of reviews
- (WIP) Review feed
- Commenting and voting on reviews and media items
- Importing from 3rd party sources
Recommendations
- Prototype logic
- Actual working implementation
- Personalized feeds
- Advanced algorithm powered by ML and graph-like database structure - already implemented
Other
- Extended configurability
- Internationalization
- Events, federating with Mobilizon
- Federated merch and works marketplace, possibly an alternative to Bandcamp
- Mobile app (although the frontend is and will be mobile friendly, but also never at the expense of desktop experience. We'll also try to make it work with Fedilab, though the number of distinctive features may make it difficult)
Adjust the configuration file example_config.yml to suit your needs.
The following configuration paths will be automatically checked and not require passing a -c
flag. These paths can either contain no or a .yml or .yaml extension.
- "./config",
-
"./config/config",
-
"/etc/librate/config",
-
"/var/lib/librate/config",
-
"/opt/librate/config",
-
"/usr/local/librate/config",
-
~/.local/share/librate/config",
-
~/.config/librate/config"
Then make the necessary adjustments to the privacy policy and Terms of Service, located in static/templates/examples and move them one directory up. If your instance is country-specific, you can add another file with your prospective users' main language code as a suffix to that directory. You need to at keep at least one version of TOS and Privacy using the BCP 47 language tag you've set as defaultLanguage
in config.
Deploying with Docker
Set up your config. If something's wrong with the networking, try setting the hostnames in config for anything except the gRPC server to 0.0.0.0
.
Then, before deploying, update the following line in postgres container start script:
psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'CHANGE_ME';"
You can use compose. Just remember to execute the commands from step 5 and create the network first.
Optionally in compose you can enable monitoring of your instance with Grafana and Prometheus, make sure to modify your password and remove the entrypoint lines for these services.
- Create a Docker network with
# 172.20.0.0 is the default subnet, this is needed for pg_hba.conf, though
# generally a hostname should work
docker network create --subnet 172.20.0.0/16 librate-net
- Run the redis container with
docker run -d --rm --network=librate-net --hostname "librate-redis"
redis:alpine
- Build and run the database container
cd db && \
docker build -t librate-db . && \
docker run -it --network=librate-net --hostname "librate-db" librate-db:latest
-
Create an config file from the provided example. Alternatively you can configure the container to use the .env config, but .yaml is somewhat more reliable (for example, as of 30-01-2024 there is no way of setting up thumbnailing with .env).
-
Build and run the app container. In the container run
lrctl -c [path to config file or 'env'] db init
lrctl -c [...] db migrate # If the migrations fail you can copy them to the database container and apply them manually, although this shouldn't happen. Note that each migration has a corresponding rollback (down) migration.
- Finally, set up some reverse proxy, like caddy or nginx, to resolve the app to a
hostname (locally you can also use something like
lr.localhost
). Note that
YOU MUST set up some reverse proxy, since the app hardcodes certain security
headers that make it unusable without HTTPS (although self-signed certs work,
but you're better off using caddy which will automatically generate a free
certificate with Let's Encrypt for you).
Prerequisites for running natively:
Get the Dependencies
- SOPS and age for handling secrets
pnpm
, yarn
or npm
, for building the frontend
- working Postgres and Redis instances. You'll also need to install the development files package for postgres since LibRate uses Postgres extensions. You may also need to manually build the sequential UUIDs extension
Setup secrets
A foreword: you may ask about other storage options for secrets.
Well, relying on local storage and age is the simplest way for now, but luckily
thanks to sops' versatility, we'll successively work on adding support for more ways of handling them.
Please don't hesitate to open an issue if you feel the need for support for a particular secrets storage option supported by SOPS (see their README linked in dependencies list) to be added first.
In a production environment, you're strongly advised to create a separate user for LibRate
and use that to handle the config, run the binary and store the
age keys.
All you need to do is generate an age X25519 identity
and then encrypt the config file
with SOPS. Don't forget to pass the -c
flag if you decide to save the encrypted file under a new path.
IMPORTANT: Updating the app and instance administration
Release notes for each update should mention when the database requires
migrations for the new release to work properly, including the migration's name.
LibRate provides an utility for administration an instance, called lrctl. If you use docker, this utility is bundled into the image. To run a migration, execute:
/app/bin/lrctl -c /app/data/config.yml db migrate <migration directory's base
path>
Development prerequisites
To develop the recommendations feature, you'll need:
protoc
and protoc-gen-go
for generating code from the protocol buffers files.
- Rust and Go toolchains
Building and installing
If you have installed just, you can simply run:
just first_run
Alternatively, edit the example config file and run:
go mod tidy && \
cd fe && pnpm install \
&& pnpm run build && \
go run . -init -exit && \
go run . migrate -auto-migrate
For subsequent runs of course you shouldn't use the init
flag.
You can then test your instance at http://127.0.0.1:3000 (or the other port you've specified)
Testing
In order to test the database code, you should create a librate_test
database.
If you set the $CLEANUP_TEST_DB
variable to 0, the test database will not be cleaned up by the deferred function in the database initialization unit test.