GitPedia

Dynmotd

Dynamic Motd (Message of the Day)

From rtulke·Updated June 13, 2026·View on GitHub·

Dynamic Message of the Day — a single Bash script that displays system information on login. The project is written primarily in Shell, first published in 2015. Key topics include: bash, bash-script, dynamic, logging, login-screen.

dynmotd

Dynamic Message of the Day — a single Bash script that displays system information on login.

Example

Features

  • Color schemes (switchable via config block at top of script)
  • Enable/disable individual information sections
  • Per-host description, environment label and SLA tag
  • Maintenance log with add/delete/list support
  • Automatic dependency installation on --install
  • --update for non-interactive binary updates (Ansible / Puppet / cron)
  • Multi-distribution support (Debian, RHEL, SUSE, Arch, Alpine families)
  • All IPv4 addresses + optional IPv6 from all active interfaces
  • Load average (1m / 5m / 15m) and realistic available memory (MemAvailable)
  • Graphical utilization bars for memory, swap and disk
  • Network interface state and link speed
  • Optional Fail2Ban section — summary, per-jail IP list, parallel reverse DNS
  • Optional Failed Systemd Services section (auto-hidden when all services are healthy)
  • Parallel section rendering for fast output
  • Update count cache to avoid slow package manager queries on every login
  • LDAP / AD / NIS user support via getent
  • Single self-contained shell script, no external dependencies beyond coreutils

Supported Linux Distributions

Distributions actively supported (last ~10 years, 2015 – 2026):

Debian family

DistributionVersions / ReleasesStatus
Debian8 (Jessie) – 12 (Bookworm)Tested
Ubuntu16.04 LTS – 24.04 LTSTested
Linux Mint18 – 22Tested
Raspberry Pi OSBullseye, BookwormTested
Kali LinuxRolling (2020+)Tested
Pop!_OS20.04 – 22.04Compatible
Elementary OS6 – 7Compatible
MX Linux19 – 23Compatible
Devuan3 – 5Compatible
Zorin OS16 – 17Compatible

RHEL family

DistributionVersionsStatus
CentOS7, 8, Stream 8/9Tested
RHEL7, 8, 9Tested
Rocky Linux8, 9Tested
AlmaLinux8, 9Tested
Fedora35 – 41Tested
Oracle Linux7, 8, 9Compatible
CloudLinux7, 8Compatible

SUSE family

DistributionVersionsStatus
openSUSE Leap15.xTested
openSUSE TumbleweedRollingTested
SLES12, 15Compatible

Arch family

DistributionVersionsStatus
Arch LinuxRollingCompatible
ManjaroRollingCompatible
EndeavourOSRollingCompatible

Other

DistributionVersionsStatus
Alpine Linux3.xCompatible

"Tested" = verified by the author. "Compatible" = dependency auto-install supported, not explicitly tested.
Tell me if you have verified it on a distribution not listed here.

Installation

The script must run as root.

bash
sudo -i git clone https://github.com/rtulke/dynmotd.git cd dynmotd ./dynmotd.sh --install

--install automatically:

  1. Detects your Linux distribution
  2. Installs any missing dependencies via your native package manager
  3. Copies the script to /usr/local/bin/dynmotd
  4. Creates /etc/profile.d/motd.sh so dynmotd runs on every login
  5. Runs first-time environment setup (function, environment label, SLA)

To verify the installation, log out and back in:

bash
exit sudo -i

Manual dependency installation

If you prefer to install packages yourself before running --install:

Debian / Ubuntu / Raspberry Pi OS / Mint

bash
apt update && apt install -y coreutils procps hostname sed gawk grep dnsutils lsb-release

CentOS 7 / RHEL 7

bash
yum install -y hostname procps-ng gawk bind-utils

CentOS Stream 8-9 / Rocky / AlmaLinux / RHEL 8-9

bash
dnf install -y hostname procps-ng gawk bind-utils

Fedora

bash
dnf install -y hostname procps-ng gawk bind-utils

openSUSE / SLES

bash
zypper install -y hostname procps gawk bind-utils lsb-release

Arch / Manjaro

bash
pacman -Sy inetutils procps-ng gawk bind

Alpine Linux

bash
apk add bind-tools busybox-extras procps gawk

Usage

Usage: dynmotd [OPTION] [value]

  e.g.  dynmotd -a "deployed new SSL certificate"

Options:

  -a | --addlog "..."           Add a maintenance log entry
  -d | --rmlog  [line-number]   Delete a log entry by line number
  -l | --log                    List all log entries
  -c | --config                 Reconfigure environment settings
  -i | --install                Install dynmotd and its dependencies
  -U | --update                 Update binary only (no setup, safe for Ansible/cron)
  -u | --uninstall              Uninstall dynmotd (log deletion is optional)
  -v | --version                Show version and exit
  -h | --help                   Show this help

Uninstall

bash
dynmotd --uninstall

The uninstaller asks two separate questions:

  1. Whether to delete the log and configuration data in /root/.dynmotd/
  2. Final confirmation before removing the binary and profile hook

System packages that were installed as dependencies are never removed automatically. Remove them with your package manager if desired.

Update

To update an already-installed dynmotd to a newer version without running the full setup again:

bash
cd dynmotd git pull sudo bash dynmotd.sh --update

--update only replaces the binary at /usr/local/bin/dynmotd. It does not ask setup questions, does not touch logs or configuration, and does not reinstall packages — safe to run from Ansible, Puppet, or a cron job.

Configuration

Edit the config block at the top of the installed script:

bash
vim /usr/local/bin/dynmotd

Enable / disable sections

Each section has an _INFO toggle and an optional _ALWAYS override:

VariableDefaultDescription
SYSTEM_INFO1System info (hostname, IP, kernel, CPU, memory, load)
STORAGE_INFO1Storage / disk usage with utilization bars
NETWORK_INFO1Network interfaces — state and link speed
USER_INFO1User sessions and SSH keys
UPDATE_INFO1Available package updates
UPDATE_ALWAYS0Show Update section even when UPDATE_INFO="0"
ENVIRONMENT_INFO1Environment label (function, env, SLA)
FAILED_SERVICES_INFO1Failed systemd services (auto-hidden when none failed)
FAILED_SERVICES_ALWAYS0Always show Failed Services, even when all healthy (= none)
FAIL2BAN_INFO1Fail2Ban summary — total banned + jail overview
FAIL2BAN_ALWAYS0Always show Fail2Ban, even if not installed
SHOWFAIL2BAN_IPS1List banned IPs per jail (no DNS, no delay)
RESOLVEFAIL2BAN_IPS1Resolve banned IPs via reverse DNS (parallel, requires SHOWFAIL2BAN_IPS="1")
MAINTENANCE_INFO1Maintenance log entries
MAINTENANCE_ALWAYS0Show Maintenance section even when MAINTENANCE_INFO="0"
WEATHER_INFO1Weather via wttr.in (auto-hidden if curl unavailable or fetch fails)
WEATHER_ALWAYS0Always show Weather section, even if fetch fails (= unavailable)
WEATHER_CITY(empty)City for weather lookup — empty = auto-detect from server IP
WEATHER_CACHE_HOURS1Hours before weather data is re-fetched (0 = always live)
WEATHER_UNITS(empty)Unit system: m = metric, u = USCS, M = wind in m/s (empty = wttr.in default)
VERSION_INFO1Version banner

1 = enabled, 0 = disabled.

Section display order

Sections are rendered in this fixed order:

  1. System Info
  2. Weather
  3. Storage Info
  4. Network Interfaces
  5. User Data
  6. Update Info
  7. Environment Data
  8. Failed Services
  9. Fail2Ban
  10. Maintenance Information
  11. Version banner

Maintenance log display

bash
LIST_LOG_ENTRY="2" # number of log lines shown in the MOTD

Update cache

bash
UPDATE_CACHE_HOURS="6" # hours before the update count is refreshed (0 = always live)

The update cache avoids running a full package manager check on every login. The cached count is stored in /root/.dynmotd/update_cache and refreshed automatically when it expires.

Color schemes

Seven schemes are pre-defined. Uncomment exactly one block to activate it (F1 = labels, F2 = borders, F3 = values, F4 = warnings):

#NameCharacter
1DOT (default)grey labels · pink borders · green values
2Retro Hackerall green, Matrix style
3Retro Alertall red, maximum urgency
4Oceancyan/blue, cool and professional
5Solarized Darkgrey with warm yellow accent
6Nordice blue, clean and modern
7Amberbrown/yellow, classic CRT terminal

Example — switching to Nord:

bash
vim /usr/local/bin/dynmotd

Comment out the active scheme and uncomment Nord:

bash
## 1. DOT - day of the tentacle (default) #F1=${C_GREY} #F2=${C_PINK} #F3=${C_LGREEN} #F4=${C_RED} ## 6. nord — ice blue, clean and modern F1=${C_LBLUE} F2=${C_LCYAN} F3=${C_WHITE} F4=${C_YELLOW}

Known Issues

Hostname not displayed correctly

The Hostname field uses hostname --fqdn. If /etc/hostname contains only the short name, only the short name is shown. Fix:

bash
hostname mail.example.com hostname > /etc/hostname

Also check /etc/hosts:

127.0.1.1  mail.example.com

Note: The Address v4 / Address v6 fields are read directly from network interfaces via ip -brief addr show and are not affected by hostname resolution.

SSH key shows "- Unknown -"

This happens when the key has no comment field. Either add a comment to the end of the key line in ~/.ssh/authorized_keys, or generate keys with:

bash
ssh-keygen -C "your.name@example.com"

Contributors

Showing top 2 contributors by commit count.

View all contributors on GitHub →

This article is auto-generated from rtulke/dynmotd via the GitHub API.Last fetched: 6/29/2026