What is the current behavior?
When using a multisite configuration, the deployment fails during the ansible task WordPress Installed?.
This is in turn caused by the wp core is-installed command exiting with non zero status because of a ConstantAlreadyDefinedException.
This is related to roots/bedrock#380 and roots/docs#168.
What is the expected or desired behavior?
The deployment completes without error.
The wp core is-installed command exits with 0.
Please provide steps to reproduce, including full log output:
MULTISITE and SUBDOMAIN_INSTALL redefinition is now prevented, by design, with the usage of the new configuration model.$: ./bin/deploy.sh staging ***
TASK [deploy : WordPress Installed?] ***********************************************************************************************
System info:
Ansible 2.6.4; Linux
Trellis version (per changelog): "Allow customizing Nginx `worker_connections`"
---------------------------------------------------
non-zero return code
fatal: [***.***.***.***]: FAILED! => {"changed": false, "cmd": ["wp", "core", "is-installed", "--skip-plugins", "--skip-themes", "--require=/srv/www/***/shared/tmp_multisite_constants.php"], "delta": "0:00:00.367497", "end": "2018-10-26 17:40:16.192522", "failed_when_result": true, "rc": 255, "start": "2018-10-26 17:40:15.825025", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
--debug flag yields the following output:$: wp core is-installed --skip-plugins --skip-themes --require=/srv/www/***/shared/tmp_multisite_constants.php --debug
Debug (bootstrap): Required file from config: /srv/www/***/shared/tmp_multisite_constants.php (0.01s)
Debug (bootstrap): No readable global config found (0.051s)
Debug (bootstrap): Using project config: /srv/www/***/releases/20181026173903/wp-cli.yml (0.051s)
Debug (bootstrap): argv: /usr/bin/wp core is-installed --skip-plugins --skip-themes --require=/srv/www/***/shared/tmp_multisite_constants.php --debug (0.051s)
Debug (bootstrap): ABSPATH defined: /srv/www/***/releases/20181026173903/web/wp/ (0.051s)
Debug (bootstrap): Begin WordPress load (0.052s)
Debug (bootstrap): wp-config.php path: /srv/www/***/releases/20181026173903/web/wp-config.php (0.052s)
PHP Fatal error: Uncaught Roots\WPConfig\Exceptions\ConstantAlreadyDefinedException: Aborted trying to redefine constant 'MULTISITE'. `define('MULTISITE', ...)` has already been occurred elsewhere. in /srv/www/***/releases/20181026173903/vendor/roots/wp-config/src/Config.php:106
Stack trace:
#0 /srv/www/***/releases/20181026173903/vendor/roots/wp-config/src/Config.php(26): Roots\WPConfig\Config::defined('MULTISITE')
#1 /srv/www/***/releases/20181026173903/config/application.php(119): Roots\WPConfig\Config::define('MULTISITE', true)
#2 phar:///usr/bin/wp/php/WP_CLI/Runner.php(1145) : eval()'d code(7): require_once('/srv/www/***...')
#3 phar:///usr/bin/wp/php/WP_CLI/Runner.php(1145): eval()
#4 phar:///usr/bin/wp/php/WP_CLI/Runner.php(1107): WP_CLI\Runner->load_wordpress()
#5 phar:///usr/bin/wp/php/WP_CLI/Bootstrap/LaunchRunner.php(23): WP_CLI\Runner->start()
#6 phar:///usr/bin/wp/php/bootstrap.php(75): WP_CLI\Bootstrap\LaunchRunner->process(Object(WP_CLI\Bootstrap\B in /srv/www/***/releases/20181026173903/vendor/roots/wp-config/src/Config.php on line 106
This is caused by the explicit and one-time requirement of the file roles/deploy/files/tmp_multisite_constants.php, which defines constant that may be re-defined later by the application config.
Possible solutions:
Either of the following:
tmp_multisite_constants.php (the purpose of which is unclear to me at the moment) so that it avoids constant definitions. This is arguably the most desirable approach, but I'm not able to assess exactly what this would entail and how to proceed, because I don't even know why this file is being required in the first place during the affected Ansible task.Roots\WPConfig\Config inside this file is feasible, because the autoloader has not been loaded yet, and I'm not clear when apply should then happen. Maybe this suggests a design oversight in the new configuration model.if defined block to the multisite configuration docs. This would also require to explain accordingly the presence and purpose of tmp_multisite_constants.php, which as previously mentioned I am unable to do. IMO it also grants a kind of "wtf" moment to trellis users, which makes this solution undesirable.define function would make docs inconsistent.Thanks for the great bug report! tmp_multisite_constants.php is a weird hack so I'm not surprised that the Bedrock configuration change didn't consider it (or remember it existed). The new config model should definitely stay since it's Trellis that's doing something weird anyway.
But I'm still not sure the best solution here.
Maybe it's something worth fixing in upstream wp cli, because the way I see it now is that the is-installed command should not require such a hack in the first place.
I tend to agree. I think WP-CLI is just running into a WP bug as well since it's an issue loading WordPress itself, but its their command so ideally it's dealt with there.
@stefanotorresi how did you fix this?
I am having the exact same issue, this fails at the point where /srv/www/sitename/current is not created it.
I manually symlinked it and did as mentioned in the multisite docs.
$ wp core multisite-install --title="site title" --admin_user="username" --admin_password="password" --admin_email="[email protected]"
then the site worked but the deploy script is still broken. How did #766 get merged when the process is still broken? #766 does solve one issue but creates another in my experience.
@geekodour I don't think the presence of /srv/www/sitename/current is related to this particular issue I reported.
To get around the issue I described above, it is sufficient reverting to the usage of builtin define() function instead of the Config wrapper, at least for just the affected constants, i.e. MULTISITE and SUBDOMAIN_INSTALL
It took me a while to remember the existance of tmp_multisite_constants.php. After updating bedrock files to use "roots/wp-config" I faced the same issues ans was only able to go over that by using the default define() function for all the definitions listed in tmp_multisite_constants.php.
I agree that this is quite confusing and it would be great to find a better solution for that.
As a new user of Trellis this problem is really annoying.
For the moment I would be happy if at least I knew how to do the workaround to be able to deploy successfully, but I don't know how to revert to the usage of define() because I don't know how this was managed before.
Finally I managed to deploy by commenting out two lines in trellis/roles/deploy/files/tmp_multisite_constants.php:
error_reporting(E_ALL & ~E_NOTICE);
//define('MULTISITE', false);
//define('SUBDOMAIN_INSTALL', false);
define('WPMU_PLUGIN_DIR', null);
define('WP_PLUGIN_DIR', null);
define('WP_USE_THEMES', false);
@arusa thanks for posting your workaround. That's all it took it fix it? It was a one-step process?
Yes, everything else is like documented as far as I remember.
Everything seems to work now, but commenting out the two lines was an act of desperation ;-)
application.php contains the following constants now:
Config::define('WP_ALLOW_MULTISITE', true);
Config::define('MULTISITE', true);
Config::define('SUBDOMAIN_INSTALL', true); // Set to true if using subdomains
Config::define('DOMAIN_CURRENT_SITE', env('DOMAIN_CURRENT_SITE'));
Config::define('PATH_CURRENT_SITE', env('PATH_CURRENT_SITE') ?: '/');
Config::define('SITE_ID_CURRENT_SITE', env('SITE_ID_CURRENT_SITE') ?: 1);
Config::define('BLOG_ID_CURRENT_SITE', env('BLOG_ID_CURRENT_SITE') ?: 1);
and to be able to login to sites with different domains I also added the following:
Config::define('ADMIN_COOKIE_PATH', '/');
Config::define('COOKIE_DOMAIN', '');
Config::define('COOKIEPATH', '');
Config::define('SITECOOKIEPATH', '');
@swalkinshaw That doesn't completely avoid the issue with the config class throwing an error when it encounters a constant that's already defined. If a user defines WPMU_PLUGIN_DIR or WP_PLUGIN_DIR (or anything else defined in tmp_multisite_constants.php) within application.php using the config class, then it will similarly throw an error.
I may be wrong here but I think this tmp_multisite_constants.php is only needed when a multisite install is configured incorrectly? For example when trying to add multisite constants prematurely and against the multisite install procedure.
The multisite install procedure should be:
WP_ALLOW_MULTISITE constant - commit to gitSo long as this procedure is followed I'm under the impression the tmp_multisite_constants.php isn't needed
Edit: For more concise setup instructions follow https://github.com/roots/trellis/issues/1025#issuecomment-579132975
Yep, confirmed that these constants don't need to be set at all for WP CLI when the correct multisite procedure is followed.
I can work on a PR to remove the constants and update the Trellis docs with some more clear guidelines if that would help? Might be next week until I can do that
Getting rid of this workaround would be amazing. Just to confirm what you're saying/proposing:
Is the latter the proper procedure even putting aside Trellis (or Bedrock)?
The initial bug report was caused by these steps:
The error happens on a first deploy of multisite -- before multisite is installed.
That's right, I went through step by step last night, all wp cli checks work absolutely fine when the above is followed. I think this just needs education / specific step by steps in the docs
This procedure is the correct way for all multisites, you can get DB errors if you don't follow this. It's even common to run into issues when you have the allow multisites constant enabled before WP is installed.
These tests were done on Trellis and Bedrock, and work exactly the same. In fact if constants were incorrectly defined an another stack you'd get the same table errors in WP CLI. This fix came about due to user error essentially. Ref: https://wordpress.org/support/article/create-a-network/
Question: What is the procedure to "taking over an existing multisite codebase"?
Example:
$ git clone <multisite-bedrock-and-trellis>$ vagrant upIt should throw errors during step 2 becuase WP_ALLOW_MULTISITE is defined and database is not yet imported.
Same goes to provsioning remote server the first time when Bedrock alredy coded in multisite (e.g: WP_ALLOW_MULTISITE is defined & codebase assuming multisite mode)
The procedure would be similar, it's erroneous to have a multisite constant and not a multisite database. The other way round however is fine.
So to import an existing multisite DB you would first have a single install, you would import the multisite DB. At this point you have a multisite DB but the multisite tables are ignored by the dashboard. Until the constants are added.
The mention of having WP_ALLOW_MULTISITE configured before the database doesn't give errors all the time. But in some situations it does. For example if you had this constant defined in WordPress VIP when a database hasn't been setup then it would throw fatal errors. The reason this is part of the procedure is because this is what WP suggests
Was your question "Why aren't I seeing errors with WP_ALLOW_MULTISITE defined before multisite has been installed?"
If the current process is just wrong, then yeah it should be changed. It sounds like right now this tmp_multisite_constants.php workaround is enabling (or mostly enabling) a process that shouldn't be supported or encouraged?
The counter point is that is has been "working" (as far as I know) and simplifies the process for people?
Is there any reason for or against updating the Trellis documentation to reflect the steps @craigpearson has outlined?
There's still a bit of uncertainty here. It would be better to solve this in Trellis itself and ideally remove tmp_multisite_constants.php instead of just documenting steps to work around it.
@swalkinshaw That's true. Can you clarify the following a bit?
On a single site:
vagrant up, I have a domain.test site I can immediately access.On a multisite:
vagrant up, I have a domain.test multisite I can immediately access.Apologies if I'm misunderstanding or asking dumb questions!
I honestly don't know... I haven't tried multisite in forever. Though I think what you're asking is due to the problem described by this issue.
If we removed the tmp_multisite_constants.php and relied on people to follow the process they'd have to install a single site first and it would behave as you expect.
@ttamnedlog This is from memory but I believe if you have the multisite constants defined in bedrock. And you're provisioning / deploying to your live environment for the first time then the deploy will report a failure.
This is due to tmp_multisite_constants.php setting constants which are then set again due to the way config::define works. tmp_multisite_constants.php also aims to bypass default WP behaviour of running WP CLI commands which are unique to a multisite install before a database is converted to a multisite database
I'm of the opinion that this shouldn't be bypassed as it leads people to break out of the normal multisite setup process, and causes confusion like this. So I personally remove the file from my projects. This means that you should do your first staging / production deploy in the following order:
config\application.php/**
* (Required) Multisite Options
*/
Config::define('WP_ALLOW_MULTISITE', true);
// Config::define('MULTISITE', true);
// Config::define('SUBDOMAIN_INSTALL', false); // Set to true if using subdomains
// Config::define('DOMAIN_CURRENT_SITE', env('DOMAIN_CURRENT_SITE'));
// Config::define('PATH_CURRENT_SITE', env('PATH_CURRENT_SITE') ?: '/');
// Config::define('SITE_ID_CURRENT_SITE', env('SITE_ID_CURRENT_SITE') ?: 1);
// Config::define('BLOG_ID_CURRENT_SITE', env('BLOG_ID_CURRENT_SITE') ?: 1);
/**
* (Optional) Constants to help with assigning custom domains and prevent redirect login loops
*/
// Config::define('ADMIN_COOKIE_PATH', '/');
// Config::define('COOKIE_DOMAIN', '');
// Config::define('COOKIEPATH', '');
// Config::define('SITECOOKIEPATH', '');
Your wordpress_sites.yml for production / staging should be like so:
multisite:
enabled: false
subdomains: false
http://example.com/wp/wp-admin/install.phpconfig\application.php such as below:/**
* (Required) Multisite Options
*/
Config::define('WP_ALLOW_MULTISITE', true);
Config::define('MULTISITE', true);
Config::define('SUBDOMAIN_INSTALL', false); // Set to true if using subdomains
Config::define('DOMAIN_CURRENT_SITE', env('DOMAIN_CURRENT_SITE'));
Config::define('PATH_CURRENT_SITE', env('PATH_CURRENT_SITE') ?: '/');
Config::define('SITE_ID_CURRENT_SITE', env('SITE_ID_CURRENT_SITE') ?: 1);
Config::define('BLOG_ID_CURRENT_SITE', env('BLOG_ID_CURRENT_SITE') ?: 1);
/**
* (Optional) Constants to help with assigning custom domains and prevent redirect login loops
*/
Config::define('ADMIN_COOKIE_PATH', '/');
Config::define('COOKIE_DOMAIN', '');
Config::define('COOKIEPATH', '');
Config::define('SITECOOKIEPATH', '');
wordpress_sites.yml to enable multisite i.e.multisite:
enabled: true
subdomains: false # Set to true if using sub domains
roles/deploy/files/tmp_multisite_constants.php error_reporting(E_ALL & ~E_NOTICE);
//define('MULTISITE', false);
//define('SUBDOMAIN_INSTALL', false);
define('WPMU_PLUGIN_DIR', null);
define('WP_PLUGIN_DIR', null);
define('WP_USE_THEMES', false);
_I believe this to conflict with Bedrocks new Config::define method if someone could confirm?_
Just to clarify on development environments WordPress is automatically configured and the above errors don't take place, so this procedure can be ignored. But on production and staging environments WordPress must be configured via the http://example.com/blog/wp-admin/install.php URL, and this procedure should be followed
@craigpearson When you say "no multisite constants" do you mean disabling all mention of multisite in both wordpress_sites.yml and application.php?
e.g.
multisite:
enabled: false # true
subdomains: false # true
/**
* Multisite
*/
// Config::define('WP_ALLOW_MULTISITE', true);
// Config::define('MULTISITE', true);
// Config::define('SUBDOMAIN_INSTALL', true); // Set to true if using subdomains
// Config::define('DOMAIN_CURRENT_SITE', env('DOMAIN_CURRENT_SITE'));
// Config::define('PATH_CURRENT_SITE', env('PATH_CURRENT_SITE') ?: '/');
// Config::define('SITE_ID_CURRENT_SITE', env('SITE_ID_CURRENT_SITE') ?: 1);
// Config::define('BLOG_ID_CURRENT_SITE', env('BLOG_ID_CURRENT_SITE') ?: 1);
If so, I'm confused as to how I can "Run the multisite installation wizard"? I may be looking in the wrong places, but I'm not seeing anything... Don't some of these options need to be enabled for the multisite stuff to be visible?
@shaneparsons Craig's response to me seems to be a bit more high level and omits some of the details provided in his earlier comment: https://github.com/roots/trellis/issues/1025#issuecomment-530616635
I would follow Craig's steps as described there. In short, yes, disable all mention of multisite initially, and yes, you will then need to enable Config::define('WP_ALLOW_MULTISITE', true); to trigger the installation wizard.
@ttamnedlog Thanks for that I've updated my previous comments to avoid any further confusion
@ttamnedlog This is from memory but I believe if you have the multisite constants defined in bedrock. And you're provisioning / deploying to your live environment for the _first time_ then the deploy will report a failure.
This is due to
tmp_multisite_constants.phpsetting constants which are then set again due to the wayconfig::defineworks.tmp_multisite_constants.phpalso aims to bypass default WP behaviour of running WP CLI commands which are unique to a multisite install _before_ a database is converted to a multisite databaseI'm of the opinion that this shouldn't be bypassed as it leads people to break out of the normal multisite setup process, and causes confusion like this. So I personally remove the file from my projects. This means that you should do your first staging / production deploy in the following order:
- Deploy a single site with the following in
config\application.php/** * (Required) Multisite Options */ Config::define('WP_ALLOW_MULTISITE', true); // Config::define('MULTISITE', true); // Config::define('SUBDOMAIN_INSTALL', false); // Set to true if using subdomains // Config::define('DOMAIN_CURRENT_SITE', env('DOMAIN_CURRENT_SITE')); // Config::define('PATH_CURRENT_SITE', env('PATH_CURRENT_SITE') ?: '/'); // Config::define('SITE_ID_CURRENT_SITE', env('SITE_ID_CURRENT_SITE') ?: 1); // Config::define('BLOG_ID_CURRENT_SITE', env('BLOG_ID_CURRENT_SITE') ?: 1); /** * (Optional) Constants to help with assigning custom domains and prevent redirect login loops */ // Config::define('ADMIN_COOKIE_PATH', '/'); // Config::define('COOKIE_DOMAIN', ''); // Config::define('COOKIEPATH', ''); // Config::define('SITECOOKIEPATH', '');Your
wordpress_sites.ymlfor production / staging should be like so:multisite: enabled: false subdomains: false
- Install WP via the GUI on the live server i.e.
http://example.com/wp/wp-admin/install.php- Run the multisite installation wizard
- Uncomment multisite constants in
config\application.phpsuch as below:/** * (Required) Multisite Options */ Config::define('WP_ALLOW_MULTISITE', true); Config::define('MULTISITE', true); Config::define('SUBDOMAIN_INSTALL', false); // Set to true if using subdomains Config::define('DOMAIN_CURRENT_SITE', env('DOMAIN_CURRENT_SITE')); Config::define('PATH_CURRENT_SITE', env('PATH_CURRENT_SITE') ?: '/'); Config::define('SITE_ID_CURRENT_SITE', env('SITE_ID_CURRENT_SITE') ?: 1); Config::define('BLOG_ID_CURRENT_SITE', env('BLOG_ID_CURRENT_SITE') ?: 1); /** * (Optional) Constants to help with assigning custom domains and prevent redirect login loops */ Config::define('ADMIN_COOKIE_PATH', '/'); Config::define('COOKIE_DOMAIN', ''); Config::define('COOKIEPATH', ''); Config::define('SITECOOKIEPATH', '');
- Update appropriate
wordpress_sites.ymlto enable multisite i.e.multisite: enabled: true subdomains: false # Set to true if using sub domains
- (Optional) Comment out multisite lines in
roles/deploy/files/tmp_multisite_constants.phperror_reporting(E_ALL & ~E_NOTICE); //define('MULTISITE', false); //define('SUBDOMAIN_INSTALL', false); define('WPMU_PLUGIN_DIR', null); define('WP_PLUGIN_DIR', null); define('WP_USE_THEMES', false);_I believe this to conflict with Bedrocks new
Config::definemethod if someone could confirm?_
- Commit code to your repo and redeploy
Just to clarify on development environments WordPress is automatically configured and the above errors don't take place, so this procedure can be ignored. But on production and staging environments WordPress must be configured via the http://example.com/blog/wp-admin/install.php URL, and this procedure should be followed
you forgot to mension that re-provision is also required
Most helpful comment
@ttamnedlog This is from memory but I believe if you have the multisite constants defined in bedrock. And you're provisioning / deploying to your live environment for the first time then the deploy will report a failure.
This is due to
tmp_multisite_constants.phpsetting constants which are then set again due to the wayconfig::defineworks.tmp_multisite_constants.phpalso aims to bypass default WP behaviour of running WP CLI commands which are unique to a multisite install before a database is converted to a multisite databaseI'm of the opinion that this shouldn't be bypassed as it leads people to break out of the normal multisite setup process, and causes confusion like this. So I personally remove the file from my projects. This means that you should do your first staging / production deploy in the following order:
config\application.phpYour
wordpress_sites.ymlfor production / staging should be like so:http://example.com/wp/wp-admin/install.phpconfig\application.phpsuch as below:wordpress_sites.ymlto enable multisite i.e.roles/deploy/files/tmp_multisite_constants.php_I believe this to conflict with Bedrocks new
Config::definemethod if someone could confirm?_Just to clarify on development environments WordPress is automatically configured and the above errors don't take place, so this procedure can be ignored. But on production and staging environments WordPress must be configured via the http://example.com/blog/wp-admin/install.php URL, and this procedure should be followed