Start, Stop & Boot-Enable
Services with systemctl

Start and stop services and configure services to start automatically at boot

CIS126RH | RHEL System Administration 1
Mesa Community College

On RHEL 9, every service is a systemd unit. The systemctl command is the universal tool for starting, stopping, restarting, enabling, and disabling services. Understanding the critical distinction between the current running state (started or stopped right now) and the boot-time state (enabled or disabled for automatic startup) is the foundation of reliable service administration. This module covers both dimensions and the --now flag that combines them. These skills are tested extensively on the RHCSA exam.

Learning Objectives

  1. Explain the two independent service state dimensions — Distinguish between the current running state (active/inactive) and the boot-time state (enabled/disabled), and explain how they interact
  2. Start, stop, and restart services — Use systemctl start, stop, and restart to control the immediate running state of services
  3. Enable and disable services at boot — Use systemctl enable and disable — with and without the --now flag — to configure persistent boot-time behaviour
  4. Verify and troubleshoot service state — Use systemctl status, is-active, is-enabled, and journalctl -u to confirm service state and diagnose failures

The Two Independent Dimensions

Every systemd service has two completely independent state dimensions. Changing one does not change the other.

Dimension Values What it controls Commands
Running state active / inactive / failed Whether the service is running right now start, stop, restart
Boot state enabled / disabled / masked Whether the service starts automatically at boot enable, disable, mask

This creates four valid combinations:

Running state Boot state Meaning
activeenabledRunning now and will start at next boot — most common for production services
activedisabledRunning now but will NOT start at next boot — temporary start
inactiveenabledNot running now but WILL start at next boot — enabled but not yet started
inactivedisabledNot running and will not start at boot — fully off

Starting and Stopping Services

These commands change the running state only — they have no effect on whether the service starts at boot.

# Start a service immediately
$ sudo systemctl start sshd
$ sudo systemctl start httpd

# Stop a running service
$ sudo systemctl stop sshd

# Restart a service (stop then start)
$ sudo systemctl restart httpd

# Reload configuration without stopping (if the service supports it)
$ sudo systemctl reload sshd

# Reload if supported, otherwise restart
$ sudo systemctl reload-or-restart httpd

# Check if the service is currently running
$ systemctl is-active sshd
active

$ systemctl is-active httpd
inactive
start does not persist across reboots

Starting a service with systemctl start is temporary. If the service is disabled, it will not start at the next reboot. To make it permanent, also run systemctl enable.

Enabling and Disabling at Boot

These commands configure the boot state only — they have no immediate effect on whether the service is currently running.

# Enable a service — creates a symlink for boot-time start
$ sudo systemctl enable sshd
Created symlink /etc/systemd/system/multi-user.target.wants/sshd.service
    → /usr/lib/systemd/system/sshd.service.

# Disable a service — removes the boot-time symlink
$ sudo systemctl disable sshd
Removed /etc/systemd/system/multi-user.target.wants/sshd.service.

# Check if a service is enabled
$ systemctl is-enabled sshd
enabled

$ systemctl is-enabled httpd
disabled

# The --now flag: combine enable + start in one command
$ sudo systemctl enable --now httpd
# Equivalent to: systemctl enable httpd && systemctl start httpd

# The --now flag: combine disable + stop
$ sudo systemctl disable --now httpd

How enable Works: Symlinks

Understanding the symlink mechanism explains why enable/disable is persistent and why it is separate from start/stop.

# After systemctl enable sshd:
$ ls -la /etc/systemd/system/multi-user.target.wants/sshd.service
lrwxrwxrwx. 1 root root 36 May 25 10:00
    /etc/systemd/system/multi-user.target.wants/sshd.service
    → /usr/lib/systemd/system/sshd.service

# The actual unit file (read-only, managed by packages)
$ cat /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
...
[Install]
WantedBy=multi-user.target

# Boot sequence: systemd reads .wants dirs → starts linked units
# /etc/systemd/system/multi-user.target.wants/ (user-created symlinks)
$ ls /etc/systemd/system/multi-user.target.wants/
auditd.service  chronyd.service  crond.service  sshd.service  ...
The [Install] section defines where the symlink goes

WantedBy=multi-user.target in the unit file's [Install] section tells enable to create the symlink in multi-user.target.wants/. Different targets have different .wants directories.

Reading systemctl status

systemctl status shows both state dimensions plus recent log entries — the single most useful diagnostic command.

$ systemctl status sshd
● sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-05-25 07:00:00 MST; 14h ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 872 (sshd)
      Tasks: 1 (limit: 49152)
     Memory: 5.2M
        CPU: 203ms
     CGroup: /system.slice/sshd.service
             └─872 sshd: /usr/sbin/sshd -D [listener]

May 25 07:00:01 servera systemd[1]: Starting OpenSSH server daemon...
May 25 07:00:01 servera sshd[872]: Server listening on 0.0.0.0 port 22.
May 25 09:05:21 servera sshd[872]: Accepted publickey for student

# The Loaded line shows:    UNIT FILE PATH;  BOOT STATE;  preset
# The Active line shows:    RUNNING STATE;  duration
Read status output top to bottom

Loaded line: enabled or disabled (boot state).
Active line: active (running), inactive (dead), or failed (running state).
Log lines at the bottom: recent events — almost always show why a failed service crashed.

All Service States

Active state Meaning Common action
active (running)Service is running with one or more processesNormal — no action
active (exited)Service ran to completion successfully (one-shot)Normal for setup scripts
active (waiting)Service is waiting for an event or socketNormal for socket-activated services
inactive (dead)Service is not running and has not failedStart if needed
failedService exited with non-zero status or was killedRead log lines; fix and restart
activatingService is starting upWait; re-check if it stays here
deactivatingService is shutting downNormal; investigate if it stays here
Boot state Meaning
enabledWill start automatically at boot (symlink exists)
disabledWill NOT start at boot (symlink removed)
maskedCannot be started by any means — symlink points to /dev/null
staticNo [Install] section — enabled by other units' dependencies only

Masking Services

Masking prevents a service from being started by any means — manually, by other units, or at boot. It is stronger than simply disabling.

# Mask a service (creates a /dev/null symlink)
$ sudo systemctl mask postfix
Created symlink /etc/systemd/system/postfix.service → /dev/null.

# Any attempt to start a masked service fails
$ sudo systemctl start postfix
Failed to start postfix.service: Unit postfix.service is masked.

# Unmask to restore normal behaviour
$ sudo systemctl unmask postfix
Removed /etc/systemd/system/postfix.service.

# After unmask, service returns to disabled state
$ systemctl is-enabled postfix
disabled

# Compare disable vs mask
$ systemctl is-enabled postfix   # after disable: "disabled"
$ systemctl start postfix         # after disable: succeeds (if configured correctly)
$ systemctl is-enabled postfix   # after mask: "masked"
$ systemctl start postfix         # after mask: FAILS

Listing Services

# List all loaded service units
$ systemctl list-units --type=service
  UNIT                  LOAD   ACTIVE SUB     DESCRIPTION
  auditd.service        loaded active running Security Auditing Service
  chronyd.service       loaded active running NTP client/server
  crond.service         loaded active running Command Scheduler
  sshd.service          loaded active running OpenSSH server daemon
...

# List only failed services
$ systemctl list-units --type=service --state=failed

# List all installed unit files (includes disabled)
$ systemctl list-unit-files --type=service
UNIT FILE              STATE    PRESET
auditd.service         enabled  enabled
chronyd.service        enabled  enabled
httpd.service          disabled disabled
postfix.service        disabled enabled
...

# Show only enabled unit files
$ systemctl list-unit-files --type=service --state=enabled
list-units vs list-unit-files

list-units shows currently loaded units (running or recently failed). list-unit-files shows all installed unit files regardless of whether they are currently loaded — including disabled services.

The --now Flag

The --now flag combines a boot state change with an immediate running state change — completing both dimensions in one command.

# Enable AND start immediately — the most common deployment pattern
$ sudo systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service
    → /usr/lib/systemd/system/httpd.service.
# httpd is now ENABLED (will start at boot) AND ACTIVE (running now)

# Disable AND stop immediately
$ sudo systemctl disable --now httpd
# httpd is now DISABLED (won't start at boot) AND INACTIVE (stopped now)

# Verify both dimensions after enable --now
$ systemctl is-enabled httpd
enabled
$ systemctl is-active httpd
active

# The full deployment workflow: install → enable --now → verify
$ sudo dnf install -y httpd
$ sudo systemctl enable --now httpd
$ systemctl status httpd
RHCSA exam pattern: enable --now completes most service tasks

When asked to "configure SERVICE to start automatically" or "ensure SERVICE is running and starts at boot", the answer is almost always: sudo systemctl enable --now SERVICE followed by systemctl status SERVICE to verify.

Diagnosing a Failed Service

When systemctl status shows failed, the log lines at the bottom of the output are the first place to look.

$ systemctl status httpd
● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled)
     Active: failed (Result: exit-code) since Mon 2026-05-25 10:00:00 MST
    Process: 5432 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (status=1/FAILURE)
   Main PID: 5432 (code=exited, status=1/FAILURE)

May 25 10:00 servera httpd[5432]: AH00526: Syntax error on line 47 of /etc/httpd/conf/httpd.conf
May 25 10:00 servera systemd[1]: httpd.service: Main process exited, code=exited
May 25 10:00 servera systemd[1]: httpd.service: Failed with result 'exit-code'.

# For more detail, check the full journal
$ journalctl -u httpd --since "10 minutes ago"

# After fixing the configuration error:
$ sudo systemctl start httpd
$ systemctl status httpd
Failed service troubleshooting workflow

1. Read the log lines in status output. 2. If insufficient, run journalctl -u SERVICE. 3. Fix the identified problem. 4. Start the service. 5. Verify with status again.

Service Unit Files

Understanding the unit file structure helps administrators know where to look for configuration and how to override settings without modifying package files.

# View a service unit file
$ systemctl cat sshd
# /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.target
Wants=sshd-keygen.target

[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure

[Install]
WantedBy=multi-user.target

# Create an override without editing the package file
$ sudo systemctl edit sshd   # creates /etc/systemd/system/sshd.service.d/override.conf

systemctl Quick Reference

Task Command
Start a service nowsudo systemctl start SERVICE
Stop a running servicesudo systemctl stop SERVICE
Restart a servicesudo systemctl restart SERVICE
Reload config without stoppingsudo systemctl reload SERVICE
Safe reload or restartsudo systemctl reload-or-restart SERVICE
Enable at boot onlysudo systemctl enable SERVICE
Enable at boot AND start nowsudo systemctl enable --now SERVICE
Disable at boot onlysudo systemctl disable SERVICE
Disable AND stop nowsudo systemctl disable --now SERVICE
Prevent any start (mask)sudo systemctl mask SERVICE
Remove masksudo systemctl unmask SERVICE
View full status (both dimensions + logs)systemctl status SERVICE
Check if runningsystemctl is-active SERVICE
Check if enabledsystemctl is-enabled SERVICE
List all running servicessystemctl list-units --type=service
List all installed servicessystemctl list-unit-files --type=service
View unit file contentssystemctl cat SERVICE
View service logsjournalctl -u SERVICE

Systemd Targets and the Boot Process

Services are enabled into a target — a named group of units that must be active for the system to be in a particular state.

# View the default boot target
$ systemctl get-default
multi-user.target

# Common targets
poweroff.target      # system shutdown
rescue.target        # single-user / rescue mode
multi-user.target    # full multi-user, no GUI (typical server)
graphical.target     # multi-user + graphical (desktop)

# Change the default boot target
$ sudo systemctl set-default multi-user.target
Created symlink /etc/systemd/system/default.target
    → /usr/lib/systemd/system/multi-user.target.

# Most services use WantedBy=multi-user.target in [Install]
# enable creates the symlink in multi-user.target.wants/
multi-user.target is the server default

RHEL server installations default to multi-user.target — full network and multi-user support without a graphical interface. Desktop installations default to graphical.target. Services enabled with WantedBy=multi-user.target start in both targets.

Common Mistakes

Mistake What goes wrong Correct approach
Starting a service without enabling it Service runs until reboot but never starts again — task is incomplete Use systemctl enable --now SERVICE to do both in one command
Enabling a service without starting it Service will start at next boot but is not running now — incomplete Use systemctl enable --now SERVICE
Not verifying service state after enabling Service may have failed to start — task appears complete but service is not running Always run systemctl status SERVICE after enable --now
Confusing reload and restart Using restart drops all active connections unnecessarily Use reload for config changes when the service supports it
Editing unit files in /usr/lib/systemd/system/ Changes are overwritten by the next package update Use systemctl edit SERVICE to create drop-in overrides in /etc/
Confusing disabled with masked A disabled service can still be started manually; a masked service cannot Use disable for normal disabling; mask only when the service must never run

Knowledge Check

Answer these before moving to the next slide.

  1. A service is active (running) but disabled. What happens to it after the next system reboot, and what command makes it persist?
  2. Write the single command to install and make httpd both running now and configured to start automatically at every future boot.
  3. systemctl status httpd shows: Active: failed (Result: exit-code). What do you look at next, and what is the likely fix workflow?
  4. What is the difference between systemctl disable httpd and systemctl mask httpd?
  5. You need to apply a change to sshd_config without dropping any active SSH sessions. Which systemctl command applies the change?
  6. After creating a custom service unit file at /etc/systemd/system/myapp.service, what command must you run before systemctl can manage it?

Knowledge Check — Answers

  1. After reboot, the service will be stopped (inactive) — it was disabled so systemd does not start it at boot. The service runs only when manually started. Fix: sudo systemctl enable SERVICE (enables for boot only) or sudo systemctl enable --now SERVICE (also starts it now, though it is already running).
  2. sudo dnf install -y httpd then sudo systemctl enable --now httpd. The --now flag both creates the boot-time symlink and starts the service immediately.
  3. Read the log lines at the bottom of the status output — they almost always identify the error (configuration syntax, missing file, permission denied). If needed: journalctl -u httpd --since "10 minutes ago". Fix the identified problem, then sudo systemctl start httpd, then verify with systemctl status httpd.
  4. disable removes the boot-time symlink — the service will not start at boot, but can still be started manually with systemctl start. mask creates a symlink to /dev/null — the service cannot be started by any means (manual, boot, or dependency) until unmasked.
  5. sudo systemctl reload sshd — sends SIGHUP to the sshd process, which causes it to re-read sshd_config without terminating. Existing SSH sessions are not interrupted.
  6. sudo systemctl daemon-reload — this command tells systemd to re-scan all unit file locations and load the new unit. Without it, systemctl enable will not find the new unit file.

Key Takeaways

  1. Services have two independent dimensions: running state and boot state. start/stop/restart change the running state (now, temporary). enable/disable change the boot state (persistent, next reboot). enable --now changes both at once — the exam standard pattern.
  2. systemctl status shows both dimensions and recent logs. Loaded line shows the boot state (enabled/disabled). Active line shows the running state. Log lines at the bottom identify why a failed service crashed.
  3. The deployment workflow: install → enable --now → verify. Always run systemctl status SERVICE after deploying. Use journalctl -u SERVICE for more log detail when needed. Use reload instead of restart when sessions must not be dropped.
  4. mask is stronger than disable; daemon-reload is required for new units. mask prevents any start — even manual. disable prevents boot-time start only. After creating or modifying a unit file, run systemctl daemon-reload before attempting to enable or start it.

Graded Lab

  • Install httpd with dnf. Run systemctl is-active httpd and systemctl is-enabled httpd to confirm it is inactive and disabled immediately after installation (both dimensions are off).
  • Use systemctl enable --now httpd to make httpd run now and start at every boot. Verify both dimensions with systemctl status httpd — confirm the Loaded line shows enabled and the Active line shows active (running).
  • Run systemctl stop httpd. Confirm with systemctl is-active it is inactive. Run systemctl is-enabled to confirm it is still enabled. Start it again with systemctl start httpd. This demonstrates the two dimensions are independent.
  • Use systemctl disable httpd. Confirm with systemctl is-enabled it is disabled. Confirm with systemctl is-active it is still running. This demonstrates disable does not stop the service.
  • Mask postfix with systemctl mask. Attempt systemctl start postfix and observe the failure. Unmask it and confirm the start succeeds (if postfix is installed) or the error changes to a different one.
  • Reboot the system. After reboot, confirm that httpd is NOT running (disabled in task 4) and that sshd IS running (enabled by default). This confirms the boot state controls persistent behaviour.
RHCSA Objective

"Start and stop services and configure services to start automatically at boot." The exam answer: systemctl enable --now SERVICE followed by systemctl status SERVICE to verify both dimensions.