[READ-ONLY] Mirror of https://github.com/FoxxMD/blog. blog.foxxmd.dev
0

Configure Feed

Select the types of activity you want to include in your feed.

First draft of plex docker access

FoxxMD (Sep 5, 2024, 1:14 PM EDT) 8db0cd87 40a48188

+248
+248
_posts/2024-09-05-plex-docker-remote-access.md
··· 1 + --- 2 + title: Plex Remote Access with Docker Compose 3 + description: >- 4 + Configuring Plex in Docker to work with Remote Access 5 + author: FoxxMD 6 + date: 2024-09-05 12:00:00 -0400 7 + categories: [Tutorial] 8 + tags: [plex, docker, iplan, networking] 9 + pin: false 10 + --- 11 + 12 + **So, you are running Plex in Docker and thought [Remote Access](https://support.plex.tv/articles/200289506-remote-access/) would be easy.** 13 + 14 + ![Captain America](https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMGdhZnlmbXdsc2VvYWM4Z3J1aTZseTd1ZjdzNWM1ZGV1MWNzNW8zZSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/5hbbUWcuvtoJGx5fQ4/giphy-downsized.gif){: width="650" height="325" } 15 + 16 + Whether it works for you or not seems to be like rolling dice. Here's what I learned, and the hoops you'll need to jump through, to _maybe_ get Remote Access working when running Plex with docker (compose). 17 + 18 + ## What Plex Wants 19 + 20 + ### Forwarded Port 21 + 22 + It needs ingress into your network so it can reach your hosted Plex server. This is the easiest part. As long as you aren't behind a NAT/CGNAT this is as simple as forwarding a port on your router to the machine where Plex is hosted. The plot thickens below though... 23 + 24 + ### Unrestricted Port Access 25 + 26 + You'll find countless solutions on Reddit and in google searches recommending that Plex **not** be in a container using [bridge networking](https://docs.docker.com/engine/network/drivers/bridge/) because it needs access to many ports. While there are known ports that can be mapped it seems Plex chooses to use random ports for reachability as well. From `Plex Media Server.log`: 27 + 28 + ``` 29 + Sep 04, 2024 22:21:43.080 [140124105521976] INFO - [Req#63] [PlexRelay] Allocated port 26243 for remote forward to 127.0.0.1:32401 30 + Sep 04, 2024 22:21:43.161 [140124105521976] INFO - [Req#79] [PlexRelay] Allocated port 18837 for remote forward to 127.0.0.1:32401 31 + Sep 04, 2024 22:21:43.553 [140124105521976] WARN - [Req#ab] MyPlex: attempted a reachability check but we're not yet mapped. 32 + Sep 04, 2024 22:21:43.621 [140124103150392] WARN - [Req#ba] MyPlex: attempted a reachability check but we're not yet mapped. 33 + ``` 34 + 35 + ### Private IP on First Interface 36 + 37 + Most importantly (and most annoyingly) **Plex listens on the first listed network interface in the container.** You can determine what this address by checking the `Private IP` on the Remote Access settings page. Alternatively, use `ifconfig` in the container (installed with `apt install net-tools`) to see all interfaces available in the container. 38 + 39 + If this interface is not the one that has forwarded traffic from your router then Plex will consider your server as unreachable and fallback to Relay (if you have it enabled). This is especially infuriating since it could just listen on `0.0.0.0`, to all interfaces, to get that traffic and establish a direction connection. 40 + 41 + ## What You Need 42 + 43 + #### Host Networking? 44 + 45 + If you're familiar with docker/compose your first thought might be "Why can't I just use [host networking](https://docs.docker.com/engine/network/drivers/host/)?" and honestly this might work for you. You'll fix port access and don't have to worry about bridge networking at all. Unfortunately, this is also dependent on the [correct interface being first on your host.](#private-ip-on-first-interface) If it isn't first there's nothing you can do about it as host networking mode gives up all networking control for the container. Short of re-naming/ordering the interfaces on your host machine this is not a situation that can be fixed. 46 + 47 + If you try host networking and it works for you, then more power to you. You can stop reading now and should be good to go. 48 + 49 + If your interfaces are not the correct order or you just want more reproducibility for the future, read on... 50 + 51 + ### IPvlan Network 52 + 53 + The solution to unfettered port access and one interface, in isolation, is [IPvlan networking.](https://docs.docker.com/engine/network/drivers/ipvlan/) This allows us to give our Plex container its own IP address on the LAN without any port restrictions. It also means that, by itself, there is only one interface attached to the container so Plex will always use the correct Private IP. 54 + 55 + > Use caution when setting up ipvlan and assigning an IP address to your container. Since you are manually setting these there is the potential for address collision which will cause serious issues for your network. Ideally you should use a subnet not in use by the rest of your LAN or reserve the IP address on your router so it can't be assigned anywhere else. 56 + {: .prompt-warning } 57 + 58 + Find the parent interface your ipvlan will communicate on by using `ifconfig` or `ip a show`. Look for the interface with the IP address of the host machine on your LAN, EX `inet 192.168.0.150/24`, and then use the interface name given for that entry, IE `eth0`. 59 + 60 + ```yaml 61 + services: 62 + plex: 63 + container_name: plex 64 + image: linuxserver/plex:latest 65 + # ... 66 + networks: 67 + plexnet: 68 + # An address you manually assign here 69 + ipv4_address: 192.168.0.233 70 + # ... 71 + networks: 72 + plexnet: 73 + driver: ipvlan 74 + driver_opts: 75 + # the interface we found above 76 + parent: eth0 77 + ipvlan_mode: l2 78 + ipam: 79 + config: 80 + # same subnet and gateway as the interface we found above 81 + - subnet: 192.168.0.0/24 82 + gateway: 192.168.0.1 83 + ``` 84 + 85 + Recreate your stack to get the network to be created (and any time you edit it): 86 + 87 + ```bash 88 + docker compose down 89 + docker compose up 90 + ``` 91 + 92 + Inspecting the container `docker container inspect plex` should result in a Networking setting that looks similar to this: 93 + 94 + ```json 95 + { 96 + "Networks": { 97 + "plexnet": { 98 + "IPAMConfig": { 99 + "IPv4Address": "192.168.0.233" 100 + }, 101 + "Links": null, 102 + "Aliases": [ 103 + "plex", 104 + "plex" 105 + ], 106 + "MacAddress": "", 107 + "DriverOpts": null, 108 + "NetworkID": "3b63c4cb58d336307feba0798a5209f0d2c1547ccf292103127412697e173c57", 109 + "EndpointID": "23af84f3e64d04ec7396dcff121412119ae982eb94769f7e44c742e77823a0e6", 110 + "Gateway": "192.168.0.1", 111 + "IPAddress": "192.168.0.233", 112 + "IPPrefixLen": 24, 113 + "IPv6Gateway": "", 114 + "GlobalIPv6Address": "", 115 + "GlobalIPv6PrefixLen": 0, 116 + "DNSNames": [ 117 + "plex", 118 + "79fa89e12c61" 119 + ] 120 + }, 121 + 122 + } 123 + } 124 + ``` 125 + 126 + At this point you only need to [change the forwarded IP address](#forwarded-port) in your router to newly assigned IP and you should be good to go. 127 + 128 + Now...the downside of using IPvlan is that **the new interface is isolated from all other docker networks.** Even though from your host machine you can access Plex at `192.168.0.233` you will find that this is not the case from any other container. This is problematic if you use any other services with Plex such as [Tautulli](https://tautulli.com/) or [Overseer](https://overseerr.dev/). 129 + 130 + To fix this we need to re-introduce bridge networking but with a small quirk... 131 + 132 + ### Bridge Network with Priority 133 + 134 + As mentioned in the previous section, you only need to complete this step if you have other containers/services in your compose stack that need access to Plex. 135 + 136 + The issue with this is that we still have to deal with that [pesky first interface problem Plex has.](#private-ip-on-first-interface) Docker does not have an explicit way to name interfaces within a container, or give priority to attaching, but it _does_ have This One Weird Trick™️ for working around this problem. Thanks to [h4ck3rk3y](https://github.com/moby/moby/issues/25181#issuecomment-1410883805) and [limscoder](https://github.com/moby/moby/issues/35221#issuecomment-537102824) in the Docker github issue comments for discovering that Docker attaches interfaces **based on alphabetically order of their names!** 137 + 138 + Using this trick we can now _force_ our ipvlan interface to be attached first by giving it a name alphabetically earlier than our bridge (default) network: 139 + 140 + ```yaml 141 + services: 142 + plex: 143 + image: linuxserver/plex:latest 144 + # ... 145 + networks: 146 + plexnet: 147 + ipv4_address: 192.168.0.233 148 + default: # specify we want our container attached to default (bridge) network, as well 149 + # ... 150 + networks: 151 + plexnet: 152 + name: aaa # give an early alphabetical name 153 + driver: ipvlan 154 + driver_opts: 155 + parent: ens18 156 + ipvlan_mode: l2 157 + ipam: 158 + config: 159 + - subnet: 192.168.0.0/24 160 + gateway: 192.168.0.1 161 + default: 162 + name: zzz # specify default network name, later than plexnet name 163 + ``` 164 + 165 + Now when we inspect our container: 166 + 167 + ```json 168 + { 169 + "Networks": { 170 + "aaa": { 171 + "IPAMConfig": { 172 + "IPv4Address": "192.168.0.233" 173 + }, 174 + "Links": null, 175 + "Aliases": [ 176 + "plex", 177 + "plex" 178 + ], 179 + "MacAddress": "", 180 + "DriverOpts": null, 181 + "NetworkID": "3b63c4cb58d336307feba0798a5209f0d2c1547ccf292103127412697e173c57", 182 + "EndpointID": "23af84f3e64d04ec7396dcff121412119ae982eb94769f7e44c742e77823a0e6", 183 + "Gateway": "192.168.0.1", 184 + "IPAddress": "192.168.0.233", 185 + "IPPrefixLen": 24, 186 + "IPv6Gateway": "", 187 + "GlobalIPv6Address": "", 188 + "GlobalIPv6PrefixLen": 0, 189 + "DNSNames": [ 190 + "plex", 191 + "79fa89e12c61" 192 + ] 193 + }, 194 + "zzz": { 195 + "IPAMConfig": null, 196 + "Links": null, 197 + "Aliases": [ 198 + "plex", 199 + "plex" 200 + ], 201 + "MacAddress": "02:42:ac:0d:00:02", 202 + "DriverOpts": null, 203 + "NetworkID": "5fe40284188df02697e0437d4c3d6495b2ad379f167cb094a8873b32b00e3a83", 204 + "EndpointID": "c4a058c9543d546bbb752593a75221cc11f2c01601f4a601941c9d2e9a475810", 205 + "Gateway": "172.13.0.254", 206 + "IPAddress": "172.13.0.2", 207 + "IPPrefixLen": 24, 208 + "IPv6Gateway": "", 209 + "GlobalIPv6Address": "", 210 + "GlobalIPv6PrefixLen": 0, 211 + "DNSNames": [ 212 + "plex", 213 + "79fa89e12c61" 214 + ] 215 + } 216 + } 217 + } 218 + ``` 219 + 220 + We see it has two attached networks with the names we gave. Inspect `ifconfig` output from the container: 221 + 222 + ```shell 223 + # ifconfig 224 + eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 225 + inet 192.168.0.233 netmask 255.255.255.0 broadcast 192.168.0.255 226 + ether bc:24:11:06:95:d8 txqueuelen 0 (Ethernet) 227 + RX packets 40175 bytes 58455639 (58.4 MB) 228 + RX errors 0 dropped 2578 overruns 0 frame 0 229 + TX packets 36774 bytes 137290812 (137.2 MB) 230 + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 231 + 232 + eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 233 + inet 172.13.0.2 netmask 255.255.255.0 broadcast 172.13.0.255 234 + ether 02:42:ac:0d:00:02 txqueuelen 0 (Ethernet) 235 + RX packets 6790 bytes 586521 (586.5 KB) 236 + RX errors 0 dropped 0 overruns 0 frame 0 237 + TX packets 9632 bytes 2310195 (2.3 MB) 238 + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 239 + ... 240 + ``` 241 + 242 + we see that our ipvlan interface is listed first as eth0, so Plex grabs the correct interface to listen on. 243 + 244 + ## Conclusion 245 + 246 + This could all be avoided if Plex just listened on `0.0.0.0`. 247 + 248 + ![Obama](https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMzhuZzJtc2cwcndpaDU4bmp2aW05aGd0NGd0dGgxYjU3eXpsMml2MiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/pPhyAv5t9V8djyRFJH/giphy-downsized.gif){: height="325" }