Add the building blocks the provisioning CLI renders per site. Base images (site-templates/images): - php-fpm: non-root (www-data) php:<ver>-fpm-alpine with pdo_mysql, mysqli, gd, intl, zip, opcache, exif; tuned php.ini + pool; built per PHP version. - nginx: hardened nginx:1.27-alpine with shared security + fastcgi snippets; per-site server block mounted at runtime. - build.sh: build + Trivy-scan (+ optional push) for both images. Profile templates (site-templates/profiles), Jinja2 rendered: - static, redirect (tiny nginx 301/302), custom-php (nginx + our php-fpm, optional DB), wordpress (nginx + official wordpress-fpm, DB required, upload-exec denied). Only nginx carries Traefik labels and joins proxy; php-fpm uses the private <slug>_net and joins platform only when a DB is needed. Secrets stay in a git-ignored .env, not the compose. CI: .forgejo/workflows/images.yml builds/scans images (gitleaks + Trivy). README documents the render context and the Phase 4 web-root ownership item. Templates validated: all profiles render to valid compose YAML across the database on/off branches and single/multi-domain host rules. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
59 lines
1.6 KiB
Django/Jinja
59 lines
1.6 KiB
Django/Jinja
# Rendered by the provisioning CLI (Phase 4) into deployments/<customer>/<site>/.
|
|
# Render context is documented in site-templates/README.md.
|
|
name: {{ slug }}
|
|
|
|
services:
|
|
nginx:
|
|
image: {{ nginx_image }}
|
|
container_name: {{ slug }}_nginx
|
|
restart: unless-stopped
|
|
depends_on: [fpm]
|
|
volumes:
|
|
- {{ webroot }}:/var/www/html:ro
|
|
- ./nginx-site.conf:/etc/nginx/conf.d/default.conf:ro
|
|
networks: [proxy, site]
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.{{ slug }}.rule=Host(`{{ domains | join('`) || Host(`') }}`)"
|
|
- "traefik.http.routers.{{ slug }}.entrypoints=websecure"
|
|
- "traefik.http.routers.{{ slug }}.tls.certresolver=le"
|
|
- "traefik.http.routers.{{ slug }}.middlewares=security-headers@file"
|
|
- "traefik.http.services.{{ slug }}.loadbalancer.server.port=80"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "{{ resources.cpu }}"
|
|
memory: {{ resources.memory }}
|
|
|
|
fpm:
|
|
image: {{ php_image }}
|
|
container_name: {{ slug }}_fpm
|
|
restart: unless-stopped
|
|
volumes:
|
|
- {{ webroot }}:/var/www/html
|
|
{% if database %}
|
|
env_file: [.env]
|
|
environment:
|
|
DB_HOST: mariadb
|
|
DB_NAME: db_{{ slug_underscored }}
|
|
DB_USER: u_{{ slug_underscored }}
|
|
# DB_PASSWORD is injected from .env
|
|
networks: [site, platform]
|
|
{% else %}
|
|
networks: [site]
|
|
{% endif %}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "{{ resources.cpu }}"
|
|
memory: {{ resources.memory }}
|
|
|
|
networks:
|
|
proxy:
|
|
external: true
|
|
{% if database %}
|
|
platform:
|
|
external: true
|
|
{% endif %}
|
|
site:
|
|
name: {{ slug }}_net
|