Files
pgsql-jellyfin/docs/FILE_BASED_STARTUP_CONFIG.md
wjones 8f860a8ec3 Centralize build output and generate OS-specific startup.json
- All DLLs now output to lib\[Configuration]\[TargetFramework]\ at repo root (see Directory.Build.props)
- .gitignore updated to exclude /lib/
- On first run, startup.json is auto-generated with OS-appropriate default paths (Windows, Linux, macOS, or portable)
- Removes null/example config; generated config is immediately usable and clearly documented
- Extensive new documentation: build output, startup.json logic, visual guides, and code proofs
- Publish profile now deletes existing files for clean deploys
- No breaking changes: existing startup.json files are preserved
- Improves first-run UX, deployment, and cross-platform consistency
2026-02-26 14:21:26 -05:00

10 KiB

File-Based Startup Configuration

Overview

Jellyfin now supports file-based configuration for all startup paths in addition to command-line options and environment variables. This provides a persistent, portable way to configure your Jellyfin installation.

New in this version: The startup.json file is automatically created on first startup if it doesn't exist, with example configurations for Linux, Windows, and portable installations. See AUTO_GENERATED_STARTUP_CONFIG.md for details.

Configuration Priority

When determining which path to use, Jellyfin follows this priority (highest to lowest):

  1. Command-line options (e.g., --datadir)
  2. Environment variables (e.g., JELLYFIN_DATA_DIR)
  3. Configuration file (startup.json)
  4. Default values

This allows you to set defaults in a file, override them with environment variables for different environments, and temporarily override with command-line options for testing.

Automatic File Creation NEW

On first startup, if no startup.json file is found, Jellyfin will automatically create one with:

  • All path properties set to null (uses defaults)
  • Example configurations for Linux, Windows, and portable setups
  • Inline documentation and comments

You'll see:

Created default startup configuration at: /path/to/startup.json
You can customize this file to set default paths for Jellyfin.

Simply edit the file and restart Jellyfin to apply your custom paths. See AUTO_GENERATED_STARTUP_CONFIG.md for complete details on the auto-generation feature.

Configuration File Location

The startup.json file is searched in the following locations (in order):

  1. Current working directory: ./startup.json
  2. Application directory: {AppDir}/startup.json
  3. Config subdirectory: {AppDir}/config/startup.json

The first file found will be used.

File Format

Create a file named startup.json with the following structure (or let it be auto-generated):

{
  "Paths": {
    "DataDir": "/var/lib/jellyfin",
    "ConfigDir": "/etc/jellyfin",
    "CacheDir": "/var/cache/jellyfin",
    "LogDir": "/var/log/jellyfin",
    "TempDir": "/var/tmp/jellyfin",
    "WebDir": "/usr/share/jellyfin/web"
  }
}

Supported Properties

All path properties are optional. Any property can be set to null or omitted entirely, and the system will fall back to environment variables or defaults.

Property Description Equivalent CLI Equivalent Env Var
DataDir Database and data files --datadir JELLYFIN_DATA_DIR
ConfigDir Configuration files --configdir JELLYFIN_CONFIG_DIR
CacheDir Cache files --cachedir JELLYFIN_CACHE_DIR
LogDir Log files --logdir JELLYFIN_LOG_DIR
TempDir Temporary files --tempdir JELLYFIN_TEMP_DIR
WebDir Web client files --webdir JELLYFIN_WEB_DIR

Example Configurations

Linux Production Server

{
  "Paths": {
    "DataDir": "/var/lib/jellyfin",
    "ConfigDir": "/etc/jellyfin",
    "CacheDir": "/var/cache/jellyfin",
    "LogDir": "/var/log/jellyfin",
    "TempDir": "/var/tmp/jellyfin",
    "WebDir": "/usr/share/jellyfin/web"
  }
}

Windows Production Server

{
  "Paths": {
    "DataDir": "C:\\ProgramData\\Jellyfin\\data",
    "ConfigDir": "C:\\ProgramData\\Jellyfin\\config",
    "CacheDir": "D:\\Cache\\Jellyfin",
    "LogDir": "C:\\ProgramData\\Jellyfin\\logs",
    "TempDir": "D:\\Temp\\Jellyfin",
    "WebDir": "C:\\Program Files\\Jellyfin\\web"
  }
}

Development Configuration

{
  "Paths": {
    "DataDir": "./dev-data",
    "ConfigDir": "./dev-config",
    "CacheDir": "./dev-cache",
    "LogDir": "./dev-logs",
    "TempDir": "./dev-temp",
    "WebDir": "./wwwroot"
  }
}

Minimal Configuration (Using Defaults)

{
  "Paths": {
    "DataDir": "/custom/jellyfin/data"
  }
}

In this example, only DataDir is overridden. All other paths will use their default values or environment variables.

Partial Override with Environment Variables

startup.json:

{
  "Paths": {
    "DataDir": "/var/lib/jellyfin",
    "ConfigDir": "/etc/jellyfin"
  }
}

Environment variables:

export JELLYFIN_TEMP_DIR=/fast-storage/jellyfin-temp

Result: DataDir and ConfigDir come from the file, TempDir from environment variable, and all others use defaults.

Use Cases

1. Containerized Deployments

Docker Example: Create startup.json in your config volume:

{
  "Paths": {
    "DataDir": "/data",
    "ConfigDir": "/config",
    "CacheDir": "/cache",
    "LogDir": "/logs",
    "TempDir": "/temp"
  }
}

docker-compose.yml:

version: '3.8'
services:
  jellyfin:
    image: jellyfin/jellyfin
    volumes:
      - ./startup.json:/config/startup.json
      - jellyfin_data:/data
      - jellyfin_cache:/cache
      - jellyfin_logs:/logs
      - jellyfin_temp:/temp

2. Multiple Instance Setup

Run multiple Jellyfin instances with different configurations:

Instance 1 (startup-prod.json):

{
  "Paths": {
    "DataDir": "/srv/jellyfin/prod/data",
    "ConfigDir": "/srv/jellyfin/prod/config",
    "LogDir": "/srv/jellyfin/prod/logs"
  }
}

Instance 2 (startup-test.json):

{
  "Paths": {
    "DataDir": "/srv/jellyfin/test/data",
    "ConfigDir": "/srv/jellyfin/test/config",
    "LogDir": "/srv/jellyfin/test/logs"
  }
}

3. Portable Installation

Create a portable Jellyfin installation with relative paths:

{
  "Paths": {
    "DataDir": "./data",
    "ConfigDir": "./config",
    "CacheDir": "./cache",
    "LogDir": "./logs",
    "TempDir": "./temp",
    "WebDir": "./web"
  }
}

4. Performance Optimization

Place different directories on different storage devices:

{
  "Paths": {
    "DataDir": "/mnt/hdd/jellyfin/data",
    "ConfigDir": "/mnt/ssd/jellyfin/config",
    "CacheDir": "/mnt/ssd/jellyfin/cache",
    "TempDir": "/mnt/nvme/jellyfin/temp",
    "LogDir": "/mnt/hdd/jellyfin/logs"
  }
}

Validation

When Jellyfin starts, it will log the configuration file being used:

Loaded startup configuration from: /path/to/startup.json

If the file has syntax errors, you'll see:

Warning: Failed to load startup configuration from /path/to/startup.json: [error message]

All resolved paths are logged at startup:

[INF] Program data path: /var/lib/jellyfin
[INF] Config directory path: /etc/jellyfin
[INF] Cache path: /var/cache/jellyfin
[INF] Log directory path: /var/log/jellyfin
[INF] Temp directory path: /var/tmp/jellyfin
[INF] Web resources path: /usr/share/jellyfin/web

Troubleshooting

Configuration File Not Found

If your configuration file isn't being loaded:

  1. Check the file is named exactly startup.json
  2. Verify it's in one of the search locations
  3. Check file permissions (must be readable)
  4. Look for typos in the JSON structure

Invalid JSON Syntax

Common JSON errors:

// ❌ Wrong - trailing comma
{
  "Paths": {
    "DataDir": "/var/lib/jellyfin",
  }
}

// ✅ Correct
{
  "Paths": {
    "DataDir": "/var/lib/jellyfin"
  }
}

// ❌ Wrong - single quotes
{
  "Paths": {
    'DataDir': '/var/lib/jellyfin'
  }
}

// ✅ Correct - double quotes
{
  "Paths": {
    "DataDir": "/var/lib/jellyfin"
  }
}

Path Resolution Order

Remember the priority:

  1. CLI argument beats everything
  2. Environment variable beats config file
  3. Config file beats defaults

To test which source is being used, try setting different values in each and check the startup logs.

Migration from Environment Variables

If you currently use environment variables, you can migrate to a config file:

Before (environment variables):

export JELLYFIN_DATA_DIR=/var/lib/jellyfin
export JELLYFIN_CONFIG_DIR=/etc/jellyfin
export JELLYFIN_CACHE_DIR=/var/cache/jellyfin
export JELLYFIN_LOG_DIR=/var/log/jellyfin

After (startup.json):

{
  "Paths": {
    "DataDir": "/var/lib/jellyfin",
    "ConfigDir": "/etc/jellyfin",
    "CacheDir": "/var/cache/jellyfin",
    "LogDir": "/var/log/jellyfin"
  }
}

Then remove the environment variables from your .bashrc, systemd service, or wherever they're defined.

Benefits

Advantages of File-Based Configuration

  1. Portability: Easy to copy configuration between systems
  2. Version Control: Track configuration changes in Git
  3. Documentation: Self-documenting with comments (in extended formats)
  4. Persistence: Survives system reboots and shell sessions
  5. Consistency: Same configuration across all instances
  6. No Shell Escaping: No need to worry about shell quoting rules
  7. Easy Editing: Simple text file, easy to modify
  8. Backup: Can be backed up with other configuration files

When to Use Each Method

Method Best For
Config File Production servers, containers, permanent installations
Environment Variables System-wide settings, CI/CD pipelines, user-specific overrides
Command Line Testing, one-time overrides, debugging

Security Considerations

  • Keep startup.json readable only by the Jellyfin user
  • Don't commit sensitive paths to public repositories
  • Use environment variables for secrets (like database passwords)
  • Consider using separate config files per environment (dev/staging/prod)

Example Setup Script

#!/bin/bash
# create-jellyfin-config.sh

cat > /etc/jellyfin/startup.json <<EOF
{
  "Paths": {
    "DataDir": "/var/lib/jellyfin",
    "ConfigDir": "/etc/jellyfin",
    "CacheDir": "/var/cache/jellyfin",
    "LogDir": "/var/log/jellyfin",
    "TempDir": "/var/tmp/jellyfin",
    "WebDir": "/usr/share/jellyfin/web"
  }
}
EOF

# Set proper permissions
chmod 644 /etc/jellyfin/startup.json
chown jellyfin:jellyfin /etc/jellyfin/startup.json

echo "Jellyfin startup configuration created at /etc/jellyfin/startup.json"

See Also