This article is a walkthrough on the steps to setup a fairly secure* WordPress site leveraging git to make updates easier. It is the result of a set of best practices that I follow when setting up a new WordPress site.
This is not a guarantee of a “hackproof” WordPress site. It is merely a tutorial based on best practices that I have evolved over time. Following these instructions will provide a more secure, better protected WordPress site but it does not confer any kind of magical or technical immunity.
Experience Prerequisites
This is a medium-level tutorial and assumes some basic knowledge about using git and working with both the command line and SQL directly. I will provide links to resources where I can and am happy to answer questions in the comments if you have them. If you have previous experience installing WordPress it will be easier to use but it should be accessible to new users who already have some technical expertise.
Roadmap
We will be covering the following topics in detail as we walk through this series. In addition, I have committed everything to GitHub at https://github.com/bookwyrm/secure-wordpress-setup so you can review the history or see setup details there if you want.
Part 1
- WordPress Setup with Git
- Cleaning up Themes and Plugins
- Pre-Install Security and Config
Part 2
- WordPress Installation
- Post-Install Plugins and Configuration
- Keeping on Top of Updates
WordPress Setup with Git
I like using Git to manage WordPress because it is much easier to manage updates to WordPress.
Setup Git Repository
First we need a local git repo to work with. This will essentially be the document root of a website assuming that you aren’t running your WordPress site in a subdirectory.
[gist id=”2b8b123f1a7079c250cc” file=”setup-git-repo.sh”]
Add WordPress as Submodule
This is where the major benefit of using git comes in. WordPress is added as a git submodule so that it is much easier to upgrade when newer versions are released.
[gist id=”2b8b123f1a7079c250cc” file=”setup-wordpress-submodule.sh”]
Initial WordPress Config
Now we need copy some bits from the submodule into our document root so that WordPress can work as expected.
[gist id=”2b8b123f1a7079c250cc” file=”initial-wordpress-config.sh”]
In this setup, I like to version my wp-config.php
because I usually run a local dev version of my WordPress instance in addition to the production version. There is more on this topic below in Pre-Install Security and Config.
You will also need to edit index.php
to load the WordPress resources correctly. The best way to see this is via the commit diff for index.php
.
Manage Themes and Plugins in Git
In order to be able to version themes and plugins in our Git repository, we need to copy the wp-content/
directory from the submodule:
[gist id=”2b8b123f1a7079c250cc” file=”manage-themes-and-plugins-in-git.sh”]
Cleaning up Themes and Plugins
It’s always a good idea to delete themes and plugins that you won’t use. To support this, I usually delete the default plugins and all but the most recent theme.
[gist id=”2b8b123f1a7079c250cc” file=”cleaning-up-themes-and-plugins.sh”]
Pre-Install Security and Config
There is some data in wp-config.php
that is common to both installations and having it versioned makes keeping everything in sync much easier. However, I do not want my keys, salts, or database credentials in version control. To support this setup I create a separate environment.php
file which contains the bits I don’t want in version control and import that into my wp-config.php
.
environment.php
You can see see the updated wp-config.php
file and a sample environment.php file both in the GitHub repo.
As you can see in the wp-config.php
we also need to setup appropriate URLs and Directories to support referencing resources in the submodule.
Database Prefix
The final step I like to take before the WordPress setup is to change the default database prefix. I like to follow the pattern of wp_XXXXXXXX_
where I still start with wp_
but then add in a random 8 character string generated by Random.org.
I keep this in the wp-config.php
file rather than environment.php
so that it is easier to keep my local dev and production in sync and refresh my local database from production when necessary.
In Conclusion
In my next post, I’ll go over post-installation security and plugins that we can use for keeping everything more secure.