~/ymo/docker
Create a separate network for all services behind the reverse proxy
docker network create proxy-network
Auto-updater for containers
docker run -d --name watchtower \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-e WATCHTOWER_NOTIFICATIONS="shoutrrr" \
-e WATCHTOWER_NOTIFICATION_URL="telegram://856583418:AAHEoI7PBxOj3nLuzzisJ7L2H9LnCGEm6eU@telegram/?channels=856583418" \
-v /etc/localtime:/etc/localtime:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower --cleanup
docker volume create adguardhome_config
docker volume create adguardhome_data
docker run --name adguardhome \
--network proxy-network --restart unless-stopped \
--ip 172.18.0.253 \
-v adguardhome_data:/opt/adguardhome/work \
-v adguardhome_config:/opt/adguardhome/conf \
-p 53:53/tcp -p 53:53/udp \
-p 853:853/tcp \
-p 784:784/udp \
-p 5443:5443/tcp -p 5443:5443/udp \
-d adguard/adguardhome
Request certificate from Let's Encrypt ACME service
docker volume create swag_config
docker run -d \
--name=swag \
--network proxy-network \
--restart unless-stopped \
--cap-add=NET_ADMIN \
-e PUID=99 \
-e PGID=99 \
-e TZ=Europe/Brussels \
-e URL=nas.reisub.io \
-e SUBDOMAINS=wildcard \
-e VALIDATION=dns \
-e DNSPLUGIN=cloudflare \
-e EMAIL=yuri.moens@gmail.com \
-e ONLY_SUBDOMAINS=false \
-e STAGING=false \
-p 4433:443 \
-p 8080:80 \
-v swag_config:/config \
ghcr.io/linuxserver/swag
Reverse proxy
docker volume create haproxy_config
docker run -d --name haproxy \
--network proxy-network \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-p 80:80 \
-p 443:443 \
-v /etc/localtime:/etc/localtime:ro \
-v /dev/log:/dev/log \
-v haproxy_config:/usr/local/etc/haproxy:ro \
-v /var/lib/docker/volumes/letsencrypt_config/_data/etc/letsencrypt/live:/etc/ssl:ro \
haproxy
Password management, this version (bitwardenrs) is a reimplementation of the Bitwarden API in Rust and runs in a single container
docker run -d --name bitwarden \
--network proxy-network \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-e ADMIN_TOKEN='<changeme>' \
-e WEBSOCKET_ENABLED=true \
-v /etc/localtime:/etc/localtime:ro \
-v bitwarden_data:/data \
bitwardenrs/server:latest
Correctly create a backup from Bitwarden
docker run -d --name bitwarden_backup \
--network proxy-network \
--restart unless-stopped \
--volumes-from=bitwarden \
-e BACKUP_FILE=/data/backup.sqlite3 \
-e UID=0 \
-e GID=0 \
bruceforce/bw_backup
Simple, real-time system monitoring
docker run -d --name netdata \
--network proxy-network \
--restart unless-stopped \
--cap-add SYS_PTRACE \
-e PGID=977 \
-e TZ=Europe/Brussels \
-v /etc/localtime:/etc/localtime:ro \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
netdata/netdata
Torrent client with WebUI
docker volume create qbittorrent_config
docker run -d --name qbittorrent \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e UMASK_SET=002 \
-e WEBUI_PORT=8080 \
-p 6881:6881 \
-p 6881:6881/udp \
-v qbittorrent_config:/config \
-v /nas/public/downloads:/downloads \
-v /nas/synology/public/games:/games \
linuxserver/qbittorrent:version-14.2.5.99202004250119-7015-2c65b79ubuntu18.04.1
docker volume create qbittorrentprivate_config
docker run -d --name qbittorrentprivate \
--network proxy-network \
--restart unless-stopped \
-e PUID=1000 \
-e PGID=2001 \
-e TZ=Europe/Brussels \
-e UMASK_SET=027 \
-e WEBUI_PORT=8080 \
-v qbittorrentprivate_config:/config \
-v /nas/private/ymo/nfye:/downloads \
linuxserver/qbittorrent:version-14.2.5.99202004250119-7015-2c65b79ubuntu18.04.1
Ping statistics
docker volume create smokeping_config
docker volume create smokeping_data
docker run -d --name smokeping \
--network proxy-network \
--restart unless-stopped \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/Brussels \
-v smokeping_config:/config \
-v smokeping_data:/data \
linuxserver/smokeping
API for Sonarr/Radarr/Lidarr, abstraction layer for plenty of torrent trackers
docker volume create jackett_config
docker run -d --name jackett \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-v jackett_config:/config \
-v /nas/public/downloads:/downloads \
linuxserver/jackett
Automatic tv series downloader
docker volume create sonarr_config
docker run -d --name sonarr \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e UMASK_SET=002 \
-v sonarr_config:/config \
-v /nas/public:/public \
linuxserver/sonarr
Automatic movies downloader
docker volume create radarr_config
docker run -d --name radarr \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e UMASK_SET=002 \
-v radarr_config:/config \
-v /nas/public:/public \
linuxserver/radarr
Automatic music downloader
Add to crontab on loki
@reboot setfacl -m user:public:rw /var/run/docker.sock
Execute
setfacl -m user:public:rw /var/run/docker.sock
mkdir -p /var/lib/docker/containers/config/lidarr
cat <<EOF > /var/lib/docker/containers/config/lidarr/90-config
#!/usr/bin/with-contenv bash
DOCKERVERSION=18.09.6
curl -fsSLO https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKERVERSION}.tgz \
&& tar xzvf docker-${DOCKERVERSION}.tgz --strip 1 \
-C /usr/local/bin docker/docker \
&& rm docker-${DOCKERVERSION}.tgz
EOF
docker volume create lidarr_config
cat <<EOF > /var/lib/docker/volumes/lidarr_config/_data/beets_import.sh
#!/bin/bash
echo "$lidarr_addedtrackpaths"
lidarr_first_track=$(echo "$lidarr_addedtrackpaths" | cut -d '|' -f1)
lidarr_album_path=$(dirname "$lidarr_first_track")
echo "Path: $lidarr_album_path"
echo "Album MBID: $lidarr_album_mbid"
echo "Release MBID: $lidarr_albumrelease_mbid"
echo "Running beet import"
docker --config "/config/.docker" exec -u abc beets /bin/bash -c "beet update"
docker --config "/config/.docker" exec -u abc beets /bin/bash -c "beet import -q '$lidarr_album_path'"
if [[ $? -eq 137 ]]; then
exit 0
fi
EOF
docker run -d --name lidarr \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e UMASK_SET=002 \
-v lidarr_config:/config \
-v /nas/public:/public \
-v /var/lib/docker/containers/config/lidarr/90-config:/etc/cont-init.d/90-config \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
linuxserver/lidarr
Automatic subtitles downloader with Sonarr/Radarr integration
docker volume create bazarr_config
docker run -d --name=bazarr \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e UMASK_SET=002 \
-v bazarr_config:/config \
-v /nas/public:/public \
linuxserver/bazarr
Media server (rather new, not as many features as Plex but open source)
docker volume create jellyfin_config
docker run -d --name=jellyfin \
--net host \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-v jellyfin_config:/config \
-v /nas/public/tv:/data/tvshows \
-v /nas/public/movies:/data/movies \
-v /nas/public/music:/data/music \
-v /tmp/transcode:/transcode \
--device /dev/dri/renderD128:/dev/dri/renderD128 \
--device /dev/dri/card0:/dev/dri/card0 \
linuxserver/jellyfin
DNS proxy, allows docker names to be resolved by the host
docker volume create dns-proxy_config
docker run -d --name dns-proxy \
--log-opt max-size=10m --log-opt max-file=3 \
--network proxy-network \
--restart=unless-stopped \
--ip 172.18.0.254 \
-e MG_LOG_LEVEL=ERROR \
-v dns-proxy_config:/app/conf \
-v /etc/localtime:/etc/localtime:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/resolv.conf:/etc/resolv.conf \
defreitas/dns-proxy-server
Postgres database server
docker volume create postgres_data
docker run -d --name postgres --hostname postgres \
--network proxy-network \
--restart=unless-stopped \
-e POSTGRES_PASSWORD=<changeme> \
-v postgres_data:/var/lib/postgresql/data \
postgres:latest
Mayan EDMS, searchable document storage with OCR
docker volume create mayan-redis_data
docker run -d --name mayan-redis \
--network proxy-network \
--restart=unless-stopped \
-v mayan-redis_data:/data \
redis:latest \
redis-server \
--databases \
"2" \
--maxmemory-policy \
allkeys-lru \
--save \
"" \
--requirepass <changeme>
docker volume create mayan-edms_data
docker run -d --name mayan-edms \
--network proxy-network \
--restart=unless-stopped \
-e MAYAN_DATABASES="{'default':{'ENGINE':'django.db.backends.postgresql','NAME':'mayan','PASSWORD':'<changeme>','USER':'mayan','HOST':'postgres'}}" \
-e MAYAN_CELERY_BROKER_URL="redis://:<changeme>@mayan-redis:6379/0" \
-e MAYAN_CELERY_RESULT_BACKEND="redis://:<changeme>@mayan-redis:6379/1" \
-e MAYAN_APT_INSTALLS="tesseract-ocr-nld tesseract-ocr-jpn tesseract-ocr-deu tesseract-ocr-fra tesseract-ocr-spa" \
-v mayan-edms_data:/var/lib/mayan \
mayanedms/mayanedms:latest
Easy to use, modern, searchable wiki with git backend support
docker run -d --name wikijs \
--network proxy-network \
--restart unless-stopped \
-e "DB_TYPE=postgres" \
-e "DB_HOST=postgres" \
-e "DB_PORT=5432" \
-e "DB_USER=wikijs" \
-e "DB_PASS=<changeme>" \
-e "DB_NAME=wikijs" \
-v /etc/localtime:/etc/localtime:ro \
requarks/wiki:latest
Personal cloud
docker volume create nextcloud_config
docker run -d --name=nextcloud \
--network proxy-network \
--restart unless-stopped \
-e PUID=1010 \
-e PGID=1010 \
-e TZ=Europe/Brussels \
-v nextcloud_config:/config \
-v /nas/cloud:/data \
linuxserver/nextcloud
MariaDB (mysql) database server
docker volume create mariadb_data
docker run -d --name mariadb --hostname mariadb \
--network proxy-network \
--restart unless-stopped \
-e MYSQL_ROOT_PASSWORD=<changeme> \
-v mariadb_data:/var/lib/mysql \
mariadb:latest
Music file tagging
docker volume create beets_config
docker run -d --name=beets \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-v beets_config:/config \
-v /nas/public:/public \
linuxserver/beets
ArchiSteamFarm, Steam bot for farming Steam cards and sale events
docker volume create asf_config
docker run -d --name asf \
--network proxy-network \
--restart unless-stopped \
-v asf_config:/app/config \
justarchi/archisteamfarm
Fast, low resource using git repository server
docker volume create gitea_config
docker run -d --name gitea \
--network proxy-network \
--restart unless-stopped \
-p 22:22 \
-e APP_NAME="NAS Git" \
-e RUN_MODE=prod \
-e SSH_DOMAIN=git.nas.reisub.io \
-e SSH_PORT=22 \
-e ROOT_URL="https://git.nas.reisub.io" \
-e DB_TYPE=postgres \
-e DB_HOST=postgres \
-e DB_NAME=gitea \
-e DB_USER=gitea \
-e DB_PASSWD=<changeme> \
-e DISABLE_REGISTRATION=true \
-v gitea_config:/data \
gitea/gitea:1
docker run -d --name=nginx \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-v /nas/public/web:/usr/share/nginx/html:ro \
nginx:latest
docker volume create airsonic_config
docker run -d --name airsonic \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e JAVA_OPTS="-Dserver.use-forward-headers -Dserver.session.cookie.max-age=31536000" \
-v airsonic_config:/config \
-v /nas/public/music:/music \
-v /nas/public/playlists:/playlists \
-v /nas/public/podcasts:/podcasts \
linuxserver/airsonic
Photo management
docker volume create lychee_config
docker volume create lychee_data
docker run -d --name=lychee \
--network proxy-network \
--restart unless-stopped \
-v lychee_config:/conf \
-v lychee_data:/uploads \
-e PUID=1000 \
-e PGID=1000 \
-e PHP_TZ=Europe/Brussels \
-e DB_CONNECTION=pgsql \
-e DB_HOST=postgres \
-e DB_PORT=5432 \
-e DB_DATABASE=lychee \
-e DB_USERNAME=lychee \
-e DB_PASSWORD=<change_me> \
bigrob8181/lychee-laravel
Bookmark tool
docker run -d --name wallabag \
--network proxy-network \
--restart unless-stopped \
-e "POSTGRES_PASSWORD=<changeme>" \
-e "POSTGRES_USER=postgres" \
-e "SYMFONY__ENV__DATABASE_DRIVER=pdo_pgsql" \
-e 'SYMFONY__ENV__DATABASE_DRIVER_CLASS=Wallabag\CoreBundle\Doctrine\DBAL\Driver\CustomPostgreSQLDriver' \
-e "SYMFONY__ENV__DATABASE_HOST=postgres" \
-e "SYMFONY__ENV__DATABASE_PORT=5432" \
-e "SYMFONY__ENV__DATABASE_NAME=wallabag" \
-e "SYMFONY__ENV__DATABASE_USER=wallabag" \
-e "SYMFONY__ENV__DATABASE_PASSWORD=w4FAQQgGFwwXpjzrSg5h4x6o5GtkhSyW" \
-e "SYMFONY__ENV__DOMAIN_NAME=https://wallabag.nas.reisub.io" \
-e "SYMFONY__ENV__SECRET=<changeme>" \
wallabag/wallabag
NZB index aggregator
docker volume create hydra_config
docker volume create hydra_data
docker run -d --name=hydra \
--network proxy-network \
--restart unless-stopped \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/Brussels \
-v hydra_config:/config \
-v hydra_data:/downloads \
linuxserver/hydra
NZB download client
docker volume create sabnzbd_config
docker run -d --name=sabnzbd \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-v sabnzbd_config:/config \
-v /nas/public/downloads:/downloads \
linuxserver/sabnzbd
Monitoring
docker volume create icinga2_config
docker volume create icinga2-web_config
docker volume create icinga2_data
docker volume create icinga2-web_data
docker run -d --name icinga2 --hostname icinga2 \
--network proxy-network \
--restart unless-stopped \
-e DEFAULT_MYSQL_HOST=mariadb \
-e MYSQL_ROOT_PASSWORD=<changeme> \
-e ICINGAWEB2_ADMIN_USER=ymo \
-e ICINGAWEB2_ADMIN_PASS=<changeme> \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/locale.gen:/etc/locale.gen:ro \
-v icinga2_config:/etc/icinga2 \
-v icinga2-web_config:/etc/icingaweb2 \
-v icinga2_data:/var/lib/icinga2 \
-v icinga2-web_data:/var/lib/php/sessions \
jordan/icinga2:latest
Plex statistics
docker volume create tautulli_config
docker run -d --name tautulli \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-v tautulli_config:/config \
-v "/var/lib/docker/volumes/plex_config/_data/Library/Application Support/Plex Media Server/Logs":/logs \
linuxserver/tautulli
docker volume create moodle_data
docker run -d --name moodle \
--network proxy-network \
--restart unless-stopped \
-e MOODLE_DATABASE_USER=moodle \
-e MOODLE_DATABASE_NAME=moodle \
-e MOODLE_DATABASE_PASSWORD=P6hMyP8UM74oip3z4C8qbZRgp8e9DPwh \
-v moodle_data:/bitnami \
bitnami/moodle:latest
Media server (great but closed source + premium plan)
docker volume create plex_config
docker run -d --name plex \
--net host \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-e PUID=2000 \
-e PGID=2000 \
-e VERSION=docker \
-v plex_config:/config \
-v /nas/public/tv:/data/tvshows \
-v /nas/public/movies:/data/movies \
-v /nas/public/music:/data/music \
-v /tmp/transcode:/transcode \
linuxserver/plex
Request tracker for Sonarr/Radarr/Lidarr download requests
docker volume create ombi_config
docker run -d --name ombi \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-v ombi_config:/config \
linuxserver/ombi
Container web frontend
docker volume create portainer_data
docker run -d --name portainer \
--network proxy-network \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-v /etc/localtime:/etc/localtime:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer
docker volume create ff-sync_data
docker run -d --name ff-sync \
--network proxy-network \
--restart unless-stopped \
-e TZ="Europe/Brussels" \
-e FF_SYNCSERVER_SECRET="changeme" \
-e FF_SYNCSERVER_PUBLIC_URL="https://ff-sync.nas.reisub.io" \
-e FF_SYNCSERVER_FORCE_WSGI_ENVIRON=true \
-v ff-sync_data:/data \
crazymax/firefox-syncserver:latest
docker volume create onlyoffice_logs
docker volume create onlyoffice_data
docker volume create onlyoffice_config
docker run -d --name onlyoffice \
--network proxy-network \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-v onlyoffice_logs:/var/log/onlyoffice \
-v onlyoffice_data:/var/www/onlyoffice/Data \
-v onlyoffice_config:/etc/onlyoffice \
onlyoffice/documentserver
VS Code in a browser
docker run -d --name=code \
--network proxy-network \
--restart unless-stopped \
-e PASSWORD=<changeme> \
-v "/nas/private/ymo/code:/home/coder/project" \
codercom/code-server --allow-http --disable-telemetry
Photo management
docker volume create piwigo_config
docker run -d --name=piwigo \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-v piwigo_config:/config \
linuxserver/piwigo
PDF reader
docker volume create ubooquity_config
docker run -d --name ubooquity \
--network proxy-network \
--restart unless-stopped \
-e PUID=2000 \
-e PGID=2000 \
-e TZ=Europe/Brussels \
-e MAXMEM=1024 \
-v ubooquity_config:/config \
-v /nas/public/books:/books \
-v /nas/public/comics:/comics \
-v /nas/public/pdf:/files \
linuxserver/ubooquity
Automatic comic downloader
docker volume create mylar_config
docker run -d --name mylar \
--network proxy-network \
--restart unless-stopped \
-e TZ=Europe/Brussels \
-e PUID=2000 \
-e PGID=2000 \
-v mylar_config:/config \
-v /nas/public:/public \
linuxserver/mylar
Caching DNS server with focus on ad-blocking
docker volume create pihole_config
docker volume create dnsmasq_config
docker run -d --name pihole \
--network proxy-network \
--restart unless-stopped \
-p 53:53/tcp -p 53:53/udp \
-e TZ="Europe/Brussels" \
-v /etc/localtime:/etc/localtime:ro \
-v pihole_config:/etc/pihole \
-v dnsmasq_config:/etc/dnsmasq.d \
--dns=127.0.0.1 \
--shm-size 1G \
pihole/pihole:latest
docker volume create cacti_plugins
docker volume create cacti_log
docker volume create cacti_templates
docker volume create cacti_mysql
docker volume create cacti_rrd
docker run -d --name cacti \
--network proxy-network \
--restart unless-stopped \
-p 80 \
-e TZ=Europe/Brussels \
-v cacti_plugins:/opt/cacti/plugins \
-v cacti_log:/var/log \
-v cacti_templates:/opt/cacti/templates \
-v cacti_mysql:/var/lib/mysql \
-v cacti-rrd:/opt/cacti/rrd \
quantumobject/docker-cacti
Landing page
docker volume create heimdall_config
docker run -d --name=heimdall \
--network proxy-network \
--restart unless-stopped \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/Brussels \
-v heimdall_config:/config \
linuxserver/heimdall