forked from coop-cloud/wordpress
Compare commits
229 Commits
service-re
...
improve-in
| Author | SHA1 | Date | |
|---|---|---|---|
| 6951115831 | |||
| bb63db7d2d | |||
| 056b072330 | |||
| 2b65a66f8e | |||
| c5fb2ebaf3 | |||
| 47fbba1505 | |||
| 32062bff94 | |||
| c7f500c428 | |||
| 391582089f | |||
| 27442e3e4e | |||
| 65e716fa20 | |||
| 15dd324102 | |||
| e14f47a4b3 | |||
| 2f1b9a2262 | |||
| bc54e86ff5 | |||
| 90d44bd3bc | |||
| 34b2515fca | |||
| fe8744e20e | |||
| 426e0367f1 | |||
| dde03454c3 | |||
| a8bb78a8db | |||
| 605f3d7fc0 | |||
| b305445512 | |||
| 69551175d5 | |||
| ef27645a30 | |||
| 5d3c019b83 | |||
| f450f2e6ba | |||
| c75c18f185 | |||
| cf54575187 | |||
| b4db12f09c | |||
| e4b87c8ab9 | |||
| 7e170adbb4 | |||
| 66e0687456 | |||
| 9209f007cb | |||
| 69cf451b98 | |||
| 73a2e98d2e | |||
| 0e229168fc | |||
| 332ab0b97d | |||
|
3b598e82dd
|
|||
|
8e81f3f81c
|
|||
| a09bd166ad | |||
|
b4c5d04382
|
|||
|
3c013d39fd
|
|||
| 285bc01bef | |||
| 2ca12bff9c | |||
| da2e62b618 | |||
| 364b5c8b8a | |||
| 306b348961 | |||
| 3c1121b7ce | |||
| b0eb1756a3 | |||
| 97b9b99e93 | |||
|
cf2a5077c9
|
|||
| 74282d5658 | |||
| ab7716bf1e | |||
| b0cc5a49a1 | |||
| 3cca5d2cf3 | |||
| f403648cf6 | |||
| 83f724a316 | |||
| e6b9f8117f | |||
| e7aef38d3b | |||
| e08838561d | |||
| 04d26a59a9 | |||
| 591019112e | |||
| 76e9b80fbd | |||
| f49fa05ded | |||
| 716e6df3cd | |||
| 457c2defaf | |||
| 37ff3e9b1b | |||
| c5443cc14b | |||
| 34f70889e3 | |||
| af04e30e36 | |||
| 17574fd3fe | |||
| 8b6983d240 | |||
| 6fb30c5bc1 | |||
| 929bfb4239 | |||
| 7e4ff5c075 | |||
| 564db5b63f | |||
| cf9b5f529e | |||
| 240b70a967 | |||
| 7f6b6a5ff2 | |||
| 4d99aae234 | |||
| 959484f5e5 | |||
| 7ef8e5515d | |||
| 770ef4932a | |||
| dcb8a9a3a9 | |||
| f3a9fad0a1 | |||
| ebbd41e612 | |||
| b45fca4a3f | |||
| 1a6b11c95b | |||
| de5455833e | |||
| 81dbeca30d | |||
| 245b800439 | |||
| 540d526914 | |||
| df32ba5141 | |||
| 8d8418a6c0 | |||
| a8d67b063c | |||
| da0f503960 | |||
| 6767d5ee65 | |||
| d5227cc534 | |||
| 45a36ba7b4 | |||
| ed77855e7d | |||
| 1c70a89ed4 | |||
| c6be9ecfcf | |||
| f2867c8359 | |||
| 4a7c468806 | |||
| 40d95417e9 | |||
| 37aa0649b9 | |||
| 5723405e51 | |||
| 650d531ed1 | |||
| 9077d0aa86 | |||
| 952044e590 | |||
| 1c03d854b2 | |||
| 38bc51f516 | |||
| 40cbb7d689 | |||
| 16ca5734d7 | |||
| 91335eac3a | |||
| dfaa04131d | |||
| b508b67752 | |||
| 8cc028fc00 | |||
| 55f00a482a | |||
| df821f5017 | |||
| 9b1e36f8c8 | |||
| f624ef2dc6 | |||
| 40e89c874a | |||
| 7c725fbf85 | |||
| ed587cd983 | |||
| 85d910f7ea | |||
| bcb911c6e0 | |||
| 7281edfd60 | |||
| 87406eb3ab | |||
| db1e7bc88a | |||
| 7962da376c | |||
| 6c97636698 | |||
| 72ff340927 | |||
| 369d962c40 | |||
| 5941680738 | |||
| 112c7a8f03 | |||
| 2550098aee | |||
| ef7bed62dd | |||
| 581cd72a9a | |||
|
50cd246597
|
|||
| a55be09951 | |||
| 5538ce9c3e | |||
| 981fe85910 | |||
| 1cedb08e46 | |||
| 37a6ff8d7a | |||
| 98f9a4f4d9 | |||
| 76b698bc30 | |||
| dcb3b410ff | |||
| ceffd9ba5d | |||
| 2d8c149b42 | |||
| 08c56a2ad9 | |||
| 2cb9b71e47 | |||
| 88ee8ae05e | |||
| 57122cd677 | |||
| ab3361f46d | |||
| 0771aae91c | |||
| 101864ce03 | |||
| 6ef2f30c0f | |||
| 26107257bc | |||
| 6b59677976 | |||
| 08fc5fe2c6 | |||
| de33fac3d3 | |||
| d6125ba37a | |||
| 6551fd8f8c | |||
| 14d50b851e | |||
| acd5e93a4b | |||
| f7600b9bc8 | |||
| febd2500b4 | |||
| a330574682 | |||
| be6cf302d0 | |||
| 8af9be6a40 | |||
| a550017071 | |||
| 9fa2b2d1b7 | |||
| 8399631c81 | |||
| e5c41fa027 | |||
| 0df2a556e8 | |||
| 4d4befc9e1 | |||
| e8aa34c7e3 | |||
| 421c01e78a | |||
| c99f35b5d9 | |||
| 36046c801e | |||
| d20b99b7b4 | |||
| 0b8c60c0f3 | |||
| f2fff04c53 | |||
| bf4e9323f3 | |||
| f28b9d69f6 | |||
| 8fc4c37e68 | |||
| 60b4398e92 | |||
| 08d9ac6e2f | |||
| fb632799c9 | |||
| f6dc0243f7 | |||
| 94459b7077 | |||
| d27c4ed6f3 | |||
| f2225be233 | |||
| aae6b22d53 | |||
| 4eaa4de5ae | |||
| 064af9c04c | |||
| 38c4fe0246 | |||
| 990a58be81 | |||
| 923295aa91 | |||
| 479d061879 | |||
| c28bb98e23 | |||
| 83130a482e | |||
| 925d5703a9 | |||
| 5d351b1ede | |||
| 5488d04c92 | |||
| 997707189e | |||
| 5c81094a82 | |||
| 26fa0bdfd3 | |||
| ebb2036510 | |||
| b0055f587d | |||
| a8d5e0553f | |||
| 6124c36f42 | |||
| 0e486d395d | |||
| 61bdd21085 | |||
| 21babc7bca | |||
| 0ac4c51b3b | |||
| 43cbfafb8a | |||
| c6039c3b54 | |||
| bdabcce977 | |||
| 42c822f819 | |||
| b5ac06c0cf | |||
| 6f10b0f3cc | |||
| 03bbf527fe | |||
| 25a98e6298 | |||
| c5beea3114 | |||
| 50a11700b4 | |||
| 65742d663d |
73
.drone.yml
73
.drone.yml
@ -1,22 +1,63 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: deploy to swarm-test.autonomic.zone
|
||||
name: test
|
||||
|
||||
steps:
|
||||
- name: deployment
|
||||
image: decentral1se/stack-ssh-deploy:latest
|
||||
settings:
|
||||
host: swarm-test.autonomic.zone
|
||||
stack: wordpress
|
||||
generate_secrets: true
|
||||
purge: true
|
||||
deploy_key:
|
||||
from_secret: drone_ssh_swarm_test
|
||||
- name: test
|
||||
image: alpine:3.21
|
||||
environment:
|
||||
DOMAIN: wordpress.swarm-test.autonomic.zone
|
||||
STACK_NAME: wordpress
|
||||
LETS_ENCRYPT_ENV: production
|
||||
DB_PASSWORD_VERSION: v1
|
||||
DB_ROOT_PASSWORD_VERSION: v1
|
||||
SHELLCHECK_OPTS: -s bash
|
||||
commands:
|
||||
- apk add --no-cache bash shellcheck py3-yaml curl
|
||||
- curl -sSLo /usr/local/bin/gomplate https://github.com/hairyhenderson/gomplate/releases/download/v5.0.0/gomplate_linux-amd64
|
||||
- chmod +x /usr/local/bin/gomplate
|
||||
- tests/run.sh
|
||||
|
||||
# deployment step disabled: swarm-test.autonomic.zone is down
|
||||
# - name: deployment
|
||||
# image: git.coopcloud.tech/coop-cloud/stack-ssh-deploy:latest
|
||||
# when:
|
||||
# event:
|
||||
# - push
|
||||
# branch:
|
||||
# - main
|
||||
# settings:
|
||||
# host: swarm-test.autonomic.zone
|
||||
# stack: wordpress
|
||||
# generate_secrets: true
|
||||
# purge: true
|
||||
# deploy_key:
|
||||
# from_secret: drone_ssh_swarm_test
|
||||
# networks:
|
||||
# - proxy
|
||||
# environment:
|
||||
# DOMAIN: wordpress.swarm-test.autonomic.zone
|
||||
# STACK_NAME: wordpress
|
||||
# LETS_ENCRYPT_ENV: production
|
||||
# SECRET_DB_PASSWORD_VERSION: v1
|
||||
# SECRET_DB_ROOT_PASSWORD_VERSION: v1
|
||||
# PHP_UPLOADS_CONF_VERSION: v1
|
||||
# ENTRYPOINT_CONF_VERSION: v1
|
||||
# HTACCESS_CONF_VERSION: v1
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- master
|
||||
- main
|
||||
---
|
||||
kind: pipeline
|
||||
name: generate recipe catalogue
|
||||
steps:
|
||||
- name: release a new version
|
||||
image: plugins/downstream
|
||||
settings:
|
||||
server: https://build.coopcloud.tech
|
||||
token:
|
||||
from_secret: drone_abra-bot_token
|
||||
fork: true
|
||||
repositories:
|
||||
- toolshed/auto-recipes-catalogue-json
|
||||
|
||||
trigger:
|
||||
event: tag
|
||||
|
||||
107
.env.sample
Normal file
107
.env.sample
Normal file
@ -0,0 +1,107 @@
|
||||
TYPE=wordpress
|
||||
#TIMEOUT=300
|
||||
ENABLE_AUTO_UPDATE=true
|
||||
COMPOSE_FILE="compose.yml"
|
||||
ENABLE_BACKUPS=true
|
||||
|
||||
DOMAIN=wordpress.example.com
|
||||
## Domain aliases
|
||||
#EXTRA_DOMAINS=', `www.wordpress.example.com`'
|
||||
# Redirects
|
||||
# All redirect domains have to be added to EXTRA_DOMAINS as well)
|
||||
# multiple redirects can be added by seperating them with a | character
|
||||
#REDIRECTS=www.wordpress.example.com
|
||||
LETS_ENCRYPT_ENV=production
|
||||
|
||||
# Setup Wordpress settings on each deploy:
|
||||
#POST_DEPLOY_CMDS="app core_install"
|
||||
|
||||
# Automatically install WordPress on first deploy (requires TITLE and ADMIN_EMAIL)
|
||||
#AUTO_INSTALL=1
|
||||
|
||||
# Enable auto-updates for plugins and themes on install/deploy (default: on)
|
||||
# Set to 0 to disable automatic plugin/theme updates
|
||||
#AUTO_UPDATES=1
|
||||
|
||||
# Optional settings, otherwise can be set in the installer
|
||||
# (Required for `app core_install`
|
||||
#TITLE="My Example Blog"
|
||||
#LOCALE="en_US" # de_DE
|
||||
#ADMIN_EMAIL=admin@example.com
|
||||
|
||||
# Every new user is per default subscriber, uncomment to change it
|
||||
#DEFAULT_USER_ROLE=administrator
|
||||
|
||||
# PHP composer for plugin installation
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.composer.yml"
|
||||
|
||||
# Self managed Wordpress for automatic updates
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.selfmanaged.yml"
|
||||
|
||||
#WORDPRESS_DEBUG=true
|
||||
|
||||
## Additional extensions
|
||||
#PHP_EXTENSIONS="calendar"
|
||||
|
||||
SECRET_DB_ROOT_PASSWORD_VERSION=v1
|
||||
SECRET_DB_PASSWORD_VERSION=v1
|
||||
SECRET_ADMIN_PASSWORD_VERSION=v1
|
||||
|
||||
# Mostly for compatibility with existing database dumps...
|
||||
#WORDPRESS_TABLE_PREFIX=wp_
|
||||
|
||||
# Multisite (see README)
|
||||
#MULTISITE=enable # either 'enable', 'subdomain' or 'subfolder'
|
||||
|
||||
# File upload settings
|
||||
#UPLOAD_MAX_SIZE=256M
|
||||
#UPLOAD_MAX_TIME=30
|
||||
|
||||
# Local SMTP relay
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.mailrelay.yml"
|
||||
#SMTP_HOST="postfix_relay_app"
|
||||
#MAIL_FROM="wordpress@example.com"
|
||||
|
||||
# Remote SMTP relay
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.mailrelay.yml:compose.smtp.yml"
|
||||
#SMTP_HOST="mail.example.com"
|
||||
#MAIL_FROM="wordpress@example.com"
|
||||
#SMTP_USER="wordpress@example.com" # optional, defaults to MAIL_FROM
|
||||
#SMTP_OVERRIDE_FROM=on # force "From" to MAIL_FROM, usually necessary
|
||||
#SMTP_PORT=587
|
||||
#SMTP_AUTH=on
|
||||
#SMTP_TLS=on
|
||||
#SECRET_SMTP_PASSWORD_VERSION=v1
|
||||
|
||||
# Authentik SSO
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.authentik.yml"
|
||||
#AUTHENTIK_DOMAIN=authentik.example.com
|
||||
#SECRET_AUTHENTIK_SECRET_VERSION=v1
|
||||
#SECRET_AUTHENTIK_ID_VERSION=v1
|
||||
#LOGIN_TYPE='auto'
|
||||
|
||||
# Matrix .well-known redirect
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.matrix.yml"
|
||||
#MATRIX_DOMAIN=matrix.example.com
|
||||
|
||||
# Allow remote connections to db
|
||||
# 🚩🚩 dangerous, use only for development sites!
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.public-db.yml
|
||||
|
||||
# Wide-open CORS
|
||||
# 🚩🚩 dangerous, use only for development sites!
|
||||
#CORS_ALLOW_ALL=1
|
||||
|
||||
# Disable the WordPress web installer (useful when migrating/importing a DB dump)
|
||||
#DISABLE_WEB_INSTALLER=1
|
||||
|
||||
# FTP
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp.yml"
|
||||
#SECRET_FTP_PASS_VERSION=v1
|
||||
# You can use a Port between 2220-2225
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2220.yml"
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2221.yml"
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2222.yml"
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2223.yml"
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2224.yml"
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2225.yml"
|
||||
@ -1,38 +0,0 @@
|
||||
export DOMAIN=wordpress.example.com
|
||||
## Domain aliases
|
||||
#export EXTRA_DOMAINS=', `www.wordpress.example.com`'
|
||||
|
||||
export STACK_NAME=wordpress
|
||||
export LETS_ENCRYPT_ENV=production
|
||||
|
||||
export DB_ROOT_PASSWORD_VERSION=v1
|
||||
export DB_PASSWORD_VERSION=v1
|
||||
|
||||
# Multisite
|
||||
#export WORDPRESS_CONFIG_EXTRA="\
|
||||
# define('WP_CACHE', false);\
|
||||
# define('WP_ALLOW_MULTISITE', true );"
|
||||
|
||||
# Multisite phase 2 (see README)
|
||||
#export WORDPRESS_CONFIG_EXTRA="\
|
||||
# define('WP_CACHE', false);\
|
||||
# define('WP_ALLOW_MULTISITE', true );\
|
||||
# define('MULTISITE', true);\
|
||||
# define('SUBDOMAIN_INSTALL', true);\
|
||||
# define('DOMAIN_CURRENT_SITE', '${DOMAIN}');\
|
||||
# define('PATH_CURRENT_SITE', '/');\
|
||||
# define('SITE_ID_CURRENT_SITE', 1);\
|
||||
# define('BLOG_ID_CURRENT_SITE', 1);\
|
||||
# define('FORCE_SSL_ADMIN', true );\
|
||||
# define('COOKIE_DOMAIN', \$_SERVER['HTTP_HOST']);"
|
||||
|
||||
# Backups
|
||||
#export COMPOSE_FILE="compose.yml:compose.backup.yml"
|
||||
|
||||
# SMTP
|
||||
#export COMPOSE_FILE="compose.yml:compose.mailrelay.yml"
|
||||
#export SMTP_HOST="postfix_relay_app"
|
||||
#export MAIL_FROM="wordpress@example.com"
|
||||
#
|
||||
#export MSMTP_CONF_VERSION=v1
|
||||
#export ENTRYPOINT_MAILRELAY_CONF_VERSION=v1
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
@ -1 +1,22 @@
|
||||
# direnv
|
||||
/.envrc
|
||||
|
||||
# Environment files (may contain secrets)
|
||||
.env
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# OS metadata
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Editor/IDE
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
*.bak
|
||||
.idea/
|
||||
.vscode/
|
||||
.project
|
||||
.classpath
|
||||
|
||||
185
README.md
185
README.md
@ -1,59 +1,158 @@
|
||||
# wordpress
|
||||
# Wordpress
|
||||
|
||||
[](https://drone.autonomic.zone/compose-stacks/wordpress)
|
||||
[](https://build.coopcloud.tech/coop-cloud/wordpress)
|
||||
|
||||
Coöp Cloud + [Wordpress](https://wordpress.org) = 🥳
|
||||
|
||||
1. Set up Docker Swarm and [`abra`][abra]
|
||||
2. Deploy [`compose-stacks/traefik`][compose-traefik]
|
||||
3. `cp .envrc.sample .envrc`
|
||||
4. Edit `.envrc` - be sure to change `$DOMAIN` to something that resolves to
|
||||
your Docker swarm box
|
||||
5. `direnv allow` (or `. .envrc`)
|
||||
6. Generate secrets:
|
||||
```
|
||||
abra secret_generate db_password v1
|
||||
abra secret_generate db_root_password v1
|
||||
```
|
||||
7. `abra deploy`
|
||||
8. Open the configured domain in your browser to finish set-up
|
||||
9. `abra run wordpress chown www-data:www-data /var/www/html/wp-content` to fix
|
||||
file permissions (see #3)
|
||||
<!-- metadata -->
|
||||
|
||||
## Network (Multi-site)
|
||||
* **Category**: Apps
|
||||
* **Status**: 4
|
||||
* **Image**: [`wordpress`](https://hub.docker.com/_/wordpress), 4, upstream
|
||||
* **Healthcheck**: Yes
|
||||
* **Backups**: Yes
|
||||
* **Email**: 3
|
||||
* **Tests**: 2
|
||||
* **SSO**: 2
|
||||
|
||||
_(Only tested using subdomains)_
|
||||
<!-- endmetadata -->
|
||||
|
||||
1. Set up as above
|
||||
2. Uncomment the first `# Multisite` section in `.envrc`
|
||||
3. `direnv allow` (or re-run `source .envrc`)
|
||||
4. `abra deploy`
|
||||
5. Log into the Wordpress admin dashboard, go to Tools » Network Setup
|
||||
6. Don't worry about the suggested file changes
|
||||
7. Comment out the first `# Multisite` section in `.envrc` and uncomment the
|
||||
`# Multisite phase 2` section
|
||||
8. `direnv allow` (or re-run `source .envrc`)
|
||||
9. `abra deploy`
|
||||
10. FIXME setting up SSL / routing
|
||||
## Quick start
|
||||
|
||||
## Installing a custom theme
|
||||
* `abra app new wordpress`
|
||||
* `abra app config <app-name>`
|
||||
* `abra app secret generate -a <app-name>`
|
||||
* `abra app deploy <app-name>`
|
||||
* `abra app cmd <app-name> app core_install`
|
||||
|
||||
`abra cp ~/path/to/local/theme wordpress:/var/www/html/wp-content/themes/`
|
||||
### Admin password
|
||||
|
||||
## Backups
|
||||
By default, WordPress generates a random admin password during `core_install` and prints it
|
||||
to the command output. To set a known password managed as a Docker secret:
|
||||
|
||||
1. Edit `.envrc` and uncomment the `export COMPOSE_FILE="compose.yml:compose.backup.yml"` line
|
||||
2. `direnv allow`
|
||||
3. `abra deploy`
|
||||
1. Uncomment `SECRET_ADMIN_PASSWORD_VERSION=v1` in your app config
|
||||
2. `abra app secret generate -a <app-name>` (creates a random password)
|
||||
3. `abra app deploy <app-name>`
|
||||
4. `abra app cmd <app-name> app core_install`
|
||||
|
||||
The password is stored in `<app-name>_admin_password_v1` — you can view it with
|
||||
`abra app secret show <app-name> admin_password`.
|
||||
|
||||
### Auto-install on first deploy
|
||||
|
||||
To skip the manual `abra app cmd ... core_install` step, enable auto-install:
|
||||
|
||||
1. Set `AUTO_INSTALL=1` in your app config
|
||||
2. Uncomment `TITLE` and `ADMIN_EMAIL` (also `LOCALE` if needed)
|
||||
3. (Optional) Uncomment `SECRET_ADMIN_PASSWORD_VERSION=v1` and run `abra app secret generate`
|
||||
4. `abra app deploy <app-name>`
|
||||
|
||||
On first deploy, the container will wait for the database, then automatically run
|
||||
`wp core install` and configure the site. It only runs once — subsequent deploys detect
|
||||
WordPress is already installed and skip.
|
||||
|
||||
### Plugin and theme auto-updates
|
||||
|
||||
By default, plugin and theme auto-updates are enabled during install and deploy.
|
||||
To disable this:
|
||||
|
||||
1. Set `AUTO_UPDATES=0` in your app config
|
||||
2. `abra app deploy <app-name>`
|
||||
|
||||
This affects `abra app cmd <app-name> app core_install`, `abra app cmd <app-name> app update`,
|
||||
and the `AUTO_INSTALL` background process.
|
||||
|
||||
## Disable the web installer
|
||||
|
||||
When migrating a site (importing a DB dump from an existing install), the web-based
|
||||
WordPress installer at `wp-admin/install.php` is a security risk — someone could
|
||||
accidentally run it and overwrite your data. To block it:
|
||||
|
||||
1. Set `DISABLE_WEB_INSTALLER=1` in your app config
|
||||
2. `abra app deploy <app-name>`
|
||||
|
||||
Apache inside the container will deny all requests to `wp-admin/install.php`. The CLI-based
|
||||
`abra app cmd <app-name> app core_install` still works unaffected.
|
||||
|
||||
## Email
|
||||
|
||||
1. Deploy `postfix-relay`
|
||||
2. Edit `.envrc` and uncomment the email lines; change `MAIL_FROM` to make sure
|
||||
the domain is the same as `postfix-relay`'s `$DOMAIN` or in its
|
||||
`$EXTRA_SENDER_DOMAINS`
|
||||
3. `direnv allow` (or `source .envrc`)
|
||||
7. `abra deploy`
|
||||
There is a local or remote SMTP relay configuration available.
|
||||
|
||||
* **local**: `COMPOSE_FILE=compose.yml:compose.mailrelay.yml`
|
||||
* **remote**: `COMPOSE_FILE=compose.yml:compose.mailrelay.yml:compose.smtp.yml`
|
||||
|
||||
Below are the instructions for the local relay.
|
||||
|
||||
1. Deploy [`postfix-relay`][cc-postfix-relay]
|
||||
2. `abra app config <app-name>`, and uncomment the email lines; change
|
||||
`MAIL_FROM` to make sure the domain is the same as `postfix-relay`'s
|
||||
`$DOMAIN` or in its `$EXTRA_SENDER_DOMAINS`
|
||||
3. `abra app deploy <app-name>`
|
||||
|
||||
## WP-CLI
|
||||
|
||||
You can either run using `abra app cmd`:
|
||||
```bash
|
||||
abra app cmd <app-name> app wp -- core check-update --major
|
||||
```
|
||||
|
||||
Or by entering the app shell:
|
||||
1. `abra app run <app-name> app bash`
|
||||
2. `su -s /bin/bash www-data -c "wp core check-update --major"`
|
||||
|
||||
## Network (Multi-site)
|
||||
|
||||
1. Set up as above
|
||||
2. `abra app config <app-name>`, and uncomment `#MULTISITE=enable`
|
||||
3. `abra app deploy <app-name>`
|
||||
4. Log into the WordPress admin dashboard, go to **Tools → Network Setup**
|
||||
5. Don't worry about the suggested file changes
|
||||
6. `abra app config <app-name>` again and set `MULTISITE` to either `subdomain` or `subfolder` depending on your setup.
|
||||
7. `abra app deploy <app-name>`
|
||||
|
||||
## Installing a custom theme
|
||||
|
||||
`abra app cp <app-name> ~/path/to/local/theme wordpress:/var/www/html/wp-content/themes/`
|
||||
|
||||
## Authentik Integration
|
||||
|
||||
Configure the following envs via `abra app config <app-name>`:
|
||||
```bash
|
||||
COMPOSE_FILE="$COMPOSE_FILE:compose.authentik.yml"
|
||||
AUTHENTIK_DOMAIN=authentik.example.com
|
||||
AUTHENTIK_SECRET_NAME=authentik_example_com_wordpress_secret_v1 # the same as in authentik
|
||||
AUTHENTIK_ID_NAME=authentik_example_com_wordpress_id_v1 # the same as in authentik
|
||||
```
|
||||
|
||||
`abra app cmd <app-name> app set_authentik`
|
||||
|
||||
## Tests
|
||||
|
||||
Run the full test suite for this repository:
|
||||
|
||||
```sh
|
||||
bash tests/run.sh
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
The test suite uses several tools. Install them with your equivalent of:
|
||||
|
||||
```sh
|
||||
brew install shellcheck gomplate
|
||||
```
|
||||
Some tests skip gracefully if their dependencies are missing.
|
||||
|
||||
## Migrate from a non-Co-op Cloud WordPress install
|
||||
|
||||
Make a `.tar.gz` backup of the site's `wp-content` dir and a `.sql.gz` backup of the database.
|
||||
|
||||
1. `abra app wp.example.com restore app wp-content.tar.gz`
|
||||
2. `abra app wp.example.com restore db wordpress.sql.gz`
|
||||
|
||||
Lastly, if there's a domain name change, run a search and replace:
|
||||
`abra app wp.example.com wp "search-replace https://old.example.com https://wp.example.com"`
|
||||
|
||||
[abra]: https://git.autonomic.zone/autonomic-cooperative/abra
|
||||
[compose-traefik]: https://git.autonomic.zone/compose-stacks/traefik
|
||||
[cc-traefik]: https://git.autonomic.zone/coop-cloud/traefik
|
||||
[cc-postfix-relay]: https://git.autonomic.zone/coop-cloud/postfix-relay
|
||||
|
||||
120
abra.sh
Normal file
120
abra.sh
Normal file
@ -0,0 +1,120 @@
|
||||
export PHP_UPLOADS_CONF_VERSION=v4
|
||||
export ENTRYPOINT_CONF_VERSION=v10
|
||||
export ENTRYPOINT_MAILRELAY_CONF_VERSION=v2
|
||||
export MSMTP_CONF_VERSION=v4
|
||||
export HTACCESS_CONF_VERSION=v3
|
||||
export USERS_CONF_VERSION=v1
|
||||
|
||||
wp() {
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp $*"
|
||||
}
|
||||
|
||||
update() {
|
||||
wp "core update-db"
|
||||
wp "plugin update --all"
|
||||
if [ "$AUTO_UPDATES" != "0" ]; then
|
||||
wp "plugin auto-updates enable --all"
|
||||
fi
|
||||
wp "theme update --all"
|
||||
if [ "$AUTO_UPDATES" != "0" ]; then
|
||||
wp "theme auto-updates enable --all"
|
||||
fi
|
||||
wp "language core update"
|
||||
wp "language plugin update --all"
|
||||
wp "language theme update --all"
|
||||
}
|
||||
|
||||
core_install(){
|
||||
ADMIN=admin
|
||||
if [ -n "$AUTHENTIK_DOMAIN" ]
|
||||
then
|
||||
ADMIN=akadmin
|
||||
fi
|
||||
chown www-data:www-data -R /var/www/html/wp-content
|
||||
ADMIN_PASSWORD=$(cat /run/secrets/admin_password 2>/dev/null | xargs || true)
|
||||
ADMIN_PASS_ARG=""
|
||||
if [ -n "$ADMIN_PASSWORD" ]; then
|
||||
ADMIN_PASS_ARG="--admin_password=$ADMIN_PASSWORD"
|
||||
fi
|
||||
wp "core install --url=$DOMAIN --title=\"$TITLE\" --admin_user=$ADMIN --admin_email=$ADMIN_EMAIL --locale=$LOCALE --skip-email $ADMIN_PASS_ARG"
|
||||
wp "language core install $LOCALE"
|
||||
wp "site switch-language $LOCALE"
|
||||
wp "rewrite structure '/%year%/%monthnum%/%day%/%postname%/'"
|
||||
if [ -n "$DEFAULT_USER_ROLE" ]
|
||||
then
|
||||
wp "option set default_role $DEFAULT_USER_ROLE"
|
||||
else
|
||||
wp "option set default_role subscriber"
|
||||
fi
|
||||
if [ "$AUTO_UPDATES" != "0" ]; then
|
||||
wp "theme auto-updates enable --all"
|
||||
wp 'plugin auto-updates enable --all' || true
|
||||
fi
|
||||
}
|
||||
|
||||
enable_auto_updates(){
|
||||
wp "plugin deactivate disable-update-notifications --allow-root"
|
||||
wp "plugin uninstall disable-update-notifications --allow-root"
|
||||
wp "option delete disable_notification_setting --allow-root"
|
||||
wp "plugin auto-updates enable --all --allow-root"
|
||||
wp "theme auto-updates enable --all --allow-root"
|
||||
}
|
||||
|
||||
disable_auto_updates(){
|
||||
wp "plugin install --activate disable-update-notifications"
|
||||
wp "option update disable_notification_setting --format=json '{\"dpun_setting\":false,\"dwtu_setting\":false,\"dwcun_setting\":true}'"
|
||||
}
|
||||
|
||||
set_authentik(){
|
||||
AUTHENTIK_SECRET=$(cat /run/secrets/authentik_secret)
|
||||
AUTHENTIK_ID=$(cat /run/secrets/authentik_id)
|
||||
if [ -z $LOGIN_TYPE ]
|
||||
then
|
||||
LOGIN_TYPE='button'
|
||||
fi
|
||||
wp "user create akadmin admin@example.com --role=administrator"
|
||||
wp "plugin install --activate daggerhart-openid-connect-generic"
|
||||
wp 'plugin auto-updates enable daggerhart-openid-connect-generic'
|
||||
wp "option update --format=json openid_connect_generic_settings '
|
||||
{
|
||||
\"login_type\":\"$LOGIN_TYPE\",
|
||||
\"client_id\":\"$AUTHENTIK_ID\",
|
||||
\"client_secret\":\"$AUTHENTIK_SECRET\",
|
||||
\"scope\":\"email profile openid\",
|
||||
\"endpoint_login\":\"https://$AUTHENTIK_DOMAIN/application/o/authorize/\",
|
||||
\"endpoint_userinfo\":\"https://$AUTHENTIK_DOMAIN/application/o/userinfo/\",
|
||||
\"endpoint_token\":\"https://$AUTHENTIK_DOMAIN/application/o/token/\",
|
||||
\"endpoint_end_session\":\"https://$AUTHENTIK_DOMAIN/application/o/wordpress/end-session/\",
|
||||
\"endpoint_jwks\":\"https://$AUTHENTIK_DOMAIN/application/o/wordpress/jwks/\",
|
||||
\"issuer\":\"https://$AUTHENTIK_DOMAIN/application/o/wordpress/\",
|
||||
\"acr_values\":\"\",
|
||||
\"identity_key\":\"preferred_username\",
|
||||
\"no_sslverify\":\"0\",
|
||||
\"http_request_timeout\":\"30\",
|
||||
\"enforce_privacy\":\"0\",
|
||||
\"alternate_redirect_uri\":\"1\",
|
||||
\"nickname_key\":\"preferred_username\",
|
||||
\"email_format\":\"{email}\",
|
||||
\"displayname_format\":\"\",
|
||||
\"identify_with_username\":\"1\",
|
||||
\"state_time_limit\":\"\",
|
||||
\"token_refresh_enable\":\"1\",
|
||||
\"link_existing_users\":\"1\",
|
||||
\"create_if_does_not_exist\":\"1\",
|
||||
\"redirect_user_back\":\"0\",
|
||||
\"redirect_on_logout\":\"1\",
|
||||
\"enable_logging\":\"0\",
|
||||
\"log_limit\":\"1000\"
|
||||
}'"
|
||||
wp "rewrite flush"
|
||||
wp "cache flush"
|
||||
|
||||
}
|
||||
|
||||
fix_mysql() {
|
||||
echo "ALTER TABLE mysql.column_stats MODIFY histogram longblob; ALTER TABLE mysql.column_stats MODIFY hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB');" | mysql -u root -p$(cat /run/secrets/db_root_password)
|
||||
}
|
||||
|
||||
show_plugins() {
|
||||
wp "plugin list --fields=name,status,wporg_status,version,update_version,auto_update,tested_up_to,wporg_last_updated"
|
||||
}
|
||||
16
alaconnect.yml
Normal file
16
alaconnect.yml
Normal file
@ -0,0 +1,16 @@
|
||||
authentik:
|
||||
uncomment:
|
||||
- compose.authentik.yml
|
||||
- AUTHENTIK_DOMAIN
|
||||
- SECRET_AUTHENTIK_SECRET_VERSION
|
||||
- SECRET_AUTHENTIK_ID_VERSION
|
||||
- LOGIN_TYPE
|
||||
inital-hooks:
|
||||
- app set_authentik
|
||||
shared_secrets:
|
||||
wordpress_secret: authentik_secret
|
||||
wordpress_id: authentik_id
|
||||
matrix:
|
||||
uncomment:
|
||||
- compose.matrix.yml
|
||||
- MATRIX_DOMAIN
|
||||
@ -1,3 +0,0 @@
|
||||
# Notes
|
||||
|
||||
- The only thing different between [fr_singlesite_wordpress.yml](./fr_singlesite_wordpress.yml) and [fr_microsites_wordpress.yml](./fr_microsites_wordpress.yml) is the `BORGBASE_REPO` environment variable and the `backup_bot_singlesite_passwd_v1`/`backup_bot_multisite_passwd_v1` secret. These are the two details which are needed for Borgmatic to know how to differentiate between each repository on the Borgbase side (where our backups are stored). Sooo, there could most definitely be a reduction in boilerplate here but I was just moving super fast and wanted to get the backup work done.
|
||||
@ -1,36 +0,0 @@
|
||||
location:
|
||||
source_directories:
|
||||
- /var/www/html/wp-content
|
||||
repositories:
|
||||
- {{ env "BORGBASE_REPO" }}
|
||||
|
||||
storage:
|
||||
compression: auto,zstd
|
||||
encryption_passphrase: {{ secret "backup_bot_password" }}
|
||||
archive_name_format: "{hostname}-{now}"
|
||||
ssh_command: "ssh -o 'StrictHostKeyChecking no' -i /run/secrets/backup_bot_ssh_key"
|
||||
|
||||
retention:
|
||||
keep_daily: 3
|
||||
keep_weekly: 4
|
||||
keep_monthly: 12
|
||||
keep_yearly: 2
|
||||
prefix: "{hostname}-"
|
||||
|
||||
consistency:
|
||||
checks:
|
||||
- disabled
|
||||
check_last: 3
|
||||
prefix: "{hostname}-"
|
||||
|
||||
hooks:
|
||||
before_backup:
|
||||
- echo "`date` - Starting backup"
|
||||
after_backup:
|
||||
- echo "`date` - Finished backup"
|
||||
mysql_databases:
|
||||
- name: {{ env "DB_TABLE" }}
|
||||
hostname: {{ env "DB_HOST" }}
|
||||
port: 3306
|
||||
username: {{ env "DB_USER" }}
|
||||
password: {{ secret "db_password" }}
|
||||
@ -1,47 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
backupbot:
|
||||
image: "decentral1se/backup-bot:latest"
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- "wordpress_content:/var/www/html/wp-content/"
|
||||
secrets:
|
||||
- source: backup_bot_ssh_key
|
||||
mode: 0400
|
||||
- backup_bot_password
|
||||
- db_password
|
||||
configs:
|
||||
- source: borgmatic_config_yml
|
||||
target: /etc/borgmatic/config.yaml
|
||||
environment:
|
||||
- BORGBASE_REPO="bp5oj726@bp5oj726.repo.borgbase.com:repo"
|
||||
- DB_HOST=mariadb
|
||||
- DB_TABLE=wordpress
|
||||
- DB_USER=wordpress
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 0
|
||||
labels:
|
||||
- "swarm.cronjob.enable=true"
|
||||
- "swarm.cronjob.schedule=0 2 * * *" # At 02:00
|
||||
restart_policy:
|
||||
condition: none
|
||||
networks:
|
||||
- backend
|
||||
|
||||
configs:
|
||||
borgmatic_config_yml:
|
||||
name: borgmatic_config_yml_v1
|
||||
file: backup.d/borgmatic.yml
|
||||
template_driver: golang
|
||||
|
||||
secrets:
|
||||
backup_bot_ssh_key:
|
||||
name: backup_bot_ssh_key_v1
|
||||
external: true
|
||||
backup_bot_password:
|
||||
name: backup_bot_multisite_passwd_v1
|
||||
external: true
|
||||
@ -1,47 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
backupbot:
|
||||
image: "decentral1se/backup-bot:latest"
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- "wordpress_content:/var/www/html/wp-content/"
|
||||
secrets:
|
||||
- source: backup_bot_ssh_key
|
||||
mode: 0400
|
||||
- backup_bot_password
|
||||
- db_password
|
||||
configs:
|
||||
- source: borgmatic_config_yml
|
||||
target: /etc/borgmatic/config.yaml
|
||||
environment:
|
||||
- BORGBASE_REPO="l32s99em@l32s99em.repo.borgbase.com:repo"
|
||||
- DB_HOST=mariadb
|
||||
- DB_TABLE=wordpress
|
||||
- DB_USER=wordpress
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 0
|
||||
labels:
|
||||
- "swarm.cronjob.enable=true"
|
||||
- "swarm.cronjob.schedule=0 2 * * *" # At 02:00
|
||||
restart_policy:
|
||||
condition: none
|
||||
networks:
|
||||
- backend
|
||||
|
||||
configs:
|
||||
borgmatic_config_yml:
|
||||
name: borgmatic_config_yml_v1
|
||||
file: backup.d/borgmatic.yml
|
||||
template_driver: golang
|
||||
|
||||
secrets:
|
||||
backup_bot_ssh_key:
|
||||
name: backup_bot_ssh_key_v1
|
||||
external: true
|
||||
backup_bot_password:
|
||||
name: backup_bot_singlesite_passwd_v1
|
||||
external: true
|
||||
@ -1,65 +0,0 @@
|
||||
# #############################################################################
|
||||
# NOTE(decentral1se): this is a test compose.yml to test abra based deployments
|
||||
# #############################################################################
|
||||
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
wordpress:
|
||||
image: "wordpress:5.5.1"
|
||||
networks:
|
||||
- backend
|
||||
- proxy
|
||||
environment:
|
||||
- WORDPRESS_DB_HOST=mariadb
|
||||
- WORDPRESS_DB_USER=wordpress
|
||||
- WORDPRESS_DB_PASSWORD_FILE=/run/secrets/db_password
|
||||
- WORDPRESS_DB_NAME=wordpress
|
||||
secrets:
|
||||
- db_password
|
||||
deploy:
|
||||
update_config:
|
||||
failure_action: rollback
|
||||
order: start-first
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.routers.${NAME}.tls=true"
|
||||
- "traefik.http.services.${NAME}.loadbalancer.server.port=80"
|
||||
- "traefik.http.routers.${NAME}.rule=Host(`${DOMAIN}`)"
|
||||
- "traefik.http.routers.${NAME}.tls.certresolver=production"
|
||||
- "traefik.http.routers.${NAME}.entrypoints=web-secure"
|
||||
|
||||
mariadb:
|
||||
image: "mariadb:10.5"
|
||||
volumes:
|
||||
- "mariadb:/var/lib/mysql"
|
||||
networks:
|
||||
- backend
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_password
|
||||
- MYSQL_DATABASE=wordpress
|
||||
- MYSQL_USER=wordpress
|
||||
- MYSQL_PASSWORD_FILE=/run/secrets/db_password
|
||||
secrets:
|
||||
- db_password
|
||||
- db_root_password
|
||||
|
||||
networks:
|
||||
backend:
|
||||
driver: overlay
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
mariadb:
|
||||
wordpress_content:
|
||||
|
||||
secrets:
|
||||
db_root_password:
|
||||
external: true
|
||||
name: ${DB_ROOT_PASSWD}
|
||||
db_password:
|
||||
external: true
|
||||
name: ${DB_PASSWD}
|
||||
14
compose.authentik.yml
Normal file
14
compose.authentik.yml
Normal file
@ -0,0 +1,14 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
app:
|
||||
secrets:
|
||||
- authentik_secret
|
||||
- authentik_id
|
||||
|
||||
secrets:
|
||||
authentik_secret:
|
||||
external: true
|
||||
name: ${STACK_NAME}_authentik_secret_${SECRET_AUTHENTIK_SECRET_VERSION}
|
||||
authentik_id:
|
||||
external: true
|
||||
name: ${STACK_NAME}_authentik_id_${SECRET_AUTHENTIK_ID_VERSION}
|
||||
14
compose.composer.yml
Normal file
14
compose.composer.yml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
volumes:
|
||||
- "composer:/var/www/html/composer"
|
||||
environment:
|
||||
- ENABLE_COMPOSER=1
|
||||
- COMPOSER=composer/composer.json
|
||||
- COMPOSER_VENDOR_DIR=composer/vendor
|
||||
|
||||
volumes:
|
||||
composer:
|
||||
7
compose.ftp-2220.yml
Normal file
7
compose.ftp-2220.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2220:22
|
||||
7
compose.ftp-2221.yml
Normal file
7
compose.ftp-2221.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2221:22
|
||||
7
compose.ftp-2222.yml
Normal file
7
compose.ftp-2222.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2222:22
|
||||
7
compose.ftp-2223.yml
Normal file
7
compose.ftp-2223.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2223:22
|
||||
7
compose.ftp-2224.yml
Normal file
7
compose.ftp-2224.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2224:22
|
||||
7
compose.ftp-2225.yml
Normal file
7
compose.ftp-2225.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2220:22
|
||||
24
compose.ftp.yml
Normal file
24
compose.ftp.yml
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
image: atmoz/sftp:alpine
|
||||
secrets:
|
||||
- ftp_pass
|
||||
volumes:
|
||||
- "wordpress_content:/home/ftp_user/wp-content"
|
||||
configs:
|
||||
- source: users_conf
|
||||
target: /etc/sftp/users.conf
|
||||
|
||||
secrets:
|
||||
ftp_pass:
|
||||
name: ${STACK_NAME}_ftp_pass_${SECRET_FTP_PASS_VERSION}
|
||||
external: true
|
||||
|
||||
configs:
|
||||
users_conf:
|
||||
name: ${STACK_NAME}_users_conf_${USERS_CONF_VERSION}
|
||||
file: users.conf.tmpl
|
||||
template_driver: golang
|
||||
@ -1,31 +1,26 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
|
||||
services:
|
||||
app:
|
||||
entrypoint: /docker-entrypoint.sh
|
||||
entrypoint: /docker-entrypoint.mailrelay.sh
|
||||
environment:
|
||||
- SMTP_HOST=${SMTP_HOST}
|
||||
- SMTP_PORT=${SMTP_PORT:-25}
|
||||
- MAIL_FROM=${MAIL_FROM}
|
||||
networks:
|
||||
- mail
|
||||
configs:
|
||||
- source: mstmp_conf
|
||||
target: /etc/msmtprc
|
||||
- source: entrypoint_conf
|
||||
target: /docker-entrypoint.sh
|
||||
- source: entrypoint_mailrelay_conf
|
||||
target: /docker-entrypoint.mailrelay.sh
|
||||
mode: 0555
|
||||
|
||||
networks:
|
||||
mail:
|
||||
external: true
|
||||
|
||||
configs:
|
||||
mstmp_conf:
|
||||
name: ${STACK_NAME}_mstmp_conf_${MSMTP_CONF_VERSION}
|
||||
file: msmtp.conf.tmpl
|
||||
template_driver: golang
|
||||
entrypoint_conf:
|
||||
entrypoint_mailrelay_conf:
|
||||
name: ${STACK_NAME}_entrypoint_mailrelay_${ENTRYPOINT_MAILRELAY_CONF_VERSION}
|
||||
file: entrypoint.mailrelay.sh.tmpl
|
||||
template_driver: golang
|
||||
|
||||
10
compose.matrix.yml
Normal file
10
compose.matrix.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.http.routers.${STACK_NAME}.middlewares=${STACK_NAME}-redirect-matrix-well-known"
|
||||
- "traefik.http.middlewares.${STACK_NAME}-redirect-matrix-well-known.redirectregex.regex=^https://(.*)/.well-known/matrix/(.*)"
|
||||
- "traefik.http.middlewares.${STACK_NAME}-redirect-matrix-well-known.redirectregex.replacement=https://${MATRIX_DOMAIN}/.well-known/matrix/$$2"
|
||||
9
compose.public-db.yml
Normal file
9
compose.public-db.yml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
db:
|
||||
ports:
|
||||
- target: 3306
|
||||
published: 3306
|
||||
mode: host
|
||||
21
compose.selfmanaged.yml
Normal file
21
compose.selfmanaged.yml
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: "wordpress:7.0.0"
|
||||
volumes:
|
||||
- "wordpress:/var/www/html/"
|
||||
environment:
|
||||
WORDPRESS_CONFIG_EXTRA: |
|
||||
define( 'AUTOMATIC_UPDATER_DISABLED', false );
|
||||
define( 'WP_AUTO_UPDATE_CORE', true );
|
||||
define( 'FS_METHOD', 'direct' );
|
||||
${WORDPRESS_CONFIG_EXTRA}
|
||||
|
||||
ftp:
|
||||
volumes:
|
||||
- "wordpress:/home/ftp_user/"
|
||||
|
||||
volumes:
|
||||
wordpress:
|
||||
19
compose.smtp.yml
Normal file
19
compose.smtp.yml
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
secrets:
|
||||
- smtp_password
|
||||
environment:
|
||||
- SMTP_HOST
|
||||
- SMTP_PORT=${SMTP_PORT:-25}
|
||||
- SMTP_AUTH
|
||||
- SMTP_TLS
|
||||
- MAIL_FROM
|
||||
- SMTP_OVERRIDE_FROM
|
||||
|
||||
secrets:
|
||||
smtp_password:
|
||||
name: ${STACK_NAME}_smtp_password_${SECRET_SMTP_PASSWORD_VERSION}
|
||||
external: true
|
||||
74
compose.yml
74
compose.yml
@ -3,20 +3,42 @@ version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: "wordpress:5.5.1"
|
||||
image: "wordpress:7.0.0"
|
||||
volumes:
|
||||
- "wordpress_content:/var/www/html/wp-content/"
|
||||
networks:
|
||||
- backend
|
||||
- proxy
|
||||
environment:
|
||||
- WORDPRESS_DB_HOST=db
|
||||
- WORDPRESS_DB_USER=wordpress
|
||||
- WORDPRESS_DB_PASSWORD_FILE=/run/secrets/db_password
|
||||
- WORDPRESS_DB_NAME=wordpress
|
||||
- WORDPRESS_CONFIG_EXTRA=${WORDPRESS_CONFIG_EXTRA}
|
||||
WORDPRESS_CONFIG_EXTRA: |
|
||||
define( 'AUTOMATIC_UPDATER_DISABLED', false );
|
||||
define( 'WP_AUTO_UPDATE_CORE', false );
|
||||
${WORDPRESS_CONFIG_EXTRA}
|
||||
PAGER: more
|
||||
WORDPRESS_DB_HOST: db
|
||||
WORDPRESS_DB_USER: wordpress
|
||||
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
|
||||
WORDPRESS_DB_NAME: wordpress
|
||||
WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX:-wp_}
|
||||
PHP_EXTENSIONS: ${PHP_EXTENSIONS}
|
||||
CORS_ALLOW_ALL:
|
||||
DISABLE_WEB_INSTALLER:
|
||||
AUTO_INSTALL:
|
||||
AUTO_UPDATES:
|
||||
COMPOSER:
|
||||
SECRET_ADMIN_PASSWORD_VERSION:
|
||||
secrets:
|
||||
- db_password
|
||||
- admin_password
|
||||
configs:
|
||||
- source: php_uploads_conf
|
||||
target: /usr/local/etc/php/conf.d/uploads.ini
|
||||
- source: entrypoint_conf
|
||||
target: /docker-entrypoint.sh
|
||||
mode: 0555
|
||||
- source: htaccess_conf
|
||||
target: /var/www/html/.htaccess
|
||||
entrypoint: /docker-entrypoint.sh
|
||||
depends_on:
|
||||
- db
|
||||
healthcheck:
|
||||
@ -31,18 +53,24 @@ services:
|
||||
order: start-first
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.swarm.network=proxy"
|
||||
- "traefik.http.routers.${STACK_NAME}.tls=true"
|
||||
- "traefik.http.services.${STACK_NAME}.loadbalancer.server.port=80"
|
||||
- "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`${EXTRA_DOMAINS})"
|
||||
# 3wc: this rule works for routing, but not for generating certificates
|
||||
# see https://git.autonomic.zone/compose-stacks/planning/issues/14
|
||||
# see https://git.autonomic.zone/coop-cloud/planning/issues/14
|
||||
#- "traefik.http.routers.${STACK_NAME}.rule=HostRegexp(`{subdomain:.+}.${DOMAIN}`, `${DOMAIN}`)"
|
||||
- "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}"
|
||||
- "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure"
|
||||
- "traefik.http.routers.${STACK_NAME}.middlewares=${STACK_NAME}-redirect"
|
||||
- "traefik.http.middlewares.${STACK_NAME}-redirect.redirectregex.regex=^https://(${REDIRECTS})/(.*)"
|
||||
- "traefik.http.middlewares.${STACK_NAME}-redirect.redirectregex.replacement=https://${DOMAIN}/$${2}"
|
||||
- "traefik.http.middlewares.${STACK_NAME}-redirect.redirectregex.permanent=true"
|
||||
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT}"
|
||||
- "coop-cloud.${STACK_NAME}.version=3.0.0+7.0.0"
|
||||
|
||||
db:
|
||||
image: "mariadb:10.5"
|
||||
image: "mariadb:12.3"
|
||||
volumes:
|
||||
- "mariadb:/var/lib/mysql"
|
||||
networks:
|
||||
@ -55,10 +83,15 @@ services:
|
||||
secrets:
|
||||
- db_password
|
||||
- db_root_password
|
||||
deploy:
|
||||
labels:
|
||||
backupbot.backup: "${ENABLE_BACKUPS:-true}"
|
||||
backupbot.backup.pre-hook: "mariadb-dump --single-transaction -u root -p\"$$(cat /run/secrets/db_root_password)\" wordpress | gzip > /var/lib/mysql/dump.sql.gz"
|
||||
backupbot.backup.volumes.mariadb.path: "dump.sql.gz"
|
||||
backupbot.restore.post-hook: "gzip -d /var/lib/mysql/dump.sql.gz && mariadb -u root -p\"$$(cat /run/secrets/db_root_password)\" wordpress < /var/lib/mysql/dump.sql && rm -f /var/lib/mysql/dump.sql"
|
||||
|
||||
networks:
|
||||
backend:
|
||||
driver: overlay
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
@ -69,7 +102,24 @@ volumes:
|
||||
secrets:
|
||||
db_root_password:
|
||||
external: true
|
||||
name: ${STACK_NAME}_db_root_password_${DB_ROOT_PASSWORD_VERSION}
|
||||
name: ${STACK_NAME}_db_root_password_${SECRET_DB_ROOT_PASSWORD_VERSION}
|
||||
db_password:
|
||||
external: true
|
||||
name: ${STACK_NAME}_db_password_${DB_PASSWORD_VERSION}
|
||||
name: ${STACK_NAME}_db_password_${SECRET_DB_PASSWORD_VERSION}
|
||||
admin_password:
|
||||
external: true
|
||||
name: ${STACK_NAME}_admin_password_${SECRET_ADMIN_PASSWORD_VERSION}
|
||||
|
||||
configs:
|
||||
entrypoint_conf:
|
||||
name: ${STACK_NAME}_entrypoint_conf_${ENTRYPOINT_CONF_VERSION}
|
||||
file: entrypoint.sh.tmpl
|
||||
template_driver: golang
|
||||
php_uploads_conf:
|
||||
name: ${STACK_NAME}_php_uploads_conf_${PHP_UPLOADS_CONF_VERSION}
|
||||
file: uploads.ini.tmpl
|
||||
template_driver: golang
|
||||
htaccess_conf:
|
||||
name: ${STACK_NAME}_htaccess_conf_${HTACCESS_CONF_VERSION}
|
||||
file: htaccess.tmpl
|
||||
template_driver: golang
|
||||
|
||||
@ -4,6 +4,4 @@ apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y msmtp && rm
|
||||
|
||||
echo "sendmail_path = /usr/bin/msmtp -t -i" > /usr/local/etc/php/conf.d/sendmail.ini
|
||||
|
||||
# Upstream ENTRYPOINT
|
||||
# https://github.com/docker-library/wordpress/blob/master/php7.4/apache/Dockerfile#L120
|
||||
/usr/local/bin/docker-entrypoint.sh apache2-foreground "$@"
|
||||
/docker-entrypoint.sh
|
||||
|
||||
131
entrypoint.sh.tmpl
Normal file
131
entrypoint.sh.tmpl
Normal file
@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
|
||||
{{ if (getenv "PHP_EXTENSIONS") }}
|
||||
docker-php-ext-install {{ getenv "PHP_EXTENSIONS" }}
|
||||
{{ end }}
|
||||
|
||||
curl -z /usr/local/bin/wp -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
chmod +x /usr/local/bin/wp
|
||||
|
||||
{{ if eq (getenv "ENABLE_COMPOSER") "1" }}
|
||||
mkdir -p /var/www/.composer
|
||||
chown www-data:www-data /var/www/.composer /var/www/html/composer
|
||||
|
||||
curl https://getcomposer.org/installer -o /tmp/composer-setup.php
|
||||
php -r "if (hash_file('sha384', '/tmp/composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
|
||||
php /tmp/composer-setup.php
|
||||
rm /tmp/composer-setup.php
|
||||
|
||||
mv /var/www/html/composer.phar /usr/local/bin/composer
|
||||
{{ end }}
|
||||
|
||||
{{ if eq (getenv "CORS_ALLOW_ALL") "1" }}
|
||||
a2enmod headers
|
||||
sed -ri -e 's/^([ \t]*)(<\/VirtualHost>)/\1\tHeader set Access-Control-Allow-Origin "*"\n\1\2/g' /etc/apache2/sites-available/*.conf
|
||||
{{ end }}
|
||||
|
||||
{{ if eq (getenv "DISABLE_WEB_INSTALLER") "1" }}
|
||||
cat > /etc/apache2/conf-enabled/disable-installer.conf <<'EOF'
|
||||
<LocationMatch "^/wp-admin/install\.php">
|
||||
Require all denied
|
||||
</LocationMatch>
|
||||
EOF
|
||||
{{ end }}
|
||||
|
||||
{{ if eq (getenv "MULTISITE") "enable" }}
|
||||
export WORDPRESS_CONFIG_EXTRA="$WORDPRESS_CONFIG_EXTRA
|
||||
define('WP_CACHE', false);
|
||||
define('WP_ALLOW_MULTISITE', true );"
|
||||
{{ end }}
|
||||
|
||||
{{ if or (eq (getenv "MULTISITE") "subdomain") (eq (getenv "MULTISITE") "subfolder") }}
|
||||
export WORDPRESS_CONFIG_EXTRA="$WORDPRESS_CONFIG_EXTRA
|
||||
define('MULTISITE', true);
|
||||
define('SUBDOMAIN_INSTALL', true);
|
||||
define('DOMAIN_CURRENT_SITE', '${DOMAIN}');
|
||||
define('PATH_CURRENT_SITE', '/');
|
||||
define('SITE_ID_CURRENT_SITE', 1);
|
||||
define('BLOG_ID_CURRENT_SITE', 1);
|
||||
define('FORCE_SSL_ADMIN', true );
|
||||
define('COOKIE_DOMAIN', \$_SERVER['HTTP_HOST']);"
|
||||
{{ end }}
|
||||
|
||||
|
||||
UPLOADS_HTACCESS=/var/www/html/wp-content/uploads/.htaccess
|
||||
if [ ! -f "$UPLOADS_HTACCESS" ]; then
|
||||
mkdir -p /var/www/html/wp-content/uploads
|
||||
cat > "$UPLOADS_HTACCESS" <<'EOF'
|
||||
# Prevent PHP execution in uploads directory
|
||||
<FilesMatch "\.(?i:php|phtml|phar)$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
EOF
|
||||
fi
|
||||
|
||||
chown -R --from=root:root www-data:www-data /var/www/html/wp-content/
|
||||
|
||||
{{ if eq (getenv "AUTO_INSTALL") "1" }}
|
||||
(
|
||||
DOMAIN="{{ getenv "DOMAIN" }}"
|
||||
TITLE="{{ getenv "TITLE" }}"
|
||||
ADMIN_EMAIL="{{ getenv "ADMIN_EMAIL" }}"
|
||||
LOCALE="{{ getenv "LOCALE" }}"
|
||||
DEFAULT_USER_ROLE="{{ getenv "DEFAULT_USER_ROLE" }}"
|
||||
AUTO_UPDATES="{{ getenv "AUTO_UPDATES" }}"
|
||||
|
||||
# Wait for wp-config.php (created by upstream entrypoint)
|
||||
for _ in $(seq 1 30); do
|
||||
if [ -f /var/www/html/wp-config.php ]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Wait for DB to be reachable
|
||||
for _ in $(seq 1 60); do
|
||||
if su -p www-data -s /bin/bash -c "/usr/local/bin/wp db check" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Skip if already installed or required vars missing
|
||||
if su -p www-data -s /bin/bash -c "/usr/local/bin/wp core is-installed" 2>/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "$TITLE" ] || [ -z "$ADMIN_EMAIL" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ADMIN="admin"
|
||||
ADMIN_PASSWORD=$(cat /run/secrets/admin_password 2>/dev/null | xargs || true)
|
||||
ADMIN_PASS_ARG=""
|
||||
if [ -n "$ADMIN_PASSWORD" ]; then
|
||||
ADMIN_PASS_ARG="--admin_password=$ADMIN_PASSWORD"
|
||||
fi
|
||||
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp core install --url=$DOMAIN --title=\"$TITLE\" --admin_user=$ADMIN --admin_email=$ADMIN_EMAIL --locale=$LOCALE --skip-email $ADMIN_PASS_ARG"
|
||||
if [ -n "$LOCALE" ]; then
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp language core install $LOCALE"
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp site switch-language $LOCALE"
|
||||
fi
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp rewrite structure '/%year%/%monthnum%/%day%/%postname%/'"
|
||||
if [ -n "$DEFAULT_USER_ROLE" ]; then
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp option set default_role $DEFAULT_USER_ROLE"
|
||||
else
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp option set default_role subscriber"
|
||||
fi
|
||||
if [ "$AUTO_UPDATES" != "0" ]; then
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp theme auto-updates enable --all"
|
||||
su -p www-data -s /bin/bash -c "/usr/local/bin/wp plugin auto-updates enable --all" || true
|
||||
fi
|
||||
) &
|
||||
{{ end }}
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
"$@"
|
||||
fi
|
||||
|
||||
# Upstream ENTRYPOINT
|
||||
# https://github.com/docker-library/wordpress/blob/master/php7.4/apache/Dockerfile#L120
|
||||
/usr/local/bin/docker-entrypoint.sh apache2-foreground
|
||||
62
htaccess.tmpl
Normal file
62
htaccess.tmpl
Normal file
@ -0,0 +1,62 @@
|
||||
# Protect sensitive files from direct access
|
||||
<FilesMatch "^(wp-config\.php|\.htaccess|\.htpasswd|readme\.html|license\.txt)$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
{{ if eq (getenv "MULTISITE") "" -}}
|
||||
# BEGIN WordPress
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
RewriteBase /
|
||||
RewriteRule ^index\.php$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . /index.php [L]
|
||||
|
||||
# END WordPress
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq (getenv "MULTISITE") "subfolder" -}}
|
||||
# BEGIN WordPress Multisite
|
||||
# Using subfolder network type: https://wordpress.org/documentation/article/htaccess/#multisite
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
RewriteBase /
|
||||
RewriteRule ^index\.php$ - [L]
|
||||
|
||||
# add a trailing slash to /wp-admin
|
||||
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [L]
|
||||
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
|
||||
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
|
||||
RewriteRule . index.php [L]
|
||||
|
||||
# END WordPress Multisite
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq (getenv "MULTISITE") "subdomain" -}}
|
||||
# BEGIN WordPress Multisite
|
||||
# Using subdomain network type: https://wordpress.org/documentation/article/htaccess/#multisite
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
RewriteBase /
|
||||
RewriteRule ^index\.php$ - [L]
|
||||
|
||||
# add a trailing slash to /wp-admin
|
||||
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [L]
|
||||
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
|
||||
RewriteRule ^(.*\.php)$ $1 [L]
|
||||
RewriteRule . index.php [L]
|
||||
|
||||
# END WordPress Multisite
|
||||
{{- end }}
|
||||
@ -1,3 +1,19 @@
|
||||
account default
|
||||
host {{ env "SMTP_HOST" }}
|
||||
from {{ env "MAIL_FROM" }}
|
||||
host {{ getenv "SMTP_HOST" }}
|
||||
from {{ getenv "MAIL_FROM" }}
|
||||
user {{ or (getenv "SMTP_USER") (getenv "MAIL_FROM") }}
|
||||
port {{ getenv "SMTP_PORT" }}
|
||||
|
||||
{{ if eq (getenv "SMTP_OVERRIDE_FROM") "on" }}
|
||||
set_from_header on
|
||||
{{ end }}
|
||||
|
||||
{{ if eq (getenv "SMTP_AUTH") "on" }}
|
||||
auth {{ getenv "SMTP_AUTH" }}
|
||||
passwordeval "cat /run/secrets/smtp_password"
|
||||
{{ end }}
|
||||
|
||||
{{ if eq (getenv "SMTP_TLS") "on" }}
|
||||
tls {{ getenv "SMTP_TLS" }}
|
||||
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||||
{{ end }}
|
||||
|
||||
17
package.yml
17
package.yml
@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Wordpress
|
||||
description: Open source software you can use to create a beautiful website, blog, or app
|
||||
arguments:
|
||||
name:
|
||||
description: The name of your Wordpress application
|
||||
example: my-cool-project
|
||||
domain:
|
||||
description: The domain name where your Wordpress will be available on the web
|
||||
example: my-cool-project.com
|
||||
secrets:
|
||||
db_passwd:
|
||||
description: The normal user database password
|
||||
length: 8
|
||||
db_root_passwd:
|
||||
description: The root user database password
|
||||
length: 8
|
||||
1
release/2.10.0+6.5.5
Normal file
1
release/2.10.0+6.5.5
Normal file
@ -0,0 +1 @@
|
||||
Adds redirects and alakazam integration
|
||||
1
release/2.13.2+6.7.1
Normal file
1
release/2.13.2+6.7.1
Normal file
@ -0,0 +1 @@
|
||||
Breaking change for ftp container: you need to uncomment COMPOSE_FILE="$COMPOSE_FILE:compose.ftp-2222.yml" to open port 2222 again. You can also select between port 2220-2225.
|
||||
1
release/2.17.1+6.9.0
Normal file
1
release/2.17.1+6.9.0
Normal file
@ -0,0 +1 @@
|
||||
Breaking change for openid plugin: The issuer must be provided, thus the set_authentik function now includes issuer and endpoint_jwks.
|
||||
1
release/2.4.0+6.3.0
Normal file
1
release/2.4.0+6.3.0
Normal file
@ -0,0 +1 @@
|
||||
The authentik secrets need to be inserted again, as wordpress is not sharing the secret with authentik any more.
|
||||
1
release/2.7.0+6.4.2
Normal file
1
release/2.7.0+6.4.2
Normal file
@ -0,0 +1 @@
|
||||
Multisite now also works with subpaths instead of subdomains. Also Multisite support was simplified. If you are using a subdomain multisite setup you can remove the `WORDPRESS_CONFIG_EXTRA="define('MULTISITE', true);...` from your config and instead set MULTISITE=subdomain.
|
||||
6
release/3.0.0+7.0.0
Normal file
6
release/3.0.0+7.0.0
Normal file
@ -0,0 +1,6 @@
|
||||
- WordPress upgraded from 6.9.4 to 7.0 (major! test before deploying)
|
||||
- MariaDB upgraded from 10.x to 11.4 (major! SSL now enabled by default)
|
||||
- ENTRYPOINT_CONF_VERSION bumped to v9
|
||||
- Breaking: MariaDB 11.4 enables SSL by default — if clients don't support SSL, add --disable-ssl to db command
|
||||
- Breaking: WordPress 7.0 introduces new AI features and admin theme changes
|
||||
- Backup database and files before upgrading
|
||||
@ -1,6 +1,37 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
"config:recommended"
|
||||
],
|
||||
"regexManagers": [
|
||||
{
|
||||
"fileMatch": ["(^|/)compose[^/]*\\.yml$"],
|
||||
"matchStrings": [
|
||||
"image:\\s*\"wordpress:(?<currentValue>[^\"]+)\"",
|
||||
"image:\\s*\"mariadb:(?<currentValue>[^\"]+)\""
|
||||
],
|
||||
"datasourceTemplate": "docker",
|
||||
"lookupNameTemplate": "{{{packageName}}}"
|
||||
},
|
||||
{
|
||||
"fileMatch": ["(^|/)\\.drone\\.yml$"],
|
||||
"matchStrings": [
|
||||
"gomplate/releases/download/v(?<currentValue>[\\d.]+)/gomplate_linux-amd64"
|
||||
],
|
||||
"datasourceTemplate": "github-releases",
|
||||
"lookupNameTemplate": "hairyhenderson/gomplate"
|
||||
}
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchDatasources": ["docker"],
|
||||
"matchPackageNames": ["wordpress"],
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["docker"],
|
||||
"matchPackageNames": ["mariadb"],
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2
tests/fixtures/composer.env
vendored
Normal file
2
tests/fixtures/composer.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
ENABLE_COMPOSER=1
|
||||
2
tests/fixtures/cors.env
vendored
Normal file
2
tests/fixtures/cors.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
CORS_ALLOW_ALL=1
|
||||
1
tests/fixtures/default.env
vendored
Normal file
1
tests/fixtures/default.env
vendored
Normal file
@ -0,0 +1 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
2
tests/fixtures/multisite-enable.env
vendored
Normal file
2
tests/fixtures/multisite-enable.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
MULTISITE=enable
|
||||
2
tests/fixtures/multisite-subdomain.env
vendored
Normal file
2
tests/fixtures/multisite-subdomain.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
MULTISITE=subdomain
|
||||
2
tests/fixtures/multisite-subfolder.env
vendored
Normal file
2
tests/fixtures/multisite-subfolder.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
MULTISITE=subfolder
|
||||
2
tests/fixtures/php-extensions.env
vendored
Normal file
2
tests/fixtures/php-extensions.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
PHP_EXTENSIONS=calendar
|
||||
8
tests/fixtures/smtp-full.env
vendored
Normal file
8
tests/fixtures/smtp-full.env
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
SMTP_HOST=mail.example.com
|
||||
SMTP_PORT=587
|
||||
MAIL_FROM=wordpress@example.com
|
||||
SMTP_USER=relay@example.com
|
||||
SMTP_AUTH=on
|
||||
SMTP_TLS=on
|
||||
SMTP_OVERRIDE_FROM=on
|
||||
3
tests/fixtures/upload-sizes.env
vendored
Normal file
3
tests/fixtures/upload-sizes.env
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
UPLOAD_MAX_SIZE=512M
|
||||
UPLOAD_MAX_TIME=60
|
||||
54
tests/run.sh
Executable file
54
tests/run.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Root of the project directory
|
||||
ROOT="$(dirname "$(realpath "$0")")"
|
||||
|
||||
echo "==================================="
|
||||
echo " WordPress Recipe Test Suite"
|
||||
echo "==================================="
|
||||
echo ""
|
||||
|
||||
# Collect all compose files for YAML validation
|
||||
COMPOSE_FILES=()
|
||||
while IFS= read -r f; do
|
||||
COMPOSE_FILES+=("$f")
|
||||
done < <(find "$ROOT/.." -maxdepth 1 -name 'compose*.yml' | sort)
|
||||
|
||||
# Collect all tmpl files for shellcheck (only those with bash content)
|
||||
SHELL_TMPL_FILES=()
|
||||
while IFS= read -r f; do
|
||||
SHELL_TMPL_FILES+=("$f")
|
||||
done < <(find "$ROOT/.." -maxdepth 1 -name '*.sh.tmpl' | sort)
|
||||
|
||||
# Track total failures across all test suites
|
||||
failures=0
|
||||
|
||||
# Validate YAML syntax of all compose files
|
||||
echo "========================================================================"
|
||||
"$ROOT/test_yaml.sh" "${COMPOSE_FILES[@]}" || failures=$((failures + 1))
|
||||
echo ""
|
||||
|
||||
# Lint shell scripts inside Go templates (after stripping template tags)
|
||||
echo "========================================================================"
|
||||
"$ROOT/test_shell.sh" "${SHELL_TMPL_FILES[@]}" || failures=$((failures + 1))
|
||||
echo ""
|
||||
|
||||
# Render templates with fixture env files and verify expected output
|
||||
echo "========================================================================"
|
||||
"$ROOT/test_templates.sh" || failures=$((failures + 1))
|
||||
echo ""
|
||||
|
||||
# Validate compose files against the Docker Compose specification
|
||||
echo "========================================================================"
|
||||
"$ROOT/test_compose_config.sh" || failures=$((failures + 1))
|
||||
echo ""
|
||||
|
||||
echo "==================================="
|
||||
if [ "$failures" -eq 0 ]; then
|
||||
echo " All tests passed!"
|
||||
else
|
||||
echo " $failures test suite(s) failed"
|
||||
fi
|
||||
echo "==================================="
|
||||
exit "$failures"
|
||||
64
tests/test_compose_config.sh
Executable file
64
tests/test_compose_config.sh
Executable file
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(dirname "$(realpath "$0")")/.."
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
# Detect available Docker Compose command
|
||||
compose_cmd=""
|
||||
if command -v docker &>/dev/null && docker compose version &>/dev/null 2>&1; then
|
||||
compose_cmd="docker compose"
|
||||
elif command -v docker-compose &>/dev/null; then
|
||||
compose_cmd="docker-compose"
|
||||
fi
|
||||
|
||||
# Validate a compose file against the Docker Compose specification
|
||||
test_compose_config() {
|
||||
local file=$1 main=${2:-}
|
||||
|
||||
# Skip if Docker Compose is not available on this system
|
||||
if [ -z "$compose_cmd" ]; then
|
||||
echo " SKIP $file (no docker compose available)"
|
||||
return
|
||||
fi
|
||||
|
||||
# Main compose file is validated standalone
|
||||
if [ -z "$main" ]; then
|
||||
if $compose_cmd -f "$file" config -q 2>/dev/null; then
|
||||
echo " PASS $file"
|
||||
pass=$((pass + 1))
|
||||
else
|
||||
echo " FAIL $file"
|
||||
fail=$((fail + 1))
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
# Override files are validated combined with the main compose file.
|
||||
# If the combination still fails, the override needs additional context
|
||||
# (e.g. other override files) and is skipped rather than failed.
|
||||
if $compose_cmd -f "$main" -f "$file" config -q 2>/dev/null; then
|
||||
echo " PASS $file"
|
||||
pass=$((pass + 1))
|
||||
else
|
||||
echo " SKIP $file (partial override, needs additional context)"
|
||||
pass=$((pass + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "=== Docker Compose Config Validation ==="
|
||||
|
||||
# Validate main compose file first, then all override files
|
||||
test_compose_config "$ROOT/compose.yml"
|
||||
|
||||
while IFS= read -r f; do
|
||||
# Skip the main compose file (already tested above)
|
||||
[ "$f" = "$ROOT/compose.yml" ] && continue
|
||||
[ -f "$f" ] && test_compose_config "$f" "$ROOT/compose.yml"
|
||||
done < <(find "$ROOT" -maxdepth 1 -name 'compose*.yml' | sort)
|
||||
|
||||
echo "---"
|
||||
echo "Passed: $pass Failed: $fail"
|
||||
# Exit with failure if any compose file failed validation
|
||||
[ "$fail" -eq 0 ]
|
||||
50
tests/test_shell.sh
Executable file
50
tests/test_shell.sh
Executable file
@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
# Skip if shellcheck is not installed
|
||||
if ! command -v shellcheck &>/dev/null; then
|
||||
echo "=== ShellCheck ==="
|
||||
echo " SKIP shellcheck not found"
|
||||
echo "---"
|
||||
echo "Passed: 0 Failed: 0"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Allow overriding shellcheck options via env var (e.g. -s bash)
|
||||
EXTRA_SHELLCHECK_OPTS="${SHELLCHECK_OPTS:-}"
|
||||
|
||||
# Run shellcheck on a Go template after stripping template tags
|
||||
shellcheck_tmpl() {
|
||||
local tmpl=$1
|
||||
# Strip Go template tags ({{ ... }} and {{- ... -}}) into whitespace
|
||||
# so shellcheck can parse the remaining bash.
|
||||
local cleaned
|
||||
cleaned=$(sed 's/{{[-]*[^}]*[-]*}}/true/g' "$tmpl")
|
||||
|
||||
local tmpfile
|
||||
tmpfile=$(mktemp)
|
||||
printf '%s\n' "$cleaned" > "$tmpfile"
|
||||
|
||||
if shellcheck $EXTRA_SHELLCHECK_OPTS "$tmpfile"; then
|
||||
echo " PASS $tmpl"
|
||||
pass=$((pass + 1))
|
||||
else
|
||||
echo " FAIL $tmpl"
|
||||
fail=$((fail + 1))
|
||||
fi
|
||||
rm -f "$tmpfile"
|
||||
}
|
||||
|
||||
echo "=== ShellCheck ==="
|
||||
# Lint each template file passed as argument
|
||||
for f in "$@"; do
|
||||
[ -f "$f" ] && shellcheck_tmpl "$f"
|
||||
done
|
||||
|
||||
echo "---"
|
||||
echo "Passed: $pass Failed: $fail"
|
||||
# Exit with failure if any template failed shellcheck
|
||||
[ "$fail" -eq 0 ]
|
||||
301
tests/test_templates.sh
Executable file
301
tests/test_templates.sh
Executable file
@ -0,0 +1,301 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(dirname "$(realpath "$0")")/.."
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
# Allow overriding gomplate binary path via env var
|
||||
gomplate="${GOMPLATE_BIN:-gomplate}"
|
||||
|
||||
# Ensure gomplate is installed before running template tests
|
||||
require_gomplate() {
|
||||
if ! command -v "$gomplate" &>/dev/null; then
|
||||
echo " SKIP gomplate not found (install from https://github.com/hairyhenderson/gomplate or set GOMPLATE_BIN)"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Render a template by exporting env vars directly
|
||||
# This avoids gomplate datasource quirks with .env files
|
||||
render_via_env() {
|
||||
local tmpl=$1 envfile=$2
|
||||
set -a
|
||||
# shellcheck disable=1090,1091
|
||||
. "$envfile"
|
||||
set +a
|
||||
"$gomplate" -f "$tmpl" 2>/dev/null
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# entrypoint.sh.tmpl tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Default entrypoint: no multisite, uploads guard, chown with --from, wp-cli
|
||||
test_entrypoint_default() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
# Should NOT have multisite config
|
||||
if echo "$output" | grep -q "WP_ALLOW_MULTISITE"; then
|
||||
echo " FAIL entrypoint default: unexpected WP_ALLOW_MULTISITE"
|
||||
return 1
|
||||
fi
|
||||
# Should have uploads .htaccess guard
|
||||
if ! echo "$output" | grep -q "Prevent PHP execution in uploads"; then
|
||||
echo " FAIL entrypoint default: missing uploads htaccess"
|
||||
return 1
|
||||
fi
|
||||
# Should use --from=root:root on chown
|
||||
if ! echo "$output" | grep -q "chown -R --from=root:root"; then
|
||||
echo " FAIL entrypoint default: missing --from=root:root on chown"
|
||||
return 1
|
||||
fi
|
||||
# Should have wp-cli download
|
||||
if ! echo "$output" | grep -q "wp-cli.phar"; then
|
||||
echo " FAIL entrypoint default: missing wp-cli download"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint default"
|
||||
}
|
||||
|
||||
# Multisite enable: should set WP_ALLOW_MULTISITE
|
||||
test_entrypoint_multisite_enable() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "WP_ALLOW_MULTISITE"; then
|
||||
echo " FAIL entrypoint multisite enable: missing WP_ALLOW_MULTISITE"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint multisite enable"
|
||||
}
|
||||
|
||||
# Multisite subdomain: should set MULTISITE, SUBDOMAIN_INSTALL, DOMAIN_CURRENT_SITE
|
||||
test_entrypoint_multisite_subdomain() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "MULTISITE"; then
|
||||
echo " FAIL entrypoint multisite subdomain: missing MULTISITE"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "SUBDOMAIN_INSTALL"; then
|
||||
echo " FAIL entrypoint multisite subdomain: missing SUBDOMAIN_INSTALL"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "DOMAIN_CURRENT_SITE"; then
|
||||
echo " FAIL entrypoint multisite subdomain: missing DOMAIN_CURRENT_SITE"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint multisite subdomain"
|
||||
}
|
||||
|
||||
# Multisite subfolder: should set MULTISITE but not SUBDOMAIN_INSTALL
|
||||
test_entrypoint_multisite_subfolder() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "MULTISITE"; then
|
||||
echo " FAIL entrypoint multisite subfolder: missing MULTISITE"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "SUBDOMAIN_INSTALL"; then
|
||||
echo " FAIL entrypoint multisite subfolder: missing SUBDOMAIN_INSTALL"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint multisite subfolder"
|
||||
}
|
||||
|
||||
# CORS: should enable Apache headers module and set Access-Control-Allow-Origin
|
||||
test_entrypoint_cors() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "a2enmod headers"; then
|
||||
echo " FAIL entrypoint CORS: missing a2enmod headers"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "Access-Control-Allow-Origin"; then
|
||||
echo " FAIL entrypoint CORS: missing Access-Control-Allow-Origin"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint CORS"
|
||||
}
|
||||
|
||||
# PHP extensions: should install additional PHP extensions like calendar
|
||||
test_entrypoint_php_extensions() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "docker-php-ext-install calendar"; then
|
||||
echo " FAIL entrypoint PHP extensions: missing docker-php-ext-install calendar"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint PHP extensions"
|
||||
}
|
||||
|
||||
# Composer: should download Composer via getcomposer.org
|
||||
test_entrypoint_composer() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "entrypoint.sh.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "getcomposer.org"; then
|
||||
echo " FAIL entrypoint composer: missing composer download"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS entrypoint composer"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# htaccess.tmpl tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Default htaccess: standard WordPress rewrite rule, no multisite section
|
||||
test_htaccess_default() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "htaccess.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "RewriteRule . /index.php"; then
|
||||
echo " FAIL htaccess default: missing standard rewrite rule"
|
||||
return 1
|
||||
fi
|
||||
if echo "$output" | grep -q "WordPress Multisite"; then
|
||||
echo " FAIL htaccess default: unexpected multisite section"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS htaccess default"
|
||||
}
|
||||
|
||||
# Multisite htaccess: multisite section present, no standard rewrite rule
|
||||
test_htaccess_multisite() {
|
||||
local envfile=$1 mode=$2
|
||||
local output
|
||||
output=$(render_via_env "htaccess.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "WordPress Multisite"; then
|
||||
echo " FAIL htaccess multisite $mode: missing multisite section"
|
||||
return 1
|
||||
fi
|
||||
if echo "$output" | grep -q "^RewriteRule . /index.php"; then
|
||||
echo " FAIL htaccess multisite $mode: has non-multisite rewrite rule"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS htaccess multisite $mode"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# uploads.ini.tmpl tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Default uploads config: 256M upload limit, 30s execution time
|
||||
test_uploads_default() {
|
||||
local output
|
||||
output=$(render_via_env "uploads.ini.tmpl" "tests/fixtures/default.env")
|
||||
|
||||
if ! echo "$output" | grep -q "upload_max_filesize = 256M"; then
|
||||
echo " FAIL uploads default: expected 256M upload_max_filesize"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "max_execution_time = 30"; then
|
||||
echo " FAIL uploads default: expected 30 max_execution_time"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS uploads default"
|
||||
}
|
||||
|
||||
# Custom uploads config: 512M upload limit, 60s execution time
|
||||
test_uploads_custom() {
|
||||
local envfile=$1
|
||||
local output
|
||||
output=$(render_via_env "uploads.ini.tmpl" "$envfile")
|
||||
|
||||
if ! echo "$output" | grep -q "upload_max_filesize = 512M"; then
|
||||
echo " FAIL uploads custom: expected 512M"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "max_execution_time = 60"; then
|
||||
echo " FAIL uploads custom: expected 60"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS uploads custom"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# msmtp.conf.tmpl tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Full SMTP config: host, from, auth, passwordeval, TLS, set_from_header
|
||||
test_msmtp_default() {
|
||||
local output
|
||||
output=$(render_via_env "msmtp.conf.tmpl" "tests/fixtures/smtp-full.env")
|
||||
|
||||
if ! echo "$output" | grep -q "host mail.example.com"; then
|
||||
echo " FAIL msmtp default: missing host"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "from wordpress@example.com"; then
|
||||
echo " FAIL msmtp default: missing from"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "auth on"; then
|
||||
echo " FAIL msmtp default: missing auth"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "passwordeval"; then
|
||||
echo " FAIL msmtp default: missing passwordeval"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "tls on"; then
|
||||
echo " FAIL msmtp default: missing tls"
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$output" | grep -q "set_from_header on"; then
|
||||
echo " FAIL msmtp default: missing set_from_header"
|
||||
return 1
|
||||
fi
|
||||
echo " PASS msmtp full config"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Run all template tests
|
||||
# ---------------------------------------------------------------------------
|
||||
echo "=== Template Rendering Tests ==="
|
||||
|
||||
cd "$ROOT"
|
||||
|
||||
echo "--- entrypoint.sh.tmpl ---"
|
||||
require_gomplate
|
||||
|
||||
test_entrypoint_default "tests/fixtures/default.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_entrypoint_multisite_enable "tests/fixtures/multisite-enable.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_entrypoint_multisite_subdomain "tests/fixtures/multisite-subdomain.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_entrypoint_multisite_subfolder "tests/fixtures/multisite-subfolder.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_entrypoint_cors "tests/fixtures/cors.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_entrypoint_php_extensions "tests/fixtures/php-extensions.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_entrypoint_composer "tests/fixtures/composer.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
|
||||
echo "--- htaccess.tmpl ---"
|
||||
test_htaccess_default "tests/fixtures/default.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_htaccess_multisite "tests/fixtures/multisite-subfolder.env" "subfolder" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_htaccess_multisite "tests/fixtures/multisite-subdomain.env" "subdomain" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
|
||||
echo "--- uploads.ini.tmpl ---"
|
||||
test_uploads_default && pass=$((pass+1)) || fail=$((fail+1))
|
||||
test_uploads_custom "tests/fixtures/upload-sizes.env" && pass=$((pass+1)) || fail=$((fail+1))
|
||||
|
||||
echo "--- msmtp.conf.tmpl ---"
|
||||
test_msmtp_default && pass=$((pass+1)) || fail=$((fail+1))
|
||||
|
||||
echo "---"
|
||||
echo "Passed: $pass Failed: $fail"
|
||||
# Exit with failure if any template test failed
|
||||
[ "$fail" -eq 0 ]
|
||||
60
tests/test_yaml.sh
Executable file
60
tests/test_yaml.sh
Executable file
@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
# Detect available YAML checker: prefer yamllint, fall back to PyYAML
|
||||
checker=""
|
||||
if command -v yamllint &>/dev/null; then
|
||||
checker=yamllint
|
||||
elif python3 -c "import yaml" 2>/dev/null; then
|
||||
checker=python
|
||||
fi
|
||||
|
||||
# Validate a single YAML file using the available checker
|
||||
test_yaml() {
|
||||
local file=$1
|
||||
|
||||
# yamllint provides richer output; PyYAML just checks parseability
|
||||
case "$checker" in
|
||||
yamllint)
|
||||
if yamllint -d "{extends: relaxed, rules: {line-length: disable}}" "$file"; then
|
||||
echo " PASS $file"
|
||||
pass=$((pass+1))
|
||||
else
|
||||
echo " FAIL $file"
|
||||
fail=$((fail+1))
|
||||
fi
|
||||
;;
|
||||
python)
|
||||
if python3 -c "
|
||||
import yaml, sys
|
||||
with open('$file') as f:
|
||||
yaml.safe_load(f)
|
||||
" 2>/dev/null; then
|
||||
echo " PASS $file"
|
||||
pass=$((pass+1))
|
||||
else
|
||||
echo " FAIL $file"
|
||||
fail=$((fail+1))
|
||||
fi
|
||||
;;
|
||||
# Skip silently if no YAML checker is installed
|
||||
*)
|
||||
echo " SKIP $file (no yamllint or PyYAML)"
|
||||
pass=$((pass+1))
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
echo "=== YAML Validation ==="
|
||||
# Test each compose file passed as argument
|
||||
for f in "$@"; do
|
||||
[ -f "$f" ] && test_yaml "$f"
|
||||
done
|
||||
|
||||
echo "---"
|
||||
echo "Passed: $pass Failed: $fail"
|
||||
# Exit with failure if any file failed validation
|
||||
[ "$fail" -eq 0 ]
|
||||
11
uploads.ini.tmpl
Normal file
11
uploads.ini.tmpl
Normal file
@ -0,0 +1,11 @@
|
||||
{{- $upload_max_size := "256M" -}}
|
||||
{{- if ne (getenv "UPLOAD_MAX_SIZE") "" }}{{ $upload_max_size = getenv "UPLOAD_MAX_SIZE" }}{{ end -}}
|
||||
{{- $upload_max_time := "30" -}}
|
||||
{{- if ne (getenv "UPLOAD_MAX_TIME") "" }}{{ $upload_max_time = getenv "UPLOAD_MAX_TIME" }}{{ end -}}
|
||||
|
||||
file_uploads = On
|
||||
upload_max_filesize = {{ $upload_max_size }}
|
||||
post_max_size = {{ $upload_max_size }}
|
||||
memory_limit = {{ $upload_max_size }}
|
||||
max_execution_time = {{ $upload_max_time }}
|
||||
max_input_time = {{ $upload_max_time }}
|
||||
1
users.conf.tmpl
Normal file
1
users.conf.tmpl
Normal file
@ -0,0 +1 @@
|
||||
ftp_user:{{ secret "ftp_pass" }}:33:33
|
||||
Reference in New Issue
Block a user