<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: whiteSama001</title>
    <description>The latest articles on DEV Community by whiteSama001 (@whitesama001).</description>
    <link>https://dev.to/whitesama001</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4112151%2F5e900db0-4ddd-42a8-bea9-7f499d6860b0.jpg</url>
      <title>DEV Community: whiteSama001</title>
      <link>https://dev.to/whitesama001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/whitesama001"/>
    <language>en</language>
    <item>
      <title>Common Problems Running HashiCorp Vault on Kubernetes (and How to Actually Fix Them)</title>
      <dc:creator>whiteSama001</dc:creator>
      <pubDate>Sun, 06 Sep 2026 11:11:06 +0000</pubDate>
      <link>https://dev.to/whitesama001/common-problems-running-hashicorp-vault-on-kubernetes-and-how-to-actually-fix-them-42bm</link>
      <guid>https://dev.to/whitesama001/common-problems-running-hashicorp-vault-on-kubernetes-and-how-to-actually-fix-them-42bm</guid>
      <description>&lt;p&gt;Vault and Kubernetes are both excellent at hiding the actual cause of a&lt;br&gt;
failure behind a generic-looking error. Put them together — Vault&lt;br&gt;
injecting secrets into pods via a sidecar, authenticating pods via&lt;br&gt;
Kubernetes service account tokens — and you get failure modes that look&lt;br&gt;
identical from the outside ("pod stuck in Init," "502 from the app,"&lt;br&gt;
"permission denied") but come from very different root causes. Below are&lt;br&gt;
the problems that come up most often, roughly in the order I'd check&lt;br&gt;
them.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. The Agent Injector silently doesn't inject
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: you've annotated the pod spec with&lt;br&gt;
&lt;code&gt;vault.hashicorp.com/agent-inject: "true"&lt;/code&gt;, but the pod comes up with no&lt;br&gt;
&lt;code&gt;vault-agent-init&lt;/code&gt; or &lt;code&gt;vault-agent&lt;/code&gt; container at all — no error, it just&lt;br&gt;
doesn't happen.&lt;/p&gt;

&lt;p&gt;This is almost always one of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The mutating webhook isn't reaching the pod's namespace.&lt;/strong&gt; Check
whether the namespace has a label that a &lt;code&gt;namespaceSelector&lt;/code&gt; on the
webhook is excluding (common when someone added
&lt;code&gt;kube-system&lt;/code&gt;-style exclusions broadly and it caught more than
intended):
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  kubectl get mutatingwebhookconfiguration vault-agent-injector-cfg &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
  kubectl get namespace &amp;lt;ns&amp;gt; &lt;span class="nt"&gt;--show-labels&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The injector pod itself isn't healthy.&lt;/strong&gt; &lt;code&gt;kubectl -n vault logs
deploy/vault-agent-injector-injector&lt;/code&gt; will usually show TLS cert
errors here if the injector's self-signed cert (used for the webhook
callback) has expired or the CA bundle in the webhook config is stale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The annotation is on the wrong object.&lt;/strong&gt; &lt;code&gt;vault.hashicorp.com/*&lt;/code&gt;
annotations must be on the &lt;strong&gt;pod template&lt;/strong&gt; (&lt;code&gt;spec.template.metadata&lt;/code&gt;
in a Deployment), not on the Deployment's own metadata. This is the
single most common cause of "I annotated it and nothing happened."&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  2. Vault Agent sidecar is running, but the secret file never appears
&lt;/h2&gt;

&lt;p&gt;If the sidecar container is present and running but the app container&lt;br&gt;
never sees &lt;code&gt;/vault/secrets/&amp;lt;name&amp;gt;&lt;/code&gt;, check the sidecar's own logs first&lt;br&gt;
— not the app's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &amp;lt;pod&amp;gt; &lt;span class="nt"&gt;-c&lt;/span&gt; vault-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typical causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template rendering failure&lt;/strong&gt; — a typo in the &lt;code&gt;agent-inject-template&lt;/code&gt;
annotation (wrong path, wrong Go template syntax) fails silently from
the app's perspective but errors clearly in the agent's own log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy doesn't grant &lt;code&gt;read&lt;/code&gt; on the secret path&lt;/strong&gt; — Vault Agent
authenticates fine but gets a 403 on the actual secret read. This
looks like "nothing happens" unless you specifically check the agent
log for the permission denied response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrong secret engine version assumed in the template&lt;/strong&gt; — KV v2 paths
need a &lt;code&gt;data/&lt;/code&gt; segment (&lt;code&gt;secret/data/myapp/config&lt;/code&gt;) that KV v1 doesn't.
Copying a template from a v1 setup into a v2-backed Vault is a classic
silent-failure source.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Kubernetes auth method: intermittent "permission denied" after it worked fine for weeks
&lt;/h2&gt;

&lt;p&gt;This one is almost always the &lt;strong&gt;Kubernetes 1.21+ bound service account&lt;br&gt;
token change&lt;/strong&gt;. Since Kubernetes moved to time-bound, audience-scoped&lt;br&gt;
service account tokens (as opposed to the old long-lived tokens&lt;br&gt;
auto-mounted from a Secret), Vault's Kubernetes auth backend needs to be&lt;br&gt;
configured to either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;iss&lt;/code&gt; validation compatible with your cluster's actual token
issuer (&lt;code&gt;kubectl get --raw /.well-known/openid-configuration&lt;/code&gt; to
confirm what the cluster is actually issuing), or&lt;/li&gt;
&lt;li&gt;Use a bound, non-expiring token explicitly created for Vault's own
reviewer service account, configured via
&lt;code&gt;kubernetes_ca_cert&lt;/code&gt; / &lt;code&gt;token_reviewer_jwt&lt;/code&gt; in the auth config.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this was configured correctly at setup time but breaks &lt;em&gt;later&lt;/em&gt; — often&lt;br&gt;
weeks in — it's frequently because the reviewer JWT itself was a&lt;br&gt;
short-lived token that expired, not a config drift issue. Check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault &lt;span class="nb"&gt;read &lt;/span&gt;auth/kubernetes/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and confirm the &lt;code&gt;token_reviewer_jwt&lt;/code&gt; isn't sitting on a token that has&lt;br&gt;
since expired.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Vault pods CrashLoopBackOff after a node restart or cluster upgrade
&lt;/h2&gt;

&lt;p&gt;If you're running Vault &lt;strong&gt;in-cluster&lt;/strong&gt; (not as a managed/external&lt;br&gt;
service) with Raft integrated storage, this is usually Vault coming back&lt;br&gt;
up &lt;strong&gt;sealed&lt;/strong&gt;, and whatever auto-unseal mechanism you configured not&lt;br&gt;
being reachable yet at boot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloud KMS auto-unseal&lt;/strong&gt; (AWS KMS / Azure Key Vault / GCP KMS): check
that the pod's identity (IRSA, workload identity, or managed identity)
has permission to the key &lt;em&gt;and&lt;/em&gt; that there's no chicken-and-egg
problem where the identity provider itself isn't ready yet during a
full cluster bootstrap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual unseal&lt;/strong&gt;: if you're still using unseal keys held by
operators, a restart means someone has to run &lt;code&gt;vault operator unseal&lt;/code&gt;
three times per pod. This doesn't scale past a handful of pods and is
usually the point at which teams move to cloud auto-unseal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Distinguish "sealed" from "actually crashing" before debugging further:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; vault-0 &lt;span class="nt"&gt;--&lt;/span&gt; vault status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A sealed-but-otherwise-fine Vault reports its seal status cleanly; a&lt;br&gt;
genuinely crashing pod won't even get that far, and the real error is in&lt;br&gt;
&lt;code&gt;kubectl logs&lt;/code&gt; — often a Raft storage corruption or disk permission&lt;br&gt;
issue after a node replacement changed the underlying PV's ownership.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Leases expiring under load, and apps not handling renewal
&lt;/h2&gt;

&lt;p&gt;Vault Agent handles token and lease renewal for you — &lt;em&gt;if&lt;/em&gt; the&lt;br&gt;
application actually re-reads the rendered secret file instead of&lt;br&gt;
caching the value in memory at startup. This is an application-level bug&lt;br&gt;
that shows up as a Vault problem: the secret rotates correctly, the file&lt;br&gt;
on disk updates correctly, and the app keeps using the old database&lt;br&gt;
password anyway because it read it into memory once at boot and never&lt;br&gt;
looked at the file again.&lt;/p&gt;

&lt;p&gt;The fix isn't in Vault — it's making sure the app either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watches the secret file for changes (inotify or a polling read), or&lt;/li&gt;
&lt;li&gt;Is restarted/rolled by a process that reacts to
&lt;code&gt;vault.hashicorp.com/agent-inject-command&lt;/code&gt; firing on template change
(a common pattern is having the sidecar send &lt;code&gt;SIGHUP&lt;/code&gt; to the app
process, or having the injector template out a checksum the app polls).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Worth checking explicitly during any "why did prod start throwing auth&lt;br&gt;
errors overnight" investigation, since it doesn't show up in Vault's own&lt;br&gt;
audit log as an error at all — from Vault's side, everything renewed&lt;br&gt;
successfully.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. NetworkPolicy quietly blocking Vault API calls
&lt;/h2&gt;

&lt;p&gt;If Vault Agent can't reach the Vault API at all, the error is usually&lt;br&gt;
obvious (connection refused/timeout in the agent log). But partially&lt;br&gt;
restrictive &lt;code&gt;NetworkPolicy&lt;/code&gt; resources cause a subtler failure: init&lt;br&gt;
succeeds (maybe egress to Vault's ClusterIP is allowed) but subsequent&lt;br&gt;
renewal calls fail if a policy is scoped too narrowly to only allow&lt;br&gt;
traffic during pod startup timing, or scoped to the wrong port when&lt;br&gt;
Vault is listening on a non-default port behind a Kubernetes Service.&lt;br&gt;
Confirm the actual policy match, not just its presence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get networkpolicy &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;ns&amp;gt; &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &amp;lt;pod&amp;gt; &lt;span class="nt"&gt;-c&lt;/span&gt; vault-agent &lt;span class="nt"&gt;--&lt;/span&gt; wget &lt;span class="nt"&gt;-qO-&lt;/span&gt; https://vault.vault.svc:8200/v1/sys/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Injector webhook timeout under cluster load
&lt;/h2&gt;

&lt;p&gt;The mutating webhook has a &lt;code&gt;timeoutSeconds&lt;/code&gt; (default 30s in most Helm&lt;br&gt;
chart versions, but drops to lower defaults in some setups) — under&lt;br&gt;
cluster-wide load or if the injector pod itself is under-resourced, pod&lt;br&gt;
creation can start failing cluster-wide with &lt;code&gt;admission webhook denied&lt;br&gt;
the request&lt;/code&gt; errors that have nothing to do with the actual pod spec.&lt;br&gt;
This tends to surface during mass rollouts or node scale-up events,&lt;br&gt;
which makes it easy to misdiagnose as a scheduling problem rather than a&lt;br&gt;
webhook capacity problem. Give the injector pod real resource&lt;br&gt;
requests/limits and consider running more than one replica behind its&lt;br&gt;
Service — it's a single point of failure for &lt;em&gt;all&lt;/em&gt; pod creation in&lt;br&gt;
namespaces it covers, not just Vault-using ones, since the webhook fires&lt;br&gt;
on every pod create by default unless scoped with a&lt;br&gt;
&lt;code&gt;namespaceSelector&lt;/code&gt;/&lt;code&gt;objectSelector&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern underneath all of this
&lt;/h2&gt;

&lt;p&gt;Almost every one of these failures looks, from the app team's side,&lt;br&gt;
like "the app can't reach the database" or "the pod won't start." The&lt;br&gt;
actual cause is almost never in the application code — it's in the&lt;br&gt;
handshake between three systems (Kubernetes' identity model, Vault's&lt;br&gt;
auth/policy model, and the injector's webhook mechanics) that only&lt;br&gt;
becomes visible if you check each layer's &lt;em&gt;own&lt;/em&gt; logs independently&lt;br&gt;
instead of inferring backward from the app's symptom. The fastest path&lt;br&gt;
through any of these, in practice, is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;kubectl describe pod&lt;/code&gt; — did the webhook even fire, did the sidecar
get injected.&lt;/li&gt;
&lt;li&gt;Vault Agent's own log — did auth succeed, did the template render.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vault status&lt;/code&gt; / &lt;code&gt;vault read auth/kubernetes/config&lt;/code&gt; — is Vault
itself healthy and is the auth backend actually configured the way
you think it is.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Only after ruling those out is it worth looking at the application&lt;br&gt;
itself — and even then, per #5 above, the bug is often "the app isn't&lt;br&gt;
watching the file," not anything Vault did wrong.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Curious which of these has bitten you — the token-issuer change from&lt;br&gt;
Kubernetes 1.21+ is the one I've seen catch out the most teams who&lt;br&gt;
configured Vault correctly once and never revisited it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hashicorp</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Debugging Redis Remote Access on RHEL: A Four-Layer Problem That Looked Like One</title>
      <dc:creator>whiteSama001</dc:creator>
      <pubDate>Sun, 06 Sep 2026 10:34:00 +0000</pubDate>
      <link>https://dev.to/whitesama001/debugging-redis-remote-access-on-rhel-a-four-layer-problem-that-looked-like-one-18ab</link>
      <guid>https://dev.to/whitesama001/debugging-redis-remote-access-on-rhel-a-four-layer-problem-that-looked-like-one-18ab</guid>
      <description>&lt;p&gt;When a request comes in as "the app can't connect to Redis," it's tempting to assume it's a one-line fix — open a port, flip a config flag, done. In practice, on a hardened RHEL/CentOS host, a single "connection refused" error can be hiding four separate problems stacked on top of each other: network-level firewall rules, SELinux policy, file-level permissions, and Redis's own safety defaults. Each layer will silently swallow the connection and give you almost no useful signal about which one is actually blocking you.&lt;/p&gt;

&lt;p&gt;This is a walkthrough of how I diagnosed and fixed exactly that scenario — a Redis instance that needed to accept connections from an application server on the same internal subnet, but wouldn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The symptom
&lt;/h2&gt;

&lt;p&gt;A service running on a separate host in the same internal network needed to read/write to a Redis instance. The &lt;code&gt;redis-cli -h &amp;lt;redis-host&amp;gt; ping&lt;/code&gt; command from the app server just hung, then timed out. No obvious error in the Redis logs. &lt;code&gt;systemctl status redis&lt;/code&gt; showed it running happily on the Redis host itself, and &lt;code&gt;redis-cli ping&lt;/code&gt; worked fine &lt;em&gt;locally&lt;/em&gt; on that box.&lt;/p&gt;

&lt;p&gt;That local-works, remote-fails split is the first useful clue: it rules out a broken Redis process and points squarely at something in the path between the two hosts, or in how Redis is bound.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1: Is Redis even listening on the right interface?
&lt;/h2&gt;

&lt;p&gt;The default Redis config binds to &lt;code&gt;127.0.0.1&lt;/code&gt; only — deliberately, since Redis has no authentication by default and was never meant to be exposed carelessly. First check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only see &lt;code&gt;127.0.0.1:6379&lt;/code&gt;, that's your answer for this layer. The fix is in &lt;code&gt;redis.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt; -::&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="c"&gt;# or, more safely, bind to the specific internal interface:
&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="n"&gt;x&lt;/span&gt;.&lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the service and re-check with &lt;code&gt;ss&lt;/code&gt;. If the socket now shows the right interface, move to the network layer — this alone rarely fixes remote access on a hardened host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2: The firewall
&lt;/h2&gt;

&lt;p&gt;RHEL-family systems default to &lt;code&gt;firewalld&lt;/code&gt;. Even if the app team swears "the network team already opened the port," verify it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--list-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;6379/tcp&lt;/code&gt; isn't in the &lt;code&gt;services&lt;/code&gt; or &lt;code&gt;ports&lt;/code&gt; list for the active zone, add it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;internal &lt;span class="nt"&gt;--add-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6379/tcp &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget any cloud-level security group or NSG sitting in front of the host — firewalld being correct doesn't mean the packet ever arrives if a cloud ACL drops it first. Test from the app server with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-zv&lt;/span&gt; &amp;lt;redis-host&amp;gt; 6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that now succeeds but &lt;code&gt;redis-cli ping&lt;/code&gt; still hangs or gets refused, the packet is arriving — the block is happening &lt;em&gt;inside&lt;/em&gt; the host, which is where most people stop looking too early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3: SELinux — the layer everyone forgets
&lt;/h2&gt;

&lt;p&gt;This is the one that trips people up because it fails silently and looks identical to a network problem from the outside. SELinux enforces policy independently of standard file/network permissions, and a denial doesn't show up in the application's own logs — it shows up in the audit log.&lt;/p&gt;

&lt;p&gt;Check for denials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ausearch &lt;span class="nt"&gt;-m&lt;/span&gt; avc &lt;span class="nt"&gt;-ts&lt;/span&gt; recent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, more readably:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sealert &lt;span class="nt"&gt;-a&lt;/span&gt; /var/log/audit/audit.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two common findings in this scenario:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Port context&lt;/strong&gt;: if you changed Redis to listen on a non-default port, SELinux won't know that port is allowed for the &lt;code&gt;redis_port_t&lt;/code&gt; type until you tell it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;semanage port &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; redis_port_t &lt;span class="nt"&gt;-p&lt;/span&gt; tcp &amp;lt;new_port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;File context on data/config paths&lt;/strong&gt;: if the Redis data directory or config file was moved, copied, or restored from a backup in a way that didn't preserve SELinux labels, the daemon can be denied access to its own files:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;restorecon &lt;span class="nt"&gt;-Rv&lt;/span&gt; /var/lib/redis /etc/redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never disable SELinux to make this go away — &lt;code&gt;setenforce 0&lt;/code&gt; "fixes" the symptom by removing a security boundary you presumably want on a production host. Diagnose the specific denial and allow exactly that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 4: File ownership
&lt;/h2&gt;

&lt;p&gt;Related but distinct from SELinux context: standard Unix ownership. If the Redis data directory, RDB/AOF files, or config file aren't owned by the &lt;code&gt;redis&lt;/code&gt; user (often because of a manual &lt;code&gt;cp&lt;/code&gt; or a restore run as root), the daemon can fail to start cleanly or fail to persist — which then surfaces upstream as flaky connectivity when the process restarts unexpectedly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; redis:redis /var/lib/redis
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;750 /var/lib/redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Layer 5: Redis's own protected mode
&lt;/h2&gt;

&lt;p&gt;Even once the network, SELinux, and ownership are all correct, Redis has one more guard rail: &lt;strong&gt;protected mode&lt;/strong&gt;. If Redis is bound to a non-loopback address &lt;em&gt;without&lt;/em&gt; a password configured, it refuses external connections by default and logs a warning about it. This is Redis protecting you from accidentally exposing an unauthenticated instance to the world.&lt;/p&gt;

&lt;p&gt;The correct fix is not to disable protected mode — it's to set a password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;requirepass&lt;/span&gt; &amp;lt;&lt;span class="n"&gt;strong&lt;/span&gt;-&lt;span class="n"&gt;password&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then connect as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli &lt;span class="nt"&gt;-h&lt;/span&gt; &amp;lt;redis-host&amp;gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;strong-password&amp;gt; ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If for some internal-only, tightly firewalled reason you genuinely don't want auth, you can explicitly set &lt;code&gt;protected-mode no&lt;/code&gt; — but treat that as a deliberate, documented exception, not a quick fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond Redis
&lt;/h2&gt;

&lt;p&gt;The specific commands here are Redis-and-RHEL-flavored, but the debugging &lt;em&gt;shape&lt;/em&gt; generalizes to almost any "service X can't talk to service Y" ticket on a hardened Linux estate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Confirm the process is actually listening where you think it is (&lt;code&gt;ss&lt;/code&gt;/&lt;code&gt;netstat&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Confirm the packet can physically arrive (firewall, security groups, routing).&lt;/li&gt;
&lt;li&gt;Confirm the kernel-level mandatory access control isn't silently dropping it (SELinux/AppArmor — check the audit log, don't guess).&lt;/li&gt;
&lt;li&gt;Confirm file/process ownership is correct.&lt;/li&gt;
&lt;li&gt;Only then look at the application's own safety defaults.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Skipping straight to "just open the port" or "just disable SELinux" will often &lt;em&gt;look&lt;/em&gt; like it worked in a rushed fix, while actually just removing a control someone put there on purpose. Working through the layers in order — and confirming each one with a command, not an assumption — gets you to a fix you can actually explain and defend later, which matters a lot more in a regulated environment (this happened on banking infrastructure) than in a hobby project.&lt;/p&gt;

&lt;h2&gt;
  
  
  A couple of open questions I'd flag to anyone in a similar spot
&lt;/h2&gt;

&lt;p&gt;Two things I left as follow-ups rather than closing out immediately, because they're policy decisions, not bugs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dir&lt;/code&gt; setting&lt;/strong&gt;: where RDB/AOF snapshots actually land matters for backup and disk-capacity planning — worth confirming it points somewhere with monitored, appropriately-sized storage rather than leaving the default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eviction policy&lt;/strong&gt;: &lt;code&gt;maxmemory-policy&lt;/code&gt; needs to match how the application actually uses Redis (cache vs. durable store). Getting this wrong either silently drops data you needed or lets Redis OOM under load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is a "fix" — they're the kind of thing worth a short design conversation with whoever owns the data before you consider the job fully done.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you've hit a similar multi-layer wall with Redis, Postgres, or any other service on a hardened RHEL box, I'd be curious to hear which layer got you — SELinux is my usual bet.&lt;/em&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>redis</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
