A self-hosted CI/CD setup for hobby projects, running on a virtual root server at pathoris.de.
All services run as containers via podman compose on pathoris.de. Nginx acts as reverse proxy, terminating TLS and enforcing client certificate authentication.
Internet
│
▼
nginx (TLS + client certs)
├── git.cicd.pathoris.de → Forgejo (port 3000)
├── ldap.cicd.pathoris.de → phpLDAPadmin (port 8080)
├── jenkins.cicd.pathoris.de → Jenkins (port 8080)
└── cicd.pathoris.de → static landing page
All services defined in a single docker-compose.yaml, managed with podman compose. Custom Dockerfiles per service, shared variables via env.txt, jinja2 templating for configuration.
TLS termination with Let's Encrypt certificates. Client certificate authentication restricts access to authorized users. Each service gets its own subdomain. - Debug Guide - Issues and Mitigations
OpenLDAP (slapd) provides centralized authentication for all services. Runs embedded inside the phpLDAPadmin container. Users, groups, and service accounts are bootstrapped automatically on first start. The memberOf overlay maintains group membership attributes. - Debug Guide - Issues and Mitigations
Web interface for managing LDAP users and groups. Includes a custom user creation template tailored for CI/CD accounts. Runs on the same container as slapd. - Debug Guide - Issues and Mitigations
Lightweight, self-hosted Git forge (Gitea fork). Authenticates against LDAP. Uses PostgreSQL as its database backend. The container automatically creates its database on first start.
Automation server for builds and tests. LDAP authentication is configured automatically on first boot via a Groovy init script. Plugins (ldap, matrix-auth, git, workflow) are installed at image build time.
Stores Forgejo's data. Uses the official postgres:16-alpine image without customization. Database and user creation is handled by Forgejo's entrypoint.
pathoris/
├── deploy.sh # Deploy configs to server
├── setup-ca.sh # Create client certificate CA
├── create-client-cert.sh # Issue client certificates
├── client-cert.cnf # Certificate extensions
├── etc/nginx/
│ ├── nginx.conf # Main nginx config
│ └── conf.d/cicd-pathoris.conf # Virtual host definitions
└── opt/docker-compose/cicd/
├── docker-compose.yaml # All services
├── env.txt # Shared environment variables
├── restart.sh # Helper functions for restart/reset
├── phpldapadmin/ # Custom image: slapd + phpLDAPadmin
├── forgejo/ # Custom image: rootless + DB init
├── jenkins/ # Custom image: plugins + LDAP config
└── postgres/ # No custom image, just README
setup-ca.sh) and issue your first cert (create-client-cert.sh)cicd-pathoris.confenv.txt (all LDAP and service credentials are centralized there)podman compose up -d to start all services