Portfolio Blog Code Repository Contact

Architecture Log: Hardening Self-Hosted CI/CD Pipelines

 Tags: DevSecOps, Infrastructure, Docker, Nginx, GitLab

Self-hosting a CI/CD pipeline (like GitLab) is a great way to maintain control over your code, but it makes your infrastructure a prime target for automated scanners and credential stuffing. I recently audited my own edge architecture and implemented a few strict defensive layers I want to document here.

If you are exposing a Git instance or Docker registry to the open internet, a standard Nginx reverse proxy isn't enough. You need aggressive, application-layer filtering.

Defensive Strategy 1: Edge Rate Limiting Most people rate-limit globally, which punishes legitimate users. I prefer targeting specific, high-value authentication endpoints. By applying a strict limit_req_zone in Nginx strictly to the /users/sign_in paths, I neutralized automated brute-forcing without impacting general repository cloning.

Defensive Strategy 2: Rootless Containers & Read-Only State At the system level, privilege escalation is the worst-case scenario.

  1. Rootless Docker: The daemon should never run as root. If a runner executes malicious CI code that escapes the container, the attacker lands in an unprivileged user space.

  2. Immutability: I've started mounting my container configuration volumes as ro (read-only). If an attacker finds a vulnerability in the web interface, they cannot overwrite the core gitlab.rb configurations to gain persistence.

The Result: A defense-in-depth model where the edge drops scanners immediately, and the host OS is shielded from container-level compromises.

References:

Amine Boutouil

Security Architect · Technical Polymath

boutouil.me →