# Development Environment A Docker Compose environment for testing Jellyswarrm against two independent Jellyfin servers for each library type: Movies, TV Shows, and Music. All six servers use read-only trees of compact, freely licensed test media while keeping their configuration, users, item databases, and caches isolated. A Seerr instance is included for developing the Jellyfin API compatibility needed by [issue #95](https://github.com/LLukas22/Jellyswarrm/issues/95). ## Quick start From the repository root: ```bash just setup ``` This command verifies Docker, fetches the Git LFS media, starts all six servers and Seerr, initializes the Jellyfin users and libraries, and waits for the complete stack to be ready. Media and application state are reused on later runs. Debug builds of `jellyswarrm-proxy` load `data/jellyswarrm.dev.toml` and automatically add or update these six servers in Jellyswarrm. Existing non-development servers are left untouched. They also create the local Jellyswarrm user `test` / `test` and map all six upstream servers to that user with the same credentials. Requirements: - Docker with the Compose v2 plugin - Git LFS - [just](https://just.systems/) The exact Jellyfin and Seerr releases are set through `JELLYFIN_VERSION` and `SEERR_VERSION` in [`dev/.env`](.env). Update either value and run `just pull && just up` to test another release. ## Servers | Server | Direct URL | | --- | --- | | Movies 1 | | | Shows 1 | | | Music 1 | | | Movies 2 | | | Shows 2 | | | Music 2 | | | Seerr | | Every server has the regular Jellyswarrm account `test` / `test`, with access to its complete library. The administrator account remains `admin` / `password`. Caddy is available at and exposes `/movies/`, `/shows/`, `/music/`, `/movies-2/`, `/shows-2/`, and `/music-2/`. ## Seerr Run `jellyswarrm-proxy` on the host, then open and select Jellyfin in the setup wizard. Use these media-server settings: | Setting | Value | | --- | --- | | Hostname or IP | `host.docker.internal` | | Port | `3000` | | Use SSL | Disabled | | URL base | Empty | | Username | `test` | | Password | `test` | `host.docker.internal` is mapped to Docker's host gateway by Compose. The proxy already listens on `0.0.0.0:3000` by default, so no host networking is needed. Seerr configuration and its SQLite database persist in the `seerr-config` named volume. Jellyswarrm reports the setup-only administrator capability that Seerr requires, but continues to enforce the virtual user's normal upstream permissions. No backend administrator account is needed, and other clients continue to see the virtual account as non-administrative. Seerr stores a dedicated read-only Jellyswarrm API key and discovers the merged Movies and Shows libraries through their virtual IDs. See [`SEERR-COMPATIBILITY.md`](SEERR-COMPATIBILITY.md) for the supported API surface. ## Commands Run `just` to list all commands. Common workflows are: ```bash just up # Start and wait for the complete stack just down # Remove containers but preserve media and server state just status # Show all containers, including one-shot initializers just logs # Follow logs from the complete stack just media # Fetch media fixtures from Git LFS just check # Validate Compose and the initializer just reset # Recreate Jellyfin state; preserve media and Seerr state ``` Use `just log jellyfin-movies-2` to follow one service. ## Integration tests Run the Docker-backed end-to-end test with: ```bash just integration-test ``` The Rust test uses Testcontainers' Docker Compose support with `docker-compose.yml` and `docker-compose.integration.yml`. It creates a unique Compose project with fresh Jellyfin configuration volumes and random host ports, so it can run while the regular development stack is active. The test starts the compiled Jellyswarrm server against those six instances and checks failed and successful login, automatic user mappings, merged virtual libraries, duplicate source labeling, playback info, and ranged media streaming from both movie servers. The test is ignored by normal `cargo test` runs because initializing all six media servers is intentionally heavyweight. ## Media layout Fixtures are stored under `dev/media/` through Git LFS: ```text dev/media/ |-- movies/ | |-- server-1/ | `-- server-2/ |-- tv-shows/ | |-- server-1/ | `-- server-2/ `-- music/ |-- server-1/ `-- server-2/ ``` Each directory is mounted only into its matching Jellyfin server: | Server | Fixtures | | --- | --- | | Movies 1 | Night of the Living Dead (exclusive), Big Buck Bunny (shared) | | Movies 2 | Plan 9 from Outer Space and Sintel (exclusive), Big Buck Bunny (shared) | | Shows 1 | The Cisco Kid (exclusive); One Step Beyond S01E02 (shared) and S02E21 (exclusive) | | Shows 2 | One Step Beyond S01E02 (shared) and S03E34 (exclusive) | | Music 1 | The Open Goldberg Variations | | Music 2 | Ghost Solos | The One Step Beyond layout provides one season and episode shared by both Shows servers, plus a different server-specific season on each. Shared files have identical LFS object IDs, so GitHub stores each shared binary once. This gives merged-library tests both overlapping and exclusive upstream items. Videos are two-minute excerpts of the real public-domain and Creative Commons works, compacted to a maximum width of 640px. The freely licensed music tracks remain complete. The whole fixture set is approximately 52 MiB. See [`MEDIA-LICENSES.md`](MEDIA-LICENSES.md) for exact sources, licenses, and required attribution. Jellyfin state is stored in `dev/data/jellyfin-*`. Seerr state is stored in the Compose-managed `seerr-config` volume. `just down` preserves both; `just reset` removes only the Jellyfin state and runs initialization again. Tracked media and Seerr state are preserved by both commands.