Skip to content

Labrinth (API)

This project is part of our monorepo. You can find it in the apps/labrinth directory.

labrinth is the Rust-based backend serving Modrinth’s API with the help of the Actix framework. To get started with a labrinth instance, install docker, docker-compose (which comes with Docker), and Rust. The initial startup can be done simply with the command docker-compose up, or with docker compose up (Compose V2 and later). That will deploy a PostgreSQL database on port 5432 and a MeiliSearch instance on port 7700. To run the API itself, you’ll need to use the cargo run command, this will deploy the API on port 8000.

Now, you’ll have to install the sqlx CLI, which can be done with cargo:

Terminal window
cargo install --git https://github.com/launchbadge/sqlx sqlx-cli --no-default-features --features postgres,rustls

From there, you can create the database and perform all database migrations with one simple command:

Terminal window
sqlx database setup

Finally, if on Linux, you will need the OpenSSL library. On Debian-based systems, this involves the pkg-config and libssl-dev packages.

To enable labrinth to create a project, you need to add two things.

  1. An entry in the loaders table.
  2. An entry in the loaders_project_types table.

A minimal setup can be done from the command line with psql:

Terminal window
psql --host=localhost --port=5432 -U <username, default is labrinth> -W

The default password for the database is labrinth. Once you’ve connected, run

INSERT INTO loaders VALUES (0, 'placeholder_loader');
INSERT INTO loaders_project_types VALUES (0, 1); -- modloader id, supported type id
INSERT INTO categories VALUES (0, 'placeholder_category', 1); -- category id, category, project type id

This will initialize your database with a modloader called ‘placeholder_loader’, with id 0, and marked as supporting mods only. It will also create a category called ‘placeholder_category’ that is marked as supporting mods only If you would like ‘placeholder_loader’ to be marked as supporting modpacks too, run

INSERT INTO loaders_project_types VALUES (0, 2); -- modloader id, supported type id

If you would like ‘placeholder_category’ to be marked as supporting modpacks too, run

INSERT INTO categories VALUES (0, 'placeholder_category', 2); -- modloader id, supported type id

The majority of configuration is done at runtime using dotenvy and the .env file. Each of the variables and what they do can be found in the dropdown below. Additionally, there are three command line options that can be used to specify to MeiliSearch what you want to do.

.env variables & command line options

Basic configuration

DEBUG: Whether debugging tools should be enabled
RUST_LOG: Specifies what information to log, from rust’s env-logger; a reasonable default is info,sqlx::query=warn
SITE_URL: The main URL to be used for CORS
CDN_URL: The publicly accessible base URL for files uploaded to the CDN
MODERATION_DISCORD_WEBHOOK: The URL for a Discord webhook where projects pending approval will be sent
CLOUDFLARE_INTEGRATION: Whether labrinth should integrate with Cloudflare’s spam protection
DATABASE_URL: The URL for the PostgreSQL database
DATABASE_MIN_CONNECTIONS: The minimum number of concurrent connections allowed to the database at the same time
DATABASE_MAX_CONNECTIONS: The maximum number of concurrent connections allowed to the database at the same time
MEILISEARCH_ADDR: The URL for the MeiliSearch instance used for search
MEILISEARCH_KEY: The name that MeiliSearch is given
BIND_ADDR: The bind address for the server. Supports both IPv4 and IPv6
MOCK_FILE_PATH: The path used to store uploaded files; this has no default value and will panic if unspecified

CDN options

STORAGE_BACKEND: Controls what storage backend is used. This can be either local, backblaze, or s3, but defaults to local

The Backblaze and S3 configuration options are fairly self-explanatory in name, so here’s simply their names:
BACKBLAZE_KEY_ID, BACKBLAZE_KEY, BACKBLAZE_BUCKET_ID
S3_ACCESS_TOKEN, S3_SECRET, S3_URL, S3_REGION, S3_BUCKET_NAME

Search, OAuth, and miscellaneous options

LOCAL_INDEX_INTERVAL: The interval, in seconds, at which the local database is reindexed for searching. Defaults to 3600 seconds (1 hour).
VERSION_INDEX_INTERVAL: The interval, in seconds, at which versions are reindexed for searching. Defaults to 1800 seconds (30 minutes).

The OAuth configuration options are fairly self-explanatory. For help setting up authentication, please contact us on Discord.

RATE_LIMIT_IGNORE_IPS: An array of IPs that should have a lower rate limit factor. This can be useful for allowing the front-end to have a lower rate limit to prevent accidental timeouts.

Command line options

--skip-first-index: Skips indexing the local database on startup. This is useful to prevent doing unnecessary work when frequently restarting.
--reconfigure-indices: Resets the MeiliSearch settings for the search indices and exits.
--reset-indices: Resets the MeiliSearch indices and exits; this clears all previously indexed mods.

Ready to open a PR?

If you’re prepared to contribute by submitting a pull request, ensure you have met the following criteria:

  • cargo fmt has been run.
  • cargo clippy has been run.
  • cargo check has been run.
  • cargo sqlx prepare has been run.

Note: If you encounter issues with sqlx saying ‘no queries found’ after running cargo sqlx prepare, you may need to ensure the installed version of sqlx-cli matches the current version of sqlx used in labrinth.