Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli.
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
Related Skills
- 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.