<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Automation | przeqpiciel's site</title><link>https://przeqpiciel.com/categories/automation/</link><description>Blog techniczny o homelabie, Linuxie i innych ciekawych tematach</description><generator>Hugo</generator><language>pl</language><managingEditor>przeqpiciel</managingEditor><webMaster>przeqpiciel</webMaster><lastBuildDate>Sat, 04 Jul 2026 15:39:03 +0200</lastBuildDate><atom:link href="https://przeqpiciel.com/categories/automation/index.xml" rel="self" type="application/rss+xml"/><item><title>Ansible w praktyce - piszemy playbooki</title><link>https://przeqpiciel.com/posts/how-to-write-ansible-playbooks/</link><pubDate>Sat, 04 Jul 2026 00:00:00 +0000</pubDate><author>przeqpiciel</author><guid>https://przeqpiciel.com/posts/how-to-write-ansible-playbooks/</guid><description>&lt;h1 id="wstęp"&gt;Wstęp&lt;/h1&gt;
&lt;p&gt;W &lt;a href="https://przeqpiciel.com/posts/how-to-start-with-ansible/"&gt;poprzednim wpisie o Ansible&lt;/a&gt; przygotowaliśmy sobie warsztat: instalacja przez &lt;code&gt;pipx&lt;/code&gt;, układ katalogów projektu, plik inventory i pierwsza rola &lt;code&gt;common&lt;/code&gt;. Wszystko ładnie, tylko że rola instalująca &lt;code&gt;vim&lt;/code&gt; i &lt;code&gt;htop&lt;/code&gt; to trochę jak kupić wiertarkę i powiesić na niej ręcznik. Czas w końcu coś tym Ansible zrobić.&lt;/p&gt;
&lt;p&gt;W tym wpisie napiszemy wspólnie trzy playbooki, których sam regularnie używam w homelabie. Każdy z nich przy okazji nauczy Cię jednego z mechanizmów, które w poprzedniej części tylko zapowiedziałem: pracy z faktami i warunkami, pętli oraz szablonów Jinja2. Na koniec pokażę Ci jeszcze Ansible Vault, czyli co zrobić z hasłami, żeby nie leżały w repozytorium w plaintext, oraz kilka flag &lt;code&gt;ansible-playbook&lt;/code&gt;, które nie raz uratowały mnie przed zrobieniem sobie krzywdy.&lt;/p&gt;</description><content:encoded>&lt;h1 id="wstęp"&gt;Wstęp&lt;/h1&gt;
&lt;p&gt;W &lt;a href="https://przeqpiciel.com/posts/how-to-start-with-ansible/"&gt;poprzednim wpisie o Ansible&lt;/a&gt; przygotowaliśmy sobie warsztat: instalacja przez &lt;code&gt;pipx&lt;/code&gt;, układ katalogów projektu, plik inventory i pierwsza rola &lt;code&gt;common&lt;/code&gt;. Wszystko ładnie, tylko że rola instalująca &lt;code&gt;vim&lt;/code&gt; i &lt;code&gt;htop&lt;/code&gt; to trochę jak kupić wiertarkę i powiesić na niej ręcznik. Czas w końcu coś tym Ansible zrobić.&lt;/p&gt;
&lt;p&gt;W tym wpisie napiszemy wspólnie trzy playbooki, których sam regularnie używam w homelabie. Każdy z nich przy okazji nauczy Cię jednego z mechanizmów, które w poprzedniej części tylko zapowiedziałem: pracy z faktami i warunkami, pętli oraz szablonów Jinja2. Na koniec pokażę Ci jeszcze Ansible Vault, czyli co zrobić z hasłami, żeby nie leżały w repozytorium w plaintext, oraz kilka flag &lt;code&gt;ansible-playbook&lt;/code&gt;, które nie raz uratowały mnie przed zrobieniem sobie krzywdy.&lt;/p&gt;
&lt;p&gt;Zakładam, że masz już strukturę projektu z poprzedniego wpisu. Jeśli nie - zajrzyj tam najpierw, to dosłownie kilka minut.&lt;/p&gt;
&lt;h2 id="playbook-1-aktualizacja-wszystkich-serwerów"&gt;Playbook 1: Aktualizacja wszystkich serwerów&lt;/h2&gt;
&lt;p&gt;Zacznijmy od czegoś, co każdy z nas robi (a przynajmniej powinien robić) regularnie. Ile razy logowałeś się po kolei na każdą maszynę tylko po to, żeby wklepać &lt;code&gt;apt update &amp;amp;&amp;amp; apt upgrade&lt;/code&gt;? U mnie, przy kilku VM-kach na Proxmoxie i paru VPS-ach, potrafiło to zjeść pół wieczoru. A przecież dokładnie od tego mamy Ansible.&lt;/p&gt;
&lt;p&gt;Tworzymy plik &lt;code&gt;playbooks/update.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# playbooks/update.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Update and upgrade all servers&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;all&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;become&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;serial&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;1&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;tasks&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Update apt cache and upgrade packages&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible.builtin.apt&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;update_cache&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;upgrade&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;dist&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;autoremove&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Check if reboot is required&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible.builtin.stat&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;path&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;/var/run/reboot-required&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;register&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;reboot_required&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Reboot server if required&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible.builtin.reboot&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;msg&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;Reboot wykonany przez Ansible po aktualizacji pakietów&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;reboot_timeout&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;600&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;when&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;reboot_required.stat.exists&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rozbierzmy to na części, bo dzieje się tutaj kilka ciekawych rzeczy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;serial: 1&lt;/code&gt;&lt;/strong&gt; - instruuje Ansible, aby przechodził przez hosty pojedynczo, zamiast aktualizować wszystkie naraz. Po co? Wyobraź sobie, że nowa wersja jakiegoś pakietu okazuje się zepsuta. Bez &lt;code&gt;serial&lt;/code&gt; położysz wszystkie maszyny jednocześnie. Z &lt;code&gt;serial: 1&lt;/code&gt; problem zauważysz po pierwszej i zdążysz przerwać. Na produkcji ta jedna linijka to różnica między &amp;ldquo;mieliśmy chwilową degradację&amp;rdquo; a &amp;ldquo;mieliśmy awarię&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;upgrade: dist&lt;/code&gt;&lt;/strong&gt; - odpowiednik &lt;code&gt;apt dist-upgrade&lt;/code&gt;, czyli aktualizacja z możliwością instalacji nowych zależności. Do wyboru masz też &lt;code&gt;safe&lt;/code&gt; (odpowiednik zwykłego &lt;code&gt;apt upgrade&lt;/code&gt;) oraz &lt;code&gt;full&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;register: reboot_required&lt;/code&gt;&lt;/strong&gt; - zapisuje wynik zadania do zmiennej. Moduł &lt;code&gt;stat&lt;/code&gt; sprawdza, czy istnieje plik &lt;code&gt;/var/run/reboot-required&lt;/code&gt; - to właśnie ten plik systemy Debianowe tworzą, kiedy aktualizacja (najczęściej jądra) wymaga restartu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;when: reboot_required.stat.exists&lt;/code&gt;&lt;/strong&gt; - warunek. Zadanie rebootu wykona się tylko wtedy, kiedy plik istnieje. To jest właśnie duet &lt;code&gt;register&lt;/code&gt; + &lt;code&gt;when&lt;/code&gt;, którego będziesz używać nieustannie: jedno zadanie coś sprawdza, drugie reaguje na wynik.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;reboot&lt;/code&gt;&lt;/strong&gt; - moduł, który restartuje maszynę i - co najlepsze - sam czeka, aż wróci do życia i będzie osiągalna po SSH. &lt;code&gt;reboot_timeout: 600&lt;/code&gt; daje jej na to 10 minut.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hint hint--info"&gt;
 &lt;span class="hint-icon"&gt;ℹ️&lt;/span&gt;
 &lt;div class="hint-content"&gt;
 Zwróć uwagę na pełne nazwy modułów, np. &lt;code&gt;ansible.builtin.apt&lt;/code&gt; zamiast samego &lt;code&gt;apt&lt;/code&gt; jak w poprzednim wpisie. Obie formy działają, ale pełna nazwa (FQCN - Fully Qualified Collection Name) jest obecnie rekomendowana przez dokumentację i jednoznacznie wskazuje, skąd pochodzi moduł. Warto się przyzwyczajać od początku.
 &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Uruchamiamy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/update.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I to tyle. Od dziś aktualizacja całego homelabu to jedno polecenie i można iść zrobić herbatę.&lt;/p&gt;
&lt;h2 id="playbook-2-użytkownicy-i-klucze-ssh-czyli-pętle"&gt;Playbook 2: Użytkownicy i klucze SSH, czyli pętle&lt;/h2&gt;
&lt;p&gt;Drugi scenariusz z życia. Dokładnie z taką sytuacją miałem do czynienia, kiedy po którejś reinstalacji maszyny okazało się, że na trzech serwerach mam użytkownika ze swoim kluczem SSH, na dwóch nie mam, a na jednym jest klucz ze starego laptopa, którego nie widziałem od roku. Spójność konfiguracji, mówili.&lt;/p&gt;
&lt;p&gt;Zamiast klepać &lt;code&gt;useradd&lt;/code&gt; po serwerach, opiszmy stan docelowy w zmiennych. Do pliku &lt;code&gt;inventory/group_vars/all.yml&lt;/code&gt; dodajemy listę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# inventory/group_vars/all.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;managed_users&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;przeq&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;groups&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;sudo&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ssh_key&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... przeq@laptop&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;deploy&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;groups&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ssh_key&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... deploy@ci&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Plik w &lt;code&gt;group_vars/all&lt;/code&gt; oznacza, że zmienne będą dostępne dla wszystkich hostów z inventory. Gdybyś chciał innych użytkowników tylko na serwerach z grupy &lt;code&gt;web&lt;/code&gt;, tworzysz analogicznie &lt;code&gt;group_vars/web.yml&lt;/code&gt; - tak jak opisywałem układ katalogów w poprzedniej części.&lt;/p&gt;
&lt;p&gt;Teraz playbook &lt;code&gt;playbooks/users.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# playbooks/users.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Manage users and SSH keys&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;all&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;become&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;tasks&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Ensure users exist&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible.builtin.user&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ item.name }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;groups&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ item.groups }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;append&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;shell&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;/bin/bash&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;state&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;present&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;loop&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ managed_users }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Ensure SSH keys are present&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible.posix.authorized_key&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;user&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ item.name }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;key&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ item.ssh_key }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;state&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;present&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;loop&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ managed_users }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nowością jest tutaj &lt;strong&gt;&lt;code&gt;loop&lt;/code&gt;&lt;/strong&gt;. Ansible wykona zadanie tyle razy, ile elementów ma lista &lt;code&gt;managed_users&lt;/code&gt;, a w każdej iteracji bieżący element będzie dostępny jako &lt;code&gt;item&lt;/code&gt;. Dlatego w parametrach odwołujemy się do &lt;code&gt;item.name&lt;/code&gt; czy &lt;code&gt;item.ssh_key&lt;/code&gt;. Jedna definicja zadania, dowolna liczba użytkowników - dopisanie kolejnego to jedna pozycja na liście w &lt;code&gt;group_vars&lt;/code&gt;, a nie kolejna sesja SSH.&lt;/p&gt;
&lt;p&gt;Warto też zwrócić uwagę na &lt;code&gt;append: yes&lt;/code&gt; w module &lt;code&gt;user&lt;/code&gt;. Bez tego parametru Ansible ustawiłby użytkownikowi &lt;em&gt;dokładnie&lt;/em&gt; te grupy, które podałeś, usuwając go ze wszystkich pozostałych. Z &lt;code&gt;append: yes&lt;/code&gt; grupy są dopisywane. Ten parametr potrafi zaoszczędzić nieprzyjemnych niespodzianek.&lt;/p&gt;
&lt;div class="hint hint--warning"&gt;
 &lt;span class="hint-icon"&gt;⚠️&lt;/span&gt;
 &lt;div class="hint-content"&gt;
 Moduł &lt;code&gt;authorized_key&lt;/code&gt; pochodzi z kolekcji &lt;code&gt;ansible.posix&lt;/code&gt;. Jeśli instalowałeś Ansible przez &lt;code&gt;pipx install ansible&lt;/code&gt; tak jak w poprzednim wpisie, masz ją już na pokładzie. Jeśli jednak wybrałeś minimalny pakiet &lt;code&gt;ansible-core&lt;/code&gt;, doinstalujesz ją poleceniem &lt;code&gt;ansible-galaxy collection install ansible.posix&lt;/code&gt;.
 &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Zanim uruchomisz playbook na ostro, sprawdź co się wydarzy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/users.yml --check --diff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;O tych dwóch flagach więcej pod koniec wpisu, ale już teraz zdradzę: to najlepsi przyjaciele początkującego (i nie tylko początkującego).&lt;/p&gt;
&lt;h2 id="playbook-3-szablony-jinja2-czyli-motd-z-faktami"&gt;Playbook 3: Szablony Jinja2, czyli MOTD z faktami&lt;/h2&gt;
&lt;p&gt;Trzeci playbook będzie najprostszy, ale nauczy Cię mechanizmu, na którym opiera się połowa prawdziwych zastosowań Ansible: &lt;strong&gt;szablonów&lt;/strong&gt;. Szablon to plik z dziurami, które Ansible wypełnia zmiennymi. A skoro tak, to wykorzystamy do tego zmienne, które Ansible zbiera zupełnie za darmo - tak zwane fakty.&lt;/p&gt;
&lt;p&gt;Fakty (facts) to informacje o hoście, które Ansible zbiera na początku każdego playbooka: nazwa hosta, wersja systemu, adresy IP, ilość RAM i dziesiątki innych. Możesz je podejrzeć poleceniem:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible web1 -m setup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Przygotujmy szablon wiadomości powitalnej, którą zobaczysz po zalogowaniu na serwer. Tworzymy plik &lt;code&gt;playbooks/templates/motd.j2&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;##################################################
# {{ ansible_facts[&amp;#39;hostname&amp;#39;] }}
# System: {{ ansible_facts[&amp;#39;distribution&amp;#39;] }} {{ ansible_facts[&amp;#39;distribution_version&amp;#39;] }}
# IP: {{ ansible_facts[&amp;#39;default_ipv4&amp;#39;][&amp;#39;address&amp;#39;] }}
#
# Maszyna zarządzana przez Ansible.
# Zmiany wprowadzone ręcznie zostaną nadpisane!
##################################################
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I playbook &lt;code&gt;playbooks/motd.yml&lt;/code&gt;, który go rozpropaguje:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# playbooks/motd.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Deploy MOTD banner&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;all&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;become&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;tasks&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Template MOTD file&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible.builtin.template&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;src&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;templates/motd.j2&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;dest&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;/etc/motd&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;owner&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;root&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;group&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;root&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;mode&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#39;0644&amp;#39;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Po uruchomieniu playbooka każda maszyna dostanie swój własny, spersonalizowany baner - z własnym hostname, wersją systemu i adresem IP. Ten sam szablon, różne wyniki na każdym hoście. Dokładnie tak samo działa generowanie konfiguracji nginx, konfiguracji agenta Zabbix czy czegokolwiek innego - różnica polega tylko na tym, że zamiast faktów podstawiasz swoje zmienne z &lt;code&gt;group_vars&lt;/code&gt; albo &lt;code&gt;defaults&lt;/code&gt; roli.&lt;/p&gt;
&lt;p&gt;A ostatnia linijka szablonu to nie żart. Jeżeli plik jest zarządzany przez Ansible, to Ansible jest jedynym miejscem, w którym się go edytuje. Ręczna poprawka na serwerze zniknie przy następnym uruchomieniu playbooka - i dobrze, na tym polega utrzymywanie spójności.&lt;/p&gt;
&lt;div class="hint hint--info"&gt;
 &lt;span class="hint-icon"&gt;ℹ️&lt;/span&gt;
 &lt;div class="hint-content"&gt;
 Gdy szablonujesz konfigurację usługi (a nie zwykły plik jak MOTD), pamiętaj o dwóch rzeczach z poprzedniego wpisu: dodaj &lt;code&gt;notify&lt;/code&gt; wskazujący handler restartujący usługę oraz - jeśli program to umożliwia - parametr &lt;code&gt;validate&lt;/code&gt;, np. &lt;code&gt;validate: 'nginx -t -c %s'&lt;/code&gt;. Dzięki temu Ansible odrzuci zepsutą konfigurację, zanim ta trafi na swoje miejsce.
 &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="ansible-vault-czyli-co-z-hasłami"&gt;Ansible Vault, czyli co z hasłami&lt;/h2&gt;
&lt;p&gt;Prędzej czy później w Twoich zmiennych pojawi się coś wrażliwego: hasło do bazy, token API, cokolwiek. Trzymanie tego w repozytorium otwartym tekstem to proszenie się o kłopoty. Odpowiedzią Ansible jest Vault - wbudowane szyfrowanie plików ze zmiennymi.&lt;/p&gt;
&lt;p&gt;Zanim utworzymy zaszyfrowany plik, mała zmiana organizacyjna. Chcemy trzymać zmienne jawne i zaszyfrowane osobno, a Ansible pozwala zamiast pojedynczego pliku &lt;code&gt;group_vars/all.yml&lt;/code&gt; użyć katalogu &lt;code&gt;group_vars/all/&lt;/code&gt; i wczytać z niego wszystkie pliki. Uwaga: nie można mieć obu naraz - plik &lt;code&gt;all.yml&lt;/code&gt; i katalog &lt;code&gt;all/&lt;/code&gt; obok siebie skończą się błędem. Dlatego najpierw przenosimy dotychczasowe zmienne:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir inventory/group_vars/all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mv inventory/group_vars/all.yml inventory/group_vars/all/vars.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Teraz tworzymy zaszyfrowany plik obok:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-vault create inventory/group_vars/all/vault.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ansible zapyta o hasło, a następnie otworzy edytor. Wpisujemy zmienne jak do każdego innego pliku:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;vault_grafana_admin_password&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;SuperTajneHaslo123&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Po zapisaniu plik na dysku wygląda tak:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ANSIBLE_VAULT;1.1;AES256
36613831356362376361643230623232616139383564383936633463323...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Możesz go spokojnie commitować do repozytorium - bez hasła nikt go nie odczyta. W playbookach używasz zmiennej normalnie, natomiast przy uruchamianiu dodajesz flagę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/site.yml --ask-vault-pass
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do edycji zaszyfrowanego pliku służy &lt;code&gt;ansible-vault edit&lt;/code&gt;, a do podejrzenia &lt;code&gt;ansible-vault view&lt;/code&gt;.&lt;/p&gt;
&lt;div class="hint hint--warning"&gt;
 &lt;span class="hint-icon"&gt;⚠️&lt;/span&gt;
 &lt;div class="hint-content"&gt;
 Przyjęła się konwencja, aby zmienne z Vault poprzedzać prefixem &lt;code&gt;vault_&lt;/code&gt;. Kiedy w playbooku widzisz &lt;code&gt;{{ vault_grafana_admin_password }}&lt;/code&gt;, od razu wiesz, gdzie szukać jej definicji i że jest wrażliwa. Drobiazg, a przy większym projekcie robi ogromną różnicę.
 &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="flagi-które-uratują-ci-skórę"&gt;Flagi, które uratują Ci skórę&lt;/h2&gt;
&lt;p&gt;Na koniec obiecany zestaw flag &lt;code&gt;ansible-playbook&lt;/code&gt;, których używam praktycznie przy każdym uruchomieniu:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--check&lt;/code&gt;&lt;/strong&gt; - tryb &amp;ldquo;na sucho&amp;rdquo;. Ansible przechodzi przez wszystkie zadania i raportuje, co &lt;em&gt;by&lt;/em&gt; zmienił, ale niczego nie dotyka. Idealne przed pierwszym uruchomieniem nowego playbooka.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--diff&lt;/code&gt;&lt;/strong&gt; - pokazuje różnice w modyfikowanych plikach, w formacie znanym z &lt;code&gt;git diff&lt;/code&gt;. W duecie z &lt;code&gt;--check&lt;/code&gt; dostajesz pełny podgląd zmian, zanim się na nie zgodzisz.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--limit web1&lt;/code&gt;&lt;/strong&gt; - ogranicza wykonanie do wskazanego hosta lub grupy, niezależnie od tego, co playbook ma w &lt;code&gt;hosts&lt;/code&gt;. Nowy playbook testuję zawsze najpierw na jednej, najmniej ważnej maszynie.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--tags users&lt;/code&gt;&lt;/strong&gt; - wykonuje tylko zadania oznaczone danym tagiem. Tagi dodajesz do zadania parametrem &lt;code&gt;tags: ['users']&lt;/code&gt;. Przy dużym playbooku oszczędza to mnóstwo czasu, bo nie musisz przechodzić przez wszystko, żeby poprawić jedną rzecz.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--syntax-check&lt;/code&gt;&lt;/strong&gt; - błyskawiczna weryfikacja składni playbooka, bez łączenia się z hostami. YAML bywa złośliwy w kwestii wcięć, więc warto odpalać ją nawykowo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mój typowy cykl pracy z nowym playbookiem wygląda więc tak:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/users.yml --syntax-check
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/users.yml --check --diff --limit web1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/users.yml --limit web1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/users.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Od składni, przez próbę generalną na jednej maszynie, aż po całą infrastrukturę. Nudno? Może trochę. Ale jeszcze nigdy tym sposobem nie położyłem sobie całego homelabu naraz, a zdarzało mi się to w czasach, kiedy flagi &lt;code&gt;--check&lt;/code&gt; używałem wyłącznie od święta.&lt;/p&gt;
&lt;h2 id="podsumowanie"&gt;Podsumowanie&lt;/h2&gt;
&lt;p&gt;W tym wpisie przeszliśmy od teorii do praktyki:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Playbook aktualizujący wszystkie serwery z kontrolowanym restartem (&lt;code&gt;register&lt;/code&gt;, &lt;code&gt;when&lt;/code&gt;, &lt;code&gt;serial&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Zarządzanie użytkownikami i kluczami SSH z jednej listy zmiennych (&lt;code&gt;loop&lt;/code&gt;, &lt;code&gt;group_vars&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Szablony Jinja2 wypełniane faktami hosta (&lt;code&gt;template&lt;/code&gt;, facts)&lt;/li&gt;
&lt;li&gt;Szyfrowanie wrażliwych zmiennych z Ansible Vault&lt;/li&gt;
&lt;li&gt;Flagi &lt;code&gt;--check&lt;/code&gt;, &lt;code&gt;--diff&lt;/code&gt;, &lt;code&gt;--limit&lt;/code&gt; i &lt;code&gt;--tags&lt;/code&gt;, czyli siatka bezpieczeństwa przy każdym uruchomieniu&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Te trzy playbooki możesz potraktować jako szkielet i rozbudowywać o własne potrzeby - dorzucić instalację agenta &lt;a href="https://przeqpiciel.com/posts/how-to-monitor-your-services/"&gt;Zabbix&lt;/a&gt; do monitoringu, konfigurację &lt;a href="https://przeqpiciel.com/posts/how-to-tunnel-through-vps/"&gt;WireGuard&lt;/a&gt; czy cokolwiek, co do tej pory klepałeś ręcznie. Zasada jest zawsze ta sama: opisujesz stan docelowy, a Ansible martwi się resztą.&lt;/p&gt;
&lt;p&gt;W kolejnych krokach warto zerknąć na przenoszenie playbooków do ról (o strukturze ról pisałem w części pierwszej), a docelowo na uruchamianie ich automatycznie z CI. Ale to już materiał na osobny wpis.&lt;/p&gt;
&lt;p&gt;Powodzenia w automatyzacji!&lt;/p&gt;</content:encoded></item><item><title>Jak zacząć z Ansible</title><link>https://przeqpiciel.com/posts/how-to-start-with-ansible/</link><pubDate>Sun, 25 Jan 2026 00:00:00 +0000</pubDate><author>przeqpiciel</author><guid>https://przeqpiciel.com/posts/how-to-start-with-ansible/</guid><description>&lt;h1 id="wstęp"&gt;Wstęp&lt;/h1&gt;
&lt;p&gt;Czy zdarzyło Ci się zarządzać wieloma serwerami i ręcznie konfigurować każdy z nich? Możliwe, że już słyszałeś o narzędziach do automatyzacji, ale nie wiedziałeś od czego zacząć. W tym artykule pokażę Ci, jak rozpocząć przygodę z Ansible - jednym z najpopularniejszych narzędzi do automatyzacji konfiguracji i zarządzania infrastrukturą.&lt;/p&gt;
&lt;p&gt;Ansible to potężne narzędzie, które pozwala na zarządzanie wieloma serwerami jednocześnie, bez konieczności instalowania agentów na docelowych maszynach. Wystarczy, że masz dostęp SSH do swoich serwerów, a Ansible zrobi resztę. W moim przypadku, kiedy zarządzałem kilkoma serwerami VPS i musiałem na każdym z nich wykonać te same czynności, Ansible okazał się prawdziwym zbawieniem.&lt;/p&gt;</description><content:encoded>&lt;h1 id="wstęp"&gt;Wstęp&lt;/h1&gt;
&lt;p&gt;Czy zdarzyło Ci się zarządzać wieloma serwerami i ręcznie konfigurować każdy z nich? Możliwe, że już słyszałeś o narzędziach do automatyzacji, ale nie wiedziałeś od czego zacząć. W tym artykule pokażę Ci, jak rozpocząć przygodę z Ansible - jednym z najpopularniejszych narzędzi do automatyzacji konfiguracji i zarządzania infrastrukturą.&lt;/p&gt;
&lt;p&gt;Ansible to potężne narzędzie, które pozwala na zarządzanie wieloma serwerami jednocześnie, bez konieczności instalowania agentów na docelowych maszynach. Wystarczy, że masz dostęp SSH do swoich serwerów, a Ansible zrobi resztę. W moim przypadku, kiedy zarządzałem kilkoma serwerami VPS i musiałem na każdym z nich wykonać te same czynności, Ansible okazał się prawdziwym zbawieniem.&lt;/p&gt;
&lt;h2 id="co-to-jest-ansible"&gt;Co to jest Ansible?&lt;/h2&gt;
&lt;p&gt;Ansible to narzędzie do automatyzacji infrastruktury IT, które pozwala na:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Konfigurację serwerów&lt;/strong&gt; - instalację pakietów, konfigurację usług, zarządzanie plikami&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wdrażanie aplikacji&lt;/strong&gt; - automatyzację procesu deploymentu&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orkiestrację&lt;/strong&gt; - zarządzanie wieloma serwerami jednocześnie&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zarządzanie konfiguracją&lt;/strong&gt; - utrzymanie spójności konfiguracji na wielu maszynach&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Główną zaletą Ansible jest to, że działa w modelu &amp;ldquo;agentless&amp;rdquo; - nie wymaga instalacji żadnego oprogramowania na docelowych serwerach. Wystarczy Python (który jest domyślnie dostępny na większości systemów Linux) i dostęp SSH.&lt;/p&gt;
&lt;p&gt;Ansible używa języka YAML do definiowania zadań, co czyni go bardzo czytelnym i łatwym do zrozumienia. Nawet jeśli nie jesteś programistą, po krótkim czasie będziesz w stanie tworzyć własne playbooki.&lt;/p&gt;
&lt;h2 id="po-co-używać-ansible"&gt;Po co używać Ansible?&lt;/h2&gt;
&lt;p&gt;Wyobraź sobie sytuację: masz pięć serwerów i musisz na każdym z nich:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zainstalować podstawowe pakiety (curl, git, vim)&lt;/li&gt;
&lt;li&gt;Skonfigurować firewall&lt;/li&gt;
&lt;li&gt;Zainstalować i skonfigurować nginx&lt;/li&gt;
&lt;li&gt;Dodać użytkownika z odpowiednimi uprawnieniami&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bez Ansible, musiałbyś zalogować się na każdy serwer osobno i wykonać te same polecenia pięć razy. Z Ansible, tworzysz jeden plik konfiguracyjny (playbook), który wykonasz raz, a wszystkie serwery zostaną skonfigurowane automatycznie.&lt;/p&gt;
&lt;p&gt;Dodatkowe korzyści:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Idempotencja&lt;/strong&gt; - możesz uruchomić playbook wielokrotnie, a Ansible upewni się, że stan końcowy jest zawsze taki sam&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dokumentacja&lt;/strong&gt; - Twój playbook jest jednocześnie dokumentacją tego, co zostało skonfigurowane&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wersjonowanie&lt;/strong&gt; - możesz trzymać konfigurację w Git i śledzić zmiany&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testowanie&lt;/strong&gt; - możesz testować konfigurację na środowisku testowym przed wdrożeniem na produkcję&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="instalacja-ansible-z-użyciem-pipx"&gt;Instalacja Ansible z użyciem pipx&lt;/h2&gt;
&lt;p&gt;Istnieje kilka sposobów instalacji Ansible. W tym artykule pokażę instalację za pomocą &lt;code&gt;pipx&lt;/code&gt;, które jest rekomendowanym sposobem dla użytkowników, którzy chcą mieć Ansible zainstalowany lokalnie, bez wpływu na systemowe pakiety Pythona.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pipx&lt;/code&gt; to narzędzie, które instaluje aplikacje Pythona w izolowanych środowiskach, co zapobiega konfliktom zależności. Jeśli nie masz jeszcze &lt;code&gt;pipx&lt;/code&gt; zainstalowanego, możesz go zainstalować na Ubuntu/Debian:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Instalacja pipx na Ubuntu/Debian&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install pipx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pipx ensurepath
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Po zainstalowaniu &lt;code&gt;pipx&lt;/code&gt;, możesz zainstalować Ansible:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Instalacja Ansible za pomocą pipx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pipx install ansible
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Po instalacji, możesz zweryfikować, że Ansible działa poprawnie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Sprawdzenie wersji Ansible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Powinieneś zobaczyć coś podobnego do:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible [core 2.15.x]
 config file = None
 configured module search path = [&amp;#39;/home/user/.local/share/ansible/plugins/modules&amp;#39;]
 ansible python module location = /home/user/.local/pipx/venvs/ansible/lib/python3.x/site-packages/ansible
 ansible collection location = /home/user/.local/share/ansible/collections
 executable location = /home/user/.local/bin/ansible
 python version = 3.x.x
 jinja version = 3.x.x
 libyaml = True
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="proponowany-układ-projektu"&gt;Proponowany układ projektu&lt;/h2&gt;
&lt;p&gt;Zgodnie z &lt;a href="https://docs.ansible.com/projects/ansible/latest/tips_tricks/sample_setup.html"&gt;oficjalną dokumentacją Ansible&lt;/a&gt;, zalecany jest następujący układ katalogów dla projektu:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible-project/
├── ansible.cfg # Konfiguracja Ansible
├── inventory/ # Definicje hostów
│ ├── hosts.yml # Plik z definicjami serwerów
│ └── group_vars/ # Zmienne dla grup hostów
│ └── all.yml
├── playbooks/ # Playbooki
│ └── site.yml # Główny playbook
├── roles/ # Role Ansible
│ ├── common/
│ ├── security/
│ └── nginx/
└── requirements.yml # Zależności (role z Ansible Galaxy)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Stwórzmy ten katalog krok po kroku:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Utworzenie struktury katalogów&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p ansible-project/&lt;span style="color:#ff7b72;font-weight:bold"&gt;{&lt;/span&gt;inventory/group_vars,playbooks,roles&lt;span style="color:#ff7b72;font-weight:bold"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ansible-project
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Następnie stwórzmy podstawowy plik &lt;code&gt;ansible.cfg&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# ansible.cfg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;[defaults]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inventory &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;inventory/hosts.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;roles_path &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;roles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;host_key_checking &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;retry_files_enabled &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;[privilege_escalation]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;become &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;become_method &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;sudo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;become_user &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;become_ask_pass &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; &lt;span style="color:#a5d6ff"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Teraz stwórzmy podstawowy plik inventory &lt;code&gt;inventory/hosts.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# inventory/hosts.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;all&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;children&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;web&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;web1&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible_host&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;192.168.1.10&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible_user&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;ubuntu&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;web2&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible_host&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;192.168.1.11&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible_user&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;ubuntu&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;db&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;db1&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible_host&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;192.168.1.20&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;ansible_user&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;ubuntu&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hint hint--info"&gt;
 &lt;span class="hint-icon"&gt;ℹ️&lt;/span&gt;
 &lt;div class="hint-content"&gt;
 Zastąp adresy IP i użytkowników własnymi wartościami. Jeśli używasz kluczy SSH, upewnij się, że są one dodane do agenta SSH lub użyj opcji &lt;code&gt;ansible_ssh_private_key_file&lt;/code&gt; w inventory.
 &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tworzenie-roli-za-pomocą-ansible-galaxy-init"&gt;Tworzenie roli za pomocą ansible-galaxy init&lt;/h2&gt;
&lt;p&gt;Role w Ansible to sposób na organizację i ponowne wykorzystanie zadań. Zamiast pisać wszystkie zadania w jednym playbooku, możesz stworzyć role, które można używać w różnych projektach.&lt;/p&gt;
&lt;p&gt;Ansible Galaxy to narzędzie, które pomaga w tworzeniu nowych ról. Użyjmy go do stworzenia przykładowej roli &lt;code&gt;common&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Przejście do katalogu roles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd roles
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Utworzenie nowej roli za pomocą ansible-galaxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-galaxy init common
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To polecenie utworzy następującą strukturę:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;roles/common/
├── defaults/
│ └── main.yml # Domyślne zmienne roli
├── files/ # Pliki statyczne do kopiowania
├── handlers/
│ └── main.yml # Handlery (np. restart usługi)
├── meta/
│ └── main.yml # Metadane roli
├── tasks/
│ └── main.yml # Główne zadania roli
├── templates/ # Szablony Jinja2
├── tests/
│ ├── inventory
│ └── test.yml
└── vars/
 └── main.yml # Zmienne roli (wyższy priorytet niż defaults)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Teraz stwórzmy prostą rolę &lt;code&gt;common&lt;/code&gt;, która zainstaluje podstawowe pakiety. Edytujmy plik &lt;code&gt;roles/common/tasks/main.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/common/tasks/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Update apt cache&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;apt&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;update_cache&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;cache_valid_time&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;3600&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Install basic packages&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;apt&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;curl&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;git&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;vim&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;htop&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;wget&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;state&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;present&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Ensure timezone is set to Europe/Warsaw&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;timezone&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Europe/Warsaw&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Możemy również zdefiniować zmienne w &lt;code&gt;roles/common/defaults/main.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/common/defaults/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;common_packages&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;curl&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;git&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;vim&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;htop&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;wget&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;timezone&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Europe/Warsaw&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I zaktualizować &lt;code&gt;tasks/main.yml&lt;/code&gt;, aby używał tych zmiennych:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/common/tasks/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Update apt cache&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;apt&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;update_cache&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;cache_valid_time&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;3600&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Install basic packages&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;apt&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ common_packages }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;state&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;present&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Ensure timezone is set&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;timezone&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#34;{{ timezone }}&amp;#34;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Teraz stwórzmy prosty playbook &lt;code&gt;playbooks/site.yml&lt;/code&gt;, który użyje tej roli:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# playbooks/site.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Configure all servers&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;all&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;become&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;roles&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;common&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Możesz teraz przetestować swoją rolę:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Test połączenia z hostami&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible all -m ping
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Uruchomienie playbooka (dry-run)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/site.yml --check
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Uruchomienie playbooka&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook playbooks/site.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="złote-zasady-tworzenia-ról-best-practices"&gt;Złote Zasady Tworzenia Ról (Best Practices)&lt;/h2&gt;
&lt;p&gt;Oto zestaw zasad, które sprawią, że Twoje role będą profesjonalne i łatwe w utrzymaniu.&lt;/p&gt;
&lt;h3 id="1-nazewnictwo-ról"&gt;1. Nazewnictwo ról&lt;/h3&gt;
&lt;p&gt;Zamiast używać numeracji w nazwach ról (co sugeruje kolejność wykonania), używaj opisowych nazw:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zamiast:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;roles/
├── 00-checks/
├── 01-common/
├── 02-security/
└── 10-nginx/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Stosuj:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;roles/
├── common/ # Podstawowe pakiety (curl, git, vim)
├── security/ # Fail2ban, SSH hardening, Firewall
├── nginx/ # Tylko instalacja i konfig serwera WWW
├── app_deploy/ # Logika specyficzna dla Twojej aplikacji
└── monitoring/ # Np. node_exporter
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Kolejność wykonania ról definiuj w playbooku, nie w nazwach katalogów.&lt;/p&gt;
&lt;h3 id="2-organizacja-playbooków"&gt;2. Organizacja playbooków&lt;/h3&gt;
&lt;p&gt;A kolejność zdefiniuj w pliku &lt;code&gt;playbooks/site.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# playbooks/site.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Configure all servers&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;all&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;become&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;roles&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;common&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;security&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;monitoring&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Configure web servers&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;hosts&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;web&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;become&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#79c0ff"&gt;yes&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;roles&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;- &lt;span style="color:#a5d6ff"&gt;app_deploy&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To podejście jest czytelne, elastyczne i zgodne ze standardami branżowymi.&lt;/p&gt;
&lt;h3 id="3-używaj-zmiennych"&gt;3. Używaj zmiennych&lt;/h3&gt;
&lt;p&gt;Zamiast hardkodować wartości, używaj zmiennych w &lt;code&gt;defaults/main.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/nginx/defaults/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;nginx_user&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;www-data&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;nginx_worker_processes&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;auto&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;nginx_worker_connections&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;1024&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-idempotencja"&gt;4. Idempotencja&lt;/h3&gt;
&lt;p&gt;Upewnij się, że Twoje zadania są idempotentne - możesz je uruchomić wielokrotnie bez zmiany wyniku:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Dobrze - idempotentne&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Ensure package is installed&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;apt&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;state&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;present&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# Źle - nie idempotentne&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Install nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;command&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;apt-get install -y nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="5-używaj-handlerów-do-restartowania-usług"&gt;5. Używaj handlerów do restartowania usług&lt;/h3&gt;
&lt;p&gt;Zamiast restartować usługi w każdym zadaniu, używaj handlerów:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/nginx/tasks/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Configure nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;template&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;src&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;nginx.conf.j2&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;dest&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;/etc/nginx/nginx.conf&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;notify&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;restart nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/nginx/handlers/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;restart nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;systemd&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;nginx&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;state&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;restarted&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="6-dokumentuj-swoje-role"&gt;6. Dokumentuj swoje role&lt;/h3&gt;
&lt;p&gt;Dodaj opis w &lt;code&gt;meta/main.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;# roles/common/meta/main.yml&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;---&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7ee787"&gt;galaxy_info&lt;/span&gt;:&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;role_name&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;common&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;description&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Installs common packages and basic configuration&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;author&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;Twoje Imię&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;license&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;MIT&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#7ee787"&gt;min_ansible_version&lt;/span&gt;:&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;&amp;#39;2.9&amp;#39;&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="podsumowanie"&gt;Podsumowanie&lt;/h2&gt;
&lt;p&gt;W tym artykule dowiedziałeś się:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Czym jest Ansible i dlaczego warto go używać&lt;/li&gt;
&lt;li&gt;Jak zainstalować Ansible za pomocą &lt;code&gt;pipx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Jak zorganizować projekt Ansible zgodnie z najlepszymi praktykami&lt;/li&gt;
&lt;li&gt;Jak stworzyć własną rolę za pomocą &lt;code&gt;ansible-galaxy init&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Złote zasady tworzenia ról&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ansible to potężne narzędzie, które może znacznie uprościć zarządzanie Twoją infrastrukturą. Zacznij od prostych ról i stopniowo rozbudowuj swoją automatyzację. Pamiętaj, że każdy playbook to jednocześnie dokumentacja tego, co zostało skonfigurowane.&lt;/p&gt;
&lt;p&gt;W następnych krokach możesz:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stworzyć role dla konkretnych usług (nginx, PostgreSQL, Redis)&lt;/li&gt;
&lt;li&gt;Poznać zaawansowane funkcje Ansible (templates, loops, conditionals)&lt;/li&gt;
&lt;li&gt;Zintegrować Ansible z CI/CD&lt;/li&gt;
&lt;li&gt;Używać Ansible Vault do przechowywania wrażliwych danych&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Powodzenia w automatyzacji!&lt;/p&gt;</content:encoded></item></channel></rss>