Persistent zsh + oh-my-zsh on Unraid

Ever since I switched to OSX, I have fallen in love with zsh. I use it wherever I can, however, Unraid poses a small challenge. Both root (/) and the root-home (/root/) are not permanent storage paths. They reside in ram and changes there are lost on reboot. You could use the Nerdpack for Unraid to install zsh, set the shell for root to /bin/zsh and call it a day. This has two flaws:

  • you will have to install and configure oh-my-zsh every time you reboot
  • if zsh fails to install on reboot, you won’t have a valid shell and you can’t ssh into the machine

Luckily, we can address that. We can utilize /boot/config/go to run any script on boot, so we can prepare the environment, zip it up and restore it on boot. Use these steps on a system without zsh + oh-my-zsh to get a persistent setup.

  1. Install Nerdpack from the Community Applications Plugin
  2. Install zsh through Nerdpack
  3. Open a shell and run zsh. It will look horrible, but don’t worry.
  4. Install oh-my-zsh using their installer
  5. Make changes to /root/.zshrc as desired. I love the included ZSH_THEME=”gentoo”

Congratulations, you now have a temporary zsh + oh-my-zsh setup that has to be invoked manually by calling zsh. Boo! Let’s make it permanent, and provide a fallback to bash if zsh is not present.

1. Change your /root/.bash_profile to:

#!/bin/bash
if [ -f /bin/zsh ]; then
  /bin/zsh; exit
else
  # console coloring for kool kids
  PS1='[33[01;32m]u@h[33[00m]:[33[01;34m]w[33[00m]$ '

  # if this is an xterm set the title to user@host:dir
  case "$TERM" in
  xterm*|rxvt*)
      PS1="[e]0;u@h: wa]$PS1"
      ;;
  *)
      ;;
  esac

  # impersonate a user
  alias user="su -ls /bin/bash"

  alias v="ls -lA"
fi

This will look for /bin/zsh and if it exists, it will run it. zsh will proceed to parse the .zshrc file and load oh-my-zsh. The && exit will make sure that when you exit the shell, it will not drop you into a bash instance. If /bin/zsh does not exist, it will just do what it did so far, giving you a colored bash session.

2. We will now archive the setup. These commands will create a folder on the USB stick and copy the relevant files into an archive.

mkdir -p /boot/root
tar -cjf /boot/root/zsh.tar.bz2 .bash_profile .oh-my-zsh .zshrc

3. To update ZSH on boot, create /boot/root/omz-update.sh

#!/bin/zsh
source /root/.zshrc
omz update
rm /root/omz-update.sh

4. Add this to /boot/config/go right under /usr/local/sbin/emhttp &

# give me oh-my-zsh
tar xjf /boot/root/zsh.tar.bz2 -C /root/
ln -s /root/.bash_profile /root/.bashrc

# and update it!
cp /boot/root/omz-update.sh /root/ && chmod +x /root/omz-update.sh && /root/omz-update.sh

5. Stop your array and reboot

And there you go. Every time you boot, it will extract oh-my-zsh and your .bash_profile and then attempt to update it after the web service has started. You might have noticed we symlink .bashrc. This is needed if you are using screen. If you also want zsh in your screen sessions, you need the same script for .bashrc.