Self-host aiometadata
v3.8.3Stremio metadata addon aggregating multiple sources
$ docker compose up -d- Stars
- 544
- Port
- 3232 (HTTP server)
- Requires
- Redis
ghcr.io/cedya77/aiometadataWhat is aiometadata?
AIOMetadata is a metadata addon for the Stremio media center that pulls movie, series, and anime information from multiple providers. Users choose their preferred source for each content type through a React-based configuration interface. The addon supports custom catalogs, streaming catalogs from services like Netflix and Disney+, and AI-powered search via Gemini. It runs in Docker with Redis for caching and SQLite or PostgreSQL for storing per-user configurations. Optional features include OpenID Connect authentication, a Jellyfin server mode that exposes catalogs as Jellyfin libraries, a built-in image cache, and integrations with self-hosted Jikan and LumiereDB instances for anime and IMDb data respectively. The project is licensed under GPL-3.0.
Should you self-host aiometadata?
aiometadata scores 54/100 on selfhost.directory (how scoring works) and ranks #47 of 118 in Media Server. It has 544 GitHub stars.
It shipped 16 stable releases in the past year. The latest, v3.8.3, came out on 28 October 2026.
Setup is moderate: expect some configuration beyond a single command. An official Docker image is available. It is GPL-3.0-licensed and written mostly in Typescript.
Its closest alternative on selfhost.directory is Jellyfin (88/100, 58 727 stars). It scores higher overall, so compare the two before you pick. See aiometadata vs Jellyfin side by side.
Features
- Advanced ID Mapping
- Anime metadata support
- Built-in image cache
- Custom Catalogs
- Dynamic search with AI
- Jellyfin server mode
- LumiereDB integration
- Multi-source metadata aggregation
- OpenID Connect Authentication
- Per-user configuration
- React configuration UI
- Rich artwork with fallback
- Self-hosted Jikan API support
- Streaming Catalogs
aiometadata README
How to install aiometadata
Install aiometadata with Docker Compose
services:
aiometadata:
image: ghcr.io/cedya77/aiometadata:latest
container_name: aiometadata
restart: unless-stopped
ports:
- "3232:3232" # Remove this if using Traefik
# expose: # Uncomment if using Traefik
# - 3232
init: true
env_file:
- .env
# labels: # Optional: Remove if not using Traefik
# - "traefik.enable=true"
# - "traefik.http.routers.aiometadata.rule=Host(${AIOMETADATA_HOSTNAME?})"
# - "traefik.http.routers.aiometadata.entrypoints=websecure"
# - "traefik.http.routers.aiometadata.tls.certresolver=letsencrypt"
# - "traefik.http.routers.aiometadata.middlewares=authelia@docker"
# - "traefik.http.services.aiometadata.loadbalancer.server.port=3232"
# - "traefik.http.routers.aiometadata.service=aiometadata"
volumes:
- ${DOCKER_DATA_DIR}/aiometadata/data:/app/addon/data
depends_on:
aiometadata_redis:
condition: service_healthy
tty: true
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3232/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
aiometadata_redis: image: redis:latest container_name: aiometadata_redis restart: unless-stopped volumes: - ${DOCKER_DATA_DIR}/aiometadata/cache:/data command: redis-server --appendonly yes --save 3600 1 healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5
#aiometadata_postgres:
image: postgres:latest
container_name: aiometadata_postgres
restart: unless-stopped
environment:
- POSTGRES_DB=aiometadata
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- ${DOCKER_DATA_DIR}/aiometadata/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d aiometadata"]
interval: 10s
timeout: 5s
retries: 5
Create a .env file with your API keys and settings as shown in .env.example
Then run:
docker compose up -d
Requires Redis. PostgreSQL optional. Uses .env file for configuration.
How to configure aiometadata
ADDON_LOGO_URLOptional: Override the logo URL in the manifestOptional: Override the logo URL in the manifest
ADDON_NAME_SUFFIX-- UI & Customization -- An optional suffix to add to the addon's name in the manifest (e.g., "| My Server").-- UI & Customization -- An optional suffix to add to the addon's name in the manifest (e.g., "| My Server").
ADDON_PASSWORDPassword for protected endpoints (if enabled in your deployment)Password for protected endpoints (if enabled in your deployment)
ADMIN_KEY-- Security & Admin -- An optional key to protect administrative dashboard endpoints.-- Security & Admin -- An optional key to protect administrative dashboard endpoints.
ANILIST_CLIENT_IDAniList API credentials (required for AniList integration) Get these from https://anilist.co/settings/developer Your AniList client IDAniList API credentials (required for AniList integration) Get these from https://anilist.co/settings/developer Your AniList client ID
ANILIST_CLIENT_SECRETYour AniList client secretYour AniList client secret
ANILIST_REDIRECT_URIThe redirect URI for AniList OAuth (must match your AniList app settings) Example: https://your-domain.com/anilist/callbackThe redirect URI for AniList OAuth (must match your AniList app settings) Example: https://your-domain.com/anilist/callback
BUILT_IN_FANART_API_KEYBUILT_IN_GEMINI_API_KEYBUILT_IN_MDBLIST_API_KEYThese two exist for the same reason but cost money per call, and every user of the instance spends them. MDBList bills past 1000 calls a day and Gemini bills per query, so set them on a private instance only. On a public one leave them blank: users who want MDBList catalogs or AI search bring their own key.These two exist for the same reason but cost money per call, and every user of the instance spends them. MDBList bills past 1000 calls a day and Gemini bills per query, so set them on a private instance only. On a public one leave them blank: users who want MDBList catalogs or AI search bring their own key.
BUILT_IN_RPDB_API_KEYBUILT_IN_TMDB_API_KEY-- API Keys: server-side (start here) -- These cover any user who has not supplied their own key, and they never leave the server: /api/config publishes only the fact that they are set. This is the way to fund an instance other people use. Every request from every user is billed to them, so mind the provider's rate limits.-- API Keys: server-side (start here) -- These cover any user who has not supplied their own key, and they never leave the server: /api/config publishes only the fact that they are set. This is the way to fund an instance other people use. Every request from every user is billed to them, so mind the provider's rate limits.
BUILT_IN_TVDB_API_KEYCACHE_CLEANUP_AUTO_ENABLED=true-- Cache Cleanup Scheduler -- Enable automatic cache cleanup (Default: true)-- Cache Cleanup Scheduler -- Enable automatic cache cleanup (Default: true)
CACHE_CLEANUP_WINDOWHours automatic cache cleanup may run, in the TZ time zone (e.g., 03:00-05:00). Empty: any timeHours automatic cache cleanup may run, in the TZ time zone (e.g., 03:00-05:00). Empty: any time
CACHE_EPOCHCache epoch — bumped by hand when a cached payload's shape changes, so ordinary releases no longer discard good cache. Governs both tiers: Redis keys are prefixed with it, and cold-store rows record it. Raise it to force a rebuild without waiting for a release.Cache epoch — bumped by hand when a cached payload's shape changes, so ordinary releases no longer discard good cache. Governs both tiers: Redis keys are prefixed with it, and cold-store rows record it. Raise it to force a rebuild without waiting for a release.
CACHE_WARM_INTERVAL_HOURS=24How often (in hours) to warm cache (Default: 24)How often (in hours) to warm cache (Default: 24)
CACHE_WARM_LANGUAGE=en-USLanguage to use for cache warming (Default: en-US)Language to use for cache warming (Default: en-US)
CACHE_WARMUP_MODE=essentialChoose warm-up mode, 'essential' warms select TMDB/MAL catalogs with limited depth whilst 'comprehensive' warms all the catalogs present in a UUID, at the max depth specified below NOTE: comprehensive *requires* a CACHE_WARMUP_UUID to be setChoose warm-up mode, 'essential' warms select TMDB/MAL catalogs with limited depth whilst 'comprehensive' warms all the catalogs present in a UUID, at the max depth specified below NOTE: comprehensive *requires* a CACHE_WARMUP_UUID to be set
CACHE_WARMUP_ON_STARTUP=trueEnable cache warmup on startup (Default: true)Enable cache warmup on startup (Default: true)
CACHE_WARMUP_UUID=system-cache-warmerCACHE_WARMUP_UUIDSSpecify a custom UUID to use for the cache warming config. Highly recommended for private instances.Specify a custom UUID to use for the cache warming config. Highly recommended for private instances.
CATALOG_LIST_ITEMS_SIZE=20-- Catalog Configuration -- The number of items to display per page in catalogs. (Default: 20)-- Catalog Configuration -- The number of items to display per page in catalogs. (Default: 20)
CATALOG_REFRESH_AHEAD_ENABLEDRebuild a catalog in the background when a request arrives near the end of its cache lifetime, so the cached copy is served immediately and the rebuild never lands on a user request. (Default: true) Cache TTLs are unchanged, so nothing is served staler than CATALOG_TTL allows.Rebuild a catalog in the background when a request arrives near the end of its cache lifetime, so the cached copy is served immediately and the rebuild never lands on a user request. (Default: true) Cache TTLs are unchanged, so nothing is served staler than CATALOG_TTL allows.
CATALOG_REFRESH_AHEAD_FRACTIONHow much of an entry's lifetime counts as due for a background rebuild. (Default: 0.1) 0.1 is the final tenth: the last 2.4 hours of a 24 hour catalog.How much of an entry's lifetime counts as due for a background rebuild. (Default: 0.1) 0.1 is the final tenth: the last 2.4 hours of a 24 hour catalog.
CATALOG_REFRESH_AHEAD_MAX_CONCURRENTHow many background catalog rebuilds may run at once. (Default: 3) Requests over the limit are skipped, not queued - the entry is still fresh.How many background catalog rebuilds may run at once. (Default: 3) Requests over the limit are skipped, not queued - the entry is still fresh.
CATALOG_TTL=86400-- Cache TTL Configuration -- Catalog cache time-to-live in seconds (default: 86400 = 24 hours)-- Cache TTL Configuration -- Catalog cache time-to-live in seconds (default: 86400 = 24 hours)
CATALOG_WARMUP_AUTO_ON_EPOCH_CHANGEAuto warmup when CACHE_EPOCH is bumped, which supersedes every cached key. (Formerly CATALOG_WARMUP_AUTO_ON_VERSION_CHANGE, still accepted.)Auto warmup when CACHE_EPOCH is bumped, which supersedes every cached key. (Formerly CATALOG_WARMUP_AUTO_ON_VERSION_CHANGE, still accepted.)
CATALOG_WARMUP_INITIAL_DELAY_SECONDS=300Initial delay before starting catalog warming (in seconds)Initial delay before starting catalog warming (in seconds)
CATALOG_WARMUP_INTERVAL_HOURS=24How often (in hours) to warm popular TMDB content. (Default: 24, Minimum: 12)How often (in hours) to warm popular TMDB content. (Default: 24, Minimum: 12)
CATALOG_WARMUP_LOG_LEVEL=infoLogging level for catalog warmingLogging level for catalog warming
CATALOG_WARMUP_MAX_PAGES_PER_CATALOG=100Set the max page number to warm per catalog (Default: 100)Set the max page number to warm per catalog (Default: 100)
CATALOG_WARMUP_RESUME_ON_RESTART=trueResume warming on restart (Default: true)Resume warming on restart (Default: true)
CATALOG_WARMUP_TASK_DELAY_MS=100Delay between catalog warmup tasks (in ms)Delay between catalog warmup tasks (in ms)
CATALOG_WARMUP_WINDOWHours catalog warming may start, in the TZ time zone (e.g., 04:00-06:00). Empty: any timeHours catalog warming may start, in the TZ time zone (e.g., 04:00-06:00). Empty: any time
COLD_STORE_INACTIVE_DAYSCOLD_STORE_STATS_TTLHow long the dashboard reuses cold-store size figures before recounting. Each recount is a synchronous scan that blocks the event loop; 0 recounts always.How long the dashboard reuses cold-store size figures before recounting. Each recount is a synchronous scan that blocks the event loop; 0 recounts always.
COLD_TTL_FROZENCOLD_TTL_STABLECUSTOM_DESCRIPTION_BLURBOptional custom HTML blurb to display on the configuration page.Optional custom HTML blurb to display on the configuration page.
DASHBOARD_METADATA_LANGUAGEPreferred language code for popular-content titles shown on the dashboard Content tab. A title captured in this language is not overwritten by requests in other languages. Leave blank to always use the most recent request's language. (Default: en)Preferred language code for popular-content titles shown on the dashboard Content tab. A title captured in this language is not overwritten by requests in other languages. Leave blank to always use the most recent request's language. (Default: en)
DATABASE_READ_URI-- Geo-redundancy / read replica (PostgreSQL only, optional) -- For multi-region deploys: point DATABASE_URI at the single writable PRIMARY (shared by every region) and DATABASE_READ_URI at the LOCAL read replica in this region. All writes (config saves, OAuth tokens, login rehash) go to the primary; reads are served locally. Leave unset to use DATABASE_URI for both. Falls back to the primary auto-- Geo-redundancy / read replica (PostgreSQL only, optional) -- For multi-region deploys: point DATABASE_URI at the single writable PRIMARY (shared by every region) and DATABASE_READ_URI at the LOCAL read replica in this region. All writes (config saves, OAuth tokens, login rehash) go to the primary; reads are served locally. Leave unset to use DATABASE_URI for both. Falls back to the primary auto
DATABASE_URI=sqlite://addon/data/db.sqlite-- Database & Caching -- Connection URI for the database. SQLite is used for local storage, but PostgreSQL is also supported. For SQLite (default):-- Database & Caching -- Connection URI for the database. SQLite is used for local storage, but PostgreSQL is also supported. For SQLite (default):
DISABLE_METRICS-- Metrics Configuration -- Set to "true" to disable all telemetry/metrics collection for the dashboard.-- Metrics Configuration -- Set to "true" to disable all telemetry/metrics collection for the dashboard.
DISABLE_TRAKT_SEARCH=falseDisable trakt as a search option (recommended on public instances)Disable trakt as a search option (recommended on public instances)
ENABLE_BUILTIN_POSTER_CACHE-- Built-in Image Cache -- Cache artwork on disk and serve it from /poster-cache on this addon's own port. No extra container, port, or volume: images are stored under addon/data/poster-cache, inside the data volume you already mount. Multi-replica/k8s deploys get an independent cache per replica; run a shared external proxy instead if that matters.-- Built-in Image Cache -- Cache artwork on disk and serve it from /poster-cache on this addon's own port. No extra container, port, or volume: images are stored under addon/data/poster-cache, inside the data volume you already mount. Multi-replica/k8s deploys get an independent cache per replica; run a shared external proxy instead if that matters.
ENABLE_CACHE_WARMING=true-- Cache Performance & Warming -- Set to "false" to disable automatic cache warming on startup. (Default: true)-- Cache Performance & Warming -- Set to "false" to disable automatic cache warming on startup. (Default: true)
ENABLE_MOVIELENS_SYNC=trueEnable the scheduled background job that re-syncs Trakt/Simkl/MDBList ratings into connected MovieLens accounts. (Default: true) Requires a restart.Enable the scheduled background job that re-syncs Trakt/Simkl/MDBList ratings into connected MovieLens accounts. (Default: true) Requires a restart.
FANART_API_KEYYour Fanart.tv API key. Optional, used for fetching high-quality logos and backgrounds.Your Fanart.tv API key. Optional, used for fetching high-quality logos and backgrounds.
FANART_API_PROJECT_KEYFanart.tv project API key. When set, user keys are sent as clientKey for faster image access.Fanart.tv project API key. When set, user keys are sent as clientKey for faster image access.
FANART_CLIENT_CACHE_MAX=2000-- In-Memory Cache Limits -- Max entries in the per-user Fanart.tv client cache. (Default: 2000) Sized for popular public instances. Lower on memory-constrained self-hosts.-- In-Memory Cache Limits -- Max entries in the per-user Fanart.tv client cache. (Default: 2000) Sized for popular public instances. Lower on memory-constrained self-hosts.
FROZEN_AGEGEMINI_API_KEYYour Gemini API key. Optional, for AI features.Your Gemini API key. Optional, for AI features.
HEAP_LOG_INTERVAL_MINLog heap and in-memory cache stats to console at this interval (in minutes). 0 or unset disables.Log heap and in-memory cache stats to console at this interval (in minutes). 0 or unset disables.
HOST_NAMEThe public hostname (e.g., https://your-domain.com or http://127.0.0.1:3232) where the addon is accessible. This is crucial for Stremio to correctly locate your addon's manifest and resources.The public hostname (e.g., https://your-domain.com or http://127.0.0.1:3232) where the addon is accessible. This is crucial for Stremio to correctly locate your addon's manifest and resources.
HTTP_PROXYOptional HTTP proxy for all requests.Optional HTTP proxy for all requests.
HTTPS_PROXYOptional HTTPS proxy for all requests.Optional HTTPS proxy for all requests.
IMAGE_PROXY_SIGNING_SECRETHMAC secret signing the /poster, /logo and /background proxy URLs. Falls back to ADMIN_KEY; unsigned if neither is set.HMAC secret signing the /poster, /logo and /background proxy URLs. Falls back to ADMIN_KEY; unsigned if neither is set.
IMAGE_WARM_CONCURRENCY_MAXIMAGE_WARM_CONCURRENCY_MINIMAGE_WARM_QUEUEImage warming runs through one bounded queue shared by every catalog, instead of an unbounded chain per catalog. Concurrency adapts to event-loop lag, so it uses whatever headroom catalog warming leaves and backs off when it does not.Image warming runs through one bounded queue shared by every catalog, instead of an unbounded chain per catalog. Concurrency adapts to event-loop lag, so it uses whatever headroom catalog warming leaves and backs off when it does not.
IMAGE_WARM_QUEUE_MAXIMAGE_WARM_TARGET_LAG_MSJIKAN_API_BASE=https://api.tenrai.org/v1Jikan v4 compatible API base URL, the source for MAL catalogs, search and anime metadata. Empty means the public Tenrai API (120 requests a minute per IP). Point it at a self-hosted Jikan (see README) for more headroom, e.g. http://jikan_rest:8080/v4 when running both on the same Docker network.Jikan v4 compatible API base URL, the source for MAL catalogs, search and anime metadata. Empty means the public Tenrai API (120 requests a minute per IP). Point it at a self-hosted Jikan (see README) for more headroom, e.g. http://jikan_rest:8080/v4 when running both on the same Docker network.
JIKAN_ENABLEDSet to false to turn off MAL catalogs, search and metadata. MAL lists and tracking use the official MAL API and keep working. (Default: true)Set to false to turn off MAL catalogs, search and metadata. MAL lists and tracking use the official MAL API and keep working. (Default: true)
LOG_BUFFER_SIZEMaximum number of log entries kept in the in-memory ring buffer for the dashboard logs tab. (Default: 10000)Maximum number of log entries kept in the in-memory ring buffer for the dashboard logs tab. (Default: 10000)
LOG_LEVEL=infoSet the logging level. Options: 'silent', 'fatal', 'error', 'warn', 'info', 'success', 'debug', 'trace', 'verbose'. (Default: 'info' for production, 'debug' for development)Set the logging level. Options: 'silent', 'fatal', 'error', 'warn', 'info', 'success', 'debug', 'trace', 'verbose'. (Default: 'info' for production, 'debug' for development)
MAL_CLIENT_IDMyAnimeList API credentials (required for MAL watch tracking) Get these from https://myanimelist.net/apiconfig Your MAL client IDMyAnimeList API credentials (required for MAL watch tracking) Get these from https://myanimelist.net/apiconfig Your MAL client ID
MAL_CLIENT_SECRETYour MAL client secretYour MAL client secret
MAL_PAGE_SIZEItems per page for all MAL/Jikan catalogs. (Default: 25) Jikan caps this at 25 by default. Only raise it on a self-hosted instance, and keep it <= the instance's MAX_RESULTS_PER_PAGE or requests will 400.Items per page for all MAL/Jikan catalogs. (Default: 25) Jikan caps this at 25 by default. Only raise it on a self-hosted instance, and keep it <= the instance's MAX_RESULTS_PER_PAGE or requests will 400.
MAL_REDIRECT_URIThe redirect URI for MAL OAuth (must match your MAL app settings) Example: https://your-domain.com/mal/callbackThe redirect URI for MAL OAuth (must match your MAL app settings) Example: https://your-domain.com/mal/callback
MAL_SOCKS_PROXY_URLOptional SOCKS proxy for Jikan/MAL requests.Optional SOCKS proxy for Jikan/MAL requests.
MAL_WARMUP_DECADES=falseEnable decade-based MAL warmingEnable decade-based MAL warming
MAL_WARMUP_ENABLED=true-- MAL Catalog Background Warming -- Set to "false" to disable MAL-specific catalog warming. (Default: true)-- MAL Catalog Background Warming -- Set to "false" to disable MAL-specific catalog warming. (Default: true)
MAL_WARMUP_INITIAL_DELAY_SECONDS=30Initial delay before starting MAL warming (in seconds)Initial delay before starting MAL warming (in seconds)
MAL_WARMUP_INTERVAL_HOURS=6Interval in hours for MAL catalog warming. (Default: 6)Interval in hours for MAL catalog warming. (Default: 6)
MAL_WARMUP_LOG_LEVEL=normalLogging level for MAL warmingLogging level for MAL warming
MAL_WARMUP_METADATA=falseEnable/disable metadata warming for MALEnable/disable metadata warming for MAL
MAL_WARMUP_PRIORITY=trueEnable priority warming for MALEnable priority warming for MAL
MAL_WARMUP_PRIORITY_PAGES=2Number of priority pages for MAL warmingNumber of priority pages for MAL warming
MAL_WARMUP_SCHEDULE=trueEnable scheduled MAL warmingEnable scheduled MAL warming
MAL_WARMUP_SFW=trueEnable SFW mode for MAL warmingEnable SFW mode for MAL warming
MAL_WARMUP_TASK_DELAY_MS=100Delay between MAL warmup tasks (in ms)Delay between MAL warmup tasks (in ms)
MAL_WARMUP_WINDOWHours MAL warming may start, in the TZ time zone (e.g., 04:00-06:00). Empty: any timeHours MAL warming may start, in the TZ time zone (e.g., 04:00-06:00). Empty: any time
MAX_CATALOGSOptional cap on catalog count per user configuration. When set to a positive integer, saving a configuration with more catalogs than this limit is rejected. Leaving this unset preserves the unbounded behaviour.Optional cap on catalog count per user configuration. When set to a positive integer, saving a configuration with more catalogs than this limit is rejected. Leaving this unset preserves the unbounded behaviour.
MDBLIST_API_KEYYour MDBList API key. Optional, for integrating MDBList catalogs.Your MDBList API key. Optional, for integrating MDBList catalogs.
META_COLD_STORE_COMPRESSIONlz4-compress stored payloads (~50% smaller disk footprint). Safe to toggle at any time — existing entries stay readable either way.lz4-compress stored payloads (~50% smaller disk footprint). Safe to toggle at any time — existing entries stay readable either way.
META_COLD_STORE_ENABLED--- Meta Cold Store (disk L2 for stable metadata; off by default) --- Persists only provably-stable metadata (old films, ended series, finished anime) in a dedicated SQLite file, so Redis eviction stops forcing upstream re-fetches.--- Meta Cold Store (disk L2 for stable metadata; off by default) --- Persists only provably-stable metadata (old films, ended series, finished anime) in a dedicated SQLite file, so Redis eviction stops forcing upstream re-fetches.
META_COLD_STORE_MAX_BYTESMETA_COLD_STORE_PATHMETA_CONCURRENCYMax concurrent getMeta() calls per catalog request (default: unlimited) Set to 20-30 on public instances to limit memory spikes from concurrent users.Max concurrent getMeta() calls per catalog request (default: unlimited) Set to 20-30 on public instances to limit memory spikes from concurrent users.
METAHUB_IMAGE_EXISTS_TTL_SECONDS=86400-- Metahub Artwork Checks -- Time-to-live for cached metahub logo/image existence checks, in seconds. (Default: 86400)-- Metahub Artwork Checks -- Time-to-live for cached metahub logo/image existence checks, in seconds. (Default: 86400)
METAHUB_IMAGE_HEAD_TIMEOUT_MS=4000Timeout for the metahub image existence HEAD request, in ms. (Default: 4000)Timeout for the metahub image existence HEAD request, in ms. (Default: 4000)
META_TTL=604800Meta cache time-to-live in seconds (default: 604800 = 7 days)Meta cache time-to-live in seconds (default: 604800 = 7 days)
MOVIELENS_API_BASELeft commented so a copied .env does not pin these past a newer default. Base URL for the MovieLens API. (Default: https://movielens.org/api)Left commented so a copied .env does not pin these past a newer default. Base URL for the MovieLens API. (Default: https://movielens.org/api)
MOVIELENS_CATALOG_TTL_SECONDS=3600Time-to-live for MovieLens catalog cache entries, in seconds. (Default: 3600) Per-catalog cacheTTL set in the UI overrides this.Time-to-live for MovieLens catalog cache entries, in seconds. (Default: 3600) Per-catalog cacheTTL set in the UI overrides this.
MOVIELENS_CRED_KEY-- MovieLens Integration -- Personalized recommendation catalogs backed by a user's MovieLens account. REQUIRED to enable the integration: AES key encrypting stored MovieLens passwords. This is env-only and never editable from the dashboard. Rotating it orphans all stored credentials, forcing every user to reconnect their MovieLens account.-- MovieLens Integration -- Personalized recommendation catalogs backed by a user's MovieLens account. REQUIRED to enable the integration: AES key encrypting stored MovieLens passwords. This is env-only and never editable from the dashboard. Rotating it orphans all stored credentials, forcing every user to reconnect their MovieLens account.
MOVIELENS_IMPORT_REFERERReferer header used for the MovieLens CSV ratings-import request.Referer header used for the MovieLens CSV ratings-import request.
MOVIELENS_LIST_MAX_PAGES=50Safety cap on pages fetched when paginating a MovieLens user list. (Default: 50)Safety cap on pages fetched when paginating a MovieLens user list. (Default: 50)
MOVIELENS_LOGIN_REFERERUser-Agent sent to MovieLens. MovieLens sits behind Cloudflare and rejects requests without a browser-like User-Agent. MOVIELENS_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Referer header used for the MovieLens login request. (Default: https://movielens.org/login)User-Agent sent to MovieLens. MovieLens sits behind Cloudflare and rejects requests without a browser-like User-Agent. MOVIELENS_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Referer header used for the MovieLens login request. (Default: https://movielens.org/login)
MOVIELENS_MANUAL_SYNC_COOLDOWN_SECONDS=21600Minimum seconds between user-triggered "Import ratings" runs. (Default: 21600)Minimum seconds between user-triggered "Import ratings" runs. (Default: 21600)
MOVIELENS_REQUEST_TIMEOUT_MS=25000Timeout for requests to the MovieLens API, in ms. (Default: 25000)Timeout for requests to the MovieLens API, in ms. (Default: 25000)
MOVIELENS_SYNC_INTERVAL_HOURS=24How often the scheduled job re-syncs ratings, in hours. (Default: 24) Requires a restart.How often the scheduled job re-syncs ratings, in hours. (Default: 24) Requires a restart.
MOVIELENS_USERMETA_TTL_SECONDSTime-to-live for cached MovieLens account metadata, in seconds. (Default: 43200) Covers the recommendation engine and taste tags. Lower this to react faster when a user upgrades from the "bard" engine to a personalized one. Replaces MOVIELENS_GROUPTAGS_TTL_SECONDS, which is still honoured as a fallback.Time-to-live for cached MovieLens account metadata, in seconds. (Default: 43200) Covers the recommendation engine and taste tags. Lower this to react faster when a user upgrades from the "bard" engine to a personalized one. Replaces MOVIELENS_GROUPTAGS_TTL_SECONDS, which is still honoured as a fallback.
NODE_ENV=developmentThe Node environment. Usually 'development' or 'production'.The Node environment. Usually 'development' or 'production'.
PORT=3232-- Core Configuration -- The port the addon server will run on.-- Core Configuration -- The port the addon server will run on.
POSTER_CACHE_ALLOWED_HOSTSComma-separated hosts allowed even when they resolve to a private/LAN address. Needed if your rating/art provider (e.g. a self-hosted PosterPlus) runs on your own network; without it those fetches are blocked as SSRF. Everything else stays blocked.Comma-separated hosts allowed even when they resolve to a private/LAN address. Needed if your rating/art provider (e.g. a self-hosted PosterPlus) runs on your own network; without it those fetches are blocked as SSRF. Everything else stays blocked.
POSTER_CACHE_BACKGROUNDSPosters are cached by default. Everything below is opt-in, so turning the cache on never changes disk usage unexpectedly. All are also toggles in the dashboard. Backgrounds are the largest images served — the biggest bandwidth win.Posters are cached by default. Everything below is opt-in, so turning the cache on never changes disk usage unexpectedly. All are also toggles in the dashboard. Backgrounds are the largest images served — the biggest bandwidth win.
POSTER_CACHE_DIROverride where cached images live. (Default: addon/data/poster-cache)Override where cached images live. (Default: addon/data/poster-cache)
POSTER_CACHE_FETCH_CONCURRENCYCeiling on simultaneous downloads of uncached images. Each in-flight fetch holds an image in memory, so this bounds peak memory during a burst of cache misses. Duplicate requests for the same image are coalesced and don't use a slot. (Default: 128)Ceiling on simultaneous downloads of uncached images. Each in-flight fetch holds an image in memory, so this bounds peak memory during a burst of cache misses. Duplicate requests for the same image are coalesced and don't use a slot. (Default: 128)
POSTER_CACHE_IMPORT_NGINX_DIRUpgrading from the OLD bundled nginx poster cache? Nothing to configure: the old cache is detected at /var/cache/nginx/posters and imported once, so long as you leave that volume mounted for one start. A marker stops it running twice. Set a path only if your old cache lived somewhere non-standard, or 'off' to skip.Upgrading from the OLD bundled nginx poster cache? Nothing to configure: the old cache is detected at /var/cache/nginx/posters and imported once, so long as you leave that volume mounted for one start. A marker stops it running twice. Set a path only if your old cache lived somewhere non-standard, or 'off' to skip.
POSTER_CACHE_INACTIVE_DAYSDrop images not requested for this many days. (Default: 30)Drop images not requested for this many days. (Default: 30)
POSTER_CACHE_INFER_TTLDerive each image's validity from the headers its own source sent, instead of the flat value above; where a source promises nothing we can act on, the flat value still applies. Expect a year for TMDB, days for MAL and metahub, hours or less for rating services. A source asking not to be cached at all is then honoured too, and its image is served without being stored. Not a substitute for a rule onDerive each image's validity from the headers its own source sent, instead of the flat value above; where a source promises nothing we can act on, the flat value still applies. Expect a year for TMDB, days for MAL and metahub, hours or less for rating services. A source asking not to be cached at all is then honoured too, and its image is served without being stored. Not a substitute for a rule on
POSTER_CACHE_LANDSCAPE_POSTERSPOSTER_CACHE_LOGOSPOSTER_CACHE_LOG_REQUESTSLog every image request. Off by default: at scale it floods the log buffer and evicts everything else. A one-line summary is logged each minute regardless.Log every image request. Off by default: at scale it floods the log buffer and evicts everything else. A one-line summary is logged each minute regardless.
POSTER_CACHE_MAX_OBJECT_BYTESImages larger than this are passed through to the client uncached, so one oversized asset cannot consume the whole budget. (Default: 20m)Images larger than this are passed through to the client uncached, so one oversized asset cannot consume the whole budget. (Default: 20m)
POSTER_CACHE_MAX_SIZEDISK budget. Least-recently-used images are evicted once exceeded. (Default: 10g)DISK budget. Least-recently-used images are evicted once exceeded. (Default: 10g)
POSTER_CACHE_MEMORY_SIZERAM budget for the hottest images, layered in front of the disk cache. A memory hit skips the disk read AND its per-request allocation, lowering GC pressure. This is on top of the addon's own footprint. Set to 0 for disk only. (Default: 128m)RAM budget for the hottest images, layered in front of the disk cache. A memory hit skips the disk read AND its per-request allocation, lowering GC pressure. This is on top of the addon's own footprint. Set to 0 for disk only. (Default: 128m)
POSTER_CACHE_PROCESSED_IMAGESCache the images the addon renders itself: rating-overlaid posters (when Proxy Rating & Custom Art is on) plus the blur/resize/banner-to-background transforms. ON by default with the cache; set false only to keep these out of it. Custom art URLs pass through unchanged, so they follow their own type's toggle above.Cache the images the addon renders itself: rating-overlaid posters (when Proxy Rating & Custom Art is on) plus the blur/resize/banner-to-background transforms. ON by default with the cache; set false only to keep these out of it. Custom art URLs pass through unchanged, so they follow their own type's toggle above.
POSTER_CACHE_PROVIDER_POLICIESPer-provider overrides, as a JSON list. Each rule names a domain and one of "default" (the flat validity above), "infer" (follow that provider's own headers), "custom" (a fixed "ttl" such as 6h, 30d, 1y) or "bypass" (serve without ever storing). A rule beats the toggle above, which beats the flat validity. A domain covers its subdomains, and the more specific rule wins, and one rule covers every iPer-provider overrides, as a JSON list. Each rule names a domain and one of "default" (the flat validity above), "infer" (follow that provider's own headers), "custom" (a fixed "ttl" such as 6h, 30d, 1y) or "bypass" (serve without ever storing). A rule beats the toggle above, which beats the flat validity. A domain covers its subdomains, and the more specific rule wins, and one rule covers every i
POSTER_CACHE_STREAM_THRESHOLDCached images above this are streamed from disk instead of buffered, so bursts of large artwork can't pile up on the heap. (Default: 256k)Cached images above this are streamed from disk instead of buffered, so bursts of large artwork can't pile up on the heap. (Default: 256k)
POSTER_CACHE_THUMBNAILSEpisode thumbnails are by far the most numerous: one long-running series can add hundreds of images. Expect disk usage to grow quickly.Episode thumbnails are by far the most numerous: one long-running series can add hundreds of images. Expect disk usage to grow quickly.
POSTER_CACHE_TTL_DAYSHow long a cached image stays fresh. Fractional allowed (0.5 = 12h); 0 never expires. Expiry is not a re-download: sources that send an ETag or Last-Modified are asked to confirm the stored copy, and a 304 restarts validity with no body transferred. If you use a rating poster service or a custom art URL pattern, give its domain a shorter rule below — those URLs name a slot rather than a file, so tHow long a cached image stays fresh. Fractional allowed (0.5 = 12h); 0 never expires. Expiry is not a re-download: sources that send an ETag or Last-Modified are asked to confirm the stored copy, and a 304 restarts validity with no body transferred. If you use a rating poster service or a custom art URL pattern, give its domain a shorter rule below — those URLs name a slot rather than a file, so t
POSTER_PROXY_ALLOW_PRIVATEWhether a signed art URL may reach a private/LAN address. Fine when you are the only one configuring art patterns. Set false on a public multi-user instance: patterns are user-supplied, so a user could aim one inside your network. (Default: true)Whether a signed art URL may reach a private/LAN address. Fine when you are the only one configuring art patterns. Set false on a public multi-user instance: patterns are user-supplied, so a user could aim one inside your network. (Default: true)
POSTER_PROXY_MAX_AGE_DAYSHow long players/browsers may keep an image from the /poster, /logo and /background proxy routes. Short by default: those routes revalidate on request parameters, not bytes, so only expiry picks up changed art. Fractional allowed (0.25 = 6h), 0 never expires, capped by the served image's own remaining validity. (Default: 1)How long players/browsers may keep an image from the /poster, /logo and /background proxy routes. Short by default: those routes revalidate on request parameters, not bytes, so only expiry picks up changed art. Fractional allowed (0.25 = 6h), 0 never expires, capped by the served image's own remaining validity. (Default: 1)
POSTER_PROXY_PREFIX_URLPublic URL clients fetch images through. Leave empty with the built-in cache — it derives {HOST_NAME}/poster-cache automatically. Set it only when pointing at an external caching proxy.Public URL clients fetch images through. Leave empty with the built-in cache — it derives {HOST_NAME}/poster-cache automatically. Set it only when pointing at an external caching proxy.
POSTER_PROXY_TIMEOUT_MSMilliseconds to wait for an upstream poster/art image before serving the fallback. (Default: 10000) Raise this if a slow rating/poster-generation service times out on first render.Milliseconds to wait for an upstream poster/art image before serving the fallback. (Default: 10000) Raise this if a slow rating/poster-generation service times out on first render.
POSTER_WARMUP_URLInternal URL used for server-side image warming (defaults to the built-in cache on 127.0.0.1 when enabled; otherwise falls back to POSTER_PROXY_PREFIX_URL).Internal URL used for server-side image warming (defaults to the built-in cache on 127.0.0.1 when enabled; otherwise falls back to POSTER_PROXY_PREFIX_URL).
PREFER_SMALLER_BACKDROPS_TMDBRequesting smaller backgrounds is usually not recommended especially if they're being rendered on high resolution (4k) screens, enable this if saving space/bandwidth is more important than sharpnessRequesting smaller backgrounds is usually not recommended especially if they're being rendered on high resolution (4k) screens, enable this if saving space/bandwidth is more important than sharpness
PREFER_SMALLER_LANDSCAPE_TMDBLandscape images are safer, as they are usually rendered in smaller boxesLandscape images are safer, as they are usually rendered in smaller boxes
PREFER_SMALLER_LOGOS_TMDB-- TMDB Image Renditions -- Request smaller images from TMDB to save space. The three below are OFF by default.. Logos are the safest win, as they can be huge from the source but are rendered small by the client.-- TMDB Image Renditions -- Request smaller images from TMDB to save space. The three below are OFF by default.. Logos are the safest win, as they can be huge from the source but are rendered small by the client.
PREFER_SMALLER_POSTERS_TMDBPosters are the exception: they have always been requested at w600_and_h900_bestv2, so this one is ON by default and setting it to false is what changes artwork. It is also the most expensive to flip - a catalog page pulls one poster per tile.Posters are the exception: they have always been requested at w600_and_h900_bestv2, so this one is ON by default and setting it to false is what changes artwork. It is also the most expensive to flip - a catalog page pulls one poster per tile.
REDIS_URL=redis://aiometadata_redis:6379Connection string for your Redis instance, used for caching.Connection string for your Redis instance, used for caching.
RESPONSE_COMPRESSION_ENABLEDCompress HTTP responses with gzip or brotli, whichever the client negotiates. (Default: true) A 20-item catalog page drops from about 99 KB to about 22 KB for roughly 1 ms of CPU. Images, server-sent events and responses under 1 KB are skipped. Set false only if a proxy in front is already compressing.Compress HTTP responses with gzip or brotli, whichever the client negotiates. (Default: true) A 20-item catalog page drops from about 99 KB to about 22 KB for roughly 1 ms of CPU. Images, server-sent events and responses under 1 KB are skipped. Set false only if a proxy in front is already compressing.
RPDB_API_KEYYour Rating Poster DB (RPDB) API key. Optional, for displaying ratings on posters.Your Rating Poster DB (RPDB) API key. Optional, for displaying ratings on posters.
RUN_MIGRATIONSSet to false on replica-region instances to skip schema creation (DDL) on startup. Run migrations once against the primary; replicas then boot without attempting DDL. (Default: true)Set to false on replica-region instances to skip schema creation (DDL) on startup. Run migrations once against the primary; replicas then boot without attempting DDL. (Default: true)
SETTLE_MOVIESETTLE_SERIESSIMKL_ACTIVITIES_TTL=1800Time-to-live (in seconds) for caching SimKL activity checks. Reduces API spam when paginating, and caps how long Up Next and Hide Simkl Watched lag behind what you just watched. This is the default; users on a V2 connection can set their own interval in the Simkl integration. Default: 1800 (30 minutes)Time-to-live (in seconds) for caching SimKL activity checks. Reduces API spam when paginating, and caps how long Up Next and Hide Simkl Watched lag behind what you just watched. This is the default; users on a V2 connection can set their own interval in the Simkl integration. Default: 1800 (30 minutes)
SIMKL_AUTH_MODEWhich SimKL connection flow(s) to offer: oauth, pin, or both. "pin" needs only SIMKL_CLIENT_ID - no client secret and no publicly reachable callback URL - which makes it the right choice for private, self-hosted instances. Default: pin when SIMKL_CLIENT_SECRET is empty, otherwise oauth.Which SimKL connection flow(s) to offer: oauth, pin, or both. "pin" needs only SIMKL_CLIENT_ID - no client secret and no publicly reachable callback URL - which makes it the right choice for private, self-hosted instances. Default: pin when SIMKL_CLIENT_SECRET is empty, otherwise oauth.
SIMKL_CLIENT_IDYour SimKL client IDYour SimKL client ID
SIMKL_CLIENT_SECRETYour SimKL client secret. Only needed for the browser-redirect OAuth flow.Your SimKL client secret. Only needed for the browser-redirect OAuth flow.
SIMKL_REDIRECT_URIThe redirect URI for SimKL OAuth (must match your SimKL app settings) Example: https://your-domain.com/api/auth/simkl/callbackThe redirect URI for SimKL OAuth (must match your SimKL app settings) Example: https://your-domain.com/api/auth/simkl/callback
SOCKS_PROXY_URL-- Advanced/Proxy Configuration -- Optional SOCKS proxy for all requests (e.g., socks5://user:pass@host:port).-- Advanced/Proxy Configuration -- Optional SOCKS proxy for all requests (e.g., socks5://user:pass@host:port).
TMDB_API_KEY-- API Keys: published to the browser -- WARNING: TMDB_API_KEY, TVDB_API_KEY, FANART_API_KEY, RPDB_API_KEY, MDBLIST_API_KEY and GEMINI_API_KEY are served to every visitor by /api/config, in full, so the configure page can prefill them. That path stays open even with AUTH_REQUIRE_SIGNIN=true, so requiring a login does not protect them. Set them only where you would hand your keys to every user. On-- API Keys: published to the browser -- WARNING: TMDB_API_KEY, TVDB_API_KEY, FANART_API_KEY, RPDB_API_KEY, MDBLIST_API_KEY and GEMINI_API_KEY are served to every visitor by /api/config, in full, so the configure page can prefill them. That path stays open even with AUTH_REQUIRE_SIGNIN=true, so requiring a login does not protect them. Set them only where you would hand your keys to every user. On
TMDB_POPULAR_WARMING_ENABLED=trueSet to "false" to disable warming of popular TMDB content. (Default: true)Set to "false" to disable warming of popular TMDB content. (Default: true)
TMDB_SCRAPED_IMDB_CACHE_MAX=10000Max entries in the TMDB scraped-IMDb-ID cache. (Default: 10000)Max entries in the TMDB scraped-IMDb-ID cache. (Default: 10000)
TMDB_SOCKS_PROXY_URLOptional SOCKS proxy for TMDB requests (e.g., socks5://user:pass@host:port).Optional SOCKS proxy for TMDB requests (e.g., socks5://user:pass@host:port).
TRAKT_CLIENT_IDTrakt API credentials (required for Trakt integration) Get these from https://trakt.tv/oauth/applications Your Trakt client IDTrakt API credentials (required for Trakt integration) Get these from https://trakt.tv/oauth/applications Your Trakt client ID
TRAKT_CLIENT_SECRETYour Trakt client secretYour Trakt client secret
TRAKT_CONCURRENCY=5Max number of trakt parallel requests (recommend 10-15 for selfhosters)Max number of trakt parallel requests (recommend 10-15 for selfhosters)
TRAKT_MIN_TIME=200Spacing between requests (recommend 100ms for selfhosters)Spacing between requests (recommend 100ms for selfhosters)
TRAKT_REDIRECT_URIThe redirect URI for Trakt OAuth (must match your Trakt app settings) Example: https://your-domain.com/api/auth/trakt/callbackThe redirect URI for Trakt OAuth (must match your Trakt app settings) Example: https://your-domain.com/api/auth/trakt/callback
TVDB_API_KEYYour TVDB API key. Optional but highly recommended for series and some anime metadata.Your TVDB API key. Optional but highly recommended for series and some anime metadata.
aiometadata releases & version history
More in Media Streaming
AIOStreamsOpen-source, self-hosted Stremio super-addon: one URL merges every addon, debrid and Usenet source, then filters, sorts and formats results your way.
AircastAirCast is a self-hosted Home Assistant add-on bridging AirPlay to Chromecast for audio streaming from Apple devices.
airtimeSelf-hosted, open-source radio station software: schedule shows and playlists, add audio remotely, and stream with sub-second playout precision.
All-jellyfin-media-serverA Docker Compose stack that combines Jellyfin, the *arr automation apps, a request manager, torrent client, subtitle tool, and VPN into one self-hosted media server.
app-airsonosAirSonos is a self-hosted Home Assistant add-on that bridges AirPlay audio from Apple devices to Sonos and UPnP speakers, exposing each as a virtual AirPlay target.
aria2-ariang-dockerSelf-hosted, open-source Docker image bundling Aria2, AriaNg, File Browser, and Rclone — runs on ARM and x86 with auto HTTPS via Caddy.
AudioserveSimple personal server to serve audiofiles files from folders. Intended primarily for audio books, but anything with decent folder structure will do.
AutoPlexxAutoPlexx is a self-hosted, open-source Docker Compose stack for a complete Plex Media Server with request handling, library automation, VPN torrent downloads, monitoring
bilistreamSelf-hosted open-source tool that monitors Twitch, YouTube, and YouTube scheduled streams and relays them to Bilibili when live, with a built-in web console.
Bitfocus CompanionBitfocus Companion is a self-hosted, open-source app that turns Elgato Stream Decks into pro control surfaces for 800+ broadcast, AV, and home automation devices.
BitPlayBitPlay is a self-hosted Go web app that streams video torrents in your browser, with Prowlarr and Jackett search integration.
bonobSelf-hosted, open-source Sonos SMAPI implementation that connects Sonos speakers to Subsonic API compatible music servers like Navidrome and Gonic.
0 comments