Nginx — Reverse Proxy

Nginx runs directly on the host (not in a container) and serves as the single entry point for all CI/CD services. It terminates TLS, enforces client certificate authentication, and proxies requests to the appropriate container based on subdomain.

Subdomain Routing

Each service gets its own subdomain, all under cicd.pathoris.de:

Subdomain Backend Notes
git.cicd.pathoris.de http://172.20.0.10:3000 Forgejo web UI and API
ldap.cicd.pathoris.de http://172.20.0.13:8080 phpLDAPadmin (Caddy on port 8080)
jenkins.cicd.pathoris.de http://172.20.0.14:8080 Jenkins web UI
cicd.pathoris.de static files in /var/www/cicd Landing page

All HTTP requests (port 80) are redirected to HTTPS (port 443) via Certbot-managed redirect blocks.

TLS

Certificates are obtained via Let's Encrypt / Certbot. The config references the cert paths managed by Certbot:

ssl_certificate /etc/letsencrypt/live/nextcloud.pathoris.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nextcloud.pathoris.de/privkey.pem;

Client Certificate Authentication

Every HTTPS server block enforces client certificate verification:

ssl_client_certificate /etc/nginx/client-certs/ca.crt;
ssl_verify_client on;

Only clients presenting a certificate signed by the project's CA can access any service. Certificates are created with setup-ca.sh (CA) and create-client-cert.sh (per-user .p12 files).

This provides an additional authentication layer on top of LDAP — even if someone has LDAP credentials, they can't reach the services without a valid client certificate.

Proxy Headers

Each location / block passes standard proxy headers to the backend:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

phpLDAPadmin-specific headers

The phpLDAPadmin block requires special treatment because it's a Laravel app behind a reverse proxy:

Other server blocks use Referrer-Policy no-referrer and X-Forwarded-Proto $scheme.

Security Headers

All server blocks include:

add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;

SSH Passthrough

Forgejo's SSH access (for git clone over SSH) bypasses nginx entirely. Port 2222 is exposed directly from the Forgejo container to the host via docker-compose:

ports:
  - '2222:2222'

Users clone with: git clone ssh://git@git.cicd.pathoris.de:2222/user/repo.git

Configuration File

The full nginx config is at pathoris/etc/nginx/conf.d/cicd-pathoris.conf. It contains: - 4 HTTP→HTTPS redirect blocks (one per subdomain) - 4 HTTPS server blocks with TLS, client certs, and proxy configuration - The cicd.pathoris.de block serves static files instead of proxying

Deploy to the server with:

scp etc/nginx/conf.d/cicd-pathoris.conf root@pathoris.de:/etc/nginx/conf.d/
systemctl reload nginx