Always Get Better

Archive for the ‘Wordpress’ Category

Reverse Proxy with IIS and Elastic Beanstalk

Monday, September 4th, 2017

Suppose your main website is a .NET/IIS stack running on AWS Elastic Beanstalk, and you decided to add a WordPress blog to the mix. Instead of having http://blog.yourdomain.com and http://www.yourdomain.com, you want to host the blog from a subdirectory at http://www.yourdomain.com/blog. There are a few ways you can go about this; this post will go through how to set up a reverse proxy to a dedicated blog server.

You have two options:

1. Host WordPress in IIS – Not fun. You need to configure IIS to run PHP, host a MySQL database, and manage your WordPress file directory and updates in an environment where user uploads and core files can get trashed at any minute when EB rolls out a new server. It’s possible to run an amazing HA WordPress install on Elastic Beanstalk (topic for another post) but in a subdirectory directly hosted in Windows/IIS? Not for the feint of heart)

2. Host WordPress on a Linux server somewhere else and reverse proxy – Let’s do this instead.

Basically you set up WordPress and get it to look how you want, configure it to respond to your domain, then configure IIS to fetch your blog URLs and return them whenever a request comes through to the blog subdirectory on your main site. Every other directory is served from your .NET app as normal.

Reverse Proxy a WordPress blog with IIS

Important: The final step to this is the most important bit if you’re running on Elastic Beanstalk. Make sure you follow it in order to actually enable IIS’ proxy module, which does not come pre-installed on Elastic Beanstalk’s AMI.

Configure WordPress to Respond to Your Domain

Add this section to the bottom of wp-config.php, just before the require_once for wp-settings.php. This tells WordPress to ignore its default server settings and use your website as its base path.

$hostname = 'www.yourdomain.com';
$_SERVER['HTTP_HOST'] = $hostname;
define('WP_HOME','https://www.yourdomain.com/blog');
define('WP_SITEURL','https://www.yourdomain.com/blog');
$current_url = 'https://' . $hostname . $_SERVER['REQUEST_URI'];

Configure IIS Paths

The reverse proxy makes use of the rewrite in IIS. To turn this on for your blog, add the following to the directive in your web.config file:

 <rewrite>
   <rules>
     <rule name="Reverse Proxy to blog" stopProcessing="true">
       <match url="^blog/(.*)" />
       <action type="Rewrite" url="https://blog.yourdomain.com/{R:1}" />
     </rule>
   </rules>
 </rewrite>

This tells IIS to redirect all requests beginning with “blog/” to your WordPress blog. IIS will reach out to your blog server as if it is the requestor, fetch the page, and return it as if the blog were hosted from within IIS itself. The {R:1} variable carries forward any path information to the blog — so your theme files, user uploads and static assets will all pass through.

If you deploy your site and try to access your blog page now, it won’t work. You’ll see a ‘404’ response code even though the rules are definitely set up properly. The final step to this is enabling the Application Request Routing module on IIS – this is not enabled by default in Elastic Beanstalk’s version of Windows.

Enabling the Reverse Proxy Module on Elastic Beanstalk

You could Remote Desktop into your web server machine and manually enable the ARR module, but it would stop working the next time your environment flips, the server gets reloaded for any reason (which can happen even if you are doing all at once deployments and not adding/removing machines), or nodes get added to your environment.

We need to make sure the module gets installed and checked every time you deploy your files, so it’s always present and available to use even when new machines come online.

To do that, we’ll use the .ebextensions scripting hooks to download, install and configure ARR every time a deploy runs.

1. Download the ARR Installer

Download the 65-bit ARR installer (from here) to S3 so it is available to your VM when it boots. We want to install to S3 instead of pulling directly off Microsoft’s servers because we can’t rely on outside links being available when we need to deploy, and if our VM happens to be inside a VM without a NAT then we can use Amazon’s S3 internal endpoints without needing to configure any more advanced network.

2. Add an ebextension hook

In your .ebextensions folder (at the root of your unzipped deploy package), add a new config file (install-arr.config) to instruct Elastic Beanstalk how to install the extension:

packages:
  msi:
    ApplicationRequestRouting: "pathtoyourinstallerons3"

commands:
  01_enablearr:
    command: "C:\\Windows\\system32\\inetsrv\\appcmd.exe set config  -section:system.webServer/proxy /enabled:True  /commit:apphost"

The packages/msi lines tell Elastic Beanstalk to download and run the installer. Since you won’t be physically present when that happens, the script will automatically accept all the license agreements and silently run.

The appcmd command instructs IIS to enable the reverse proxy module, which turns your rewrite instructions into actual reverse proxy commands. Now if you visit www.yourdomain.com/blog/, you will see your WordPress blog.

Bonus: Trailing Slashes

If you visit www.yourdomain.com/blog without a trailing slash, you won’t see the blog. You don’t want to start the rewrite rule at this level because your reverse proxy will try to access blog.yourdomain.com// (with a double slash) for all dependent resources, which can cause problems with WordPress’ routing.

For this case, I like to redirect to a trailing slash at the IIS level. Every time someone comes to yourdomain.com/blog, they will redirect with a clean 302 status command to yourdomain.com/blog/. Just add this rule in your section of web.config

<rule name="Add trailing slash to blog reverse proxy" stopProcessing="true">
  <matchurl="^blog$"/>
  <action type="Redirect" redirectType="Permanent" url="{R:1}/"/>
</rule>

The regular expression in the match url tells the web server this should only apply to the “blog” path, that is, nothing before or after the word “blog”. This lets you have “blog” in other parts of your URL without accidentally redirecting valid pages.

Cheap File Replication: Synchronizing Web Assets with fsniper

Sunday, November 14th, 2010

Awhile ago I wrote about how I was using nginx to serve static files rather than letting the more memory-intensive Apache handle the load for files that don’t need its processing capabilities. The basic premise is that nginx is the web-facing daemon and handles static files directly from the file system, while shipping any other request off to Apache on another port.

What if Apache is on a different server entirely? Unless you have the luxury of an NAS device, your options are:

1. Maintain a copy of the site’s assets separate from the web site
There are two problems with this approach: maintainability, and synchronization. You’ll have to remember to deploy any content changes separately to the rest of the site, which is counter-intuitive and opens up your process to human error. User-generated content stays on the Apache server and would be inaccessible to nginx.

2. Use a replicating network file system like GlusterFS
Network-based replication systems are advanced and provide amazing redundancy. Any changes you make to one server can be replicated to the others very quickly, so any user generated content will be available to your content servers, and you only have to deploy your web site once.

The downside is that many NFS solutions are optimized for larger (>50Mb) filesizes. If you rely on your content server for small files (images, css, js), the read performance may decline when your traffic numbers increase. For high availability systems where it is critical for each server to have a full set of up-to-date files, this is probably the best solution.

3. Use an rsync-based solution
This is the method I’ve chosen to look at here. It’s important that my content server is updated as fast as possible, and I would like to know that when I perform disaster recovery or make backups of my web site the files will be reasonably up to date. If a single file takes a few seconds to appear on any of my servers, it isn’t a huge deal (I’m just running WordPress).

The Delivery Mechanism
rsync is fast and installed by default on most servers. Pair it with ssh and use password-less login keys, and you have an easy solution for script-able file replication. The only missing piece is the “trigger” – whenever the filesystem is updated, we need to run our update script in order to replicate to our content server.

Icrond is one possible solution – whenever a directory is updated icrond can run our update script. The problem here is that service does not act upon file updates recursively. fsniper is our solution.

The process flow should look like this.
1. When the content directory is updated (via site upload or user file upload), fsniper initiates our update script.
2. Update script connects to the content server via ssh, and issues an rsync command between our content directory and the server’s content directory.
3. Hourly (or whatever), initiate an rsync command from the content server to any web servers – this will keep all the nodes fairly up-to-date for backup and disaster recovery purposes.

How to Move a WordPress Database

Saturday, April 4th, 2009

One of the most common requirements for web developers is the ability to switch code from development servers to live production environments. This can be tricky if you’re working with WordPress; moving the files is dead simple, but since WordPress uses canonical URLs you have to be careful if you are trying to transfer any of your database content.

Canonical URLs force your site to use the same base path (www.yourdomain.com rather than yourdomain.com). But if you are working in a development environment – e.g. the development site’s address isn’t the same as your web site, but is rather something like 127.0.0.1 – you need to be able to make the switch to WordPress without bringing your site down.

Since I end up having to look for this information so often, here are the steps I use to accomplish this amazing feat:

Download The Database

From the shell prompt of your server, dump WordPress’ MySQL database into a backup file:

mysqldump –-add-drop-table -uusername -ppassword databasename > mysqlbackup.DATE.sql

Move it over to the new server and run this command to overwrite your target:

mysql -udb##### -p -hinternal-db.s#####.gridserver.com db#####_dbname < mysqlbackup.DATE.sql

Update the Database Paths

Log into your MySQL database and issue this update command to ensure WordPress redirects to the new server:

UPDATE wp_options SET option_value = replace(option_value, ‘http://www.old-domain.com’, ‘http://www.new-domain.com’) WHERE option_name = ‘home’ OR option_name = ‘siteurl’;

Next update the post URLs:

UPDATE wp_posts SET guid = replace(guid, ‘http://www.old-domain.com’,’http://www.new-domain.com’);

Finally, update your posts’ content to fix any internal links:

UPDATE wp_posts SET post_content = replace(post_content, ‘http://www.old-domain.com’, ‘http://www.new-domain.com’);

That’s all! Repeat these steps when moving from production to development and vise-versa.

As I said I typically search for this information whenever I need to move WordPress sites. I find the SQL queries at: http://www.mydigitallife.info/2007/10/01/how-to-move-wordpress-blog-to-new-domain-or-location/