Forward ROOT mail to a user

To forward all root emails to a user you can add an entry in the aliases file, like:

root: sam

After updating the aliases run the command below.

newaliases /etc/aliases

Restart your mail server and you should see all root emails being sent to the user specified in the aliases file. A different process can be used to achieve the same behavior by making an entry in the .forward file of the root but I haven’t tried that as I prefer to have it done with aliases.

Setup Couchpotato with virtualenv

I run Couchpotato on my media server and since the project isn’t actively maintained it doesn’t run on python3. My linux os dropped having pip2.7 available by default likely to encourage people to migrate to python3, I decided to run it in a python virtual environment to break the apps dependency on the system python support. Below are the steps I took to get it running.

Setup virtualenv

Python3 comes with venv or creating virtual enviroments but venv doesn’t support creating environments with python2.7. Current versions of virtualenv also don’t support python2.7 so we have to install a version that has this support we will go with version 20.21.1

pip install virtualenv==20.21.1

Create your virtual environment directory I created this inside the couchpotato project but you can also place it outside if you intend to use it with more than one project.

mkdir couchpotatoserver/.venv/

Point the virtualenvironment to the actual path of your python2.7 binary

virtualenv --python=/usr/bin/python2.7 /<path>/couchpotatoserver/.venv/

This will install python2.7 and a compatible pip version in the virtual environment.

Use virtualenv

You should be able to install all your needed dependencies from the couchpotato requirements file with the pip cmd. Use the path to the pip binary to make sure the dependencies get installed in your virtual environment and not the OS.

.venv/bin/pip install -r requirements-dev.txt

Just as we had to install a specific version of virtualenv which supports Python2.7 we will need to install specific versions of 2 other libraries needed by couchpotato in our virtual environment.

.venv/bin/pip install cryptography==2.2.2
.venv/bin/pip install PyOpenSSL==17.5.0

Update whichever script you are using to startup couch potato to use the Python installed in the virtual environment, it is very important to reference the actual path otherwise by omitting the path you will be using the system level Python version which will cause startup to fail.

/<root-path>/couchpotatoserver.venv/bin/python /apps/couchpotatoserver/CouchPotato.py

You should now be able to startup your couchpotato service using your virtual environment and should be safe from future OS updates breaking your setup. This documentation assumes you already have an existing couchpotato setup already, the setup of couchpotato is outside scope of this notes.

Update Remi PHP to next version

Since Centos ships with an old PHP version, there are many tutorials on how to install Remi PHP which enables you to use more modern versions of PHP on your site. But when it came time to update from PHP72 to php73/4 I couldn’t find a lot of docs on this so I decided to put this one up to remind me next time am doing this.

First, we will need to enable the PHP version we want to install such as below.

# yum-config-manager --enable remi-php73
# yum-config-manager --enable remi-php74

In my case, I was moving from php72 to 73 before 74 so I enabled 73 and disabled 72.

# yum-config-manager --enable remi-php73
# yum-config-manager --disable remi-php72

After enabling the version you want to move to and disabling your current version, run yum update and restart your webserver.

# yum update
# apachectl restart

To validate the update was successful check the current version of PHP as reported in your terminal, and those are the steps needed to move from one Remi PHP version to another.

# php -v
PHP 7.3.29 (cli) (built: Jun 29 2021 09:30:31) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.29, Copyright (c) 1998-2018 Zend Technologies

Running KVM and docker on the same host with a bridge

I have been running kvm with a bridge on my fedora machine for a while, when trying to run docker on the same host access to the kvm hosts would die as soon as docker came up. I read up online and most places mention that the two technologies should be able to co-exist with each other without any problems, after some further searching I was able to find an article that mentioned that if you have already setup a bridge for KVM you can tell docker to use this bridge. I was able to test this on my setup and it worked allowing docker to run without interfering with the existing bridge. Looking at the interfaces I can still see docker created an interface docker0 but it doesn’t seem to be active.

The docker configuration involved adding this file /etc/docker/daemon.jsonwith the following entry.
{ "bridge": "br0" }
Make sure the bridge number matches your existing bridge number in use by kvm.

Converting selinium code to headless tests with PhantomJS

The word test here is used ambiguously as I use selenium for more than just UI tests, it makes a great tool for browser automation which I use it for this purpose a lot. While writing your browser automation most of the time it’s easier to do it in browser mode by using the firefox or chrome driver so that you can visually inspect the HTML. Once you are done writing the code and finished testing sometimes you would prefer to switch it to headless mode so that it can be run without having a UI, at which point you are likely to tryout PhantomJS driver and your fully tested code starts throwing all sorts of errors like “Element not found” or “Stale Element Exception”. If all this errors go away if you switch back to chrome or firefox driver then the likeliest cause of your troubles is you might need to add delays in most places where you have the browser loading new data compared to the other browser drivers.
To me this seemed a bit counter intuitive at first as I though headless mode should run faster therefore requiring even less time to load UI changes, but I guess it might actually take a little longer since all the browser rendering is being done is software only. Just thought to put this out there as I have run into the issue a few times.

Automate letsencrypt certificate renewal

I recently switched from self signed certs to free SSL certs from letsencrypt and for the first time I could load my https url without getting the annoying prompt from chrome due to self signed certificates. The only problem is the certs expire pretty fast in about 90 days as of this writing, while this is nothing to complain about since the certs are free handling the renewal each time manually would be a pain and also leave me in a bind in case I forgot to do it.
I decided to automate the renewal process to save myself the hassle of having to do it manually and found two resources here and here on how to do it, I went with a combination of the two methods as my requirements were different.
I wanted the renewal to be run from a script to support email notification on success or failures which is similar to the first source and use the webroot plugin to perform renewal as it has lesser steps to perform renewal reducing any failure points during the process like the second source. The script needed to be able to run everyday and check cert expiration I didn’t want to hard code the cron job to run based on how long the certs are valid that way if letsencrypt changes the life of the certs no change is required on my side.
Let’s get started I won’t cover the install as that’s covered by letsencrypt site, I would advise you to read the different install methods and choose the one that best fits your needs.
After performing the install
Create your config file which will contain the arguments submitted to letsencrypt api I named mine “muthii.com.ini”

rsa-key-size = 4096
server = https://acme-v01.api.letsencrypt.org/directory
text = True
authenticator = webroot
agree-tos = True
renew-by-default = True
email = root@domain.com
webroot-path = /your/webserver/path

Run the command used to create/renew your certs, which creates the certs for you and shows you the path to find them.
[cc lang=”bash”]/root/.local/share/letsencrypt/bin/letsencrypt -c /path/muthii.com.ini -d muthii.com -d www.muthii.com auth[/cc]

Only run the above command if you haven’t created your certs or are ready to renew your current certs, otherwise just grab the script file and add it to your cron. Make sure to change the emails and file paths based on your setup. I have commented out the echo statements and only enable then for testing

For someone doing this for the first time locate your ssl.conf file used by your server and set the paths to the new certs

SSLCertificateFile /etc/letsencrypt/live/domain.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain.com/fullchain.pem

Once you are done setting up head over to SSLLabs and test your certificate is recognized as expected, then setup a cron job to run the script daily .

0 2 * * * sh /path/SSLRenew.sh

CIFS VFS: cifs_mount failed w/return code = -2

I hit this error while adding a samba mount to my fstab, but mounting the same end point would work when executed from command line. For my scenario it turns out that it might be an issue with cifs-utils or kernel if your mount point is under more than one sub-directory. My solution was to go with option 3 and have my target as a share


"//host.IPAddress/share/subdir/subdir/target" - This failed with error "CIFS VFS: cifs_mount failed w/return code = -2"
"//host.IPAddress/share/target" - This worked
"//host.IPAddress/target" - This worked

Owncloud Error: Console has to be executed with the same user as the web server is operated

After a recent Owncloud 8.o.x update I started getting this error being logged whenever the owncloud cron job run. To resolve the issue I had to change the cron job to be run as the user apache.

su -s /bin/sh apache -c "php -f /path/to/owncloud/cron.php"

The webserver on CentOS is run under the user apache, on other linux flavous it’s www-data to find out what it is on your system just check the error being logged it will log the user running the webserver.


Console has to be executed with the same user as the web server is operated
Current user: someuser
Web server user: apache <- This is the user you want. Unexpected error!

FreeNX – 1004 Error: NX Agent exited with exit status 1

This error is very generic and while googling I found different issues can cause it. I was able to resolve it this particular instance by creating the folders


/tmp/.X11-unix - as root
/tmp/.ICE-unix - as user logging in

and file
/tmp/.X0-lock - as root

Which had been deleted while manually cleaning up a previous session. The statement below was also logged when this error occured but it to appears to be a generic error logged for different cases whenever a session fails.

596 Session startup failed

KVM usage tips

I have been playing around with KVM lately, just to see how it stacks up against VirtualBox and am loving it. I have found the following commands interesting while working with VMs.

List all VMs
virsh list --all

Start stop a VM
virsh start/stop vmName

Clone VM
virt-clone --original vmName --name newVmName --file /some/path/newVmName.qcow2

Clone VM and assign Random Mac address to new image
virt-clone --original vmName --name newVmName --file /some/path/newVmName.qcow2 --mac=RANDOM
Copy over the xml for the new clone which you can use to define your clone if moving the image to another host
cp /etc/libvirt/qemu/newVmName.xml /some/path/newVmName.xml

Shrink/Sparcify VM image
virt-sparsify --format qcow2 --compress vmName.bkp.qcow2 vmName.qcow2 --tmp /some/path
This command assumes you renamed the original VM image file to “vmName.bkp.qcow2” incase the new image has problems you can revert to original image. You can skip the –tmp argument if you have more than double the size of the VM image available in your /tmp directory. You will need to make sure you have package “libguestfs-tools” installed which supplies the sparsify command.

Delete VM
virsh undefine vmName
This removes the XMl configuration for qemu you might have to delete the VM image yourself.

List storage pools
virsh pool-list

Refresh pool data
virsh pool-refresh poolName
You will need to run this command if you delete a VM and you need to reuse the VM name you had used, so make sure you refresh the pool where your deleted image was located.

Disable autostarting of a VM

virsh autostart vmName --disable

Move VM to another system Offline
Step 1 from original host shutdown your VM, copy xml and image to backup location.

virsh dumpxml vmName > /bkpLocation/vmName.xml
cp /locationofVMs/vmname.qcow2 /bkpLocation/vmName.qcow2

Bye default if you didn’t change image storage location it will be “/var/lib/libvirt/images”. I prefer to store them in a separate partition from the OS.

Step 2 on new host get VM xml and image and enjoy.

virsh define /bkpLocation/vmName.xml
Domain vmName defined from /bkpLocation/vmName.xml
virsh start vmName

This all works if you are moving from host1 and host2 with similar cpus, for my purpose host2 had a different cpu type so I had to first create a new vm in host2 and compare the xml with my backed up copy then changed a few lines specific to CPU on host2.