# Lumina

Lumina is a self-hosted photo and video library for organizing, browsing, and sharing your personal media collection. It keeps original files on storage you control while providing a fast, responsive web interface for everyday use.

## Features

- Automatic photo and video indexing
- Timeline, album, and folder views
- Full-text search by filename, date, camera, and location
- EXIF metadata and map display
- Duplicate detection using file hashes
- Background thumbnail and preview generation
- Private and password-protected shared albums
- Multiple user accounts with configurable permissions
- Favorites, tags, ratings, and captions
- Dark mode and mobile-friendly interface
- Read-only import directories
- Local filesystem and S3-compatible storage support
- Docker-based deployment
- REST API for integrations and automation

## Installation

### Requirements

- Docker Engine 24 or newer
- Docker Compose v2
- At least 2 GB of RAM
- A persistent directory for application data
- A directory containing your photos and videos

### Docker Compose

Create a `compose.yaml` file:

```yaml
services:
  lumina:
    image: ghcr.io/example/lumina:latest
    container_name: lumina
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      LUMINA_DATABASE_URL: postgres://lumina:change-me@database:5432/lumina
      LUMINA_SECRET_KEY: replace-with-a-long-random-value
      LUMINA_MEDIA_PATH: /media
    volumes:
      - ./data:/var/lib/lumina
      - /path/to/photos:/media:ro
    depends_on:
      database:
        condition: service_healthy

  database:
    image: postgres:16-alpine
    container_name: lumina-database
    restart: unless-stopped
    environment:
      POSTGRES_DB: lumina
      POSTGRES_USER: lumina
      POSTGRES_PASSWORD: change-me
    volumes:
      - ./postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U lumina"]
      interval: 10s
      timeout: 5s
      retries: 5
```

Replace `/path/to/photos`, the database password, and `LUMINA_SECRET_KEY` before starting the service.

```sh
docker compose up -d
```

Open `http://localhost:8080` and follow the setup wizard to create the first administrator account.

To view service logs:

```sh
docker compose logs -f lumina
```

To upgrade:

```sh
docker compose pull
docker compose up -d
```

Back up both the `data` and `postgres` directories before upgrading.

## Usage

### Importing media

Files mounted at `LUMINA_MEDIA_PATH` are indexed without being modified. Add new files to the mounted directory, then start a scan from **Library → Scan**.

You can also trigger a scan from the command line:

```sh
docker compose exec lumina lumina scan
```

For large libraries, the initial scan and preview generation may take several hours. Progress is available under **Administration → Jobs**.

### Creating albums

1. Select one or more items in the library.
2. Choose **Add to album**.
3. Select an existing album or create a new one.
4. Add a title, description, and optional cover image.

Albums reference library items and do not duplicate the original files.

### Sharing

Open an album and select **Share** to create a public link. Shares can include:

- An expiration date
- Password protection
- Download permissions
- Original-file access
- A custom title and description

Public sharing is disabled by default. Enable it in the administration settings or with `LUMINA_SHARING_ENABLED=true`.

### Managing users

Administrators can create users from **Administration → Users**. Available roles are:

- **Administrator:** Full access to settings, users, jobs, and all libraries
- **Member:** Access to assigned libraries and personal albums
- **Viewer:** Read-only access to assigned libraries and albums

## Configuration

Lumina is configured through environment variables. Restart the application after changing them.

| Variable | Default | Description |
| --- | --- | --- |
| `LUMINA_DATABASE_URL` | — | PostgreSQL connection URL |
| `LUMINA_SECRET_KEY` | — | Secret used to sign sessions and tokens |
| `LUMINA_MEDIA_PATH` | `/media` | Root directory scanned for media |
| `LUMINA_DATA_PATH` | `/var/lib/lumina` | Thumbnails, previews, and application data |
| `LUMINA_BIND` | `0.0.0.0:8080` | HTTP bind address and port |
| `LUMINA_PUBLIC_URL` | `http://localhost:8080` | External URL used in links and redirects |
| `LUMINA_TIMEZONE` | `UTC` | Time zone used for dates and scheduled jobs |
| `LUMINA_LOG_LEVEL` | `info` | Logging level: `debug`, `info`, `warn`, or `error` |
| `LUMINA_SCAN_SCHEDULE` | `0 2 * * *` | Cron schedule for automatic library scans |
| `LUMINA_WORKERS` | `2` | Number of background processing workers |
| `LUMINA_SHARING_ENABLED` | `false` | Enables public album links |
| `LUMINA_MAX_UPLOAD_SIZE` | `10G` | Maximum size of an uploaded file |
| `LUMINA_TRUST_PROXY` | `false` | Trusts forwarded headers from a reverse proxy |
| `LUMINA_READ_ONLY` | `false` | Disables uploads and metadata changes |

Generate a suitable secret key with:

```sh
openssl rand -hex 32
```

### Reverse proxy

When serving Lumina behind a reverse proxy:

1. Set `LUMINA_PUBLIC_URL` to the public HTTPS URL.
2. Set `LUMINA_TRUST_PROXY=true`.
3. Forward the `Host`, `X-Forwarded-For`, and `X-Forwarded-Proto` headers.
4. Configure the proxy to allow large uploads and long-running requests.

Example environment values:

```yaml
environment:
  LUMINA_PUBLIC_URL: https://photos.example.com
  LUMINA_TRUST_PROXY: "true"
  LUMINA_MAX_UPLOAD_SIZE: 20G
```

### S3-compatible storage

To store generated previews and uploaded originals in S3-compatible object storage, set:

```yaml
environment:
  LUMINA_STORAGE_DRIVER: s3
  LUMINA_S3_ENDPOINT: https://s3.example.com
  LUMINA_S3_REGION: us-east-1
  LUMINA_S3_BUCKET: lumina
  LUMINA_S3_ACCESS_KEY: access-key
  LUMINA_S3_SECRET_KEY: secret-key
```

Do not commit credentials to version control. Use Docker secrets or your deployment platform's secret manager in production.

## Backup and Recovery

A complete backup includes:

- The PostgreSQL database
- The Lumina data directory
- Original media, if Lumina manages uploaded files

Create a database backup with:

```sh
docker compose exec -T database pg_dump -U lumina lumina > lumina.sql
```

The thumbnail cache can be regenerated, but preserving it significantly reduces recovery time.

Test backups regularly by restoring them into a separate environment.