DEV Community

crow
crow

Posted on

How a Crypto-Miner Infiltrated My Umami Analytics (and How I Defeated It)

Building in public means sharing the wins, but it also means being honest about the technical challenges. Recently, my project Musical Chairs faced a common but dangerous threat: an automated exploit targeted my self-hosted Umami analytics instance to install a Monero miner.

Here is exactly what happened, how my architecture saved the host, and a guide to hardening your Docker setup.

The Red Flag: Decoding the "Digest"

It started when I checked my Docker logs. Instead of standard traffic, I saw Base64-encoded strings in the error reports. After decoding the digest field, I found the output of a top command showing a process named next-server attempting to reserve 10.4 GB of virtual memory.

The Verdict: My Umami container was compromised. An automated bot had gained access and was attempting to run a crypto-miner (xmrig variant) disguised as a Next.js process.

Why the Hacker Failed (The Power of Isolation)

Despite the container being compromised, the attacker never reached the host machine. Two layers of my architecture worked exactly as intended:

  1. Networking: I used the expose directive instead of ports. Umami was only accessible via my Nginx Reverse Proxy internal network.
  2. Resource Limits: In my docker-compose.yml, I had strictly limited the container's memory to 1GB. When the miner tried to reserve 10GB of RAM, Docker’s resource management "choked" the process, preventing the host from freezing or crashing.

The Recovery: Major Upgrade & Hardening

If you are self-hosting Umami, simply restarting is not enough. You need to purge the old environment and upgrade to the latest major release.

1. Identify and Purge

I killed the compromised instance and wiped the potentially "poisoned" image layers.

docker compose stop umami
docker compose rm -f umami
# Removing the old v2 image to prevent accidental reuse
docker rmi ghcr.io/umami-software/umami:postgresql-latest
Enter fullscreen mode Exit fullscreen mode

2. Upgrading to Umami v3 (Major Release)

I updated my docker-compose.yml to pull the latest major version and added strict resource quotas. Switching from postgresql-latest (v2) to latest (v3.0.3+) ensured I was on the most secure, up-to-date version.

umami:
    image: ghcr.io/umami-software/umami:latest # Upgraded to major v3
    expose:
      - "3000"
    deploy:
      resources:
        limits:
          memory: 1G # This killed the miner's memory hunger
    environment:
      DATABASE_URL: ${DATABASE_URL}
      HASH_SALT: ${UMAMI_HASH_SALT}
      APP_SECRET: ${UMAMI_HASH_SALT} # New requirement for Umami v3 / Next.js 15
    networks:
      - app_network
Enter fullscreen mode Exit fullscreen mode

3. Updating Secrets

The attacker likely exploited a weak or default HASH_SALT. With the move to v3, I generated a new 32-character string for both HASH_SALT and APP_SECRET:


# Generating a new high-entropy secret
openssl rand -base64 32
Enter fullscreen mode Exit fullscreen mode

4. Administrative Lockdown

After pulling the fresh image and restarting:

I immediately logged into the dashboard.

Changed the default admin/umami credentials to a unique, high-entropy password.

Verified that the database migrations were successful — all historical data was preserved!

Lessons Learned for Founders

  1. Resource Limits are Mandatory: Always set deploy.resources.limits.memory in Docker. It prevents a single compromised container from crashing your entire VPS.

  2. Major Upgrades Matter: Don't get stuck on old major versions (like Umami v2). Newer versions often have better security defaults and more robust underlying frameworks like Next.js 15.

  3. Expose vs Ports: Never map a port to 0.0.0.0 unless it's your entry point (like Nginx).

  4. Audit Your Logs: If you see Base64 strings where they don't belong, decode them immediately. They are usually a "calling card" of an exploit.

By sharing this, I hope to help other Web3 founders stay secure while they build. Musical Chairs is now faster, more secure, and ready for our upcoming investment rounds.

Stay safe and keep building! 🚀

Top comments (0)