Managing WordPress installations that only use free plugins and themes is painful. ManagedWP allows you to use Composer for plugin and theme dependency management and provides scripts to deploy updates with a simple shell command.
This is a stripped-down version of WordPressBP.
Index:
- System requirements
- Installation
- Development
- Sync from staging or production
- Deployment
- Recommended plugins
- License
Read this Gist on how to correctly set these tools up on your development environment.
Quick-start guide:
- Clone this repository and move into it
- Run the setup script
./setup.sh mywebsite /srv/http/mywebsite.dev
- Set up the web server to serve
mywebsite.dev
from/srv/http/mywebsite.dev/web
- Map the server IP to
mywebsite.dev
in your local hosts file (/etc/hosts
) - Login at
http://mywebsite.dev/wp/wp-login.php
(login: dev / dev) - Initialize Git in
/srv/http/mywebsite.dev/
and start developing
Continue reading for details.
$ ./setup.sh
Usage:
./setup.sh <namespace> <project_path> [<branch>]
Params:
<namespace>: Lowercase alphanumeric name for your project. Must not start with a number. Must be directory / file system / URL friendly.
<project_path>: Path to directory where the project structure will be set up.
<branch>: Branch from which to create the project structure. Defaults to 'master'.
Example:
./setup.sh mything /srv/http/mything.dev
The script will create the directory at project_path
if it doesn't exist. Make sure the parent directory (or project_path
if exists) is writable by the user running this script. Do not run the setup script as root unless you're doing everything as root on your dev environment.
The script will use composer, npm and wp (WP-CLI) to install dependencies and setup WordPress. Make sure these tools are installed as explained here.
If you don't have or don't want to use a root MySQL account, you'll be asked to manually create a database and user for it.
Lets assume your project_path
is /srv/http/mywebsite.dev
and namespace
is mywebsite
.
Create /etc/nginx/sites-enabled/mywebsite.dev.conf
with the following content and restart Nginx:
server {
listen [::]:80;
listen 80;
server_name mywebsite.dev;
root /srv/http/mywebsite.dev/web;
access_log off;
# Rewrite URLs for uploaded files from dev to prod
# - If you've synced the DB from a production site, you don't need to
# download the uploads folder for images to work.
#location /app/uploads/ {
# rewrite ^ http://production.site/$request_uri permanent;
#}
location / {
try_files $uri $uri/ @wordpress;
}
location @wordpress {
rewrite ^ /index.php last;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}
}
To be able to access http://mywebsite.dev
you need to map the server IP to mywebsite.dev
domain in /etc/hosts
. If you're running the server on your local machine, the IP is 127.0.0.1
, if you are using a virtual environment (and you should), then use the IP of that VM.
$ /etc/hosts
...
127.0.0.1 mywebsite.dev
For production refer to the following guides. They include expire headers, gzip configuration and various other settings necessary for high performance and security.
Go to your project at <project_path>/repo
and initialize git or whatever versioning system you like. Note that .gitignore
and .gitattributes
are already present so you can quick-start by running:
git init
git add .
git commit -m "Initial commit"
git remote add origin [email protected]:mygithubname/mywebsite.git
git push -u origin master
WordPress configuration is set in the following files:
.env
- local environment settingsconfig/application.php
- global defaultsconfig/environments/<environment>.php
- environment specific defaults
Use composer to pull in free plugins and themes from WordPres Packagist. You can also include any packages from Packagist and other compatible repositories.
- Include a plugin:
composer require wpackagist-plugin/wordpress-seo
- Keep dependencies updated:
composer update
You want to keep those out of the repository but still deploy them with the rest of the code. .gitignore
is set up to ignore everything inside web/app/{themes,plugins}/
unless the name starts with <namespace>
so you can easily place non-free themes and plugin there for local development.
Then open config/scripts/deploy-pack.js
and make sure these files are copied into the build
directory before deploy. Look for the TODO
comment near the top of the file for examples.
Protip: If you're developing multiple sites on the same dev environment and share a plugin between them (like ACF Pro), symlink it from a single source everywhere you need it. When the project is being packed for deploy, the copy
command will resolve the symlink and copy the files instead. E.g.:
- Shared plugin:
/srv/http/shared-plugin
- Project 1
/srv/http/project1/web/app/plugins/shared-plugin -> /srv/http/shared-plugin
- a symlink to shared plugin - Project 2
/srv/http/project2/web/app/plugins/shared-plugin -> /srv/http/shared-plugin
- a symlink to shared plugin - Then for every project copy the common plugin into
build
when deploying:add to: config/scripts/deploy-pack.js: ... sh.cp('-fr', 'web/app/plugins/shared-plugin', 'build/web/app/plugins/') ...
You could set up composer to use WP language packs by Koodimonni or you can manually download the language pack you need and place the files in web/app/languages/
.
Then edit config/scripts/deploy-pack.js
and make sure these files are copied into the build
directory before deploy.
Syncing from the server requires SSH access. Basic SSH understanding is expected for syncing and deployment which isn't covered here.
Syncing requires wp
(WP-CLI) also available in non-interactive shells on the server. This gist explains that as well.
Open sync.sh
and look for TODO
comments. Set those up before you use the script.
- Ensure you have SSH access to staging or production (wherever
sync.sh
points to) - Create a local database and user
- Clone the repository
- Copy
.env.example
to.env
and set it up - Install dependencies
composer install
npm install
- Sync the database
./sync.sh
- Set up the web server and
/etc/hosts
If you want to push database changes upstream, you will have to figure out how to do migrations. Without that, the only way to ensure a working codebase for everybody on the team is to only sync the database downstream. Whenever database changes are required (WP settings, posts, pages etc.) repeat them on staging when you push and deploy the code.
Keep notes on what to configure when you push everything to production.
Ideas / contributions for DB migrations welcome!
ManagedWP includes a simple automated deployment script using node-shell
and node-ssh
packages. You can deploy your website by running npm run deploy
but this requires some setup. All the configuration for deploys is in config/scripts
directory.
Deploy requires Git, SSH and tar. It's been tested on Linux environments, Mac should work, but Windows probably won't.
Run npm run deploy
or npm run deploy <environment>
.
- When you run deploy, current repository
HEAD
will be build and zipped into a tarball archive - The tarball is uploaded to server over SSH and extracted into a temporary directory
- Static folders and files like
uploads
are symlinked into this temporary directory - Finally, the live
current
directory is renamed toprevious
and the new temporary directory is renamed tocurrent
- Cleanup tasks are run to remove any temporary files from server and local folders
If there's an error with the newly deployed version, you are able to revert to previous deploy by running npm run deploy:revert <environment>
.
If your server is correctly configured, the deployment scripts will never require root (or sudo) to any command or part of the file system.
Edit config/scripts/deploy-config.js
.
defaultDeployEnv
- default environment to deploy to. Needs an entry indeployEnvSSH
anddeployEnvPaths
deployEnvSSH
- SSH connection parameters for all environments you want to deploy toodeployEnvPaths
- Path to directory where you want to deploy the files to for all environments
If your server requires public key authentication, locally the key needs to be managed by an SSH agent so that NodeJS can access it through the SSH_AUTH_SOCK
environment variable.
- Create a writable (for the SSH user) directory on the server where you want to store the files. This should be the path set in
deployEnvPaths
inconfig/scripts/deploy-config.js
. - On development machine run
npm run deploy:init
ornpm run deploy:init [environment]
. This will create the needed directory structure. - Configure the web server to serve from
<directory_from_step_1>/current/web
. - Visit your website. If everything is correct you should see a
phpinfo()
page. - Create the database:
$ mysql -u root -p
create database mywebsitedb;
grant all privileges on mywebsitedb.* to 'dbuser'@'localhost' identified by 'some_password';
flush privileges;
\q
- Dump local database and import it on the server:
wp db export - | ssh user@host -p 54321 'mysql -u dbuser -psome_password mywebsitedb'
(run this locally, the-p<password>
is intentionally without space after-p
). - Set up the environment in
<directory_from_step_1>/static/.env
. - Make
<directory_from_step_1>/static/uploads
writable for the PHP process group:
chown user:www-data uploads # you might need to sudo this
chmod g+w uploads
- Finally, deploy the code:
npm run deploy
ornpm run deploy [environment]
.
All commands support optional environment. If you don't specify it, the default from config/scripts/deploy-config.js
will be used.
npm run deploy [environment]
will deploy the current GitHEAD
toenvironment
. If you leave out the environment, thedefaultDeployEnv
will be used.npm run deploy:revert [environment]
allows you to revert 1 time to previously deployed release.
If you need more flexibility, you can extend the deploy scripts or look into a dedicated deploy tool.
ManagedWP is licensed under the MIT license. See LICENSE.md