The Jellyfin default port is 8096 over TCP: browse to http://your-server-ip:8096 and you get the web UI and the API every client app talks to. HTTPS defaults to 8920/tcp but stays off until you supply a certificate. Client discovery uses 7359/udp, and the DLNA plugin uses 1900/udp. Only 8096 is required.
Those numbers come straight from the code. Jellyfin’s NetworkConfiguration.cs defines DefaultHttpPort = 8096 and DefaultHttpsPort = 8920, and the official Docker image declares EXPOSE 8096 and nothing else. The more useful question is which of the four ports to publish, open or move, and the honest answer is fewer than you’d guess.
What ports does Jellyfin use, and which do you need?
You need 8096/tcp and nothing else for a working server. 7359/udp is a LAN convenience that lets apps find the server without typing an address. 8920/tcp only matters if Jellyfin terminates TLS itself, which it mostly shouldn’t. 1900/udp only matters if you install the DLNA plugin and run host networking.
| Port | Protocol | Purpose | On by default? | Can you change it? | Publish in Docker? |
|---|---|---|---|---|---|
| 8096 | TCP | HTTP web UI and API | Yes | Yes | Yes |
| 8920 | TCP | HTTPS | No, needs a certificate | Yes | Rarely |
| 7359 | UDP | Client auto-discovery | Yes | No | Optional, LAN only |
| 1900 | UDP | DLNA (SSDP) discovery | Only with the DLNA plugin | No | Use host networking instead |
The Jellyfin networking docs mark 8096 and 8920 as configurable and 7359 as fixed. The DLNA docs say 1900/udp can’t be moved because UPnP expects it there, that DLNA left the base install in 10.9 for a first-party plugin, and that a Docker install needs host mode because bridged containers don’t receive the discovery broadcasts.
That last point catches people using the LinuxServer.io image, whose compose example lists 1900:1900/udp as an optional published port. By the official docs’ account, publishing it on a bridge network does not get you working DLNA. If you want DLNA, switch to network_mode: host, and read the Compose host networking guide first, because it changes how every other port on the box behaves.
One thing missing from the list: automatic router port forwarding. The EnableUPnP property still exists in the config class but is marked [Obsolete("No longer supported")], so Jellyfin will not open anything on your router for you. Any port that reaches the internet got there because you put it there.
Should you use port 8920 for HTTPS?
Not on a typical homelab. Jellyfin’s networking docs say “it is strongly recommended to handle HTTPS termination separately on a reverse proxy,” and they strongly discourage self-signed certificates. Built-in HTTPS leaves you owning the certificate file, its password and every renewal. A proxy on 443 automates Let’s Encrypt and keeps Jellyfin on plain 8096 behind it.
Pick the proxy you’ll actually maintain: Nginx Proxy Manager if you want a web form, Traefik if you’d rather keep routing in compose labels. Either way the proxy forwards to jellyfin:8096 across a shared Docker network, and you add the proxy’s address under Jellyfin’s Known Proxies setting. The docs warn that external access through a reverse proxy only works if known proxies are set up correctly, so it’s the first thing to check when a proxied Jellyfin half-works.
How do you change the Jellyfin port in Docker?
Change the host side of the port mapping and leave the container side at 8096. In compose, "8097:8096" makes Jellyfin reachable at http://your-server-ip:8097 while the process inside keeps listening where the image expects it. No dashboard setting, no config file, just docker compose up -d to recreate the container.
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
restart: unless-stopped
user: 1000:1000
ports:
- "8097:8096/tcp" # host 8097 -> container 8096
- "7359:7359/udp" # optional, LAN discovery only
volumes:
- ./config:/config
- ./cache:/cache
- /mnt/media:/media:ro
The left number is always the host. Docker’s port publishing docs describe -p 8080:80 as host port 8080 to container port 80, and compose reads the same way.
Why not change the internal port instead? Because the image’s healthcheck is pinned to it. The official Dockerfile sets ENV HEALTHCHECK_URL=http://localhost:8096/health and curls it every 30 seconds. Move Jellyfin to 8097 inside the container and the server works fine while docker ps reports it unhealthy, which will confuse you, and any autoheal container, nine months from now when you’ve forgotten you did it.
Two related tweaks worth knowing:
- Bind to one address. Docker publishes to every host address by default, and its docs say plainly that publishing container ports “is insecure by default.”
"127.0.0.1:8096:8096"limits access to the host itself;"192.168.1.20:8096:8096"pins it to one LAN interface. - Skip publishing entirely behind a proxy. If the reverse proxy shares a Docker network with Jellyfin, it reaches
jellyfin:8096by service name and no host port is needed. The Compose networking guide explains the service-name DNS that makes this work.
If the host runs ufw, note that Docker’s firewall docs call Docker and ufw incompatible: published container traffic gets “diverted before it goes through the ufw firewall settings.” A ufw deny 8096 does not hide a published port. Binding it to a specific address does.
When do you have to change Jellyfin’s internal port?
Only when there’s no port mapping to edit: host networking, which DLNA requires, or a bare-metal package install where another service already owns 8096. In those cases you change Jellyfin’s own HTTP port, in the dashboard under Networking or in network.xml, then restart the server so it binds to the new number.
If the dashboard is unreachable because of the conflict, edit the file directly. The element is InternalHttpPort, and the file lives in one of two places:
- Official Docker image:
./config/config/network.xmlon the host, because the image setsJELLYFIN_CONFIG_DIR=/config/config. - Debian/Ubuntu packages:
/etc/jellyfin/network.xml, the file a Jellyfin forum thread edited to move a 10.11.5 server to 8097.
Stop the container before editing so a shutdown doesn’t write the old value back. If an older config shows HttpServerPortNumber instead of InternalHttpPort, that’s the pre-rename element; issue #10905 documents the rename and an upgrade where the migration didn’t carry the setting across. The same file also carries PublicHttpPort and PublicHttpsPort, defaulting to 8096 and 8920 like their internal twins.
On host networking, override the healthcheck to match the new port. The extra_hosts line comes from the official container docs, which note it may be needed for the healthcheck to pass in host mode:
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
restart: unless-stopped
network_mode: host
user: 1000:1000
environment:
- HEALTHCHECK_URL=http://localhost:8097/health
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./config:/config
- ./cache:/cache
- /mnt/media:/media:ro
There’s no ports: block because host mode doesn’t use one; Jellyfin binds straight to the host’s interfaces.
Should you port-forward 8096 to the internet?
No. Jellyfin’s networking docs list direct forwarding as “(not recommended!)” and call opening a port straight to the internet insecure. Port 8096 is plain HTTP, so a forward sends logins and session tokens across the internet unencrypted. Use a VPN, or a reverse proxy on 443 with a real certificate.
The realistic options for an N100 mini-PC and a handful of viewers:
- Tailscale or WireGuard. Nothing is exposed and Jellyfin stays on 8096. The cost is that every client device needs the VPN, and a smart TV at a relative’s house is where that plan usually dies.
- Reverse proxy plus a 443 forward. One port open, a Let’s Encrypt certificate, Known Proxies set. Works with every client app. You are now running a public web service, so keep Jellyfin updated.
- Cloudflare Tunnel. Fine for many services, a poor fit for this one. Cloudflare’s service-specific terms say non-Enterprise customers must use paid services such as Stream “in order to serve video” through its CDN. The Cloudflare Tunnel guide covers what it is good for.
Why can’t you reach Jellyfin on port 8096?
Almost always one of four things: the container isn’t running, another service already holds the port, a firewall drops the traffic, or you’re using the wrong address or a remapped port. Check them in that order from the host’s shell before blaming the client app, starting with whether Jellyfin answers locally.
docker compose ps # running, and healthy?
docker compose logs --tail=50 jellyfin # startup or bind errors
sudo ss -tlnp | grep 8096 # who owns the port
curl -fsS http://localhost:8096/health # use your host port if remapped
If the local curl works but other machines can’t connect, it’s a firewall or a bind address. A bare-metal install on a firewalld host needs sudo firewall-cmd --permanent --add-port=8096/tcp followed by sudo firewall-cmd --reload. If docker compose up fails with “port is already allocated”, something else claimed 8096 first; remap the host side as shown above. If apps can’t discover the server, remember 7359/udp discovery stays on the local subnet. Type the URL in and move on.
For everything beyond ports, the Jellyfin Docker Compose guide covers volumes and permissions, and the hardware transcoding walkthrough covers the GPU side.
FAQ
is jellyfin port 8096 tcp or udp
Port 8096 is TCP. It carries plain HTTP for the web interface and the API that every Jellyfin client uses, so a compose mapping of 8096:8096/tcp, or just 8096:8096 since TCP is Docker’s default, is correct. The only UDP ports Jellyfin uses are 7359 for client discovery and 1900 for the optional DLNA plugin.
can i run jellyfin on port 80
Yes, map the host’s port 80 to the container’s 8096 with "80:8096" and Jellyfin answers without a port number in the URL. It is still unencrypted HTTP, though, and port 80 is usually better spent on a reverse proxy that redirects to HTTPS on 443 and serves Jellyfin alongside your other services.
do i need to open port 7359 for jellyfin
No, port 7359/udp is optional. It only lets Jellyfin apps on the same local network find the server automatically, and it does not reach across the internet or into other subnets. If you skip it, enter the server address manually in each app once; playback and everything else runs over 8096.
can jellyfin and plex run on the same server
Yes, their main ports don’t collide: Jellyfin listens on 8096/tcp and Plex Media Server on 32400/tcp, according to Plex’s support documentation. The one overlap is 1900/udp, which both use for DLNA discovery, so if you need DLNA at all, let one server handle it.