forked from coop-cloud/wordpress
Compare commits
2 Commits
tests
...
service-re
| Author | SHA1 | Date | |
|---|---|---|---|
| c3b4bb5dfb | |||
| 82332b6854 |
75
.drone.yml
75
.drone.yml
@ -1,63 +1,22 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: test
|
||||
|
||||
name: deploy to swarm-test.autonomic.zone
|
||||
steps:
|
||||
- name: test
|
||||
image: alpine:3.21
|
||||
environment:
|
||||
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:
|
||||
- main
|
||||
---
|
||||
kind: pipeline
|
||||
name: generate recipe catalogue
|
||||
steps:
|
||||
- name: release a new version
|
||||
image: plugins/downstream
|
||||
- name: deployment
|
||||
image: decentral1se/stack-ssh-deploy:latest
|
||||
settings:
|
||||
server: https://build.coopcloud.tech
|
||||
token:
|
||||
from_secret: drone_abra-bot_token
|
||||
fork: true
|
||||
repositories:
|
||||
- toolshed/auto-recipes-catalogue-json
|
||||
|
||||
host: swarm-test.autonomic.zone
|
||||
stack: wordpress
|
||||
generate_secrets: true
|
||||
purge: true
|
||||
deploy_key:
|
||||
from_secret: drone_ssh_swarm_test
|
||||
environment:
|
||||
DOMAIN: wordpress.swarm-test.autonomic.zone
|
||||
STACK_NAME: wordpress
|
||||
LETS_ENCRYPT_ENV: production
|
||||
DB_PASSWORD_VERSION: v1
|
||||
DB_ROOT_PASSWORD_VERSION: v1
|
||||
trigger:
|
||||
event: tag
|
||||
branch:
|
||||
- master
|
||||
|
||||
96
.env.sample
96
.env.sample
@ -1,96 +0,0 @@
|
||||
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"
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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"
|
||||
38
.envrc.sample
Normal file
38
.envrc.sample
Normal file
@ -0,0 +1,38 @@
|
||||
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,22 +1 @@
|
||||
# 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
|
||||
|
||||
123
README.md
123
README.md
@ -1,96 +1,59 @@
|
||||
# Wordpress
|
||||
# wordpress
|
||||
|
||||
[](https://build.coopcloud.tech/coop-cloud/wordpress)
|
||||
[](https://drone.autonomic.zone/compose-stacks/wordpress)
|
||||
|
||||
Coöp Cloud + [Wordpress](https://wordpress.org) = 🥳
|
||||
|
||||
<!-- metadata -->
|
||||
|
||||
* **Category**: Apps
|
||||
* **Status**: 4
|
||||
* **Image**: [`wordpress`](https://hub.docker.com/_/wordpress), 4, upstream
|
||||
* **Healthcheck**: Yes
|
||||
* **Backups**: Yes
|
||||
* **Email**: 3
|
||||
* **Tests**: 2
|
||||
* **SSO**: No
|
||||
|
||||
<!-- endmetadata -->
|
||||
|
||||
|
||||
## Quick start
|
||||
|
||||
|
||||
* `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`
|
||||
|
||||
### Authentik Integration
|
||||
|
||||
|
||||
`abra app config <app-name>`
|
||||
Configure the following envs:
|
||||
```
|
||||
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`
|
||||
|
||||
## Running WP-CLI
|
||||
|
||||
`abra app cmd <app-name> app wp -- core check-update --major`
|
||||
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)
|
||||
|
||||
## Network (Multi-site)
|
||||
|
||||
_(Only tested using subdomains)_
|
||||
|
||||
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>`
|
||||
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
|
||||
|
||||
## Installing a custom theme
|
||||
|
||||
`abra app cp <app-name> ~/path/to/local/theme wordpress:/var/www/html/wp-content/themes/`
|
||||
`abra cp ~/path/to/local/theme wordpress:/var/www/html/wp-content/themes/`
|
||||
|
||||
## Backups
|
||||
|
||||
1. Edit `.envrc` and uncomment the `export COMPOSE_FILE="compose.yml:compose.backup.yml"` line
|
||||
2. `direnv allow`
|
||||
3. `abra deploy`
|
||||
|
||||
## Email
|
||||
|
||||
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>`
|
||||
|
||||
## Tests
|
||||
|
||||
Run the full test suite:
|
||||
|
||||
```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.
|
||||
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`
|
||||
|
||||
[abra]: https://git.autonomic.zone/autonomic-cooperative/abra
|
||||
[cc-traefik]: https://git.autonomic.zone/coop-cloud/traefik
|
||||
[cc-postfix-relay]: https://git.autonomic.zone/coop-cloud/traefik
|
||||
[compose-traefik]: https://git.autonomic.zone/compose-stacks/traefik
|
||||
|
||||
109
abra.sh
109
abra.sh
@ -1,109 +0,0 @@
|
||||
export PHP_UPLOADS_CONF_VERSION=v4
|
||||
export ENTRYPOINT_CONF_VERSION=v9
|
||||
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"
|
||||
wp "plugin auto-updates enable --all"
|
||||
wp "theme update --all"
|
||||
wp "theme auto-updates enable --all"
|
||||
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
|
||||
wp "core install --url=$DOMAIN --title=\"$TITLE\" --admin_user=$ADMIN --admin_email=$ADMIN_EMAIL --locale=$LOCALE --skip-email"
|
||||
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
|
||||
wp "theme auto-updates enable --all"
|
||||
wp 'plugin auto-updates enable --all' || true
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
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
|
||||
3
backup.d/NOTES.md
Normal file
3
backup.d/NOTES.md
Normal file
@ -0,0 +1,3 @@
|
||||
# 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.
|
||||
36
backup.d/borgmatic.yml
Normal file
36
backup.d/borgmatic.yml
Normal file
@ -0,0 +1,36 @@
|
||||
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" }}
|
||||
47
backup.d/fr_microsites_wordpress.yml
Normal file
47
backup.d/fr_microsites_wordpress.yml
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
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
|
||||
47
backup.d/fr_singlesite_wordpress.yml
Normal file
47
backup.d/fr_singlesite_wordpress.yml
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
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
|
||||
65
compose.abra.yml
Normal file
65
compose.abra.yml
Normal file
@ -0,0 +1,65 @@
|
||||
# #############################################################################
|
||||
# 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}
|
||||
@ -1,14 +0,0 @@
|
||||
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}
|
||||
@ -1,14 +0,0 @@
|
||||
---
|
||||
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:
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2220:22
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2221:22
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2222:22
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2223:22
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2224:22
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
ftp:
|
||||
ports:
|
||||
- 2220:22
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
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,26 +1,31 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
|
||||
services:
|
||||
app:
|
||||
entrypoint: /docker-entrypoint.mailrelay.sh
|
||||
entrypoint: /docker-entrypoint.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_mailrelay_conf
|
||||
target: /docker-entrypoint.mailrelay.sh
|
||||
- source: entrypoint_conf
|
||||
target: /docker-entrypoint.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_mailrelay_conf:
|
||||
entrypoint_conf:
|
||||
name: ${STACK_NAME}_entrypoint_mailrelay_${ENTRYPOINT_MAILRELAY_CONF_VERSION}
|
||||
file: entrypoint.mailrelay.sh.tmpl
|
||||
template_driver: golang
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
---
|
||||
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"
|
||||
@ -1,9 +0,0 @@
|
||||
---
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
db:
|
||||
ports:
|
||||
- target: 3306
|
||||
published: 3306
|
||||
mode: host
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
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:
|
||||
@ -1,19 +0,0 @@
|
||||
---
|
||||
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
|
||||
66
compose.yml
66
compose.yml
@ -3,37 +3,20 @@ version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: "wordpress:7.0.0"
|
||||
image: "wordpress:5.5.1"
|
||||
volumes:
|
||||
- "wordpress_content:/var/www/html/wp-content/"
|
||||
networks:
|
||||
- backend
|
||||
- proxy
|
||||
environment:
|
||||
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:
|
||||
COMPOSER:
|
||||
- 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}
|
||||
secrets:
|
||||
- db_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:
|
||||
@ -48,24 +31,18 @@ services:
|
||||
order: start-first
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network=proxy"
|
||||
- "traefik.docker.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/coop-cloud/planning/issues/14
|
||||
# see https://git.autonomic.zone/compose-stacks/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:12.3"
|
||||
image: "mariadb:10.5"
|
||||
volumes:
|
||||
- "mariadb:/var/lib/mysql"
|
||||
networks:
|
||||
@ -78,15 +55,10 @@ 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
|
||||
|
||||
@ -97,21 +69,7 @@ volumes:
|
||||
secrets:
|
||||
db_root_password:
|
||||
external: true
|
||||
name: ${STACK_NAME}_db_root_password_${SECRET_DB_ROOT_PASSWORD_VERSION}
|
||||
name: ${STACK_NAME}_db_root_password_${DB_ROOT_PASSWORD_VERSION}
|
||||
db_password:
|
||||
external: true
|
||||
name: ${STACK_NAME}_db_password_${SECRET_DB_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
|
||||
name: ${STACK_NAME}_db_password_${DB_PASSWORD_VERSION}
|
||||
|
||||
@ -4,4 +4,6 @@ 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
|
||||
|
||||
/docker-entrypoint.sh
|
||||
# Upstream ENTRYPOINT
|
||||
# https://github.com/docker-library/wordpress/blob/master/php7.4/apache/Dockerfile#L120
|
||||
/usr/local/bin/docker-entrypoint.sh apache2-foreground "$@"
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
#!/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 "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 [ $# -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
|
||||
@ -1,62 +0,0 @@
|
||||
# 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,19 +1,3 @@
|
||||
account default
|
||||
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 }}
|
||||
host {{ env "SMTP_HOST" }}
|
||||
from {{ env "MAIL_FROM" }}
|
||||
|
||||
17
package.yml
Normal file
17
package.yml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
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 +0,0 @@
|
||||
Adds redirects and alakazam integration
|
||||
@ -1 +0,0 @@
|
||||
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 +0,0 @@
|
||||
Breaking change for openid plugin: The issuer must be provided, thus the set_authentik function now includes issuer and endpoint_jwks.
|
||||
@ -1 +0,0 @@
|
||||
The authentik secrets need to be inserted again, as wordpress is not sharing the secret with authentik any more.
|
||||
@ -1 +0,0 @@
|
||||
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.
|
||||
@ -1,6 +0,0 @@
|
||||
- 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,37 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"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
|
||||
}
|
||||
"config:base"
|
||||
]
|
||||
}
|
||||
|
||||
2
tests/fixtures/composer.env
vendored
2
tests/fixtures/composer.env
vendored
@ -1,2 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
ENABLE_COMPOSER=1
|
||||
2
tests/fixtures/cors.env
vendored
2
tests/fixtures/cors.env
vendored
@ -1,2 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
CORS_ALLOW_ALL=1
|
||||
1
tests/fixtures/default.env
vendored
1
tests/fixtures/default.env
vendored
@ -1 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
2
tests/fixtures/multisite-enable.env
vendored
2
tests/fixtures/multisite-enable.env
vendored
@ -1,2 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
MULTISITE=enable
|
||||
2
tests/fixtures/multisite-subdomain.env
vendored
2
tests/fixtures/multisite-subdomain.env
vendored
@ -1,2 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
MULTISITE=subdomain
|
||||
2
tests/fixtures/multisite-subfolder.env
vendored
2
tests/fixtures/multisite-subfolder.env
vendored
@ -1,2 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
MULTISITE=subfolder
|
||||
2
tests/fixtures/php-extensions.env
vendored
2
tests/fixtures/php-extensions.env
vendored
@ -1,2 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
PHP_EXTENSIONS=calendar
|
||||
8
tests/fixtures/smtp-full.env
vendored
8
tests/fixtures/smtp-full.env
vendored
@ -1,8 +0,0 @@
|
||||
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
3
tests/fixtures/upload-sizes.env
vendored
@ -1,3 +0,0 @@
|
||||
DOMAIN=wordpress.example.com
|
||||
UPLOAD_MAX_SIZE=512M
|
||||
UPLOAD_MAX_TIME=60
|
||||
54
tests/run.sh
54
tests/run.sh
@ -1,54 +0,0 @@
|
||||
#!/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"
|
||||
@ -1,64 +0,0 @@
|
||||
#!/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 ]
|
||||
@ -1,50 +0,0 @@
|
||||
#!/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 ]
|
||||
@ -1,301 +0,0 @@
|
||||
#!/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 ]
|
||||
@ -1,60 +0,0 @@
|
||||
#!/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 ]
|
||||
@ -1,11 +0,0 @@
|
||||
{{- $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 +0,0 @@
|
||||
ftp_user:{{ secret "ftp_pass" }}:33:33
|
||||
Reference in New Issue
Block a user