├── .dockerignore ├── .env ├── .github ├── dependabot.yaml └── workflows │ └── release.yaml ├── .gitignore ├── DEVELOPMENT.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── container-files ├── entrypoint-riotkit.sh ├── entrypoint.sh ├── etc │ └── nginx │ │ └── nginx.conf ├── install-plugins-first-time.sh └── usr │ └── local │ └── etc │ └── php │ └── php.ini ├── env.mk ├── helm └── wordpress-hardened │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── README.md.gotmpl │ ├── bin │ └── get-app-version │ ├── templates │ ├── _helpers.tpl │ ├── dba.configmap.yaml │ ├── dba.cronjob.yaml │ ├── dba.job.yaml │ ├── deployment.yaml │ ├── extra-configmaps.yaml │ ├── ingress.yaml │ ├── poddisruptionbudget.yaml │ ├── pvc.yaml │ ├── secret.yaml │ ├── service.yaml │ └── waf.configmap.yaml │ └── values.yaml ├── htpasswd ├── kuttl-test.yaml ├── liveness.php ├── readiness.php ├── skaffold.values.yaml ├── skaffold.yaml ├── tests └── e2e │ └── preinstalls-with-plugins │ ├── 01-prepare.yaml │ ├── 02-assert-pod-running.yaml │ ├── 03-check-healthy.yaml │ └── values.yaml ├── wp-config-riotkit.php └── wp-config-sample.php /.dockerignore: -------------------------------------------------------------------------------- 1 | /skaffold.yaml 2 | /.env 3 | /.gitignore 4 | /Makefile 5 | /kuttl-report.xml 6 | /kuttl-test.yaml 7 | /kubeconfig 8 | /tests 9 | /helm 10 | /.github 11 | /.build 12 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | ENV_CLUSTER_NAME=rkt 2 | ENV_NS=wp 3 | ENV_APP_SVC=wordpress-hardened 4 | ENV_PORT_FORWARD=8050:8080 5 | 6 | ENV_SKAFFOLD_DEPLOY_DEPS=true 7 | ENV_SKAFFOLD_DEPLOY_APP=false 8 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "docker" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Test and release 2 | on: 3 | push: 4 | workflow_dispatch: 5 | inputs: {} 6 | 7 | jobs: 8 | test: 9 | uses: riotkit-org/.github/.github/workflows/test.integration-tests.yaml@release-1 10 | if: "!startsWith(github.ref, 'refs/tags/v')" 11 | with: 12 | osVariant: ubuntu-22.04 13 | pythonEnabled: true 14 | testReportEnabled: true 15 | testReportPattern: kuttl-report.xml 16 | 17 | container-image: 18 | uses: riotkit-org/.github/.github/workflows/release.container.yaml@release-1 19 | needs: ["test"] 20 | if: | 21 | always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') 22 | with: 23 | osVariant: ubuntu-22.04 24 | intermediateArtifactsPath: "" 25 | dockerImage: "ghcr.io/riotkit-org/wordpress-hardened" 26 | 27 | helm: 28 | uses: riotkit-org/.github/.github/workflows/release.helm.yaml@release-1 29 | needs: ["container-image"] 30 | if: | 31 | always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') 32 | with: 33 | chartPath: helm/wordpress-hardened 34 | chartName: wordpress-hardened 35 | enableHelmDocs: true 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.build/* 2 | /kubeconfig 3 | /kuttl-report.xml 4 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | Development 2 | =========== 3 | 4 | Setting up the environment 5 | -------------------------- 6 | 7 | WordPress will start in local Kubernetes (inside docker) using Skaffold. Every [CTRL] + [S] will trigger rebuilding the container and reinstalling the WordPress. 8 | 9 | ```yaml 10 | make -f env.mk k3d dev 11 | ``` 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM wordpress:6.1.1-php7.4-fpm-alpine 2 | MAINTAINER RiotKit 3 | 4 | # The credentials does not need to be top secret, at least those credentials needs to protect against automatic bots 5 | # default basic auth credentials: riotkit, riotkit 6 | # to change credentials just replace file "/opt/htpsswd" using volume mount or customized image 7 | 8 | ENV AUTO_UPDATE_CRON="0 5 * * TUE" \ 9 | XMLRPC_DISABLED=true \ 10 | DISABLE_DIRECT_CONTENT_PHP_EXECUTION=false \ 11 | BASIC_AUTH_USER=riotkit \ 12 | BASIC_AUTH_PASSWORD=riotkit \ 13 | ASIC_AUTH_ENABLED=true \ 14 | PHP_DISPLAY_ERRORS="Off" \ 15 | PHP_ERROR_REPORTING="E_ALL & ~E_DEPRECATED & ~E_STRICT" \ 16 | PHP_POST_MAX_SIZE="32M" \ 17 | PHP_UPLOAD_MAX_FILESIZE="32M" \ 18 | PHP_MEMORY_LIMIT="128M" \ 19 | HEALTH_CHECK_ALLOWED_SUBNET="" \ 20 | FORCE_UPGRADE=false \ 21 | ENABLED_PLUGINS="" \ 22 | WP_PREINSTALL=false \ 23 | WP_SITE_URL=example.org \ 24 | WP_SITE_ADMIN_LOGIN=admin \ 25 | WP_SITE_ADMIN_PASSWORD=riotkit \ 26 | WP_SITE_ADMIN_EMAIL=example@example.org \ 27 | ACCESS_LOG=/dev/stdout \ 28 | ERROR_LOG=/dev/stderr \ 29 | WORDPRESS_TABLE_PREFIX=wp_ \ 30 | WP_INSTALLATION_WAIT_INTERVAL=20 \ 31 | WP_PLUGINS_REINSTALL_RETRIES=30 32 | 33 | # p2 (jinja2) 34 | RUN wget https://github.com/wrouesnel/p2cli/releases/download/r13/p2-linux-x86_64 -O /usr/bin/p2 && chmod +x /usr/bin/p2 35 | 36 | # multirun (supervisord equivalent) 37 | RUN wget https://github.com/nicolas-van/multirun/releases/download/1.1.3/multirun-x86_64-linux-musl-1.1.3.tar.gz -O /tmp/multirun.tar.gz \ 38 | && cd /tmp \ 39 | && tar xvf multirun.tar.gz \ 40 | && rm multirun.tar.gz \ 41 | && mv multir* /usr/bin/multirun \ 42 | && chmod +x /usr/bin/multirun 43 | 44 | RUN apk --update add nginx apache2-utils rsync less \ 45 | && curl "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar" --output /usr/bin/wp \ 46 | && mkdir -p /var/tmp/nginx/ /var/lib/nginx/tmp/ \ 47 | && chown www-data:www-data /var/tmp/nginx/ /var/lib/nginx/tmp/ -R \ 48 | && chmod +x /usr/bin/wp 49 | 50 | ADD ./wp-config-sample.php /usr/src/wordpress/wp-config.php 51 | ADD ./wp-config-riotkit.php /usr/src/wordpress/wp-config-riotkit.php 52 | ADD ./liveness.php /usr/src/wordpress/liveness.php 53 | ADD ./readiness.php /usr/src/wordpress/readiness.php 54 | ADD ./container-files /templates 55 | ADD htpasswd /opt/htpasswd 56 | 57 | # Allow runtime modify of those files by entrypoint, so the container could be rootless 58 | RUN mkdir -p /var/www/riotkit /var/lib/nginx/tmp/proxy /var/lib/nginx/logs \ 59 | && touch /usr/local/etc/php/php.ini /usr/local/sbin/php-fpm.bckp /etc/crontabs/www-data /var/lib/nginx/logs/error.log 60 | RUN chown -R 65161:65161 \ 61 | /etc/nginx/nginx.conf \ 62 | /usr/local/etc/php/php.ini \ 63 | /opt/htpasswd \ 64 | /usr/local/sbin \ 65 | /etc/crontabs/www-data \ 66 | /var/www \ 67 | /usr/src/wordpress \ 68 | /var/lib/nginx \ 69 | /var/log \ 70 | /var/run \ 71 | /run 72 | 73 | # non-root container does not need root tasks 74 | RUN rm /etc/crontabs/root 75 | 76 | # change www-data uid and gid to 65161 77 | RUN cat /etc/passwd | grep -v "www-data" > /etc/passwd.tmp \ 78 | && echo "www-data:x:65161:65161:Linux User,,,:/home/www-data:/sbin/nologin" >> /etc/passwd.tmp \ 79 | && cat /etc/passwd.tmp > /etc/passwd 80 | RUN cat /etc/group | grep -v "www-data" > /etc/group.tmp \ 81 | && echo "www-data:x:65161:" >> /etc/group.tmp \ 82 | && cat /etc/group.tmp > /etc/group 83 | 84 | # add entrypoints 85 | ADD container-files/entrypoint-riotkit.sh /usr/local/bin/ 86 | ADD container-files/entrypoint.sh /usr/local/bin/docker-entrypoint.sh 87 | ADD container-files/install-plugins-first-time.sh /usr/local/bin/install-plugins-first-time.sh 88 | RUN chmod +x /usr/local/bin/entrypoint-riotkit.sh /usr/local/bin/docker-entrypoint.sh /usr/local/bin/install-plugins-first-time.sh 89 | 90 | # high user id number should be more compatible with OpenShift 91 | USER 65161 92 | 93 | # test nginx configuration file 94 | RUN HEALTH_CHECK_ALLOWED_SUBNET=0.0.0.0/0; \ 95 | DISABLE_DIRECT_CONTENT_PHP_EXECUTION=true; \ 96 | BASIC_AUTH_ENABLED=true; \ 97 | p2 --template /templates/etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -t 98 | 99 | WORKDIR "/var/www/riotkit" 100 | ENTRYPOINT ["/usr/local/bin/entrypoint-riotkit.sh"] 101 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include env.mk 2 | 3 | IMAGE=wordpress-hardened 4 | 5 | build: 6 | docker build . -t ${IMAGE} 7 | 8 | run: 9 | docker run --rm --name wp-riotkit -p 8090:8080 ${IMAGE} 10 | 11 | integration-test: prepare-tools kubeconfig 12 | kuttl test --report xml 13 | 14 | test: test_installed test_installs_plugins 15 | 16 | test_installed: 17 | docker run --rm --name wp-riotkit ${IMAGE} /bin/bash -c "echo 'Testing installation...'; test -f /var/www/riotkit/index.php && test -f /var/www/riotkit/wp-admin/index.php" 18 | 19 | test_installs_plugins: 20 | docker rm -f wph-test-mariadb || true 21 | docker network remove wph-test || true 22 | docker network create wph-test 23 | 24 | # MariaDB (dependency) 25 | docker run --rm -d --name wph-test-mariadb -e MARIADB_ROOT_PASSWORD=riotkit -e MARIADB_PASSWORD=riotkit -e MARIADB_USER=wp -e MARIADB_DATABASE=wp --network wph-test --network-alias mariadb.db.svc.cluster.local mariadb:10.7.3 && sleep 15 26 | docker run --rm --name wp-riotkit -e WP_PREINSTALL=true -e WORDPRESS_DB_HOST=mariadb.db.svc.cluster.local -e WORDPRESS_DB_PASSWORD=riotkit -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_NAME=wp -e ENABLED_PLUGINS="amazon-s3-and-cloudfront,classic-editor" --network wph-test ${IMAGE} /bin/bash -c "find /var/www/riotkit/wp-content 2>&1 |grep amazon-s3-and-cloudfront" 27 | docker rm -f wph-test-mariadb || true 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WordPress Hardened 2 | ================== 3 | 4 | Hardened version of official WordPress container, with special support for Kubernetes. 5 | 6 | **Features:** 7 | - Scheduled updates via wp-cli 8 | - **NGINX instead of Apache** 9 | - Supports [NGINX-PROXY](https://github.com/nginx-proxy/nginx-proxy) (VIRTUAL_HOST environment variable) 10 | - Hardened settings for WordPress: limiting access to code execution from wp-content directory, basic auth on wp-login.php 11 | - Basic Auth enabled by default to protect wp-login against bots (default user: `riotkit`, password: `riotkit`), can be changed using environment variables 12 | - Non-root container 13 | - Free from Supervisord, using lightweight [multirun](https://github.com/nicolas-van/multirun) instead 14 | - Runtime NGINX and PHP configuration to adjust things like `memory_limit`, `error_reporting` or `post_max_size` 15 | - Pre-configuration of admin account, website name and list of installed plugins 16 | - Possible to upgrade WordPress together with docker container 17 | - Built-in primitive rules to block common exploits targeting PHP 18 | 19 | **Kubernetes-only features:** 20 | - Helm installer 21 | - Integration with [Backup Repository](https://github.com/riotkit-org/backup-repository) (for Kubernetes-native backups) 22 | - Integration with [Volume Syncing Controller](https://github.com/riotkit-org/volume-syncing-controller) (for WordPress volume synchronization between Pod and cloud filesystem) 23 | - Web Application Firewall and OWASP CRS support (experimental) 24 | - Schedule SQL query execution periodically to perform tasks like deletion of old, unapproved comments 25 | 26 | Roadmap 27 | ------- 28 | 29 | - [x] Use GitHub Actions as CI 30 | - [x] Replace J2cli with [P2cli](https://github.com/wrouesnel/p2cli) 31 | - [x] Replace Supervisord with [multirun](https://github.com/nicolas-van/multirun) 32 | - [x] Non-root container 33 | - [x] Helm Chart 34 | - [x] Plugins management - container installs selected plugins right after start or before starting 35 | - [ ] Support for Network Policy templates 36 | - [x] Support for Backup Repository template 37 | - [ ] Support WAF (Web Application Firewall) with [OWASP CRS](https://owasp.org/www-project-modsecurity-core-rule-set/) 38 | - [x] Real liveness and readiness checks 39 | - [ ] PHP-FPM chroot (to verify first) 40 | - [ ] Support for WP Super Cache plugin (https://www.nginx.com/blog/9-tips-for-improving-wordpress-performance-with-nginx/#wp-super-cache) 41 | 42 | Changing basic auth password or disabling it at all 43 | --------------------------------------------------- 44 | 45 | **Disabling:** 46 | 47 | ```bash 48 | -e BASIC_AUTH_ENABLED=false 49 | ``` 50 | 51 | **Changing password:** 52 | 53 | ```bash 54 | -e BASIC_AUTH_USER=some-user -e BASIC_AUTH_PASSWORD=some-password 55 | ``` 56 | 57 | Versions 58 | -------- 59 | 60 | https://github.com/riotkit-org/wordpress-hardened/packages 61 | 62 | Example: `ghcr.io/riotkit-org/wordpress-hardened:5.9.3-1` 63 | 64 | Running 65 | ------- 66 | 67 | With docker command: 68 | 69 | ```bash 70 | sudo docker run -v $(pwd)/your-www-files:/var/www/html -e WORDPRESS_DB_HOST=... -e WORDPRESS_DB_USER=... -e WORDPRESS_DB_PASSWORD=... -e WORDPRESS_DB_NAME=... -p 80:80 ghcr.io/riotkit-org/wordpress-hardened:5.9.3-1 71 | ``` 72 | 73 | Or with docker-compose: 74 | 75 | ```yaml 76 | version: "2.3" 77 | services: 78 | app_your_app: 79 | image: ghcr.io/riotkit-org/wordpress-hardened:5.9.3-1 80 | volumes: 81 | - ./your-www-files/:/var/www/html 82 | environment: 83 | WORDPRESS_DB_HOST: "db" 84 | WORDPRESS_DB_USER: "your_user" 85 | WORDPRESS_DB_PASSWORD: "${DB_PASSWORD_THERE}" 86 | WORDPRESS_DB_NAME: "your_app" 87 | WORDPRESS_TABLE_PREFIX: "wp_" 88 | AUTO_UPDATE_CRON: "0 5 * * SAT" 89 | XMLRPC_DISABLED: "true" 90 | DISABLE_DIRECT_CONTENT_PHP_EXECUTION: "false" 91 | ENABLED_PLUGINS: "amazon-s3-and-cloudfront" 92 | 93 | # basic auth on administrative endpoints 94 | BASIC_AUTH_ENABLED: "true" 95 | BASIC_AUTH_USER: john 96 | BASIC_AUTH_PASSWORD: secret 97 | 98 | # main page URL 99 | WP_PAGE_URL: "zsp.net.pl" 100 | 101 | # multiple domains can be pointing at this container 102 | VIRTUAL_HOST: "zsp.net.pl,www.zsp.net.pl,wroclaw.zsp.net.pl,wwww.wroclaw.zsp.net.pl" 103 | 104 | ``` 105 | 106 | Automating installation 107 | ----------------------- 108 | 109 | You can skip installation wizard by installing WordPress on container startup. 110 | This container uses `wp-cli` to install WordPress and plugins allowing you to prepare a fully automated website. 111 | 112 | **Example configuration:** 113 | ```yaml 114 | WP_PREINSTALL: true 115 | WP_SITE_URL: example.org 116 | WP_SITE_ADMIN_LOGIN: admin 117 | WP_SITE_ADMIN_PASSWORD: riotkit 118 | WP_SITE_ADMIN_EMAIL: example@example.org 119 | 120 | # NOTICE: The plugins will be installed right after WordPress installation is finished, 121 | # this means that when `WP_PREINSTALL=false`, then the entrypoint will wait for user 122 | # to complete the installation wizard, then the plugins will be installed 123 | ENABLED_PLUGINS: "amazon-s3-and-cloudfront,classic-editor" 124 | 125 | WP_INSTALLATION_WAIT_INTERVAL: 20 # in seconds, how long to wait until the WordPress is installed to start installing plugins 126 | WP_PLUGINS_REINSTALL_RETRIES: 30 # 30 retries with 20s interval 127 | ``` 128 | 129 | **Example log:** 130 | 131 | ```bash 132 | >> Checking if autoupdate should be scheduled... [scheduling at '0 5 * * TUE'] 133 | >> Writing to basic auth file - /opt/htpasswd 134 | Adding password for user riotkit 135 | >> Rendering configuration files... 136 | >> Installing Wordpress 137 | >> UID=65161, GID=65161 138 | WordPress not found in /var/www/riotkit - copying now... 139 | sending incremental file list 140 | index.php 141 | liveness.php 142 | readiness.php 143 | ... 144 | wp-includes/widgets/class-wp-widget-text.php 145 | 146 | sent 58,545,704 bytes received 54,312 bytes 39,066,677.33 bytes/sec 147 | total size is 58,341,389 speedup is 1.00 148 | Complete! WordPress has been successfully copied to /var/www/riotkit 149 | No 'wp-config.php' found in /var/www/riotkit, but 'WORDPRESS_...' variables supplied; copying 'wp-config-docker.php' (WORDPRESS_DB_HOST WORDPRESS_DB_NAME WORDPRESS_DB_PASSWORD WORDPRESS_DB_USER) 150 | Success: WordPress installed successfully. 151 | >> Installing plugin 'amazon-s3-and-cloudfront' 152 | Installing WP Offload Media Lite for Amazon S3, DigitalOcean Spaces, and Google Cloud Storage (2.6.2) 153 | Downloading installation package from https://downloads.wordpress.org/plugin/amazon-s3-and-cloudfront.2.6.2.zip... 154 | Unpacking the package... 155 | Installing the plugin... 156 | Plugin installed successfully. 157 | Success: Installed 1 of 1 plugins. 158 | >> Installing plugin 'classic-editor' 159 | Installing Classic Editor (1.6.2) 160 | Downloading installation package from https://downloads.wordpress.org/plugin/classic-editor.1.6.2.zip... 161 | Unpacking the package... 162 | Installing the plugin... 163 | Plugin installed successfully. 164 | Success: Installed 1 of 1 plugins. 165 | ``` 166 | 167 | ### How it works? 168 | 169 | - Plugins will be installed AFTER WordPress will be installed. Use `WP_PREINSTALL: true` to install WordPress immediately, else the plugins will be installed after user will finish installation process 170 | - There will be `WP_PLUGINS_REINSTALL_RETRIES` retries of plugins installation 171 | - If at least one plugin installation will fail, then **after exceeding maximum number of retries the container will exit** 172 | - Even if some plugins installation will fail, the rest will be installed (installation process does not exit immediately after first fail) 173 | 174 | 175 | Access log and error log 176 | ------------------------ 177 | 178 | Point access and error logs to files, to stdout/stderr or disable logging by using environment variables. 179 | 180 | ```bash 181 | ACCESS_LOG: /dev/stdout 182 | ERROR_LOG: /dev/stderr 183 | ``` 184 | 185 | ```bash 186 | ACCESS_LOG: /mnt/logs/access.log 187 | ERROR_LOG: /mnt/logs/error.log 188 | ``` 189 | 190 | ```bash 191 | ACCESS_LOG: off 192 | ERROR_LOG: off 193 | ``` 194 | 195 | Using proxy to connect to the internet (egress traffic, http proxy) 196 | ------------------------------------------------------------------- 197 | 198 | In restricted environments you may want to deny all egress traffic from your WordPress instance, but let the WordPress 199 | update itself and install/upgrade plugins using a HTTP proxy, where you are in control of allowed internet destinations. 200 | 201 | ```yaml 202 | env: 203 | WP_PROXY_HOST: my-proxy.proxy.svc.cluster.local 204 | WP_PROXY_PORT: 8080 205 | WP_PROXY_USERNAME: user 206 | WP_PROXY_PASSWORD: xxxxx 207 | WP_PROXY_BYPASS_HOSTS: localhost 208 | ``` 209 | 210 | ## Kubernetes 211 | 212 | `wordpress-hardened` provides both container image and **Helm Chart**. 213 | 214 | Helm Chart can be installed from an OCI repository [ghcr.io/riotkit-org/charts/wordpress-hardened - check all available versions there](https://ghcr.io/riotkit-org/charts/wordpress-hardened) 215 | 216 | ```bash 217 | # change version to non-latest :-) 218 | helm pull oci://ghcr.io/riotkit-org/charts/wordpress-hardened --version 0.0-latest-master 219 | helm install myrelease oci://ghcr.io/riotkit-org/charts/wordpress-hardened --version 0.0-latest-master 220 | ``` 221 | 222 | [Check Helm values there](./helm/wordpress-hardened) 223 | ----------------------- 224 | 225 | Keeping wp-content and themes in GIT repository (Kubernetes only) 226 | ----------------------------------------------------------------- 227 | 228 | [git-clone-controller](https://github.com/riotkit-org/git-clone-controller) is a Kubernetes controller allowing to clone a GIT repository before a Pod is launched, can be used to automatically fetch your website theme within just few seconds before Pod starts. 229 | 230 | Use and adjust following Helm values to clone your WordPress theme from a GIT repository before the application will start up. 231 | 232 | **values.yaml** 233 | 234 | ```yaml 235 | # ---------------------------------------------------------- 236 | # theme 237 | # ---------------------------------------------------------- 238 | podLabels: 239 | riotkit.org/git-clone-controller: "true" 240 | podAnnotations: 241 | git-clone-controller/revision: main 242 | git-clone-controller/url: "https://git.example.org/my-example/my-theme.git" 243 | git-clone-controller/path: /var/www/riotkit/wp-content/themes/my-theme 244 | git-clone-controller/secretName: my-secret-name 245 | git-clone-controller/secretTokenKey: gitToken 246 | git-clone-controller/owner: "65161" 247 | git-clone-controller/group: "65161" 248 | ``` 249 | 250 | Backup with Backup Repository (Kubernetes only) 251 | ----------------------------------------------- 252 | 253 | Automatically taking a snapshot of database + files using a CronJob can be configured within Helm Values. Requires to have a [Backup Repository](https://github.com/riotkit-org/backup-repository) instance installed inside the cluster or outside the cluster. 254 | 255 | **values.yaml** 256 | 257 | ```yaml 258 | backups: 259 | enabled: true 260 | schedule: "16 1 * * *" 261 | collectionId: "xxx" 262 | ``` 263 | 264 | Enabling WAF protection using waf-proxy (Kubernetes only) 265 | --------------------------------------------------------- 266 | 267 | > :warning: This is experimental and may not work yet. 268 | 269 | Use following values to enable Web Application Firewall rules to protect your WordPress instance against various forms of attacks. 270 | 271 | _Learn more about Web Application Firewall setup - [waf-proxy](https://github.com/riotkit-org/waf-proxy)_ 272 | 273 | **values.yaml** 274 | 275 | ```yaml 276 | waf: 277 | enabled: true 278 | env: 279 | ENABLE_RULE_WORDPRESS: true 280 | ENABLE_CRS: true 281 | ENABLE_RATE_LIMITER: true 282 | RATE_LIMIT_EVENTS: "30" 283 | RATE_LIMIT_WINDOW: "5s" 284 | ENABLE_CORAZA_WAF: true 285 | #DEBUG: true 286 | ``` 287 | 288 | Enabling WAF protecting using ingress-nginx (Kubernetes only) 289 | ------------------------------------------------------------- 290 | 291 | > :information_source: Works only if you are using [ingress-nginx](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx) as Ingress Controller. 292 | 293 | [ingress-nginx](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx) has a built-in mod_security v3, that needs to be enabled on global configuration level using those helm values: 294 | 295 | ```yaml 296 | # Ingress NGINX config snippet 297 | controller: 298 | config: 299 | enable-modsecurity: "true" 300 | enable-owasp-modsecurity-crs: "true" 301 | modsecurity-snippet: | 302 | SecRuleEngine On 303 | ``` 304 | 305 | > :warning: This will enable mod_security and OWASP Core RuleSet on all ingress resources by default! According to documentation you need to set ingress annotation `nginx.ingress.kubernetes.io/enable-modsecurity: "false"` in every ingress, where you want the WAF to be disabled 306 | 307 | **WordPress requires additional tweaking, this can be done using Helm values of our Helm Chart as follows:** 308 | 309 | ```yaml 310 | # WordPress Hardened config snippet 311 | ingresses: 312 | - name: wp-https 313 | className: nginx 314 | annotations: 315 | cert-manager.io/cluster-issuer: letsencrypt-staging 316 | 317 | # WAF provided by Ingress NGINX 318 | nginx.ingress.kubernetes.io/enable-modsecurity: "true" 319 | nginx.ingress.kubernetes.io/enable-owasp-core-rules: "true" 320 | nginx.ingress.kubernetes.io/modsecurity-transaction-id: "$request_id" 321 | nginx.ingress.kubernetes.io/modsecurity-snippet: | 322 | SecRuleEngine On 323 | SecAction "id:900130,phase:1,nolog,pass,t:none,setvar:tx.crs_exclusions_drupal=0,setvar:tx.crs_exclusions_wordpress=1,setvar:tx.crs_exclusions_nextcloud=0,setvar:tx.crs_exclusions_dokuwiki=0,setvar:tx.crs_exclusions_cpanel=0" 324 | hosts: 325 | - host: my-domain.org 326 | paths: 327 | - path: / 328 | pathType: ImplementationSpecific 329 | tls: 330 | - hosts: ["my-domain.org"] 331 | secretName: my-domain-tls 332 | ``` 333 | 334 | Mounting extra volumes (Kubernetes only) 335 | ---------------------------------------- 336 | 337 | Every file placed in `/mnt/extra-files` will be copied during startup to `/var/www/riotkit/`, this mechanism ensures that 338 | no any file will be created with root-permissions inside a `/var/www/riotkit` directory - mounting a volume directly could do so. 339 | 340 | ```yaml 341 | # create extra ConfigMaps 342 | extraConfigMaps: 343 | - name: my-configmap-name 344 | data: 345 | something.php: | 346 | 7; 390 | ``` 391 | 392 | 393 | From authors 394 | ------------ 395 | 396 | Project was started as a part of RiotKit initiative, for the needs of grassroot organizations such as: 397 | 398 | - Fighting for better working conditions syndicalist (International Workers Association for example) 399 | - Tenants rights organizations 400 | - Political prisoners supporting organizations 401 | - Various grassroot organizations that are helping people to organize themselves without authority 402 | 403 | We provide tools that organizations can host themselves with trust. 404 | -------------------------------------------------------------------------------- /container-files/entrypoint-riotkit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | # 6 | # Setup Wordpress files, extracts from files provided by official WordPress base image 7 | # 8 | setupWP() { 9 | echo " >> Installing Wordpress" 10 | /usr/local/bin/docker-entrypoint.sh || exit 1 11 | } 12 | 13 | # 14 | # Preinstall WordPress, setup admin account, set URL, install plugins etc. - make it immediately ready 15 | # 16 | preinstallWP() { 17 | if [[ "${WP_PREINSTALL}" == "true" ]]; then 18 | wp core install --url=${WP_SITE_URL} --title=${WP_SITE_TITLE} --admin_user=${WP_SITE_ADMIN_LOGIN} --admin_password=${WP_SITE_ADMIN_PASSWORD} --admin_email=${WP_SITE_ADMIN_EMAIL} 19 | /usr/local/bin/install-plugins-first-time.sh no-wait 20 | fi 21 | } 22 | 23 | # 24 | # Automatic updates 25 | # 26 | scheduleAutoupdate() { 27 | echo -n " >> Checking if autoupdate should be scheduled..." 28 | if [[ "${AUTO_UPDATE_CRON}" != "" ]]; then 29 | echo " [scheduling at '${AUTO_UPDATE_CRON}']" 30 | echo "${AUTO_UPDATE_CRON} cd /var/www/riotkit && wp core update" > /etc/crontabs/www-data 31 | else 32 | echo " [not scheduling]" 33 | fi 34 | } 35 | 36 | # 37 | # Basic AUTH on wp-login.php is a very primitive additional layer of security against bots 38 | # 39 | setupBasicAuth() { 40 | if [[ "${BASIC_AUTH_USER}" ]] && [[ "${BASIC_AUTH_PASSWORD}" ]]; then 41 | echo " >> Writing to basic auth file - /opt/htpasswd" 42 | htpasswd -b -c /opt/htpasswd "${BASIC_AUTH_USER}" "${BASIC_AUTH_PASSWORD}" 43 | else 44 | echo " >> No user or password set, skipping writing to /opt/htpasswd" 45 | fi 46 | } 47 | 48 | # 49 | # Runtime configuration setup: NGINX, PHP configuration is templated during startup 50 | # to allow using environment variables as configuration 51 | # 52 | setupConfiguration() { 53 | echo " >> Rendering configuration files..." 54 | p2 --template /templates/etc/nginx/nginx.conf > /etc/nginx/nginx.conf 55 | p2 --template /templates/usr/local/etc/php/php.ini > /usr/local/etc/php/php.ini 56 | } 57 | 58 | # 59 | # Extra files: In /mnt/extra-files you can volume-mount extra files that would be copied into WWW-root directory 60 | # This allows to keep WWW-root directory not mounted by any volume to avoid conflicts with permissions 61 | # (mounted volumes are creating directories owned by ROOT) 62 | # 63 | copyExtraFiles() { 64 | echo " >> Copying extra files if placed in /mnt/extra-files" 65 | if [[ -d /mnt/extra-files ]]; then 66 | cp -rf /mnt/extra-files/* /var/www/riotkit/ 67 | fi 68 | } 69 | 70 | scheduleAutoupdate 71 | setupBasicAuth 72 | setupConfiguration 73 | setupWP 74 | preinstallWP 75 | copyExtraFiles 76 | 77 | # Allows to pass own CMD 78 | # Also allows to execute tests on the container 79 | if [[ "${1}" == "exec" ]] || [[ "${1}" == "sh" ]] || [[ "${1}" == "bash" ]] || [[ "${1}" == "/bin/sh" ]] || [[ "${1}" == "/bin/bash" ]] ; then 80 | echo " >> Running ${@}" 81 | exec "$@" 82 | fi 83 | 84 | multirun_args=("php-fpm" "nginx -c /etc/nginx/nginx.conf" "/usr/local/bin/install-plugins-first-time.sh") 85 | if [[ "${AUTO_UPDATE_CRON}" != "" ]]; then 86 | multirun_args+=("crond -f -d 6") 87 | fi 88 | 89 | exec multirun "${multirun_args[@]}" 90 | -------------------------------------------------------------------------------- /container-files/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | uid="$(id -u)" 5 | gid="$(id -g)" 6 | 7 | echo " >> UID=${uid}, GID=${gid}" 8 | 9 | if ([ ! -e index.php ] && [ ! -e wp-includes/version.php ]) || [[ "${FORCE_UPGRADE}" == "true" ]]; then 10 | args=( "--exclude" "readme.html" "--exclude" "*.txt" "--exclude" "wp-content" ) 11 | 12 | echo >&2 " >> WordPress not found in $PWD - copying now..." 13 | if [ -n "$(find -mindepth 1 -maxdepth 1 -not -name wp-content)" ]; then 14 | echo >&2 "WARNING: $PWD is not empty! (copying anyhow)" 15 | fi 16 | 17 | echo >&2 " >> Running rsync, additional args: ${args[@]}" 18 | rsync -av /usr/src/wordpress/* /var/www/riotkit "${args[@]}" 19 | 20 | # does not exist OR is empty 21 | if [[ ! -d /var/www/riotkit/wp-content ]] || [[ ! -z "$(ls -A /var/www/riotkit/wp-content)" ]]; then 22 | echo >&2 " >> Syncing wp-content as it does not exists or is empty" 23 | mkdir -p /usr/src/wordpress/wp-content || true 24 | 25 | # do not set owner/group/time on a volume mount to avoid non-root permission denied 26 | rsync -av --no-o --no-g --no-t --no-p /usr/src/wordpress/wp-content/* /var/www/riotkit/wp-content 27 | fi 28 | 29 | echo >&2 " >> YAY! WordPress has been successfully copied to $PWD" 30 | fi 31 | 32 | echo " >> Filling up wp-config.php" 33 | wpConfigContent=$(cat wp-config.php) 34 | echo "${wpConfigContent}" | awk ' 35 | /put your unique phrase here/ { 36 | cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" 37 | cmd | getline str 38 | close(cmd) 39 | gsub("put your unique phrase here", str) 40 | } 41 | { print } 42 | ' > wp-config.php 43 | -------------------------------------------------------------------------------- /container-files/etc/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | daemon off; 2 | worker_processes 3; 3 | pid /var/run/nginx.pid; 4 | 5 | events { 6 | worker_connections 768; 7 | } 8 | 9 | http { 10 | sendfile on; 11 | tcp_nopush on; 12 | tcp_nodelay on; 13 | keepalive_timeout 65; 14 | types_hash_max_size 4096; 15 | 16 | client_max_body_size 512M; 17 | client_body_temp_path /tmp 1 2; 18 | client_body_buffer_size 256k; 19 | client_body_in_file_only off; 20 | 21 | server_tokens off; 22 | max_ranges 1; 23 | 24 | include /etc/nginx/mime.types; 25 | default_type application/octet-stream; 26 | 27 | fastcgi_temp_file_write_size 20m; 28 | fastcgi_busy_buffers_size 786k; 29 | fastcgi_buffer_size 512k; 30 | fastcgi_buffers 16 512k; 31 | 32 | access_log {{ ACCESS_LOG }}; 33 | error_log {{ ERROR_LOG }} info; 34 | 35 | # should be enabled on gateway 36 | gzip off; 37 | 38 | server { 39 | listen 8080 default_server; 40 | root /var/www/riotkit; 41 | index index.html index.php; 42 | server_name _; 43 | 44 | index index.php; 45 | 46 | fastcgi_param GATEWAY_INTERFACE CGI/1.1; 47 | fastcgi_param SERVER_SOFTWARE Nginx; 48 | fastcgi_param QUERY_STRING $query_string; 49 | fastcgi_param REQUEST_METHOD $request_method; 50 | fastcgi_param CONTENT_TYPE $content_type; 51 | fastcgi_param CONTENT_LENGTH $content_length; 52 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 53 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 54 | fastcgi_param REQUEST_URI $request_uri; 55 | fastcgi_param DOCUMENT_URI $document_uri; 56 | fastcgi_param DOCUMENT_ROOT $document_root; 57 | fastcgi_param SERVER_PROTOCOL $server_protocol; 58 | fastcgi_param REMOTE_ADDR $remote_addr; 59 | fastcgi_param REMOTE_PORT $remote_port; 60 | fastcgi_param SERVER_ADDR $server_addr; 61 | fastcgi_param SERVER_PORT $server_port; 62 | fastcgi_param SERVER_NAME $server_name; 63 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 64 | 65 | 66 | set $path_info $fastcgi_path_info; 67 | fastcgi_param PATH_INFO $path_info; 68 | fastcgi_index index.php; 69 | fastcgi_read_timeout 60s; 70 | fastcgi_hide_header X-Powered-By; 71 | proxy_hide_header X-Powered-By; 72 | 73 | # https://ayrn.io/how-to-harden-nginx-security/ 74 | 75 | location ~* "(eval\(|shell_exec\(|exec\(|system\(unserialize\(|query\(|serialize\(|popen\(|pcntl_exec\(|passthru\(|require\(|include\(|require_once\(|include_once\(|create_function\(|proc_open\(|base64_decode\(|str_rot13\()" { return 416; } 76 | location ~* "(javascript:)(.*)(;)" { return 416; } 77 | location ~* "(GLOBALS|REQUEST)(=|\[|%)" { return 416; } 78 | 79 | ## 80 | # Block common exploits 81 | ## 82 | set $block_common_exploits 0; 83 | if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]{0,2})") { set $block_common_exploits 1; } 84 | if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2})") { set $block_common_exploits 1; } 85 | if ($query_string ~ "proc/self/environ") { set $block_common_exploits 1; } 86 | if ($query_string ~ "(eval\(|shell_exec\(|exec\(|system\(unserialize\(|query\(|serialize\(|popen\(|pcntl_exec\(|passthru\(|require\(|include\(|require_once\(|include_once\(|create_function\(|proc_open\(|base64_decode\(|str_rot13\()") { set $block_common_exploits 1; } 87 | if ($block_common_exploits = 1) { return 416; } 88 | 89 | location = /favicon.ico { 90 | log_not_found off; 91 | access_log off; 92 | } 93 | 94 | location = /robots.txt { 95 | allow all; 96 | log_not_found off; 97 | access_log off; 98 | } 99 | 100 | {% if BASIC_AUTH_ENABLED == "true" %} 101 | location ^~ /wp-login.php { 102 | auth_basic "Access secured"; 103 | auth_basic_user_file /opt/htpasswd; 104 | 105 | try_files $fastcgi_script_name =404; 106 | fastcgi_pass localhost:9000; 107 | 108 | break; 109 | } 110 | {% endif %} 111 | 112 | {% if XMLRPC_DISABLED == "true" %} 113 | location = /xmlrpc.php { 114 | allow 172.0.1.1; 115 | deny all; 116 | access_log off; 117 | log_not_found off; 118 | return 444; 119 | } 120 | {% endif %} 121 | 122 | {% if HEALTH_CHECK_ALLOWED_SUBNET %} 123 | location ^~ /readiness.php { 124 | allow {{ HEALTH_CHECK_ALLOWED_SUBNET }}; 125 | deny all; 126 | 127 | try_files $fastcgi_script_name =404; 128 | fastcgi_pass localhost:9000; 129 | break; 130 | } 131 | location ^~ /liveness.php { 132 | allow {{ HEALTH_CHECK_ALLOWED_SUBNET }}; 133 | deny all; 134 | 135 | try_files $fastcgi_script_name =404; 136 | fastcgi_pass localhost:9000; 137 | break; 138 | } 139 | {% endif %} 140 | 141 | {% if DISABLE_DIRECT_CONTENT_PHP_EXECUTION == "true" %} 142 | location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/.*.php$ { 143 | deny all; 144 | access_log off; 145 | log_not_found off; 146 | } 147 | {% endif %} 148 | 149 | # https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/ 150 | location ^~ /wp-content/aiowps_backups { 151 | deny all; 152 | } 153 | 154 | location ~ /\.(svn|git)/* { 155 | deny all; 156 | access_log off; 157 | log_not_found off; 158 | 159 | break; 160 | } 161 | location ~ /\.ht { 162 | deny all; 163 | access_log off; 164 | log_not_found off; 165 | 166 | break; 167 | } 168 | 169 | location / { 170 | # This is cool because no php is touched for static content. 171 | # include the "?$args" part so non-default permalinks doesn't break when using query string 172 | try_files $uri $uri/ /index.php?$args; 173 | } 174 | 175 | location ~ \.php$ { 176 | try_files $fastcgi_script_name =404; 177 | fastcgi_pass localhost:9000; 178 | } 179 | 180 | location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { 181 | expires max; 182 | log_not_found off; 183 | } 184 | 185 | location ~ /\.ht { 186 | deny all; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /container-files/install-plugins-first-time.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | installPlugins() { 4 | status=0 5 | 6 | IFS=, read -ra plugins <<< "${ENABLED_PLUGINS}" 7 | for plugin in "${plugins[@]}"; do 8 | echo " >> Installing plugin '${plugin}'" 9 | if ! wp plugin install "${plugin}" --activate; then 10 | status=1 11 | fi 12 | done 13 | 14 | return ${status} 15 | } 16 | 17 | if [[ "${1}" == "no-wait" ]]; then 18 | installPlugins 19 | else 20 | retryNum=0 21 | retryMaxNum=${WP_PLUGINS_REINSTALL_RETRIES} 22 | 23 | while [[ ! -f /var/www/riotkit/wp-content/.plugins-installed ]]; do 24 | if wp core is-installed; then 25 | if installPlugins; then 26 | echo " >> Plugins installed" 27 | break 28 | else 29 | if [[ "$retryNum" -gt "$retryMaxNum" ]]; then 30 | echo " >> Cannot install plugins - maximum retries of ${$retryMaxNum} exceeded" 31 | exit 1 32 | fi 33 | 34 | echo " !!! Plugins installation failed" 35 | retryNum=$((retryNum+1)) 36 | fi 37 | else 38 | echo " ... Waiting for Wordpress to be installed" 39 | fi 40 | 41 | sleep "${WP_INSTALLATION_WAIT_INTERVAL}" 42 | done 43 | 44 | echo ">> Plugins installed, fuckwork mode on" 45 | sleep 999999999 46 | fi 47 | -------------------------------------------------------------------------------- /container-files/usr/local/etc/php/php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | ;;;;;;;;;;;;;;;;;;; 4 | ; About php.ini ; 5 | ;;;;;;;;;;;;;;;;;;; 6 | ; PHP's initialization file, generally called php.ini, is responsible for 7 | ; configuring many of the aspects of PHP's behavior. 8 | 9 | ; PHP attempts to find and load this configuration from a number of locations. 10 | ; The following is a summary of its search order: 11 | ; 1. SAPI module specific location. 12 | ; 2. The PHPRC environment variable. (As of PHP 5.2.0) 13 | ; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) 14 | ; 4. Current working directory (except CLI) 15 | ; 5. The web server's directory (for SAPI modules), or directory of PHP 16 | ; (otherwise in Windows) 17 | ; 6. The directory from the --with-config-file-path compile time option, or the 18 | ; Windows directory (usually C:\windows) 19 | ; See the PHP docs for more specific information. 20 | ; http://php.net/configuration.file 21 | 22 | ; The syntax of the file is extremely simple. Whitespace and lines 23 | ; beginning with a semicolon are silently ignored (as you probably guessed). 24 | ; Section headers (e.g. [Foo]) are also silently ignored, even though 25 | ; they might mean something in the future. 26 | 27 | ; Directives following the section heading [PATH=/www/mysite] only 28 | ; apply to PHP files in the /www/mysite directory. Directives 29 | ; following the section heading [HOST=www.example.com] only apply to 30 | ; PHP files served from www.example.com. Directives set in these 31 | ; special sections cannot be overridden by user-defined INI files or 32 | ; at runtime. Currently, [PATH=] and [HOST=] sections only work under 33 | ; CGI/FastCGI. 34 | ; http://php.net/ini.sections 35 | 36 | ; Directives are specified using the following syntax: 37 | ; directive = value 38 | ; Directive names are *case sensitive* - foo=bar is different from FOO=bar. 39 | ; Directives are variables used to configure PHP or PHP extensions. 40 | ; There is no name validation. If PHP can't find an expected 41 | ; directive because it is not set or is mistyped, a default value will be used. 42 | 43 | ; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one 44 | ; of the INI constants (On, Off, True, False, Yes, No and None) or an expression 45 | ; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a 46 | ; previously set variable or directive (e.g. ${foo}) 47 | 48 | ; Expressions in the INI file are limited to bitwise operators and parentheses: 49 | ; | bitwise OR 50 | ; ^ bitwise XOR 51 | ; & bitwise AND 52 | ; ~ bitwise NOT 53 | ; ! boolean NOT 54 | 55 | ; Boolean flags can be turned on using the values 1, On, True or Yes. 56 | ; They can be turned off using the values 0, Off, False or No. 57 | 58 | ; An empty string can be denoted by simply not writing anything after the equal 59 | ; sign, or by using the None keyword: 60 | 61 | ; foo = ; sets foo to an empty string 62 | ; foo = None ; sets foo to an empty string 63 | ; foo = "None" ; sets foo to the string 'None' 64 | 65 | ; If you use constants in your value, and these constants belong to a 66 | ; dynamically loaded extension (either a PHP extension or a Zend extension), 67 | ; you may only use these constants *after* the line that loads the extension. 68 | 69 | ;;;;;;;;;;;;;;;;;;; 70 | ; About this file ; 71 | ;;;;;;;;;;;;;;;;;;; 72 | ; PHP comes packaged with two INI files. One that is recommended to be used 73 | ; in production environments and one that is recommended to be used in 74 | ; development environments. 75 | 76 | ; php.ini-production contains settings which hold security, performance and 77 | ; best practices at its core. But please be aware, these settings may break 78 | ; compatibility with older or less security conscience applications. We 79 | ; recommending using the production ini in production and testing environments. 80 | 81 | ; php.ini-development is very similar to its production variant, except it is 82 | ; much more verbose when it comes to errors. We recommend using the 83 | ; development version only in development environments, as errors shown to 84 | ; application users can inadvertently leak otherwise secure information. 85 | 86 | ; This is the php.ini-production INI file. 87 | 88 | ;;;;;;;;;;;;;;;;;;; 89 | ; Quick Reference ; 90 | ;;;;;;;;;;;;;;;;;;; 91 | ; The following are all the settings which are different in either the production 92 | ; or development versions of the INIs with respect to PHP's default behavior. 93 | ; Please see the actual settings later in the document for more details as to why 94 | ; we recommend these changes in PHP's behavior. 95 | 96 | ; display_errors 97 | ; Default Value: On 98 | ; Development Value: On 99 | ; Production Value: Off 100 | 101 | ; display_startup_errors 102 | ; Default Value: Off 103 | ; Development Value: On 104 | ; Production Value: Off 105 | 106 | ; error_reporting 107 | ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED 108 | ; Development Value: E_ALL 109 | ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT 110 | 111 | ; html_errors 112 | ; Default Value: On 113 | ; Development Value: On 114 | ; Production value: On 115 | 116 | ; log_errors 117 | ; Default Value: Off 118 | ; Development Value: On 119 | ; Production Value: On 120 | 121 | ; max_input_time 122 | ; Default Value: -1 (Unlimited) 123 | ; Development Value: 60 (60 seconds) 124 | ; Production Value: 60 (60 seconds) 125 | 126 | ; output_buffering 127 | ; Default Value: Off 128 | ; Development Value: 4096 129 | ; Production Value: 4096 130 | 131 | ; register_argc_argv 132 | ; Default Value: On 133 | ; Development Value: Off 134 | ; Production Value: Off 135 | 136 | ; request_order 137 | ; Default Value: None 138 | ; Development Value: "GP" 139 | ; Production Value: "GP" 140 | 141 | ; session.gc_divisor 142 | ; Default Value: 100 143 | ; Development Value: 1000 144 | ; Production Value: 1000 145 | 146 | ; session.sid_bits_per_character 147 | ; Default Value: 4 148 | ; Development Value: 5 149 | ; Production Value: 5 150 | 151 | ; short_open_tag 152 | ; Default Value: On 153 | ; Development Value: Off 154 | ; Production Value: Off 155 | 156 | ; variables_order 157 | ; Default Value: "EGPCS" 158 | ; Development Value: "GPCS" 159 | ; Production Value: "GPCS" 160 | 161 | ;;;;;;;;;;;;;;;;;;;; 162 | ; php.ini Options ; 163 | ;;;;;;;;;;;;;;;;;;;; 164 | ; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" 165 | ;user_ini.filename = ".user.ini" 166 | 167 | ; To disable this feature set this option to an empty value 168 | ;user_ini.filename = 169 | 170 | ; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) 171 | ;user_ini.cache_ttl = 300 172 | 173 | ;;;;;;;;;;;;;;;;;;;; 174 | ; Language Options ; 175 | ;;;;;;;;;;;;;;;;;;;; 176 | 177 | ; Enable the PHP scripting language engine under Apache. 178 | ; http://php.net/engine 179 | engine = On 180 | 181 | ; This directive determines whether or not PHP will recognize code between 182 | ; tags as PHP source which should be processed as such. It is 183 | ; generally recommended that should be used and that this feature 184 | ; should be disabled, as enabling it may result in issues when generating XML 185 | ; documents, however this remains supported for backward compatibility reasons. 186 | ; Note that this directive does not control the would work. 319 | ; http://php.net/syntax-highlighting 320 | ;highlight.string = #DD0000 321 | ;highlight.comment = #FF9900 322 | ;highlight.keyword = #007700 323 | ;highlight.default = #0000BB 324 | ;highlight.html = #000000 325 | 326 | ; If enabled, the request will be allowed to complete even if the user aborts 327 | ; the request. Consider enabling it if executing long requests, which may end up 328 | ; being interrupted by the user or a browser timing out. PHP's default behavior 329 | ; is to disable this feature. 330 | ; http://php.net/ignore-user-abort 331 | ;ignore_user_abort = On 332 | 333 | ; Determines the size of the realpath cache to be used by PHP. This value should 334 | ; be increased on systems where PHP opens many files to reflect the quantity of 335 | ; the file operations performed. 336 | ; Note: if open_basedir is set, the cache is disabled 337 | ; http://php.net/realpath-cache-size 338 | ;realpath_cache_size = 4096k 339 | 340 | ; Duration of time, in seconds for which to cache realpath information for a given 341 | ; file or directory. For systems with rarely changing files, consider increasing this 342 | ; value. 343 | ; http://php.net/realpath-cache-ttl 344 | ;realpath_cache_ttl = 120 345 | 346 | ; Enables or disables the circular reference collector. 347 | ; http://php.net/zend.enable-gc 348 | zend.enable_gc = On 349 | 350 | ; If enabled, scripts may be written in encodings that are incompatible with 351 | ; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such 352 | ; encodings. To use this feature, mbstring extension must be enabled. 353 | ; Default: Off 354 | ;zend.multibyte = Off 355 | 356 | ; Allows to set the default encoding for the scripts. This value will be used 357 | ; unless "declare(encoding=...)" directive appears at the top of the script. 358 | ; Only affects if zend.multibyte is set. 359 | ; Default: "" 360 | ;zend.script_encoding = 361 | 362 | ;;;;;;;;;;;;;;;;; 363 | ; Miscellaneous ; 364 | ;;;;;;;;;;;;;;;;; 365 | 366 | ; Decides whether PHP may expose the fact that it is installed on the server 367 | ; (e.g. by adding its signature to the Web server header). It is no security 368 | ; threat in any way, but it makes it possible to determine whether you use PHP 369 | ; on your server or not. 370 | ; http://php.net/expose-php 371 | expose_php = Off 372 | 373 | ;;;;;;;;;;;;;;;;;;; 374 | ; Resource Limits ; 375 | ;;;;;;;;;;;;;;;;;;; 376 | 377 | ; Maximum execution time of each script, in seconds 378 | ; http://php.net/max-execution-time 379 | ; Note: This directive is hardcoded to 0 for the CLI SAPI 380 | max_execution_time = 30 381 | 382 | ; Maximum amount of time each script may spend parsing request data. It's a good 383 | ; idea to limit this time on productions servers in order to eliminate unexpectedly 384 | ; long running scripts. 385 | ; Note: This directive is hardcoded to -1 for the CLI SAPI 386 | ; Default Value: -1 (Unlimited) 387 | ; Development Value: 60 (60 seconds) 388 | ; Production Value: 60 (60 seconds) 389 | ; http://php.net/max-input-time 390 | max_input_time = 60 391 | 392 | ; Maximum input variable nesting level 393 | ; http://php.net/max-input-nesting-level 394 | ;max_input_nesting_level = 64 395 | 396 | ; How many GET/POST/COOKIE input variables may be accepted 397 | ;max_input_vars = 1000 398 | 399 | ; Maximum amount of memory a script may consume (128MB) 400 | ; http://php.net/memory-limit 401 | memory_limit = {{ PHP_MEMORY_LIMIT }} 402 | 403 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 404 | ; Error handling and logging ; 405 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 406 | 407 | ; This directive informs PHP of which errors, warnings and notices you would like 408 | ; it to take action for. The recommended way of setting values for this 409 | ; directive is through the use of the error level constants and bitwise 410 | ; operators. The error level constants are below here for convenience as well as 411 | ; some common settings and their meanings. 412 | ; By default, PHP is set to take action on all errors, notices and warnings EXCEPT 413 | ; those related to E_NOTICE and E_STRICT, which together cover best practices and 414 | ; recommended coding standards in PHP. For performance reasons, this is the 415 | ; recommend error reporting setting. Your production server shouldn't be wasting 416 | ; resources complaining about best practices and coding standards. That's what 417 | ; development servers and development settings are for. 418 | ; Note: The php.ini-development file has this setting as E_ALL. This 419 | ; means it pretty much reports everything which is exactly what you want during 420 | ; development and early testing. 421 | ; 422 | ; Error Level Constants: 423 | ; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) 424 | ; E_ERROR - fatal run-time errors 425 | ; E_RECOVERABLE_ERROR - almost fatal run-time errors 426 | ; E_WARNING - run-time warnings (non-fatal errors) 427 | ; E_PARSE - compile-time parse errors 428 | ; E_NOTICE - run-time notices (these are warnings which often result 429 | ; from a bug in your code, but it's possible that it was 430 | ; intentional (e.g., using an uninitialized variable and 431 | ; relying on the fact it is automatically initialized to an 432 | ; empty string) 433 | ; E_STRICT - run-time notices, enable to have PHP suggest changes 434 | ; to your code which will ensure the best interoperability 435 | ; and forward compatibility of your code 436 | ; E_CORE_ERROR - fatal errors that occur during PHP's initial startup 437 | ; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's 438 | ; initial startup 439 | ; E_COMPILE_ERROR - fatal compile-time errors 440 | ; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) 441 | ; E_USER_ERROR - user-generated error message 442 | ; E_USER_WARNING - user-generated warning message 443 | ; E_USER_NOTICE - user-generated notice message 444 | ; E_DEPRECATED - warn about code that will not work in future versions 445 | ; of PHP 446 | ; E_USER_DEPRECATED - user-generated deprecation warnings 447 | ; 448 | ; Common Values: 449 | ; E_ALL (Show all errors, warnings and notices including coding standards.) 450 | ; E_ALL & ~E_NOTICE (Show all errors, except for notices) 451 | ; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) 452 | ; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) 453 | ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED 454 | ; Development Value: E_ALL 455 | ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT 456 | ; http://php.net/error-reporting 457 | error_reporting = {{ PHP_ERROR_REPORTING }} 458 | 459 | ; This directive controls whether or not and where PHP will output errors, 460 | ; notices and warnings too. Error output is very useful during development, but 461 | ; it could be very dangerous in production environments. Depending on the code 462 | ; which is triggering the error, sensitive information could potentially leak 463 | ; out of your application such as database usernames and passwords or worse. 464 | ; For production environments, we recommend logging errors rather than 465 | ; sending them to STDOUT. 466 | ; Possible Values: 467 | ; Off = Do not display any errors 468 | ; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) 469 | ; On or stdout = Display errors to STDOUT 470 | ; Default Value: On 471 | ; Development Value: On 472 | ; Production Value: Off 473 | ; http://php.net/display-errors 474 | display_errors = {{ PHP_DISPLAY_ERRORS }} 475 | 476 | ; The display of errors which occur during PHP's startup sequence are handled 477 | ; separately from display_errors. PHP's default behavior is to suppress those 478 | ; errors from clients. Turning the display of startup errors on can be useful in 479 | ; debugging configuration problems. We strongly recommend you 480 | ; set this to 'off' for production servers. 481 | ; Default Value: Off 482 | ; Development Value: On 483 | ; Production Value: Off 484 | ; http://php.net/display-startup-errors 485 | display_startup_errors = Off 486 | 487 | ; Besides displaying errors, PHP can also log errors to locations such as a 488 | ; server-specific log, STDERR, or a location specified by the error_log 489 | ; directive found below. While errors should not be displayed on productions 490 | ; servers they should still be monitored and logging is a great way to do that. 491 | ; Default Value: Off 492 | ; Development Value: On 493 | ; Production Value: On 494 | ; http://php.net/log-errors 495 | log_errors = On 496 | 497 | ; Set maximum length of log_errors. In error_log information about the source is 498 | ; added. The default is 1024 and 0 allows to not apply any maximum length at all. 499 | ; http://php.net/log-errors-max-len 500 | log_errors_max_len = 1024 501 | 502 | ; Do not log repeated messages. Repeated errors must occur in same file on same 503 | ; line unless ignore_repeated_source is set true. 504 | ; http://php.net/ignore-repeated-errors 505 | ignore_repeated_errors = Off 506 | 507 | ; Ignore source of message when ignoring repeated messages. When this setting 508 | ; is On you will not log errors with repeated messages from different files or 509 | ; source lines. 510 | ; http://php.net/ignore-repeated-source 511 | ignore_repeated_source = Off 512 | 513 | ; If this parameter is set to Off, then memory leaks will not be shown (on 514 | ; stdout or in the log). This has only effect in a debug compile, and if 515 | ; error reporting includes E_WARNING in the allowed list 516 | ; http://php.net/report-memleaks 517 | report_memleaks = On 518 | 519 | ; This setting is on by default. 520 | ;report_zend_debug = 0 521 | 522 | ; Store the last error/warning message in $php_errormsg (boolean). Setting this value 523 | ; to On can assist in debugging and is appropriate for development servers. It should 524 | ; however be disabled on production servers. 525 | ; This directive is DEPRECATED. 526 | ; Default Value: Off 527 | ; Development Value: Off 528 | ; Production Value: Off 529 | ; http://php.net/track-errors 530 | ;track_errors = Off 531 | 532 | ; Turn off normal error reporting and emit XML-RPC error XML 533 | ; http://php.net/xmlrpc-errors 534 | ;xmlrpc_errors = 0 535 | 536 | ; An XML-RPC faultCode 537 | ;xmlrpc_error_number = 0 538 | 539 | ; When PHP displays or logs an error, it has the capability of formatting the 540 | ; error message as HTML for easier reading. This directive controls whether 541 | ; the error message is formatted as HTML or not. 542 | ; Note: This directive is hardcoded to Off for the CLI SAPI 543 | ; Default Value: On 544 | ; Development Value: On 545 | ; Production value: On 546 | ; http://php.net/html-errors 547 | html_errors = On 548 | 549 | ; If html_errors is set to On *and* docref_root is not empty, then PHP 550 | ; produces clickable error messages that direct to a page describing the error 551 | ; or function causing the error in detail. 552 | ; You can download a copy of the PHP manual from http://php.net/docs 553 | ; and change docref_root to the base URL of your local copy including the 554 | ; leading '/'. You must also specify the file extension being used including 555 | ; the dot. PHP's default behavior is to leave these settings empty, in which 556 | ; case no links to documentation are generated. 557 | ; Note: Never use this feature for production boxes. 558 | ; http://php.net/docref-root 559 | ; Examples 560 | ;docref_root = "/phpmanual/" 561 | 562 | ; http://php.net/docref-ext 563 | ;docref_ext = .html 564 | 565 | ; String to output before an error message. PHP's default behavior is to leave 566 | ; this setting blank. 567 | ; http://php.net/error-prepend-string 568 | ; Example: 569 | ;error_prepend_string = "" 570 | 571 | ; String to output after an error message. PHP's default behavior is to leave 572 | ; this setting blank. 573 | ; http://php.net/error-append-string 574 | ; Example: 575 | ;error_append_string = "" 576 | 577 | ; Log errors to specified file. PHP's default behavior is to leave this value 578 | ; empty. 579 | ; http://php.net/error-log 580 | ; Example: 581 | ;error_log = php_errors.log 582 | ; Log errors to syslog (Event Log on Windows). 583 | ;error_log = syslog 584 | 585 | ; The syslog ident is a string which is prepended to every message logged 586 | ; to syslog. Only used when error_log is set to syslog. 587 | ;syslog.ident = php 588 | 589 | ; The syslog facility is used to specify what type of program is logging 590 | ; the message. Only used when error_log is set to syslog. 591 | ;syslog.facility = user 592 | 593 | ; Set this to disable filtering control characters (the default). 594 | ; Some loggers only accept NVT-ASCII, others accept anything that's not 595 | ; control characters. If your logger accepts everything, then no filtering 596 | ; is needed at all. 597 | ; Allowed values are: 598 | ; ascii (all printable ASCII characters and NL) 599 | ; no-ctrl (all characters except control characters) 600 | ; all (all characters) 601 | ; raw (like "all", but messages are not split at newlines) 602 | ; http://php.net/syslog.filter 603 | ;syslog.filter = ascii 604 | 605 | ;windows.show_crt_warning 606 | ; Default value: 0 607 | ; Development value: 0 608 | ; Production value: 0 609 | 610 | ;;;;;;;;;;;;;;;;; 611 | ; Data Handling ; 612 | ;;;;;;;;;;;;;;;;; 613 | 614 | ; The separator used in PHP generated URLs to separate arguments. 615 | ; PHP's default setting is "&". 616 | ; http://php.net/arg-separator.output 617 | ; Example: 618 | ;arg_separator.output = "&" 619 | 620 | ; List of separator(s) used by PHP to parse input URLs into variables. 621 | ; PHP's default setting is "&". 622 | ; NOTE: Every character in this directive is considered as separator! 623 | ; http://php.net/arg-separator.input 624 | ; Example: 625 | ;arg_separator.input = ";&" 626 | 627 | ; This directive determines which super global arrays are registered when PHP 628 | ; starts up. G,P,C,E & S are abbreviations for the following respective super 629 | ; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty 630 | ; paid for the registration of these arrays and because ENV is not as commonly 631 | ; used as the others, ENV is not recommended on productions servers. You 632 | ; can still get access to the environment variables through getenv() should you 633 | ; need to. 634 | ; Default Value: "EGPCS" 635 | ; Development Value: "GPCS" 636 | ; Production Value: "GPCS"; 637 | ; http://php.net/variables-order 638 | variables_order = "GPCS" 639 | 640 | ; This directive determines which super global data (G,P & C) should be 641 | ; registered into the super global array REQUEST. If so, it also determines 642 | ; the order in which that data is registered. The values for this directive 643 | ; are specified in the same manner as the variables_order directive, 644 | ; EXCEPT one. Leaving this value empty will cause PHP to use the value set 645 | ; in the variables_order directive. It does not mean it will leave the super 646 | ; globals array REQUEST empty. 647 | ; Default Value: None 648 | ; Development Value: "GP" 649 | ; Production Value: "GP" 650 | ; http://php.net/request-order 651 | request_order = "GP" 652 | 653 | ; This directive determines whether PHP registers $argv & $argc each time it 654 | ; runs. $argv contains an array of all the arguments passed to PHP when a script 655 | ; is invoked. $argc contains an integer representing the number of arguments 656 | ; that were passed when the script was invoked. These arrays are extremely 657 | ; useful when running scripts from the command line. When this directive is 658 | ; enabled, registering these variables consumes CPU cycles and memory each time 659 | ; a script is executed. For performance reasons, this feature should be disabled 660 | ; on production servers. 661 | ; Note: This directive is hardcoded to On for the CLI SAPI 662 | ; Default Value: On 663 | ; Development Value: Off 664 | ; Production Value: Off 665 | ; http://php.net/register-argc-argv 666 | register_argc_argv = Off 667 | 668 | ; When enabled, the ENV, REQUEST and SERVER variables are created when they're 669 | ; first used (Just In Time) instead of when the script starts. If these 670 | ; variables are not used within a script, having this directive on will result 671 | ; in a performance gain. The PHP directive register_argc_argv must be disabled 672 | ; for this directive to have any affect. 673 | ; http://php.net/auto-globals-jit 674 | auto_globals_jit = On 675 | 676 | ; Whether PHP will read the POST data. 677 | ; This option is enabled by default. 678 | ; Most likely, you won't want to disable this option globally. It causes $_POST 679 | ; and $_FILES to always be empty; the only way you will be able to read the 680 | ; POST data will be through the php://input stream wrapper. This can be useful 681 | ; to proxy requests or to process the POST data in a memory efficient fashion. 682 | ; http://php.net/enable-post-data-reading 683 | ;enable_post_data_reading = Off 684 | 685 | ; Maximum size of POST data that PHP will accept. 686 | ; Its value may be 0 to disable the limit. It is ignored if POST data reading 687 | ; is disabled through enable_post_data_reading. 688 | ; http://php.net/post-max-size 689 | post_max_size = {{ PHP_POST_MAX_SIZE }} 690 | 691 | ; Automatically add files before PHP document. 692 | ; http://php.net/auto-prepend-file 693 | auto_prepend_file = 694 | 695 | ; Automatically add files after PHP document. 696 | ; http://php.net/auto-append-file 697 | auto_append_file = 698 | 699 | ; By default, PHP will output a media type using the Content-Type header. To 700 | ; disable this, simply set it to be empty. 701 | ; 702 | ; PHP's built-in default media type is set to text/html. 703 | ; http://php.net/default-mimetype 704 | default_mimetype = "text/html" 705 | 706 | ; PHP's default character set is set to UTF-8. 707 | ; http://php.net/default-charset 708 | default_charset = "UTF-8" 709 | 710 | ; PHP internal character encoding is set to empty. 711 | ; If empty, default_charset is used. 712 | ; http://php.net/internal-encoding 713 | ;internal_encoding = 714 | 715 | ; PHP input character encoding is set to empty. 716 | ; If empty, default_charset is used. 717 | ; http://php.net/input-encoding 718 | ;input_encoding = 719 | 720 | ; PHP output character encoding is set to empty. 721 | ; If empty, default_charset is used. 722 | ; See also output_buffer. 723 | ; http://php.net/output-encoding 724 | ;output_encoding = 725 | 726 | ;;;;;;;;;;;;;;;;;;;;;;;;; 727 | ; Paths and Directories ; 728 | ;;;;;;;;;;;;;;;;;;;;;;;;; 729 | 730 | ; UNIX: "/path1:/path2" 731 | ;include_path = ".:/php/includes" 732 | ; 733 | ; Windows: "\path1;\path2" 734 | ;include_path = ".;c:\php\includes" 735 | ; 736 | ; PHP's default setting for include_path is ".;/path/to/php/pear" 737 | ; http://php.net/include-path 738 | 739 | ; The root of the PHP pages, used only if nonempty. 740 | ; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root 741 | ; if you are running php as a CGI under any web server (other than IIS) 742 | ; see documentation for security issues. The alternate is to use the 743 | ; cgi.force_redirect configuration below 744 | ; http://php.net/doc-root 745 | doc_root = 746 | 747 | ; The directory under which PHP opens the script using /~username used only 748 | ; if nonempty. 749 | ; http://php.net/user-dir 750 | user_dir = 751 | 752 | ; Directory in which the loadable extensions (modules) reside. 753 | ; http://php.net/extension-dir 754 | ;extension_dir = "./" 755 | ; On windows: 756 | ;extension_dir = "ext" 757 | 758 | ; Directory where the temporary files should be placed. 759 | ; Defaults to the system default (see sys_get_temp_dir) 760 | ;sys_temp_dir = "/tmp" 761 | 762 | ; Whether or not to enable the dl() function. The dl() function does NOT work 763 | ; properly in multithreaded servers, such as IIS or Zeus, and is automatically 764 | ; disabled on them. 765 | ; http://php.net/enable-dl 766 | enable_dl = Off 767 | 768 | ; cgi.force_redirect is necessary to provide security running PHP as a CGI under 769 | ; most web servers. Left undefined, PHP turns this on by default. You can 770 | ; turn it off here AT YOUR OWN RISK 771 | ; **You CAN safely turn this off for IIS, in fact, you MUST.** 772 | ; http://php.net/cgi.force-redirect 773 | ;cgi.force_redirect = 1 774 | 775 | ; if cgi.nph is enabled it will force cgi to always sent Status: 200 with 776 | ; every request. PHP's default behavior is to disable this feature. 777 | ;cgi.nph = 1 778 | 779 | ; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape 780 | ; (iPlanet) web servers, you MAY need to set an environment variable name that PHP 781 | ; will look for to know it is OK to continue execution. Setting this variable MAY 782 | ; cause security issues, KNOW WHAT YOU ARE DOING FIRST. 783 | ; http://php.net/cgi.redirect-status-env 784 | ;cgi.redirect_status_env = 785 | 786 | ; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's 787 | ; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok 788 | ; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting 789 | ; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting 790 | ; of zero causes PHP to behave as before. Default is 1. You should fix your scripts 791 | ; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. 792 | ; http://php.net/cgi.fix-pathinfo 793 | ;cgi.fix_pathinfo=1 794 | 795 | ; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside 796 | ; of the web tree and people will not be able to circumvent .htaccess security. 797 | ;cgi.discard_path=1 798 | 799 | ; FastCGI under IIS supports the ability to impersonate 800 | ; security tokens of the calling client. This allows IIS to define the 801 | ; security context that the request runs under. mod_fastcgi under Apache 802 | ; does not currently support this feature (03/17/2002) 803 | ; Set to 1 if running under IIS. Default is zero. 804 | ; http://php.net/fastcgi.impersonate 805 | ;fastcgi.impersonate = 1 806 | 807 | ; Disable logging through FastCGI connection. PHP's default behavior is to enable 808 | ; this feature. 809 | ;fastcgi.logging = 0 810 | 811 | ; cgi.rfc2616_headers configuration option tells PHP what type of headers to 812 | ; use when sending HTTP response code. If set to 0, PHP sends Status: header that 813 | ; is supported by Apache. When this option is set to 1, PHP will send 814 | ; RFC2616 compliant header. 815 | ; Default is zero. 816 | ; http://php.net/cgi.rfc2616-headers 817 | ;cgi.rfc2616_headers = 0 818 | 819 | ; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #! 820 | ; (shebang) at the top of the running script. This line might be needed if the 821 | ; script support running both as stand-alone script and via PHP CGI<. PHP in CGI 822 | ; mode skips this line and ignores its content if this directive is turned on. 823 | ; http://php.net/cgi.check-shebang-line 824 | ;cgi.check_shebang_line=1 825 | 826 | ;;;;;;;;;;;;;;;; 827 | ; File Uploads ; 828 | ;;;;;;;;;;;;;;;; 829 | 830 | ; Whether to allow HTTP file uploads. 831 | ; http://php.net/file-uploads 832 | file_uploads = On 833 | 834 | ; Temporary directory for HTTP uploaded files (will use system default if not 835 | ; specified). 836 | ; http://php.net/upload-tmp-dir 837 | ;upload_tmp_dir = 838 | 839 | ; Maximum allowed size for uploaded files. 840 | ; http://php.net/upload-max-filesize 841 | upload_max_filesize = {{ PHP_UPLOAD_MAX_FILESIZE }} 842 | 843 | ; Maximum number of files that can be uploaded via a single request 844 | max_file_uploads = 20 845 | 846 | ;;;;;;;;;;;;;;;;;; 847 | ; Fopen wrappers ; 848 | ;;;;;;;;;;;;;;;;;; 849 | 850 | ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. 851 | ; http://php.net/allow-url-fopen 852 | allow_url_fopen = On 853 | 854 | ; Whether to allow include/require to open URLs (like http:// or ftp://) as files. 855 | ; http://php.net/allow-url-include 856 | allow_url_include = Off 857 | 858 | ; Define the anonymous ftp password (your email address). PHP's default setting 859 | ; for this is empty. 860 | ; http://php.net/from 861 | ;from="john@doe.com" 862 | 863 | ; Define the User-Agent string. PHP's default setting for this is empty. 864 | ; http://php.net/user-agent 865 | ;user_agent="PHP" 866 | 867 | ; Default timeout for socket based streams (seconds) 868 | ; http://php.net/default-socket-timeout 869 | default_socket_timeout = 60 870 | 871 | ; If your scripts have to deal with files from Macintosh systems, 872 | ; or you are running on a Mac and need to deal with files from 873 | ; unix or win32 systems, setting this flag will cause PHP to 874 | ; automatically detect the EOL character in those files so that 875 | ; fgets() and file() will work regardless of the source of the file. 876 | ; http://php.net/auto-detect-line-endings 877 | ;auto_detect_line_endings = Off 878 | 879 | ;;;;;;;;;;;;;;;;;;;;;; 880 | ; Dynamic Extensions ; 881 | ;;;;;;;;;;;;;;;;;;;;;; 882 | 883 | ; If you wish to have an extension loaded automatically, use the following 884 | ; syntax: 885 | ; 886 | ; extension=modulename 887 | ; 888 | ; For example: 889 | ; 890 | ; extension=mysqli 891 | ; 892 | ; When the extension library to load is not located in the default extension 893 | ; directory, You may specify an absolute path to the library file: 894 | ; 895 | ; extension=/path/to/extension/mysqli.so 896 | ; 897 | ; Note : The syntax used in previous PHP versions ('extension=.so' and 898 | ; 'extension='php_.dll') is supported for legacy reasons and may be 899 | ; deprecated in a future PHP major version. So, when it is possible, please 900 | ; move to the new ('extension=) syntax. 901 | ; 902 | ; Notes for Windows environments : 903 | ; 904 | ; - Many DLL files are located in the extensions/ (PHP 4) or ext/ (PHP 5+) 905 | ; extension folders as well as the separate PECL DLL download (PHP 5+). 906 | ; Be sure to appropriately set the extension_dir directive. 907 | ; 908 | ;extension=bz2 909 | ;extension=curl 910 | ;extension=fileinfo 911 | ;extension=gd2 912 | ;extension=gettext 913 | ;extension=gmp 914 | ;extension=intl 915 | ;extension=imap 916 | ;extension=interbase 917 | ;extension=ldap 918 | ;extension=mbstring 919 | ;extension=exif ; Must be after mbstring as it depends on it 920 | ;extension=mysqli 921 | ;extension=oci8_12c ; Use with Oracle Database 12c Instant Client 922 | ;extension=odbc 923 | ;extension=openssl 924 | ;extension=pdo_firebird 925 | ;extension=pdo_mysql 926 | ;extension=pdo_oci 927 | ;extension=pdo_odbc 928 | ;extension=pdo_pgsql 929 | ;extension=pdo_sqlite 930 | ;extension=pgsql 931 | ;extension=shmop 932 | 933 | ; The MIBS data available in the PHP distribution must be installed. 934 | ; See http://www.php.net/manual/en/snmp.installation.php 935 | ;extension=snmp 936 | 937 | ;extension=soap 938 | ;extension=sockets 939 | ;extension=sodium 940 | ;extension=sqlite3 941 | ;extension=tidy 942 | ;extension=xmlrpc 943 | ;extension=xsl 944 | 945 | ;;;;;;;;;;;;;;;;;;; 946 | ; Module Settings ; 947 | ;;;;;;;;;;;;;;;;;;; 948 | 949 | [CLI Server] 950 | ; Whether the CLI web server uses ANSI color coding in its terminal output. 951 | cli_server.color = On 952 | 953 | [Date] 954 | ; Defines the default timezone used by the date functions 955 | ; http://php.net/date.timezone 956 | ;date.timezone = 957 | 958 | ; http://php.net/date.default-latitude 959 | ;date.default_latitude = 31.7667 960 | 961 | ; http://php.net/date.default-longitude 962 | ;date.default_longitude = 35.2333 963 | 964 | ; http://php.net/date.sunrise-zenith 965 | ;date.sunrise_zenith = 90.583333 966 | 967 | ; http://php.net/date.sunset-zenith 968 | ;date.sunset_zenith = 90.583333 969 | 970 | [filter] 971 | ; http://php.net/filter.default 972 | ;filter.default = unsafe_raw 973 | 974 | ; http://php.net/filter.default-flags 975 | ;filter.default_flags = 976 | 977 | [iconv] 978 | ; Use of this INI entry is deprecated, use global input_encoding instead. 979 | ; If empty, default_charset or input_encoding or iconv.input_encoding is used. 980 | ; The precedence is: default_charset < input_encoding < iconv.input_encoding 981 | ;iconv.input_encoding = 982 | 983 | ; Use of this INI entry is deprecated, use global internal_encoding instead. 984 | ; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. 985 | ; The precedence is: default_charset < internal_encoding < iconv.internal_encoding 986 | ;iconv.internal_encoding = 987 | 988 | ; Use of this INI entry is deprecated, use global output_encoding instead. 989 | ; If empty, default_charset or output_encoding or iconv.output_encoding is used. 990 | ; The precedence is: default_charset < output_encoding < iconv.output_encoding 991 | ; To use an output encoding conversion, iconv's output handler must be set 992 | ; otherwise output encoding conversion cannot be performed. 993 | ;iconv.output_encoding = 994 | 995 | [imap] 996 | ; rsh/ssh logins are disabled by default. Use this INI entry if you want to 997 | ; enable them. Note that the IMAP library does not filter mailbox names before 998 | ; passing them to rsh/ssh command, thus passing untrusted data to this function 999 | ; with rsh/ssh enabled is insecure. 1000 | ;imap.enable_insecure_rsh=0 1001 | 1002 | [intl] 1003 | ;intl.default_locale = 1004 | ; This directive allows you to produce PHP errors when some error 1005 | ; happens within intl functions. The value is the level of the error produced. 1006 | ; Default is 0, which does not produce any errors. 1007 | ;intl.error_level = E_WARNING 1008 | ;intl.use_exceptions = 0 1009 | 1010 | [sqlite3] 1011 | ; Directory pointing to SQLite3 extensions 1012 | ; http://php.net/sqlite3.extension-dir 1013 | ;sqlite3.extension_dir = 1014 | 1015 | ; SQLite defensive mode flag (only available from SQLite 3.26+) 1016 | ; When the defensive flag is enabled, language features that allow ordinary 1017 | ; SQL to deliberately corrupt the database file are disabled. This forbids 1018 | ; writing directly to the schema, shadow tables (eg. FTS data tables), or 1019 | ; the sqlite_dbpage virtual table. 1020 | ; https://www.sqlite.org/c3ref/c_dbconfig_defensive.html 1021 | ; (for older SQLite versions, this flag has no use) 1022 | ;sqlite3.defensive = 1 1023 | 1024 | [Pcre] 1025 | ; PCRE library backtracking limit. 1026 | ; http://php.net/pcre.backtrack-limit 1027 | ;pcre.backtrack_limit=100000 1028 | 1029 | ; PCRE library recursion limit. 1030 | ; Please note that if you set this value to a high number you may consume all 1031 | ; the available process stack and eventually crash PHP (due to reaching the 1032 | ; stack size limit imposed by the Operating System). 1033 | ; http://php.net/pcre.recursion-limit 1034 | ;pcre.recursion_limit=100000 1035 | 1036 | ; Enables or disables JIT compilation of patterns. This requires the PCRE 1037 | ; library to be compiled with JIT support. 1038 | ;pcre.jit=1 1039 | 1040 | [Pdo] 1041 | ; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" 1042 | ; http://php.net/pdo-odbc.connection-pooling 1043 | ;pdo_odbc.connection_pooling=strict 1044 | 1045 | ;pdo_odbc.db2_instance_name 1046 | 1047 | [Pdo_mysql] 1048 | ; Default socket name for local MySQL connects. If empty, uses the built-in 1049 | ; MySQL defaults. 1050 | pdo_mysql.default_socket= 1051 | 1052 | [Phar] 1053 | ; http://php.net/phar.readonly 1054 | ;phar.readonly = On 1055 | 1056 | ; http://php.net/phar.require-hash 1057 | ;phar.require_hash = On 1058 | 1059 | ;phar.cache_list = 1060 | 1061 | [mail function] 1062 | ; For Win32 only. 1063 | ; http://php.net/smtp 1064 | SMTP = localhost 1065 | ; http://php.net/smtp-port 1066 | smtp_port = 25 1067 | 1068 | ; For Win32 only. 1069 | ; http://php.net/sendmail-from 1070 | ;sendmail_from = me@example.com 1071 | 1072 | ; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). 1073 | ; http://php.net/sendmail-path 1074 | ;sendmail_path = 1075 | 1076 | ; Force the addition of the specified parameters to be passed as extra parameters 1077 | ; to the sendmail binary. These parameters will always replace the value of 1078 | ; the 5th parameter to mail(). 1079 | ;mail.force_extra_parameters = 1080 | 1081 | ; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename 1082 | mail.add_x_header = Off 1083 | 1084 | ; The path to a log file that will log all mail() calls. Log entries include 1085 | ; the full path of the script, line number, To address and headers. 1086 | ;mail.log = 1087 | ; Log mail to syslog (Event Log on Windows). 1088 | ;mail.log = syslog 1089 | 1090 | [ODBC] 1091 | ; http://php.net/odbc.default-db 1092 | ;odbc.default_db = Not yet implemented 1093 | 1094 | ; http://php.net/odbc.default-user 1095 | ;odbc.default_user = Not yet implemented 1096 | 1097 | ; http://php.net/odbc.default-pw 1098 | ;odbc.default_pw = Not yet implemented 1099 | 1100 | ; Controls the ODBC cursor model. 1101 | ; Default: SQL_CURSOR_STATIC (default). 1102 | ;odbc.default_cursortype 1103 | 1104 | ; Allow or prevent persistent links. 1105 | ; http://php.net/odbc.allow-persistent 1106 | odbc.allow_persistent = On 1107 | 1108 | ; Check that a connection is still valid before reuse. 1109 | ; http://php.net/odbc.check-persistent 1110 | odbc.check_persistent = On 1111 | 1112 | ; Maximum number of persistent links. -1 means no limit. 1113 | ; http://php.net/odbc.max-persistent 1114 | odbc.max_persistent = -1 1115 | 1116 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1117 | ; http://php.net/odbc.max-links 1118 | odbc.max_links = -1 1119 | 1120 | ; Handling of LONG fields. Returns number of bytes to variables. 0 means 1121 | ; passthru. 1122 | ; http://php.net/odbc.defaultlrl 1123 | odbc.defaultlrl = 4096 1124 | 1125 | ; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. 1126 | ; See the documentation on odbc_binmode and odbc_longreadlen for an explanation 1127 | ; of odbc.defaultlrl and odbc.defaultbinmode 1128 | ; http://php.net/odbc.defaultbinmode 1129 | odbc.defaultbinmode = 1 1130 | 1131 | [Interbase] 1132 | ; Allow or prevent persistent links. 1133 | ibase.allow_persistent = 1 1134 | 1135 | ; Maximum number of persistent links. -1 means no limit. 1136 | ibase.max_persistent = -1 1137 | 1138 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1139 | ibase.max_links = -1 1140 | 1141 | ; Default database name for ibase_connect(). 1142 | ;ibase.default_db = 1143 | 1144 | ; Default username for ibase_connect(). 1145 | ;ibase.default_user = 1146 | 1147 | ; Default password for ibase_connect(). 1148 | ;ibase.default_password = 1149 | 1150 | ; Default charset for ibase_connect(). 1151 | ;ibase.default_charset = 1152 | 1153 | ; Default timestamp format. 1154 | ibase.timestampformat = "%Y-%m-%d %H:%M:%S" 1155 | 1156 | ; Default date format. 1157 | ibase.dateformat = "%Y-%m-%d" 1158 | 1159 | ; Default time format. 1160 | ibase.timeformat = "%H:%M:%S" 1161 | 1162 | [MySQLi] 1163 | 1164 | ; Maximum number of persistent links. -1 means no limit. 1165 | ; http://php.net/mysqli.max-persistent 1166 | mysqli.max_persistent = -1 1167 | 1168 | ; Allow accessing, from PHP's perspective, local files with LOAD DATA statements 1169 | ; http://php.net/mysqli.allow_local_infile 1170 | ;mysqli.allow_local_infile = On 1171 | 1172 | ; Allow or prevent persistent links. 1173 | ; http://php.net/mysqli.allow-persistent 1174 | mysqli.allow_persistent = On 1175 | 1176 | ; Maximum number of links. -1 means no limit. 1177 | ; http://php.net/mysqli.max-links 1178 | mysqli.max_links = -1 1179 | 1180 | ; Default port number for mysqli_connect(). If unset, mysqli_connect() will use 1181 | ; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the 1182 | ; compile-time value defined MYSQL_PORT (in that order). Win32 will only look 1183 | ; at MYSQL_PORT. 1184 | ; http://php.net/mysqli.default-port 1185 | mysqli.default_port = 3306 1186 | 1187 | ; Default socket name for local MySQL connects. If empty, uses the built-in 1188 | ; MySQL defaults. 1189 | ; http://php.net/mysqli.default-socket 1190 | mysqli.default_socket = 1191 | 1192 | ; Default host for mysql_connect() (doesn't apply in safe mode). 1193 | ; http://php.net/mysqli.default-host 1194 | mysqli.default_host = 1195 | 1196 | ; Default user for mysql_connect() (doesn't apply in safe mode). 1197 | ; http://php.net/mysqli.default-user 1198 | mysqli.default_user = 1199 | 1200 | ; Default password for mysqli_connect() (doesn't apply in safe mode). 1201 | ; Note that this is generally a *bad* idea to store passwords in this file. 1202 | ; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") 1203 | ; and reveal this password! And of course, any users with read access to this 1204 | ; file will be able to reveal the password as well. 1205 | ; http://php.net/mysqli.default-pw 1206 | mysqli.default_pw = 1207 | 1208 | ; Allow or prevent reconnect 1209 | mysqli.reconnect = Off 1210 | 1211 | [mysqlnd] 1212 | ; Enable / Disable collection of general statistics by mysqlnd which can be 1213 | ; used to tune and monitor MySQL operations. 1214 | mysqlnd.collect_statistics = On 1215 | 1216 | ; Enable / Disable collection of memory usage statistics by mysqlnd which can be 1217 | ; used to tune and monitor MySQL operations. 1218 | mysqlnd.collect_memory_statistics = Off 1219 | 1220 | ; Records communication from all extensions using mysqlnd to the specified log 1221 | ; file. 1222 | ; http://php.net/mysqlnd.debug 1223 | ;mysqlnd.debug = 1224 | 1225 | ; Defines which queries will be logged. 1226 | ;mysqlnd.log_mask = 0 1227 | 1228 | ; Default size of the mysqlnd memory pool, which is used by result sets. 1229 | ;mysqlnd.mempool_default_size = 16000 1230 | 1231 | ; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. 1232 | ;mysqlnd.net_cmd_buffer_size = 2048 1233 | 1234 | ; Size of a pre-allocated buffer used for reading data sent by the server in 1235 | ; bytes. 1236 | ;mysqlnd.net_read_buffer_size = 32768 1237 | 1238 | ; Timeout for network requests in seconds. 1239 | ;mysqlnd.net_read_timeout = 31536000 1240 | 1241 | ; SHA-256 Authentication Plugin related. File with the MySQL server public RSA 1242 | ; key. 1243 | ;mysqlnd.sha256_server_public_key = 1244 | 1245 | [OCI8] 1246 | 1247 | ; Connection: Enables privileged connections using external 1248 | ; credentials (OCI_SYSOPER, OCI_SYSDBA) 1249 | ; http://php.net/oci8.privileged-connect 1250 | ;oci8.privileged_connect = Off 1251 | 1252 | ; Connection: The maximum number of persistent OCI8 connections per 1253 | ; process. Using -1 means no limit. 1254 | ; http://php.net/oci8.max-persistent 1255 | ;oci8.max_persistent = -1 1256 | 1257 | ; Connection: The maximum number of seconds a process is allowed to 1258 | ; maintain an idle persistent connection. Using -1 means idle 1259 | ; persistent connections will be maintained forever. 1260 | ; http://php.net/oci8.persistent-timeout 1261 | ;oci8.persistent_timeout = -1 1262 | 1263 | ; Connection: The number of seconds that must pass before issuing a 1264 | ; ping during oci_pconnect() to check the connection validity. When 1265 | ; set to 0, each oci_pconnect() will cause a ping. Using -1 disables 1266 | ; pings completely. 1267 | ; http://php.net/oci8.ping-interval 1268 | ;oci8.ping_interval = 60 1269 | 1270 | ; Connection: Set this to a user chosen connection class to be used 1271 | ; for all pooled server requests with Oracle 11g Database Resident 1272 | ; Connection Pooling (DRCP). To use DRCP, this value should be set to 1273 | ; the same string for all web servers running the same application, 1274 | ; the database pool must be configured, and the connection string must 1275 | ; specify to use a pooled server. 1276 | ;oci8.connection_class = 1277 | 1278 | ; High Availability: Using On lets PHP receive Fast Application 1279 | ; Notification (FAN) events generated when a database node fails. The 1280 | ; database must also be configured to post FAN events. 1281 | ;oci8.events = Off 1282 | 1283 | ; Tuning: This option enables statement caching, and specifies how 1284 | ; many statements to cache. Using 0 disables statement caching. 1285 | ; http://php.net/oci8.statement-cache-size 1286 | ;oci8.statement_cache_size = 20 1287 | 1288 | ; Tuning: Enables statement prefetching and sets the default number of 1289 | ; rows that will be fetched automatically after statement execution. 1290 | ; http://php.net/oci8.default-prefetch 1291 | ;oci8.default_prefetch = 100 1292 | 1293 | ; Compatibility. Using On means oci_close() will not close 1294 | ; oci_connect() and oci_new_connect() connections. 1295 | ; http://php.net/oci8.old-oci-close-semantics 1296 | ;oci8.old_oci_close_semantics = Off 1297 | 1298 | [PostgreSQL] 1299 | ; Allow or prevent persistent links. 1300 | ; http://php.net/pgsql.allow-persistent 1301 | pgsql.allow_persistent = On 1302 | 1303 | ; Detect broken persistent links always with pg_pconnect(). 1304 | ; Auto reset feature requires a little overheads. 1305 | ; http://php.net/pgsql.auto-reset-persistent 1306 | pgsql.auto_reset_persistent = Off 1307 | 1308 | ; Maximum number of persistent links. -1 means no limit. 1309 | ; http://php.net/pgsql.max-persistent 1310 | pgsql.max_persistent = -1 1311 | 1312 | ; Maximum number of links (persistent+non persistent). -1 means no limit. 1313 | ; http://php.net/pgsql.max-links 1314 | pgsql.max_links = -1 1315 | 1316 | ; Ignore PostgreSQL backends Notice message or not. 1317 | ; Notice message logging require a little overheads. 1318 | ; http://php.net/pgsql.ignore-notice 1319 | pgsql.ignore_notice = 0 1320 | 1321 | ; Log PostgreSQL backends Notice message or not. 1322 | ; Unless pgsql.ignore_notice=0, module cannot log notice message. 1323 | ; http://php.net/pgsql.log-notice 1324 | pgsql.log_notice = 0 1325 | 1326 | [bcmath] 1327 | ; Number of decimal digits for all bcmath functions. 1328 | ; http://php.net/bcmath.scale 1329 | bcmath.scale = 0 1330 | 1331 | [browscap] 1332 | ; http://php.net/browscap 1333 | ;browscap = extra/browscap.ini 1334 | 1335 | [Session] 1336 | ; Handler used to store/retrieve data. 1337 | ; http://php.net/session.save-handler 1338 | session.save_handler = files 1339 | 1340 | ; Argument passed to save_handler. In the case of files, this is the path 1341 | ; where data files are stored. Note: Windows users have to change this 1342 | ; variable in order to use PHP's session functions. 1343 | ; 1344 | ; The path can be defined as: 1345 | ; 1346 | ; session.save_path = "N;/path" 1347 | ; 1348 | ; where N is an integer. Instead of storing all the session files in 1349 | ; /path, what this will do is use subdirectories N-levels deep, and 1350 | ; store the session data in those directories. This is useful if 1351 | ; your OS has problems with many files in one directory, and is 1352 | ; a more efficient layout for servers that handle many sessions. 1353 | ; 1354 | ; NOTE 1: PHP will not create this directory structure automatically. 1355 | ; You can use the script in the ext/session dir for that purpose. 1356 | ; NOTE 2: See the section on garbage collection below if you choose to 1357 | ; use subdirectories for session storage 1358 | ; 1359 | ; The file storage module creates files using mode 600 by default. 1360 | ; You can change that by using 1361 | ; 1362 | ; session.save_path = "N;MODE;/path" 1363 | ; 1364 | ; where MODE is the octal representation of the mode. Note that this 1365 | ; does not overwrite the process's umask. 1366 | ; http://php.net/session.save-path 1367 | ;session.save_path = "/tmp" 1368 | 1369 | ; Whether to use strict session mode. 1370 | ; Strict session mode does not accept an uninitialized session ID, and 1371 | ; regenerates the session ID if the browser sends an uninitialized session ID. 1372 | ; Strict mode protects applications from session fixation via a session adoption 1373 | ; vulnerability. It is disabled by default for maximum compatibility, but 1374 | ; enabling it is encouraged. 1375 | ; https://wiki.php.net/rfc/strict_sessions 1376 | session.use_strict_mode = 0 1377 | 1378 | ; Whether to use cookies. 1379 | ; http://php.net/session.use-cookies 1380 | session.use_cookies = 1 1381 | 1382 | ; http://php.net/session.cookie-secure 1383 | ;session.cookie_secure = 1384 | 1385 | ; This option forces PHP to fetch and use a cookie for storing and maintaining 1386 | ; the session id. We encourage this operation as it's very helpful in combating 1387 | ; session hijacking when not specifying and managing your own session id. It is 1388 | ; not the be-all and end-all of session hijacking defense, but it's a good start. 1389 | ; http://php.net/session.use-only-cookies 1390 | session.use_only_cookies = 1 1391 | 1392 | ; Name of the session (used as cookie name). 1393 | ; http://php.net/session.name 1394 | session.name = PHPSESSID 1395 | 1396 | ; Initialize session on request startup. 1397 | ; http://php.net/session.auto-start 1398 | session.auto_start = 0 1399 | 1400 | ; Lifetime in seconds of cookie or, if 0, until browser is restarted. 1401 | ; http://php.net/session.cookie-lifetime 1402 | session.cookie_lifetime = 0 1403 | 1404 | ; The path for which the cookie is valid. 1405 | ; http://php.net/session.cookie-path 1406 | session.cookie_path = / 1407 | 1408 | ; The domain for which the cookie is valid. 1409 | ; http://php.net/session.cookie-domain 1410 | session.cookie_domain = 1411 | 1412 | ; Whether or not to add the httpOnly flag to the cookie, which makes it 1413 | ; inaccessible to browser scripting languages such as JavaScript. 1414 | ; http://php.net/session.cookie-httponly 1415 | session.cookie_httponly = 1416 | 1417 | ; Add SameSite attribute to cookie to help mitigate Cross-Site Request Forgery (CSRF/XSRF) 1418 | ; Current valid values are "Strict", "Lax" or "None". When using "None", 1419 | ; make sure to include the quotes, as `none` is interpreted like `false` in ini files. 1420 | ; https://tools.ietf.org/html/draft-west-first-party-cookies-07 1421 | session.cookie_samesite = 1422 | 1423 | ; Handler used to serialize data. php is the standard serializer of PHP. 1424 | ; http://php.net/session.serialize-handler 1425 | session.serialize_handler = php 1426 | 1427 | ; Defines the probability that the 'garbage collection' process is started on every 1428 | ; session initialization. The probability is calculated by using gc_probability/gc_divisor, 1429 | ; e.g. 1/100 means there is a 1% chance that the GC process starts on each request. 1430 | ; Default Value: 1 1431 | ; Development Value: 1 1432 | ; Production Value: 1 1433 | ; http://php.net/session.gc-probability 1434 | session.gc_probability = 1 1435 | 1436 | ; Defines the probability that the 'garbage collection' process is started on every 1437 | ; session initialization. The probability is calculated by using gc_probability/gc_divisor, 1438 | ; e.g. 1/100 means there is a 1% chance that the GC process starts on each request. 1439 | ; For high volume production servers, using a value of 1000 is a more efficient approach. 1440 | ; Default Value: 100 1441 | ; Development Value: 1000 1442 | ; Production Value: 1000 1443 | ; http://php.net/session.gc-divisor 1444 | session.gc_divisor = 1000 1445 | 1446 | ; After this number of seconds, stored data will be seen as 'garbage' and 1447 | ; cleaned up by the garbage collection process. 1448 | ; http://php.net/session.gc-maxlifetime 1449 | session.gc_maxlifetime = 1440 1450 | 1451 | ; NOTE: If you are using the subdirectory option for storing session files 1452 | ; (see session.save_path above), then garbage collection does *not* 1453 | ; happen automatically. You will need to do your own garbage 1454 | ; collection through a shell script, cron entry, or some other method. 1455 | ; For example, the following script is the equivalent of setting 1456 | ; session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): 1457 | ; find /path/to/sessions -cmin +24 -type f | xargs rm 1458 | 1459 | ; Check HTTP Referer to invalidate externally stored URLs containing ids. 1460 | ; HTTP_REFERER has to contain this substring for the session to be 1461 | ; considered as valid. 1462 | ; http://php.net/session.referer-check 1463 | session.referer_check = 1464 | 1465 | ; Set to {nocache,private,public,} to determine HTTP caching aspects 1466 | ; or leave this empty to avoid sending anti-caching headers. 1467 | ; http://php.net/session.cache-limiter 1468 | session.cache_limiter = nocache 1469 | 1470 | ; Document expires after n minutes. 1471 | ; http://php.net/session.cache-expire 1472 | session.cache_expire = 180 1473 | 1474 | ; trans sid support is disabled by default. 1475 | ; Use of trans sid may risk your users' security. 1476 | ; Use this option with caution. 1477 | ; - User may send URL contains active session ID 1478 | ; to other person via. email/irc/etc. 1479 | ; - URL that contains active session ID may be stored 1480 | ; in publicly accessible computer. 1481 | ; - User may access your site with the same session ID 1482 | ; always using URL stored in browser's history or bookmarks. 1483 | ; http://php.net/session.use-trans-sid 1484 | session.use_trans_sid = 0 1485 | 1486 | ; Set session ID character length. This value could be between 22 to 256. 1487 | ; Shorter length than default is supported only for compatibility reason. 1488 | ; Users should use 32 or more chars. 1489 | ; http://php.net/session.sid-length 1490 | ; Default Value: 32 1491 | ; Development Value: 26 1492 | ; Production Value: 26 1493 | session.sid_length = 26 1494 | 1495 | ; The URL rewriter will look for URLs in a defined set of HTML tags. 1496 | ;
is special; if you include them here, the rewriter will 1497 | ; add a hidden field with the info which is otherwise appended 1498 | ; to URLs. tag's action attribute URL will not be modified 1499 | ; unless it is specified. 1500 | ; Note that all valid entries require a "=", even if no value follows. 1501 | ; Default Value: "a=href,area=href,frame=src,form=" 1502 | ; Development Value: "a=href,area=href,frame=src,form=" 1503 | ; Production Value: "a=href,area=href,frame=src,form=" 1504 | ; http://php.net/url-rewriter.tags 1505 | session.trans_sid_tags = "a=href,area=href,frame=src,form=" 1506 | 1507 | ; URL rewriter does not rewrite absolute URLs by default. 1508 | ; To enable rewrites for absolute paths, target hosts must be specified 1509 | ; at RUNTIME. i.e. use ini_set() 1510 | ; tags is special. PHP will check action attribute's URL regardless 1511 | ; of session.trans_sid_tags setting. 1512 | ; If no host is defined, HTTP_HOST will be used for allowed host. 1513 | ; Example value: php.net,www.php.net,wiki.php.net 1514 | ; Use "," for multiple hosts. No spaces are allowed. 1515 | ; Default Value: "" 1516 | ; Development Value: "" 1517 | ; Production Value: "" 1518 | ;session.trans_sid_hosts="" 1519 | 1520 | ; Define how many bits are stored in each character when converting 1521 | ; the binary hash data to something readable. 1522 | ; Possible values: 1523 | ; 4 (4 bits: 0-9, a-f) 1524 | ; 5 (5 bits: 0-9, a-v) 1525 | ; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") 1526 | ; Default Value: 4 1527 | ; Development Value: 5 1528 | ; Production Value: 5 1529 | ; http://php.net/session.hash-bits-per-character 1530 | session.sid_bits_per_character = 5 1531 | 1532 | ; Enable upload progress tracking in $_SESSION 1533 | ; Default Value: On 1534 | ; Development Value: On 1535 | ; Production Value: On 1536 | ; http://php.net/session.upload-progress.enabled 1537 | ;session.upload_progress.enabled = On 1538 | 1539 | ; Cleanup the progress information as soon as all POST data has been read 1540 | ; (i.e. upload completed). 1541 | ; Default Value: On 1542 | ; Development Value: On 1543 | ; Production Value: On 1544 | ; http://php.net/session.upload-progress.cleanup 1545 | ;session.upload_progress.cleanup = On 1546 | 1547 | ; A prefix used for the upload progress key in $_SESSION 1548 | ; Default Value: "upload_progress_" 1549 | ; Development Value: "upload_progress_" 1550 | ; Production Value: "upload_progress_" 1551 | ; http://php.net/session.upload-progress.prefix 1552 | ;session.upload_progress.prefix = "upload_progress_" 1553 | 1554 | ; The index name (concatenated with the prefix) in $_SESSION 1555 | ; containing the upload progress information 1556 | ; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" 1557 | ; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" 1558 | ; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" 1559 | ; http://php.net/session.upload-progress.name 1560 | ;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" 1561 | 1562 | ; How frequently the upload progress should be updated. 1563 | ; Given either in percentages (per-file), or in bytes 1564 | ; Default Value: "1%" 1565 | ; Development Value: "1%" 1566 | ; Production Value: "1%" 1567 | ; http://php.net/session.upload-progress.freq 1568 | ;session.upload_progress.freq = "1%" 1569 | 1570 | ; The minimum delay between updates, in seconds 1571 | ; Default Value: 1 1572 | ; Development Value: 1 1573 | ; Production Value: 1 1574 | ; http://php.net/session.upload-progress.min-freq 1575 | ;session.upload_progress.min_freq = "1" 1576 | 1577 | ; Only write session data when session data is changed. Enabled by default. 1578 | ; http://php.net/session.lazy-write 1579 | ;session.lazy_write = On 1580 | 1581 | [Assertion] 1582 | ; Switch whether to compile assertions at all (to have no overhead at run-time) 1583 | ; -1: Do not compile at all 1584 | ; 0: Jump over assertion at run-time 1585 | ; 1: Execute assertions 1586 | ; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) 1587 | ; Default Value: 1 1588 | ; Development Value: 1 1589 | ; Production Value: -1 1590 | ; http://php.net/zend.assertions 1591 | zend.assertions = -1 1592 | 1593 | ; Assert(expr); active by default. 1594 | ; http://php.net/assert.active 1595 | ;assert.active = On 1596 | 1597 | ; Throw an AssertionError on failed assertions 1598 | ; http://php.net/assert.exception 1599 | ;assert.exception = On 1600 | 1601 | ; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) 1602 | ; http://php.net/assert.warning 1603 | ;assert.warning = On 1604 | 1605 | ; Don't bail out by default. 1606 | ; http://php.net/assert.bail 1607 | ;assert.bail = Off 1608 | 1609 | ; User-function to be called if an assertion fails. 1610 | ; http://php.net/assert.callback 1611 | ;assert.callback = 0 1612 | 1613 | ; Eval the expression with current error_reporting(). Set to true if you want 1614 | ; error_reporting(0) around the eval(). 1615 | ; http://php.net/assert.quiet-eval 1616 | ;assert.quiet_eval = 0 1617 | 1618 | [COM] 1619 | ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs 1620 | ; http://php.net/com.typelib-file 1621 | ;com.typelib_file = 1622 | 1623 | ; allow Distributed-COM calls 1624 | ; http://php.net/com.allow-dcom 1625 | ;com.allow_dcom = true 1626 | 1627 | ; autoregister constants of a component's typlib on com_load() 1628 | ; http://php.net/com.autoregister-typelib 1629 | ;com.autoregister_typelib = true 1630 | 1631 | ; register constants casesensitive 1632 | ; http://php.net/com.autoregister-casesensitive 1633 | ;com.autoregister_casesensitive = false 1634 | 1635 | ; show warnings on duplicate constant registrations 1636 | ; http://php.net/com.autoregister-verbose 1637 | ;com.autoregister_verbose = true 1638 | 1639 | ; The default character set code-page to use when passing strings to and from COM objects. 1640 | ; Default: system ANSI code page 1641 | ;com.code_page= 1642 | 1643 | [mbstring] 1644 | ; language for internal character representation. 1645 | ; This affects mb_send_mail() and mbstring.detect_order. 1646 | ; http://php.net/mbstring.language 1647 | ;mbstring.language = Japanese 1648 | 1649 | ; Use of this INI entry is deprecated, use global internal_encoding instead. 1650 | ; internal/script encoding. 1651 | ; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) 1652 | ; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. 1653 | ; The precedence is: default_charset < internal_encoding < iconv.internal_encoding 1654 | ;mbstring.internal_encoding = 1655 | 1656 | ; Use of this INI entry is deprecated, use global input_encoding instead. 1657 | ; http input encoding. 1658 | ; mbstring.encoding_translation = On is needed to use this setting. 1659 | ; If empty, default_charset or input_encoding or mbstring.input is used. 1660 | ; The precedence is: default_charset < input_encoding < mbsting.http_input 1661 | ; http://php.net/mbstring.http-input 1662 | ;mbstring.http_input = 1663 | 1664 | ; Use of this INI entry is deprecated, use global output_encoding instead. 1665 | ; http output encoding. 1666 | ; mb_output_handler must be registered as output buffer to function. 1667 | ; If empty, default_charset or output_encoding or mbstring.http_output is used. 1668 | ; The precedence is: default_charset < output_encoding < mbstring.http_output 1669 | ; To use an output encoding conversion, mbstring's output handler must be set 1670 | ; otherwise output encoding conversion cannot be performed. 1671 | ; http://php.net/mbstring.http-output 1672 | ;mbstring.http_output = 1673 | 1674 | ; enable automatic encoding translation according to 1675 | ; mbstring.internal_encoding setting. Input chars are 1676 | ; converted to internal encoding by setting this to On. 1677 | ; Note: Do _not_ use automatic encoding translation for 1678 | ; portable libs/applications. 1679 | ; http://php.net/mbstring.encoding-translation 1680 | ;mbstring.encoding_translation = Off 1681 | 1682 | ; automatic encoding detection order. 1683 | ; "auto" detect order is changed according to mbstring.language 1684 | ; http://php.net/mbstring.detect-order 1685 | ;mbstring.detect_order = auto 1686 | 1687 | ; substitute_character used when character cannot be converted 1688 | ; one from another 1689 | ; http://php.net/mbstring.substitute-character 1690 | ;mbstring.substitute_character = none 1691 | 1692 | ; overload(replace) single byte functions by mbstring functions. 1693 | ; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), 1694 | ; etc. Possible values are 0,1,2,4 or combination of them. 1695 | ; For example, 7 for overload everything. 1696 | ; 0: No overload 1697 | ; 1: Overload mail() function 1698 | ; 2: Overload str*() functions 1699 | ; 4: Overload ereg*() functions 1700 | ; http://php.net/mbstring.func-overload 1701 | ;mbstring.func_overload = 0 1702 | 1703 | ; enable strict encoding detection. 1704 | ; Default: Off 1705 | ;mbstring.strict_detection = On 1706 | 1707 | ; This directive specifies the regex pattern of content types for which mb_output_handler() 1708 | ; is activated. 1709 | ; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) 1710 | ;mbstring.http_output_conv_mimetype= 1711 | 1712 | ; This directive specifies maximum stack depth for mbstring regular expressions. It is similar 1713 | ; to the pcre.recursion_limit for PCRE. 1714 | ; Default: 100000 1715 | ;mbstring.regex_stack_limit=100000 1716 | 1717 | [gd] 1718 | ; Tell the jpeg decode to ignore warnings and try to create 1719 | ; a gd image. The warning will then be displayed as notices 1720 | ; disabled by default 1721 | ; http://php.net/gd.jpeg-ignore-warning 1722 | ;gd.jpeg_ignore_warning = 1 1723 | 1724 | [exif] 1725 | ; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. 1726 | ; With mbstring support this will automatically be converted into the encoding 1727 | ; given by corresponding encode setting. When empty mbstring.internal_encoding 1728 | ; is used. For the decode settings you can distinguish between motorola and 1729 | ; intel byte order. A decode setting cannot be empty. 1730 | ; http://php.net/exif.encode-unicode 1731 | ;exif.encode_unicode = ISO-8859-15 1732 | 1733 | ; http://php.net/exif.decode-unicode-motorola 1734 | ;exif.decode_unicode_motorola = UCS-2BE 1735 | 1736 | ; http://php.net/exif.decode-unicode-intel 1737 | ;exif.decode_unicode_intel = UCS-2LE 1738 | 1739 | ; http://php.net/exif.encode-jis 1740 | ;exif.encode_jis = 1741 | 1742 | ; http://php.net/exif.decode-jis-motorola 1743 | ;exif.decode_jis_motorola = JIS 1744 | 1745 | ; http://php.net/exif.decode-jis-intel 1746 | ;exif.decode_jis_intel = JIS 1747 | 1748 | [Tidy] 1749 | ; The path to a default tidy configuration file to use when using tidy 1750 | ; http://php.net/tidy.default-config 1751 | ;tidy.default_config = /usr/local/lib/php/default.tcfg 1752 | 1753 | ; Should tidy clean and repair output automatically? 1754 | ; WARNING: Do not use this option if you are generating non-html content 1755 | ; such as dynamic images 1756 | ; http://php.net/tidy.clean-output 1757 | tidy.clean_output = Off 1758 | 1759 | [soap] 1760 | ; Enables or disables WSDL caching feature. 1761 | ; http://php.net/soap.wsdl-cache-enabled 1762 | soap.wsdl_cache_enabled=1 1763 | 1764 | ; Sets the directory name where SOAP extension will put cache files. 1765 | ; http://php.net/soap.wsdl-cache-dir 1766 | soap.wsdl_cache_dir="/tmp" 1767 | 1768 | ; (time to live) Sets the number of second while cached file will be used 1769 | ; instead of original one. 1770 | ; http://php.net/soap.wsdl-cache-ttl 1771 | soap.wsdl_cache_ttl=86400 1772 | 1773 | ; Sets the size of the cache limit. (Max. number of WSDL files to cache) 1774 | soap.wsdl_cache_limit = 5 1775 | 1776 | [sysvshm] 1777 | ; A default size of the shared memory segment 1778 | ;sysvshm.init_mem = 10000 1779 | 1780 | [ldap] 1781 | ; Sets the maximum number of open links or -1 for unlimited. 1782 | ldap.max_links = -1 1783 | 1784 | [dba] 1785 | ;dba.default_handler= 1786 | 1787 | [opcache] 1788 | ; Determines if Zend OPCache is enabled 1789 | ;opcache.enable=1 1790 | 1791 | ; Determines if Zend OPCache is enabled for the CLI version of PHP 1792 | ;opcache.enable_cli=0 1793 | 1794 | ; The OPcache shared memory storage size. 1795 | ;opcache.memory_consumption=128 1796 | 1797 | ; The amount of memory for interned strings in Mbytes. 1798 | ;opcache.interned_strings_buffer=8 1799 | 1800 | ; The maximum number of keys (scripts) in the OPcache hash table. 1801 | ; Only numbers between 200 and 1000000 are allowed. 1802 | ;opcache.max_accelerated_files=10000 1803 | 1804 | ; The maximum percentage of "wasted" memory until a restart is scheduled. 1805 | ;opcache.max_wasted_percentage=5 1806 | 1807 | ; When this directive is enabled, the OPcache appends the current working 1808 | ; directory to the script key, thus eliminating possible collisions between 1809 | ; files with the same name (basename). Disabling the directive improves 1810 | ; performance, but may break existing applications. 1811 | ;opcache.use_cwd=1 1812 | 1813 | ; When disabled, you must reset the OPcache manually or restart the 1814 | ; webserver for changes to the filesystem to take effect. 1815 | ;opcache.validate_timestamps=1 1816 | 1817 | ; How often (in seconds) to check file timestamps for changes to the shared 1818 | ; memory storage allocation. ("1" means validate once per second, but only 1819 | ; once per request. "0" means always validate) 1820 | ;opcache.revalidate_freq=2 1821 | 1822 | ; Enables or disables file search in include_path optimization 1823 | ;opcache.revalidate_path=0 1824 | 1825 | ; If disabled, all PHPDoc comments are dropped from the code to reduce the 1826 | ; size of the optimized code. 1827 | ;opcache.save_comments=1 1828 | 1829 | ; Allow file existence override (file_exists, etc.) performance feature. 1830 | ;opcache.enable_file_override=0 1831 | 1832 | ; A bitmask, where each bit enables or disables the appropriate OPcache 1833 | ; passes 1834 | ;opcache.optimization_level=0x7FFFBFFF 1835 | 1836 | ;opcache.dups_fix=0 1837 | 1838 | ; The location of the OPcache blacklist file (wildcards allowed). 1839 | ; Each OPcache blacklist file is a text file that holds the names of files 1840 | ; that should not be accelerated. The file format is to add each filename 1841 | ; to a new line. The filename may be a full path or just a file prefix 1842 | ; (i.e., /var/www/x blacklists all the files and directories in /var/www 1843 | ; that start with 'x'). Line starting with a ; are ignored (comments). 1844 | ;opcache.blacklist_filename= 1845 | 1846 | ; Allows exclusion of large files from being cached. By default all files 1847 | ; are cached. 1848 | ;opcache.max_file_size=0 1849 | 1850 | ; Check the cache checksum each N requests. 1851 | ; The default value of "0" means that the checks are disabled. 1852 | ;opcache.consistency_checks=0 1853 | 1854 | ; How long to wait (in seconds) for a scheduled restart to begin if the cache 1855 | ; is not being accessed. 1856 | ;opcache.force_restart_timeout=180 1857 | 1858 | ; OPcache error_log file name. Empty string assumes "stderr". 1859 | ;opcache.error_log= 1860 | 1861 | ; All OPcache errors go to the Web server log. 1862 | ; By default, only fatal errors (level 0) or errors (level 1) are logged. 1863 | ; You can also enable warnings (level 2), info messages (level 3) or 1864 | ; debug messages (level 4). 1865 | ;opcache.log_verbosity_level=1 1866 | 1867 | ; Preferred Shared Memory back-end. Leave empty and let the system decide. 1868 | ;opcache.preferred_memory_model= 1869 | 1870 | ; Protect the shared memory from unexpected writing during script execution. 1871 | ; Useful for internal debugging only. 1872 | ;opcache.protect_memory=0 1873 | 1874 | ; Allows calling OPcache API functions only from PHP scripts which path is 1875 | ; started from specified string. The default "" means no restriction 1876 | ;opcache.restrict_api= 1877 | 1878 | ; Mapping base of shared memory segments (for Windows only). All the PHP 1879 | ; processes have to map shared memory into the same address space. This 1880 | ; directive allows to manually fix the "Unable to reattach to base address" 1881 | ; errors. 1882 | ;opcache.mmap_base= 1883 | 1884 | ; Enables and sets the second level cache directory. 1885 | ; It should improve performance when SHM memory is full, at server restart or 1886 | ; SHM reset. The default "" disables file based caching. 1887 | ;opcache.file_cache= 1888 | 1889 | ; Enables or disables opcode caching in shared memory. 1890 | ;opcache.file_cache_only=0 1891 | 1892 | ; Enables or disables checksum validation when script loaded from file cache. 1893 | ;opcache.file_cache_consistency_checks=1 1894 | 1895 | ; Implies opcache.file_cache_only=1 for a certain process that failed to 1896 | ; reattach to the shared memory (for Windows only). Explicitly enabled file 1897 | ; cache is required. 1898 | ;opcache.file_cache_fallback=1 1899 | 1900 | ; Enables or disables copying of PHP code (text segment) into HUGE PAGES. 1901 | ; This should improve performance, but requires appropriate OS configuration. 1902 | ;opcache.huge_code_pages=1 1903 | 1904 | ; Validate cached file permissions. 1905 | ;opcache.validate_permission=0 1906 | 1907 | ; Prevent name collisions in chroot'ed environment. 1908 | ;opcache.validate_root=0 1909 | 1910 | ; If specified, it produces opcode dumps for debugging different stages of 1911 | ; optimizations. 1912 | ;opcache.opt_debug_level=0 1913 | 1914 | [curl] 1915 | ; A default value for the CURLOPT_CAINFO option. This is required to be an 1916 | ; absolute path. 1917 | ;curl.cainfo = 1918 | 1919 | [openssl] 1920 | ; The location of a Certificate Authority (CA) file on the local filesystem 1921 | ; to use when verifying the identity of SSL/TLS peers. Most users should 1922 | ; not specify a value for this directive as PHP will attempt to use the 1923 | ; OS-managed cert stores in its absence. If specified, this value may still 1924 | ; be overridden on a per-stream basis via the "cafile" SSL stream context 1925 | ; option. 1926 | ;openssl.cafile= 1927 | 1928 | ; If openssl.cafile is not specified or if the CA file is not found, the 1929 | ; directory pointed to by openssl.capath is searched for a suitable 1930 | ; certificate. This value must be a correctly hashed certificate directory. 1931 | ; Most users should not specify a value for this directive as PHP will 1932 | ; attempt to use the OS-managed cert stores in its absence. If specified, 1933 | ; this value may still be overridden on a per-stream basis via the "capath" 1934 | ; SSL stream context option. 1935 | ;openssl.capath= 1936 | 1937 | ; Local Variables: 1938 | ; tab-width: 4 1939 | ; End: 1940 | -------------------------------------------------------------------------------- /env.mk: -------------------------------------------------------------------------------- 1 | # =============================================================================== 2 | # Managed by Riotkit Standard One - a set of Open Source Github Actions Workflows 3 | # 4 | # NOTICE: ANY CHANGE made to this file would be overwritten by the Pipeline 5 | # =============================================================================== 6 | 7 | SUDO= 8 | SHELL := /bin/bash 9 | 10 | ifneq (,$(wildcard ./.env)) 11 | include .env 12 | export 13 | endif 14 | 15 | # default values 16 | ENV_CLUSTER_NAME ?= "rkt" 17 | ENV_NS ?= "default" 18 | ENV_APP_SVC ?= "service-name" 19 | ENV_PORT_FORWARD ?= "8050:8080" 20 | 21 | 22 | .EXPORT_ALL_VARIABLES: 23 | PATH = $(shell pwd)/.build:$(shell echo $$PATH) 24 | KUBECONFIG = $(shell /bin/bash -c 'k3d kubeconfig merge ${ENV_CLUSTER_NAME} > /dev/null 2>&1 || true; echo "$$HOME/.k3d/kubeconfig-${ENV_CLUSTER_NAME}.yaml"') 25 | 26 | .PHONY: kubeconfig 27 | kubeconfig: 28 | k3d kubeconfig merge ${ENV_CLUSTER_NAME} 29 | 30 | k3d: prepare-tools 31 | (${SUDO} docker ps | grep k3d-${ENV_CLUSTER_NAME}-server-0 > /dev/null 2>&1) || ${SUDO} k3d cluster create ${ENV_CLUSTER_NAME} --registry-create ${ENV_CLUSTER_NAME}-registry:0.0.0.0:5000 --agents 0 32 | k3d kubeconfig merge ${ENV_CLUSTER_NAME} 33 | kubectl create ns ${ENV_NS} || true 34 | cat /etc/hosts | grep "${ENV_CLUSTER_NAME}-registry" > /dev/null || (sudo /bin/bash -c "echo '127.0.0.1 ${ENV_CLUSTER_NAME}-registry' >> /etc/hosts") 35 | 36 | prepare-tools: ## Installs required tools 37 | mkdir -p .build 38 | # skaffold 39 | @test -f ./.build/skaffold || (curl -sL https://storage.googleapis.com/skaffold/releases/v2.2.0/skaffold-linux-amd64 --output ./.build/skaffold && chmod +x ./.build/skaffold) 40 | # kubectl 41 | @test -f ./.build/kubectl || (curl -sL https://dl.k8s.io/release/v1.26.0/bin/linux/amd64/kubectl --output ./.build/kubectl && chmod +x ./.build/kubectl) 42 | # k3d 43 | @test -f ./.build/k3d || (curl -sL https://github.com/k3d-io/k3d/releases/download/v5.4.6/k3d-linux-amd64 --output ./.build/k3d && chmod +x ./.build/k3d) 44 | # helm 45 | @test -f ./.build/helm || (curl -sL https://get.helm.sh/helm-v3.11.2-linux-amd64.tar.gz --output /tmp/helm.tar.gz && tar xf /tmp/helm.tar.gz -C /tmp && mv /tmp/linux-amd64/helm ./.build/helm && chmod +x ./.build/helm) 46 | # kubens 47 | @test -f ./.build/kubens || (curl -sL https://raw.githubusercontent.com/ahmetb/kubectx/master/kubens --output ./.build/kubens && chmod +x ./.build/kubens) 48 | # kuttl 49 | @test -f ./.build/kuttl || (curl -sL https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64 --output ./.build/kuttl && chmod +x ./.build/kuttl) 50 | 51 | skaffold-deploy: skaffold-deploy-deps skaffold-deploy-app ## Deploys app with dependencies using Skaffold 52 | kubectl port-forward svc/${ENV_APP_SVC} -n ${ENV_NS} ${ENV_PORT_FORWARD} & 53 | 54 | skaffold-deploy-deps: prepare-tools ## Deploy app dependencies 55 | k3d kubeconfig merge ${ENV_CLUSTER_NAME} 56 | skaffold deploy -p deps 57 | 58 | skaffold-deploy-app: prepare-tools ## Deploy app 59 | skaffold build -p app --tag e2e --default-repo ${ENV_CLUSTER_NAME}-registry:5000 --push --insecure-registry ${ENV_CLUSTER_NAME}-registry:5000 --disable-multi-platform-build=true --detect-minikube=false --cache-artifacts=false; \ 60 | skaffold deploy -p app --tag e2e --assume-yes=true --default-repo ${ENV_CLUSTER_NAME}-registry:5000; 61 | 62 | dev: ## Runs the development environment in Kubernetes 63 | if [[ "${ENV_SKAFFOLD_DEV_DEPLOY_DEPS}" == "true" ]]; then skaffold deploy -p deps; fi 64 | skaffold dev -p app --tag e2e --assume-yes=true --default-repo ${ENV_CLUSTER_NAME}-registry:5000 65 | 66 | 67 | ## Frameworks support 68 | _pytest: 69 | pipenv sync 70 | pipenv run pytest -s 71 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: wordpress-hardened 3 | description: "Lightweight Wordpress installation with additional security fixes" 4 | type: application 5 | version: 0.0.1-latest-master 6 | appVersion: master # replaced by CI on build stage 7 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/README.md: -------------------------------------------------------------------------------- 1 | # wordpress-hardened 2 | 3 | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/wordpress-hardened)](https://artifacthub.io/packages/search?repo=wordpress-hardened) 4 | 5 | Hardened version of official WordPress container, with special support for Kubernetes. 6 | 7 | ```bash 8 | helm install my-wordpress-hardened oci://ghcr.io/riotkit-org/charts/wordpress-hardened --version -------------------------------------------------------------------------------- /helm/wordpress-hardened/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.deprecationWarning" . }} 3 | 4 | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/wordpress-hardened)](https://artifacthub.io/packages/search?repo=wordpress-hardened) 5 | 6 | Hardened version of official WordPress container, with special support for Kubernetes. 7 | 8 | ```bash 9 | helm install my-wordpress-hardened oci://ghcr.io/riotkit-org/charts/wordpress-hardened --version {{ .chart.appVersion }} 10 | ``` 11 | 12 | **Features:** 13 | - Scheduled updates via wp-cli 14 | - **NGINX instead of Apache** 15 | - Supports [NGINX-PROXY](https://github.com/nginx-proxy/nginx-proxy) (VIRTUAL_HOST environment variable) 16 | - Hardened settings for WordPress: limiting access to code execution from wp-content directory, basic auth on wp-login.php 17 | - Basic Auth enabled by default to protect wp-login against bots (default user: `riotkit`, password: `riotkit`), can be changed using environment variables 18 | - Non-root container 19 | - Free from Supervisord, using lightweight [multirun](https://github.com/nicolas-van/multirun) instead 20 | - Runtime NGINX and PHP configuration to adjust things like `memory_limit`, `error_reporting` or `post_max_size` 21 | - Pre-configuration of admin account, website name and list of installed plugins 22 | - Possible to upgrade Wordpress together with docker container 23 | - Built-in primitive rules to block common exploits targeting PHP 24 | 25 | **Kubernetes-only features:** 26 | - Helm installer 27 | - Integration with [Backup Repository](https://github.com/riotkit-org/backup-repository) (for Kubernetes-native backups) 28 | - Integration with [Volume Syncing Controller](https://github.com/riotkit-org/volume-syncing-controller) (for WordPress volume synchronization between Pod and cloud filesystem) 29 | - Web Application Firewall and OWASP CRS support (experimental) 30 | 31 | 32 | [Check full documentation](https://github.com/riotkit-org/wordpress-hardened) 33 | ------------------------ 34 | 35 | {{ template "chart.homepageLine" . }} 36 | 37 | {{ template "chart.maintainersSection" . }} 38 | 39 | {{ template "chart.sourcesSection" . }} 40 | 41 | {{ template "chart.requirementsSection" . }} 42 | 43 | {{ template "chart.valuesSection" . }} 44 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/bin/get-app-version: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 5 | echo -n $(cat ${SCRIPT_DIR}/../../../Dockerfile | grep "FROM wordpress" | grep -P -o '[0-9.]+' | head -1) 6 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "wordpress-hardened.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "wordpress-hardened.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default "wph" $.Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "wordpress-hardened.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "wordpress-hardened.labels" -}} 37 | helm.sh/chart: {{ include "wordpress-hardened.chart" . }} 38 | {{ include "wordpress-hardened.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "wordpress-hardened.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "wordpress-hardened.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "wordpress-hardened.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "wordpress-hardened.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | 64 | {{- define "wordpress-hardened.mounts" }} 65 | {{- if .Values.pv.wp.enabled }} 66 | - name: wp 67 | mountPath: /var/www/riotkit 68 | {{- end }} 69 | 70 | {{- if .Values.pv.wp_content.enabled }} 71 | - name: wp-content 72 | mountPath: /var/www/riotkit/wp-content 73 | {{- end }} 74 | 75 | {{ with .Values.pv.extraVolumeMounts }} 76 | {{ toYaml . }} 77 | {{ end }} 78 | 79 | {{- end }} 80 | 81 | {{- define "wordpress-hardened.job" }} 82 | {{ $job := .job }} 83 | {{ $jobName := .jobName }} 84 | 85 | ttlSecondsAfterFinished: {{ ($job.ttlSecondsAfterFinished | default "86400") }} 86 | activeDeadlineSeconds: {{ ($job.activeDeadlineSeconds | default "60") }} 87 | backoffLimit: 1 88 | completions: 1 89 | parallelism: 1 90 | suspend: false 91 | template: 92 | spec: 93 | volumes: 94 | - name: scripts 95 | configMap: 96 | name: {{ include "wordpress-hardened.name" . }}-sql-scripts 97 | containers: 98 | - name: mysql 99 | image: {{ $job.image | quote }} 100 | imagePullPolicy: IfNotPresent 101 | args: ["-c", "cat /mnt/script.sql | mysql -u {{ .Values.db.user }} -h {{ .Values.db.host }} -P {{ .Values.db.port }} -p${WORDPRESS_DB_PASSWORD} {{ .Values.db.name }}"] 102 | command: ["/bin/sh"] 103 | env: 104 | {{- if not (hasKey $.Values.env "WORDPRESS_DB_PASSWORD") }} 105 | - name: WORDPRESS_DB_PASSWORD 106 | valueFrom: 107 | secretKeyRef: 108 | name: {{ .Values.db.password.secretName | quote }} 109 | key: {{ .Values.db.password.secretKey | quote }} 110 | {{ else }} 111 | - name: WORDPRESS_DB_PASSWORD 112 | value: {{ .Values.env.WORDPRESS_DB_PASSWORD | quote }} 113 | {{- end }} 114 | resources: {} 115 | volumeMounts: 116 | - name: scripts 117 | mountPath: /mnt/script.sql 118 | subPath: {{ $jobName }} 119 | dnsPolicy: ClusterFirst 120 | restartPolicy: Never 121 | automountServiceAccountToken: false 122 | terminationGracePeriodSeconds: {{ ($job.terminationGracePeriodSeconds | default "5") }} 123 | {{- end }} -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/dba.configmap.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.db.administrativeJobs }} 2 | --- 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: {{ include "wordpress-hardened.name" . }}-sql-scripts 7 | data: 8 | {{ range $jobName, $job := .Values.db.administrativeJobs }} 9 | {{ $jobName }}: | 10 | {{ $job.sql | nindent 8 }} 11 | {{ end }} 12 | {{ end }} 13 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/dba.cronjob.yaml: -------------------------------------------------------------------------------- 1 | {{ range $jobName, $job := .Values.db.administrativeJobs }} 2 | {{ if not $job.isHelmHook }} 3 | --- 4 | apiVersion: batch/v1 5 | kind: CronJob 6 | metadata: 7 | name: {{ $jobName }} 8 | labels: 9 | {{- include "wordpress-hardened.labels" $ | nindent 8 }} 10 | spec: 11 | suspend: false 12 | schedule: "{{ $job.schedule }}" 13 | jobTemplate: 14 | spec: 15 | {{ $context := dict "Values" $.Values "Release" $.Release "Chart" $.Chart "job" $job "jobName" $jobName }} 16 | {{ include "wordpress-hardened.job" $context | nindent 12 }} 17 | {{ end }} 18 | {{ end }} 19 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/dba.job.yaml: -------------------------------------------------------------------------------- 1 | {{ range $jobName, $job := .Values.db.administrativeJobs }} 2 | {{ if and $job.isHelmHook (not $job.schedule) }} 3 | --- 4 | apiVersion: batch/v1 5 | kind: Job 6 | metadata: 7 | name: {{ $jobName }} 8 | labels: 9 | {{- include "wordpress-hardened.labels" $ | nindent 8 }} 10 | annotations: 11 | "helm.sh/hook": post-install 12 | "helm.sh/hook-delete-policy": before-hook-creation 13 | spec: 14 | {{ $context := dict "Values" $.Values "Release" $.Release "Chart" $.Chart "job" $job "jobName" $jobName }} 15 | {{ include "wordpress-hardened.job" $context | nindent 4 }} 16 | {{ end }} 17 | {{ end }} 18 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ include "wordpress-hardened.fullname" . }} 6 | labels: 7 | {{- include "wordpress-hardened.labels" . | nindent 8 }} 8 | spec: 9 | replicas: {{ .Values.replicas }} 10 | revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} 11 | selector: 12 | matchLabels: 13 | {{- include "wordpress-hardened.selectorLabels" . | nindent 10 }} 14 | 15 | {{- if .Values.rollingUpdate.enabled }} 16 | strategy: 17 | type: RollingUpdate 18 | rollingUpdate: 19 | {{ toYaml .Values.rollingUpdate.spec | nindent 12 }} 20 | {{- end }} 21 | 22 | template: 23 | metadata: 24 | {{- with .Values.podAnnotations }} 25 | annotations: 26 | {{- toYaml . | nindent 16 }} 27 | {{- end }} 28 | labels: 29 | {{- include "wordpress-hardened.selectorLabels" . | nindent 16 }} 30 | {{- if eq (.Values.image.tag | default .Chart.AppVersion) "latest" | or (eq (.Values.image.tag | default .Chart.AppVersion) "snapshot") }} 31 | refreshImageTag: "{{- randAlphaNum 24 | nospace -}}" 32 | {{- end }} 33 | {{- with .Values.podLabels }} 34 | {{- toYaml . | nindent 16 }} 35 | {{- end }} 36 | spec: 37 | automountServiceAccountToken: false 38 | terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds | default "5" }} 39 | securityContext: 40 | {{- if .Values.podSecurityContext }} 41 | {{- toYaml . | nindent 16 }} 42 | {{ else }} 43 | runAsUser: {{ .Values.permissions.uid }} 44 | runAsGroup: {{ .Values.permissions.uid }} 45 | fsGroup: {{ .Values.permissions.gid }} 46 | {{- end }} 47 | {{- with .Values.nodeSelector }} 48 | nodeSelector: 49 | {{- toYaml . | nindent 14 }} 50 | {{- end }} 51 | {{- with .Values.affinity }} 52 | affinity: 53 | {{- toYaml . | nindent 14 }} 54 | {{- end }} 55 | {{- with .Values.tolerations }} 56 | tolerations: 57 | {{- toYaml . | nindent 14 }} 58 | {{- end }} 59 | 60 | # ================================================================ 61 | # Init Container for fixing permissions 62 | # ================================================================ 63 | {{ if .Values.chownInitContainer.enabled }} 64 | initContainers: 65 | - name: set-volume-permissions 66 | image: {{ .Values.chownInitContainer.image }} 67 | command: ['sh', '-c', 'chown {{ .Values.permissions.uid }}:{{ .Values.permissions.gid }} /var/www/riotkit /var/www/riotkit/wp-content'] 68 | securityContext: 69 | runAsNonRoot: false 70 | runAsUser: 0 71 | runAsGroup: 0 72 | volumeMounts: 73 | {{ include "wordpress-hardened.mounts" . | nindent 22 }} 74 | {{ end }} 75 | containers: 76 | # ================================================================ 77 | # Web Application Firewall (WAF) support 78 | # ================================================================ 79 | {{- if .Values.waf.enabled }} 80 | - name: waf-proxy 81 | image: {{ .Values.waf.image.repository }}:{{ .Values.waf.image.tag }} 82 | imagePullPolicy: Always 83 | env: 84 | - name: CADDY_PORT 85 | value: "8090" 86 | 87 | {{- range $num, $ingress := $.Values.ingresses }} 88 | {{- range $ingress.hosts }} 89 | - name: UPSTREAM_{{ $num }} 90 | value: '{"pass_to": "http://127.0.0.1:8080", "hostname": "{{ .host }}"}' 91 | {{- end }} 92 | {{- end }} 93 | 94 | {{- with .Values.waf.env }} 95 | {{- range $key, $value := . }} 96 | - name: {{ $key }} 97 | value: "{{ $value }}" 98 | {{- end }} 99 | {{- end }} 100 | 101 | volumeMounts: 102 | # allows to add extra directives 103 | - name: waf-custom-config 104 | mountPath: /etc/caddy/rules/custom.conf 105 | subPath: custom.conf 106 | 107 | ports: 108 | - name: http-waf 109 | containerPort: 8090 110 | protocol: TCP 111 | 112 | - name: waf-metrics 113 | containerPort: 2019 114 | protocol: TCP 115 | 116 | - name: waf-healthcheck 117 | containerPort: 8081 118 | protocol: TCP 119 | 120 | {{- if .Values.waf.health.liveness.enabled }} 121 | livenessProbe: 122 | {{- with .Values.waf.health.liveness.attributes}} 123 | {{- toYaml . | nindent 22 }} 124 | {{- end}} 125 | httpGet: 126 | path: / 127 | scheme: HTTP 128 | port: waf-healthcheck 129 | {{- end }} 130 | {{- end }} 131 | 132 | # ================================================================ 133 | # WordPress container 134 | # ================================================================ 135 | - name: app 136 | image: {{ .Values.image.repository }}:{{ default .Values.riotkit.release.ref .Values.image.tag }} 137 | imagePullPolicy: Always 138 | env: 139 | {{- with .Values.env }} 140 | {{- range $key, $value := . }} 141 | - name: {{ $key }} 142 | value: "{{ $value }}" 143 | {{- end }} 144 | {{- end }} 145 | 146 | {{- if not (hasKey .Values.env "WP_PAGE_URL") }} 147 | - name: WP_PAGE_URL 148 | value: "http{{ if eq .Values.wordpress.https "on" }}s{{ end }}://{{ .Values.wordpress.domain }}{{ if not (eq (.Values.wordpress.publicPort | toString) "443") }}:{{ .Values.wordpress.publicPort }}{{ end }}" 149 | {{- end }} 150 | 151 | {{- if not (hasKey .Values.env "HEALTH_CHECK_ALLOWED_SUBNET") }} 152 | - name: HEALTH_CHECK_ALLOWED_SUBNET 153 | value: {{ .Values.health.allowedSubnets | quote }} 154 | {{- end }} 155 | 156 | {{- if not (hasKey .Values.env "HTTPS") }} 157 | - name: HTTPS 158 | value: {{ .Values.wordpress.https | quote }} 159 | {{- end }} 160 | 161 | - name: WORDPRESS_DB_NAME 162 | value: {{ .Values.db.name | quote }} 163 | - name: WORDPRESS_DB_USER 164 | value: {{ .Values.db.user | quote }} 165 | - name: WORDPRESS_DB_PORT 166 | value: {{ .Values.db.port | quote }} 167 | - name: WORDPRESS_DB_HOST 168 | value: {{ .Values.db.host | quote }} 169 | 170 | {{- if not (hasKey .Values.env "WORDPRESS_DB_PASSWORD") }} 171 | - name: WORDPRESS_DB_PASSWORD 172 | valueFrom: 173 | secretKeyRef: 174 | name: {{ .Values.db.password.secretName | quote }} 175 | key: {{ .Values.db.password.secretKey | quote }} 176 | {{- end }} 177 | 178 | {{ if .Values.secrets.enabled }} 179 | envFrom: 180 | - secretRef: 181 | optional: true 182 | name: {{ .Values.secrets.name }} 183 | {{ end }} 184 | securityContext: 185 | allowPrivilegeEscalation: false 186 | runAsNonRoot: true 187 | volumeMounts: 188 | {{ include "wordpress-hardened.mounts" . | nindent 22 }} 189 | ports: 190 | - name: http 191 | containerPort: 8080 192 | protocol: TCP 193 | {{- if .Values.health.liveness.enabled }} 194 | livenessProbe: 195 | {{- with .Values.health.liveness.attributes}} 196 | {{- toYaml . | nindent 22 }} 197 | {{- end}} 198 | httpGet: 199 | path: /liveness.php 200 | scheme: HTTP 201 | port: http 202 | {{- end }} 203 | {{- if .Values.health.readiness.enabled }} 204 | readinessProbe: 205 | {{- with .Values.health.readiness.attributes }} 206 | {{- toYaml . | nindent 22 }} 207 | {{- end }} 208 | httpGet: 209 | path: /readiness.php 210 | scheme: HTTP 211 | port: http 212 | {{- end }} 213 | startupProbe: 214 | httpGet: 215 | path: /liveness.php 216 | scheme: HTTP 217 | port: http 218 | failureThreshold: 10 219 | periodSeconds: 5 220 | resources: 221 | {{- toYaml .Values.resources | nindent 20 }} 222 | volumes: 223 | {{- if .Values.pv.wp.enabled }} 224 | - name: wp 225 | persistentVolumeClaim: 226 | claimName: {{ .Values.pv.wp.claimName }} 227 | {{- end }} 228 | {{- if .Values.pv.wp_content.enabled }} 229 | - name: wp-content 230 | persistentVolumeClaim: 231 | claimName: {{ .Values.pv.wp_content.claimName }} 232 | {{- end }} 233 | {{- if .Values.waf.enabled }} 234 | - name: waf-custom-config 235 | configMap: 236 | name: {{ include "wordpress-hardened.fullname" . }}-waf-custom-config 237 | {{- end }} 238 | {{ with .Values.pv.extraVolumes }} 239 | {{ toYaml . | nindent 16 }} 240 | {{ end }} 241 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/extra-configmaps.yaml: -------------------------------------------------------------------------------- 1 | {{- range $attrs := $.Values.extraConfigMaps }} 2 | --- 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: {{ $attrs.name }} 7 | data: 8 | {{- toYaml $attrs.data | nindent 4 }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- range $num, $ingress := $.Values.ingresses }} 2 | {{- $fullName := include "wordpress-hardened.fullname" $ }} 3 | 4 | --- 5 | {{ $svcPort := $.Values.service.port -}} 6 | {{ if $ingress.className }} 7 | {{ if not (hasKey $ingress.annotations "kubernetes.io/ingress.class") }} 8 | {{ $_ := set $ingress.annotations "kubernetes.io/ingress.class" $ingress.className}} 9 | {{ end }} 10 | {{ end }} 11 | apiVersion: networking.k8s.io/v1 12 | kind: Ingress 13 | metadata: 14 | name: {{ .name | default $fullName }} 15 | labels: 16 | {{- include "wordpress-hardened.labels" $ | nindent 6 }} 17 | {{- with $ingress.annotations }} 18 | annotations: 19 | {{- toYaml . | nindent 6 }} 20 | {{- end }} 21 | spec: 22 | {{- if and $ingress.className (not (hasKey $ingress.annotations "kubernetes.io/ingress.class")) }} 23 | ingressClassName: {{ $ingress.className }} 24 | {{- end }} 25 | {{- if $ingress.tls }} 26 | tls: 27 | {{- range $ingress.tls }} 28 | - hosts: 29 | {{- if or (not (hasKey . "hosts")) (not .hosts) }} 30 | - {{ $.Values.wordpress.domain | quote }} 31 | {{ else }} 32 | {{- range .hosts }} 33 | - {{ . | quote }} 34 | {{- end }} 35 | {{ end }} 36 | secretName: {{ .secretName | default $fullName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range $ingress.hosts }} 41 | - host: {{ default $.Values.wordpress.domain .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if .pathType }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | service: 51 | name: {{ if $.Values.waf.enabled }}{{ $fullName }}-waf-protected{{ else }}{{ $fullName }}{{ end }} 52 | port: 53 | number: 80 54 | {{- end }} 55 | {{- end }} 56 | 57 | {{- end }} 58 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.podDisruptionBudget.enabled }} 2 | --- 3 | apiVersion: policy/v1 4 | kind: PodDisruptionBudget 5 | metadata: 6 | name: {{ include "wordpress-hardened.fullname" . }} 7 | spec: 8 | {{ toYaml .Values.podDisruptionBudget.spec | nindent 4 }} 9 | selector: 10 | matchLabels: 11 | {{- include "wordpress-hardened.selectorLabels" . | nindent 12 }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.pv.wp.enabled .Values.pv.wp.create }} 2 | --- 3 | apiVersion: v1 4 | kind: PersistentVolumeClaim 5 | metadata: 6 | name: {{ .Values.pv.wp.claimName }} 7 | spec: 8 | {{- if .Values.pv.storageClassName }} 9 | storageClassName: {{ .Values.pv.wp.storageClassName }} 10 | {{- end }} 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: {{ .Values.pv.wp.size }} 16 | {{- end }} 17 | 18 | {{- if .Values.pv.wp_content.create }} 19 | --- 20 | apiVersion: v1 21 | kind: PersistentVolumeClaim 22 | metadata: 23 | name: {{ .Values.pv.wp_content.claimName }} 24 | spec: 25 | {{- if .Values.pv.storageClassName }} 26 | storageClassName: {{ .Values.pv.wp_content.storageClassName }} 27 | {{- end }} 28 | accessModes: 29 | - ReadWriteOnce 30 | resources: 31 | requests: 32 | storage: {{ .Values.pv.wp_content.size }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.secrets.create }} 2 | --- 3 | apiVersion: {{ .Values.secrets.apiVersion }} 4 | kind: {{ .Values.secrets.kind }} 5 | metadata: 6 | name: {{ .Values.secrets.name }} 7 | namespace: {{ .Release.Namespace }} 8 | {{ .Values.secrets.content }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "wordpress-hardened.fullname" . }} 6 | labels: 7 | {{- include "wordpress-hardened.labels" . | nindent 8 }} 8 | spec: 9 | type: {{ .Values.service.type }} 10 | ports: 11 | - port: 80 12 | targetPort: http 13 | protocol: TCP 14 | name: http 15 | selector: 16 | {{- include "wordpress-hardened.selectorLabels" . | nindent 8 }} 17 | 18 | {{- if .Values.waf.enabled }} 19 | --- 20 | apiVersion: v1 21 | kind: Service 22 | metadata: 23 | name: {{ include "wordpress-hardened.fullname" . }}-waf-protected 24 | labels: 25 | {{- include "wordpress-hardened.labels" . | nindent 8 }} 26 | spec: 27 | type: {{ .Values.service.type }} 28 | ports: 29 | - port: 80 30 | targetPort: http-waf 31 | protocol: TCP 32 | name: http 33 | 34 | - port: 8081 35 | targetPort: waf-healthcheck 36 | protocol: TCP 37 | name: waf-healthcheck 38 | selector: 39 | {{- include "wordpress-hardened.selectorLabels" . | nindent 8 }} 40 | 41 | --- 42 | apiVersion: v1 43 | kind: Service 44 | metadata: 45 | name: {{ include "wordpress-hardened.fullname" . }}-waf-metrics 46 | labels: 47 | {{- include "wordpress-hardened.labels" . | nindent 8 }} 48 | spec: 49 | type: {{ .Values.service.type }} 50 | ports: 51 | - port: 2019 52 | targetPort: waf-metrics 53 | protocol: TCP 54 | name: waf-metrics 55 | selector: 56 | {{- include "wordpress-hardened.selectorLabels" . | nindent 8 }} 57 | {{- end }} 58 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/templates/waf.configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.waf.enabled }} 2 | --- 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: {{ include "wordpress-hardened.fullname" . }}-waf-custom-config 7 | data: 8 | custom.conf: | 9 | {{ .Values.waf.directives }} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /helm/wordpress-hardened/values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | repository: ghcr.io/riotkit-org/wordpress-hardened 3 | tag: "" # defaults to {{ .Release.appVersion }} 4 | 5 | terminationGracePeriodSeconds: 20 6 | revisionHistoryLimit: 1 7 | podLabels: {} 8 | 9 | # -- If .Values.podSecurityContext is not specified, then this section will set securityContext. Those values also applies to the chown init container 10 | permissions: 11 | uid: 65161 12 | gid: 65161 13 | podSecurityContext: {} 14 | podDisruptionBudget: 15 | enabled: false 16 | spec: 17 | minAvailable: 1 18 | maxUnavailable: 0 19 | replicas: 1 20 | rollingUpdate: 21 | enabled: true 22 | spec: 23 | maxSurge: 1 24 | maxUnavailable: 0 25 | 26 | extraConfigMaps: [] 27 | 28 | db: 29 | user: riotkit 30 | name: riotkit 31 | host: mariadb.db.svc.cluster.local 32 | port: 3306 33 | password: 34 | secretName: db-credentials 35 | secretKey: password 36 | 37 | administrativeJobs: {} 38 | # delete-old-comments: 39 | # image: bitnami/mariadb:10.6 40 | # isHelmHook: false 41 | # schedule: "16 1 * * *" 42 | # # language=mysql 43 | # sql: | 44 | # DELETE FROM x WHERE y; 45 | 46 | wordpress: 47 | # -- Should the WordPress automatically update itself periodically? NOTICE! Use with .pv.wp.enabled = true 48 | autoUpdate: true 49 | 50 | # -- Ingress domain name 51 | domain: example.org 52 | 53 | # -- Ingress port 54 | publicPort: "443" 55 | 56 | # -- HTTP/HTTPS 57 | https: "on" 58 | 59 | pv: 60 | # -- Disable whole root directory volume to have WordPress version managed by the container. Enable it to use updater from the web - in this case the image version would only matter for PHP, NGINX versions, but the WordPress version would be bumped by WordPress by his own 61 | wp: 62 | enabled: true 63 | create: true 64 | claimName: wp 65 | size: 256Mi 66 | #storageClassName: "..." 67 | 68 | # [!!!] Disabling persistence on wp-content may be dangerous, better know what you are doing 69 | wp_content: 70 | enabled: true 71 | claimName: wp-content 72 | create: true 73 | size: 1Gi 74 | #storageClassName: "..." 75 | 76 | # use those following to e.g. mount a custom ConfigMap, or a PVC with some data 77 | extraVolumes: [] 78 | extraVolumeMounts: [] 79 | 80 | 81 | ingresses: 82 | - className: nginx 83 | annotations: 84 | cert-manager.io/cluster-issuer: letsencrypt-staging 85 | hosts: 86 | - paths: 87 | - path: / 88 | pathType: ImplementationSpecific 89 | tls: 90 | - hosts: [] 91 | 92 | # environment variables passed to the container - see Dockerfile and https://github.com/riotkit-org/wordpress-hardened for reference 93 | env: {} 94 | 95 | # -- Allows to embed `kind: Secret`, `kind: SealedSecret`, `kind: ExternalSecret` or any other secret. Use it for example with Bitnami's Sealed Secret 96 | secrets: 97 | enabled: false 98 | name: wordpress-secrets 99 | create: false 100 | apiVersion: bitnami.com/v1alpha1 101 | kind: SealedSecret 102 | content: | 103 | encryptedData: 104 | ... 105 | 106 | resources: 107 | requests: 108 | memory: 16Mi 109 | cpu: 0 110 | limits: 111 | memory: 128Mi 112 | cpu: 1 113 | 114 | health: 115 | allowedSubnets: "10.0.0.0/8" 116 | liveness: 117 | enabled: true 118 | attributes: 119 | failureThreshold: 2 120 | periodSeconds: 60 121 | readiness: 122 | enabled: true 123 | attributes: 124 | failureThreshold: 2 125 | periodSeconds: 60 126 | 127 | service: 128 | type: ClusterIP 129 | port: 8080 130 | 131 | # ===================================================================== 132 | # Web Application Firewall - protects your WP instance against attacks 133 | # Requires Ingress to be created. 134 | # ===================================================================== 135 | waf: 136 | enabled: false 137 | image: 138 | repository: ghcr.io/riotkit-org/waf-proxy 139 | tag: snapshot 140 | env: 141 | ENABLE_RULE_WORDPRESS: true 142 | ENABLE_CRS: true 143 | ENABLE_RATE_LIMITER: true 144 | RATE_LIMIT_EVENTS: "30" 145 | RATE_LIMIT_WINDOW: "5s" 146 | 147 | # due to bug temporarily the CORAZA WAF is disabled, it will be enabled by default in future releases 148 | ENABLE_CORAZA_WAF: false 149 | 150 | directives: | 151 | #SecDefaultAction "phase:4,allow,log" 152 | #SecAction "id:1,pass,log" 153 | #SecAuditLog /dev/stdout 154 | #SecDebugLog /dev/stdout 155 | #SecDebugLogLevel 5 156 | health: 157 | liveness: 158 | enabled: true 159 | attributes: 160 | failureThreshold: 2 161 | periodSeconds: 60 162 | 163 | # ===================================================================== 164 | # Backup Repository integration 165 | # 166 | # Docs: 167 | # - Client: https://github.com/riotkit-org/br-backup-maker 168 | # - Client's controller: https://github.com/riotkit-org/backup-maker-controller 169 | # - Server: https://github.com/riotkit-org/backup-repository 170 | # ===================================================================== 171 | backups: 172 | enabled: false 173 | 174 | # -- Crontab-like syntax, will be used in a `kind: CronJob` object 175 | schedule: "16 1 * * *" # 01:16 in the night 176 | 177 | # -- Backup Repository instance URL 178 | url: https://my-backup-repository-instance.org 179 | 180 | # -- Server side collection id (a backup slot/directory) 181 | collectionId: "" 182 | 183 | # -- Use MariaDB template version matching your server's version for best compatibility 184 | templateName: wordpress-mariadb-10.10 185 | templateType: internal 186 | 187 | # -- Used for GPG encryption. Recommended: Set the same as in user account in Backup Repository 188 | email: example@example.org 189 | 190 | secrets: 191 | # -- Login token is a JWT token generated by logging in to Backup Repository (see: https://github.com/riotkit-org/backup-repository/blob/767707ada71781a59b583f3e35f22618cf7c1e44/docs/api/users/README.md#post-apistableauthlogin) 192 | loginToken: 193 | secretName: "" # defaults to .Values.secrets.name 194 | secretKey: backup-login-token 195 | 196 | # -- GPG key pair - public & private key used for backup encryption. Will generate automatically if not present (make sure to back up created `kind: Secret`) 197 | gpgKeys: 198 | createIfNotExists: true 199 | secretName: backups-gpg 200 | 201 | # -- Use PRIVILEGED init container to correct permissions of your volumes 202 | chownInitContainer: 203 | enabled: true 204 | image: busybox:1.36.0-musl 205 | 206 | riotkit: 207 | # -- filled up by CI/CD pipeline during the release 208 | release: 209 | ref: "master" 210 | isSnapshot: false 211 | -------------------------------------------------------------------------------- /htpasswd: -------------------------------------------------------------------------------- 1 | riotkit:$apr1$UmjxQSi2$0YCrneUIpiAjetzQrhqoj. 2 | -------------------------------------------------------------------------------- /kuttl-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | testDirs: 4 | - tests/e2e/ 5 | timeout: 60 6 | -------------------------------------------------------------------------------- /liveness.php: -------------------------------------------------------------------------------- 1 | 7; 15 | 16 | env: 17 | HTTPS: off 18 | WP_PREINSTALL: true 19 | WORDPRESS_DB_PASSWORD: "lgbt-1312" 20 | 21 | # PVC cannot be re-deployed 22 | pv: 23 | wp: 24 | enabled: false 25 | create: false 26 | wp_content: 27 | enabled: false 28 | create: false 29 | chownInitContainer: 30 | enabled: false 31 | 32 | wordpress: 33 | domain: "localhost" 34 | publicPort: "8050" 35 | https: "off" 36 | health: 37 | allowedSubnets: 0.0.0.0/0 38 | -------------------------------------------------------------------------------- /skaffold.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: skaffold/v3 3 | kind: Config 4 | profiles: 5 | - name: app 6 | build: 7 | local: 8 | push: true 9 | artifacts: 10 | - image: rkt-registry:5000/wordpress-hardened 11 | docker: 12 | dockerfile: Dockerfile 13 | tagPolicy: 14 | gitCommit: {} 15 | insecureRegistries: 16 | - rkt-registry:5000 17 | deploy: 18 | statusCheck: true 19 | statusCheckDeadlineSeconds: 120 20 | helm: 21 | releases: 22 | - name: wp 23 | chartPath: helm/wordpress-hardened 24 | recreatePods: true 25 | namespace: wp 26 | createNamespace: true 27 | valuesFiles: 28 | - skaffold.values.yaml 29 | setValueTemplates: 30 | image: 31 | repository: rkt-registry:5000/wordpress-hardened 32 | tag: '{{.IMAGE_TAG}}' 33 | 34 | portForward: 35 | - resourceType: service 36 | resourceName: wp-wph 37 | namespace: wp 38 | port: 80 39 | localPort: 8050 40 | 41 | 42 | - name: deps 43 | deploy: 44 | statusCheck: true 45 | statusCheckDeadlineSeconds: 120 46 | helm: 47 | releases: 48 | - name: mariadb 49 | repo: https://charts.bitnami.com/bitnami 50 | version: 11.5.4 51 | remoteChart: mariadb 52 | namespace: db 53 | createNamespace: true 54 | wait: true 55 | setValueTemplates: 56 | fullnameOverride: mariadb 57 | architecture: standalone 58 | auth.rootPassword: "lgbt-1312" 59 | auth.password: "lgbt-1312" 60 | auth.database: "riotkit" 61 | auth.username: "riotkit" 62 | 63 | -------------------------------------------------------------------------------- /tests/e2e/preinstalls-with-plugins/01-prepare.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - command: kubectl create secret generic db-credentials --from-literal=password=lgbt-1312 -n ${NAMESPACE} 6 | - command: helm upgrade --install wp ../../../helm/wordpress-hardened --values ./values.yaml -n ${NAMESPACE} 7 | -------------------------------------------------------------------------------- /tests/e2e/preinstalls-with-plugins/02-assert-pod-running.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | status: 5 | phase: Running 6 | -------------------------------------------------------------------------------- /tests/e2e/preinstalls-with-plugins/03-check-healthy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | # Assert Pod is running and healthy 5 | # language=bash 6 | - script: | 7 | #!/bin/bash 8 | set -ex 9 | kubectl wait --timeout=30s --for=condition=ready pod -l app.kubernetes.io/instance=wp -n ${NAMESPACE} || (echo "Application is not ready"; kubectl logs deployment/wp-wph -n ${NAMESPACE}; exit 1) 10 | 11 | # Check endpoints 12 | # language=bash 13 | - script: | 14 | #!/bin/bash 15 | set -ex 16 | killall kubectl 2>/dev/null || true; kubectl port-forward deployment/wp-wph -n ${NAMESPACE} 8050:8080 & 17 | sleep 2 18 | URL=http://127.0.0.1:8050 19 | 20 | # perform HTTP checks 21 | curl -s ${URL}/readiness.php || (echo "Application is not ready"; kubectl logs deployment/wp-wph -n ${NAMESPACE}; exit 1) 22 | killall kubectl 2>/dev/null || true 23 | -------------------------------------------------------------------------------- /tests/e2e/preinstalls-with-plugins/values.yaml: -------------------------------------------------------------------------------- 1 | db: 2 | user: riotkit 3 | name: riotkit 4 | host: mariadb.db.svc.cluster.local 5 | port: 3306 6 | password: 7 | secretName: db-credentials 8 | secretKey: password 9 | 10 | env: 11 | HTTPS: off 12 | WP_PREINSTALL: true 13 | 14 | domain: "localhost" 15 | publicPort: "8050" 16 | 17 | health: 18 | allowedSubnets: 0.0.0.0/0 19 | -------------------------------------------------------------------------------- /wp-config-riotkit.php: -------------------------------------------------------------------------------- 1 |