I’ve been having problems with theming multiple blogs on WordPress using the default Debian Etch settings. Those problems are gone, as of today. Here’s how I fixed the blog.
The setup I wanted was as follows:
- blog.aeolis.org goes to the main system blog.
- name.blogs.aeolis.org goes to an individual’s blog.
- blogs.aeolis.org by itself gets punted to the main system blog.
One note about the way things are installed on my server: I put all the blog sites in the /srv/www hierarchy, with each unique hostname getting a separate directory. For example, ‘blog.aeolis.org’ would be located in ‘/srv/www/blog.aeolis.org’.
The first thing I did was to create a new site definition for WordPress:
Site Definition
# WordPress blog setup.
#
# Wayfarer
#
# Blog software should be in /srv/www/blog.aeolis.org (or linked from there).
# Address of blogs.aeolis.org gets redirected to blog.aeolis.org.
# URLs of form: .blogs.aeolis.org get separate blogs.
UseCanonicalName Off
ServerName blog.aeolis.org
ServerAlias blogs.aeolis.org *.blogs.aeolis.org
VirtualDocumentRoot /srv/www/%0
Options All
ErrorLog /var/log/apache2/error-blog.aeolis.org.log
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog /var/log/apache2/access-blog.aeolis.org.log vcommon
I made a point of making this the last set of hostnames considered for the virtual hosting system by creating a symlink in /etc/apache2/sites-enabled that was at the very end of the alphabet.
ln -s ../sites-available/wordpress /etc/apache2/sites-enabled/zzz-wordpress
Then I force-reloaded Apache.
/etc/init.d/apache2 force-reload
After that, I ran the setup script, as recommended by the README.Debian file.
sh /usr/share/doc/wordpress/examples/setup-mysql -u wp-aeolis blog.aeolis.org
Here’s where I ran into trouble. Because the setup script simply symlinks the blog’s directory under /srv/www to /usr/share/wordpress, a user can’t generally write to important places like the .htaccess file (for pretty permalinks) or the wp-content directory (for themes and plugins and such). Furthermore, even if I symlinked the contents of /usr/share/wordpress into the user’s directory, the wp-config.php script would still be pointing at /usr/share/wordpress for those resources. Therefore, I needed to change some things around.
I started by hacking the global wp-config.php to point directly to the requested blog’s path under /srv/www.
wp-config.php
<?php
/** WordPress's Debianised default master config file
Please do NOT edit and read about how the configuration works in the README.Debian
**/
require_once('/etc/wordpress/config-'.strtolower($_SERVER['HTTP_HOST']).'.php');
define('ABSPATH', '/srv/www/' . strtolower($_SERVER['HTTP_HOST']) . '/');
require_once(ABSPATH.'wp-settings.php');
?>
See what I did? I changed the ABSPATH to reflect the particular host whose blog is being requested. I figure that since the WordPress installation is already aware of individual host configuration files (/etc/wordpress/config-hostname.php), it won’t be too dangerous to make it aware of individual WordPress directories. I probably should make it default to /usr/share/wordpress/ if the directory doesn’t exist, but that’s for round 2.
With that out of the way, I was free to play with some symlinks. I removed /srv/www/blog.aeolis.org (a link to /usr/share/wordpress), and created an actual directory there. I then changed into that directory and ran the following script.
#!/bin/bash
#
# WordPress directory prep.
#
# Wayfarer
#
# Meant to be run in the directory you want WordPress installed to.
WP_DIR=/usr/share/wordpress
INST_DIR=.
ln -vs ${WP_DIR}/* ${INST_DIR}
# Create user-customizable wp-content directory.
rm -f ${INST_DIR}/wp-content
for d in themes plugins; do
mkdir -p ${INST_DIR}/wp-content/${d}
ln -vs ${WP_DIR}/wp-content/${d}/* ${INST_DIR}/wp-content/${d}
chown www-data:www-data ${INST_DIR}/wp-content/${d}
chmod 0775 ${INST_DIR}/wp-content/${d}
done
ln -vs ${WP_DIR}/wp-content/index.php ${INST_DIR}/wp-content/index.php
chown www-data:www-data ${INST_DIR}/wp-content
chmod 0775 ${INST_DIR}/wp-content
# Create uploads directory.
mkdir -p ${INST_DIR}/wp-content/uploads
chown www-data:www-data ${INST_DIR}/wp-content/uploads
chmod 0775 ${INST_DIR}/wp-content/uploads
# Create user-customizable .htaccess file.
rm -f ${INST_DIR}/.htaccess
cp ${WP_DIR}/.htaccess ${INST_DIR}/.htaccess
chown www-data:www-data ${INST_DIR}/.htaccess
chmod 0664 ${INST_DIR}/.htaccess
Still very alpha in nature, but you get the gist. The script symlinks each item in /usr/share/wordpress to the current directory. The wp-content subdirectory gets special treatment, as the themes and plugins subdirectories absolutely must be user- (and probably group-) writable. And, of course, I fixed up .htaccess so that the admin script can edit it for permalinking.
The result? The admin interface is able to edit files, my plugins work, and I stop losing hair wondering why .htaccess can’t be edited even if it’s world-writable.