Quick start#

The fastest way to a running instance is the Docker image. You need a PostgreSQL database and, at minimum, a Brave Search API key.

With Docker#

docker run -p 8000:8000 \
  -e SECRET_KEY=your-long-random-secret \
  -e DATABASE_URL=postgres://user:password@db-host:5432/searpa \
  -e ALLOWED_HOSTS=search.example.com \
  -e BRAVE_API_KEY=your-brave-key \
  -e BRAVE_SUGGEST_API_KEY=your-brave-suggest-key \
  -e MARGINALIA_API_KEY=public \
  searpa

On start the container:

  1. Applies database migrations (a no-op once the schema is current).
  2. Serves the app with gunicorn (2 workers) on port 8000.
  3. Serves its own static files via WhiteNoise (compressed and hashed), no separate web server or CDN required.
  4. Answers a health check at /up.

The translation catalogs and static files are compiled at build time, so there is nothing else to run.

Point a reverse proxy with TLS (Caddy, nginx, Traefik, …) at port 8000 and set ALLOWED_HOSTS to your domain. See Production notes.

Create your first user#

The app has no public registration, so create an account before you can sign in:

docker exec -it <container> python manage.py createsuperuser

See Users & access for more.

With Docker Compose#

A minimal compose.yaml with the database alongside the app:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: searpa
      POSTGRES_USER: searpa
      POSTGRES_PASSWORD: change-me
    volumes:
      - pgdata:/var/lib/postgresql/data

  app:
    image: searpa
    depends_on: [db]
    ports:
      - "8000:8000"
    environment:
      SECRET_KEY: your-long-random-secret
      DATABASE_URL: postgres://searpa:change-me@db:5432/searpa
      ALLOWED_HOSTS: search.example.com
      BRAVE_API_KEY: your-brave-key
      BRAVE_SUGGEST_API_KEY: your-brave-suggest-key
      MARGINALIA_API_KEY: public

volumes:
  pgdata:
docker compose up -d
docker compose exec app python manage.py createsuperuser

See Configuration for the full list of environment variables, and Search providers for the keys that enable each tab and card.

From source#

To build the image yourself or develop locally, clone the Searpa repository and use the bundled workflow:

cp .env.example .env        # then add at least BRAVE_API_KEY
make setup                  # install deps, start dev services, migrate, compile i18n
make run                    # dev server at http://localhost:8000
make superuser              # create an account

make setup starts a dev stack (PostgreSQL + a mail catcher + LibreTranslate) via Podman Compose, so you get a working Translate tab out of the box. Run make with no arguments to list every target. Build a production image with:

docker build -t searpa .

Always set a long, random SECRET_KEY and a real DATABASE_URL in production, and set DEBUG=False (the default when unset). The value in .env.example is for local development only.