<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-04-18T09:14:36+00:00</updated><id>/feed.xml</id><title type="html">alec.dev</title><subtitle>Infrastructure, Linux, and things worth writing down.</subtitle><author><name>Alec</name></author><entry><title type="html">Managing SELinux contexts with rhel-system-roles</title><link href="/2026/04/12/selinux-contexts-ansible/" rel="alternate" type="text/html" title="Managing SELinux contexts with rhel-system-roles" /><published>2026-04-12T00:00:00+00:00</published><updated>2026-04-12T00:00:00+00:00</updated><id>/2026/04/12/selinux-contexts-ansible</id><content type="html" xml:base="/2026/04/12/selinux-contexts-ansible/"><![CDATA[<p>Getting SELinux file contexts right in Ansible is one of those things that looks simple until it isn’t.</p>

<h2 id="the-problem-with-command-and-semanage">The problem with <code class="language-plaintext highlighter-rouge">command</code> and <code class="language-plaintext highlighter-rouge">semanage</code></h2>

<p>Running <code class="language-plaintext highlighter-rouge">semanage fcontext</code> directly via the <code class="language-plaintext highlighter-rouge">command</code> module works, but it’s not idempotent by default. You’ll need a <code class="language-plaintext highlighter-rouge">creates:</code> guard or a <code class="language-plaintext highlighter-rouge">changed_when: false</code> override, or you’ll get a changed task on every run even if the context is already set.</p>

<h2 id="using-communitygeneralsefcontext">Using <code class="language-plaintext highlighter-rouge">community.general.sefcontext</code></h2>

<p>The cleaner path is the dedicated module:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">set custom fcontext for app directory</span>
  <span class="na">community.general.sefcontext</span><span class="pi">:</span>
    <span class="na">target</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/srv/myapp(/.*)?'</span>
    <span class="na">setype</span><span class="pi">:</span> <span class="s">httpd_sys_content_t</span>
    <span class="na">state</span><span class="pi">:</span> <span class="s">present</span>
  <span class="na">notify</span><span class="pi">:</span> <span class="s">restorecon app dir</span>
</code></pre></div></div>

<p>The module handles idempotency for you. Pair it with a handler that runs <code class="language-plaintext highlighter-rouge">restorecon</code> — the module only updates policy, not filesystem labels on existing files.</p>

<h2 id="where-to-look-things-up">Where to look things up</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ansible-doc community.general.sefcontext
man semanage-fcontext
</code></pre></div></div>]]></content><author><name>Alec</name></author><category term="Ansible" /><category term="ansible" /><category term="selinux" /><category term="rhce" /><category term="rhel" /><summary type="html"><![CDATA[Walking through sefcontext tasks, idempotency patterns, and where the documentation actually lives.]]></summary></entry></feed>