Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ErsatzTV/legacy/llms.txt

Use this file to discover all available pages before exploring further.

ErsatzTV Legacy accumulates data over time — transcoded segments, artwork cache files, orphaned database records, and soft-deleted media items. Periodic maintenance keeps the database compact, frees disk space in the config volume, and ensures the application continues to perform well as your library grows. Most maintenance actions are available through a dedicated REST API at /api/maintenance, and the SQLite database can be compacted directly from the command line when disk reclamation is needed.

Maintenance API Endpoints

The maintenance controller exposes three endpoints. All are available immediately after startup with no authentication required by default (apply reverse-proxy authentication if your instance is publicly accessible).
MethodEndpointDescription
GET/api/maintenance/gcTrigger a .NET garbage collection pass to release unused managed memory. Accepts an optional ?force=true query parameter to perform an aggressive collection (equivalent to GC.Collect() with compaction).
POST/api/maintenance/empty_trashPermanently delete all media items that have been moved to the trash. Returns 200 OK on success or 500 with a plain-text error body if the operation fails.
POST/api/maintenance/clean_artworkQueue a background job to delete orphaned artwork records and files from the artwork cache. Accepts an optional ?limit=100000 query parameter to cap the number of records processed in one run.

Garbage Collection

Calling the GC endpoint is a low-risk operation that can be done at any time without stopping ErsatzTV. It is rarely necessary — the .NET runtime manages memory automatically — but can be useful after a large library import or playout rebuild if you notice memory usage is elevated and has not returned to baseline.
# Soft GC pass
curl -X GET http://localhost:8409/api/maintenance/gc

# Aggressive GC pass
curl -X GET "http://localhost:8409/api/maintenance/gc?force=true"

Emptying the Trash

When ErsatzTV detects that media files have been removed from disk or a library source has been disconnected, those items are not immediately deleted from the database — they are moved to a soft-deleted “trash” state. This preserves playout history and schedule references while giving you a chance to review what was removed. Emptying the trash permanently removes all trashed items from the database. This action is irreversible, so confirm the trashed items are genuinely gone before proceeding.
curl -X POST http://localhost:8409/api/maintenance/empty_trash

Cleaning the Artwork Cache

The artwork cache stores poster images, thumbnails, fan art, logos, and watermarks downloaded from your media server integrations. Over time, artwork associated with deleted media items can become orphaned — the file exists in the cache folder but no database record references it. The clean_artwork endpoint queues a background job (processed by the worker service) that:
  1. Identifies actors with no remaining metadata references and deletes them.
  2. Identifies artwork records with no remaining media references and deletes them and their cache files.
  3. Removes empty subdirectories from the artwork cache folder.
Orphaned artwork is also cleaned automatically on an hourly schedule. When the automated job completes cleanly, you will see these messages in the logs:
No orphaned actors to delete
No orphaned artwork to delete
Once you see both messages, the database and artwork cache are in sync and it is safe to run a SQLite VACUUM to reclaim disk space (see below).
# Clean up to 100,000 orphaned records (default)
curl -X POST http://localhost:8409/api/maintenance/clean_artwork

# Clean a smaller batch (useful on low-memory devices)
curl -X POST "http://localhost:8409/api/maintenance/clean_artwork?limit=5000"

SQLite Database Maintenance

ErsatzTV Legacy stores all configuration, schedule data, playout history, media metadata, and channel settings in a SQLite database at ersatztv.sqlite3 in the config folder (i.e. /config/ersatztv.sqlite3 in Docker). SQLite uses a Write-Ahead Log (WAL) alongside the main database file — after large deletions (such as removing an Emby or Jellyfin library, or emptying the trash), the WAL can hold a significant amount of data that has not yet been checkpointed back into the main file. Running a WAL checkpoint followed by a VACUUM compacts the database and reclaims the disk space freed by deletions.
You must stop ErsatzTV Legacy before running VACUUM. SQLite does not allow an exclusive lock (required for VACUUM) while the application has the database open. Running VACUUM against a live database will either fail immediately or, in the worst case, corrupt the database file. Confirm the container is stopped before proceeding.

When to Run VACUUM

Run the SQLite VACUUM procedure after any of the following events:
  • Removing a large Emby or Jellyfin library from ErsatzTV.
  • Emptying the trash after a bulk media deletion.
  • Cleaning orphaned artwork (after seeing No orphaned actors to delete and No orphaned artwork to delete in the logs).
  • Noticing that the database file (ersatztv.sqlite3) is unexpectedly large relative to your current library size.

Reclaiming Disk Space with SQLite

1

Confirm artwork cleanup is complete

Before vacuuming, trigger the artwork cleanup API and wait for the background job to complete. Monitor Settings → Logs until you see both No orphaned actors to delete and No orphaned artwork to delete. This ensures that all orphaned records are removed from the database before compaction.
curl -X POST http://localhost:8409/api/maintenance/clean_artwork
2

Stop ErsatzTV Legacy

Stop the container before touching the database file.
docker compose stop ersatztv
# or, if using docker run:
docker stop ersatztv
3

Navigate to the config directory

Access the config volume on the host. If you used the default named volume from the Compose file, find its mount point with:
docker volume inspect ersatztv
Then change to that directory (the Mountpoint value), or use docker run --rm -v ersatztv:/data -w /data to run commands against the volume directly.
4

Run WAL checkpoint and VACUUM

Execute the following two SQLite pragmas in a single command. The PRAGMA wal_checkpoint(TRUNCATE) flushes and truncates the WAL file; VACUUM rewrites the main database file to reclaim freed space.
sqlite3 ersatztv.sqlite3 'PRAGMA wal_checkpoint(TRUNCATE); VACUUM;'
A VACUUM on a large database (several gigabytes) may take several minutes. The command will return to the prompt when complete.
5

Restart ErsatzTV Legacy

Once VACUUM completes, restart the container normally.
docker compose start ersatztv
# or:
docker start ersatztv
ErsatzTV will reopen the database and resume normal operation.

MySQL Support

For users who prefer MySQL over SQLite (for example, when hosting ErsatzTV on a server that already runs MySQL and want centralised database management), ErsatzTV Legacy includes the ErsatzTV.Infrastructure.MySql project. MySQL support allows the same ErsatzTV application to store all data in a MySQL or MariaDB instance instead of the local SQLite file.
MySQL configuration is not yet documented here — if you are using MySQL, refer to the ErsatzTV.Infrastructure.MySql project in the source repository for the connection string format and any additional environment variables required.
When using MySQL, the SQLite-specific VACUUM procedure does not apply. Use your MySQL server’s own tooling (OPTIMIZE TABLE, mysqlcheck) for equivalent table compaction.

Backup Recommendations

The entire /config directory is the single source of truth for your ErsatzTV installation. Back it up regularly, especially before upgrades. It contains:
PathContents
/config/ersatztv.sqlite3Main database — all configuration, schedules, metadata, playout history
/config/ersatztv.sqlite3-walSQLite Write-Ahead Log (only present when the application is running or was not cleanly shut down)
/config/logs/Rolling daily log files
/config/cache/Artwork cache — can be rebuilt from scratch but takes time to repopulate from media servers
/config/search/Lucene search index — can be rebuilt from Settings → Libraries → Rebuild Search Index
/config/plex-secrets.jsonPlex authentication tokens
/config/jellyfin-secrets.jsonJellyfin authentication tokens
/config/emby-secrets.jsonEmby authentication tokens
The artwork cache (/config/cache/) is the largest component of the config directory and is fully rebuildable. If you are space-constrained on your backup destination, you can safely exclude the cache/ subfolder and accept that artwork will need to be re-downloaded after a restore. The database and secrets files are the critical items to protect.
A minimal Docker backup using docker run:
docker run --rm \
  -v ersatztv:/config:ro \
  -v /backup:/backup \
  busybox \
  tar czf /backup/ersatztv-$(date +%Y%m%d).tar.gz \
    --exclude=/config/cache \
    --exclude=/config/search \
    /config

Build docs developers (and LLMs) love