<?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>SmallOps on ascia.tech</title>
    <link>https://ascia.tech/tags/smallops/</link>
    <description>Recent content in SmallOps on ascia.tech</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <managingEditor>cmhobbs@ascia.tech (C.M. Hobbs)</managingEditor>
    <webMaster>cmhobbs@ascia.tech (C.M. Hobbs)</webMaster>
    <copyright>C.M. Hobbs</copyright>
    <lastBuildDate>Thu, 09 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://ascia.tech/tags/smallops/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>SmallOps Part 1:  Rootless Podman Containers as Systemd Units with jinja2 Tempates</title>
      <link>https://ascia.tech/blog/smallops-with-podman-pt1/</link>
      <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate><author>cmhobbs@ascia.tech (C.M. Hobbs)</author>
      <guid>https://ascia.tech/blog/smallops-with-podman-pt1/</guid>
      <description>&lt;p&gt;When I started writing this post, it grew substantially larger than intended.&#xA;Initially I set out to document how I&amp;rsquo;ve moved from deploying podman&#xA;containers using jinja2 templates to using quadlets but it exposed an idea&#xA;that&amp;rsquo;s been in the back of my head for a bit:  SmallOps.  General&#xA;sysadmin/devoops stuff that isn&amp;rsquo;t big enterprise and isn&amp;rsquo;t directly MSP type&#xA;management.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve decided to break this information up into posts with some practical&#xA;examples. I&amp;rsquo;m starting with how I deploy podman containers in my homelab using&#xA;jinja2 templates.  I&amp;rsquo;ll expand from there, probably moving beyond podman as a&#xA;topic.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When I started writing this post, it grew substantially larger than intended.
Initially I set out to document how I&rsquo;ve moved from deploying podman
containers using jinja2 templates to using quadlets but it exposed an idea
that&rsquo;s been in the back of my head for a bit:  SmallOps.  General
sysadmin/devoops stuff that isn&rsquo;t big enterprise and isn&rsquo;t directly MSP type
management.</p>
<p>I&rsquo;ve decided to break this information up into posts with some practical
examples. I&rsquo;m starting with how I deploy podman containers in my homelab using
jinja2 templates.  I&rsquo;ll expand from there, probably moving beyond podman as a
topic.</p>
<p>I am not a massive fan of systemd or k8s by any stretch of the imagination but
I am also relatively pragmatic.  I did not heavily adopt containers in my own
infrastructure until recent years (though I&rsquo;ve dealt with them professionally)
for quite a while now.  While the world rode the serverless hype-wave, I took
time to evaluate my options over those years.</p>
<p>A lot of folks jump directly to k8s for their projects when it&rsquo;s often not
needed.  I tend to only reach for k8s whenever I know that I will need to make
large scaling leaps quickly.  For everything else, a few containers running on
a VM or VPS is totally fine (especially in the homelab).</p>
<p>My infra-related client base can be categorized by two groups at the moment:</p>
<ol>
<li>Cloud-dependent or cloud-native types</li>
<li>On-prem traditional rack types</li>
</ol>
<p>For the first group, I lean into k8s or various serverless options from the big
cloud providers. Typically they either need scaling agility and/or they want
more managed services and abstractions.  For the second group, I lean into VMs
and containers because they are usually running very small workloads.  Both can
be managed with OpenTofu and Asible equally well.  I like to consider the
second group as &ldquo;SmallOps&rdquo; and it&rsquo;s a different kind of management approach.</p>
<p>I know Docker is the king of containers these days and I interface with it
daily.  For my homelab and the second group of clients, I&rsquo;ve reached for Podman
instead of docker for a couple of reasons:  daemonless architecture and
rootless operation.  The third (and maybe most weighty reason) is because
Fedora and RedHat servers have a high adoption rate among my clients.  I would
eventually like to look into k8s integrations with podman but that&rsquo;s a
post/exercise for another day.</p>
<h2 id="antiquated-deployments-in-the-homelab">Antiquated Deployments in the Homelab</h2>
<p>A while back, my main home server shuffled off this mortal coil.  I used the
opportunity to completely start over and rebuild everything with cleaner
playbooks.  My container layout on the old server was chaotic at best and I
wanted to get it under control.</p>
<p>I had conceded the systemd fight ages ago but knew I would have to deal with it
in the homelab if I wanted to keep up with the rest of the world and have
access to quality documentation.  I had read about people creating systemd
units for their containers and I thought this would be a useful thing to have
in my environment.</p>
<p>At the time, I had not yet read about Quadlets, so I ended up using jinja2
templates in my playbooks that create systemd units for me.  While there isn&rsquo;t
necessarily anything wrong with this process, I don&rsquo;t recommend it for regular
use.  There&rsquo;s easier ways to handle this these days but I&rsquo;m writing it out for
historical reference.</p>
<p>For this post, I&rsquo;ll go over a high level look at what I have and then provide specific examples with my pi-hole container.  My basic deployment pipeline in the homelab looks something like this:</p>
<ol>
<li>Container definitions live in yaml dicts in my ansible host_vars (one per
host).  Each container is defined with its image, ports, volumes, env
vars, optional devices, and mount flags.</li>
<li>Jinja2 templates in <code>playbooks/templates/</code> generate systemd <code>.service</code>
files.  Each container gets its own template (e.g.,
<code>container-pihole.service.j2</code>). These are not generic; each template is
written for the specific container&rsquo;s needs.</li>
<li>Ansible deploys the rendered service files to <code>~/.config/systemd/user/</code> on
the target host, then triggers <code>systemctl --user daemon-reload</code> and
restarts the service via handlers.</li>
</ol>
<p>The systemd unit structure I have looks something like this for all of the containers:</p>





<pre tabindex="0"><code>[Unit]
Description=Podman container-&lt;name&gt;
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
ExecStartPre=/usr/bin/podman pull &lt;image&gt;
ExecStart=/usr/bin/podman run --rm --name &lt;name&gt; \
    -p &lt;host&gt;:&lt;container&gt; \
    -v &lt;host_path&gt;:&lt;container_path&gt;:Z \
    -e KEY=VALUE \
    &lt;image&gt;
ExecStop=/usr/bin/podman stop -t 10 &lt;name&gt;
ExecStopPost=/usr/bin/podman rm -f &lt;name&gt;
Restart=on-failure
RestartSec=30

[Install]
WantedBy=default.target</code></pre><p>A few things to note here: <code>ExecStartPre</code> pulls the latest image before
starting (hacky auto-update mechanism because I am lazy).  The <code>--rm</code> flag
cleans up the container on stop.  <code>ExecStopPost</code> with <code>podman rm -f</code> is a
safety net of sorts to avoid a stopped but not removed state.
<code>WantedBy=default.target</code> (not multi-user.target) because these are user units.</p>
<p>I won&rsquo;t get into variations by container for now but for my pi-hole, I need to
bind to port 53.  This isn&rsquo;t easily done so I have to allow users to do that.<br>
This is pretty sketchy from my perspective.  I would like to find a better way
to handle this at some point but the risk is tolerable in my homelab.  Here&rsquo;s
the snippet in my &lsquo;site.yaml&rsquo; file that sets that up:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Allow unprivileged users to bind low ports</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">  </span><span class="nt">become</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">  </span><span class="nt">ansible.posix.sysctl</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">net.ipv4.ip_unprivileged_port_start</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">    </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;53&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">    </span><span class="nt">sysctl_set</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="l">present</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">    </span><span class="nt">reload</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">containers, system]</span></span></span></code></pre></div><p>Also, one other quirk i use is that I <a href="https://wiki.archlinux.org/title/Podman#Containers_terminate_on_shell_logout">enable lingering</a> for user services:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Enable lingering for {{ primary_user }}</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">  </span><span class="nt">become</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.command</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">    </span><span class="nt">cmd</span><span class="p">:</span><span class="w"> </span><span class="l">loginctl enable-linger {{ primary_user }}</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">  </span><span class="nt">changed_when</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">containers, system]</span></span></span></code></pre></div><p>Going back to the deployment pipeline I mentioned above, here is my container
definition for my <code>host_vars</code> file for the server pi-hole lives on (and I need to fix that timezone&hellip;):</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">pihole</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">  </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">docker.io/pihole/pihole:latest</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">  </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ bind_ip }}:53:53/tcp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ bind_ip }}:53:53/udp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;127.0.0.1:53:53/tcp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;127.0.0.1:53:53/udp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ bind_ip }}:8080:80/tcp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">  </span><span class="nt">env</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="nt">TZ</span><span class="p">:</span><span class="w"> </span><span class="l">America/New_York</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">    </span><span class="nt">DNSMASQ_LISTENING</span><span class="p">:</span><span class="w"> </span><span class="l">all</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">  </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ containers_dir }}/pihole/etc-pihole:/etc/pihole:Z&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ containers_dir }}/pihole/etc-dnsmasq.d:/etc/dnsmasq.d:Z&#34;</span></span></span></code></pre></div><p>Here is the jinja2 template I use for my pi-hole container:</p>





<pre tabindex="0"><code class="language-jinja2" data-lang="jinja2">[Unit]
Description=Pi-hole Container
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Restart=always
RestartSec=10
ExecStartPre=-/usr/bin/podman rm -f pihole
ExecStart=/usr/bin/podman run --name pihole \
{% for port in containers.pihole.ports %}
  -p {{ port }} \
{% endfor %}
{% for key, val in containers.pihole.env.items() %}
  -e {{ key }}={{ val }} \
{% endfor %}
{% for vol in containers.pihole.volumes %}
  -v {{ vol }} \
{% endfor %}
  --replace \
  {{ containers.pihole.image }}
ExecStop=/usr/bin/podman stop pihole
ExecStopPost=-/usr/bin/podman rm -f pihole

[Install]
WantedBy=default.target</code></pre><p>Lastly here&rsquo;s the remaining setup bits in my <code>site.yml</code> file:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Create container directories</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">  </span><span class="nt">become</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.file</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ item }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="l">directory</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span><span class="nt">owner</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_user }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">    </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_user }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">    </span><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0755&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">  </span><span class="nt">loop</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="c"># other dir defs go here</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ containers_dir }}/pihole&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ containers_dir }}/pihole/etc-pihole&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span>- <span class="s2">&#34;{{ containers_dir }}/pihole/etc-dnsmasq.d&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">    </span><span class="c"># other dir defs go here, too</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">containers]</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">  
</span></span></span><span class="line"><span class="ln">17</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Create user systemd directory</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">  </span><span class="nt">become</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.file</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="w">    </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_home }}/.config/systemd/user&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="w">    </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="l">directory</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">    </span><span class="nt">owner</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_user }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">    </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_user }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">    </span><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0755&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">containers]</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="c"># install other services before this</span><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Install Pi-hole user service</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">  </span><span class="nt">become</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">  </span><span class="nt">become_user</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_user }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="w">    </span><span class="nt">src</span><span class="p">:</span><span class="w"> </span><span class="l">templates/container-pihole.service.j2</span><span class="w">
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="w">    </span><span class="nt">dest</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_home }}/.config/systemd/user/container-pihole.service&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="w">    </span><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0644&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="w">  </span><span class="nt">notify</span><span class="p">:</span><span class="w"> </span><span class="l">reload user systemd</span><span class="w">
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">containers]</span><span class="w">
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">38</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Flush handlers before enabling services</span><span class="w">
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.meta</span><span class="p">:</span><span class="w"> </span><span class="l">flush_handlers</span><span class="w">
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">41</span><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Enable and start container services</span><span class="w">
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="w">  </span><span class="nt">become</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="w">  </span><span class="nt">become_user</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ primary_user }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.shell</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="sd">    export XDG_RUNTIME_DIR=/run/user/$(id -u)
</span></span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="sd">    export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
</span></span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="sd">    systemctl --user enable {{ item }}
</span></span></span><span class="line"><span class="ln">48</span><span class="cl"><span class="sd">    systemctl --user start {{ item }}</span><span class="w">
</span></span></span><span class="line"><span class="ln">49</span><span class="cl"><span class="w">  </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">50</span><span class="cl"><span class="w">    </span><span class="nt">executable</span><span class="p">:</span><span class="w"> </span><span class="l">/bin/bash</span><span class="w">
</span></span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="w">  </span><span class="nt">loop</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="w">    </span><span class="c"># other services here</span><span class="w">
</span></span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="w">    </span>- <span class="l">container-pihole.service</span><span class="w">
</span></span></span><span class="line"><span class="ln">54</span><span class="cl"><span class="w">    </span><span class="c"># yet more services here</span><span class="w">
</span></span></span><span class="line"><span class="ln">55</span><span class="cl"><span class="w">  </span><span class="nt">when</span><span class="p">:</span><span class="w"> </span><span class="l">not ansible_check_mode</span><span class="w">
</span></span></span><span class="line"><span class="ln">56</span><span class="cl"><span class="w">  </span><span class="nt">changed_when</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">57</span><span class="cl"><span class="w">  </span><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">containers]</span></span></span></code></pre></div><p>With all of that configuration out of the way, the final process looks
something like this:</p>
<ol>
<li>I run the play with <code>ansible-playbook -i playbooks/inventory.ini playbooks/site.yml</code></li>
<li>Ansible picks up my inventory and vars</li>
<li>Lingering is enabled so my containers don&rsquo;t stop on logout</li>
<li>The appropriate directories are created</li>
<li>The template is rendered and the reload user systemd handler is notified</li>
<li>Flush handlers is run so that systemd picks up the new/changed unit</li>
<li>The container is enabled/started</li>
</ol>
<p>So far this is idempotent and works pretty well.  I might upload the playbooks
to a public git forge in the future for some clarity.  For the moment, feel
free to reach out on the fediverse or via email if this is confusing.</p>
<p>As I stated earlier in the post, I don&rsquo;t recommend this approach.  In the next
post in this series, I&rsquo;ll cover how I replaced all of this with quadlets when I
began deploying these sorts of services in my clients&rsquo; networks.</p>
<p>Some references for this post and the next:</p>
<ul>
<li><a href="https://wiki.archlinux.org/title/Podman">Podman - ArchWiki</a></li>
<li><a href="https://mo8it.com/blog/quadlet/">Quadlet: Running Podman containers under systemd</a></li>
<li><a href="https://docs.podman.io/en/latest/">Podman Documentation</a></li>
<li><a href="https://www.redhat.com/en/blog/quadlet-podman">Make systemd better for Podman with Quadlet</a></li>
<li><a href="https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html">podman-systemd.unit</a></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
