Update automatically a Linux Server
One of the basics in security is to have updated servers with the latest security versions. In a company, you may have access to variant automation tools for this, but for a personal usage or hobby, maintaining for server could be redundant and not very fun.
Here is some scripts and procedures to simplify your life. Be careful, this article will mostly concern the Red Hat family like CentOS or Rocky Linux, and some of these tools might not exists, or with another name, on other Linux Distributions like Debian.
Automate the package update
This part is not very difficult, just ask to the package manager !
For Red Hat family, we use dnf
to maintain the system up to date. You can place it into a script shell and it’ll update your system automatically.
Example for a full unattended system upgrade :
$ dnf update -y
In case you need to avoid some softwares or repositories, you may exclude them with the related commands.
$ dnf update -y --disablerepo <repo-to-ignore>
$ dnf update -y --exclude <package-to-ignore>
Reboot only when required
It’s a common knowledge for Linux system admins : you don’t need to reboot for the fun. However, when you want to automatize it, how do we know when the system requires a restart ?
Usually, Linux wants to restart when the Kernel was updated to boot the new one. We could do it stupidly by asking a reboot
every time dnf
is launched, but there is a more intelligent utility : needs-restarting
.
If the command needs-restarting
is not available, you can install it with dnf-utils
or yum-utils
.
With the argument -r
, needs-restarting
can tells you if the reboot is necessary or not. This tool can send more informations, but in our case it would be enough.
## when you don't need to reboot
$ needs-restarting -r
No core libraries or services have been updated since boot-up.
Reboot should not be necessary.
## when you need to reboot
$ needs-restarting -r
Core libraries or services have been updated since boot-up:
* kernel
Reboot is required to fully utilize these updates.
More information: https://access.redhat.com/solutions/27943
A nice thing with needs-restarting -r
is the exit code is different depending of restart required or not. If required, the commande will exit with 1, else with 0. So we can chain it to the update command in a small script like this.
#!/usr/bin/env bash
## launch dnf update
/usr/bin/dnf update -y
## check if restart is required
## if exit 0, no
## If other, then reboot
/usr/bin/needs-restarting -r && echo "Nope" || systemctl reboot
If you’re not used to this syntax, a small reminder :
- The
&&
operator (AND) tells the system to execute the second command only if the first one succeed. - The
||
operator (OR) tells the system to execute the third command only if the first failed.
This syntaxe is similar to a IF...THEN...ELSE
statement.
Now we just need to schedule it in the system scheduler. In /etc/cron.d
we create a file named system-update
that will contain our script. In this example, the script is scheduled every Monday morning at 2AM.
00 02 * * 1 root /usr/local/bin/system-update.sh
Start some containers at boot
As I use some containers with podman
, I want to have them starting up with the system.
Unitary containers
The good news is podman
is able to generate systemd
services files for a container. By executing the following command on a started container :
podman generate systemd --new --name mycontainer
This will return a ready to use service file. You can use by writing it directly into a file :
podman generate systemd --new --name mycontainer >> /etc/systemd/system/mycontainer.service
With that, you can start your container at boot with systemctl enable mycontainer.service
Containers maintained by podman-compose
The previous method does not work with podman-compose
because it removes the containers when stopping the deployment. So the service file won’t work.
However, the following service file can start a podman-compose
service and is usually working for me :
[Unit]
Description=MyContainer
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/podman-compose -f /path/to/docker-compose.yml up -d
ExecStop=/usr/bin/podman-compose -f /path/to/docker-compose.yml down
[Install]
WantedBy=multi-user.target
In the same way, just enable the service with systemd.
Run some scripts at startup
I have some cleanup and maintenance scripts running as background jobs at boot. But these scripts are not made to be executed as services. In case you have the same needs, you can easily start them at boot with Cron. Just add into the user’s contrab, or in /etc/cron.d
the following line :
@reboot /path/to/script.sh
Et voilà !
I hope you enjoyed these small tips. Don’t hesitate to share your or send your remarks with the contact section !