Unofficial Ubuntu 22.04 45Drives Cockpit Install

With a few modifications, I was able to get the ubuntu-preconfig.sh script from 45Drives repo to work/not fail on a clean install of Ubuntu 22.04. Sharing below in case anyone finds this useful.

A few caveats should you proceed at your own risk:

  • If your already have a working 45Drives Houston/Cockpit install on 45Drives hardware, backup files /etc/45drives/server_info/server_info.json, /etc/vdev_id.conf, /usr/lib/udev/rules.d/68-vdev.rules, and /usr/lib/udev/vdev_id_45drives before doing anything! You will need to put these files back after installing Ubuntu either before the script or after. First timers will need to run dalias after the script to create the files initially.
  • Script uses focal stable repository which has worked well for me. Don’t enable test as that breaks cockpit login.
  • Script assumes standard installation. If you do a minimal install of Ubuntu then script will fail disablng UFW. Easiest fix is to install ufw via apt before running.
  • Install Ubuntu and run the script using the standard kernel (5.15). ZFS will have some issues if you start with the HWE kernel. Installing linux-generic-hwe-22.04 after the script still throws an error but proceeds and seems to work just fine.
unofficial_ubuntu_preconfig.sh
#!/usr/bin/env bash

# Unofficial Ubuntu 22.04 LTS System Configuration Tweaks
# Official preconfiguration script found at <https://scripts.45drives.com/ubuntu-preconfig.sh> written by...
#   Brett Kelly <bkelly@45drives.com>
#   Josh Boudreau <jboudreau@45drives.com>
#   Dawson Della Valle <ddellavalle@45drives.com>

interpreter=$(ps -p $$ | awk '$1 != "PID" {print $(NF)}' | tr -d '()')

if [ "$interpreter" != "bash" ]; then
	echo "Please run with bash. (\`./ubuntu-preconfig.sh\` or \`bash ubuntu-preconfig.sh\`)"
	echo "Current interpreter: $interpreter"
	exit 1
fi

euid=$(id -u)

if [[ "$euid" != 0 ]]; then 
	echo "Please run as root or with sudo."
	exit 1
fi

LSBVERSION=$(lsb_release -rs)

if [[ "$LSBVERSION" != 22.04 ]]; then 
	echo "Sorry. This script is only valid on Ubuntu 22.04."
	exit 1
fi

welcome() {
	local response
	cat <<EOF
Welcome to the UNOFFICIAL

 /##   /## /#######  /#######            /##                              
| ##  | ##| ##____/ | ##__  ##          |__/                              
| ##  | ##| ##      | ##  \ ##  /######  /## /##    /## /######   /#######
| ########| ####### | ##  | ## /##__  ##| ##|  ##  /##//##__  ## /##_____/
|_____  ##|_____  ##| ##  | ##| ##  \__/| ## \  ##/##/| ########|  ###### 
      | ## /##  \ ##| ##  | ##| ##      | ##  \  ###/ | ##_____/ \____  ##
      | ##|  ######/| #######/| ##      | ##   \  #/  |  ####### /#######/
      |__/ \______/ |_______/ |__/      |__/    \_/    \_______/|_______/

                                         Ubuntu 22.04 Preconfiguration Script.

    This will set up the root login password, enable root login over SSH,
add the 45Drives apt repository, replace systemd-networkd with NetworkManager,
remove cloud-init and snapd, and add the Houston Management UI.

    This script should *not* be run in an SSH session, as the network will be
modified and you may be disconnected. Run this script from the console or IPMI
remote console.
EOF

	read -p "Are you sure you want to continue? [y/N]: " response

	case $response in
		[yY]|[yY][eE][sS])
			echo
			;;
		*)
			echo "Exiting..."
			exit 0
			;;
	esac

	return 0
}

enable_root_user() {
	local ROOTPASSWD=""
	local ROOTPASSWD2=""
	local res
	
    echo "ENABLING ROOT LOGIN"
	
    while true; do
		read -sp "Enter password for root user: " ROOTPASSWD
		
        echo
		
        if [[ "$ROOTPASSWD" == "" ]]; then
			echo "Root password cannot be empty! Try again."
			continue
		fi
		
        read -sp "Confirm password for root user: " ROOTPASSWD2
		
        echo
		
        if [[ "$ROOTPASSWD" != "$ROOTPASSWD2" ]]; then
			echo "Passwords do not match! Try again."
			continue
		fi
		
        echo "root:$ROOTPASSWD" | chpasswd
		
        res=$?
		
        if [[ $res != 0 ]]; then
			echo "Setting password failed! Exit code: $res"
			continue
		fi

		echo "Successfully set root password."
		
        break
	done
	
    return 0
}

enable_root_ssh() {
	local res
	
    echo "ENABLING ROOT LOGIN VIA SSH"
	
    cat > /etc/ssh/sshd_config.d/45drives.conf <<EOF
PermitRootLogin yes
PasswordAuthentication yes
EOF

	# Restart sshd
	systemctl restart sshd
	res=$?
	if [[ $res != 0 ]]; then
		echo "Restarting sshd failed!"
		exit $res
	fi

	# test root login
	echo "Adding localhost's ECDSA Key Fingerprint to $HOME/.ssh/known_hosts"

	ssh-keyscan -H localhost >> $HOME/.ssh/known_hosts

	echo "Enter password to test root login to localhost:"

	ssh root@localhost exit

	res=$?

	if [[ $res != 0 ]]; then
		echo "Root ssh login failed!"
		exit $res
	fi

	echo "Successfully enabled ssh login."

	return 0
}

update_system() {
	local res
	## Update system
	# Install 45drives repository
	echo "UPDATING SYSTEM"

	echo "Downloading 45Drives Repo Setup Script"
	curl -sSL https://repo.45drives.com/setup -o setup-repo.sh

	res=$?
	if [[ $res != 0 ]]; then
		echo "Failed to download repo setup script! (https://repo.45drives.com/setup)"
		exit $res
	fi

	echo "Running 45Drives Repo Setup Script"

	bash setup-repo.sh
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Failed to run the setup script! (https://repo.45drives.com/setup)"
		exit $res
	fi

	# apt upgrade
	echo "Upgrading packages"
	
    apt upgrade -y
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "apt upgrade failed!"
		exit $res
	fi

	echo "Successfully updated system."
	
    return 0
}

init_network() {
	local res
	
    echo "SETTING UP NETWORK MANAGER"
	# Install network packages
	
    apt update
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "apt update failed!"
		exit $res
	fi
	
	apt install -y network-manager firewalld
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Installing network manager and/or firewalld failed!"
		exit $res
	fi
	
	systemctl enable --now NetworkManager
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Enabling network manager failed!"
		exit $res
	fi
	
	# Disable ufw and enable firewalld
	systemctl enable --now firewalld
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Enabling firewalld failed!"
		exit $res
	fi
	
	ufw disable
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Disabling ufw failed!"
		exit $res
	fi
	
	echo "Successfully set up network manager."
	
	return 0
}

remove_garbage() {
	local res
	
    echo "REMOVING CLOUD-INIT AND SNAPD"
	
    # Disable cloud-init
    touch /etc/cloud/cloud-init.disabled
	
	# Remove snapd
	apt autoremove --purge -y snapd
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Disabling snapd failed!"
		exit $res
	fi
	
	echo "Successfully removed cloud-init and snapd."
	
	return 0
}

add_cockpit() {
	local res
	
    echo "INITIALIZING HOUSTON"
	
    # Install cockpit and cockpit related things
	
    echo "Installing dependencies"
	
    apt update
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "apt update failed!"
		exit $res
	fi

    # Get Ubuntu Release to install latest version of cockpit via backports
    LSBCODENAME=$(lsb_release -cs)
	
	apt install -t $LSBCODENAME-backports -y cockpit cockpit-zfs-manager cockpit-benchmark cockpit-navigator cockpit-file-sharing cockpit-45drives-hardware cockpit-identities cockpit-machines cockpit-sosreport realmd tuned udisks2-lvm2 zfs-dkms samba winbind nfs-kernel-server nfs-client 45drives-tools
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Installing Houston dependencies failed!"
		exit $res
	fi
	
	# Open firewall for cockpit
	echo "Opening firewall for cockpit"
	
    firewall-cmd --permanent --add-service=cockpit
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Adding cockpit to firewall failed!"
		exit $res
	fi
	
	firewall-cmd --reload
	
    res=$?
	
    if [[ $res != 0 ]]; then
		echo "Reloading firewall failed!"
		exit $res
	fi
	
	# Install cockpit override manifests for 45ddrives-hardware and apps
	
    cat >> /usr/share/cockpit/45drives-disks/override.json <<EOF
{
	"menu": {
		"45drives-disks": {
			"order": 110
		}
	}
}
EOF

	cat >> /usr/share/cockpit/45drives-motherboard/override.json <<EOF
{
	"menu": {
		"45drives-motherboard": {
			"order": 111
		}
	}
}
EOF

	cat >> /usr/share/cockpit/45drives-system/override.json <<EOF
{
	"menu": {
		"45drives-system": {
			"order": 112
		}
	}
}
EOF

	cat >> /usr/share/cockpit/apps/override.json <<EOF
{
	"tools": {
		"index": null
		}
}
EOF

	systemctl enable --now cockpit.socket

	res=$?

	if [[ $res != 0 ]]; then
		echo "Enabling cockpit.socket failed!"
		exit $res
	fi
	
	echo "Successfully initialized Houston."
	
	return 0
}

use_nm_not_systemd-networkd() {
	local res

	echo "ENABLING NETWORK MANAGER"
	# Use Network Manager instead of systemd-networkd

	cat > /etc/netplan/00-networkmanager.yaml <<EOF
network:
  version: 2
  renderer: NetworkManager
EOF

	[[ -f /etc/netplan/00-installer-config.yaml ]] && mv /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.backup

	netplan try

	res=$?

	if [[ $res != 0 ]]; then
		echo "netplan try failed."
		exit $res
	fi
	
	ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

	mv /usr/lib/NetworkManager/conf.d/10-globally-managed-devices.conf  /usr/lib/NetworkManager/conf.d/10-globally-managed-devices.conf.backup

	sed -i '/^managed/s/false/true/' /etc/NetworkManager/NetworkManager.conf
	
	systemctl restart NetworkManager
	
	res=$?

	if [[ $res != 0 ]]; then
		echo "Reloading NetworkManager failed."
		exit $res
	fi
	
	echo "Successfully enabled NetworkManager."
	
	if [[ $res != 0 ]]; then
		echo "Reloading NetworkManager failed."
		exit $res
	fi

	# Disable Networkd
	systemctl disable --now systemd-networkd-wait-online 

	res=$?

	if [[ $res != 0 ]]; then
		echo "Disabling systemd-networkd-wait-online failed."
		exit $res
	fi
	
	echo "Successfully disabled systemd-networkd-wait-online."

	return 0
}

setup_done() {
	local response=""

	echo "SETUP COMPLETE"

	read -p "Reboot system now? [y/N]: " response

	case $response in
		[yY]|[yY][eE][sS])
			reboot now
			;;
		*)
			echo "Reboot soon to finish configuration."
			;;
	esac

	return 0
}

progress=""

if [[ -f .ubuntu-preconfig.progress ]]; then
	progress=$(cat .ubuntu-preconfig.progress)
fi

if [[ $progress != "" ]]; then
	echo "Found progress from previous time running this script. ($PWD/.ubuntu-preconfig.progress)"
	echo "1. Continue from last successful step."
	echo "2. Start from beginning."
	echo "3. Exit. (default)"
	read -p "[1-3]: " response
	case $response in
		1)
			echo "Starting from last successful step."
			;;
		2)
			echo "Starting from beginning."
			progress=""
			;;
		*)
			echo "Exiting..."
			exit 0
			;;
	esac
fi

case $progress in
	"")
		welcome
		;& # fallthrough
	0)
		echo "################################################################################"
		enable_root_user
		echo 1 > .ubuntu-preconfig.progress
		;&
	1)
		echo "################################################################################"
		enable_root_ssh
		echo 2 > .ubuntu-preconfig.progress
		;&
	2)
		echo "################################################################################"
		update_system
		echo 3 > .ubuntu-preconfig.progress
		;&
	3)
		echo "################################################################################"
		init_network
		echo 4 > .ubuntu-preconfig.progress
		;&
	4)
		echo "################################################################################"
		remove_garbage
		echo 5 > .ubuntu-preconfig.progress
		;&
	5)
		echo "################################################################################"
		add_cockpit
		echo 6 > .ubuntu-preconfig.progress
		;&
	6)
		echo "################################################################################"
		use_nm_not_systemd-networkd
		echo 7 > .ubuntu-preconfig.progress
		;&
	7)
		echo "################################################################################"
		setup_done
		echo 8 > .ubuntu-preconfig.progress
		;;
	8)
		echo "Setup successfully finished the previous time running this script."
		;;
esac

exit 0

6 Likes

Updated script with a few improvements…

  • Check for Ubuntu 22.04 before executing
  • Install cockpit via backports to obtain the latest version
  • Disable systemd-networkd-wait-online after installing and setting up NetworkManager
1 Like

I’m going to check this out later, thank you for sharing!

I’m hopeful that with 24.04 LTS around the corner that Houston will get a large facelift, as I did enjoy my time with it but ultimately gave up as the project contributions seemed a bit neglected. Begrudginly, I’ve moved my HL15 to TrueNAS Scale as I never felt fully confident in my Rocky 8 install with Houston, too many strange UI bugs, a handful of SSSD/Winbind woes, and neverending SELinux recommendations that just would not go away after running the suggested “Fix”.

Ultimately, it’s a shame as I was hopeful to see something that could rival that of TrueNAS and unRAID for those of us that prefer a UI that simply mirrors a standard Distro’s CLI rather than a proprietary Distro or one that’s CLI is severly limited.

2 Likes

Happy to share! Let us know if it doesn’t work out for some reason.

Looks like you ended up in the same place I did with my HL15. After trying Houston on both Rocky and Ubuntu, I landed on TrueNAS Scale. I kind of wished I would have tried Proxmox with Houston.

I just installed 22.04 Tonight, Everything went pretty smooth, I wish I would have checked here for the post, It would have saved me a little trial and error. Thanks for all the information. The biggest issue I seemed to have is that network-manager was renamed to NetworkManager, and realizing that I had to choose the ‘focal’ repo. I haven’t tested any ZFS workloads yet, I remember trying this earlier, and having issues with Znapzend but that was probably a self inflicted wound. I will report back if I run into any issues.

2 Likes

znapzend keeps failing for me too. everything else is nice though

Can you tell me more about how your znapzend fails. Mine would not allow me to make the changes to znapzend in the UI, I was able to make the changes to the datasets in the CLI. I didn’t have an issue with the service failing after I got everything set up. But the UI was definitely broken.

@Specter, ZnapZend will fail if there is no backup plan created. if you are not planning on setting up a backup plan you can mask the service.

If you do want to create a backup snapshot plan please make the plan first then restart the service

1 Like

Thank you! I was more concerned with getting my pools set correctly before setting up a snapshot plan.

1 Like