February 13, 2014

Set up Apache (2.4) with php-fpm on Ubuntu 13.10

Recently I was trying to help a friend get Apache working with php-fpm on Ubuntu 13.10, I’m generally more of a CentOS guy and have recently switched to nginx from apache, so this was slightly unfamiliar territory for me.  The fact that the default php-fpm install on ubuntu uses sockets but mod_proxy_fcgi doesn’t support sockets yet,  combined with some differences between apache 2.2 and apache 2.4 made this a little tricky, so I figured that I would lay it out for anyone else looking for answers.

Step 1 – Install apache, php and enable mod_proxy_fcgi

$ sudo apt-get install apt-get install apache2 php5-fpm php5
$ sudo a2enmod proxy_fcgi

 Step 2 – Edit your php-fpm config to use a localhost port rather than a socket

In your favourite text editor (vim) open up /etc/php5/fpm/pool.d/www.conf

and change

listen = /var/run/php5-fpm.sock

to

 listen = 127.0.0.1:9000

and then restart php5-fpm

$ sudo service restart php5-fpm

 

Step 3 – Setup your apache virtual host file

Lets start with the default config, then edit it to match our needs. Navigate to the apache sites-available directory and copy the default config to your new config, we’ll call it yoursite.com.conf

$ sudo cd /etc/apache2/sites-available
$ sudo cp 000-default.conf yoursite.com.conf

You need to set the ServerName, DocumentRoot and add the ProxyPassMatch line along with the Directory stanza, making sure that your DocumentRoot is used for the values in ProxyPassMatch and the Directory stanza.  I like to set the document root to a folder named after the site of the virtual host inside /var/www so for yoursite.com it should look something like this

<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        ServerName yoursite.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/yoursite.com

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf

        ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/yoursite.com/$1

        <Directory "/var/www/yoursite.com">
                Order allow,deny
                Allow from all
                AllowOverride FileInfo All
                # New directive needed in Apache 2.4.3:
                Require all granted
        </Directory>

</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

 

Step 4 – Setup a test page

I generally like to test new php setups with a simple phpinfo script, ensure the DocumentRoot directory you previously defined exists and create it if it doesn’t, then add a phpinfo index.php file

$ sudo mkdir -p /var/www/yoursite.com
$ sudo echo "<?php phpinfo(); ?>" > /var/www/yoursite.com/index.php

 

Step 5 – Restart apache and test it out

$ sudo service apache2 restart

Point your web browser to the site and you should now see a php information page!

Caveats

It appears that the proxypass doesn’t work well with apache aliases, like the ones that you get from wordpress and phpmyadmin if you install them with apt. However, if you install them “normally” by putting them in a directory on your vhost, or in the root of your vhost itself they should work assuming you have all the other required php extensions installed.

EDIT: To use Aliased sites with php-fpm you just need more proxypass rules for them, and also leave the Alias line in the config for the site (ie wordpress/phpmyadmin)

This setup works for phpmyadmin installed with apt-get install phpmyadmin. Make sure they come BEFORE the default ProxyPassMatch line in the vhost config file.  You can also move all of the proxypass lines to something like /etc/apache2/conf-available/php-fpm.conf then do “a2enconf php-fpm” to enable it.

ProxyPassMatch ^/phpmyadmin/(.*\.php)$ fcgi://127.0.0.1:9000/usr/share/phpmyadmin/$1
ProxyPassMatch ^/phpmyadmin(.*/)$ fcgi://127.0.0.1:9000/usr/share/phpmyadmin$1index.php

This is also a very simple setup, you can refer to other articles for information on how to best optimize php-fpm pools and apache performance, but this should get you a bare minimum working config suitable for a development environment or small blog.

July 26, 2013

Git + mercurial (hg) restricted shared ssh server.

I had a problem at work, where we needed to restrict vcs user’s access to only allow git and mercurial commands. There was a server that had been designated as the central repository server that everyone wash pushing to and pulling from, but as we added more users it became apparent that we should lock things down a bit to prevent repo tampering since everyone had shell access to the server and write permissions to their repos.

There are several existing solutions for this for git and mercurial individually but nothing that encompassed both of them.  I found a great idea here Code Your Own Multi-User Private Git Server in 5 Minutes and extended it to include hg commands, then locked down the hg commands using the same logic as hg-ssh. I removed the read/write logic since hg handles commands differently than git, and I can control that with file permissions for the users and repos to a certain degree.

You need to setup command restricted authorized_keys files for each user, then point the command to this script.

#!/usr/bin/env ruby
# Example authorized_keys
#
# command="/usr/local/bin/vcs-srv jconway",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAA...examplekey...zzz jconway@jordanconway.com
#
# user is passed from authorized_keys

user = ARGV[0]
command = ENV['SSH_ORIGINAL_COMMAND']
abort "No login, just git and hg commands" unless user and command

# check the supplied command contains a valid git action 

valid_actions = ['git-receive-pack', 'git-upload-pack', 'hg']
action = command.split[0]
abort "git and hg commands only" unless valid_actions.include? action

# user made a valid request so handing over to git-shell unless it's a mercurial request

Kernel.exec 'git', 'shell', '-c', command if action != 'hg'

# Make sure the hg command is safe

abort "quit trying to do fancy hg stuff" unless command.split[0] == 'hg' and command.split[1] == '-R' and command.split[3] == 'serve' and command.split[4] == '--stdio' 

# If we made it this far, execute the command as is for mercurial
Kernel.exec command

Here is an example of the authorized_keys file

command="/usr/local/bin/vcs-srv jconway",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAA...examplekey...zzz jconway@jordanconway.com

I then used puppet to manage authorized_keys files for each user.

February 27, 2013

Node.js Centos 6.3 RPM Spec

I’m trying my best to keep a spec file for node.js updated on github whenever there’s a new stable release since there’s no ‘simple’ way to install it in CentOS.

I haven’t used node.js much at all, but it’s very interesting from what I’ve seen and some of my favourite developers are singing it’s praises.  If you’re interested in it, take a look at the spec file on my very meager github page – I didn’t write it, but when I found it it was several versions behind so I updated it and have taken it upon myself to keep it up to date with each stable release. As of this posting it’s at version 0.8.21

https://github.com/jordanconway/node-rpm-spec

This is also my first post in around 3 years, in that time I’ve gone from an inside sales representative at an industrial supply company with a passion for technology to a System Administrator working in the clinical research field specializing in Linux and virtualization – yay me!