Make driver disk for CentOS


If you want to make a generic USB driver disk for RHEL/CentOS, you can follow these instructions. The drivers are in rpm format, and you need those drivers during installation of a new system, primarily storage drivers.


On an existing CentOS system, install the dependencies.

yum -y install createrepo squashfs-tools

Change directory to where your rpms and make a new directory tree.

cd path/to/rpms
export SQUASH_ROOT=./squashfs-root
mkdir -p "${SQUASH_ROOT}/rpms/x86_64"

Make a specific file with any contents you wish.

echo "My custom driver disk" > "${SQUASH_ROOT}/rhdd3"

Make a yum repository

cp -p *rpm "${SQUASH_ROOT}/rpms/x86_64/"
createrepo --basedir "${SQUASH_ROOT}/rpms/x86_64/" .

Make the driver disk-only components.

touch "${SQUASH_ROOT}/.rundepmod"
( cd "${SQUASH_ROOT}" ;
   for thisrpm in "${SQUASH_ROOT}/rpms/x86_64/*rpm ;
      rpm2cpio "${thisrpm}" | cpio -imVd ./lib/*

And make the image file from the custom directory.

mksquashfs "${SQUASH_ROOT}" ./my-driver-disk.img

Clean up the custom directory if you’re done with it! The image is now complete and we will use it for the last step.

rm -rf "${SQUASH_ROOT}"

Deploy the image onto your preferred disk drive. Be sure you know which drive is the flash drive you want!

sudo dd if=/path/to/my-driver-disk.img of=/dev/sdz

The image file should be really small, so there is no need to control block size (bs=2048). Also, this disk will not be directly readable to a regular system, so do not let that alarm you.



  1. Red Hat Enterprise Linux and CentOS 7 Driver Disk
  2. Install CentOS 7 on HP ProLiant DL360 G5 with P400i SAS Controller | Knowledge Base

Glusterfs on CentOS 7 notes

Repos and packages to install.

sudo yum -y --enablerepo=extras install centos-release-gluster ;
sudo yum -y install glusterfs-server

Or just the client packages.

sudo yum -y --enablerepo=extras install centos-release-gluster ;
sudo yum -y install glusterfs-fuse glusterfs

If you encounter this error in the glusterfs log, nominally /var/log/glusterfs/$MNTNAME.log, it means the client version does not match the
server version.

[2019-11-08 21:26:53.707738] I [MSGID: 100030] [glusterfsd.c:2646:main] 0-/usr/sbin/glusterfs: Started running /usr/sbin/glusterfs version 3.12.2 (args: /usr/sbin/glusterfs --volfile-server=c7-03a --volfile-id=/gv1 /mnt/gv1)
[2019-11-08 21:26:53.814029] W [MSGID: 101002] [options.c:995:xl_opt_validate] 0-glusterfs: option 'address-family' is deprecated, preferred is 'transport.address-family', continuing with correction
[2019-11-08 21:26:53.830793] I [MSGID: 101190] [event-epoll.c:676:event_dispatch_epoll_worker] 0-epoll: Started thread with index 0
[2019-11-08 21:26:53.830902] I [MSGID: 101190] [event-epoll.c:676:event_dispatch_epoll_worker] 0-epoll: Started thread with index 1
[2019-11-08 21:26:53.890326] W [MSGID: 101095] [xlator.c:213:xlator_dynload] 0-xlator: /usr/lib64/glusterfs/3.12.2/xlator/features/ cannot open shared object file: No such file or directory
[2019-11-08 21:26:53.890369] E [MSGID: 101002] [graph.y:213:volume_type] 0-parser: Volume 'gv1-utime', line 61: type 'features/utime' is not valid or not found on this machine
[2019-11-08 21:26:53.890415] E [MSGID: 101019] [graph.y:321:volume_end] 0-parser: "type" not specified for volume gv1-utime
[2019-11-08 21:26:53.899127] E [MSGID: 100026] [glusterfsd.c:2473:glusterfs_process_volfp] 0-: failed to construct the graph
[2019-11-08 21:26:53.899488] W [glusterfsd.c:1462:cleanup_and_exit] (-->/usr/sbin/glusterfs(mgmt_getspec_cbk+0x532) [0x55c73804bb02] -->/usr/sbin/glusterfs(glusterfs_process_volfp+0x193) [0x55c738045633] -->/usr/sbin/glusterfs(cleanup_and_exit+0x6b) [0x55c738044b2b] ) 0-: received signum (-1), shutting down
[2019-11-08 21:26:53.899536] I [fuse-bridge.c:6611:fini] 0-fuse: Unmounting '/mnt/gv1'.
[2019-11-08 21:26:53.908659] I [fuse-bridge.c:6616:fini] 0-fuse: Closing fuse connection to '/mnt/gv1'.
[2019-11-08 21:26:53.908857] W [glusterfsd.c:1462:cleanup_and_exit] (-->/lib64/ [0x7f9f96227e65] -->/usr/sbin/glusterfs(glusterfs_sigwaiter+0xe5) [0x55c738044cc5] -->/usr/sbin/glusterfs(cleanup_and_exit+0x6b) [0x55c738044b2b] ) 0-: received signum (15), shutting down

To fix, use the same client version.

Install CentOS 7 on HP ProLiant DL360 G5 with P400i SAS Controller


You need to add the cciss.ko driver which has been removed from the kernel or CentOS 7 or whatever. Anyway, you can get it by using a driver disk.

Build the USB driver disk

Building the driver disk can be done on any Centos System. Install the dependencies for making a driver disk.

yum -y install wget createrepo squashfs-tools

Create the driver disk image using this script.

# Author: Ithanga
export CURR=`pwd`
export SQUASH_ROOT=${CURR}/squashfs-root
export VER=3.6.26-5
export RPM_PKG=kmod-cciss-${VER}.el7_5.elrepo.x86_64.rpm
mkdir -p ${SQUASH_ROOT}/rpms/x86_64/
echo "HP Smart Array CCISS driver ver. 3.6.26" > ${SQUASH_ROOT}/rhdd3
wget --directory-prefix=${SQUASH_ROOT}/rpms/x86_64/${RPM_PKG}
createrepo --basedir ${SQUASH_ROOT}/rpms/x86_64/ .
touch ${SQUASH_ROOT}/.rundepmod
rpm2cpio ${SQUASH_ROOT}/rpms/x86_64/${RPM_PKG} | cpio -imVd ./lib/*
cd ${CURR}
mksquashfs ${SQUASH_ROOT} ${CURR}/kmod-cciss-${VER}-driver-disk.img
rm -fr ${SQUASH_ROOT}

Insert a USB flash drive and write the image file to the correct disk. It can be as easy as:

time sudo dd if=/path/to/kmod-cciss-3.6.26-5-driver-disk.img of=/dev/sdz

Of course, make sure you use the right storage device. I noticed that when you fdisk -l or parted print the device afterwards, it doesn’t really show a whole lot, but it does work.

Create the CentOS 7 install dvd

A regular USB flash drive method will work here too. I don’t know about burning dvds; I haven’t done that for a long time. For my flash drive it was:

time sudo dd if=/path/to/CentOS-7-x86_64-Minimal-1810.iso bs=4096 of=/dev/sdz status=progress

It is important to note that the rpm in the above script is for the exact el7 release in this 1810 iso.

Loading the driver for the installation

Boot from the CentOS 7 install disk, and at the disc menu (where it asks “Install CentOS 7”, “Test this media…”, and “Troubleshooting … >”) hit Tab to edit the boot option.
Add the single parameter “dd” at the end, which will make it pause and ask you which partition to load drivers from.
You will have to choose which partition from the next menu, so if you cannot determine which partition is your driver disk, just try all of them. When you hit the right one, it will ask you which rpm to load. Select that driver based on the prompt, and then continue the installation.

Install like normal!

The story

I received an HP ProLiant DL360 G5 server which is about a decade old. I love old hardware, if it still runs. However, getting the driver for CentOS 8 proved to be impossible at this time. I investigated what kind of driver to use, and it appears to be either the cciss or hpsa kmods. The wonderful folks over at elrepo have packaged the cciss kernel module for el7 (CentOS 7) but have not yet accomplished this feat for el8.
I reverted to el7, and then had to load up the rpm on a driver disk.



  1. Ripped off entirely from No disk detected on ProLiant DL360 G5 – CentOS
  2. elrepo-packaged cciss driver

Auxiliary reading

  1. CentOS 7 x64 and HP Proliant DL360 G5 SCSI Controller compatibility – Server Fault
  2. trying hpsa driver which failed for me drivers – Install Fedora core 15 on HP Smart Array Controller HDD – Unix & Linux Stack Exchange
  3. Add kmod RAID driver in Centos 7 installer for HP Proliant – CentOS
  4. driver is not compiled for el8 yet 0000951: kmod-cciss driver for el8 – Mantis

Save firefox profile to 7zip file

Because one of my workstations is a non-persistent environment, I wrote a script to backup my Firefox profile. It uses a few tricks to do what I want it to do– serialize the filename, and encrypt even the filenames in the compressed file.

# File: \\storage2\c$\users\bgstack15\u_drive\vdi\save-firefox.ps1
# License: CC-BY-SA 4.0
# Author: bgstack15
# Startdate: 2019-11-05 11:24
# Title: Script that Saves Firefox Profile from VDI
# Purpose: Backup the entire Firefox directory because the VDI has nonpersistent sessions
# History:
# Usage:
# Reference:
# Improve:
# Documentation:
#  Assumptions:
#   The network location  has already been accessed, particularly because this script is hosted there and we need to dump a file there without having to authenticate.
#   7zip is installed in the VDI

# Define variables
# it is assumed I already access this network location so I do not need to authenticate
$outdir = "\\storage2\c$\users\bgstack15\u_drive\vdi"
$7z = "${env:ProgramFiles}\7-zip\7z.exe"
$today = Get-Date -Format yyyy-MM-dd
$indir = "${env:APPDATA}\Mozilla\Firefox"

# Functions
Function MyWait {
   Write-Host -NoNewLine 'Press any key to continue...'
   $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')

Function ToPlainText {
	#$inSecureString = ConvertTo-SecureString $PlainPassword
	$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($inSecureString)
	$outPlainString = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
	Return $outPlainString

# Main

# learn filename to use
$outfile = $outdir + "\firefox." + $today
# if file exists, change name.
while (Test-Path "${outfile}.${num}.7z")
   write-Host "Incrementing because ${outfile}.${num}.7z exists..."

# prompt for password
$pass1 = Read-Host -AsSecureString -Prompt "Generate a password"
$pass2 = Read-Host -AsSecureString -Prompt "Enter the password again"

# validate passwords
if (($pass1 | ToPlainText) -ne ($pass2 | ToPlainText))
   Write-Error -Category InvalidData -ErrorId "PasswordsMismatched" "Passwords do not match. Aborted."
   Exit 1
$passparam="-p$($pass1 | ToPlainText)"

# archive
Write-Host "$7z" -ArgumentList $passparam,"a","${outfile}",$indir
Start-Process -Wait -NoNewWindow "$7z" -ArgumentList "-mhe=on","$passparam","a","${outfile}",$indir

Thunar column widths

So I suffer from Thunar columns that reset for each new window. I just want to see the full name of each file!

I can resize the columns of course, however, I have to do it every single time. There’s a config setting that changes this!

View menu -> Configure columns… -> “Automatically expand columns as needed.”

After changing that setting, my new windows show the full filename! Hurray!



xfce – Thunar column width – Unix & Linux Stack Exchange

How I host a Devuan ceres mirror for myself

Building on what I learned a long time ago for building an apt repo on CentOS, and some guidance from the Devuan forum, I have now validated my local Devuan mirror.

I chose to use debmirror because it can be limited to just certain suites (that’s Debian-speak for “version”) and package repositories. I exclusively use Devuan ceres (testing) because I need the FreeIPA packages. And also CentOS had an rpm of debmirror.

I run my script on Sunday and weekdays.
Cron job:

0	9	*	*	0-5	root	/etc/installed/ 1>/dev/null 2>&1

And my script:

#!/usr/bin/env sh
# File: /etc/installed/
# Startdate: 2019-10-02 21:08
# Usage: by cron
{ debmirror --keyring /var/storage1/shares/public/Support/Platforms/devuan/keyrings/devuan-archive-keyring.gpg --verbose --config-file=/etc/debmirror.conf.devuan-ceres ; } 2>&1 | tee -a /var/storage1/shares/public/Support/Systems/storage1/var/log/debmirror/debmirror.devuan.$( date "+%F" ).log

Pretty basic, right? I had to prep the keyrings directory with the contents of a devuan install’s /usr/share/keyrings, but calling the debmirror was pretty easy. I pipe it to some logging as well.

Of course the debmirror.conf for this is extremely relevant.

# File: debmirror.conf.devuan-ceres
# Location: storage1:/etc/
# Author: bgstack15
# Startdate: 2019-09-27 22:43
# Title: Debmirror config for Devuan Ceres i386 and amd64 only
# Purpose: To provide a local mirror of devuan unstable so my clients can traverse only the local network
# History:
# Usage:
#    { time sudo debmirror --keyring /var/storage1/shares/public/Support/Platforms/devuan/keyrings/devuan-archive-keyring.gpg --verbose --config-file=/etc/debmirror.conf.devuan-ceres ; } 2>&1 | tee -a /var/storage1/shares/public/Support/Systems/storage1/var/log/debmirror/debmirror.devuan.$( date "+%F" ).log
# Reference:
#    how to get working keyring
# Improve:
# Documentation:
#    To get the gpg keyring, copy d2-02a:/usr/share/keyrings/ to /mnt/public/Support/Platforms/devuan/keyrings.
#    This setup will copy all the debian+devuan packages into one devuan/ directory. No amprolla or apache rewrites are necessary.
# Location of the local mirror (use with care)

# Output options

# Download options
# @ignores="";
# @excludes="";
# @includes="";
# @excludes_deb_section="";
# @limit_priority="";
# @rsync_extra="doc,tools";
# @di_dists="dists";
# @di_archs="arches";

# Save mirror state between runs; value sets validity of cache in days

# Security/Sanity options

# Cleanup

# Locking options

# Rsync options
$rsync_options="-aIL --partial";

# FTP/HTTP options
# $proxy="http://proxy:port/";

# Dry run

# Don't keep diff files but use them

# The config file must return true or perl complains.
# Always copy this.



  1. How to mirror ascii? / Other Issues / Dev1 Galaxy Forum
  2. Make a mirror of devuan package repository with a modified debmirror / Documentation / Dev1 Galaxy Forum
  7. how to get working keyring: Technical notes, my online memory: Debmirror of ubuntu archive, with valid gpg keys

Web searches

  1. devuan debmirror

Sample makefile

Here is a quick little makefile I use in small projects. It compiles all *.cpp files, and then links all *.o files into a single binary. It also includes a nice “list” target, which lists all the available targets. I realize bash tab auto-complete usually is good enough, but for programmatic uses, make list is helpful.

# references:
#    BUILD_DIR and per-.cpp file
awkbin     :=$(shell which awk)
cpbin      :=$(shell which cp)
echobin    :=$(shell which echo)
findbin    :=$(shell which find)
grepbin    :=$(shell which grep)
installbin :=$(shell which install)
rmbin      :=$(shell which rm)
sedbin     :=$(shell which sed)
sortbin    :=$(shell which sort)
truebin    :=$(shell which true)

CXX = g++

# to get full debug symbols, add to both FLAGS: -g
# to make all warnings act as errors: -Wall -Weffc++ -Wextra -Wsign-conversion -Werror
CXXFLAGS = -g -std=c++17 -Wall -Weffc++ -Wextra -Wsign-conversion -Werror

# to remove all debug symbols: -s
# to add full debug symbols: -g

src = $(wildcard *.cpp)
obj = $(src:.cpp=.o)


OUTEXE = mine

all: $(OUTEXE)

# compile, which is not actually used?
$(BUILD_DIR)%.o: %.cpp
	$(CXX) -c $(CXXFLAGS) $+

# link
$(OUTEXE): $(obj)
	$(CXX) -o $@ $^ $(LDFLAGS)

.PHONY: clean cleanall list

	@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | ${awkbin} -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | ${sortbin} | ${grepbin} -E -v -e '^[^[:alnum:]]' -e '^$@$$' -e '\.(cp*|o)'

	rm -f $(obj)

	rm -f $(obj) $(OUTEXE)