Environment Variables
This page documents the environment variables specific to Koel. These variables are typically set in the .env file at the root of your Koel installation.
Laravel Variables
Koel is built on Laravel, which has its own set of environment variables (e.g. APP_ENV, APP_DEBUG, APP_KEY, APP_URL, DB_*, CACHE_DRIVER, QUEUE_CONNECTION, SESSION_DRIVER, etc.). These are not documented here — please refer to the Laravel documentation for details.
Storage
| Variable | Description | Default |
|---|---|---|
STORAGE_DRIVER | The storage driver for your media files. Valid values: local, sftp, s3 (Koel Plus), dropbox (Koel Plus), webdav (Koel Plus). See Cloud Storage Support. | local |
MEDIA_PATH | The absolute path to your media directory. Required when using STORAGE_DRIVER=local. Can also be changed via the web interface. | (empty) |
ARTIFACTS_PATH | The absolute path to store Koel artifacts (transcoded files, podcast episodes, temporary downloads, etc.). If empty, uses the system's temporary directory. | (empty) |
LARAVEL_STORAGE_PATH | Absolute path Koel uses for writable runtime data — album/artist images (under app/public/images), logs, search indexes, framework cache, sessions. Set this to keep mutable state outside the application directory (read-only deploys, multi-instance setups, etc.). After setting it, run php artisan storage:link (or composer koel:init) so public/storage symlinks to LARAVEL_STORAGE_PATH/app/public. | <app>/storage |
Upgrading an older Koel install
The image storage location moved from public/img/storage/ to storage/app/public/images/ (or LARAVEL_STORAGE_PATH/app/public/images/ when set). php artisan koel:init handles the migration automatically on the first run after upgrading — no manual action needed.
If koel:init reports Some legacy images could not be migrated. Keeping public/img/storage for manual recovery., rerun koel:init after fixing the underlying cause (most often a permissions issue on storage/). As a last resort, perform the move manually:
mkdir -p "${LARAVEL_STORAGE_PATH:-$(pwd)/storage}/app/public/images"
rsync -a public/img/storage/ "${LARAVEL_STORAGE_PATH:-$(pwd)/storage}/app/public/images/"
php artisan storage:linkAfter confirming images render, the old public/img/storage/ directory can be removed.
S3 / S3-Compatible
Required when STORAGE_DRIVER=s3. Remember to set your CORS policy to allow access from Koel's domain.
| Variable | Description | Default |
|---|---|---|
AWS_ACCESS_KEY_ID | Your AWS (or S3-compatible service) access key ID. | (empty) |
AWS_SECRET_ACCESS_KEY | Your AWS secret access key. | (empty) |
AWS_REGION | The region of your bucket. Set to auto for Cloudflare R2. | (empty) |
AWS_ENDPOINT | The endpoint URL for S3-compatible services. | (empty) |
AWS_BUCKET | The name of your S3 bucket. | (empty) |
Dropbox
Required when STORAGE_DRIVER=dropbox. Run php artisan koel:setup-dropbox to set all Dropbox-related variables.
| Variable | Description | Default |
|---|---|---|
DROPBOX_APP_KEY | Your Dropbox app key. | (empty) |
DROPBOX_APP_SECRET | Your Dropbox app secret. | (empty) |
DROPBOX_REFRESH_TOKEN | Your Dropbox refresh token. | (empty) |
SFTP
Required when STORAGE_DRIVER=sftp.
| Variable | Description | Default |
|---|---|---|
SFTP_HOST | The SFTP server hostname. | (empty) |
SFTP_PORT | The SFTP server port. | (empty) |
SFTP_ROOT | The absolute path on the SFTP server to store media files. | (empty) |
SFTP_USERNAME | The SFTP username. | (empty) |
SFTP_PASSWORD | The SFTP password. | (empty) |
SFTP_PRIVATE_KEY | Path to the private key for key-based authentication (alternative to password). | (empty) |
SFTP_PASSPHRASE | The passphrase for the private key. | (empty) |
WebDAV
Required when STORAGE_DRIVER=webdav.
| Variable | Description | Default |
|---|---|---|
WEBDAV_BASE_URL | The WebDAV base URL. For NextCloud, this looks like https://your-nextcloud.example/remote.php/dav/files/<username>/. | (empty) |
WEBDAV_USERNAME | The WebDAV username. For NextCloud, use a dedicated app password rather than the account password. | (empty) |
WEBDAV_PASSWORD | The WebDAV password (or NextCloud app password). | (empty) |
WEBDAV_PATH_PREFIX | Optional path prefix beneath the base URL where Koel stores its media (no leading or trailing slash). For example: Music. | (empty) |
Media Scanning
| Variable | Description | Default |
|---|---|---|
APP_MAX_SCAN_TIME | The maximum scan time in seconds when scanning via the browser. Does not affect koel:sync. | 600 |
MEMORY_LIMIT | The memory limit in MB for the scanning process. Example: 2048. | (empty) |
SCAN_JOBS | The number of parallel worker processes for scanning. Set to 1 to disable parallel scanning. Can be overridden with --jobs flag. | 4 |
IGNORE_DOT_FILES | Whether to ignore dot files and folders when scanning. Greatly improves performance if your media root has folders like .git or .cache. | true |
SYNC_LOG_LEVEL | The verbosity of sync logs (found under storage/logs/). Options: all, error. | error |
Streaming & Transcoding
| Variable | Description | Default |
|---|---|---|
STREAMING_METHOD | The streaming method. Options: php, x-sendfile, x-accel-redirect. See Streaming Music. Using x-sendfile or x-accel-redirect is highly recommended for better performance. | php |
TRANSCODE_FLAC | Whether to transcode FLAC to AAC on the fly. Set to false to stream FLAC as-is. | true |
TRANSCODE_BIT_RATE | The bit rate (in kbps) for transcoded audio. Higher values mean better quality but slower streaming. | 128 |
TRANSCODE_AAC_FAST | Whether to use FFmpeg's faster AAC coding algorithm. Set to false to use its default AAC coder. | true |
FFMPEG_PATH | The full path to the ffmpeg binary. Automatically detected if left empty. | (auto-detected) |
TRANSCODE_TIMEOUT | The maximum time in seconds allowed for transcoding a single file. Increase for very large files. 0 disables the timeout. | 300 |
Downloading
| Variable | Description | Default |
|---|---|---|
ALLOW_DOWNLOAD | Whether to allow song downloading. | true |
Service Integrations
Also see Service Integrations for detailed setup instructions.
| Variable | Description | Default |
|---|---|---|
USE_MUSICBRAINZ | Whether to use MusicBrainz for metadata fetching. | true |
MUSICBRAINZ_USER_AGENT | The user agent for MusicBrainz API requests. Auto-generated if empty. | (auto-generated) |
LASTFM_API_KEY | Your Last.fm API key. Required for artist/album info and scrobbling. | (empty) |
LASTFM_API_SECRET | Your Last.fm API secret. | (empty) |
LISTENBRAINZ_API_ENDPOINT | The ListenBrainz API root. Change this only if you run your own ListenBrainz server. | https://api.listenbrainz.org |
SPOTIFY_CLIENT_ID | Your Spotify application client ID. Used for fetching artist and album images. | (empty) |
SPOTIFY_CLIENT_SECRET | Your Spotify application client secret. | (empty) |
YOUTUBE_API_KEY | Your YouTube API key. See YouTube integration. | (empty) |
TICKETMASTER_API_KEY | Your Ticketmaster API key. See Ticketmaster. | (empty) |
TICKETMASTER_DEFAULT_COUNTRY_CODE | Fallback country code for Ticketmaster when IP-based lookup fails. See ISO 3166-1 alpha-2. | US |
IPINFO_TOKEN | Your IPinfo token, used to look up the user's country for Ticketmaster. | (empty) |
SSO (Single Sign-On)
Koel Plus only. See Single Sign-On.
| Variable | Description | Default |
|---|---|---|
SSO_GOOGLE_CLIENT_ID | Your Google OAuth client ID. | (empty) |
SSO_GOOGLE_CLIENT_SECRET | Your Google OAuth client secret. | (empty) |
SSO_GOOGLE_HOSTED_DOMAIN | The Google Workspace domain users must belong to. | (empty) |
SSO_OIDC_ISSUER | Issuer URL of an OpenID Connect IdP (Authentik, Authelia, Keycloak, Zitadel, …). Koel reads <issuer>/.well-known/openid-configuration for endpoint discovery. | (empty) |
SSO_OIDC_CLIENT_ID | OAuth client ID registered with the IdP. | (empty) |
SSO_OIDC_CLIENT_SECRET | OAuth client secret. | (empty) |
SSO_OIDC_BUTTON_LABEL | Label shown on the OIDC login button. | OpenID Connect |
SSO_DEFAULT_ROLE | The role given to a user on their first SSO login: user or guest. Applies to OIDC, Google, and reverse-proxy auth. | user |
Proxy Authentication
Koel Plus only. See Proxy Authentication.
| Variable | Description | Default |
|---|---|---|
PROXY_AUTH_ENABLED | Whether to enable proxy authentication. | false |
PROXY_AUTH_USER_HEADER | The header containing the unique user identifier. | remote-user |
PROXY_AUTH_PREFERRED_NAME_HEADER | The header containing the user's preferred display name. | remote-preferred-name |
PROXY_AUTH_ALLOW_LIST | A comma-separated list of allowed proxy IPs or CIDRs. If empty, no requests are allowed. | (empty) |
AI Assistant
The AI assistant is no longer set up here. An admin turns it on and adds the provider's API key under Settings → AI Assistant. See AI Assistant.
Miscellaneous
| Variable | Description | Default |
|---|---|---|
APP_URL | The address people use to reach Koel, e.g. https://music.example.com. Links in emails, such as password resets and invitations, point here, so make sure it is correct. | http://localhost |
TRUSTED_HOSTS | A comma-separated list of hostnames allowed to access Koel. Requests for any other hostname are rejected. Prefix a hostname with *. to allow any of its subdomains. Leave empty to allow any hostname. Example: localhost,192.168.0.1,yourdomain.com,*.yourdomain.com | (empty) |
TRUSTED_PROXIES | A comma-separated list of IP addresses or ranges of the reverse proxies in front of Koel. Koel trusts X-Forwarded-* headers only from these. Set it if your proxy is on a public IP, such as Cloudflare. | PRIVATE_SUBNETS |
FORCE_HTTPS | Force Koel to use HTTPS URLs. Set to true if automatic detection fails. | false |
SENTRY_LARAVEL_DSN | Report unhandled exceptions to Sentry. Leave empty to disable reporting entirely. Events are tagged with APP_ENV. | (empty) |
BACKUP_ON_DELETE | Whether to create a backup of a song when deleting it from the filesystem. | true |
CDN_URL | A CDN URL mapped to Koel's home URL, used to serve media files. No trailing slash. | (empty) |
IMAGE_STORAGE_DRIVER | The filesystem driver for artwork — album covers, artist images and avatars. Use s3 to keep them on S3 or an S3-compatible service such as Cloudflare R2, reusing the AWS_* settings. | local |
IMAGE_STORAGE_DIR | Where artwork is stored: a path under Koel's public directory for the local driver, or a key prefix inside the bucket otherwise. | storage/images |
IMAGE_STORAGE_BUCKET | A separate, public bucket for artwork, so media can stay private. | (AWS_BUCKET) |
IMAGE_STORAGE_URL | The public URL artwork is served from. Required when the driver is not local. No trailing slash. | (empty) |
MEDIA_BROWSER_ENABLED | Whether to enable the media browser (experimental Koel Plus feature). | false |
CLEAN_URLS_ENABLED | Whether to use plain URLs like /albums instead of /#/albums. | false |
EMBED_ENABLED | Whether to allow embedding songs, albums, artists, and playlists on external sites. Set to false to hide the "Embed…" menu entries and disable both creation and rendering of embed widgets. | true |
PODCASTS_ENABLED | Whether to enable podcasts. Set to false to hide podcasts from the interface and stop serving them over both Koel's own API and Subsonic. Existing subscriptions and episodes are left untouched. | true |
RADIO_ENABLED | Whether to enable radio stations. Set to false to hide radio from the interface and stop serving it over both Koel's own API and Subsonic. Existing stations are left untouched. | true |