netsapiensis

rocky-core-system

0
0
# Install this skill:
npx skills add netsapiensis/claude-code-skills --skill "rocky-core-system"

Install specific skill from multi-skill repository

# Description

Rocky Linux 8/9 core system administration including dnf/yum package management, module streams, systemd service and timer management, user/group administration, sudo configuration, and cron scheduling. Use when managing packages, services, users, or scheduled tasks on Rocky Linux.

# SKILL.md


name: rocky-core-system
description: Rocky Linux 8/9 core system administration including dnf/yum package management, module streams, systemd service and timer management, user/group administration, sudo configuration, and cron scheduling. Use when managing packages, services, users, or scheduled tasks on Rocky Linux.


Rocky Linux Core System Administration

Package management, systemd services, user administration, and task scheduling for Rocky Linux 8/9.

Prerequisite: See rocky-foundation for OS detection and safety tier definitions.

Package Management

DNF Basics

# Search for packages  # [READ-ONLY]
dnf search nginx
dnf info nginx
dnf provides /usr/sbin/nginx

# List installed packages  # [READ-ONLY]
dnf list installed
dnf list installed | grep php
rpm -qa --last | head -20        # Recently installed

# Install packages  # [CONFIRM]
dnf install -y nginx

# Remove packages  # [CONFIRM]
dnf remove nginx

# Update system  # [CONFIRM]
dnf update -y

# Update single package  # [CONFIRM]
dnf update -y openssl

# Check for available updates  # [READ-ONLY]
dnf check-update

Version Differences: DNF

Feature Rocky 8 (dnf 4) Rocky 9 (dnf 5)
Config manager dnf config-manager --set-enabled Same syntax
Module streams Extensive use Reduced, some removed
Automatic updates dnf-automatic dnf-automatic (same)
Groups dnf group install Same syntax
History dnf history Same syntax, improved output

Module Streams

Module streams provide multiple versions of software. Rocky 8 relies on them heavily; Rocky 9 less so.

# List available module streams  # [READ-ONLY]
dnf module list
dnf module list php
dnf module list --enabled

# Enable a module stream  # [CONFIRM]
dnf module enable php:8.0 -y          # Rocky 8
dnf module enable php:8.2 -y          # Rocky 8 (if available from Remi)

# Reset a module stream (to switch)  # [CONFIRM]
dnf module reset php -y
dnf module enable php:8.0 -y

# Install module profile  # [CONFIRM]
dnf module install php:8.0/common -y

WRONG -- switching streams without reset:

# WRONG: This will fail or cause conflicts
dnf module enable php:8.0 -y  # Already had 7.4 enabled

CORRECT -- switching streams:

# CORRECT: Reset first, then enable new stream
dnf module reset php -y
dnf module enable php:8.0 -y
dnf module install php:8.0/common -y

Repository Management

# List repos  # [READ-ONLY]
dnf repolist
dnf repolist all                  # Including disabled

# Enable/disable repos  # [CONFIRM]
dnf config-manager --set-enabled crb          # Rocky 9 CodeReady Builder
dnf config-manager --set-enabled powertools   # Rocky 8 PowerTools

# Add a repo file  # [CONFIRM]
dnf config-manager --add-repo https://example.com/repo.repo

# Clean caches  # [CONFIRM]
dnf clean all
dnf makecache

EPEL Setup

# Install EPEL  # [CONFIRM]
dnf install -y epel-release

# Rocky 9: also enable CRB for EPEL dependencies
ROCKY_VERSION=$(source /etc/os-release && echo "${VERSION_ID%%.*}")
if [[ "$ROCKY_VERSION" == "9" ]]; then
    dnf config-manager --set-enabled crb  # [CONFIRM]
fi

DNF History and Rollback

# View transaction history  # [READ-ONLY]
dnf history
dnf history info 15

# Undo a transaction  # [CONFIRM]
dnf history undo 15 -y

# Rollback to a point  # [CONFIRM]
dnf history rollback 12 -y

Automatic Updates

# Install dnf-automatic  # [CONFIRM]
dnf install -y dnf-automatic

# Configure: /etc/dnf/automatic.conf
# apply_updates = yes          # Auto-apply updates
# emit_via = email             # Notification method

# Enable timer  # [CONFIRM]
systemctl enable --now dnf-automatic.timer

# Check timer status  # [READ-ONLY]
systemctl status dnf-automatic.timer
systemctl list-timers dnf-*

Service Management (systemd)

Basic Service Operations

# Status and inspection  # [READ-ONLY]
systemctl status nginx
systemctl is-active nginx
systemctl is-enabled nginx
systemctl show nginx --property=MainPID,ActiveState,SubState

# Start/stop/restart  # [CONFIRM]
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx           # Graceful reload (preferred)

# Enable/disable at boot  # [CONFIRM]
systemctl enable nginx
systemctl disable nginx
systemctl enable --now nginx     # Enable + start in one command

# Mask a service (prevent starting)  # [CONFIRM]
systemctl mask postfix
systemctl unmask postfix

List and Inspect Services

# List all services  # [READ-ONLY]
systemctl list-units --type=service
systemctl list-units --type=service --state=running
systemctl list-units --type=service --state=failed
systemctl list-unit-files --type=service

# Show service dependencies  # [READ-ONLY]
systemctl list-dependencies nginx
systemctl list-dependencies --reverse nginx

Journal Logs

# View service logs  # [READ-ONLY]
journalctl -u nginx
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2024-01-15 10:00" --until "2024-01-15 11:00"
journalctl -u nginx -f                  # Follow (live tail)
journalctl -u nginx -n 50               # Last 50 lines
journalctl -u nginx -p err              # Only errors
journalctl -u nginx --no-pager          # Don't page

# System-wide logs  # [READ-ONLY]
journalctl -p err --since today
journalctl --disk-usage                  # Check journal disk usage
journalctl -b                            # Current boot only
journalctl -b -1                         # Previous boot

Version Differences: systemd

Feature Rocky 8 (systemd 239) Rocky 9 (systemd 252)
systemctl edit Creates override Same, improved
Portable services Limited Full support
systemd-sysext Not available Available
Credential passing Not available LoadCredential=
journalctl --sync Available Available
Soft reboot Not available systemctl soft-reboot

Custom Service Unit Files

CORRECT -- create a drop-in or new unit:

# /etc/systemd/system/myapp.service  # [CONFIRM]
[Unit]
Description=My Application
After=network.target
Wants=network.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/start
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5

# Hardening (Rocky 8+)
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/myapp/data /var/log/myapp
PrivateTmp=yes
PrivateDevices=yes

[Install]
WantedBy=multi-user.target
# After creating/editing unit files  # [CONFIRM]
systemctl daemon-reload
systemctl enable --now myapp

WRONG -- editing vendor unit files directly:

# WRONG: Editing /usr/lib/systemd/system/nginx.service
# This will be overwritten on package updates

# CORRECT: Use a drop-in override
systemctl edit nginx  # Creates /etc/systemd/system/nginx.service.d/override.conf

Drop-in Overrides

# Create override for existing service  # [CONFIRM]
systemctl edit nginx
# Opens editor for /etc/systemd/system/nginx.service.d/override.conf

# Example override content:
# [Service]
# LimitNOFILE=65535
# Nice=-5

# View effective configuration  # [READ-ONLY]
systemctl cat nginx

systemd Timers

Preferred over cron for systemd-native services:

# /etc/systemd/system/backup.timer  # [CONFIRM]
[Unit]
Description=Daily backup timer

[Timer]
OnCalendar=daily
# Or specific time: OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
# /etc/systemd/system/backup.service  # [CONFIRM]
[Unit]
Description=Daily backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=root
# Enable the timer  # [CONFIRM]
systemctl daemon-reload
systemctl enable --now backup.timer

# List timers  # [READ-ONLY]
systemctl list-timers --all

# Manually trigger  # [CONFIRM]
systemctl start backup.service

User Administration

User Management

# List users  # [READ-ONLY]
getent passwd
awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd  # Regular users only
id username
groups username

# Create user  # [CONFIRM]
useradd -m -s /bin/bash -c "Deploy User" deploy
useradd -r -s /sbin/nologin -d /opt/myapp myapp   # System user (no login)

# Modify user  # [CONFIRM]
usermod -aG wheel deploy           # Add to sudo group
usermod -s /sbin/nologin olduser   # Disable shell access
usermod -L username                # Lock account
usermod -U username                # Unlock account

# Set password  # [CONFIRM]
passwd username

# Delete user  # [DESTRUCTIVE]
userdel username                   # Keep home directory
userdel -r username                # Remove home directory too

WRONG -- adding user to group without -a:

# WRONG: This REPLACES all supplementary groups with just 'docker'
usermod -G docker deploy

# CORRECT: Append to existing groups
usermod -aG docker deploy

Group Management

# List groups  # [READ-ONLY]
getent group
getent group wheel

# Create group  # [CONFIRM]
groupadd developers

# Add user to group  # [CONFIRM]
usermod -aG developers deploy

# Remove user from group  # [CONFIRM]
gpasswd -d deploy developers

# Delete group  # [CONFIRM]
groupdel developers

Sudo Configuration

CORRECT -- use drop-in files in /etc/sudoers.d/:

# Create sudo rule  # [CONFIRM]
visudo -f /etc/sudoers.d/deploy
# Content: deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx

# Validate syntax  # [READ-ONLY]
visudo -cf /etc/sudoers.d/deploy

WRONG -- editing /etc/sudoers directly:

# WRONG: Direct edit risks breaking sudo entirely
vim /etc/sudoers

# CORRECT: Always use visudo (validates syntax)
visudo
# Or better, use drop-in files:
visudo -f /etc/sudoers.d/myapp

Common sudoers patterns:

# /etc/sudoers.d/deploy  # [CONFIRM]
# Allow deploy to restart web services without password
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, \
                           /usr/bin/systemctl reload nginx, \
                           /usr/bin/systemctl restart php-fpm

# Allow developers group to run specific commands
%developers ALL=(ALL) NOPASSWD: /usr/bin/journalctl -u myapp*, \
                                 /usr/bin/systemctl status myapp

Checklist: sudoers file safety
- [ ] File has no syntax errors (visudo -cf /etc/sudoers.d/filename)
- [ ] File permissions are 0440 (chmod 0440 /etc/sudoers.d/filename)
- [ ] No wildcards on dangerous commands (avoid ALL=(ALL) NOPASSWD: ALL)
- [ ] Uses full paths to commands

Scheduling

Cron Jobs

# View cron jobs  # [READ-ONLY]
crontab -l                        # Current user
crontab -l -u deploy              # Specific user
ls -la /etc/cron.d/               # System cron jobs
ls -la /etc/cron.{hourly,daily,weekly,monthly}/

# Edit user crontab  # [CONFIRM]
crontab -e
crontab -e -u deploy

# System cron job  # [CONFIRM]
# /etc/cron.d/myapp-cleanup
# SHELL=/bin/bash
# PATH=/usr/local/bin:/usr/bin:/bin
# 0 2 * * * root /usr/local/bin/cleanup.sh >> /var/log/cleanup.log 2>&1

Cron expression reference:

# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€ minute (0-59)
# β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€ hour (0-23)
# β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€ day of month (1-31)
# β”‚ β”‚ β”‚ β”Œβ”€β”€β”€ month (1-12)
# β”‚ β”‚ β”‚ β”‚ β”Œβ”€ day of week (0-7, 0 and 7 are Sunday)
# β”‚ β”‚ β”‚ β”‚ β”‚
# * * * * * command

Cron vs systemd Timers

Feature Cron systemd Timer
Logging Manual (redirect) Automatic (journalctl)
Dependencies None Full systemd dependency model
Randomized delay Not built-in RandomizedDelaySec=
Persistent (catch-up) anacron only Persistent=true
Resource control None Full cgroup support
Calendar syntax Cron format OnCalendar= (more flexible)

Recommendation: Use systemd timers for new scheduled tasks; cron is fine for simple existing jobs.

Process Management

# View processes  # [READ-ONLY]
ps aux
ps -ef | grep nginx
top -bn1 | head -20
pgrep -la nginx

# Resource usage  # [READ-ONLY]
free -h
df -h
lsof -i :80
ss -tlnp

# Kill processes  # [CONFIRM]
kill -TERM <pid>                  # Graceful shutdown
kill -HUP <pid>                   # Reload config

# Force kill  # [DESTRUCTIVE]
kill -9 <pid>                     # Last resort only

System Information

# Hardware info  # [READ-ONLY]
lscpu
lsmem
lsblk
lspci
dmidecode -t system               # May need root

# OS info  # [READ-ONLY]
cat /etc/os-release
uname -r
hostnamectl

# Set hostname  # [CONFIRM]
hostnamectl set-hostname webserver01.example.com

When to Use This Skill

  • Installing, updating, or removing packages
  • Managing module streams (especially PHP, MariaDB, Nginx versions)
  • Creating, enabling, or troubleshooting systemd services
  • Creating systemd timers or cron jobs
  • Managing users, groups, or sudo permissions
  • Investigating system logs or process issues
  • Checking system resources or hardware info
  • rocky-foundation -- OS detection, safety tiers, cross-reference index
  • rocky-networking -- Network configuration and firewall
  • rocky-storage -- Disk, LVM, and filesystem management
  • rocky-selinux -- SELinux context and boolean management
  • rocky-security-hardening -- SSH, PAM, audit, and compliance

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.