Advanced 9 min · 2026-06-21

Ansible Package & Service Modules: Cross-Distro Gotchas & Production Fixes

Master Ansible apt, yum, dnf, package, pip, service, and systemd modules.

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Production
production tested
June 21, 2026
last updated
1,596
articles · all by Naren
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer

Use the generic package module for cross-distro playbooks; it delegates to apt/yum/dnf automatically. Always set update_cache: yes for apt/yum/dnf to avoid stale package indexes. Use pip module with state: present and version pinning to avoid unexpected upgrades. For systemd services, prefer systemd over service module to control daemon-reload and unit files. Set daemon_reload: yes when modifying unit files; otherwise changes won't take effect until next reload. Use enabled: yes to enable service at boot, and state: started to start it immediately. Loop over multiple services with loop and {{ item }}; pass a list of service names. Avoid using service module for systemd-based systems; it may not trigger daemon-reload correctly.

โœฆ Definition~90s read
What is Ansible Package and Service Modules?

Ansible provides a set of modules to manage packages and services across different operating systems. The apt, yum, and dnf modules are distribution-specific, each with its own set of parameters. The generic package module abstracts these differences: it detects the target system's package manager and delegates to the appropriate module.

โ˜…
Imagine you're a restaurant manager.

This is essential for writing cross-distro playbooks.

The pip module installs Python packages from PyPI or other indexes. It manages pip itself if needed and can handle virtual environments.

For services, the service module is the traditional interface, but it lacks systemd-specific controls. The systemd module provides full access to systemd's unit management: daemon_reload, enabled, state, scope, and more. Using systemd is recommended for any system running systemd (most modern Linux distros).

These modules solve the problem of idempotent, declarative management of software and daemons. Instead of writing shell scripts that check state, you declare the desired state, and Ansible ensures it.

Plain-English First

Imagine you're a restaurant manager. Different kitchens (distros) have different chefs (package managers): one chef uses a specific recipe book (apt), another uses a different one (yum). The package module is like a universal translator that tells each chef in their own language to prepare the same dish. The pip module is like a special order for a gourmet ingredient that only one supplier carries. Now, the service and systemd modules are like telling the waitstaff to start or stop a specific task (like turning on the espresso machine). The systemd module is the more detailed instruction that also tells the staff to reload the machine's settings (daemon_reload) and to ensure it starts automatically every morning (enabled). If you use the simpler service module on a modern kitchen, it might not reload settings, causing the machine to run with old instructions.

I once spent three hours debugging why a web server wouldn't start after a deployment. The playbook used the service module to restart nginx, but the unit file had been modified by a previous task. The service module didn't trigger a daemon-reload, so systemd was still using the old unit file. The symptom was a cryptic 'Failed to start nginx.service: Unit not found' error. That night, I learned the critical difference between service and systemd modules.

Historically, Ansible's service module was designed for SysV init systems, but modern distributions use systemd. The systemd module was introduced to provide full control over systemd units, including daemon-reload. Similarly, package management evolved from distro-specific modules (apt, yum) to the generic package module, which detects the underlying package manager.

This article covers the essential Ansible modules for managing packages and services in production. You'll learn when to use apt vs yum vs the generic package module, how to install Python packages with pip, and the nuances of service vs systemd. We'll also cover managing multiple services in a loop and real-world gotchas that can cause outages.

1. The Package Module: Cross-Distro Package Management

The package module is your Swiss Army knife for package management across different distributions. It automatically detects the system's package manager (apt, yum, dnf, zypper, pacman) and delegates to the appropriate module.

Basic usage: ``yaml - name: Install nginx on any distro package: name: nginx state: present ``

Production gotcha: The package module does not automatically update the package cache. On Debian/Ubuntu, this can lead to 'package not found' errors if the cache is stale. Always use update_cache with apt/yum/dnf, but note that package does not support update_cache directly. Instead, you must add a separate task: ```yaml - name: Update apt cache (Debian/Ubuntu) apt: update_cache: yes cache_valid_time: 3600 when: ansible_os_family == "Debian"

  • name: Install nginx
  • package:
  • name: nginx
  • state: present
  • ```

Multiple packages: ``yaml - name: Install multiple packages package: name: - nginx - git - curl state: present ``

Version pinning: ``yaml - name: Install specific version of nginx package: name: nginx=1.18.0-0ubuntu1 state: present ` Note: Version syntax varies by distro. For apt, it's name=version; for yum/dnf, it's name-version-release`.

Production insight: In a mixed environment with CentOS 7 (yum) and Ubuntu 20.04 (apt), I used the package module but forgot to handle cache updates. The Ubuntu hosts failed with 'E: Unable to locate package nginx'. Adding a conditional apt task before the package task solved it.

Key takeaway: Use package for cross-distro playbooks, but always handle cache updates separately per distro family.

update_cache not supported in package module
The generic package module does not have an update_cache parameter. You must use the distro-specific module (apt, yum, dnf) to update the cache before using package.
Production Insight
In a mixed environment with CentOS 7 (yum) and Ubuntu 20.04 (apt), I used the package module but forgot to handle cache updates. The Ubuntu hosts failed with 'E: Unable to locate package nginx'. Adding a conditional apt task before the package task solved it.
Key Takeaway
Use package for cross-distro playbooks, but always handle cache updates separately per distro family.

2. Apt Module: Debian/Ubuntu Specifics

The apt module manages packages on Debian-based systems. It supports update_cache, cache_valid_time, install_recommends, and more.

Basic install with cache update: ``yaml - name: Install nginx with cache update apt: name: nginx state: present update_cache: yes cache_valid_time: 3600 ` cache_valid_time` prevents cache update if it was updated within that many seconds โ€“ saves time in repeated runs.

Removing packages: ``yaml - name: Remove apache2 apt: name: apache2 state: absent purge: yes ` purge: yes` also removes configuration files.

Installing from a .deb file: ``yaml - name: Install a .deb package apt: deb: /tmp/mypackage.deb ``

Production gotcha: Using install_recommends: no to avoid pulling in recommended packages: ``yaml - name: Install minimal nginx apt: name: nginx state: present install_recommends: no ``

Key takeaway: Use cache_valid_time to optimize playbook speed and install_recommends to control dependency bloat.

cache_valid_time for speed
Set cache_valid_time: 3600 to only update the apt cache if it's older than 1 hour. This speeds up subsequent playbook runs.
Production Insight
In a CI pipeline, we had a task that ran every commit. Without cache_valid_time, it updated the apt cache every time, adding 30 seconds to every run. Adding cache_valid_time: 3600 reduced the pipeline time significantly.
Key Takeaway
Use cache_valid_time to optimize playbook speed and install_recommends to control dependency bloat.

3. Yum and Dnf Modules: RHEL/CentOS/Fedora Specifics

The yum module is for RHEL/CentOS 7 and older, while dnf is for Fedora and RHEL 8+. Both support update_cache, enablerepo, disablerepo, and allow_downgrade.

Basic install: ``yaml - name: Install nginx on CentOS 7 yum: name: nginx state: present update_cache: yes ``

For RHEL 8+/Fedora: ``yaml - name: Install nginx on RHEL 8 dnf: name: nginx state: present update_cache: yes ``

Installing from a specific repository: ``yaml - name: Install from EPEL yum: name: nginx enablerepo: epel state: present ``

Disabling a repo: ``yaml - name: Install without certain repo yum: name: nginx disablerepo: '*' enablerepo: base,updates state: present ``

Production gotcha: Downgrading packages requires allow_downgrade: yes: ``yaml - name: Downgrade nginx to 1.18 yum: name: nginx-1.18.0-1.el7 state: present allow_downgrade: yes ``

Key takeaway: Use enablerepo/disablerepo to control which repos are used, and allow_downgrade for version rollbacks.

yum vs dnf
On RHEL 8+, yum is symlinked to dnf, but it's best to use the dnf module explicitly for clarity. For CentOS 7, use yum.
Production Insight
We had a security patch that required downgrading a library. Without allow_downgrade: yes, the task failed with 'Package is already installed'. Adding that parameter fixed it.
Key Takeaway
Use enablerepo/disablerepo to control which repos are used, and allow_downgrade for version rollbacks.

4. The Pip Module: Python Package Management

The pip module installs Python packages from PyPI or other indexes. It can manage pip itself and work with virtual environments.

Basic install: ``yaml - name: Install requests library pip: name: requests state: present ``

Version pinning: ``yaml - name: Install specific version pip: name: requests==2.25.1 state: present ``

Upgrading pip: ``yaml - name: Upgrade pip pip: name: pip state: latest ``

Installing from requirements file: ``yaml - name: Install from requirements.txt pip: requirements: /path/to/requirements.txt ``

Virtual environment: ``yaml - name: Install package in virtualenv pip: name: flask virtualenv: /opt/myapp/venv virtualenv_python: python3.8 ``

Production gotcha: Without state: present, if the package is already installed, it won't be upgraded. Use state: latest to force upgrade, but be careful with breaking changes. Always pin versions in production.

Key takeaway: Pin package versions and use virtualenv for isolated environments.

Avoid state: latest in production
Using state: latest can pull in breaking changes. Always pin to a specific version in production playbooks.
Production Insight
A colleague used state: latest for a critical library, which upgraded from v1 to v2 and broke our API. We now enforce version pinning in all pip tasks.
Key Takeaway
Pin package versions and use virtualenv for isolated environments.

5. Service Module: The Legacy Approach

The service module is the traditional way to manage services. It works with SysV init, Upstart, and systemd, but with limited control.

Basic usage: ``yaml - name: Start nginx service: name: nginx state: started enabled: yes ``

Supported states: started, stopped, restarted, reloaded.

Production gotcha: The service module does not trigger daemon-reload on systemd systems. If you modify a unit file, the service may fail to start. Always use systemd module if you need daemon-reload.

When to use service: For non-systemd systems (e.g., older Ubuntu with Upstart, or containers without systemd).

Key takeaway: Prefer systemd over service on modern Linux. Only use service for legacy init systems.

service module and daemon-reload
The service module never runs systemctl daemon-reload. If you change a unit file, the service may not start correctly. Use systemd module instead.
Production Insight
The incident described earlier: we used service to restart a service after updating its unit file. The service failed to start because systemd didn't know about the new unit. We lost 30 minutes of uptime.
Key Takeaway
Prefer systemd over service on modern Linux. Only use service for legacy init systems.

6. Systemd Module: Full Control Over systemd Units

The systemd module provides complete control over systemd units, including daemon_reload, enabled, state, scope, and more.

Basic usage: ``yaml - name: Start and enable nginx systemd: name: nginx state: started enabled: yes daemon_reload: yes ``

Daemon-reload only when unit file changes: Use a handler: ```yaml tasks: - name: Copy unit file template: src: myapp.service.j2 dest: /etc/systemd/system/myapp.service notify: reload systemd

handlers: - name: reload systemd systemd: daemon_reload: yes listen: "reload systemd" ```

Other parameters: - scope: user for user services (e.g., --user flag). - no_block: yes to not wait for job completion (async). - masked: yes to mask a unit.

Production gotcha: Forgetting daemon_reload: yes after changing unit files is the #1 mistake.

Key takeaway: Always use systemd for systemd-based systems and set daemon_reload: yes when unit files change.

Use handlers for daemon-reload
Trigger daemon_reload only when unit files change using a handler. This avoids unnecessary reloads on every playbook run.
Production Insight
After the outage, we added a handler for daemon-reload and never had the issue again. We also added a pre-task that checks if any unit file changed and only then notifies the handler.
Key Takeaway
Always use systemd for systemd-based systems and set daemon_reload: yes when unit files change.

7. Managing Multiple Services in a Loop

Often you need to manage several services (e.g., web server, app server, database). Use loop with a list.

Example: Start multiple services: ``yaml - name: Start required services systemd: name: "{{ item }}" state: started enabled: yes loop: - nginx - postgresql - myapp ``

Conditional loops: ``yaml - name: Enable services based on role systemd: name: "{{ item }}" enabled: yes state: started loop: "{{ services_to_enable }}" when: services_to_enable is defined ``

Using with_items (older syntax): ``yaml - name: Stop services service: name: "{{ item }}" state: stopped with_items: - apache2 - mysql ``

Production gotcha: When looping, ensure the service names are correct for each distro. For example, Apache is httpd on RHEL and apache2 on Debian. Use variables or ansible_facts.

Key takeaway: Use loop to manage multiple services, but account for distro-specific service names.

Service name differences
Apache: httpd on RHEL, apache2 on Debian. MySQL: mysqld on RHEL, mysql on Debian. Use variables to handle differences.
Production Insight
In a multi-distro environment, I looped over a list of services that included 'apache2'. On RHEL hosts, the task failed because the service is 'httpd'. We now maintain a mapping dict: services: { debian: { apache: apache2 }, redhat: { apache: httpd } }.
Key Takeaway
Use loop to manage multiple services, but account for distro-specific service names.

8. State and Enabled: Understanding the Difference

state controls the immediate runtime state (started, stopped, restarted, reloaded). enabled controls whether the service starts at boot.

Combinations: - state: started and enabled: yes: Start now and persist on reboot. - state: stopped and enabled: no: Stop now and disable on boot. - state: restarted with enabled: yes: Restart now and ensure enabled.

Idempotency: Ansible checks the current state and only acts if needed. For example, if the service is already started, state: started does nothing.

Production gotcha: Using state: restarted without enabled will restart the service but not ensure it's enabled. If the service was disabled, after a reboot it won't start.

Key takeaway: Always set both state and enabled to ensure desired runtime and boot behavior.

state: restarted does not enable
state: restarted only restarts the service. It does not set enabled. If you want the service to start on boot, add enabled: yes.
Production Insight
A junior engineer used state: restarted without enabled. After a reboot, the service was down. We now have a linting rule that flags any state: restarted without enabled.
Key Takeaway
Always set both state and enabled to ensure desired runtime and boot behavior.

9. Daemon_reload: When and Why

daemon_reload tells systemd to reload its configuration, picking up changes to unit files. It is equivalent to running systemctl daemon-reload.

When to use: - After adding, removing, or modifying unit files in /etc/systemd/system/. - After changing symlinks in /etc/systemd/system/multi-user.target.wants/.

When not needed: - If you're just starting/stopping an existing service without changing unit files. - If the unit file is in /usr/lib/systemd/system/ (system packages), but changes there are rare.

Performance impact: Running daemon_reload is fast but can be expensive if done on every playbook run. Use handlers to trigger only when needed.

Example with handler: ```yaml tasks: - name: Copy unit file template: src: myapp.service.j2 dest: /etc/systemd/system/myapp.service notify: reload systemd

handlers: - name: reload systemd systemd: daemon_reload: yes ```

Key takeaway: Use daemon_reload: yes only when unit files change; use handlers to avoid unnecessary reloads.

daemon_reload is idempotent
Running systemd: daemon_reload=yes multiple times is safe; it simply reloads the daemon. But it's still a waste of time if no unit files changed.
Production Insight
We had a playbook that ran daemon_reload: yes on every run, adding 2 seconds per host. With hundreds of hosts, that added up. Moving it to a handler saved minutes.
Key Takeaway
Use daemon_reload: yes only when unit files change; use handlers to avoid unnecessary reloads.

10. Common Trap: service vs systemd on systemd Systems

The service module works on systemd systems but lacks daemon_reload. It uses systemctl under the hood, but without the daemon-reload command.

What happens: - service: name=myapp state=restarted runs systemctl restart myapp. - If the unit file was changed, systemd uses the old cached version. - The service may fail to start or run with old settings.

Why it's a trap: The service module doesn't error; it returns success even if the service fails to start (depending on the state). The error may only appear in logs.

Detection: After a playbook run, check systemctl status myapp and systemctl show myapp to see if the unit file is the expected one.

Best practice: Use systemd module exclusively on systemd-based systems. Reserve service for non-systemd systems (e.g., Docker containers without systemd, or legacy init).

Key takeaway: On systemd systems, always use systemd module to avoid silent failures.

service module can mask failures
The service module may return success even if the service fails to start after a unit file change, because it doesn't check for daemon-reload issues.
Production Insight
We had a monitoring alert that a service was down after a deployment. The playbook reported success, but the service had been using an old unit file. Switching to systemd with daemon_reload fixed it.
Key Takeaway
On systemd systems, always use systemd module to avoid silent failures.

11. Cross-Distro Playbook Patterns for Packages and Services

Writing playbooks that work on both Debian and RHEL families requires careful handling of package names, service names, and cache updates.

Package names: Use variables: ``yaml vars: packages: - nginx - git debian_packages: - python3-apt redhat_packages: - python3-dnf ``

Service names: ``yaml vars: apache_service: "{{ 'httpd' if ansible_os_family == 'RedHat' else 'apache2' }}" ``

Cache update pattern: ```yaml - name: Update package cache (Debian) apt: update_cache: yes cache_valid_time: 3600 when: ansible_os_family == "Debian"

  • name: Update package cache (RedHat)
  • yum:
  • update_cache: yes
  • when: ansible_os_family == "RedHat"
  • ```

Using the generic package module: ``yaml - name: Install packages package: name: "{{ item }}" state: present loop: "{{ packages }}" ``

Key takeaway: Use ansible_os_family and variables to handle distro-specific differences.

ansible_os_family values
Debian family: 'Debian' (includes Ubuntu). RedHat family: 'RedHat' (includes CentOS, Fedora, RHEL).
Production Insight
Our playbook initially hardcoded 'apache2' for the service name. When we added CentOS hosts, the service task failed. We now use a dict variable mapping OS family to service names.
Key Takeaway
Use ansible_os_family and variables to handle distro-specific differences.

12. Advanced: Using Handlers with Package and Service Modules

Handlers are tasks that run only when notified. They are perfect for service restarts after configuration changes.

Pattern: Restart service after config change: ```yaml tasks: - name: Update nginx config template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx

handlers: - name: restart nginx systemd: name: nginx state: restarted daemon_reload: yes ```

Multiple handlers for different services: ```yaml tasks: - name: Update app config template: src: app.conf.j2 dest: /opt/myapp/app.conf notify: restart myapp

  • name: Update nginx config
  • template:
  • src: nginx.conf.j2
  • dest: /etc/nginx/nginx.conf
  • notify: restart nginx

handlers: - name: restart myapp systemd: name: myapp state: restarted

  • name: restart nginx
  • systemd:
  • name: nginx
  • state: restarted
  • ```

Handlers with package installation: ```yaml tasks: - name: Install nginx package: name: nginx state: present notify: start nginx

handlers: - name: start nginx systemd: name: nginx state: started enabled: yes ```

Production gotcha: Handlers run at the end of the play, not immediately. If a later task depends on the service being restarted, you may need to use meta: flush_handlers.

Key takeaway: Use handlers to trigger service restarts only when configuration changes, and use flush_handlers if immediate restart is needed.

Flush handlers early
If a subsequent task requires the service to be restarted, add - meta: flush_handlers to run handlers immediately.
Production Insight
We had a task that deployed a new version of an app, and then a task that ran integration tests. The tests failed because the service hadn't been restarted yet (handler ran at end). Adding meta: flush_handlers after the deploy task fixed it.
Key Takeaway
Use handlers to trigger service restarts only when configuration changes, and use flush_handlers if immediate restart is needed.
● Production incidentPOST-MORTEMseverity: high

The Missing daemon_reload: A Service Outage

Symptom
After deployment, the service failed to start with 'Failed to start myapp.service: Unit not found' despite the unit file being present.
Assumption
The engineer assumed the unit file was corrupted or missing, so they checked file permissions and contents repeatedly.
Root cause
The service module does not call systemctl daemon-reload. The unit file was updated, but systemd was still using the old cached version, so the service name wasn't recognized.
Fix
Replace service with systemd module and set daemon_reload: yes before restarting. Also added a handler to run daemon-reload only when unit files change.
Key lesson
  • Always use the systemd module for systemd-based systems, and explicitly trigger daemon-reload after modifying unit files.
Production debug guideSymptom โ†’ Root cause โ†’ Fix4 entries
Symptom · 01
Package installation fails with 'No package matching' or '404 Not Found'
Fix
Root cause: stale package cache. Fix: add update_cache: yes to the package task. Example: apt: name=nginx state=present update_cache=yes
Symptom · 02
Service fails to start after unit file change: 'Unit not found' or 'Failed to reload daemon'
Fix
Root cause: missing daemon_reload. Fix: use systemd: name=myapp daemon_reload=yes state=restarted.
Symptom · 03
Playbook hangs or times out when installing packages on a slow network
Fix
Root cause: default timeout is too short. Fix: set timeout parameter (e.g., apt: timeout=300) or use async with poll.
Symptom · 04
Service is running but not enabled at boot (after reboot, service down)
Fix
Root cause: missing enabled: yes. Fix: systemd: name=myapp enabled=yes state=started.
★ Ansible Package and Service Modules Quick Referenceprint this for your desk
Package not found (apt/yum/dnf)
Immediate action
Check if cache is stale
Commands
ansible all -m apt -a 'update_cache=yes'
ansible all -m apt -a 'name=nginx state=present update_cache=yes'
Fix now
Add update_cache: yes to your playbook task
Service won't start after unit file change+
Immediate action
Run daemon-reload
Commands
ansible all -m systemd -a 'daemon_reload=yes'
ansible all -m systemd -a 'name=myapp state=restarted'
Fix now
Replace service with systemd module and set daemon_reload: yes
Service not enabled at boot+
Immediate action
Check enabled state
Commands
ansible all -m systemd -a 'name=myapp'
ansible all -m systemd -a 'name=myapp enabled=yes'
Fix now
Add enabled: yes to your service task
Cross-distro playbook fails on different OS+
Immediate action
Use `package` module instead of apt/yum
Commands
ansible all -m package -a 'name=nginx state=present'
Fix now
Replace apt: or yum: with package:
pip install fails with 'Could not find a version'+
Immediate action
Check Python version and pip constraints
Commands
ansible all -m pip -a 'name=requests version=2.25.1'
ansible all -m pip -a 'name=requests state=latest'
Fix now
Pin version and ensure pip is up-to-date: pip: name=pip state=latest
Package Module Comparison: apt vs yum vs dnf vs package
Featureaptyumdnfpackage
update_cacheyesyesyesno (use distro-specific)
cache_valid_timeyesnonono
install_recommendsyesnonono
enablerepo/disablereponoyesyesno
allow_downgradenoyesyesno
Cross-distroDebian onlyRHEL 7 onlyRHEL 8+All distros

Key takeaways

1
Use the generic package module for cross-distro playbooks, but handle cache updates separately.
2
Always set `update_cache
yes and cache_valid_time` for apt, yum, dnf tasks.
3
Pin pip package versions to avoid unexpected upgrades.
4
Prefer systemd over service module on modern Linux systems.
5
Always set `daemon_reload
yes` when modifying systemd unit files.
6
Use handlers to trigger service restarts only when configuration changes.
7
Set both state and enabled to control runtime and boot behavior.
8
Use variables and ansible_os_family to handle distro-specific service and package names.

Common mistakes to avoid

6 patterns
×

Using `service` module on systemd systems and not triggering daemon-reload after unit file changes

Symptom
Service fails to start or runs with old configuration after unit file update
Fix
Use systemd module with daemon_reload: yes
×

Forgetting `update_cache: yes` in apt/yum/dnf tasks

Symptom
Package installation fails with 'package not found'
Fix
Add update_cache: yes to the task
×

Not pinning pip package versions

Symptom
Unexpected package upgrades break the application
Fix
Always specify version: pip: name=requests==2.25.1
×

Using `state: latest` for packages in production

Symptom
Unplanned upgrades cause instability
Fix
Use state: present with a specific version
×

Not setting `enabled: yes` when starting a service

Symptom
Service is running but doesn't survive reboot
Fix
Add enabled: yes to the service task
×

Hardcoding service names without considering distro differences

Symptom
Playbook fails on different OS families
Fix
Use variables based on ansible_os_family
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the difference between the `service` and `systemd` modules in An...
Q02JUNIOR
How do you handle cross-distro package management in Ansible?
Q03SENIOR
What is the purpose of `daemon_reload` in the `systemd` module?
Q04JUNIOR
How can you install multiple packages with a single task in Ansible?
Q05SENIOR
Explain the difference between `state: started` and `state: restarted` i...
Q06SENIOR
How do you manage a service that should be started only if a certain con...
Q07SENIOR
What is the best practice for ensuring a service restarts only when its ...
Q08SENIOR
How can you install a Python package from a private repository using the...
Q01 of 08JUNIOR

What is the difference between the `service` and `systemd` modules in Ansible?

ANSWER
The service module is a generic module that works with SysV init, Upstart, and systemd. However, it does not support daemon_reload, which is required after modifying systemd unit files. The systemd module is specific to systemd and provides full control, including daemon_reload, scope, masked, and more. For modern Linux distributions using systemd, the systemd module is recommended.
FAQ · 8 QUESTIONS

Frequently Asked Questions

01
Can I use the `package` module to update the package cache?
02
What is the difference between `state: present` and `state: latest` in package modules?
03
Do I need to use `daemon_reload` every time I start a service?
04
How can I check if a service is enabled using Ansible?
05
Can I manage services inside a Docker container with Ansible?
06
What is the `pip` module's `virtualenv` parameter?
07
How do I handle packages that have different names on different distros?
08
Is it possible to downgrade a package with Ansible?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Verified
production tested
June 21, 2026
last updated
1,596
articles · all by Naren
🔥

That's Ansible. Mark it forged?

9 min read · try the examples if you haven't

Previous
Ansible File Management Modules
12 / 23 · Ansible
Next
Ansible Command and Shell Modules