Important
This uses Cloudflare for incoming connections, NordVPN for outgoing, and Google Auth for logging in. If you cannot figure those out with help from google then this might not be the setup for you!
Warning
I do not use all of these services, so not everything is guaranteed to work.
Note
This is the barebones setup for a media server, it does not include any config (although over time I may add more documentation and templates explaining what to do).
Every service uses a similar folder layout, this includes having a config folder inside the service folder for easier backup and configuration.
When one service depends on another it should only be started first (with a couple of exceptions that require them to be healthy first).
There are some included scripts for use within various services directly - you do not need to install python or have anything more than bash available on the server.
This has two networks defined in compose.yaml.
- The
internalnetwork does not have internet access, and is used for inter-service communication. All routing into the stack should come throughtraefikwhich acts as a bridge between the two. - The
externalnetwork allows for a service to contact the internet directly. (Ideally services should be using thehttp://vpn:8888service as an http(s) proxy instead.)
Important
The install.sh script is not usable yet, these other steps are always going to be manual!
It is advised to use VSCode or similar that does syntax highlighting (ie, colors) for the files you edit!
Duplicate the .env.example file as .env, all configuration needs to go in here.
Create an empty compose.override.yaml file, and copy the commented block of include: services into it, then to enable a service you can simply uncomment that line. For some services have a look for included template files that want copying into theit config/ folders and renaming.
- Add your email address as the
EMAILandWHITELISTin.env - Follow these instructions: https://developers.google.com/identity/protocols/oauth2
- Add the
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETin.env - Place a long random hexadecimal value in
OAUTH_SECRETin .env`- The best way is to use the output of
openssl rand -hex 16
- The best way is to use the output of
- Make an account if you haven't already.
- Buy a domain, or if you already have one you can transfer the domain servers accross.
- Set this as the
DOMAINin.env - Replace the
$DOMAINinPLEX_URLwith this.
- Set this as the
- Sign up for Zero Trust - you can choose the personal 0-cost.
- Go to Networks -> Tunnels
- Create a Tunnel, name it for your domain
- Copy the "Run the following command" suggestion, paste it as
CLOUDFLARED_TOKENin.envthen remove thecloudflared.exe service installprefix (including space). - Create 2 public hostnames, one to your domain, and one to
*at your domain- Both have a service of
https://traefik - Both have Advanced -> TLS -> Origin Server Name as your domain
- Both have Advanced -> TLS -> HTTP2 connection turned on
- Both have a service of
- Go back to Account Home, then click on your domain name.
- Under the Domain (Zone) settings go to SSL/TLS -> Overview, and enable Full encryption.
- Under DNS -> Records, create a CNAME entry for
*pointing at your domain. - Under DNS -> Settings, enable DNSSEC.
- Click on your Profile in the top right, go to your profile, then click on API Tokens on the left.
- Create a Token using the Edit zone DNS template
- Allow it access to your domain under Zone Resources
- Copy the token to
CLOUDFLARE_APIin.env
- Make an account, click on NordVPN on the left, scroll down to API Key, create one and copy to
VPN_PRIVATE_KEYin.env
- Make sure you set
PATH_DOWNLOADSto a good download folder, this will be used by multiple services as a consistent location. - Place all of your media paths in the
PATH_XYZvariables in.env- add more as needed.
- Use these instructions to get
PLEX_TOKENin.env- https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/ - Ensure you have all the correct paths for Plex from the Media Paths section above. Internally we're going to map them all under the
/data/folder. - In your current Plex server go to Settings -> Library, and disable (and save) the "Empty trash automatically after every scan" option!
- Stop Plex Media Server!
- Copy (move is risky, but it's your library) the Plex Config folder starting at
Libraryintoplex/config/- so there is a folder in there calledLibrary.
This is a list of all services, and the profiles they are started with. Note that only the core profiles are included in the compose.yaml file, everything else needs to be manually added.
| NAME | PROFILE | DESCRIPTION |
|---|---|---|
| cloudflared | core | Cloudflare tunnel |
| deunhealth | core | Bring unhealthy containers back up |
| error-pages | core | Error pages |
| socket-proxy | core | Secure access to the docker socket |
| tinyauth | core | OAuth via Google |
| traefik | core | HTTP routing |
| vpn | core | VPN + HTTP Proxy + Socks5 Proxy |
| watchtower | core | Auto-update containers |
| adguardhome | network | Ads & trackers blocking DNS server |
| audiobookshelf | library | Audiobooks library |
| bazarr | media | Subtitles |
| beszel | information | System information |
| chaptarr | media | Books / Audiobooks |
| cleanuparr | download | Bad download handling |
| docker-discord-alerts | tools | Notify Discord when docker containers change |
| dozzle | information | Docker status |
| duc | tools | Disk usage |
| emby | library | Media library |
| flaresolverr | network | Cloudflare captcha bypasss |
| glances | information | Operating system status |
| homepage | information | Dashboard |
| i2p | network | I2P Client |
| imagemaid | quality | Cleanup Plex image cache |
| jellyfin | library | Open source media library |
| kapowarr | library | Comics |
| kometa | quality | Poster overlays, collections, playlists for Plex |
| komga | library | Comic library |
| libretranslate | tools | Translation |
| lidarr | media | Music |
| lingarr | quality | Subtitle translation |
| manyfold | library | 3d models library |
| minecraft | games | Minecraft |
| mylar | media | Comics |
| neutarr | download | Missing media search |
| notifiarr | tools | System notifications |
| onlyfans | download | Download all subscriptions |
| openspeedtest | network | Bandwidth test to server |
| pgadmin | tools | Database admin |
| plex | library | Media library |
| plex-find-mismatch | quality | Finds mismatches between tvdb/tmdb/imdb and Plex |
| portainer | information | Container management |
| postgres | tools | Database |
| prowlarr | download | Torrent / NNTP search proxy |
| qbittorrent | download | Torrent downloader |
| radarr | media | Movies |
| sabnzbd | download | NNTP downloader |
| scrutiny | information | S.M.A.R.T. information |
| seerr | information | Media requests and issue tracking |
| sonarr | media | TV Shows |
| sonarr_youtubedl | disabled | Download from Youtube |
| speedtest-tracker | information | Speedtest with history |
| stash | tools | Porn database |
| subgen | quality | Audio transription |
| syncthing | download | Remote data synchronisation |
| tautulli | information | Plex stats |
| tdarr | quality | Transcoding / format shifting / audio normalisation |
| tdarr_inform | quality | Notifications from sonarr / radarr / etc to tdarr |
| tdarr-node | quality | Transcoding node for tdarr |
| titlecardmaker | quality | Episode thumbnails for Plex |
| tracearr | library | Plex & Emby monitoring |
| ubooquity | media | Comics |
| watchstate | tools | Sync media library watch state |
| webtop | desktop | Linux desktop |
| whisparr | media | Porn |
| whoami | network | Who... Am... I...? |
| windows | desktop | Windows desktop |
| zfdash | information | ZFS administration |
| zfs-discord-alerts | tools | Notify Discord when there are zfs problems |
Note
The core PROFILE services are enabled in the compose.yaml file, you must add any others you wish to a compose.override.yaml file instead:
include:
- whoami/compose.yamlImportant
The Plex library must have finished copying before you do this, and you must not run the old one again (unless you decide not to go ahead with this).
- Run
docker compose pull- disable any services that you don't have permission for. - Just before running go to https://account.plex.tv/claim and copy the token to
PLEX_CLAIMin.env - Run
docker compose up -dand wait for everything to come up. - Go to
https://dozzle.<domain>and wait for all the red dots to turn green. - Optional: Run
docker compose downfollowed bydocker compose up -d dozzle plex- this reduces load and lets you setup things one at a time. - Go to Plex and tell it to rescan everything - every entry should get re-found as Plex uses file hashes for identification.