You’re welcome to do as you please, just wanted to alert others attention to the video tutorial.
Since this is a less brittle long term solution, I would imagine any additional upfront effort is worth it. This new methodology shouldnt arbitrarily break on an update.
This was discussed multiple times already, and it’s not the same in terms of performance.
I would not call this method brittle, it has survived multiple major updates with minor changes that were made before the final release of that update.
And now, with the “install-dev-tools” option, they have solved 2 problems, they have kept TrueNAS as they say “an appliance” to maintain support.
And whoever doesn’t want to use it like this, activates this option, and TrueNAS becomes a true Linux/Debian, but without any support.
I myself have already updated the script and removed the checks from the beginning that became obsolete and some others.
I also added the optional installation for Portainer and for those who use/need Nvidia VGA.
There are 4 new variables that need to be changed, 3 for the portainer and 1 to activate Nvidia support, they are self-explanatory, but if you have any doubts I can explain:
#!/usr/bin/env bash
# Enable docker and docker-compose on TrueNAS SCALE (no Kubernetes)
# Follow the guide in this post before using this script:
# https://forum.level1techs.com/t/truenas-scale-native-docker-vm-access-to-host-guide/190882
# This script is a hack! Use it at your own risk!!
# Edit all the vars under:
# Vars you need to change
# to point to your storage
#
# Schedule this script to run via System Settings -> Advanced -> Init/Shutdown Scripts
# Click Add -> Type: Script and choose this script -> When: choose to run as Post Init
exec >/mnt/ssd/Tools/enable-docker.log
# Vars you need to change:
# set a path to your docker dataset
docker_dataset="/you/docker/dataset"
# set the docker_daemon path on your storage for it to survive upgrades
new_docker_daemon="/you/new/docker/daemon.json"
# apt sources persist
new_apt_sources="/you/new/aptsources.list"
# Options: ON/OFF
# Install the Portainer container:
portainer_on="ON"
portainer_data="/you/data/portainer"
portainer_port=9443
# If you use an Nvidia VGA for transcoding in docker, enable this:
nvidia_on="OFF"
echo "§§ Starting script! §§"
echo "§§ Activating Developer Mode... §§"
install-dev-tools > /dev/null
echo "§§ Developer Mode Enabled. §§"
if [[ "$nvidia_on" == "ON" ]]; then
echo "§§ Enabling Nvidia VGA for transcoding in docker... §§"
KERNER=$(uname -r)
DUNAME=/lib/modules/"$KERNER"/
DIDKMS=/lib/modules/"$KERNER"/updates/dkms/
echo "§§ Checking if nvidia modules are started... §§"
if [[ ! -f "$DUNAME"nvidia-uvm.ko ]]; then
echo "§§ nvidia-uvm.ko does not exist, creating module with symbolic link... §§"
ln -s "$DIDKMS"nvidia-current-uvm.ko "$DUNAME"nvidia-uvm.ko
echo "§§ Updating the module list... §§"
depmod -a
echo "§§ Starting Nvidia modules... §§"
nvidia-container-cli -k -d /dev/tty info
else
echo "§§ nvidia-uvm.ko exists, checking if it is started... §§"
if [[ ! -f /dev/nvidia-uvm ]]; then
echo "§§ nvidia-uvm not started, starting... §§"
nvidia-container-cli -k -d /dev/tty info
else
echo "§§ nvidia-uvm is already started. §§"
fi
fi
fi
echo "§§ apt update §§"
apt update > /dev/null
echo "§§ Linking apt sources to your storage for persistance §§"
echo "§§ Please note that with this you'll have to update the links manually on your storage when there's an update §§"
aptsources="/etc/apt/sources.list"
if [[ -f "$aptsources" ]] && [[ ! -L "$aptsources" ]]; then
cp "$aptsources" "$new_apt_sources"
mv "$aptsources" "$aptsources".old
fi
if [[ ! -f "$new_apt_sources" ]]; then
touch "$new_apt_sources"
fi
if [[ ! -f "$aptsources" ]]; then
ln -s "$new_apt_sources" "$aptsources"
fi
echo "§§ Fix the trust.gpg warnings §§"
# Create a directory for the new keyrings if it doesn't exist
mkdir -p /etc/apt/trusted.gpg.d
# Find all keys in the old keyring
for key in $(gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --list-keys --with-colons | awk -F: '/^pub:/ { print $5 }'); do
echo "Processing key: $key"
# Export each key to a new keyring file in the trusted.gpg.d directory
gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --export --armor "$key" >/etc/apt/trusted.gpg.d/"$key".asc
done
# Backup the old keyring
mv /etc/apt/trusted.gpg /etc/apt/trusted.gpg.backup
#Docker Checks
echo "§§ Docker Checks §§"
if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then
echo "§§ Missing Keyrings §§"
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
else
echo "§§ Keyrings Exist §§"
fi
if ! grep -q "https://download.docker.com/linux/debian" /etc/apt/sources.list; then
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(lsb_release -cs) stable" >> /etc/apt/sources.list
apt update
else
echo "§§ Docker List: §§"
cat /etc/apt/sources.list
fi
Docker=$(which docker)
DCRCHK=$(apt list --installed | grep docker)
if [[ -z "$Docker" ]] || [[ -z "$DCRCHK" ]]; then
echo "Docker executable not found"
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
fi
echo "§§ Which Docker: $Docker §§"
## HEREDOC: docker/daemon.json
echo "§§ Docker daemon.json §§"
read -r -d '' JSON <<END_JSON
{
"data-root": "${docker_dataset}",
"storage-driver": "overlay2",
"exec-opts": [
"native.cgroupdriver=cgroupfs"
]
}
END_JSON
## path to docker daemon file
docker_daemon="/etc/docker/daemon.json"
if [[ ${EUID} -ne 0 ]]; then
echo "§§ Please run this script as root or using sudo §§"
elif [[ "$(systemctl is-enabled k3s)" == "enabled" ]] || [[ "$(systemctl is-active k3s)" == "active" ]]; then
echo "§§ You can not use this script while k3s is enabled or active §§"
elif ! zfs list "$docker_dataset" &>/dev/null; then
echo "§§ Dataset not found: $docker_dataset §§"
else
echo "§§ Checking file: ${docker_daemon} §§"
if [[ -f "$docker_daemon" ]] && [[ ! -L "$docker_daemon" ]]; then
rm -rf "$docker_daemon"
fi
if [[ ! -f "$new_docker_daemon" ]]; then
touch "$new_docker_daemon"
fi
if [[ ! -f "$docker_daemon" ]]; then
ln -s "$new_docker_daemon" "$docker_daemon"
fi
# Read the current JSON from the file
current_json=$(cat $docker_daemon 2>/dev/null)
echo -e "§§ current_json:\n$current_json\n§§"
# Check if current_json is empty and if so, set it to an empty JSON object
if [[ -z "$current_json" ]]; then
current_json="{}"
fi
# Merge the current JSON with the new JSON
merged_json=$(echo "$current_json" | jq --argjson add "$JSON" '. * $add')
echo -e "§§ merged_json:\n$merged_json\n§§"
# Check if the merged JSON is different from the current JSON
if [[ "$merged_json" != "$current_json" ]] || [[ -z "$current_json" ]]; then
echo "§§ Updating file: $docker_daemon §§"
echo "$merged_json" | tee "$docker_daemon" >/dev/null
if [[ "$(systemctl is-active docker)" == "active" ]]; then
echo "§§ Restarting Docker §§"
systemctl restart docker
elif [[ "$(systemctl is-enabled docker)" != "enabled" ]]; then
echo "§§ Enable and starting Docker §§"
systemctl enable --now docker
fi
fi
fi
if [[ "$nvidia_on" == "ON" ]]; then
## Configure NVIDIA runtime in docker
echo "§§ Configuring Nvidia runtime in docker... §§"
RUNCHK=$(grep "nvidia-container-runtime" /etc/docker/daemon.json)
if [ -z "$RUNCHK" ]; then
nvidia-ctk runtime configure --runtime=docker
echo "§§ Nvidia runtime configured. §§"
echo "§§ Restarting Docker §§"
systemctl restart docker
else
echo "§§ NVIDIA runtime is already configured. §§"
fi
fi
if [[ "$portainer_on" == "ON" ]]; then
echo "§§ Checking if Portainer is installed... §§"
PORCHK=$(docker ps | grep portainer)
if [ -z "$NVDCHK" ]; then
echo "§§ Installing Portainer... §§"
docker run -d -p $portainer_port:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v $portainer_data:/data portainer/portainer-ce:latest > /dev/null
echo "§§ Portainer installed. §§"
else
echo "§§ Portainer is already installed. §§"
fi
fi
Docker=$(which docker)
DockerV=$(docker --version)
echo "§§ Which Docker: $Docker §§"
echo "§§ Docker Version: $DockerV §§"
echo "§§ Script Finished! §§"
@Scepterus It clears me some doubts, the first, why do you use it:
#!/usr/bin/env bash
rather than: #!/bin/bash
Another thing, I believe we no longer need to check the storage-driver, because apparently, now it will always be overlay2, correct?
And also, what this option does exactly: . ~/.bashrc
And if you can take a look at the script I updated based on yours, any tips to improve it are always welcome
I tried to remove the NVIDIA kernel and reinstall it, but the NVIDIA container is tied to TrueNAS, at least in 23, so that’s not possible.
I just finished the Apps script, and upgraded to Dragonfish, I will update the first post with the relevant codes.
Because it is a better standard, if someone decided they wanted to install another version of bash, for example, I would always use the one that the user has defined.
Yes, but I would keep it as legacy for at least 2 more major versions, for backwards compatibility.
It sources the file bashrc after we make changes to it, or if we want to reload everything in the path and aliases.
PORCHK=$(docker ps | grep portainer)
if [ -z "$NVDCHK" ]; then
Two issues there, you used two names for the var, and also you only used one , it’s better to use 2 like [].
Aside from that, do you set the Nvidia on manually? You could just check if an NVIDIA card is present and switch it based on that.
Upgrade conclusions:
Just found out the upgrade overwrote the apt sources list in the link, I will need to figure out how to account for that, but thankfully I have a snapshot to restore from.
Another thing, I got this error when trying to update:
rm: cannot remove '/lib32': Read-only file system
dpkg: error processing package usrmerge (--configure):
installed usrmerge package post-installation script subprocess returned error exit status 1
Errors were encountered while processing:
usrmerge
E: Sub-process /usr/bin/dpkg returned an error code (1)
Using apt update. Still more fixing and adapting needed.
Ok, for some reason / was mounted as read-only. Adding a remount to the script.
I encountered the same issue with / being mounted read only. If you wait some time after booting, it would eventually get mounted read/write. Adding a remount very early in your script fixes this, as you found out.
if [[ ! -f "$DUNAME"nvidia-uvm.ko ]]; then
echo "§§ nvidia-uvm.ko does not exist, creating module with symbolic link... §§"
ln -s "$DIDKMS"nvidia-current-uvm.ko "$DUNAME"nvidia-uvm.ko
echo "§§ Updating the module list... §§"
depmod -a
echo "§§ Starting Nvidia modules... §§"
nvidia-container-cli -k -d /dev/tty info
else
echo "§§ nvidia-uvm.ko exists, checking if it is started... §§"
if [[ ! -e /dev/nvidia-uvm ]]; then
echo "§§ nvidia-uvm not started, starting... §§"
modprobe nvidia-uvm
echo "§§ Updating the module list... §§"
depmod -a
nvidia-container-cli -k -d /dev/tty info
else
echo "§§ nvidia-uvm is already started. §§"
fi
fi
Because your code was always looping the same results.
Hi Scepterus, thank you for the original post and your effort to answer all people’s questions from 2022!I actually had used WenDell’s method to migrate my apps (nextcloud, immich etc.) from Truecharts docker to VM. It seems that everything works well. However I feel that the performance of apps under VM is a bit below the Truecharts apps. Maybe it is because of the overhead in VM? By the way I am using DragonFish which is the latest version of TrueNAS Scale.
Now I saw your solution and feel that I may give it a try. I have some questions before trying:
Apologise I haven’t gone through all your replies and posts. I would like to know if the original script in the 1st post (2022) still works under DragonFish. From a few latest posts it seems yes but I would just like to double check. Do I need to refer to a later post to make some changes?
Would running docker natively break the TrueNAS system in some way? Is there any potential risk I need to be aware of?
What is the best way to back up all the dockers/containers, configration, dataset if I take your approach? I would like to be able to restore all of them if something goes wrong.
Amazing, our hard work here paid off. However, the script for apps restore, and the other parts of the guide will still be relevant as each update will still remove the apps you install with apt.
So just upgraded, needed to touch @Finallf script by a bit (thanks for sharing it btw!) and ensure it matches up with your latest script. I’m now running Dragonfish and it was mostly painless (needed to mkdir those directories to persist the daemon and apt source, woops).
Glad to see the next version is finally adding docker natively and properly! Like about time but hopefully this enforces running docker containers natively won’t be considered “breaking” the appliance that is truenas.
Did anynone’s script stopped working after the update to 24.04.2?
I am getting this error when running the script.
E: Package 'docker-ce' has no installation candidate
E: Package 'docker-ce-cli' has no installation candidate
E: Unable to locate package containerd.io
E: Couldn't find any package by glob 'containerd.io'
E: Unable to locate package docker-buildx-plugin
E: Unable to locate package docker-compose-plugin
Hi, thanks so much for the guide! I’d like to run plex as a docker container accessible from my local network. Any hints as to how I can do this would be appreciated! I’m using this image plexinc/pms-docker:latest it seems to come up fine but nothing can connect to plex. I’m assuming some sort of network/firewall change is needed
Hey, did you use the latest version of the script? If so, we’ll debug further.
You’ll need to set up ports that are accessible in your compose file, any guide online on how to set up plex in docker compose should be fine, TrueNAS really does not play a part here.
It still not working for me on 24.04.2, looks like an issue with pkg sources. I get this error when doing apt update.
sudo apt update
Hit:1 https://apt.sys.truenas.net/dragonfish/nightlies/debian bookworm InRelease
Hit:2 https://apt.sys.truenas.net/dragonfish/nightlies/libnvidia bookworm InRelease
Hit:3 https://apt.sys.truenas.net/dragonfish/nightlies/helm all InRelease
Hit:4 https://apt.sys.truenas.net/dragonfish/nightlies/debian-security bookworm-security InRelease
Hit:5 https://apt.sys.truenas.net/dragonfish/nightlies/debian-backports bookworm-backports InRelease
Hit:6 https://apt.sys.truenas.net/dragonfish/nightlies/debian-debug bookworm-debug InRelease
Hit:7 https://apt.sys.truenas.net/dragonfish/nightlies/yarn stable InRelease
Hit:8 https://apt.sys.truenas.net/dragonfish/nightlies/nvidia bookworm InRelease
Hit:9 https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
3 packages can be upgraded. Run 'apt list --upgradable' to see them.
W: Skipping acquire of configured file 'contrib/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/debian-backports bookworm-backports InRelease' doesn't have the component 'contrib' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'contrib/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/debian-backports bookworm-backports InRelease' doesn't have the component 'contrib' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'non-free/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/debian-backports bookworm-backports InRelease' doesn't have the component 'non-free' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'non-free/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/debian-backports bookworm-backports InRelease' doesn't have the component 'non-free' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'maindeb/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'maindeb' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'maindeb/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'maindeb' (component misspelt in sources.list?)
W: Skipping acquire of configured file '[arch=amd64 signed-by=/etc/apt/keyrings/docker.asc]/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component '[arch=amd64 signed-by=/etc/apt/keyrings/docker.asc]' (component misspelt in sources.list?)
W: Skipping acquire of configured file '[arch=amd64 signed-by=/etc/apt/keyrings/docker.asc]/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component '[arch=amd64 signed-by=/etc/apt/keyrings/docker.asc]' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'https://download.docker.com/linux/debian/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'https://download.docker.com/linux/debian' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'https://download.docker.com/linux/debian/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'https://download.docker.com/linux/debian' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'bookworm/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'bookworm' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'bookworm/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'bookworm' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'stable/binary-amd64/Packages' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'stable' (component misspelt in sources.list?)
W: Skipping acquire of configured file 'stable/i18n/Translation-en' as repository 'https://apt.sys.truenas.net/dragonfish/nightlies/pcm bookworm InRelease' doesn't have the component 'stable' (component misspelt in sources.list?)
that’s because you have nightlies in your apt list.
try these:
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
deb http://deb.debian.org/debian/ bookworm main non-free non-free-firmware
#deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/debian/ bookworm main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/libnvidia/ bookworm main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/helm/ all main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/debian-security/ bookworm-security main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/debian-backports/ bookworm-backports main contrib non-free
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/debian-debug/ bookworm-debug main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/yarn/ stable main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/nvidia/ bookworm main
deb http://apt.tn.ixsystems.com/apt-direct/dragonfish/24.04.0/pcm/ bookworm main