Taming the Ports: Debugging Infinite Redirect Loops and Paranoiac Wazuh Deployments

It’s going on 10:23 PM, and it looks like I'm making good time kicking these entries out.

Act I:Part 1 of the sovereign ThreatLabs CTI stack continues, but today we're talking about what happens right after you build the network roads and the actual containers start throwing absolute tantrums. You think containerization solves your deployment hurdles, right? Wrong. The second you drop enterprise security platforms behind a prosumer Traefik ingress, reality hits you fast in the form of infinite browser spins and kernel panics.

Time to pull back the curtain on why raw systems administration tissue always trumps basic theoretical architecture.

Pitfall 3: The Infinite Redirect Loop of MISP

So, the cti-net shared network was live, Docker was happy, and I fired up the MISP stack. Navigated to the interface page. Typed in the baseline credentials. Hit enter.

Browser immediately went into a loopy existential crisis before spitting back ERR_TOO_MANY_REDIRECTS.

Spent three hours furiously ripping apart my Traefik frontend configurations, tracking headers, and cursing under my breath. Here is the trap: Traefik was listening on external port 8443, handling the SSL termination, and passing clean traffic down to the internal proxy on port 80. But MISP's internal code is hyper-paranoid; it saw an incoming secure request but its internal Nginx webserver assumed it was supposed to be living on standard port 443. They couldn't agree on basic port reality, so they just kept bouncing the request back and forth forever.

The fix wasn't an ingress re-write—it was forcing MISP to look at the world through our lens. You have to explicitly inject the CORE_HTTPS_PORT environment variable straight into the container environment so the internal app engine stops guessing.

# Snippet from the isolated MISP stack configuration
services:
  misp:
    image: misp-os:latest
    networks:
      - cti-net
    environment:
      - Variable_Port_Mappings=True
      # Tell MISP's internal engine exactly how the public sees it:
      - CORE_HTTPS_PORT=8443

Save config. Re-up the stack. Voila! Browser settles down, the login registers instantly, and we are in.

Pitfall 4: The Elasticsearch Memory Hog Dilemma

With MISP behaving, it was time to spin up the logging engine—Elasticsearch—to drive the indexing for TheHive and our Wazuh SIEM components. Fired it up, watched the initial process strings, and then the entire node ground to a miserable, choking crawl.

Out of Memory (OOM) killed. Standard container deployment behavior when an enterprise app hits consumer bare-metal limits.

Everyone forgets that Elasticsearch is a ravenous data hoarder. By default, it wants to allocate massive virtual memory regions and map the entire host structure directly into its heap. If your host OS kernel isn't tuned to allow massive memory allocation handles, the container drops dead on line one. Running a CTI pipeline isn't just about lazy containerized isolation—it's deep host-level systems engineering.

Had to jump directly onto the host terminal and forcefully alter the Linux kernel configurations on the fly to support the database indexing load.

# Temporarily patch the host kernel boundaries
sudo sysctl -w vm.max_map_count=262144

# Lock it down permanently so a power failure won't brick the stack
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf

The Ingress Media Hook

Tinker Note: Always set your internal ES cluster heap size explicit constraints (ES_JAVA_OPTS="-Xms2g -Xmx2g") inside the Compose environment definitions, or it will attempt to swallow every byte of RAM available in your rack space.

Pitfall 5: The Wazuh Certificate Exception Tantrum

Then came the grand finale: adding Wazuh for centralized SIEM logging capabilities. Wazuh is rightfully paranoid; it flatly refuses to pass threat data over its internal APIs without mutual TLS (mTLS) verification.

Ran their automated certificate generation tool. Total failure.

The automated script generated default credentials bound strictly to localhost. But inside our internal cti-net fabric, the containers talk to each other using explicit hostnames like wazuh.indexer. The Java engine inside the platform took one look at the hostname mismatch and threw a massive CertificateException tantrum.

Never rely on magical black-box installation scripts when things fail. We yanked the automated tools, threw together a custom OpenSSL bash script—generate-certs.sh—and hand-crafted our own Subject Alternative Names (SANs) directly into the cryptographic extensions. Controlling the root CA yourself turns a broken deployment into an absolute security fortress.

#!/bin/bash
# generate-certs.sh: Hand-crafting TLP-compliant mTLS certificates with strict SAN definitions
echo "Generating authenticated certificates for wazuh.indexer..."

# Create custom openssl configuration inline
cat <<EOF > san.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = wazuh.indexer
DNS.2 = localhost
EOF

# Generate private key and sign the certificate with host SAN extensions
openssl req -new -newkey rsa:4096 -nodes -keyout wazuh-indexer.key \
  -out wazuh-indexer.csr -subj "/CN=wazuh.indexer" -config san.cnf

openssl x509 -req -in wazuh-indexer.csr -CA root-ca.crt -CAkey root-ca.key \
  -CAcreateserial -out wazuh-indexer.crt -days 365 -extensions v3_req -extfile san.cnf

echo "Cryptography verified. Host alignment locked down."

Injected the signed certificate files into the production volumes, restarted the deployment sequence, and the indexers initialized flawlessly on the first pass. And profit!

The infrastructure ports are officially tamed, the indexers are stable, and the internal cryptography isn't lying to itself anymore. Act I is officially wrapped up and behind us. Next month, we're moving into Act II: Zero-Trust and Secrets, mapping out how we re-routed coordination through self-hosted Headscale VPN infrastructure on LXC 137 and killed off brittle plaintext .env configurations via runtime Infisical dynamic machine identities.

Until then, see ya later. Happy tinkering!