# WebHosting Shared web applications behind Nginx/Apache, deployed in `/opt/WebHosting`. - `docker-compose.yaml` combines `stacks//compose.yaml` into one Compose project. Run commands from the repository root; relative paths resolve from there. - Only Nginx publishes host ports (`80`/`443`) and joins `public` and `backend`. Web applications share `backend`; databases use their separate application networks. These are bridge networks with outbound access, without `internal: true`. - Puppet manages secrets through `hiera/data-lx/default/lx-docker-01.psi.ch.yaml`. The service env files live under `/etc/webhosting/`, separately from this repo. - Env files are root-owned (`0600`, directories `0700`) and use `format: raw`: keep values literal, without adding quotes or escaping dollar signs. Puppet must provision all required env files before Compose validation or deployment. Use `config --quiet` to avoid printing secrets. After an update, check the application; if its container IP changed, validate and reload Nginx using the host's deployment procedure. Gitea Actions runs linting and Compose syntax checks for PRs. After a merge to `main`, it pulls the repo, obtains missing certificates, runs Compose, and tests/reloads Nginx. Failed commands stop the job; there is no automatic rollback. For new sites, use `/etc/nginx/certs/.crt` and `/etc/nginx/private/.key` in the Nginx config. CI checks the host's `/etc/letsencrypt/live//` for `fullchain.pem` and `privkey.pem`, requesting a certificate if either is missing. It uses the existing host ACME config and ensures symlinks under `/etc/pki/tls/`, mounted at those Nginx paths in the container. It reloads Nginx at the end. Existing certificates keep their normal renewal schedule.