diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 53cd5f1..b888abf 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -42,6 +42,12 @@ jobs: matrix: arch: [amd64, arm64] image: &images + - path: '8.6' + tags: silarhi/php-apache:8.6 + - path: '8.6-ci' + tags: silarhi/php-apache:8.6-ci + - path: '8.6-symfony' + tags: silarhi/php-apache:8.6-symfony - path: '8.5' tags: | silarhi/php-apache:latest diff --git a/8.6-ci/Dockerfile b/8.6-ci/Dockerfile new file mode 100644 index 0000000..0a125e3 --- /dev/null +++ b/8.6-ci/Dockerfile @@ -0,0 +1,18 @@ +FROM mlocati/php-extension-installer:latest AS php-extension-installer +FROM php:8.6-rc-alpine + +ENV COMPOSER_ALLOW_SUPERUSER=1 + +WORKDIR /app + +SHELL ["/bin/ash", "-o", "pipefail", "-c"] + +# Install dependencies +RUN apk add --no-cache \ + bash \ + git \ + icu + +# PHP Extensions +COPY --from=php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN install-php-extensions @composer intl opcache zip diff --git a/8.6-symfony/Dockerfile b/8.6-symfony/Dockerfile new file mode 100644 index 0000000..f838d8d --- /dev/null +++ b/8.6-symfony/Dockerfile @@ -0,0 +1,37 @@ +FROM mlocati/php-extension-installer:latest AS php-extension-installer +FROM php:8.6-rc-apache + +ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 + +EXPOSE 80 +WORKDIR /app + +HEALTHCHECK --interval=1m --timeout=3s --start-period=5s --start-interval=1s --retries=3 \ + CMD ["/bin/sh", "-c", "curl -f http://localhost/_health || exit 1"] + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN apt-get update -qq && \ + apt-get install -qy \ + git \ + gnupg \ + unzip \ + zip && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# PHP Extensions +COPY --from=php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN install-php-extensions @composer intl opcache pdo_mysql zip +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" +COPY --link conf/php.ini $PHP_INI_DIR/conf.d/app.ini + +# Apache +COPY --link errors /errors +COPY --link health.php /health/index.php +COPY --link conf/vhost.conf /etc/apache2/sites-available/000-default.conf +COPY --link conf/apache.conf /etc/apache2/conf-available/z-app.conf +COPY --link index.php /app/index.php + +RUN a2enmod rewrite remoteip && \ + a2enconf z-app diff --git a/8.6-symfony/conf/apache.conf b/8.6-symfony/conf/apache.conf new file mode 100644 index 0000000..142ec3c --- /dev/null +++ b/8.6-symfony/conf/apache.conf @@ -0,0 +1,64 @@ + + Options -Indexes +FollowSymLinks + AllowOverride None + Require all granted + + SetEnvIf X-Forwarded-Proto "^https$" HTTPS=on + + +ServerTokens Prod +ServerSignature Off + +LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined + +RemoteIPHeader X-Forwarded-For +RemoteIPInternalProxy 10.0.0.0/8 +RemoteIPInternalProxy 172.16.0.0/12 +RemoteIPInternalProxy 192.168.0.0/16 +RemoteIPInternalProxy 169.254.0.0/16 +RemoteIPInternalProxy 127.0.0.0/8 +RemoteIPInternalProxy ::1 + +# Add Cloudflare IP ranges +RemoteIPTrustedProxy 173.245.48.0/20 +RemoteIPTrustedProxy 103.21.244.0/22 +RemoteIPTrustedProxy 103.22.200.0/22 +RemoteIPTrustedProxy 103.31.4.0/22 +RemoteIPTrustedProxy 141.101.64.0/18 +RemoteIPTrustedProxy 108.162.192.0/18 +RemoteIPTrustedProxy 190.93.240.0/20 +RemoteIPTrustedProxy 188.114.96.0/20 +RemoteIPTrustedProxy 197.234.240.0/22 +RemoteIPTrustedProxy 198.41.128.0/17 +RemoteIPTrustedProxy 162.158.0.0/15 +RemoteIPTrustedProxy 104.16.0.0/13 +RemoteIPTrustedProxy 104.24.0.0/14 +RemoteIPTrustedProxy 172.64.0.0/13 +RemoteIPTrustedProxy 131.0.72.0/22 +RemoteIPTrustedProxy 2400:cb00::/32 +RemoteIPTrustedProxy 2606:4700::/32 +RemoteIPTrustedProxy 2803:f800::/32 +RemoteIPTrustedProxy 2405:b500::/32 +RemoteIPTrustedProxy 2405:8100::/32 +RemoteIPTrustedProxy 2a06:98c0::/29 +RemoteIPTrustedProxy 2c0f:f248::/32 + + + Options -Indexes + AllowOverride None + Require all granted + + + + Options -Indexes + AllowOverride None + Require local + + +Alias /_errors/ /errors/ + + Alias "/health/index.php" + +ErrorDocument 404 /_errors/404.html +ErrorDocument 403 /_errors/403.html +ErrorDocument 500 /_errors/500.html diff --git a/8.6-symfony/conf/php.ini b/8.6-symfony/conf/php.ini new file mode 100644 index 0000000..81f7cde --- /dev/null +++ b/8.6-symfony/conf/php.ini @@ -0,0 +1,23 @@ +date.timezone = Europe/Paris + +opcache.enable = 1 +opcache.enable_cli = 1 +opcache.memory_consumption = 256 +opcache.interned_strings_buffer = 16 +opcache.max_accelerated_files = 20000 +; Files are compiled once and never checked again: restart PHP to deploy new code, or set +; PHP_OPCACHE_VALIDATE_TIMESTAMPS=1 when the sources are mounted and edited in place. +opcache.validate_timestamps = ${PHP_OPCACHE_VALIDATE_TIMESTAMPS} +opcache.revalidate_freq = 0 +apc.enable_cli = On + +upload_max_filesize = 16M +post_max_size = 16M + +realpath_cache_size = 4096k +realpath_cache_ttl = 7200 + +expose_php = Off +display_errors = Off +display_startup_errors = Off +error_log = /proc/self/fd/2 diff --git a/8.6-symfony/conf/vhost.conf b/8.6-symfony/conf/vhost.conf new file mode 100644 index 0000000..4295c31 --- /dev/null +++ b/8.6-symfony/conf/vhost.conf @@ -0,0 +1,23 @@ + + ServerAdmin hello@silarhi.fr + + DocumentRoot /app/public + + + + Options -MultiViews + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php [QSA,L] + + + + + RedirectMatch 302 ^/$ /index.php/ + + + + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + diff --git a/8.6-symfony/errors/403.html b/8.6-symfony/errors/403.html new file mode 100644 index 0000000..97890d1 --- /dev/null +++ b/8.6-symfony/errors/403.html @@ -0,0 +1,20 @@ + + + + + + + Erreur 403 (Interdit) + + + + +
+
+

403

+

Accès interdit.

+

L'accès à cette page requiert une autorisation.

+ Retour à la page d'accueil +
+ + diff --git a/8.6-symfony/errors/404.html b/8.6-symfony/errors/404.html new file mode 100644 index 0000000..f0b6399 --- /dev/null +++ b/8.6-symfony/errors/404.html @@ -0,0 +1,20 @@ + + + + + + + Erreur 404 (Introuvable) + + + + +
+
+

404

+

Oops! Vous êtes perdu.

+

La page que vous demandez est introuvable. Elle a peut-être été supprimée ou déplacée.

+ Retour à la page d'accueil +
+ + diff --git a/8.6-symfony/errors/500.html b/8.6-symfony/errors/500.html new file mode 100644 index 0000000..b34c2d7 --- /dev/null +++ b/8.6-symfony/errors/500.html @@ -0,0 +1,20 @@ + + + + + + + Erreur 500 (Inaccessible) + + + + +
+
+

500

+

Huston, on a un problème !

+

La page que vous demandez est temporairement inaccessible.

+ Retour à la page d'accueil +
+ + diff --git a/8.6-symfony/errors/css/style.css b/8.6-symfony/errors/css/style.css new file mode 100644 index 0000000..6be89a5 --- /dev/null +++ b/8.6-symfony/errors/css/style.css @@ -0,0 +1,102 @@ +html { + box-sizing: border-box; + font-size: 16px; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body, h1, h2, h3, h4, h5, h6, p, ol, ul { + margin: 0; + padding: 0; + font-weight: normal; +} + +ol, ul { + list-style: none; +} + +html, body { + height: 100%; +} + +body { + font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +#error-box { + position: relative; + max-width: 560px; + width: 100%; + padding-left: 160px; + line-height: 1.1; +} + +#error-box #error-image { + position: absolute; + left: 0; + top: 0; + display: inline-block; + width: 140px; + height: 140px; + background-image: url('/_errors/img/emoji.png'); + background-size: cover; +} + +#error-box #error-image:before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + transform: scale(2.4); + border-radius: 50%; + background-color: #f2f5f8; + z-index: -1; +} + +#error-box h1 { + font-size: 65px; + font-weight: 700; + margin-top: 0; + margin-bottom: 10px; + color: #151723; + text-transform: uppercase; +} + +#error-box h2 { + font-size: 21px; + font-weight: 400; + margin: 0 0 1rem 0; + text-transform: uppercase; + color: #151723; +} + +#error-box p { + color: #999fa5; + font-weight: 400; + margin-bottom: 1rem; +} + +#error-box a { + font-weight: 500; + text-decoration: none; + color: #388dbc; +} + +@media only screen and (max-width: 767px) { + #error-box #error-image { + width: 110px; + height: 110px; + } + + #error-box { + padding-left: 15px; + padding-right: 15px; + padding-top: 110px; + } +} diff --git a/8.6-symfony/errors/img/emoji.png b/8.6-symfony/errors/img/emoji.png new file mode 100644 index 0000000..7cd4942 Binary files /dev/null and b/8.6-symfony/errors/img/emoji.png differ diff --git a/8.6-symfony/health.php b/8.6-symfony/health.php new file mode 100644 index 0000000..d6bd4dc --- /dev/null +++ b/8.6-symfony/health.php @@ -0,0 +1,3 @@ + + Options -Indexes +FollowSymLinks + AllowOverride None + Require all granted + + SetEnvIf X-Forwarded-Proto "^https$" HTTPS=on + + +ServerTokens Prod +ServerSignature Off + +LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined + +RemoteIPHeader X-Forwarded-For +RemoteIPInternalProxy 10.0.0.0/8 +RemoteIPInternalProxy 172.16.0.0/12 +RemoteIPInternalProxy 192.168.0.0/16 +RemoteIPInternalProxy 169.254.0.0/16 +RemoteIPInternalProxy 127.0.0.0/8 +RemoteIPInternalProxy ::1 + +# Add Cloudflare IP ranges +RemoteIPTrustedProxy 173.245.48.0/20 +RemoteIPTrustedProxy 103.21.244.0/22 +RemoteIPTrustedProxy 103.22.200.0/22 +RemoteIPTrustedProxy 103.31.4.0/22 +RemoteIPTrustedProxy 141.101.64.0/18 +RemoteIPTrustedProxy 108.162.192.0/18 +RemoteIPTrustedProxy 190.93.240.0/20 +RemoteIPTrustedProxy 188.114.96.0/20 +RemoteIPTrustedProxy 197.234.240.0/22 +RemoteIPTrustedProxy 198.41.128.0/17 +RemoteIPTrustedProxy 162.158.0.0/15 +RemoteIPTrustedProxy 104.16.0.0/13 +RemoteIPTrustedProxy 104.24.0.0/14 +RemoteIPTrustedProxy 172.64.0.0/13 +RemoteIPTrustedProxy 131.0.72.0/22 +RemoteIPTrustedProxy 2400:cb00::/32 +RemoteIPTrustedProxy 2606:4700::/32 +RemoteIPTrustedProxy 2803:f800::/32 +RemoteIPTrustedProxy 2405:b500::/32 +RemoteIPTrustedProxy 2405:8100::/32 +RemoteIPTrustedProxy 2a06:98c0::/29 +RemoteIPTrustedProxy 2c0f:f248::/32 + + + Options -Indexes + AllowOverride None + Require all granted + + + + Options -Indexes + AllowOverride None + Require local + + +Alias /_errors/ /errors/ + + Alias "/health/index.php" + +ErrorDocument 404 /_errors/404.html +ErrorDocument 403 /_errors/403.html +ErrorDocument 500 /_errors/500.html diff --git a/8.6/conf/php.ini b/8.6/conf/php.ini new file mode 100644 index 0000000..81f7cde --- /dev/null +++ b/8.6/conf/php.ini @@ -0,0 +1,23 @@ +date.timezone = Europe/Paris + +opcache.enable = 1 +opcache.enable_cli = 1 +opcache.memory_consumption = 256 +opcache.interned_strings_buffer = 16 +opcache.max_accelerated_files = 20000 +; Files are compiled once and never checked again: restart PHP to deploy new code, or set +; PHP_OPCACHE_VALIDATE_TIMESTAMPS=1 when the sources are mounted and edited in place. +opcache.validate_timestamps = ${PHP_OPCACHE_VALIDATE_TIMESTAMPS} +opcache.revalidate_freq = 0 +apc.enable_cli = On + +upload_max_filesize = 16M +post_max_size = 16M + +realpath_cache_size = 4096k +realpath_cache_ttl = 7200 + +expose_php = Off +display_errors = Off +display_startup_errors = Off +error_log = /proc/self/fd/2 diff --git a/8.6/conf/vhost.conf b/8.6/conf/vhost.conf new file mode 100644 index 0000000..a16c65c --- /dev/null +++ b/8.6/conf/vhost.conf @@ -0,0 +1,8 @@ + + ServerAdmin hello@silarhi.fr + + DocumentRoot /app + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + diff --git a/8.6/errors/403.html b/8.6/errors/403.html new file mode 100644 index 0000000..97890d1 --- /dev/null +++ b/8.6/errors/403.html @@ -0,0 +1,20 @@ + + + + + + + Erreur 403 (Interdit) + + + + +
+
+

403

+

Accès interdit.

+

L'accès à cette page requiert une autorisation.

+ Retour à la page d'accueil +
+ + diff --git a/8.6/errors/404.html b/8.6/errors/404.html new file mode 100644 index 0000000..f0b6399 --- /dev/null +++ b/8.6/errors/404.html @@ -0,0 +1,20 @@ + + + + + + + Erreur 404 (Introuvable) + + + + +
+
+

404

+

Oops! Vous êtes perdu.

+

La page que vous demandez est introuvable. Elle a peut-être été supprimée ou déplacée.

+ Retour à la page d'accueil +
+ + diff --git a/8.6/errors/500.html b/8.6/errors/500.html new file mode 100644 index 0000000..b34c2d7 --- /dev/null +++ b/8.6/errors/500.html @@ -0,0 +1,20 @@ + + + + + + + Erreur 500 (Inaccessible) + + + + +
+
+

500

+

Huston, on a un problème !

+

La page que vous demandez est temporairement inaccessible.

+ Retour à la page d'accueil +
+ + diff --git a/8.6/errors/css/style.css b/8.6/errors/css/style.css new file mode 100644 index 0000000..6be89a5 --- /dev/null +++ b/8.6/errors/css/style.css @@ -0,0 +1,102 @@ +html { + box-sizing: border-box; + font-size: 16px; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body, h1, h2, h3, h4, h5, h6, p, ol, ul { + margin: 0; + padding: 0; + font-weight: normal; +} + +ol, ul { + list-style: none; +} + +html, body { + height: 100%; +} + +body { + font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +#error-box { + position: relative; + max-width: 560px; + width: 100%; + padding-left: 160px; + line-height: 1.1; +} + +#error-box #error-image { + position: absolute; + left: 0; + top: 0; + display: inline-block; + width: 140px; + height: 140px; + background-image: url('/_errors/img/emoji.png'); + background-size: cover; +} + +#error-box #error-image:before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + transform: scale(2.4); + border-radius: 50%; + background-color: #f2f5f8; + z-index: -1; +} + +#error-box h1 { + font-size: 65px; + font-weight: 700; + margin-top: 0; + margin-bottom: 10px; + color: #151723; + text-transform: uppercase; +} + +#error-box h2 { + font-size: 21px; + font-weight: 400; + margin: 0 0 1rem 0; + text-transform: uppercase; + color: #151723; +} + +#error-box p { + color: #999fa5; + font-weight: 400; + margin-bottom: 1rem; +} + +#error-box a { + font-weight: 500; + text-decoration: none; + color: #388dbc; +} + +@media only screen and (max-width: 767px) { + #error-box #error-image { + width: 110px; + height: 110px; + } + + #error-box { + padding-left: 15px; + padding-right: 15px; + padding-top: 110px; + } +} diff --git a/8.6/errors/img/emoji.png b/8.6/errors/img/emoji.png new file mode 100644 index 0000000..7cd4942 Binary files /dev/null and b/8.6/errors/img/emoji.png differ diff --git a/8.6/health.php b/8.6/health.php new file mode 100644 index 0000000..d6bd4dc --- /dev/null +++ b/8.6/health.php @@ -0,0 +1,3 @@ +