This is an old revision of the document!
Table of Contents
First, create the Universe...
In this guide, I'm just gonna do everything as root unless otherwise specified.
Install Debian 7, following the Naptastic Initial guide. During the install process:
- De-select Graphical Desktop Environment and Laptop.
- Select Web Server, SQL Database, and SSH server.
Apache
Apache is already installed by virtue of your having selected “Web Server” in the installer.
Change to a Threaded Multi-Process Module (MPM)
Change Apache to the Event MPM and install the development libraries
apt-get install apache2-mpm-event apache2-threaded-dev
FastCGI
Download, build, and install libapache-mod-fastcgi. (At some point I need to put an explanation here of why we're using this module instead of one of the bazillions of other available FastCGI implementations.)
git clone https://github.com/ByteInternet/libapache-mod-fastcgi.git libapache-mod-fastcgi
cd libapache-mod-fastcgi/
make -f Makefile.AP2 top_dir=/usr/share/apache2
cp .libs/mod_fastcgi.so /usr/lib/apache2/modules/
Create /etc/apache2/mods-available/fastcgi.load
and add this:
LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so
Now create /etc/apache2/mods-available/fastcgi.conf
:
<IfModule mod_fastcgi.c> AddHandler fastcgi-script .fcgi FastCgiIpcDir /var/lib/apache2/fastcgi # Add a pair of these for every user who will run PHP processes. FastCGIExternalServer /dev/shm/david-php.fcgi -socket /var/run/david.sock FastCGIExternalServer /dev/shm/david-php53.fcgi -socket /var/run/php53-david.sock </IfModule>
Replace 'david' with the name of the user who will be running PHP processes. This is very, very important for server security.
Now create the IPC (Inter-Process Communication) directory that the configuration file references, and give it proper ownership:
mkdir -p /var/lib/apache2/fastcgi
chown www-data. /var/lib/apache2/fastcgi
Enable mod_fastcgi, mod_actions (which mod_fastcgi requires) and mod_expires (which you should always enable anyway.)
a2enmod fastcgi actions expires rewrite
service apache2 restart
Tune Apache
Find this section in /etc/apache2/apache2.conf:
<IfModule mpm_event_module> StartServers 2 MinSpareThreads 25 MaxSpareThreads 75 ThreadLimit 64 ThreadsPerChild 25 MaxClients 150 MaxRequestsPerChild 0 </IfModule>
Change it to look like this:
<IfModule mpm_event_module> StartServers 16 ServerLimit 16 MaxClients 1024 MinSpareThreads 32 MaxSpareThreads 96 ThreadLimit 64 ThreadsPerChild 64 MaxRequestsPerChild 0 </IfModule>
What we're doing here is tuning Apache to handle the largest possible number of simultaneous connections while consuming the least resources and producing the fewest errors.
ThreadLimit
and ThreadsPerChild
are set to 64. This is a good value, and also convenient because on the Apache scoreboard, each line is 64 clients wide, so it makes it easier to read.
MaxClients
needs to be equal to ThreadsPerChild
* ServerLimit
.
MinSpareThreads
and MaxSpareThreads
should not be multiples of ThreadLimit. That will lead to need to constant spawning and reaping of server processes, adding latency and wasting CPU time. If a server is very busy, or traffic is very spiky, these are the values you want to increase first.
Timeout
Then find the Timeout
variable and change it to 15 instead of 300. This is how long Apache will wait for a new connection to send a request before giving up on it. Having it so long allows attackers to just saturate the server with new connections. Lowering it makes that kind of attack more difficult. (20 times more difficult, to be precise.) You could probably lower this to 10 or 5 seconds, but… let's not get too crazy, eh?
KeepAlive
Make sure KeepAlive is turned on.
MySQL
apt-get -y install mysql-server mysql-client
As part of this, you will create a MySQL root password. This doesn't have to be the same as the system root password.
Create /root/.my.cnf
If you ever want to do anything from the command line you will either need this file, or a wig before you're done. The format is as follows:
[client] user="root" password="password"
You can create a .my.cnf file in any user's home directory so they can do mysql stuff from the shell without having to constantly supply their MySQL username and password. It should go without saying, but I'll say it anyway: don't give user accounts access to the MySQL root password.
PHP
You'll need these:
apt-get -y install libxml2-dev zlib1g-dev libbz2-dev libcurl4-openssl-dev libjpeg8-dev libpng12-dev libmcrypt-dev libaspell-dev libpspell-dev libtidy-dev libxslt1-dev
Download and build PHP to include everything we'll need:
cd
wget -O php-5.4.28.tar.bz2 http://www.php.net/get/php-5.4.28.tar.bz2/from/this/mirror
tar -xvf php-5.4.28.tar.bz2
cd php-5.4.28/
./configure –enable-fpm –prefix=/usr/local –enable-bcmath –enable-calendar –enable-ftp –enable-libxml –enable-mbstring –with-gd –with-jpeg-dir=/usr –with-png-dir=/usr –enable-gd-native-ttf –with-mcrypt –with-mysql –enable-pdo –enable-soap –enable-sockets –enable-wddx –enable-zip –with-bz2 –with-kerberos –with-pcre-regex –with-pdo-mysql=shared –with-pic –with-pspell –with-tidy –with-xmlrpc –with-xsl –with-zlib –with-curl
make
make install
Install php.ini
:
cp php.ini-production /usr/local/lib/php.ini
Install the initscript:
cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chown root. !$
chmod 755 !$
update-rc.d php-fpm defaults
Install the FPM-specific configuration files.
mkdir -p /usr/local/etc/pools.d/
Edit the file /usr/local/etc/php-fpm.conf
and put this in it:
include=/usr/local/etc/pools.d/*.conf [global] pid = /usr/local/var/run/php-fpm.pid error_log = /var/log/php-fpm.log
In /usr/local/etc/pools.d/
, you need to create a pool definition file for every user who will be using PHP scripts. I name them $username.conf
.
I'm debating whether it makes more sense to create a separate pool per-virtualhost instead of per-user. Whatever. Here's what you put in each pool definition file:
[david] user = david group = david listen = /var/run/david.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 pm = dynamic pm.max_children = 24 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 2 pm.max_requests = 32768 ;pm.status_path = /fpm-status
Of course, change 'david' to whatever username you're using.
PHP-APC
wget http://pecl.php.net/get/APC-3.1.13.tgz
tar -xvf APC-3.1.13.tgz
cd APC-3.1.13
phpize
./configure –enable-apc
make
make install
Add this to the end of /usr/local/lib/php.ini
:
extension='apc.so' apc.enable=1 apc.shm_size=256m
At this point, PHP-FPM is ready to start if you want.
service php-fpm start
LAMP stack done.
Time to create some sites. By Debian convention, virtualhost definition files go in /etc/apache2/sites-available. By Naptastic convention, the vhost definition file is named the same as the ServerName directive contained within. If you're running Apache 2.4 (not documented yet; sorry,) add .conf to the end of the filename.
Here's the format for virtualhost files:
<VirtualHost *:80> ServerName blog.naptastic.com ServerAdmin naptastic@gmail.com DocumentRoot /var/www/blog.naptastic.com/ <Directory /> Options -FollowSymLinks -Indexes -MultiViews AllowOverride all </Directory> <Directory /var/www/blog.naptastic.com/> DirectoryIndex index.php Options -Indexes -FollowSymLinks -MultiViews AllowOverride all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log LogLevel warn CustomLog ${APACHE_LOG_DIR}/access-logs/blog.naptastic.com combined <IfModule mod_fastcgi.c> AddType application/x-httpd-php .php Action application/x-httpd-php /php.fcgi Alias /php.fcgi /dev/shm/david-php.fcgi </IfModule> ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/blog.naptastic.com/$1 </VirtualHost>
- This is specific to one site. Needs to be generalized.