Documentation Index Fetch the complete documentation index at: https://mintlify.com/modrinth/code/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide covers setting up the complete Modrinth development environment, including the backend API (Labrinth) and all required services.
Prerequisites
Before you begin, ensure you have:
Services Overview
Modrinth uses several backend services:
Service Purpose Port PostgreSQL Primary database 5432 Redis Cache and sessions 6379 ClickHouse Analytics database 8123 Meilisearch Search engine 7700 Mailpit Email testing 8025 (UI), 1025 (SMTP) Gotenberg PDF generation 13000 Labrinth API server 8000
All services are defined in docker-compose.yml at the root of the repository.
Quick Start
Clone Repository
git clone https://github.com/modrinth/code.git
cd code
Start Services
This starts PostgreSQL, Redis, ClickHouse, Meilisearch, Mailpit, and Gotenberg.
Verify Services
Check that all services are healthy: All services should show status “healthy”.
Service Details
PostgreSQL
Image : postgres:15-alpine
Port : 5432
Database : labrinth
User : labrinth
Password : labrinth
Accessing PostgreSQL
# Via docker exec
docker exec labrinth-postgres psql -U labrinth -d labrinth
# Run a query
docker exec labrinth-postgres psql -U labrinth -d labrinth -c "SELECT COUNT(*) FROM projects;"
# Using local psql client
psql postgresql://labrinth:labrinth@localhost:5432/labrinth
Database Structure
Labrinth uses SQLx migrations located in apps/labrinth/migrations/.
# Run migrations (from apps/labrinth)
cd apps/labrinth
cargo sqlx migrate run
# Create new migration
cargo sqlx migrate add create_my_table
Redis
Image : redis:alpine
Port : 6379
Accessing Redis
# Connect to Redis CLI
docker exec -it labrinth-redis redis-cli
# Example commands
> KEYS *
> GET session:abc123
> HGETALL user:456
Usage in Labrinth
Session storage
Rate limiting counters
Temporary caches
Background job queues
ClickHouse
Image : clickhouse/clickhouse-server
Port : 8123 (HTTP)
Database : staging_ariadne
User : default
Password : default
Accessing ClickHouse
# Connect to ClickHouse client
docker exec -it labrinth-clickhouse clickhouse-client
# Use staging database
USE staging_ariadne ;
# Query analytics
SELECT COUNT ( * ) FROM downloads ;
Creating Tables
CREATE TABLE IF NOT EXISTS staging_ariadne . downloads (
version_id String,
timestamp DateTime ,
ip String,
user_agent String
) ENGINE = MergeTree()
ORDER BY timestamp ;
Meilisearch
Image : getmeili/meilisearch:v1.12.0
Port : 7700
Master Key : modrinth
Accessing Meilisearch
Web UI : http://localhost:7700
API Key : modrinth
# Check health
curl http://localhost:7700/health
# List indexes
curl http://localhost:7700/indexes \
-H "Authorization: Bearer modrinth"
Indexing Projects
Labrinth automatically indexes projects to Meilisearch on creation/update.
# Manually trigger reindex (from Labrinth API)
curl -X POST http://localhost:8000/_internal/search/reindex \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Mailpit (Email Testing)
Image : axllent/mailpit:v1.27
SMTP Port : 1025
Web UI Port : 8025
Viewing Emails
Open http://localhost:8025 to view all emails sent by Labrinth during development.
Use cases :
Email verification
Password reset emails
Notification emails
Gotenberg (PDF Generation)
Image : gotenberg/gotenberg:8
Port : 13000
Used for generating PDF reports and invoices.
# Test PDF generation
curl --request POST \
--url http://localhost:13000/forms/chromium/convert/url \
--form url=https://modrinth.com \
--output test.pdf
Running Labrinth (Backend API)
Setup
Copy Environment File
cp .env.docker-compose .env
This file contains pre-configured settings for local development.
Run Migrations
This creates all necessary database tables.
Start Labrinth
Or for faster compilation (debug mode):
Labrinth will be available at http://localhost:8000
Verify API is Running
# Check health endpoint
curl http://localhost:8000/health
# Browse API docs
open http://localhost:8000/docs
Environment Variables
Key variables in .env.docker-compose:
# Database
DATABASE_URL = postgres://labrinth:labrinth@localhost/labrinth
# Redis
REDIS_URL = redis://localhost:6379
# ClickHouse
ANALYTICS_URL = http://localhost:8123
ANALYTICS_DATABASE = staging_ariadne
# Meilisearch
MEILISEARCH_ADDR = http://localhost:7700
MEILISEARCH_KEY = modrinth
# S3 (local development - optional)
# S3_URL=http://localhost:9000 # If using MinIO
# S3_BUCKET_NAME=modrinth
# Email (Mailpit)
SMTP_HOST = localhost
SMTP_PORT = 1025
# Auth (for OAuth - use test credentials)
GITHUB_CLIENT_ID = your_test_client_id
GITHUB_CLIENT_SECRET = your_test_secret
# Internal API key (for admin endpoints)
ADMIN_KEY = feedbeef
Running Frontend Applications
Web Interface
# From root directory
cd apps/frontend
cp .env.local .env
# Edit .env if needed to point to local Labrinth
# NUXT_PUBLIC_LABRINTH_URL=http://localhost:8000
cd ../..
pnpm web:dev
Access at http://localhost:3000
Desktop App
# From root directory
cd packages/app-lib
cp .env.local .env
cd ../..
pnpm app:dev
The Tauri app window will open automatically.
Database Management
Resetting the Database
To start fresh:
# Stop services
docker compose down -v
# Remove all data
rm -rf docker-volumes/ # If you have local volumes
# Start services
docker compose up -d
# Run migrations
cd apps/labrinth
cargo sqlx migrate run
Seeding Test Data
Create test data for development:
-- Connect to PostgreSQL
docker exec - it labrinth - postgres psql - U labrinth - d labrinth
-- Create test user
INSERT INTO users (id, username, email, created)
VALUES ( 'local_1' , 'testuser' , 'test@example.com' , NOW ());
-- Create test project
INSERT INTO projects (id, slug, title, description , published)
VALUES ( 'local_proj_1' , 'test-mod' , 'Test Mod' , 'A test mod' , NOW ());
Or use the Labrinth API to create projects:
# Authenticate (requires GitHub OAuth setup)
curl -X POST http://localhost:8000/v3/project \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"title": "Test Mod",
"slug": "test-mod",
"description": "A test mod",
"project_type": "mod",
"categories": ["technology"],
"license_id": "MIT"
}'
Backup and Restore
Backup :
docker exec labrinth-postgres pg_dump -U labrinth labrinth > backup.sql
Restore :
cat backup.sql | docker exec -i labrinth-postgres psql -U labrinth -d labrinth
Optional Services
Delphi (Malware Scanner)
Delphi scans uploaded files for malware. It’s optional for local development.
# Start with Delphi profile
docker compose --profile with-delphi up -d
Port : 59999
Sharded Meilisearch
For testing search with multiple Meilisearch instances:
docker compose --profile sharded-meilisearch up -d
This starts:
meilisearch0 on 7700
meilisearch1 on 7701
Nginx load balancer on 7710
Running Labrinth in Docker
To run Labrinth itself in Docker:
docker compose --profile with-labrinth up -d
This builds and runs Labrinth in a container instead of running it locally with cargo run.
Troubleshooting
Services Won’t Start
# Check service logs
docker compose logs postgres_db
docker compose logs redis
docker compose logs clickhouse
# Check all logs
docker compose logs -f
Port Already in Use
If a port is already in use, edit docker-compose.yml to change the port mapping:
ports :
- '127.0.0.1:5433:5432' # Use 5433 instead of 5432
Then update DATABASE_URL in .env:
DATABASE_URL=postgres://labrinth:labrinth@localhost:5433/labrinth
Database Connection Errors
# Verify PostgreSQL is running and healthy
docker compose ps postgres_db
# Check connection
psql postgresql://labrinth:labrinth@localhost:5432/labrinth -c "SELECT 1;"
Meilisearch Index Issues
If search isn’t working:
# Check Meilisearch health
curl http://localhost:7700/health
# List indexes
curl http://localhost:7700/indexes -H "Authorization: Bearer modrinth"
# Trigger reindex from Labrinth
curl -X POST http://localhost:8000/_internal/search/reindex \
-H "Authorization: Bearer feedbeef"
Slow Compilation (Rust)
Speed up Rust compilation:
# Install sccache (compilation cache)
cargo install sccache
# Add to ~/.cargo/config.toml
[build]
rustc-wrapper = "sccache"
# Or use mold linker (Linux)
sudo apt install mold
export RUSTFLAGS = "-C link-arg=-fuse-ld=mold"
Out of Disk Space
Docker can consume a lot of disk space:
# Clean up unused containers and images
docker system prune -a
# Remove volumes
docker volume prune
Development Workflow
Typical Development Session
# 1. Start services
docker compose up -d
# 2. Start Labrinth (in one terminal)
cd apps/labrinth
cargo run
# 3. Start frontend (in another terminal)
pnpm web:dev
# 4. Make changes and test
# 5. When done, stop services
docker compose down
Hot Reloading
Frontend : Vite provides instant HMR
Backend : Rust requires manual restart after code changes
Tip : Use cargo-watch for auto-restart:
cargo install cargo-watch
# Auto-restart on file changes
cargo watch -x 'run -p labrinth'
Viewing Logs
# Docker service logs
docker compose logs -f postgres_db
docker compose logs -f meilisearch0
# Labrinth logs (if running with cargo)
# Already visible in terminal
# Frontend logs
# Already visible in terminal running pnpm web:dev
PostgreSQL Tuning
For local development, you can increase performance by adjusting PostgreSQL settings:
# Edit docker-compose.yml to add environment variables:
environment:
- POSTGRES_SHARED_BUFFERS=256MB
- POSTGRES_WORK_MEM=16MB
- POSTGRES_MAINTENANCE_WORK_MEM=64MB
Redis Memory Limit
redis :
command : redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
ClickHouse Memory
clickhouse :
environment :
- CLICKHOUSE_MAX_MEMORY_USAGE=4000000000 # 4GB
Next Steps
Backend (Labrinth) Learn about the Rust backend architecture
Frontend (Web) Develop the Nuxt 3 web interface
Testing Run tests and ensure quality
Deployment Learn about the production deployment