# Run each line incrementally
# Remove old packages
sudo apt remove docker docker-engine docker.io containerd runc
# Install dependencies
sudo apt-get install ca-certificates curl gnupg lsb-release -y
sudo mkdir -p /etc/apt/keyrings
# Get source (Ubuntu)
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Get source (Debian)
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
# Check if Docker was sucessfully installed
docker info
# Create Docker volume for Portainer
docker volume create portainer_data
# Pull Portainer image and run
docker run -d -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
# These services are essential to managing Docker and the host
version: '3.9'
name: core
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer:/data
ports:
- 8000:8000
- 9000:9000
restart: unless-stopped
watchtower:
image: containrrr/watchtower
container_name: watchtower
env_file:
- ./env/watchtower.env
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
code-server:
image: lscr.io/linuxserver/code-server:latest
container_name: code-server
env_file:
- ./env/common.env
- ./env/codeserver.env
volumes:
- code-server:/config
ports:
- 9443:8443
restart: unless-stopped
dozzle:
container_name: dozzle
image: amir20/dozzle:latest
restart: unless-stopped
env_file:
- ./env/common.env
- ./env/dozzle.env
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 9999:8080
volumes:
portainer:
code-server:
# Database and data management
version: '3.9'
name: database
services:
redis:
image: redis:latest
container_name: redis
restart: unless-stopped
ports:
- '6379:6379'
volumes:
- redis:/data
postgres:
image: postgres:11-alpine
container_name: postgres
env_file:
- ./env/postgres.env
ports:
- '5432:5432'
restart: unless-stopped
volumes:
- /ac9/scripts/postgres/db_init.sh:/docker-entrypoint-initdb.d/db_init.sh
- postgres:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4:8.5
restart: unless-stopped
container_name: pgadmin
env_file:
- ./env/pgadmin.env
ports:
- "5050:80"
volumes:
- pgadmin:/var/lib/pgadmin
- pgadmin_config:/pgadmin4
volumes:
redis:
postgres:
pgadmin:
pgadmin_config:
# Media automation
version: '3.9'
name: media
services:
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
env_file:
- ./env/common.env
volumes:
- radarr:/config
- /mnt/w10_plex:/plex
- /mnt/w10_fileserver:/mnt/fileserver
ports:
- 7878:7878
restart: unless-stopped
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
env_file:
- ./env/common.env
volumes:
- sonarr:/config
- /mnt/w10_plex:/plex
- /mnt/w10_fileserver:/mnt/fileserver
ports:
- 8989:8989
restart: unless-stopped
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
env_file:
- ./env/common.env
volumes:
- prowlarr:/config
- /mnt/w10_fileserver:/mnt/fileserver
ports:
- 9696:9696
restart: unless-stopped
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
env_file:
- ./env/common.env
ports:
- 8191:8191
restart: unless-stopped
overseerr:
image: sctx/overseerr:latest
container_name: overseerr
env_file:
- ./env/common.env
volumes:
- overseerr:/app/config
ports:
- 5055:5055
restart: unless-stopped
decluttarr:
image: ghcr.io/manimatter/decluttarr:latest
container_name: decluttarr
restart: unless-stopped
env_file:
- ./env/decluttarr.env
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
env_file:
- ./env/common.env
volumes:
- qbittorrent:/config
- /mnt/w10_plex:/plex
- /mnt/w10_fileserver/:/fileserver
ports:
- 8080:8080
- 55555:55555
- 55555:55555/udp
restart: unless-stopped
tautulli:
image: lscr.io/linuxserver/tautulli:latest
container_name: tautulli
env_file:
- ./env/common.env
volumes:
- tautulli:/config
- /mnt/w10_fileserver/Backups/Tautulli:/config/backups
ports:
- 8181:8181
restart: unless-stopped
ytdl_material:
image: tzahi12345/youtubedl-material:latest
container_name: ytdl_material
restart: unless-stopped
env_file:
- ./env/common.env
volumes:
- ytdl_material:/app/appdata
- ytdl_material:/app/users
- /mnt/w10_fileserver/Downloads/YTDL:/app/users/ac9/audio
- /mnt/w10_fileserver/Downloads/YTDL:/app/users/ac9/video
ports:
- 8083:17442
fireshare:
container_name: fireshare
image: shaneisrael/fireshare:latest
restart: unless-stopped
ports:
- 8282:80
volumes:
- fireshare:/data
- /docker/volumes/media_fireshare/_data/processed:/processed
- /mnt/w10_plex/Gameplay:/videos
env_file:
- ./env/common.env
- ./env/fireshare.env
volumes:
radarr:
sonarr:
prowlarr:
qbittorrent:
overseerr:
tautulli:
ytdl_material:
fireshare:
# Webfront services
version: '3.9'
name: webfront
services:
heimdall:
container_name: heimdall
image: lscr.io/linuxserver/heimdall:latest
restart: unless-stopped
env_file:
- ./env/common.env
volumes:
- heimdall:/config
ports:
- 8084:80
filebrowser:
image: filebrowser/filebrowser:latest
container_name: filebrowser
restart: unless-stopped
ports:
- 8087:80
env_file:
- ./env/common.env
- ./env/filebrowser.env
volumes:
- filebrowser:/srv
- /mnt/w10_fileserver:/srv/AC9
filebrowser_upload:
container_name: filebrowser_upload
image: filebrowser/filebrowser:latest
restart: unless-stopped
ports:
- 8018:80
environment:
- FB_NOAUTH=true
env_file:
- ./env/common.env
- ./env/filebrowser.env
volumes:
- filebrowser_upload:/srv
- /mnt/w10_fileserver/Temp:/srv/AC9
wikijs:
image: requarks/wiki:latest
container_name: wikijs
ports:
- 3033:3000
env_file:
- ./env/wikijs.env
volumes:
- wikijs:/root
- /docker/volumes/webfront_wikijs/_data/wiki/data/content:/wiki/data/content
restart: unless-stopped
trilium:
image: zadam/trilium:latest
container_name: trilium
restart: unless-stopped
env_file:
- ./env/trilium.env
ports:
- 8088:8080
volumes:
- trilium:/data
shlink_host:
image: shlinkio/shlink:latest
container_name: shlink-host
restart: unless-stopped
ports:
- 8081:8080
volumes:
- shlink-host:/etc/shlink
env_file:
- ./env/common.env
- ./env/shlink.env
shlink_client:
image: shlinkio/shlink-web-client:latest
container_name: shlink-client
restart: unless-stopped
env_file:
- ./env/common.env
ports:
- 8082:8080
volumes:
- shlink-client:/usr/share/nginx/html
homebox:
image: ghcr.io/hay-kot/homebox:latest
container_name: homebox
restart: unless-stopped
env_file:
- ./env/homebox.env
volumes:
- homebox:/data/
ports:
- 7745:7745
snapdrop:
image: lscr.io/linuxserver/snapdrop:latest
container_name: snapdrop
env_file:
- ./env/common.env
volumes:
- snapdrop:/config
ports:
- 7777:80
restart: unless-stopped
volumes:
heimdall:
filebrowser:
filebrowser_upload:
wikijs:
trilium:
shlink-host:
shlink-client:
homebox:
snapdrop:
# Networking - DNS, Reverse Proxy and SSO..
version: '3.9'
name: networking
services:
nginxproxymanager:
image: lepresidente/nginxproxymanager:latest
container_name: nginxproxymanager
restart: unless-stopped
env_file:
- ./env/common.env
ports:
- 443:443
- 80:80
- 81:81
volumes:
- nginxproxymanager:/data
- /docker/volumes/networking_nginxproxymanager/_data/letsencrypt:/etc/letsencrypt
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
env_file:
- ./env/common.env
expose:
- 8080
volumes:
- crowdsec-db:/var/lib/crowdsec/data/
- crowdsec-config:/etc/crowdsec/
- /docker/volumes/networking_nginxproxymanager/_data/logs:/var/log/npm:ro
- /var/log/auth.log:/var/log/auth.log:ro
restart: unless-stopped
netbootxyz:
image: ghcr.io/netbootxyz/netbootxyz
container_name: netbootxyz
env_file:
- ./env/common.env
volumes:
- netbootxyz:/config
- "/mnt/w10_fileserver/My\ Files/ISO/netboot:/assets"
ports:
- 3001:3000
- 69:69/udp
- 82:80
restart: unless-stopped
pihole:
container_name: pihole
image: pihole/pihole:latest
network_mode: host
ports:
- 53:53/tcp
- 53:53/udp
- 83:83/tcp
env_file:
- ./env/pihole.env
cap_add:
- NET_ADMIN
volumes:
- pihole:/etc/
restart: unless-stopped
ddclient:
image: lscr.io/linuxserver/ddclient:latest
container_name: ddclient
restart: unless-stopped
env_file:
- ./env/common.env
volumes:
- ddclient:/config
volumes:
nginxproxymanager:
ddclient:
netbootxyz:
pihole:
crowdsec-db:
crowdsec-config:
# QOL
version: '3.9'
name: personal
services:
changedetection:
image: ghcr.io/dgtlmoon/changedetection.io
container_name: changedetection
restart: unless-stopped
ports:
- 5555:5000
volumes:
- changedetection:/datastore
environment:
PUID: $AC9
PGID: $AC9
TZ: $AU
BASE_URL: $CD_BASE_URL
PLAYWRIGHT_DRIVER_URL: $PLAYWRIGHT_DRIVER_URL
playwright-chrome:
depends_on:
- changedetection
container_name: playwright-chrome
hostname: playwright-chrome
image: browserless/chrome
restart: unless-stopped
firefly:
container_name: firefly
image: fireflyiii/core:latest
restart: unless-stopped
ports:
- 8888:8080
environment:
PUID: $AC9
PGID: $AC9
TZ: $AU
APP_KEY: $FF_APP_KEY
APP_URL: $FF_APP_URL
TRUSTED_PROXIES: $FF_TRUSTED_PROXIES
DB_CONNECTION: $FF_DB_CONNECTION
DB_HOST: $POSTGRES_HOST
DB_DATABASE: $POSTGRES_FIREFLY
DB_USERNAME: $POSTGRES_USER
DB_PASSWORD: $POSTGRES_PASSWORD
DB_PORT: $POSTGRES_DB_PORT
volumes:
- firefly:/var/www/html/storage/upload
shlink_host:
image: 'shlinkio/shlink:latest'
container_name: shlink-host
restart: unless-stopped
ports:
- '8081:8080'
volumes:
- shlink-host:/etc/shlink
environment:
PUID: $AC9
PGID: $AC9
TZ: $AU
DEFAULT_DOMAIN: $SHLINK_DEFAULT_DOMAIN
IS_HTTPS_ENABLED: $SHLINK_IS_HTTPS_ENABLED
GEOLITE_LICENSE_KEY: $SHLINK_GEOLITE_LICENSE_KEY
TIMEZONE: $TIMEZONE
shlink_client:
image: 'shlinkio/shlink-web-client:latest'
container_name: shlink-client
restart: unless-stopped
environment:
PUID: $AC9
PGID: $AC9
TIMEZONE: $TIMEZONE
ports:
- '8082:80'
volumes:
- shlink-client:/usr/share/nginx/html
volumes:
changedetection:
firefly:
shlink-host:
shlink-client:
version: '3.9'
networks:
logging:
services:
grafana:
image: grafana/grafana:latest
user: '1000'
container_name: grafana
restart: unless-stopped
networks:
- logging
ports:
- 3001:3000
volumes:
- grafana:/var/lib/grafana
environment:
TZ: Australia/Melbourne
GF_SERVER_ROOT_URL: https://your.domain
loki:
image: grafana/loki:latest
container_name: loki
restart: unless-stopped
networks:
- logging
ports:
- 3100:3100
environment:
TZ: Australia/Melbourne
volumes:
- loki:/etc/loki
logging:
driver: loki
options:
loki-url: http://192.168.1.3:3100/loki/api/v1/push
mode: non-blocking
max-buffer-size: 5m
loki-retries: "2"
command: -config.file=/etc/loki/loki-config.yml
promtail:
image: grafana/promtail:latest
container_name: promtail
restart: unless-stopped
networks:
- logging
environment:
TZ: Australia/Melbourne
volumes:
- promtail:/etc/promtail
- /var/log:/var/log
command: -config.file=/etc/promtail/promtail-config.yml
volumes:
grafana:
loki:
promtail:
version: "3.9"
services:
tdarr:
container_name: tdarr
image: ghcr.io/haveagitgat/tdarr:latest
restart: unless-stopped
cpus: 0.33
ports:
- 8265:8265 # webUI port
- 8266:8266 # server port
- 8267:8267 # Internal node port
environment:
- TZ=Australia/Melbourne
- PUID=1000
- PGID=1000
- UMASK_SET=775
- serverIP=0.0.0.0
- serverPort=8266
- webUIPort=8265
- internalNode=true
- nodeID=Tdarr_Internal
volumes:
- tdarr:/app
- /mnt/w10_plex/:/media
- /mnt/w10_plex/Agents/TdarrCache:/temp
volumes:
tdarr:
Docker volumes are stored in /var/lib/docker/volumes/ by default. This can be changed by manually binding volumes, creating symlinks or editing docker.service.
Backing up volumes is simple but please be aware that permissions and owners must be preserved for restores. Otherwise the containers will run into R/W issues.
Sample script:
# Stop docker so we don't corrupt databases
echo "Stopping Docker.."
service docker stop
# Pack volumes
cd /docker/volumes
echo "Backing up Docker Volumes.."
tar -cf /ac9/docker/docker_volumes.tar --exclude={'metadata.db','ipc-socket','backingFsBlockDev','[Bb]ackup*','MediaCover','*.log','log*','querylog*','cache','*GeoLite2*'} *
# Start again, takes 10 seconds for 2gb for me
echo "Restoring Docker.."
service docker start
# Grab some other configs
echo "Backing up Ubuntu configs.."
tar -cf /mnt/w10_fileserver/Backups/Docker/$(date +%d_%m_%y-%I_%M_%p).tar \
/ac9 \
/etc/fstab \
~/.ssh \
/etc/ssh/sshd_config \
/var/spool/cron/crontabs
echo "Back up completed."