Managing Linux Services: systemd and Ansible¶
If you're running services on a Linux server, systemd is what you're working with day-to-day — starting, stopping, restarting, and checking on things. For managing services across multiple machines, Ansible is where I've landed. It handles the repetitive stuff so you can focus on what actually matters.
The Short Answer¶
# Check a service status
systemctl status servicename
# Start / stop / restart
sudo systemctl start servicename
sudo systemctl stop servicename
sudo systemctl restart servicename
# Enable at boot
sudo systemctl enable servicename
# Disable at boot
sudo systemctl disable servicename
# Reload config without full restart (if supported)
sudo systemctl reload servicename
systemd Basics¶
systemd is the init system on basically every major Linux distro now. Love it or not, it's what you're using. The systemctl command is your interface to it.
Checking what's running:
# List all active services
systemctl list-units --type=service --state=active
# List failed services (run this when something breaks)
systemctl list-units --type=service --state=failed
Reading logs for a service:
# Last 50 lines
journalctl -u servicename -n 50
# Follow live (like tail -f)
journalctl -u servicename -f
# Since last boot
journalctl -u servicename -b
journalctl is your friend. When a service fails, go here before you do anything else.
Writing a simple service file:
Drop a .service file in /etc/systemd/system/ and systemd will pick it up.
[Unit]
Description=My Custom App
After=network.target
[Service]
Type=simple
User=myuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/start.sh
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
After creating or editing a service file, reload the daemon before doing anything else:
Ansible for Service Management Across Machines¶
For a single box, systemctl is fine. Once you've got two or more servers doing similar things, Ansible starts paying for itself fast. I've been using it heavily at work and it's changed how I think about managing infrastructure.
The ansible.builtin.service module handles start/stop/enable/disable:
- name: Ensure nginx is started and enabled
ansible.builtin.service:
name: nginx
state: started
enabled: true
A more complete playbook pattern:
---
- name: Manage web services
hosts: webservers
become: true
tasks:
- name: Install nginx
ansible.builtin.package:
name: nginx
state: present
- name: Start and enable nginx
ansible.builtin.service:
name: nginx
state: started
enabled: true
- name: Reload nginx after config change
ansible.builtin.service:
name: nginx
state: reloaded
Run it with:
Gotchas & Notes¶
- daemon-reload is mandatory after editing service files. Forgetting this is the most common reason changes don't take effect.
restartvsreload:restartkills and relaunches the process.reloadsends SIGHUP and asks the service to re-read its config without dropping connections — only works if the service supports it. nginx and most web servers do. Not everything does.- Ansible's
restartedvsreloadedstate: Same distinction applies. Usereloadedin Ansible handlers when you're pushing config changes to a running service. - Checking if a service is masked: A masked service can't be started at all.
systemctl status servicenamewill tell you. Unmask withsudo systemctl unmask servicename. - On Fedora/RHEL: SELinux can block a custom service from running even if systemd says it started fine. If you see permission errors in
journalctl, checkausearch -m avcfor SELinux denials.
See Also¶
- [[wsl2-instance-migration-fedora43]]
- [[tuning-netdata-web-log-alerts]]