type: install jpsVersion: '1.7.2' name: Multi-Region WordPress Cluster v1 (Alpha) id: wordpress-cluster-multiregions categories: - apps/clusters - apps/content-management description: text: Highly-available and reliable WordPress cluster setup with automatic multi-region distribution. The package creates interconnected WordPress sub clusters across several regions ensuring the highest uptime and lowest latency. short: Enterprise-grade WordPress Cluster with automatic distribution across several regions. logo: https://raw.githubusercontent.com/jelastic-jps/wordpress-multiregions/master/images/82dark-back-01.svg baseUrl: https://raw.githubusercontent.com/jelastic-jps/wordpress-multiregions/master onBeforeInit: /scripts/settings.js?_r=${fn.random} settings: fields: - caption: Database Topology type: list name: db_async_topology default: async required: true width: 443 tooltip: tipParams: maxWidth: 610 dismissDelay: 600000 hideOnOver: false values: - value: async caption: Async Primary/Replica Distribution tooltip: <h2>Primary Replication with Extra Replicas</h2> Pre-configured asynchronous replication with two interconnected<br> primary databases and one secondary replica.<br> This topology is recommended when <b>Latency</b> between regions is more than <b>20ms</b>.<br> <ul> <li>Primary node at Region 1 performs writes and reads operations<br> <li>Primary node at Region 2 by default performs reads operations but starts handling writes if initial primary database becomes unavailable<br> <li>Replica node at Region 3 is used for reads operations only<br> </ul> <img width='587' height='480' src='https://raw.githubusercontent.com/jelastic-jps/wordpress-multiregions/master/images/wp-geo-mm-white-1-bl.svg?sanitize=true'> - value: sync caption: Sync Galera Distribution tooltip: <h2>Galera Cluster</h2> All servers can accept updates even if being issued concurrently.<br> This topology is recommended when <b>Latency</b> between regions is less than <b>20ms</b><br> <ul> <li>Region 1 includes 3 primary database nodes<br> <li>Region 2 and 3 each includes 2 primary database nodes<br> <li>All Galera Cluster nodes perform reads and writes operation<br> </ul> <img width='580' height='400' src='https://raw.githubusercontent.com/jelastic-jps/wordpress-multiregions/master/images/wp-geo-galera-white-1-bl.svg?sanitize=true'> showIf: async: - caption: Regions type: regionlist name: regions disableInactive: true selectFirstAvailable: false multiSelect: true required: true min: 2 max: 5 filter: isActive: true type: ["vz7"] tooltip: Select the destination regions. The first selected region will host the primary cluster, so this region should have the highest performance. sync: - caption: Regions type: regionlist name: regions disableInactive: true selectFirstAvailable: false multiSelect: true required: true min: 3 max: 5 filter: isActive: true type: ["vz7"] tooltip: Select the destination regions. The first selected region will host the primary cluster, so this region should have the highest performance. - caption: Environment type: envname name: envName dependsOn: region randomName: true showFullDomain: false required: true - caption: Scaling Strategy type: list name: loadGrowth default: slow required: true width: 225 tooltip: | Configure auto-scaling triggers, i.e. how fast the system responds to load spikes by adding or removing nodes. <p>Read more about <a href="https://docs.jelastic.com/automatic-horizontal-scaling">Automatic Horizontal Scaling</a></p> values: - value: slow caption: Low Load tooltip: <h2>Low load scaling strategy</h2>add 1 new node when CPU > 70% <p>remove when CPU < 20%</p> - value: medium caption: Medium Load tooltip: <h3>Medium load scaling strategy</h3>add 1 new node when CPU > 50% <p>remove when CPU < 20%</p> - value: fast caption: High Load tooltip: <h3>High load scaling strategy</h3>add 2 new nodes when CPU > 30% <p>remove when CPU < 10%</p> - caption: Advanced Features type: displayfield name: displayfield markup: - caption: WordPress Brute Force Attack Protection type: checkbox name: wp_protect value: true disabled: false tooltip: "Secure WordPress Admin Panel with <a href='https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:config:wordpress-protection'>LiteSpeed Brute Force Protection</a> that limits failed login attempts. Default action is <b>Throttle</b> and number of allowed attempts is <b>100</b>." - caption: Web Application Firewall type: checkbox name: waf value: true disabled: false tooltip: "Protect web sites with <a href='https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:waf'>LiteSpeed built-in WAF</a> based on Free ModSecurity Rules from Comodo." - caption: Install Let's Encrypt SSL with Auto-Renewal type: checkbox name: le_addon value: true disabled: false tooltip: "Advanced integration with Let's Encrypt certificate authority that simplifies and automates the process of issuing, configuring and renewing trusted SSL certificates." - caption: Install Lightning-Fast Premium CDN with 160+ PoPs type: checkbox name: cdn_addon value: false hidden: true disabled: false tooltip: "Jelastic CDN is an HTTP/3 premium content delivery network of 160+ Super PoPs (points of presence) with bandwidth capacity up to 115 Tbps, advanced caching and acceleration strategies based on best-in-class IP Anycast technology." - caption: Install WordPress Multisite Network type: checkbox name: mu_addon value: false disabled: false tooltip: "Multisite is a type of WordPress installation that allows you to create and manage a network of multiple websites from a single WordPress dashboard. This lets you easily make changes and keep all of your websites updated from one place." - type: displayfield hideLabel: true hidden: true name: bl_count value: 1 markup: mixins: - https://raw.githubusercontent.com/jelastic-jps/wordpress-cluster/master/configs/vers.yaml globals: wp_cluster_url: https://raw.githubusercontent.com/jelastic-jps/wordpress-cluster/v3.0.0 db_cluster_url: https://raw.githubusercontent.com/jelastic-jps/mysql-cluster/v3.0.0 galera_server_id: ${fn.random} db_user: jelastic-${fn.random} db_pass: ${fn.password(10)} repl_user: replica-${fn.random} repl_pass: ${fn.password(10)} monitor_user: monitor-${fn.random} monitor_pass: ${fn.password(10)} protocol: http wp_admin_pass: ${fn.password(10)} ls_admin_pass: ${fn.password(10)} success: default email: default onInstall: - if ('${settings.db_async_topology}' == 'async'): setGlobals: db_host: proxy db_async_topology: true - else: setGlobals: db_host: sqldb db_async_topology: false - initGlobals - setGlobals: domain: ${settings.envName}-1.${globals.domain-1} - createEnvs - getEnvNodes - installEnvsManager - if ('${globals.db_async_topology}' == 'true'): - install: - jps: ${baseUrl}/scripts/asyncReplicationManager.jps envName: ${settings.envName}-1 settings: db_user: ${globals.db_user} db_pass: ${globals.db_pass} repl_user: ${globals.repl_user} repl_pass: ${globals.repl_pass} monitor_user: ${globals.monitor_user} monitor_pass: ${globals.monitor_pass} cluster_name: ${settings.envName} - jps: ${baseUrl}/scripts/geoGlusterManager.jps envName: ${globals.master_env_name} settings: install_gluster_cluster: true - jps: ${baseUrl}/scripts/cacheManager.jps envName: ${globals.master_env_name} settings: setup_cache_replication: true - else: - install: - jps: ${baseUrl}/scripts/geoGaleraManager.jps envName: ${globals.master_env_name} settings: install_galera_cluster: true - jps: ${baseUrl}/scripts/geoGlusterManager.jps envName: ${globals.master_env_name} settings: install_gluster_cluster: true - jps: ${baseUrl}/scripts/cacheManager.jps envName: ${globals.master_env_name} settings: setup_cache_replication: true - install-wordpress - if (${settings.mu_addon:false}): - install: ${globals.wp_cluster_url}/addon/WPMU.jps envName: ${globals.master_env_name} settings: mode: subdir - if ('${settings.le_addon:false}' == 'true'): - setGlobals: protocol: https - install: jps: https://github.com/jelastic-jps/lets-encrypt/blob/stage/manifest.jps?_r=${fn.random} envName: ${settings.envName}-1 nodeGroup: bl skipEmail: true settings: customDomains: ${globals.domain} fallbackToX1: true webroot: true webrootPath: /var/www/webroot/ROOT - if ('${settings.cdn_addon:false}' == 'true'): - install: jps: https://raw.githubusercontent.com/jelastic-jps/cdn/master/manifest.yml?_r=${fn.random} envName: ${settings.envName}-1 nodeGroup: bl skipEmail: true settings: note: ${settings.noteCDN:} - install: jps: ${baseUrl}/scripts/cacheManager.jps envName: ${globals.master_env_name} settings: clean_cache: true actions: initGlobals: - script: | var regions = '${settings.regions}'.split(','), envGroups = eval('(' + MANIFEST + ')').envGroups, index, onAfterReturn = { setGlobals: {} }, glbs = onAfterReturn.setGlobals, resp, domain; resp = jelastic.env.control.GetRegions(appid, session); if (resp.result != 0) return resp; resp = resp.array; for (var i = 0, n = regions.length; i < n; i ++) { index = i + 1; glbs["region-" + index] = regions[i]; for (var a = 0, b = resp.length; a < b; a++) { for (var k = 0, l = resp[a].hardNodeGroups.length; k < l; k++) { if (resp[a].hardNodeGroups[k].uniqueName == regions[i]) glbs["domain-" + index] = resp[a].domain; } } if (index == 1) { glbs["displayName-" + index] = "WP Cluster Primary"; glbs["initial_env_master-" + index] = "true"; } else { glbs["displayName-" + index] = "WP Cluster Secondary " + i; glbs["initial_env_master-" + index] = "false"; } } glbs["envGroups"] = envGroups; glbs["regionsCount"] = regions.length; glbs["master_env_name"] = "${settings.envName}-1"; return { result: 0, onAfterReturn: onAfterReturn }; createEnvs: - script: | var regions = '${settings.regions}'.split(','), actions = []; var envGroups = eval('(' + MANIFEST + ')').envGroups; for (var cluster = 1, n = regions.length + 1; cluster < n; cluster ++) { actions.push({ jps: "${globals.wp_cluster_url}/manifest.yml?_r=${fn.random}", envName: "${settings.envName}-" + cluster, loggerName: "${settings.envName}-" + cluster, envGroups: envGroups, displayName: "${globals.displayName-" + cluster + "}", region: "${globals.region-" + cluster + "}", settings: { waf: "${settings.waf}", wp_protect: "${settings.wp_protect}", le_addon: "false", cdn_addon: "false", is_install_wp: "false", is_db_cluster: "false", bl_count: "1", ls_admin_pass: "${globals.ls_admin_pass}", glusterfs: "true", galera: "${globals.initial_env_master-" + cluster + "}", db_user: "${globals.db_user}", db_pass: "${globals.db_pass}", loadGrowth: "${settings.loadGrowth}", db_async_topology: "${globals.db_async_topology}" } }); } return { result: 0, onAfterReturn: { 'marketplace.jps.install': actions } }; getEnvNodes: - script: | var regions = '${settings.regions}'.split(','), onAfterReturn = { setGlobals: {} }, glbs = onAfterReturn.setGlobals; for (var cluster = 1, n = regions.length + 1; cluster < n; cluster ++) { var resp = jelastic.env.control.GetEnvInfo('${settings.envName}-' + cluster, session); if (resp.result != 0) return resp; for (var i = 0, k = resp.nodes; i < k.length; i++) { if (k[i].nodeGroup == 'sqldb') k[i].ismaster ? glbs["master_id_galera-" + cluster] = k[i].id : 0; if (k[i].nodeGroup == 'bl') k[i].ismaster ? glbs["master_id_bl-" + cluster] = k[i].id : 0; if (k[i].nodeGroup == 'cp') k[i].ismaster ? glbs["master_id_cp-" + cluster] = k[i].id : 0; } } return { result: 0, onAfterReturn: onAfterReturn }; installEnvsManager: script: | var regions = '${settings.regions}'.split(','), actions = []; for (var cluster = 1, n = regions.length + 1; cluster < n; cluster ++) { actions.push({ jps: "${baseUrl}/scripts/envManager.jps?_r=${fn.random}", envName: "${settings.envName}-" + cluster, settings: { wp_cluster_url: "${globals.wp_cluster_url}", db_cluster_url: "${globals.db_cluster_url}", master_env_name: "${settings.envName}-1", cluster_name: "${settings.envName}", galera_server_id: "${globals.galera_server_id}", galera_segment_id: cluster, db_user: "${globals.db_user}", db_pass: "${globals.db_pass}", ls_admin_pass: "${globals.ls_admin_pass}", envName: "${settings.envName}" } }); } return { result: 0, onAfterReturn: { install: actions } }; install-wordpress: - install: ${globals.wp_cluster_url}/scripts/installWP.jps envName: ${globals.master_env_name} settings: db_host: ${globals.db_host} db_user: ${globals.db_user} db_pass: ${globals.db_pass} wp_admin_pass: ${globals.wp_admin_pass} wp_title: "Hello World" wp_url: ${globals.protocol}://${globals.domain} version_wordpress: ${globals.version_wordpress} success: email: success/email/${globals.regionsCount}-region-${globals.email}.md?_r=${fn.random} text: success/text/${globals.regionsCount}-region-${globals.success}.md?_r=${fn.random} startPage: ${globals.protocol}://${globals.domain}/