Creating a Simple systemd Service to Launch Shell Script on System Boot

We will setup a simple systemd service to automatically run a bash script on system boot.

Create systemd file

Create the service file with

vi /etc/systemd/system/

Now fill out the file. Change the Description and ExecStart. After= means only start this unit after the other units have finished. This is needed if we need to make a network connection. If our script runs before the network is up, the connection will fail.

Description=systemd Unit File to Launch Bash Script on System Boot



Change the ExecStart to your bash script and save the file

Enable systemd file

Now that the file is created, we need to enable the service so it starts on system boot

systemctl enable bashscript.service

You should get the following output.

Created symlink /etc/systemd/system/ → /etc/systemd/system/bash.service.

Now to test, reboot your system, or start the service with

systemctl start bashscript.service

How to Bypass NVIDIA NVENC Limits on RTX Cards on Linux

It appears that NVIDIA has limited the number of NVEncoding streams on consumer GPUs. Guess it is so people have to buy the more expensive professional cards.

Fortunately, the limit is only applied to the driver, and there is a patch available that let’s us bypass the limiter.

Install Patch

This assumes you already have the driver installed. If you do not, or run into issues with the commands below, refer to the above link.

Download the tool


Unzip the file


Run the patch script

cd nvidia-patch-master
sudo bash ./

And we are finished!

Further reading

NVIDIA has a matrix of which cards support how many streams etc.

And while we are on the topic of artificial limits, check out the vGPU license bypass

How to POST a message to a Telegram Channel

It’s fairly easy to send a message to a Telegram Channel using curl. Copy and paste the following command in, replacing the API_TOKEN, chat_id, and test_message, with the appropriate items.

curl -s -o /dev/null -X POST -H "Content-Type: application/json" -d "{\"chat_id\": \"-100XXXXXXXXXX\", \"text\": \"test_message\", \"disable_notification\": true}"{API_TOKEN}/sendMessage

Need to send a message to Teams? Check out the following post.

Bash script to send messages to Microsoft Teams

How to Read git Object File Without git?

Git object files are a zlib compressed data file type.

We can check this by running the file command. “6ae4147121f0165e7c0e309bad649c2c4d3a55” is our git file of interest.

$ file 6ae4147121f0165e7c0e309bad649c2c4d3a55
6ae4147121f0165e7c0e309bad649c2c4d3a55: zlib compressed data

The above link has helpful information. Easiest way I found was to install zlib-flate by installing qpdf with apt.

sudo apt install qpdf

We can now use the zlib-flate command with the -uncompress option to decompress the file and print the contents.

$ zlib-flate -uncompress < 6ae4147121f0165e7c0e309bad649c2c4d3a55
var b64 = ("");

Redirect website HTTP to HTTPS using the .htaccess file

The following can be added to the .htaccess file to redirect all http request to https.

RewriteEngine On
RewriteCond %{HTTPS} off  
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteEngine On – Allows the rewrite capabilities. If it was off, the last rule “RewriteRule” would not work.
RewriteCond – This is a conditional that says if the current request is using HTTPS, don’t rewrite. If this option was not here, we would get an infinite redirect loop.
RewriteRule – This is the actual rule that rewrites or redirects any HTTP request to HTTPS. the R=301 means that it redirects using a 301 status code.

The following links provide more detail and info on htaccess redirects.

Raspberry Pi – Blink Light – Python

A Simple Python script to blink a Raspberry Pi LED.

import RPi.GPIO as GPIO
from time import sleep

GPIO.setmode(GPIO.BOARD)  # Uses the physical pin numbering
GPIO.setup(7, initial=GPIO.LOW)  # Set GPIO pin to off

while True:
    GPIO.output(7, GPIO.HIGH)
    GPIO.output(7, GPIO.LOW)

Change pin numbers as needed.

We can also do this with BASH.

Control LED using BASH

SELinux Audit Commands and Links

Show what and why something is failing

audit2why < /var/log/audit/audit.log

Search with ausearch

ausearch -m avc --start recent

Create and apply a module to fix the failure

This creates two files, a .pp and .te. The .pp is the compiled version of the .te

audit2allow -M mymodule < /var/log/audit/audit.log
semodule -i mymodule.pp

Note that “mymodule.pp” will replace any previous “mymodule.pp”. If your needing to create multiple modules/allow multiple exceptions, you can change the name of each module.

You can also add the rules together then manually compile it. Refer to the first link for more details.

Links with more info

Error Starting Peertube “no such file or directory, open ‘/var/www/peertube/storage/tmp/plugins-global.css”

systemctl status peertube shows the following error.

Error: ENOENT: no such file or directory, open ‘/var/www/peertube/storage/tmp/plugins-global.css’

Looks like an error because the global.css file is not there. You can temporarily fix the issue by creating the file.

su peertube
touch /var/www/peertube/storage/tmp/plugins-global.css

Probably an issue with a plugin being installed or something of the sort.

Setting up RRDReST on CentOS 8 or AlmaLinux 9

There are some differences on setting up RRDReST on CentOS 8, Almalinux 9 vs CentOS 7

If you are setting this up to use with LibreNMS and Grafana, check out the rest of the this article.

Installing RRDReST

All the docker commands have been swapped out for podman.

  1. Install Docker
  2. Create a compose file
  3. Run compose file to create container

Install docker

Podman is default on CentOS 8 and later and is for the most part a drop in replacement for Docker.

sudo yum install -y podman podman-compose
sudo systemctl enable podman

Create podman-compose file

Create docker compose file with the following options

vi podman-compose.yml

Change the TZ to your time zone. If you have issues with the graphs, most likely something is off with the time zone between this container and Grafana/LibreNMS server

version: "3.5"


    image: michaelwadman/rrdrest:latest
    container_name: rrdrest
    restart: always
      - "/opt/librenms/rrd:/opt/librenms/rrd:Z"
      - TZ=America/Denver

Note that the :Z is needed for SELinux to allow RRDReST to access the sub folders. AKA. the rrd files.

Run RRDReST Container

Save the file and start and setup the container with

sudo podman-compose up -d

You will need your docker container IP address to setup the connection in Grafana

sudo docker exec -it rrdrest ip addr | grep eth0

Configure RRDRest to start on system boot with systemd

The “restart: always” option does not appear to work on systems with podman. We can create a systemd service instead.

Use the following command to automatically create a

podman generate systemd rrdrest

Copy the contents to a new file in


Enable the new service with

systemctl enable rrdrest

Congratulations. RRDReST is now setup and running.

Dual Zones in Firewalld (Public/Private or External/Internal)

In Firewalld we can use multiple zones for different types of traffic. For instance, we can setup an “internal” zone with our local IP addresses that are trusted, and then setup the public facing interface to the “drop” or “block” zone to block everything not from our internal network.

  1. Setup trusted IP addresses in the “internal” zone
  2. Configure services/ports that should be allowed on our “internal” zone
  3. Set “drop” zone as the default for all other traffic
  4. Reload firewall

1. Setup trusted IP addresses in “internal” zone

Add all of our trusted IP addresses to the internal zone. The following example adds all of the private IP addresses “RFC 1918” to the internal zone. Change as needed.

firewall-cmd --zone=internal --add-source= --add-source= --add-source= --permanent

2. Configure services/ports that should be allowed on our “internal” zone

Next we need to specify which services or ports should be accessible in our trusted zone.

Here is an example to allow https, ssh, and cockpit services

firewall-cmd --zone=internal --add-service=https --add-service=ssh --add-service=cockpit --permanent 

Here is an example to allow port 8080 tcp

firewall-cmd --zone=internal --add-port=8080/tcp --permanent

3. Set “drop” zone as the default for all other traffic

The final configuration piece we need to do is set the default zone. Anything not specified in other zones will get processed by the default zone.

firewall-cmd --set-default-zone=drop

The drop zone drops everything.

4. Reload firewall

Reload the firewall with

firewall-cmd --reload

Verifying changes

Let’s verify the changes with the firewall-cmd –get-active-zones command

# firewall-cmd --get-active-zones
  interfaces: en0

You can also use

firewall-cmd --list-all-zones

to list all the zones. Active zones show (active) next to them.

You can verify that your changes worked by doing an internal and external nmap scan.

If you have issues with services still being accessible from the outside, try disabling Network Manager for that specific interface

You can edit the ifcfg-eth0 file and add