# Getting started - Bash script actions "converted" into a playbook

**URL:** <https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331>\
**Category:** Get Help\
**Tags:** debian\
**Created:** [February 13, 2026, 9:13am UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331 "2026-02-13T09:13:21Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [February 13, 2026, 9:13am UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/1 "2026-02-13T09:13:21Z")

</div>

Hi All,

I’m managing a set of about 60 Debian computers with a deployment script.  
Purpose is to copy some system files to configure the system (login manager, …) and have a default /home/user directory (bookmarks, pinneds apps, …).

I’d like to switch to Ansible to avoid having to run the script manually or each system, and to benefit from “idempotence” (I love the word 😍).

I’m not asking to do the job on my behalf, just would like to confirm that my script building blocks properly translate into playbook entries.

# Software updates

## Script

```auto
apt update
apt upgrade -y
apt install -y rsync openssh-client openssh-server net-tools
apt purge -y --autoremove gnome-games

```

## Ansible

```auto
  tasks:
    - name: updates
      block:
        - name: update
          apt:
            update_cache: yes
        - name: upgrade
          apt:
            upgrade: dist
        - name: install
          apt:
            name:
              - rsync
              - openssh-client
              - openssh-server
              - net-tools
            state: present
        - name: remove
          apt:
            name: gnome-games
            state: absent
            autoremove: yes

```

# Disabling passwords

## Script

```auto
passwd -d guest

```

## Ansible

```auto
    - name: Désactivation du mot de passe pour l'utilisateur guest
      user:
        name: guest
        password: "" # Mot de passe vide

```

# Remove some files and copy some others

## Script

```auto
rm -Rf /usr/share/wayland-sessions/*
rm -Rf /usr/share/xsessions/*
rm -Rf /etc/skel/*
rm -Rf /home/guest/*
rm -Rf /home/guest/.*
rsync -az --progress --ignore-times root@$SKELETON_SERVER:$SKELETON_PATH/ /etc/skel/
rsync -az --progress --ignore-times /etc/skel/ /

```

## Ansible

```auto
    - name: Copie du skeleton depuis le serveur
      block:
        - name: Suppression des sessions Wayland et X existantes
          file:
            path: "{{ item }}"
            state: absent
          loop:
            - /usr/share/wayland-sessions/
            - /usr/share/xsessions/
        - name: Copie du skeleton depuis le serveur distant
          synchronize:
            src: "root@{{ skeleton_server }}:{{ skeleton_path }}/"
            dest: "{{ local_dest }}etc/skel/"
            mode: push
            archive: yes
            compress: yes
        - name: Application du skeleton à la racine
          synchronize:
            src: "{{ local_dest }}etc/skel/"
            dest: "{{ local_dest }}/"
            mode: pull
            archive: yes
            compress: yes

```

# Ownership and permission changes

## Script

```auto
chown -R guest:guest /home/guest
chmod +x /usr/share/sddm/scripts/Xstop

```

## Ansible

```auto
        - name: Changement de propriétaire pour /home/guest
          file:
            path: /home/guest
            owner: guest
            group: guest
            recurse: yes

```

# Other actions required

1. I don’t know how to change permissions on folders
2. I don’t know how to invoke extra specific cxommands such as

```auto
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
sudo dconf update #pour couvrir la partie Cinnamon
sudo update-grub
systemctl restart ssh

```

Can you please help me confirm that my building blocks look OK?  
Are there ways to run commands such as the ones at the bottom of my list?

Ultimately, if I have a working script, should I consider copying the script and simply running it on my clients via Ansible, and avoid converting the whole script into a playbook?

Thanks a lot!

---

<div class="post-metadata">

**Author:** ![dbrennand](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dbrennand/32/7830_2.png) [@dbrennand](https://forum.ansible.com/u/dbrennand)\
**Post date:** [February 13, 2026, 12:29pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/2 "2026-02-13T12:29:51Z")

</div>

Hi @cndpansible

Welcome to the Ansible forum! 🙂

You got a really good starting point here. Under your **Ansible** heading, for your playbook tasks I’d recommend using the Fully Qualified Collection Name (FQCN) for the modules used in each task, this helps with knowing which [collection](https://docs.ansible.com/projects/ansible/latest/collections_guide/index.html) the modules are from and if another collection has an `apt` module then it avoids potential clashes in the future.

A small example:

```auto
---
- name: Example Playbook
  hosts: some_hosts
  tasks:
    - name: Update apt cache
      ansible.builtin.apt:
        update_cache: true

```

You can find module FQCNs using the `ansible-doc` command like: `ansible-doc apt` or you can use the online doc site: [ansible.builtin.apt module – Manages apt-packages — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/apt_module.html)

> 1. I don’t know how to change permissions on folders

You can use the [`mode`](https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/file_module.html#parameter-mode) parameter with the `file` module to change permissions (RWX):

```auto
- name: Change permissions for /home/guest
  ansible.builtin.file:
    path: /home/guest
    owner: guest
    group: guest
    recurse: true
    state: directory
    mode: u=rwx,g=rx,o=

```

The above `mode` is the equivalent of: `chmod 750`.

> 1. I don’t know how to invoke extra specific cxommands such as

```auto
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

```

You could use the [ansible.builtin.systemd\_service module – Manage systemd units — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/systemd_service_module.html#ansible-collections-ansible-builtin-systemd-service-module) to mask these and restart services like `ssh`.

Hope this helps 🙂 - Based on what you’ve said, I think Ansible would be ideal for this.

Here is some links which might help you further:

- [Getting started with Ansible — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/getting_started/index.html)
- [Ansible concepts — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/getting_started/basic_concepts.html)
- [Creating a playbook — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/getting_started/get_started_playbook.html)
- [Using Ansible command line tools — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/command_guide/index.html)
- [Building an inventory — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/latest/getting_started/get_started_inventory.html)

---

<div class="post-metadata">

**Author:** ![U880D](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/u880d/32/10032_2.png) [@U880D](https://forum.ansible.com/u/U880D)\
**Post date:** [February 13, 2026, 4:14pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/3 "2026-02-13T16:14:00Z")

</div>

> I don’t know how to invoke extra specific commands such as …

Out of mind, for the systemd services you could try

```yaml
    - name: Mask service
      systemd:
        name: "{{ item }}"
        masked: true
      loop:
        - sleep.target
        - suspend.target
        - hibernate.target
        - hybrid-sleep.target

```

and

```yaml
    - name: Restart ssh daemon
      systemd:
        name: sshd
        daemon_reload: true
        state: restarted

```

For `dconf` There is also a module [`ansible.builtin.debconf `](https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/debconf_module.html).

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [February 13, 2026, 10:15pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/4 "2026-02-13T22:15:07Z")

</div>

For `update-grub` I think the only option is to use the [command module](https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/command_module.html), there is no grub module:

```yaml
- name: Grub configuration updated
  ansible.builtin.command:
    cmd: update-grub
  changed_when: true

```

I suggest setting `changed_when` to true because otherwise you would probably have to do something like use the `shell` module and write a Bash script that writes the output somewhere on each run and compare the latest run output to the previous output to see if they differ, I don’t think there is a simply way of knowing if running `update-grub` changed anything as it is a command with few options:

```bash
update-grub -h
Usage: grub-mkconfig [OPTION]
Generate a grub config file

  -o, --output=FILE output generated config to FILE [default=stdout]
  -h, --help print this message and exit
  -V, --version print the version information and exit

Report bugs to <bug-grub@gnu.org>.

```

---

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [February 15, 2026, 8:31am UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/5 "2026-02-15T08:31:51Z")

</div>

Thanks a million @chris @dbrennand !

So many details and pointers, I had looked at the doc, but clearly had overlooked some stuff.

Allow me to play devil’s advocate: I do see the value of Ansible, but can you please help me understand what would be the upsides and downsides of trying to “simply” trigger my deployment script via Ansible, rather than fully translating it into playbooks?

I believe this might be a “too easy way out”, and maybe I would regret it in the future, but on the short term, I feel tempted to take the shortcut 😉

Thanks again!

---

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [February 15, 2026, 8:32am UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/6 "2026-02-15T08:32:27Z")

</div>

And thank you @U880D too (I could only tag 2 people per post 😉 )

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [February 15, 2026, 10:59am UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/7 "2026-02-15T10:59:06Z")

</div>

I started using Ansible to run the Bash commands I’d be using for years, it’s fine to start there! Take it one step at a time and see how you get on.

---

<div class="post-metadata">

**Author:** ![U880D](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/u880d/32/10032_2.png) [@U880D](https://forum.ansible.com/u/U880D)\
**Post date:** [February 16, 2026, 8:07am UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/8 "2026-02-16T08:07:37Z")

</div>

> [@cndpansible](#):
>
> understand what would be the upsides and downsides of trying to “simply” trigger my deployment script via Ansible

Well, from my point of view there is no right or wrong at the beginning. Since Ansible is agentless, you are almost writing a kind of documentation upfront, which can then be read and executed by a human or by a machine, it will depend on the complexity of the tasks and its dependencies.

For simple tasks without complexity it might be OK to use `command` or `shell`. But they may lack error handling then. Also be non-technical human may have problems to understand what the task is about. If there is more complexity which needs to be abstracted, error handling necessary, or dealing with data structures and formatting output, specific Ansible modules will gain advantage fast.

An example for such could be accessing REST APIs versus `command` with `curl` or the `uri` module. A lot of Ansible modules are just abstractions for REST API but make it very simple the write and read them, but it will also introduce a dependency to such modules, there availability and maintenance.

For the beginning one could start with commands and introduce more and more specific modules later during daily development and operations.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [February 16, 2026, 7:36pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/9 "2026-02-16T19:36:17Z")

</div>

> [@cndpansible](#):
>
> help me understand what would be the upsides and downsides of trying to “simply” trigger my deployment script via Ansible, rather than fully translating it into playbooks?

The upside is your existing script is already written. That’s kind of a huge thing. Within the scope of your question, there hardly is any downside. You can use ansible as an “easy button” to continue doing things the way you’ve been doing them. Even so, Ansible brings some things to the table. For example, how are you deploying the script to your hosts? An Asible project can act as the canonical source for your script (or its equivalent functionality in tasks), an automatic deployment mechanism, plus a trigger to run it, along with a lot of flexibility for specifying which hosts to deploy and run it on. That’s a lot of gain simply by using Ansible to “simply” trigger your script.

The downsides for _only_ doing that, though, include missing out on a lot of error handling. Shell scripts are notoriously difficult to write in a way that properly handles errors. It’s possible, but rarely done. Breaking out that functionality into tasks gives you that error detection almost for free. You still have to decide what to do about errors, maybe, eventually, but at least you’ll have a reasonable chance of becoming aware of them. There’s a high likelihood that you wouldn’t find out about errors in your current script until you tried to use one of these new hosts.

Beyond the scope of this script or its equivalent functionality, though, you’ll likely come up with additional things you’ll need to do on, with, or to these or other hosts. Creating additional playbooks in the project fits perfectly into Ansible’s organized framework for accomplishing “_do A, B, and C to hosts X, Y, and Z_”-type activities. That’s so much cleaner than adding yet another script-without-a-home that only you know about that has to be deployed and run a certain way but not on Tuesday…

You can certainly start using Ansible as a simple trigger, but it quickly becomes a solution to a range of problems you may not have realized you have. You’ll soon find you aren’t “doing things the way you’ve been doing them” any more. You’ll still accomplish those things, but within a manageable, scalable framework that a bunch of scripts lacks.

So, you’re on the right track. Keep looking for additional things that Ansible can do for you, and by all means keep asking good questions when you get stuck. We’re all here to help each other succeed.

---

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [February 16, 2026, 7:56pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/10 "2026-02-16T19:56:46Z")

</div>

Thank you so much @utoddl !  
I feel that I would miss a lot if I would just use Ansible to trigger my script, but your help made me realize it’s not an “all or nothing” thing. I’ll explore and progress!  
Thanks a lot to you and the splendid community 😄

---

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [March 5, 2026, 12:16pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/11 "2026-03-05T12:16:05Z")

</div>

Hi All,

I just wanted to proudly share my current progress on script commands that were now translated into small Ansible playbooks 😍

Sharing in case it can help other people. Thanks again for the kind and responsive Ansible community!

FYI:

1. I will shortly regroup my tasks into a single playbook, but using many small playbooks helped me a lot to understand, write, and test each type of action.
2. I have currently relied on `ansible.builtin.command` for the following actions:

- Perform `rsync` (todo: investigate `ansible.posix.synchronize`)
- Perform `chmod` and `chown` (todo: investigate `ansible.builtin.file` with `owner`, `group`, `state`, `mode`)
- Perform `sudo dconf update` and `sudo update-grub`

1. I still need to reflect on how to handle the end of a playbook run. When I was running the script, there was a prompt “do you want to sudo reboot?”. It helped me see if there were any errors before doing the unique reboot needed. With Ansible (made to automate, so certainly not to make interactive stuff), I wonder if I will simply rely on Ansible output and consider initiating a reboot via another tool. Any feedback is welcome!

# 1. Debian APT operations

## Script

```auto
apt update
apt upgrade -y
apt install -y rsync openssh-client openssh-server net-tools debconf-utils sddm libreoffice-l10n-fr firefox-esr-l10n-fr
apt purge -y --autoremove gnome-games

```

## Ansible playbook

```auto
---
- name: apt operations
  hosts: test
  tasks:
    - name: updates
      block:
        - name: update
          apt:
            update_cache: yes
        - name: upgrade
          apt:
            upgrade: dist
        - name: install
          apt:
            name:
              - rsync
              - openssh-client
              - openssh-server
              - net-tools
              - emacs
            state: present
        - name: remove
          apt:
            name: gnome-games
            state: absent
            autoremove: yes

```

# 2. Removal of user password with passwd

## Script

```auto
passwd -d guest

```

## Ansible playbook

```auto
---
- name: Change guest user password
  hosts: test
  tasks:
    - name: Define a new password for user guest (here: none)
      ansible.builtin.user:
        name: guest
        password: "{{ '' | password_hash('sha512') }}"

```

# 3. Files deletion (recursive, including directories)

## Script

```auto
rm -Rf /home/guest/*
rm -Rf /home/guest/.*

```

## Ansible playbook

```auto
---
- name: Empty directories
  hosts: test
  tasks:
    - name: Find content of /home/guest/
      ansible.builtin.find:
        paths: /home/guest/
        hidden: yes
        recurse: yes
        file_type: any
      register: contenu_rep
    - name: Delete all found content
      ansible.builtin.file:
        path: "{{ item.path }}"
        state: absent
      loop: "{{ contenu_rep.files }}"

```

# 4. rsync

## Script

```auto
rsync -az --progress --ignore-times root@192.168.64.1:/root/latest/etc/skel/ /etc/skel/
rsync -az --progress --ignore-times /etc/skel/ /

```

## Ansible playbook

```auto
---
- name: Run rsync commands
  hosts: test
  tasks:
    - name: rsync master to client /etc/skel
      ansible.builtin.command: rsync -az --progress --ignore-times root@$192.168.64.1:.root/latest/skel/ /etc/skel/
    - name: rsync local from /etc/skel to /
      ansible.builtin.command: rsync -az --progress --ignore-times /etc/skel/ /

```

# 5. Change files permissions and ownership

## Script

```auto
chown -R guest:guest /home/guest
chmod +x /usr/share/sddm/scripts/Xstop

```

## Ansible playbook

```auto
---
- name: Fix permissions on required files
  hosts: test
  tasks:
    - name: chown on /home/guest for guest (in case rsync messed up permissions/ownership)
      ansible.builtin.command: chown -R guest:guest /home/guest
    - name: chmod +x (cross/execute) Xstop 
      ansible.builtin.command: chmod +x /usr/share/sddm/scripts/Xstop

```

# 6. Mask (disable) some systemd services

## Script

```auto
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

```

## Ansible playbook

```auto
---
- name: With systemctl, mask sleep related services
  hosts: test
  become: yes
  tasks:
    - name: disabled (mask) sleep related services
      ansible.builtin.systemd:
        name: "{{ item }}"
        masked: yes
      loop:
        - sleep.target
        - suspend.target
        - hibernate.target
        - hybrid-sleep.target

```

# 7. Update some system config (dconf and grub)

## Script

```auto
sudo dconf update
sudo update-grub

```

## Ansible playbook

```auto
---
- name: Update config grub et dconf
  hosts: test
  become: yes
  tasks:
    - name: Update dconf
      ansible.builtin.command: sudo dconf update
    - name: Update grub
      ansible.builtin.command: sudo update-grub

```

# 8. Restart SSH Daemon

## Script

```auto
systemctl restart ssh

```

## Ansible playbook

```auto
---
- name: Restart SSH daemon
  hosts: test
  become: yes
  tasks:
    - name: restart sshd
      ansible.builtin.systemd:
        name: sshd
        state: restarted

```

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 5, 2026, 1:04pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/12 "2026-03-05T13:04:47Z")

</div>

> [@cndpansible](#):
>
> I still need to reflect on how to handle the end of a playbook run. When I was running the script, there was a prompt “do you want to sudo reboot?”. It helped me see if there were any errors before doing the unique reboot needed. With Ansible (made to automate, so certainly not to make interactive stuff), I wonder if I will simply rely on Ansible output and consider initiating a reboot via another tool. Any feedback is welcome!

You can prompt for reboots like in the following. I included a `- false` in my list of conditions because I didn’t want to actually reboot my local machine. Take that line out if you really do want to reboot.

```yaml
---
# pause.yml
- name: Demonstrate using pause with prompt to reboot
  hosts: localhost
  gather_facts: false
  become: true
  tasks:
    - name: Pause with prompt
      ansible.builtin.pause:
        prompt: "Enter 'REBOOT' to reboot"
      register: prompt

    - name: Did user ask for a reboot?
      ansible.builtin.debug:
        msg: 'Reboot requested: {{ prompt.user_input == "REBOOT" }}'

    - name: Reboot if requested
      ansible.builtin.reboot:
      when:
        - prompt.user_input == "REBOOT"
        - false # Remove this line to reboot for realz!!
      register: reboot_status

    - name: Report reboot status
      ansible.builtin.debug:
        var: reboot_status

```

---

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [March 5, 2026, 1:50pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/13 "2026-03-05T13:50:53Z")

</div>

Thanks a lot @utoddl !

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 5, 2026, 3:04pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/14 "2026-03-05T15:04:04Z")

</div>

> [@cndpansible](#):
>
> I will shortly regroup my tasks into a single playbook, but using many small playbooks helped me a lot to understand, write, and test each type of action.

Small one-off playbooks are great for trying out techniques, but integrated playbook development (or later, role development) is a technique in itself.

I got a little carried away integrating your tasks into a playbook that uses tags to execute only the part(s) you’re interested in running. In fact, if you don’t specify tags, it will stop with a message to that effect:

```plaintext
    During development, this playbook requires run tags
    that are a subset of
    - apt
    - guestpw
    - cleanup
    - rsync
    - services
    - updates
    - sshd
    - reboot
    - all

```

The other habit I highly recommend developing is to run `ansible-lint` early and often.

Here’s my take on your current tasks integrated into a single playbook. I called it `setup-test-host.yml`, and you’d run it like

```
ansible-playbook setup-test-host.yml -vv --tags=guestpw,rsync,sshd -K

```

```yaml
---
# setup-test-host.yml
- name: Demonstrate using tags in playbook development
  hosts: test
  gather_facts: true
  become: true
  tasks:
    - name: Ensure user specified valid tags
      # This is only used during playbook development
      ansible.builtin.assert:
        that:
          - ansible_run_tags | intersect(valid_tags) | length > 0
        fail_msg: |
          During development, this playbook requires run tags
          that are a subset of
          {{ valid_tags | to_nice_yaml }}
      vars:
        valid_tags:
          - apt
          - guestpw
          - cleanup
          - rsync
          - services
          - updates
          - sshd
          - reboot
          - all # in case you want to run everything
      tags: always

    - name: Manage packages
      tags: apt
      block:
        - name: Block for updates
          block:
            - name: Update the apt cache
              ansible.builtin.apt:
                update_cache: true
            - name: Distribution upgrade
              ansible.builtin.apt:
                upgrade: dist
            - name: Install selected packages
              ansible.builtin.apt:
                name:
                  - rsync
                  - openssh-client
                  - openssh-server
                  - net-tools
                  - emacs
                state: present
            - name: Remove unwanted packages
              ansible.builtin.apt:
                name: gnome-games
                state: absent
                autoremove: true

    - name: Define a new password for user guest
      ansible.builtin.user:
        name: guest
        password: "{{ '' | password_hash('sha512') }}"
      tags: guestpw

    - name: Block for directory cleanup
      tags: cleanup
      block:
        - name: Find content of /home/guest/
          ansible.builtin.find:
            paths: /home/guest/
            hidden: true
            recurse: true
            file_type: any
          register: contenu_rep
        - name: Delete all found content
          ansible.builtin.file:
            path: "{{ item.path }}"
            state: absent
          loop: "{{ contenu_rep.files }}"

    - name: Block for rsyncs
      tags: rsync
      block:
        - name: Sync master to client /etc/skel # noqa no-changed-when command-instead-of-module
          ansible.builtin.command: rsync -az --progress --ignore-times root@$192.168.64.1:.root/latest/skel/ /etc/skel/
        - name: Sync local from /etc/skel to / # noqa no-changed-when command-instead-of-module
          ansible.builtin.command: rsync -az --progress --ignore-times /etc/skel/ /
        - name: Ownership of /home/guest for guest # noqa no-changed-when
          ansible.builtin.command: chown -R guest:guest /home/guest
        - name: Mode of Xstop # noqa no-changed-when
          ansible.builtin.command: chmod +x /usr/share/sddm/scripts/Xstop

    - name: Block for system services
      tags: services
      block:
        - name: Disabled (mask) sleep-related services
          ansible.builtin.systemd:
            name: "{{ item }}"
            masked: true
          loop:
            - sleep.target
            - suspend.target
            - hibernate.target
            - hybrid-sleep.target

    - name: Block for grub et dconf
      tags: updates
      block:
        - name: Update dconf # noqa no-changed-when
          ansible.builtin.command: sudo dconf update
        - name: Update grub # noqa no-changed-when
          ansible.builtin.command: sudo update-grub

    - name: Restart sshd
      ansible.builtin.systemd:
        name: sshd
        state: restarted
      tags: sshd

    - name: Block for prompted reboot
      tags: reboot
      block:
        - name: Pause with prompt
          ansible.builtin.pause:
            prompt: "Enter 'REBOOT' to reboot"
          register: prompt

        - name: Reboot if requested
          ansible.builtin.reboot:
          when:
            - prompt.user_input == "REBOOT"
          register: reboot_status

        - name: Report reboot status
          ansible.builtin.debug:
            var: reboot_status

```

---

<div class="post-metadata">

**Author:** ![cndpansible](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@cndpansible](https://forum.ansible.com/u/cndpansible)\
**Post date:** [March 5, 2026, 5:36pm UTC](https://forum.ansible.com/t/getting-started-bash-script-actions-converted-into-a-playbook/45331/15 "2026-03-05T17:36:43Z")

</div>

Thank you so much @utoddl !  
I didn’t know well how to use tags yet, so great learning thanks to you, and it helps me a lot to understand stuff I didn’t play with yet and need to understand (`ansible-lint`, those `block`s instead of just a sequence of `name`s…)  
I just bought the O’Reilly book on Ansible, will study it starting with pointers you have kindly shared with me.  
Thanks again!
