An Intro to Bedrock for WordPress
The following is a guest post by Alessandro Vendruscolo, who wrote to me excited to write a guest post about a WordPress tool that I didn’t know much about: Bedrock. It’s not a theme, it’s a way to install, configure, and manage WordPress with security and modern development practices in mind.
Bedrock is an open source project made by Roots that you use as base for WordPress projects.
Why should you care about Bedrock? Let’s take one step back and think about a typical way to work on a WordPress project.
Classic WordPress Workflow
You can download and install WordPress both on your local machine and production server. You can have a git repository for your theme. Deployment can be FTP transferring of theme or git pulling the repo from the server. For some projects, you might want to keep the entire site (even WordPress files) under git as well.
This has issues:
- Updating WordPress/plugins from production may break your production site
- You have to manually keep track of WordPress/plugin versions
- Deploys can be cumbersome
- Configuring WordPress is difficult, because the
wp-config.php
can’t be under version control
Here’s an example of what I mean. You update a plugin locally because you need some new functionality that the updated plugin provides. You write code based on that new functionality. Now it’s time to deploy. You:
- Install or update the plugin on the production site (make sure it’s the same version!)
- Compile assets
- Update the theme on the remote server (using whatever deployment method)
- If it’s a new plugin, make sure it’s been activated on the production site
This is a rather manual approach and can be quite error prone. Most importantly, it can cause downtime or fatal errors. For instance, you update the plugin and it’s not backwards-compatible, so it throws errors until the deployment is finished. Or you deploy first and the site throws errors until you update the plugin.
Enter Bedrock
If the issues above sound like something you have dealt with in the past, you’ll like Bedrock. It brings:
- Explicit dependencies tracked by Composer
- Easy configuration with phpdotenv
- Easy one-command deploys with Capistrano
You’ll end up with a self-contained WordPress project that installs an explicit version of WordPress and required plugins (composer install
) which can be easily configured. All configuration is kept in a .env
text file) and deployed (cap production deploy
).
Less troubles and more automation! Even onboarding a new developer is easier.
You also get a multistage environment for free. You can have a development
configuration for working locally and, a staging
configuration for tests, and a production
configuration for the live site. You can also define custom configuration, such as backup
where you can have a 1:1 copy of the production environment, on a different server.
Requirements
Here are the requirements for working with Bedrock:
- You should be comfortable working on the command line.
- You need shell access to the server: if your site is hosted on shared host you’re probably out of luck1.
- PHP >= 5.5
- You need Composer on the server (install instructions).
- You need to have a working Ruby and gem environment on your machine to perform deploys.
- You need to have WP-CLI installed locally and on the server if you plan to use it. It’s not required, but you’ll see later that’s useful (install instructions).
This is in addition to all the normal WordPress server requirements, like MySQL.
Getting Started
Let’s assume a brand new WordPress project. First, you’ll need a copy of Bedrock, which you can get from its repository.
Should I clone or download the repo?
Bedrock’s README tells you to clone the repository, but in my opinion you’re better off downloading it. If it’s something that you plan to regularly keep up to date, go for the clone route; if it’s something that you plan to set-and-forget, go for the download route.
Keeping Bedrock up to date is certainly a good thing (improvements, security, etc) but it can be tricky. You may need to hand-pick changes or try to merge two upstreams. Since it is a starting point, downloading it means you can set it up once and forget about it.
Installation
Now that you have downloaded the repo, you can initialize your own repository for the project.
wget https://github.com/roots/bedrock/archive/master.zip
unzip master.zip
rm master.zip
mv bedrock-master ~/Sites/example.dev
cd !$
git init
I keep all my web projects in the Sites folder in my home directory (I develop on OS X) and keep them indexed by their name. I use the `.dev` TLD so I can configure nginx with virtual hosts. This way, even when working locally, I have a configuration that’s almost identical to the live website. (Bonus points compared to using localhost
: you get a new environment to work on: cookies, local storage, URLs for caching, etc are not shared with any other site you previously worked on.)
On my machine, I use this minimal configuration to instruct nginx how to host the website. Please note that the root folder isn’t the same as the project. Bedrock puts all public files in the web
folder.
server {
listen 80;
server_name example.dev;
root /Users/MJ/Sites/example.dev/web;
location / {
try_files $uri $uri/ /index.php;
}
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass unix:/tmp/php5-fpm.sock;
}
}
Now we need to run a command to let the magic happen:
composer install
As you can see by the output, Composer will install dependencies listed in the composer.lock
file, including WordPress itself2.
So, what’s happening?
If you’re new to Composer, I’ll quickly explain what it is and how it works.
Composer is a tool written in PHP that lets you manage PHP dependencies (just like Ruby gems, npm modules, CocoaPods, etc). These days all languages have a dependency manager.
You declare the packages you need in the composer.json
file, then declare them with constraints. Having constraints lets you define how Composer will update them when you run composer update
.
For example, Bedrock requires an explicit version for WordPress (4.5 at the time of writing) and any version
greater than 2 but less than 3 for phpdotenv.
Every time you execute composer update
Composer will try to update your packages to the latest version allowed, and will write down that version number to the composer.lock
file.
Now, when you run composer install
(just like you did earlier) it’ll install that specific version no matter what, reading from the composer.lock
file (This is a reason that using Composer is very safe, just like gem and CocoaPods, and unlike npm, unless you use the shrink-wrap feature).
If you now list the contents of the web
and web/wp
directory, you will see something you’re familiar with: Composer has moved the wp-config.php
file to web
and all WordPress files are in the web/wp
folder. If you inspect that file you can understand why it’s there.
We’ve everything in place, it’s now time to configure WordPress.
Copy the `.env.example` to `.env` and edit it:
cp .env.example .env
vim .env
It asks you for:
- The name of the database you use (I’ll use
example_development
) - The username that will be used to connect to the database (on my machine I have just one
root
user) - The password of that user
- The host of the database (
127.0.0.1
orlocalhost
is fine) - The environment of this installation (
development
is fine, you can set whatever you want: usually you havedevelopment
,staging
, andproduction
) - The homepage URL that WordPress will use to build URLs among other things (I set
http://example.dev
) - The URL for the admin page. Leave it as it is and you’ll access WordPress admin pages at
http://example.dev/wp
. If you change this you’ll also need to move thewp
folder contents accordingly - Authorization keys and salts that you can generate online
After you’ve saved the file you can proceed to install WordPress (it needs to create all the tables in the database!). You can do this by visiting the website on http://example.dev/
or by using WP-CLI:
wp core install --url='http://example.dev' --title='Example' --admin_user='admin' --admin_password='enter' --admin_email=''
WordPress has been successfully installed!
We can commit what we did (git add . && git commit -m 'First commit'
).
Let’s recap that process:
- Download Bedrock;
- Run
composer install
; - Edit the
.env
file; - Install WordPress (automated with the
wp core install …
command).
If other developers later join the team, they’ll clone the project’s repo and start at step 2.
Working on your project
At this point we have a default WordPress installation, and we can start customizing it!
If we inspect the folder structure you can see how Bedrock organizes the files:
.
├── config
│ ├── application.php
│ └── environments
│ ├── development.php
│ ├── production.php
│ └── staging.php
├── vendor
├── web
│ ├── app
│ │ ├── mu-plugins
│ │ ├── plugins
│ │ ├── themes
│ │ └── uploads
│ ├── wp
│ └── wp-config.php
config
: this is where you configure WordPress. These files can’t be accessed from the Internet, because we set nginx to serve files from theweb
folder.config/application.php
: this file contains the usual WordPress configuration and is intended to include base settings that are common to all environments.config/environments/*
: these contain environment-specific settings. For example in production it disables errors output.
vendor
: dependencies managed by Composer will be installed there, except WordPress plugins and themes; if you inspect thecomposer.json
file you’ll see that these kind of packages will be moved inweb/app/{mu-plugins,plugins,themes}/
.web
: files included in this directory are publicly available
— only the files that are required are in theweb
folder (seeconfig
above).web/app
: this is the oldwp-content
folder. It’s been renamed to better reflect its content (this also matches other frameworks conventions, such as Rails and Symfony). This is where your plugins and themes will end up.web/wp
: the whole WordPress package. This should be put invendor
but can’t be because of WordPress limitations.web/wp-config.php
: this file is well-known, but in Bedrock it acts as a loader (it loads settings from theconfig
directory). It needs to stay here because WordPress core hard codes paths.
Configuration and environment variables
As we saw earlier we have multiple configuration files under the `config` directory, and we also have the `.env` file where we put the username/password for the database.
The key aspect is this: if it’s something that’s sensitive (a password or an external service access key) you should put that in the `.env` file and read that with the env('')
function. Sensitive information will never be stored in your git repository (the `.env` file is ignored by git) which is a huge benefit. It also allows you to define a different password/key for each machine. Imagine if every developer has to generate their Twitter consumer key or has to generate a new one for testing purposes: if the key is stored in a file that’s tracked by git you have to remember not to add that file to the staging area.
The solution is to add it to the .env
file:
[…]
DB_PASSWORD=<password>
[…]
and read that value in the configuration file:
define('DB_PASSWORD', env('DB_PASSWORD'));
Remember that environment-specific files (`config/environment/.php`) are required before the main (`config/application.php`). This means that you can’t override settings. Say that you have the same configuration for development and staging but a different one for production. You can:
- define it in every environment file (`development.php`, `staging.php`, `production.php`, etc).
- put it in the `.env` file and define it in the main application (`application.php`) file.
Plugins
If your plugin is available in the official plugin registry, you can install using Composer and WordPress Packagist, which is a Composer repository that mirrors WordPress’ official plugin and theme registry.
Bedrock already added wpackagist’s repository, so installing a plugin is just a matter of running the following command to install the latest version:
composer require wpackagist-plugin/<name>
git add composer.json composer.lock
git commit -m 'Install <name> plugin'
Plugins are prefixed with wpackagist-plugin/
so the plugin Memberful WP becomes wpackagist-plugin/memberful-wp
.
You can provide a constraint for the version (the previous command would use the ^
constraint):
composer require wpackagist-plugin/memberful-wp ~1.0
git add composer.json composer.lock
git commit -m 'Install Memberful plugin'
You can achieve the same if you manually edit the composer.json
file and run composer install
.
If your plugin isn’t available on the official registry (like custom or paid plugins), you will need to put it in `web/app/plugins` and remove it from the ignore list:
mv ~/Downloads/my-plugin web/app/plugins/
echo '!/web/app/plugins/my-plugin' >> .gitignore
git add .gitignore web/app/plugins/my-plugin
git commit -m 'Add my AWESOME plugin'
Even better, if you have a git repository for the plugin, you can use Composer directly. Add the following to the repositories
array of the composer.json
file:
{
"type": "git",
"url": "<repository url>"
}
The repository needs to contain a `composer.json` manifest file in the root, such as this:
{
"name": "macstories/wp-push-plugin",
"description": "MacStories' implementation of Safari Push Notifications",
"type": "wordpress-plugin",
"license": "proprietary",
"require": {
"php": ">=5.5",
"composer/installers": "~1.0.12"
}
}
When everything above is set, you can run composer require macstories/wp-push-plugin
to install it. Composer expects to have at least one git tag on that repository.
Now we have the plugin in place, we can enable it. Head over the WordPress admin page or once again use WP-CLI:
wp plugin activate memberful-wp
This time we don’t need the wpackagist-plugin
prefix, as WordPress doesn’t know about Composer.
If plugins need to create files or folders, they should be ignored by git, adding them in the .gitignore
file. One example of this is WP Super Cache: it creates two PHP files containing settings.
If plugins ask you to modify the wp-config.php
file, move those new settings to `application.php` (or the environment specific one) as explained earlier.
Themes
Themes work the same way as plugins, with two differences:
- Their directory is
web/app/themes
; - Composer’s vendor name is
wpackagist-theme
.
If you use a theme that’s available on the official WordPress registry you can install it with Composer:
composer require wpackagist-theme/activello
If you’re going to develop your own theme, create its folder under web/app/themes
and you’re ready to go. There’s no need to exclude it from the .gitignore
file.
In your theme you can query the current environment and take advantage from that. For example, on MacStories (a site I developed with Bedrock), I don’t include the minified assets in development
:
$main = '';
if (WP_ENV === 'development') {
$main = macstories_asset_url( '/dist/main.css' );
} else {
$main = macstories_asset_url( '/dist/main.min.css' );
}
// use the $main variable
Another difference is analytics. I only include Mint Analytics in production, using an approach similar to above. Google Analytics is available even in development or staging, but these two environments use a different site ID, so it’s easier to perform tests.
Upgrading WordPress
At the time of this writing, WordPress is at 4.5.2. Let’s say 4.5.3 version comes out. We need to change the required version. You can edit the composer.json
file and run composer install
or you can just issue the following command:
composer require johnpbloch/wordpress 4.5.1
It will update the `composer.json` file (and also the lock file, since we upgraded a dependency) and install the dependency.
Usually after each WordPress update there’s a database schema upgrade to be performed which you can do by visiting the WordPress admin page. But that’s tedious, so WP-CLI has a command to perform that:
wp core update-db
There’s also another thing to keep in mind when upgrading the database schema: if you use the web UI to do that, and the operation takes too much time, you may encounter HTTP timeouts. WP-CLI skips the HTTP layer and performs the operations running PHP from the command line, which doesn’t have any timeout issues.
Upgrading plugins
Upgrading plugins is similar to upgrading WordPress: if you used Composer to install them, use Composer to upgrade them.
You can run composer require wpackagist-plugin/
to upgrade a given plugin to a specific version or, even better, use composer update
to update every package to their latest version that satisfies the constraints set in the `composer.json` file.
When you composer require
something (without specifying a version), Composer will by default use the ^
constraint: running composer update
will update the package to the latest version that’s not a new major version. Easy peasy.
Deploying your project
At this point you should have a working WordPress site on your machine. But that’s almost useless, unless your machine is on the Internet.
Capistrano is the de-facto tool used for deploys, and you can use it to deploy WordPress sites.
What is Capistrano?
Capistrano is a powerful tool written in Ruby used mainly3 to perform deploys. Originally it was born to deploy Ruby on Rails web applications, but then it grew to deploy any kind of web application, with plugins to run custom tasks or connect to external services.
There are plenty of guides on the Internet and many conference talks, but to sum it up: Capistrano will connect to your server using SSH and then follow this flow to update a repository on the server and run tasks. You add hooks on every task to perform what you need.
It’s designed to work with SSH keys (so you don’t have to use passwords) and it should connect to the server as an unprivileged user. It can issue sudo
commands, but if you need to do that, there’s probably something wrong with your setup. You can learn more about this on the Authentication & Authorisation documentation page. I use SSH agent forwarding so Capistrano is able to pull from the git host using my local SSH key.
On the server, Capistrano works by keeping multiple directories in the directory you set as the target of deploys:
.
├── current -> releases/20160420173015
├── releases
│ ├── 20160420173015
│ ├── 20160412113015
├── repo
└── revisions.log
├── shared
current
: this is a symlink to the current version deployed (either the latest one or a previous one if you rolled back).releases
: every time you deploy Capistrano will create a new folder with a timestamp. You can configure the number of releases to keep, and Capistrano will clean up old releases (defaults to keeping 5 releases).repo
: Capistrano keeps the repository on the server and checkouts the correct revision on the server — nothing is transferred from your machine to the remote server.revisions.log
after every deploy or rollback this log will be updated.shared
: contains files and folders that must be shared between releases, such as user uploads.
Each deploy is run in isolation and has its own folder in the releases
folder. If something goes wrong, nothing happens to the current version. When it’s done, Capistrano will update the symlink to the version that was just deployed.
In your project you’ll have a Capfile
that requires the tasks to run (see the example from the flow) and a deploy.rb
file that contains settings.
If you don’t want to use Capistrano
Bedrock supports Capistrano, but it’s not required. If Capistrano doesn’t compel you, or you prefer to use a different tool, or prefer to use no tool at all, you’re free to do so.
The only requirement is that you run composer install
on the server, so Composer can pull down WordPress, plugins, and any other dependency your site needs. Otherwise you’ll have a sort of zombie website with just application code but not the application itself.
Deploying with Capistrano
OK, I convinced you to try Capistrano, let’s go on!
The Roots team (the team behind Bedrock) created a separate repository to host the Capistrano integration for Bedrock. This is because Capistrano is not required by Bedrock but can be added at any time.
Create or edit a Gemfile
file in the root of the project and paste this content:
source 'https://rubygems.org'
group :deployment do
gem 'capistrano', '~> 3.4'
gem 'capistrano-composer'
gem 'capistrano-wpcli'
end
Now run bundle
to have it install the gems. This differs a bit from Roots’ setup, because we grouped these gem in the deployment
group and also installed the WP-CLI
extension.
Capistrano will be installed by Bundler and be treated as a dependency just like we did with WordPress and Composer earlier. This is useful because every project can use a different version of Capistrano and will not depend on a globally installed one. Also, if there are multiple developers on the team, a locally installed (and synchronized) version of Capistrano ensures that everything will be as smooth as possible4.
Commit both `Gemfile` and `Gemfile.lock` – just as with Composer:
git add 'Gemfile*' && git commit -m 'Install Capistrano'
Now we need to set up Capistrano. Capistrano’s configuration will be kept in the git repo. You have to copy the Capfile
file and the contents of the config
directory from the repository. This is the equivalent of running bundle exec cap install
and editing Capistrano’s configuration files.
Since we also installed the WP-CLI plugin, we have to require it in the Capfile
. Add the following line after we required the Composer plugin:
require 'capistrano/wpcli'
Edit the config/deploy.rb
and set the :application
and :repo_url
variables and remove the :deploy_to
line. If you want, you can also change other settings here. There are many code comments and the documentation is great.
The :linked_files
and :linked_dirs
variables are important. If you recall from earlier, Capistrano will create on the server a shared
folder (shared between deploys). By default, we’ll share the `.env` file and the `web/app/uploads` folder.
The `.env` file contains application settings and needs to be shared for the site to work, and also because this file isn’t under version control. The `web/app/uploads` folder is the old `wp-content/uploads` folder and needs to be shared because otherwise uploads would exist only within a release.
You can probably ignore the rest of the config/deploy.rb
file. After line 22 it defines two custom tasks. The first is empty and disabled by default. It can be used for example to restart the web server. If you have something to restart after a deploy, update the task and enable it.
The second task has been added by the roots team and is disabled by default. It’s used update the stylesheet_root
and template_root
options of WordPress. I’ve never had a reason to change them.
Edit the `config/deploy/.rb` file to set per-stage settings.
You have to update the server
setting, because the production env is likely to be on a different server than the staging one.
We’ll move the :deploy_to
path setting here, as your staging path is probably different from the production one. You can also override settings set in the main `deploy.rb` file. The rationale of these files is the same as Bedrock environment files.
Now we configured Capistrano and everything should work. Capistrano comes with a check task that, well, checks that everything works.
Run the following command to perform the check:
bundle exec cap staging deploy:check
Capistrano will:
- Log in on the server with the user you defined (so you’re sure the SSH connection works)
- List repository remote files (so you know Capistrano is able to connect and authenticate with the git host)
- Create the directory structure
- Create linked folders
- Check for linked files
Here’s an example of a Capistrano error we might see:
ERROR linked file /path/to/:deploy_to/shared/.env does not exist on
Create that file (you can use scp .env @:/shared/.env
to upload your development `.env` file to the server. At this time, we’re interested in having the file, not having the correct file) and when you’re done check again that everything works. Hooray it works!
Push your changes (otherwise Capistrano will clone an empty or old repository) and run the following to perform a real deploy:
bundle exec cap <stage> deploy
This is the command that you’ll need to remember and run every time you’ll want to deploy your site.
Configuring the remote WordPress
You will have to update the `.env` file on the remote server to set the correct database information and, most importantly, the WP_ENV
and WP_HOME
settings.
If you deployed to production that must be WP_ENV=production
(I don’t know your WP_HOME
value).
Your web server needs to serve contents from the current
folder, so if locally you had this this setting for nginx:
root /Users/MJ/Sites/example.dev/web;
on the server you’ll have to update it in this way:
root <value of :deploy_to>/current/web;
Installing WordPress on the remote server is just a matter of doing the same things you did on your local machine. You can use the web UI or use WP-CLI, even from within Capistrano.
When you deploy a new version and in that version you install a new plugin, you can use the following command to enable the plugin:
bundle exec cap <stage> wpcli:run['plugin activate <name>']
To perform database migrations:
bundle exec cap <stage> wpcli:run['core update-db']'
Hooks
You can define custom tasks for Capistrano to run, but before doing so, search for an existing solution. Capistrano comes with many official plugins, like Bundler, npm and many other community driven plugins.
For example, say you have a build script that compiles Sass assets. Because of the benefits we talked earlier, you should require Sass in the Gemfile
with:
gem 'sass', '~> 3.4'
Now we need to do two things when we deploy:
- Ensure the sass gem is installed
- Run our own build script
Capistrano-bundler
The first step is easy to achieve: we’ll require the capistrano-bundler
gem by adding this line to the :deployment
group:
gem 'capistrano-bundler', '~> 1.1.2'
After that you run bundle
to install the gem and also edit the Capfile
to require it:
require 'capistrano/bundler'
Done. Every time we deploy, Capistrano will run bundle install
on the server, after the deploy:updated
task.
If you want, set the :bundle_without
variable in the `deploy.rb` file:
set :bundle_without, %w{deployment development test}.join(' ')
Doing so will exclude those groups of gems from being installed. Bundler will install less gems (that we won’t need!) and our deploys will be faster.
Running custom scripts
I don’t know how your build script is structured. I’m a fan of make, but you can have anything you want: a shell script, npm scripts, Grunt/Gulp tasks, etc. No matter what, we have to run them, otherwise our site will be without assets.
We can create a custom task easily. Create your .cap
(e.g. make.cap
) file in lib/capistrano/tasks
to have it automatically loaded (otherwise you’d have to explicitly require from the Capfile
) with this content:
namespace :make do
desc "Runs make all"
task :all do
on roles :all do
within release_path do
execute :make
end
end
end
before 'deploy:updated', 'make:all'
end
Capistrano will run our task before the deploy:updated
task. Since we used the within release_path do …
bit, this command will be executed in the correct release/
directory that Capistrano is deploying.
Check out Capistrano’s documentation for more. Hot tip: be sure to use the colon before any argument (it has to do with shell escaping).
Adding a new stage
Bedrock comes with three default environments:
- Development (Bedrock only)
- Staging (Bedrock and Capistrano)
- Production (Bedrock and Capistrano)
You can add a new stage if you need to. An example could be a backup
environment that is 100% equal to the production
one. The database could be synced periodically or you could setup MySQL replica functionality. In case of failure you’d update your DNS to point to the different host and nobody will notice anything.
To add a new stage:
- Create a new environment for Bedrock: `config/environment/backup.php` (you can copy an existing one and update what’s needed)
- Create the Capistrano stage configuration: `config/deploy/backup.rb` (again use an existing one as a base)
- Setup the server (web server, database, etc)
- Deploy the project (
bundle exec cap backup deploy:check
andbundle exec cap backup deploy
) - Be sure the `.env` file contains
WP_ENV=production
Migrating an existing project to Bedrock
In this tutorial we created a new project, but Bedrock can be used with existing projects.
If you have an existing WordPress site and want to convert it to Bedrock, you can treat it as if it was a new project:
- Install Bedrock
- Configure WordPress
- Restore your theme
- Install plugins with Composer
If you didn’t modify WordPress core files you’re done. If you modified WordPress core files you’ll have to keep your custom WordPress version under version control (you’ll lose easy-Composer-driven WordPress updates, but still have every other feature).
Gotchas and tips
Some tips:
- Remember that if [something] created [something else], you shouldn’t manage it. This includes for example: files created by plugins, files installed by a package manager, files uploaded by users, etc — don’t add them to git. If you ignore them, there’s also an high chance they should end up in the
linked_files
setting of Capistrano. - Don’t store sensitive information in git.
- Don’t forget to
git push
before deploying: I’ve deployed multiple times the same version before realizing that I forgot to push (on the server Capistrano was pulling the same version over and over again). - Use WP-CLI whenever possible: it’s faster and can be executed by Capistrano. Examples include:
wp plugin activate
bundle exec cap wpcli:run['plugin activate ']
wp core update-db
bundle exec cap wpcli:run['core update-db']
- You can set Capistrano branch (
config/deploy.rb
) toset :branch, ENV['BRANCH'] || :master
: doing so lets you easily deploy a branch by doingBRANCH=my-feature bundle exec cap deploy
(remember to push, see tip #3); if you don’t provide theBRANCH=
environment variable, Capistrano will fall back to deploying master. - Using Slackistrano you can post to a Slack channel after every successful deploy.
Recap
I hope you followed and enjoyed this tutorial. I encourage you to create a new site on your local machine to have something to experiment with.
To recap, these are the advantages that Bedrock brings:
- Self-contained repository
- Easy deploys
- Easy multi-stage support
- More consistency between environments
- Separation between configuration files and everything-else
Congrats on making it through this tutorial. Sorry if it was long and difficult. It’s definitely not for beginners! Hopefully along the way you learned some new tools and leveled up your understanding of all the different moving parts.
The benefits of working like this are well worth it, in my opinion. Now go create something nice!
[^1]: That’s not because you can’t ssh @
(some hosts permit that) but because you can’t install some of the required software — if you’re using a script that runs on the server to build the assets you’re probably fine.
[^2]: Unfortunately at this time it doesn’t exist an official version of WordPress distributed via Composer. Bedrock uses this fork that syncs every 15 minutes.
[^3]: In fact, you can deploy whatever you want with Capistrano: you’re not constrained to web apps, you could deploy iOS apps to a remote server, if that makes sense to you.
[^4]: Later you’ll see cap
commands prefixed by bundle exec
: doing so ensures that the local gem is used instead of a globally installed one (which might not exist). You should do the same for Sass or any other gem.
An Intro to Bedrock for WordPress is a post from CSS-Tricks