tl;dr Instructions for Drupal7 on rpm-based Systems

I threw a few sites up for folks in need the other day, one of them being myself (lots of folks’ businesses were wrecked during the tsunami two months ago). From doing that I realized the Drupal 7 documentation on rpm-based systems is a bit lacking (especially in Japanese). There are a few reasons for this. For one thing, Drupal 6 is still what’s in the Fedora repositories (at least as of F15 — and its orphaned?!?). So the Fedora wiki has basic install instructions for 6, but not 7. The Fedora-ized version also places things in a symlinked area under /usr, which may be more secure, but it confuses new Drupal users about “how to get rid of the” problem under Apache. And… lastly, SELinux requires a few adjustments to let httpd and drupal to work well together. Most users’ reaction to the first sign of SELinux issues is to hurriedly turn it off… emphasis on the hurr in “hurriedly” there, because that is stupid.

Even a lot of professional web developers do this, which should drive home the point I’ve made elsewhere of web people != systems people (though systems people might be capable web developers). As of this writing Ubuntu doesn’t even field SELinux by default and their millions of users don’t get chewed up as easily as Windows folks do, but the majority use case for Ubuntu is not (and should not, imo) be server deployment. But why risk it when you have such a powerful security tool right in front of you? For the enterprise I just don’t find it prudent to abandon such a great and easy tool. That’s like choosing to not learn iptables — which some folks have also opted out of as well.

So, without further ado, here is the quick and dirty to get Drupal 7 working on a Fedora/CentOS/RHEL type OS with SELinux intact:

[Please note these instructions assume three things: 1) a completely fresh minimal install, 2) you have control of the server, and 3) you are able to execute commands as root or through sudo. Also note that I have removed foreign language setup from this, as I doubt anyone who reads my blog really needs Japanese but me.]

[root@localhost]# yum install postgresql postgresql-server php-pgsql php-xml \
    php-pear php-devel gcc zlib-devel libcurl-devel make wget httpd php-mbstring
[root@localhost ~]# cd /var/www/html
[root@localhost html]# wget
[root@localhost html]# tar -zxf ./drupal-7.0.tar.gz
[root@localhost html]# mv drupal-7.0 drupal7
[root@localhost html]# cd drupal7
[root@localhost drupal7]# pecl install pecl_http
[root@localhost drupal7]# pecl install uploadprogress
[root@localhost drupal7]# echo > /etc/php.d/php_http.ini
[root@localhost drupal7]# echo  >> /etc/php.d/php_http.ini
[root@localhost drupal7]# service postgresql initdb
[root@localhost drupal7]# service postgresql start
[root@localhost drupal7]# chkconfig postgresql on
[root@localhost drupal7]# chkconfig httpd on
[root@localhost drupal7]# setsebool -P httpd_can_network_connect_db=1
[root@localhost drupal7]# setsebool -P httpd_can_sendmail=1
[root@localhost drupal7]# setsebool -P httpd_unified=1
[root@localhost drupal7]# cp sites/default/default.settings.php sites/default/settings.php
[root@localhost drupal7]# chmod 666 sites/default/settings.php
[root@localhost drupal7]# su postgres
bash-4.1$ createuser --pwprompt --encrypted --no-adduser --no-createdb drupal
Enter password for new role:
Enter it again:
Shall the new role be allowed to create more new roles? (y/n) n
bash-4.1$ createdb --encoding=UNICODE --owner=drupal drupaldb
bash-4.1$ exit
[root@localhost drupal7]# cp /var/lib/pgsql/data/pg_hba.conf /var/lib/pgsql/data/pg_hba.conf.original
[root@localhost drupal7]# vi /var/lib/pgsql/data/pg_hba.conf

Add the following line at about line 71 or so, just after the local all all ident line (check first, don’t blindly dump this in with sed because this could all be wrong if you’re running a different version of Postgres or reading this far in the future):

host    drupaldb    drupal    md5

Remove the Apache and OS identification tags on server-generated error messages (such as the default Apache ### error messages):

[root@localhost drupal7]# vi /etc/httpd/conf/httpd.conf

Replace “ServerTokens OS” with “ServerTokens Prod
Replace “ServerSignature On” with “ServerSignature Off

And since I’m paranoid and use my servers only as servers (and prefer to send logs to a separate logging server), I also change “LogLevel Warn” to “LogLevel Info” and let my parsing scripts do the work of finding the important stuff. That makes forensics a lot easier later on down the road (though more compute intensive).

Add the following lines to your httpd.conf file if you are running multiple websites on a single server (on a single IP address that is hosting multiple domain names):

NameVirtualHost *:80

<VirtualHost *:80>
    DocumentRoot /var/www/html/drupal7
    ErrorLog logs/

<VirtualHost *:80>
    DocumentRoot /var/www/html/

If you are not running virtual servers, or if you are running them in /home/user/public_html or whatever, adjust the way the file is written.

Now input iptable rules necessary to open port 80 for web traffic from outside, and allow httpd to access Postgres:

[root@localhost drupal7]# iptables -vI INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
[root@localhost drupal7]# iptables -vI INPUT -m state --state NEW -m udp -p udp --dport 5353 -j ACCEPT

Now point a browser at the server and do your Drupal installation setup. Once you’re done there reset the permissions on sites/default/settings.php and remove the last iptables rule:

[root@localhost drupal7]# chmod 644 sites/default/settings.php
[root@localhost drupal7]# iptables -vD INPUT -m state --state NEW -m udp -p udp --dport 5353 -j ACCEPT

If everything went correctly you should be able to use Drupal 7 with SELinux in Enforcing mode, with your iptables intact aside from however you remote login for administration (SSH, if you use it, if you don’t, then close off port 22 and do chkconfig sshd off as well).

The next time you reboot you will notice you can still log in to your shell, but you can’t access the website with a browser. That is because the iptables rule fell off (they don’t persist unless you tell them do). Once everything works the way it should, commit the iptable rule that is letting port 80 stay open:

iptables-save > /etc/sysconfig/iptables

And while we’re messing with security… let’s go ahead and turn off a php feature that the cracker wannabes have recently learned about: allow_url_fopen.

[root@localhost drupal7]# vi /etc/php.ini

Replace “allow_url_fopen On” with “allow_url_fopen Off

It is very unlikely that you will need all_url_fopen to be active, as very few modules use it (there is a Drupal-sepecific alternative to this, so it seems). Of course, if your site breaks it would be good to check if you actually did need this, but otherwise I’d leave it turned off until things go wrong.

Now we need to restart Apache:

[root@localhost drupal7]# apachectl restart

Given that the biggest fans of tutorials such as these are the sort of folks who would never spend the time to research the meaning of all this themselves and given that you wouldn’t be reading this if you already knew how to do the above in the first place, I must remind you to head to your favorite search engine and do searches for things like “hardening sshd”, “hardening httpd”, “turning off root login”, “using public key encryption with sshd” and anything else that might strike your fancy (protip: read as much as you can about SELinux and iptables).

3 thoughts on “tl;dr Instructions for Drupal7 on rpm-based Systems

  1. There is a weird issue some folks have had with the owner and group of the drupal files being 6226 (or whoever user # 6226 happens to be on a system with that many users). To correct this:

    # chown -R siteadmin:apache /var/www/drupal-installation-directory
    # chmod -R 640 /var/www/drupal-installation-directory
    # find /var/www/drupal-installation-directory -type d -exec chmod u=rwx,g=rx,o= {} \;

    There is a more complete discussion on the Drupal website that goes over the security implications of file ownership within the site. Be aware that the script and commands on that page assume an Ubuntu installation and need to be modified in places to accomodate Fedora-based systems.

  2. What’s about now (June 2011) that Drupal 7.2 seems to be officially available on Fedora 15 repository ?
    I installed it via Yum but all drupal7 files/folders are now under /usr/share.
    I’m not sure how to go on: have I to move drupal7 whole folder’s tree from /usr/share/ to /var/www/html/ as it’s usual to have it there ?
    Then, can I still follow your instructions ?
    Kind regards, Davide.

  3. Fedora places all architecture-independent code under /usr/share to comply with the FHS guidelines. When the guidelines were written Apache data and code being so enmeshed that entire software systems would be embedded in user-invisible .php files was unthought of, so compliance with FHS for these sort of systems is a point of debate today.

    Fedora reconciles this by using symlinks from /var/www/html to the /usr/share/drupal folders. For example, if Drupal needs access to the themes folder (which it does) then you would need a symlink from /var/www/html/drupal7-folder/themes that points to /usr/share/drupal/themes .

    You will need to make sure that your /etc/httpd/conf/httpd.conf file has a line that points it to /var/www/html/drupal7-folder (whether that is /var/www/drupal7 or somewhere else completely) by including a vHost clause, like I did above, or by making that folder the DocumentRoot for Apache. (Notice that /etc/httpd contains symlinks to log files under /var/log on Fedora systems. That is also an FHS compliance issue. I recommend that you don’t change this setup, particularly if you have placed /var on its own partition.)

    Sounds tricky? It can be if you are new to this type of thinking. If you want to be 100% Fedora-ish then do things the symlink way. You will definitely learn a few things about symlinks and httpd.conf — which will benefit you in the long run. If you do things the Fedora way you can also benefit from repository updates (which is a debatable benefit, considering how dangerous the www is — receiving slightly out-of-date updates from a repository unstead of 100% up-to-date manual updates can mean the difference between being subjected to thousands of automated attacks and not).

    If this sounds like too much trouble, just “yum uninstall drupal” and then follow the instructions above from scratch (make sure you do the uninstall, otherwise you will be moving packages around that yum is trying to keep track of without telling it, which is a Bad Thing). You will have to do your Drupal updates manually, but it isn’t very difficult and you can be certain you are getting current updates, not week-late repository ones. This is the way I run Drupal, phpBB, Wikimedia and WordPress, just for simplicity’s sake, accepting that I have to keep up with the security mailing lists for each of these — which is very little trouble.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.