I haven't posted any telecom stuff in a while, and there are some reasons for that I won't get into. I'm still very much active in the industry.
In the meantime, I've been working on a lot of fun stuff. One of those things was replacing the OS on my older server. I switched from Fedora 22 to Rocky 9 - a massive jump. I made a decision to move most of my applications to Docker, as this was the easiest way to manage the deployment of new applications. My media was a different story, though.
The solution I was previously using implemented a tool called Greyhole to pool drives. Greyhole is a really neat utility, and it has served my purpose well over the years. It works by creating links from a folder called the Landing Zone to files on mounted storage drives. Of course, now I have 60 TB of data on these storage drives, and migrating to a new solution is impractical. I decided to do what any normal person would do and load Greyhole into my new environment. I had no idea what I was in for!
It turns out there are a lot of changes to the underlying Linux operating system between Fedora 22 and Rocky 9. The first major issue for me was that I couldn't use the well documented installation methods to install Greyhole in my environment - that meant building it from scratch.
Creating the Environment
By default Greyhole wants to mount shares in /mnt/samba/ but that wasn't going to work for my setup. I have a /docker/ folder on every server in my network and this is my common point for all services. I created a subfolder in this folder for my Samba shares: /docker/mnt/ with the structure I intend to use for my shares:
/docker└──
mnt
├── anime
├── backups
├── books
├── movies
├── music
├── pictures
├── software
└── tv
Additionally, Greyhole needs its own folder with a landing zone. The folders in the landing zone will correspond with the Samba shares that will be mounted to /docker/mnt. This is the structure I created:
/greyhole
└── lz
├── anime
├── backups
├── books
├── movies
├── music
├── pictures
├── software
└── tv
Now that I have the correct folder structure, I assigned it to my docker user. I created a docker user and group on each of my servers with the uid and gid of 1500. I have added any users who require access to this folder to the docker group. I ran the chown command and the chmod command to set the ownership and permissions of all the folders:
chown -R /docker/
chmod -R 774 /docker/
The greyhole folder will be owned by root, so we do not need to make any changes to the ownership and permissions of the greyhole folder. Rocky Linux does have other requirements, though - SELinux restricts access
The Back End Database
Greyhole requires a database to work properly. For this implementation I went with MySQL. I installed SQL with these commands:
sudo dnf install -y mysql-serversudo dnf install -y php-mysqlndsudo service mysqld startsudo systemctl enable mysqld
You can confirm that this has run properly by checking the status of the mysql service:
sudo systemctl status mysql
Next we need to secure mysql. Run this command:
sudo mysql_secure_installation
This will trigger the MySQL Secure Access Wizard. The output below is what I used for my configuration with a dummy root password for public consumption. Typed characters are in BOLD.
MySQL Secure Access
Would you like to setup VALIDATE PASSWORD component? Y
There are three levels of password validation policy:
LOW Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 0
Please set the password for root here. MySQLr00t
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : Y
Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y
Now that MySQL is secured, we need to create the user and database that Greyhole will use. First, log in to MySQL. When prompted, enter the root password you set when securing MySQL.
mysql -u root -p
We need to create a greyhole user with a password. The Greyhole documentation suggests using the psasword 89y63jdwe, however this does not meet the modern complexity requirements. For the purpose of this document we will use the password MySql_gr3yhole for the greyhole user. Run these commands to create the greyhole database and user:
CREATE DATABASE greyhole;
CREATE USER 'greyhole_user'@'localhost' IDENTIFIED BY 'MySql_gr3yhole';
USE greyhole;GRANT ALL PRIVILEGES ON greyhole.* TO 'greyhole_user'@'localhost';
Samba Configuration
Applications on my network will access the files on my server using Samba, and it is necessary for the operation of Greyhole. There are plenty of guides on how to configure Samba in Linux, but I encountered a few things that I didn't expect along the way.
We need to install a Samba client and the CIFS Utilities packages:
sudo dnf install -y cifs-utils samba-client
The smb.conf file will need to be modified to reflect your environment. Here is a snippet of one of the shares I created:
[tv]path = /greyhole/lz/tvbrowseable = yeswriteable = yesguest ok = nocreate mask = 0770directory mask = 0770dfree command = /usr/bin/greyhole-dfreevfs objects = greyhole
sudo smbpasswd -a docker
Samba Configuration: SELinux
sudo semanage fcontext -a -t samba_share_t "/greyhole/lz(/.*)?"
sudo semanage fcontext -a -t container_file_t "/docker(/.*)?"
sudo restorecon -Rv /docker/sudo restorecon -Rv /greyhole/
setsebool -P samba_export_all_rw=1
Building the Storage Pool
/greyhole/├── drive1│ ├── gh├── drive2│ ├── gh├── drive3│ ├── gh├── drive4│ ├── gh├── drive5│ ├── gh├── drive6│ ├── gh└── lz├── anime├── backups├── books├── movies├── music├── pictures├── software└── tv
Manual Installation of Greyhole
dnf install -y heimdal-devel
dnf install -y chkconfig
dnf install -y initscripts
dnf install -y lm_sensors-libscd /greyhole
cd /greyhole
wget https://github.com/gboudreau/Greyhole/releases/download/0.15.25/greyhole-0.15.25.tar.gz
tar -xvf greyhole-0.15.25.tar.gz
cd greyhole-0.15.25
GREYHOLE_INSTALL_DIR=`pwd`
mkdir -p /var/spool/greyhole
mkdir -p /var/spool/greyhole
chmod 777 /var/spool/greyhole
mkdir -p /usr/share/greyhole
install -m 0755 -D -p greyhole /usr/bin
install -m 0755 -D -p greyhole-dfree /usr/bin
install -m 0755 -D -p greyhole-php /usr/bin
install -m 0755 -D -p greyhole-dfree.php /usr/share/greyhole
install -m 0644 -D -p schema-mysql.sql /usr/share/greyhole
install -m 0644 -D -p greyhole.example.conf /usr/share/greyhole
install -m 0644 -D -p greyhole.example.conf /etc/greyhole.conf
install -m 0644 -D -p logrotate.greyhole /etc/logrotate.d/greyhole
install -m 0644 -D -p greyhole.cron.d /etc/cron.d/greyhole
install -m 0755 -D -p greyhole.cron.weekly /etc/cron.weekly/greyhole
install -m 0755 -D -p greyhole.cron.daily /etc/cron.daily/greyhole
cp -r web-app /usr/share/greyhole/web-app
install -m 0755 -D -p scripts-examples/greyhole_file_changed.sh /usr/share/greyhole/scripts-examples
install -m 0755 -D -p scripts-examples/greyhole_idle.sh /usr/share/greyhole/scripts-examples
install -m 0755 -D -p scripts-examples/greyhole_notify_error.sh /usr/share/greyhole/scripts-examples
install -m 0755 -D -p scripts-examples/greyhole_send_fsck_report.sh /usr/share/greyhole/scripts-examples
install -m 0755 -D -p scripts-examples/greyhole_sysadmin_notification.sh /usr/share/greyhole/scripts-examples
install -m 0644 -D -p USAGE /usr/share/greyhole
install -m 0755 -D -p build_vfs.sh /usr/share/greyhole
install -m 0644 -D -p docs/greyhole.1.gz /usr/share/man/man1/
install -m 0644 -D -p docs/greyhole-dfree.1.gz /usr/share/man/man1/
install -m 0644 -D -p docs/greyhole.conf.5.gz /usr/share/man/man5/
LIBDIR=/usr/lib
SMB_VERSION="`smbd --version | awk '{print $2}' | awk -F'-' '{print $1}' | awk -F'.' '{print $1,$2}' | tr ' ' .`"
mkdir "$LIBDIR/greyhole"
cp samba-module/bin/$SMB_VERSION/greyhole-$(uname -m).so "$LIBDIR/greyhole/greyhole-samba${SMB_VERSION//.}.so"
install -m 0644 -D -p greyhole.systemd /usr/lib/systemd/system/greyhole.service
cp $GREYHOLE_INSTALL_DIR/samba-module/vfs_greyhole-samba-4.x.c $GREYHOLE_INSTALL_DIR/samba-module/vfs_greyhole-samba-4.20.c
cp $GREYHOLE_INSTALL_DIR/samba-module/wscript-samba-4.x.patch $GREYHOLE_INSTALL_DIR/samba-module/wscript-samba-4.20.patch
$GREYHOLE_INSTALL_DIR/build_vfs.sh current
Fixing the Greyhole Implementation
Requires=mysqld.service smb.service
Mounting Shares Locally
There is a documented method to create a service that will mount shares locally on the server so that applications can write files that Greyhole will be able to see. The exact script didn't fit my requirements, so I made a few changes. The first thing we need to do is create a credentials file for our Samba user. This is a plain text file that contains the Samba username and password that Greyhole will use to mount the shares. I put my in my /greyhole/ folder and called it .smb_credentials. Using your favourite text editor, populate the file with a username and password. My sample file is below:
username=docker
password=**********
Now we need to create the mount_shares_locally service. Using your favourite text editor, create the file /etc/init.d/mount_shares_locally and modify the contents of the file to reflect the Greyhole configuration you are implementing. Mine is included below. For convenience, I have identified the specific sections I changed.
#!/bin/bash#### BEGIN INIT INFO# Provides: mount_shares_locally# Required-Start: $network $local_fs $remote_fs smb mysqld# Required-Stop: $network $local_fs $remote_fs smb# Default-Start: 2 3 4 5# Default-Stop: 0 1 6# Short-Description: mount Samba shares locally### END INIT INFOusername="docker"if [ -f /etc/rc.d/init.d/functions ]; then. /etc/rc.d/init.d/functionsfistart () {uid=`id -u $username`gid=`id -g $username`echo -n $"Mounting Samba shares locally: "mkdir -p /docker/mnt/cd /docker/mnttestparm -s /etc/samba/smb.conf 2>/dev/null | grep "^\[" | grep -v "\[global\]\|\[homes\]\|\[netlogon\]\|\[sysvol\]\|\[printers\]" | awk -F'[' '{print $2}' | awk -F']' '{print $1}' | xargs -d "\n" mkdir -psleep 5 opt="credentials=/greyhole/.smb_credentials,uid=${uid},gid=${gid},file_mode=0660,dir_mode=0770,nobrl,hard,_netdev,iocharset=utf8,noserverino,mfsymlinks"if mount.cifs 2>&1 | grep vers= >/dev/null; thenopt="$opt,vers=3.0"elif man mount.cifs 2>&1 | grep vers= >/dev/null; thenopt="$opt,vers=3.0"fiwhile IFS='' read -r d; doif [ "`mount | grep "//127.0.0.1/$d/* on " | wc -l`" = "0" ]; then/sbin/mount.cifs "//127.0.0.1/$d" "$d" -o $optelseecho " Share [$d] is already mounted."fidone < <(testparm -s /etc/samba/smb.conf 2>/dev/null | grep "^\[" | grep -v "\[global\]\|\[homes\]\|\[netlogon\]\|\[sysvol\]\|\[printers\]" | awk -F'[' '{print $2}' | awk -F']' '{print $1}')touch /var/lock/subsys/mount_shares_locallysuccess $"$base startup"echoreturn 0}stop () {echo -n $"Unmounting locally mounted Samba shares: "/bin/umount -l /docker/mnt/*rm -f /var/lock/subsys/mount_shares_locallysuccess $"$base shutdown"echoreturn 0}restart () {stopstart}case "$1" instart)start;;stop)stop;;restart)restart;;*)echo $"Usage: $0 {start|stop|restart}"exit 1;;esacexit $?
sudo chmod +x /etc/init.d/mount_shares_locallysudo systemctl enable mount_shares_locally
Bringing it all together
- Created our folder structure
- Installed MySQL
- Configured Samba
- Configured SELinux to allow our shares to work
- Built a storage pool
- Manually installed Greyhole
- Modified the Greyhole configuration to suit our environment
sudo systemctl daemon-reload
sudo service smb startsudo service greyhole start
#greyhole -sGreyhole Statistics===================Storage PoolTotal - Used = Free + Trash = Possible/greyhole/drive1/gh: 5544G - 2479G = 2786G + 67G = 2853G/greyhole/drive2/gh: 5081G - 2039G = 2785G + 12G = 2798G/greyhole/drive3/gh: 7392G - 4242G = 2777G + 64G = 2841G/greyhole/drive4/gh: 14783G - 11253G = 2786G + 66G = 2852G/greyhole/drive5/gh: 16696G - 13075G = 2783G + 82G = 2865G/greyhole/drive6/gh: 18551G - 14835G = 2785G + 36G = 2822G==========================================Total: 68048G - 47922G = 16703G + 327G = 17030G
sudo greyhole --fsck --delete-orphaned-metadata --find-orphaned-files --fix-symlinks
Let me know if you are able to replicate my results. I did A LOT of stuff that isn't included in this guide, but I've pared it down to just what I think I need to include. If you are having difficulty, let me know. We may be able to set up a working session to figure it out together, then I can update my docs.