{"id":13551413,"url":"https://github.com/croneter/docker_mediaserver","last_synced_at":"2025-04-12T08:50:55.402Z","repository":{"id":43189739,"uuid":"137912631","full_name":"croneter/docker_mediaserver","owner":"croneter","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-16T14:17:59.000Z","size":182,"stargazers_count":7,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-03T21:35:33.435Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/croneter.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-19T15:44:45.000Z","updated_at":"2023-11-06T17:05:13.000Z","dependencies_parsed_at":"2023-01-29T14:15:36.340Z","dependency_job_id":null,"html_url":"https://github.com/croneter/docker_mediaserver","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/croneter%2Fdocker_mediaserver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/croneter%2Fdocker_mediaserver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/croneter%2Fdocker_mediaserver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/croneter%2Fdocker_mediaserver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/croneter","download_url":"https://codeload.github.com/croneter/docker_mediaserver/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224717666,"owners_count":17357917,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T12:01:47.842Z","updated_at":"2024-11-15T02:12:12.002Z","avatar_url":"https://github.com/croneter.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"Tested on Ubuntu Pro 18-04\n\n## Get the server up and running\n### Install Docker\nUpdate to latest Linux version\n```\nsudo apt-get update\nsudo apt-get dist-upgrade\n```\nEnable the official Docker repository by following [this docker.com guide](https://docs.docker.com/install/linux/docker-ce/ubuntu/). Then install Docker:\n```\nsudo apt-get install docker-ce\n```\nTest docker:\n```\nsudo docker run hello-world\n```\nNext, install Docker-Compose following [this docker.com guide](https://docs.docker.com/compose/install/). \nThen add a new user `dockeruser` and make the user a member of the `docker` user group and switch to the new user.\n```\nsudo adduser dockeruser\nsudo usermod -aG docker dockeruser\nsu dockeruser\n```\nFrom now on, always use `dockeruser` for any operations.\n\n### Get Docker Swarm up and running\nReplace the IP `192.168.0.2` with your own for the swarm, e.g. simply the server's own IP if your running everything on a single host/node/server:\n```\ndocker swarm init --advertise-addr 192.168.0.2\n```\n\n### Pull code from Github\nNavigate to a folder where you'd like to set-up this docker-compose recipe and your personal docker setup, e.g. `~/docker-mediaserver`. Get everything from Github:\n```\ncd ~/\ngit clone https://github.com/croneter/docker_mediaserver ./docker-mediaserver\ncd docker-mediaserver\ngit fetch --all\ngit pull --all\n```\n\n### Fetch latest update from Github\nAny time you want to get the latest code from Github, type\n```\ngit pull\n```\n\n## Configuration Using Docker\n\n### Set Your Secrets\nCreate the secrets that we need to run our stacks. Choose any strong master/admin password for Keycloak with `keycloak_admin_password`. Grab your personal token from [duckdns.org](https://www.duckdns.org/) for `traefik_duckdns_token`.\n```\nprintf \u003csecret\u003e | docker secret create keycloak_admin_password -\nprintf \u003csecret\u003e | docker secret create traefik_duckdns_token -\n```\nIf you ever want to edit a secret, simply remove it first with\n```\ndocker secret rm \u003cname of the secret, e.g. keycloak_admin_password\u003e\n```\nYou'll also need a short-lived Plex secret once, see below.\n\n### Set your environment variables to suit your config\nRun the dedicated script; be sure to log-out and log-in again after doing so!\n```\npython setup.py\n```\nNote done all the values you insert; you'll need some below. You'll also probably need to run that command once per Docker swarm node.\n\n### Adapt all environment files\nSet-up your values in all the environment files:\n```\nnano forward-auth.env.example\nnano keycloak.env.example\nnano pihole.env.example\n```\nBe sure to safe each file WITHOUT the ending `.example`, so e.g. as `forward-auth.env`.\n\n## Run The Stacks\nTo get everything up and running, be sure to be in your `~/docker_mediaserver` folder and type\n```\npython start.py\n```\nBe sure to first start the stack `overlay` as that stack is needed for everything else, but also `traefik` and `keycloak` should be up and running at any point of time.    \nAlternatively, type directly:\n```\ndocker stack deploy -c overlay.yml overlay\ndocker stack deploy -c traefik.yml traefik\ndocker stack deploy -c keycloak.yml keycloak\n```\n\n### Plex\nBefore running the Plex stack, you'll need to set your short-lived Plex claim. See below.\n\n### Customize Your Lidarr Docker Image\nLidarr is customized to enable you to automatically convert FLAC to MP3. Build (or later upgrade) the `lidarr` Docker image with:\n```\ndocker build -t lidarr .\n```\nTo enable automatic conversation, customize Lidarr:\n* Navigate to Settings -\u003e Connection\n* Create a new Custom Connection\n* For the path, add `/usr/local/bin/flac2mp3.sh`. Only select\n  * \"On Release Import\"\n  * \"On Upgrade\"\n\n### Build Your DNS Over HTTPS image\nIn the `dns-over-https` directory, do\n```\ndocker build -t dns-over-https .\n```\nThen\n```\ndocker tag dns-over-https:latest dns-over-https:staging\n```\n\n## Setting Up Your Services Using a Browser\n### Setting up Keycloak\nOn first \"boot\" of your server, visit `https://keycloak.\u003cyourdomain\u003e`. Use your Keycloak admin credentials to log-in.\n* Create a new realm. Paste that realm's name into `.env` as `HTPC_KEYCLOAK_REALM`\n* Create a new client for our container `forward-auth`. Set `Access Type` to `Confidential`. Set one `Valid Redirect URIs` to `https://auth.\u003cyourdomain\u003e/_oauth`\n* Copy the `Client ID` and paste it as `KEYCLOAK_CLIENT_ID` in our `.env` file\n* In the Credentials tab, copy the `Secret` and paste it as `KEYCLOAK_CLIENT_SECRET` in our `.env` file. \n* Reboot your server with `docker-compose down`, then `docker-compose up`\n\n### Configure SABNZBD once\nAdd your domain to whitelist. Navigate to your chosen `config_dir`, then\n```\ncd sabnzbd\nnano sabnzbd.ini\n```\nAdd your domain to the `host_whitelist`-entry like this:\n```\nhost_whitelist = \u003cother entries\u003e, sabnzbd.example.duckdns.org\n```\nDeactivate the `X_Frame_Options` to allow iFrames for Organizr by editing the line to\n```\nx_frame_options = 0\n```\n\n### Setup your Plex Media Server\nYou need to have a valid Plex claim ONCE in order to claim your new Plex Media Server and tie it to your account. \n* Grab a Plex claim token from [plex.tv/claim](https://www.plex.tv/claim) - it will only be valid for 4 minutes!!\n* Paste the claim token into a new Docker secret: \n```\nprintf \u003csecret\u003e | docker secret create plex_claim -\n```\n* Start your Plex stack.\n* Then connect to Plex by visiting `https://example.duckdns.org:\u003cYOUR EXTERNAL PLEX PORT\u003e` and claim your PMS.\n* Make sure your PMS can be reached from outside: navigate to the PMS settings, then `Remote Access`. Set `Manually specify public port` to your custom port\n\n### Setup Organizr\nChoose a `Personal`-License if you want Radarr, Sonarr, etc. working, i.e. appearing as Homepage options. For Organizr Single Sign On, use an email address as username. Set-up the exact same email address as a user within Organizr.\n\nChoose the following Organizr `Auth Proxy` settings in the Organizr settings:\n* Auth Proxy: On\n* Auth Proxy Whitelist: `0.0.0.0/0`\n* Auth Proxy Header Name: `X-Forwarded-User`\n\nWhen adding tabs, use the following setup:\n* Type: `iFrame`\n* Tab Url: https://\u003cservice\u003e.croneter-test.duckdns.org\n\n### Pi-Hole\nSee https://www.smarthomebeginner.com/run-pihole-in-docker-on-ubuntu-with-reverse-proxy/ for configuration tipps. \n\n\nPihole uses the user `root`: Log in to Linux as a user with sudo-rights, then\n```\nsudo chown -R root:root /home/dockeruser/config/pihole\n```\nIn Pi-Hole, set `172.29.0.2#5053` as upstream DNS and make sure all other DNS entries are disabled. If that does not work, use `1.1.1.1`\n\n\n\n## Other Useful Stuff\n### Power Management\nList current hard drives with `lsblk`. Use [TLP](https://linrunner.de/en/tlp/docs/tlp-linux-advanced-power-management.html):\n```\nsudo apt-get update\nsudo apt install tlp tlp-rdw \n```\nShow the current configuration of TLP with\n```\nsudo tlp-stat -c\n```\nSee [here for configuration options](https://linrunner.de/en/tlp/docs/tlp-configuration.html). E.g change the config to power down the second of a total of 2 hard drives with `sudo nano /etc/default/tlp` and adding\n```\n# Spin down the second of 2 hard disks after 5min\nDISK_SPINDOWN_TIMEOUT_ON_AC=\"0 60\"\nDISK_SPINDOWN_TIMEOUT_ON_BAT=\"0 60\"\n```\nCheck whether the hard disk `/dev/sda` is powered down (wait 5 min!) with\n```\nsudo hdparm -C /dev/sda\n```\n\n### Permissions off for writing/accessing a directory?\nMake sure that the user `dockeruser` owns the entire directory (use a user with sudo-rights):\n```\nsudo chown -R dockeruser:docker \u003cdirname\u003e\n```\nChange the standard group new files and folders are associated with, permanently to `docker`, and associate all existing files and folders with that group:\n```\nchmod -R g+s \u003cdirname\u003e\nchgrp -R docker \u003cdirname\u003e\n```\nNew files and folders shall be fully readable and writable by the associated group, not even visible for `others`:\n```\nsetfacl -R -d -m g::rwx \u003cdirname\u003e\nsetfacl -R -d -m o::--- \u003cdirname\u003e\n```\nChange this also for existing files and folders:\n```\nsetfacl -R -m g::rwx \u003cdirname\u003e\nsetfacl -R -m o::--- \u003cdirname\u003e\n```\n\n### Copy an existing host `directory` into a Docker volume `dockervolume`\nAlso see https://github.com/moby/moby/issues/25245. `directory/.` will copy the contents of `directory`; if you want to also copy the `directory` (\"name\") itself, simply drop `/.`\n```\ndocker run -d --rm --name dummy -v dockervolume:/root alpine tail -f /dev/null\ndocker cp directory/. dummy:/root/\ndocker stop dummy\n```\n\n### Find the 20 largest files NOT containing `.mkv`\n```\nfind . -printf '%s %p\\n'| sort -nr | grep -v '.mkv' | head -n 20\n```\n\n### Convert all audio streams to AC3 / Dolby Surround 5.1, leave video untouched\n```\ndocker run -v \"$(pwd):$(pwd)\" -w \"$(pwd)\" jrottenberg/ffmpeg:4.1-alpine \\\n       -stats \\\n       -i input.mkv \\\n       -map 0 \\\n       -c:v copy \\\n       -acodec ac3 -b:a 640k \\\n       output.mkv\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcroneter%2Fdocker_mediaserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcroneter%2Fdocker_mediaserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcroneter%2Fdocker_mediaserver/lists"}