Skip to content

Labrinth (API)

This project is part of our monorepo. You can find it in the apps/labrinth directory. The instructions below assume that you have switched your working directory to the apps/labrinth subdirectory.

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, a MeiliSearch instance on port 7700, and a Mailpit SMTP server on port 1025, with a web UI to inspect sent emails on port 8025. To run the API itself, you’ll need to use the cargo run command, this will deploy the API on port 8000.

To get a basic configuration, copy the .env.local file to .env. Now, you’ll have to install the sqlx CLI, which can be done with cargo:

Terminal window
cargo install sqlx-cli --no-default-features --features mysql,sqlite,postgres,rustls,completions

From there, you can create the database and set up its schema with one simple command:

Terminal window
cargo sqlx database setup

To enable labrinth to create projects and serve useful metadata to the frontend build scripts, you’ll need to seed the database with several key entities:

  1. Categories, in the categories table.
  2. Loaders and their fields, in the loaders, loader_fields, loader_field_enums, loader_field_enum_values, and loader_fields_loaders tables.
  3. Project types and their allowed loaders and games, in the project_types, loaders_project_types, and loaders_project_types_games tables.
  4. Optionally, to moderate projects from the frontend, an admin user, in the users table.

The most convenient way to do this seeding is with the psql command line tool and the pre-existing seed data fixture. This fixture was generated by dumping the official staging environment database at a specific point in time, and defines an admin user with email admin@modrinth.invalid and password admin:

Terminal window
source .env
psql "$DATABASE_URL" < fixtures/labrinth-seed-data-202508052143.sql

You can find more example SQL statements for seeding the database in the tests/files/dummy_data.sql file.

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.

During development, you might notice that changes made directly to entities in the PostgreSQL database do not seem to take effect. This is often because the Redis cache still holds outdated data. To ensure your updates are reflected, clear the cache by e.g. running redis-cli FLUSHALL, which will force labrinth to fetch the latest data from the database the next time it is needed.

You can also start labrinth and its backing services at once using docker compose --profile with-labrinth up, which will build and start labrinth through its Docker image as if it was yet another service container. To have that container be automatically rebuilt during development as changes to the source code are made, add the --watch flag, which enables Compose Watch. Keep in mind, however, that Compose Watch is bound to be slower than other similar solutions that work outside of a container, particularly on Windows or macOS, where Docker runs in a virtual machine.

.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, including its username, password, host, port, and database name 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 SMTP_USERNAME: The username used to authenticate with the SMTP server SMTP_PASSWORD: The password associated with the SMTP_USERNAME for SMTP authentication SMTP_HOST: The hostname or IP address of the SMTP server SMTP_PORT: The port number on which the SMTP server is listening (commonly 25, 465, or 587) SMTP_TLS: The TLS mode to use for the SMTP connection, which can be one of the following: none, opportunistic_start_tls, requires_start_tls, tls

CDN options

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

The S3 configuration options are fairly self-explanatory in name, so here’s simply their names: S3_ACCESS_TOKEN, S3_SECRET, S3_URL, S3_REGION, S3_PUBLIC_BUCKET_NAME, S3_PRIVATE_BUCKET_NAME, S3_USES_PATH_STYLE_BUCKETS

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 --all has been run.
  • cargo clippy --all-targets 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.