Skip to main content

How to Migrate Plex from Windows to Linux: What Most Guides Miss

Home Server Overhaul

Note that I was migrating from a plain Windows install to a containerised Linux install, but for this guide, this info should not matter.

The Official Guide

Update SQLite File Paths

  1. First backup your SQLite database for Plex, located here:
C:\Users\YOURUSER\AppData\Local\Plex Media Server\Plug-in Support\Databases\com.plexapp.plugins.library.db"
  1. Enter the Plex SQLite shell
"C:\Program Files\Plex\Plex Media Server\Plex SQLite.exe" "C:\Users\YOURUSER\AppData\Local\Plex Media Server\Plug-in Support\Databases\com.plexapp.plugins.library.db"

Note that Plex uses a custom implementation of SQLite… standard browsers might corrupt your file, or just not work.

  1. Replace Windows backslash with Linux forward slash
UPDATE media_parts SET file=REPLACE(file, '\', '/');
UPDATE section_locations SET root_path=REPLACE(root_path, '\', '/');
UPDATE media_streams SET url=REPLACE(url, '\', '/') WHERE url LIKE 'file://%';
  1. Replace library root paths
// First get all of your library root locations
SELECT root_path FROM section_locations;

// For each location, replace with the correct path
UPDATE section_locations SET root_path=REPLACE(root_path, 'D:/Path/To/Library1', '/data/library1');
UPDATE section_locations SET root_path=REPLACE(root_path, 'D:/Path/To/Library2', '/data/library2');
  1. Replace media part paths
// Inspect the format of the file paths
SELECT file FROM media_parts WHERE file != "" LIMIT 20;

// For each library above, ensure you correctly set the path here
UPDATE media_parts SET file=REPLACE(file, 'D:/Path/To/Library1', '/data/library1');
UPDATE media_parts SET file=REPLACE(file, 'D:/Path/To/Library2', '/data/library2');
  1. Replace media stream paths
// Note here we possibly have double and triple slash prefixes that must be replaced
UPDATE media_streams SET url=REPLACE(url, 'file://D:/Path/To/Library1', 'file:///data/library1');
UPDATE media_streams SET url=REPLACE(url, 'file:///D:/Path/To/Library1', 'file:///data/library1');
UPDATE media_streams SET url=REPLACE(url, 'file://D:/Path/To/Library2', 'file:///data/library2');
UPDATE media_streams SET url=REPLACE(url, 'file:///D:/Path/To/Library2', 'file:///data/library2');
  1. Replace metadata_item paths
UPDATE metadata_items SET guid=REPLACE(guid, 'file:///D:/Path/To/Library1', 'file:///data/library1');
UPDATE metadata_items SET guid=REPLACE(guid, 'file:///D:/Path/To/Library2', 'file:///data/library2');
  1. Final checks
// Check for any corruption
PRAGMA integrity_check;
// If errors, try a reindex
REINDEX;

// Vacuum db
VACUUM;

// Exit
.quit

Migrating Preferences

Windows Registry

Linux Preferences

<?xml version="1.0" encoding="utf-8"?>
<Preferences
  allowedNetworks="127.0.0.1,192.168.90.11"
  autoEmptyTrash="0"
  secureConnections="1"
  sendCrashReports="1"
  customConnections="https:/your.custom.domain:443"
  AcceptedEULA="1" 
  AnonymousMachineIdentifier="xxx-xxx"
  CertificateUUID="xxx-xxx"
  CertificateVersion="3"
  CloudSyncNeedsUpdate="0"
  DatabaseCacheSize="4000"
  DisableTLSv1_0="1"
  DlnaEnabled="0"
  DvrIncrementalEpgLoader="0"
  EnableIPv6="0"
  FSEventLibraryPartialScanEnabled="0"
  FSEventLibraryUpdatesEnabled="0"
  FriendlyName="Name-Of-Your-Plex-Server"
  GlobalMusicVideoPathMigrated="1"
  LanNetworksBandwidth="192.168.90.11/24"
  LanguageInCloud="1"
  LastAutomaticMappedPort="0"
  LogVerbose="0"
  MachineIdentifier="xxx-xxx"
  ManualPortMappingMode="1"
  ManualPortMappingPort="32400"
  MergedRecentlyAdded="0"
  MetricsEpoch="1"
  MinutesAllowedPaused="30"
  OldestPreviousVersion="legacy"
  PlexOnlineHome="0"
  PlexOnlineMail="your@email.com"
  PlexOnlineToken="token_from_previous_install"
  PlexOnlineUsername="your_plex_username"
  PreferredNetworkInterface="eth0"
  ProcessedMachineIdentifier="xxx-xxx"
  PubSubServer="xxx"
  PubSubServerPing="xx"
  PubSubServerRegion="lhr"
  PublishServerOnPlexOnlineKey="1"
  PushNotificationsEnabled="1"
  RelayEnabled="0"
  ScannerLowPriority="1"
  ScheduledLibraryUpdateInterval="86400"
  ScheduledLibraryUpdatesEnabled="0"
  TranscodeCountLimit="3"
  TranscoderCanOnlyRemuxVideo="0"
  TranscoderH264BackgroundPreset="medium"
  TranscoderQuality="0"
  TranscoderTempDirectory="/tmp/transcode"
  TranscoderThrottleBuffer="1800"
  WanPerUserStreamCount="2"
  WanTotalMaxUploadRate="20000"
  WebHooksEnabled="0"
/>