├── README.md ├── nginx.conf └── plex.conf /README.md: -------------------------------------------------------------------------------- 1 | Plex Load Balancer 2 | ================= 3 | 4 | NOTE: This is super super beta. I did have it running without issue for 5 | roughly a day but just recently I started running into issues with the slave 6 | complaining a lot about not being able to write to the database and seemingly 7 | crashing because of it. 8 | 9 | This nginx configuration effectively load balances the Plex Transcoder across 10 | multiple machines. 11 | 12 | Environment Configuration 13 | ------------------------- 14 | 15 | The master Plex server has read/write access to the database. The slaves, on 16 | the other hand, do not. The master server is configured like any normal Plex 17 | server only the application data is hosted on an external share (could be local, 18 | but you'd have to mount it from the slaves to access it). 19 | 20 | The slaves mount the external Plex application data as read only. The exact 21 | flags that I used are: 22 | 23 | //nas/cache on /mnt/cache type cifs (ro,relatime,vers=1.0,cache=strict,domain=TOWER,uid=998,forceuid,gid=997,forcegid,addr=10.0.19.142,file_mode=0777,dir_mode=0777,nounix,serverino,rsize=61440,wsize=65536,actimeo=1) 24 | 25 | Where uid and gid are the group and user id's of plex. You can determine that 26 | with: 27 | 28 | sudo -u plex id 29 | 30 | I believe that the only necessary mount flags would be: 31 | 32 | ro, uid=998, gid=997, file_mode=0777, dir_mode=0777 33 | 34 | Once the share is mounted, you have to symlink the appropriate files/folders to 35 | the slaves Plex application data directory. The symlinks are set up as follows: 36 | 37 | ![ScreenShot](http://i.imgur.com/9sRbK9A.png) 38 | 39 | The Preferences.xml should be the same, but should be copied from the r/o 40 | directory. This allows you to modify configs on the slaves, but still maintain 41 | the same Plex "server ID" that is used by plex.tv 42 | 43 | The reason we get so granular with the symlinks is because we don't want to 44 | symlink the "com.plexapp.plugins.library.db-shm" or 45 | "com.plexapp.plugins.library.db-shm" files. Those files are the temporary 46 | database files that need to be created by the local Plex instance. If Plex can't 47 | read or write to those files it will refuse to start. When Plex attempts to 48 | flush those files out to the main database, it throws errors in the log, but 49 | nothing mission critical as far as I can tell. 50 | 51 | Note: This whole thing is setup behind a NAT. Plex thinks it's going to a 52 | single server when in reality it is being managed by nginx. I currently have 53 | everything come in as follows: 54 | 55 | Internet --:32400--> Router --:80--> nginx --:32400--> appropriate Plex instance 56 | 57 | Issues 58 | ------ 59 | 60 | There are still some weird issues with files not wanting to play. This is 61 | something I believe can be remedied by a more granular nginx config file. I'm 62 | not versed enough in nginx to really determine what needs to be load balanced. 63 | That's why I'm posting it up here :) 64 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log; 5 | 6 | pid /run/nginx.pid; 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | sendfile on; 23 | keepalive_timeout 0; 24 | index index.html index.htm; 25 | include /etc/nginx/conf.d/*.conf; 26 | 27 | # The Plex IPs you with to load balance between. 28 | upstream plextranscodelb{ 29 | # Load balances based on source IP. One IP will be mapped to the 30 | # appropriate server. (So we don't start streaming and sending status 31 | # updates to a different server) 32 | ip_hash; 33 | server 127.0.0.1:32400; 34 | server 10.0.19.132:32400; 35 | } 36 | 37 | server{ 38 | listen 0.0.0.0:80; 39 | 40 | # Load balances only the /video/* location 41 | location /video/ { 42 | include plex.conf; 43 | proxy_pass http://plextranscodelb; 44 | } 45 | 46 | # If you uncomment the following block, play status is not updated 47 | # properly. 48 | # 49 | # location /:/ { 50 | # include plex.conf; 51 | # proxy_pass http://plextranscodelb; 52 | # } 53 | 54 | # Defaults all output to localhost (Master Plex Server) 55 | location / { 56 | include plex.conf; 57 | proxy_pass http://127.0.0.1:32400; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /plex.conf: -------------------------------------------------------------------------------- 1 | proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; 2 | proxy_redirect off; 3 | proxy_buffering off; 4 | proxy_set_header Host $host; 5 | proxy_set_header X-Real-IP $remote_addr; 6 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 7 | proxy_set_header X-Forwarded-Proto $scheme; 8 | 9 | # Required for Websockets 10 | proxy_http_version 1.1; 11 | proxy_set_header Upgrade $http_upgrade; 12 | proxy_set_header Connection "upgrade"; 13 | proxy_read_timeout 36000s; # Timeout after 10 hours 14 | --------------------------------------------------------------------------------