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.
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.
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;
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.
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;
The phpLDAPadmin block requires special treatment because it's a Laravel app behind a reverse proxy:
X-Forwarded-Proto https (hardcoded, not $scheme) — ensures Laravel generates HTTPS URLsContent-Security-Policy 'upgrade-insecure-requests' — tells browsers to upgrade any remaining HTTP resource loadsReferrer-Policy same-origin (not no-referrer) — Laravel's CSRF protection needs the Referer header on AJAX requestsOther server blocks use Referrer-Policy no-referrer and X-Forwarded-Proto $scheme.
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;
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
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