UBUNTU 9.10 — NGINX + PHP5 + APC + MEMCACHED + IMAGEMAGICK ..

OK, SO I’VE BEEN DOING SOME RESEARCH ON NGINX, AND HOW TO USE IT WITH PHP AND I’VE COME UP WITH SOMETHING FAST, SIMPLE, AND A METHOD THAT JUST WORKS WITH EXTRAS LIKE APC, MEMCACHED, AND IMAGEMAGICK. YOU CAN ALSO ADD FFMPEG, OR W/E…SINCE YOU HAVE THE PHPIZE FUNCTION.

SO LET’S START OUT FRESH WITH UBUNTU 9.10
GO GO GO!

…UPDATE AND UPGRADE YOUR DISTRO
apt-get update && apt-get upgrade && apt-get install build-essential

LETS BEGIN THE APTGETTING
apt-get install bison flex gcc make patch autoconf subversion locate libxml2-dev libbz2-dev libpcre3-dev libssl-dev zlib1g-dev libmcrypt-dev libmhash-dev libmhash2 libcurl4-openssl-dev libpq-dev libpq5 libsyck0-dev libpng-dev libmysqlclient15-dev libevent-dev libjpeg62-dev memcached imagemagick libmagickwand-dev

IF YOU’RE USING UBUNTU 8.10 AND BELOW, YOU’LL NEED make AND libpng12-dev

OK, SO THAT’S ALL FINISH, LET’S PROCEED WITH THE COMPILING OF PHP5 w/FASTCGI
cd /usr/local/src && wget http://us3.php.net/get/php-5.2.10.tar.gz/from/us.php.net/mirror && wget http://php-fpm.org/downloads/php-5.2.10-fpm-0.5.13.diff.gz && tar -xzf ./php-5.2.10.tar.gz && gzip -cd php-5.2.10-fpm-0.5.13.diff.gz | patch -d php-5.2.10 -p1 && cd php-5.2.10

Alright so we’ve downloaded PHP5.2 and have patched it with PHP-FPM, that was easy right? Now let’s configure:
./configure –with-openssl –enable-fastcgi –enable-fpm –with-zlib –enable-mbstring –with-mysqli –with-mysql –with-pdo_mysql –with-gd –with-jpeg-dir=/usr/lib/libjpeg.so.62 –without-sqllite –enable-gd-native-tff

AND MAKE AND MAKE INSTALL. 
make all install

LET’S MAKE SOME A SYMLINK
cp /usr/local/src/php-5.2.*/php.ini-recommended /usr/local/lib/php.ini

MAKING LIFE EASIER AND CLEAN UP SOME THINGS
mkdir /etc/php/ && ln -s /usr/local/lib/php.ini /etc/php/php.ini && ln -s /usr/local/etc/php-fpm.conf /etc/php/php-fpm.conf && rm -rf /usr/local/lib/php/.channels && /usr/local/bin/pear update-channels && cd /usr/local/src

ADD THOSE EXTENSIONS! AND IF IT ASKS YOU ABOUT APACHE, THEN JUST SAY NO!
/usr/local/bin/pecl install memcache
/usr/local/bin/pecl install apc
/usr/local/bin/pecl install pecl_http
/usr/local/bin/pecl install imagick

SO NOW WE HAVE PHP5.2 INSTALLED, WITH MEMCACHE, APC, HTTP, and IMAGEMAGICK. SO NOW I’M GOING TO GIVE YOU MY PHP.INI I USE FOR MY WEBSITE, YOU CAN CHANGE WHAT YOU WANT OR ADD AS YOU SEE FIT…

THE PHP.INI IS LOCATED -> /etc/php/php.ini
REMEMBER WE CREATED A SYMLINK RIGHT? … RIGHT.

[PHP]
engine = On
short_open_tag = On
asp_tags = Off
precision = 14
y2k_compliance = On
output_buffering = 4096
;output_handler =
zlib.output_compression = Off
;zlib.output_compression_level = -1
;zlib.output_handler =
implicit_flush = Off
unserialize_callback_func=
serialize_precision = 100
allow_call_time_pass_reference = Off

safe_mode = Off
safe_mode_gid = Off
safe_mode_include_dir =
safe_mode_exec_dir =
safe_mode_allowed_env_vars = PHP_
safe_mode_protected_env_vars = LD_LIBRARY_PATH
open_basedir =
output_buffering = On
disable_functions =
disable_classes =
;highlight.string = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #007700
;highlight.bg = #FFFFFF
;highlight.default = #0000BB
;highlight.html = #000000
; ignore_user_abort = On
; realpath_cache_size=16k
; realpath_cache_ttl=120

expose_php = Off

max_execution_time = 0;
max_input_time = 0;
;max_input_nesting_level = 64;
memory_limit = 512M;

error_reporting = E_ALL
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
;report_zend_debug = 0
track_errors = Off
;xmlrpc_errors = 0
;xmlrpc_error_number = 0
;html_errors = Off
;docref_root = “/phpmanual/”
;docref_ext = .html
;error_prepend_string = “<font color=#ff0000>”
;error_append_string = “</font>”
;error_log = filename
;error_log = syslog

;arg_separator.output = “&”
;arg_separator.input = “;&”
variables_order = “GPCS”
;request_order = “GP”
register_globals = Off
register_long_arrays = Off
register_argc_argv = On
auto_globals_jit = On
post_max_size = 200M

magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off
auto_prepend_file =
auto_append_file =
default_mimetype = “text/html”
default_charset = “utf-8”
;always_populate_raw_post_data = On

;include_path = “.:/php/includes”
;include_path = “.;c:\php\includes”
doc_root =
user_dir =
extension_dir = “./”
enable_dl = On
; cgi.force_redirect = 1
; cgi.nph = 1
; cgi.redirect_status_env = ;
; cgi.fix_pathinfo=1
; fastcgi.impersonate = 1;
; fastcgi.logging = 0
;cgi.rfc2616_headers = 0

file_uploads = On
;upload_tmp_dir =
upload_max_filesize = 200M

allow_url_fopen = On
allow_url_include = Off
;from=”john@doe.com”
; user_agent=”PHP”
default_socket_timeout = 60
; auto_detect_line_endings = Off

extension=apc.so
extension=http.so
extention=imagick.so
extension=memcache.so
extension_dir = “/usr/local/lib/php/extensions/no-debug-non-zts-20060613”

[Date]
;date.timezone =

;date.default_latitude = 31.7667
;date.default_longitude = 35.2333

;date.sunrise_zenith = 90.583333
;date.sunset_zenith = 90.583333

[filter]
;filter.default = unsafe_raw
;filter.default_flags =

[iconv]
;iconv.input_encoding = ISO-8859-1
;iconv.internal_encoding = ISO-8859-1
;iconv.output_encoding = ISO-8859-1

[sqlite]
;sqlite.assoc_case = 0

[Pcre]
;pcre.backtrack_limit=100000
;pcre.recursion_limit=100000

[Syslog]
define_syslog_variables = Off

[mail function]
SMTP = localhost
smtp_port = 25
;sendmail_from = me@example.com
sendmail_path = /usr/sbin/sendmail -t -i
;mail.force_extra_parameters =

[SQL]
sql.safe_mode = Off

[ODBC]
;odbc.default_db = Not yet implemented
;odbc.default_user = Not yet implemented
;odbc.default_pw = Not yet implemented
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1

[MySQL]
mysql.allow_persistent = On
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off

[MySQLi]
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off

[mSQL]
msql.allow_persistent = On
msql.max_persistent = -1
msql.max_links = -1

[OCI8]
;oci8.privileged_connect = Off
;oci8.max_persistent = -1
;oci8.persistent_timeout = -1
;oci8.ping_interval = 60
;oci8.statement_cache_size = 20
;oci8.default_prefetch = 10
;oci8.old_oci_close_semantics = Off

[PostgresSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

[Sybase]
sybase.allow_persistent = On
sybase.max_persistent = -1
sybase.max_links = -1
;sybase.interface_file = “/usr/sybase/interfaces”
sybase.min_error_severity = 10
sybase.min_message_severity = 10
sybase.compatability_mode = Off

[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10

[bcmath]
bcmath.scale = 0

[browscap]
;browscap = extra/browscap.ini

[Informix]
ifx.default_host =
ifx.default_user =
ifx.default_password =
ifx.allow_persistent = On
ifx.max_persistent = -1
ifx.max_links = -1
ifx.textasvarchar = 0
ifx.byteasvarchar = 0
ifx.charasvarchar = 0
ifx.blobinfile = 0
ifx.nullformat = 0

[Session]
session.save_handler = files
;session.save_path = “/tmp”
session.use_cookies = 1
;session.cookie_secure =
; session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 144000
session.bug_compat_42 = 0
session.bug_compat_warn = 1
session.referer_check =
session.entropy_length = 0
session.entropy_file =
;session.entropy_length = 16
;session.entropy_file = /dev/urandom
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = “a=href,area=href,frame=src,input=src,form=fakeentry”

[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatability_mode = Off
;mssql.connect_timeout = 5
;mssql.timeout = 60
;mssql.textlimit = 4096
;mssql.textsize = 4096
;mssql.batchsize = 0
;mssql.datetimeconvert = On
mssql.secure_connection = Off
;mssql.max_procs = -1
;mssql.charset = “ISO-8859-1”

[Assertion]
;assert.active = On
;assert.warning = On
;assert.bail = Off
;assert.callback = 0
;assert.quiet_eval = 0

[COM]
;com.typelib_file =
;com.allow_dcom = true
;com.autoregister_typelib = true
;com.autoregister_casesensitive = false
;com.autoregister_verbose = true

[mbstring]
;mbstring.language = Japanese
;mbstring.internal_encoding = EUC-JP
;mbstring.http_input = auto
;mbstring.http_output = SJIS
;mbstring.encoding_translation = Off
;mbstring.detect_order = auto
;mbstring.substitute_character = none;
;mbstring.func_overload = 0

; enable strict encoding detection.
;mbstring.strict_detection = Off

[FrontBase]
;fbsql.allow_persistent = On
;fbsql.autocommit = On
;fbsql.show_timestamp_decimals = Off
;fbsql.default_database =
;fbsql.default_database_password =
;fbsql.default_host =
;fbsql.default_password =
;fbsql.default_user = “_SYSTEM”
;fbsql.generate_warnings = Off
;fbsql.max_connections = 128
;fbsql.max_links = 128
;fbsql.max_persistent = -1
;fbsql.max_results = 128

[gd]
;gd.jpeg_ignore_warning = 0

[exif]
;exif.encode_unicode = ISO-8859-15
;exif.decode_unicode_motorola = UCS-2BE
;exif.decode_unicode_intel = UCS-2LE
;exif.encode_jis =
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel = JIS

[Tidy]
;tidy.default_config = /usr/local/lib/php/default.tcfg
tidy.clean_output = Off

[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir=”/tmp”
soap.wsdl_cache_ttl=86400

NOW WE NEED TO EDIT THE PHP-FPM WHICH IS LOCATED -> /etc/php/php-fpm.conf — USE THIS CONF FILE I CREATED

Code:
<?xml version="1.0" ?>
 <configuration>
 	<section name="global_options">
 		<value name="pid_file">/usr/local/logs/php-fpm.pid</value>
 		<value name="error_log">/usr/local/logs/php-fpm.log</value>
 		<value name="log_level">notice</value>
 		<value name="emergency_restart_threshold">10</value>
 		<value name="emergency_restart_interval">1m</value>
 		<value name="process_control_timeout">5s</value>
 		<value name="daemonize">yes</value>
 	</section>

 	<workers>
 		<section name="pool">
 			<value name="name">default</value>
 			<value name="listen_address">127.0.0.1:9000</value>
 			<value name="listen_options">
 				<value name="backlog">-1</value>
 				<value name="owner"></value>
 				<value name="group"></value>
 				<value name="mode">0666</value>
 			</value>
 			<value name="php_defines">
 				<value name="sendmail_path">/usr/sbin/sendmail -t -i</value>
 				<value name="display_errors">0</value>
 			</value>
 			<value name="user">www-data</value>
 			<value name="group">www-data</value>
 			<value name="pm">
 				<value name="style">static</value>
 				<value name="max_children">5</value>
 				<value name="apache_like">
 					<value name="StartServers">20</value>
 					<value name="MinSpareServers">5</value>
 					<value name="MaxSpareServers">35</value>
 				</value>
 			</value>
 			<value name="request_terminate_timeout">0s</value>
 			<value name="request_slowlog_timeout">0s</value>
 			<value name="slowlog">logs/slow.log</value>
 			<value name="rlimit_files">1024</value>
 			<value name="rlimit_core">0</value>
 			<value name="chroot"></value>
 			<value name="chdir"></value>
 			<value name="catch_workers_output">yes</value>

 			How much requests each process should execute before respawn.
 			Useful to work around memory leaks in 3rd party libraries.
 			For endless request processing please specify 0
 			Equivalent to PHP_FCGI_MAX_REQUESTS
 			<value name="max_requests">500</value>
 			<value name="allowed_clients">127.0.0.1</value>

 			Pass environment variables like LD_LIBRARY_PATH
 			All $VARIABLEs are taken from current environment
 			<value name="environment">
 				<value name="HOSTNAME">$HOSTNAME</value>
 				<value name="PATH">/usr/local/bin:/usr/bin:/bin</value>
 				<value name="TMP">/tmp</value>
 				<value name="TMPDIR">/tmp</value>
 				<value name="TEMP">/tmp</value>
 				<value name="OSTYPE">$OSTYPE</value>
 				<value name="MACHTYPE">$MACHTYPE</value>
 				<value name="MALLOC_CHECK_">2</value>
 			</value>
 		</section>
 	</workers>
 </configuration>

PHEWWW, NOW WE FINALLY GOT OUR PHP ALL SETUP, NOW LETS MOVE ON TO THE WEBSERVER, NGINX 0.7.65
cd /usr/local/src && wget http://nginx.org/download/nginx-0.7.65.tar.gz && tar -xzf nginx-0.7.65.tar.gz && cd nginx-0.7.65

CONFIGURE, AND OF COURSE MAKE AND INSTALL IT! (OF COURSE YOU CAN CHANGE THE CONFIGURATION IF YOU’D LIKE )
./configure –with-http_ssl_module –sbin-path=/usr/local/sbin –without-mail_pop3_module –without-mail_imap_module –without-mail_smtp_module –with-http_stub_status_module && make build install

LET’S ENABLE MEMCACHED, WHICH IS OPTIONAL…
vi /etc/default/memcached
CHANGE no TO yes
SAVE and CLOSE

NOW IN YOUR NGINX CONFIGURATION FILE WHICH IS LOCATED -> /usr/local/nginx/conf/nginx.conf — YOU NEED TO EDIT THAT TO LET NGINX KNOW, “HEY I GOT PHP DUDE, PLEASE RUN PHP FOR ME, THNX” SO USE THIS CONF FILE, AND OF COURSE YOU CAN CHANGE IT HOW YOU WANT, MAKE SURE YOU HAVE THAT.

Code:
 user  www-data;
 worker_processes  4;

 #error_log  logs/error.log;
 #error_log  logs/error.log  notice;
 #error_log  logs/error.log  info;

 #pid        logs/nginx.pid;

 events {
     worker_connections  1024;
 }

 http {
     include       mime.types;
     default_type  application/octet-stream;

     #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
     #                  '$status $body_bytes_sent "$http_referer" '
     #                  '"$http_user_agent" "$http_x_forwarded_for"';
     #access_log  logs/access.log  main;

     sendfile        on;
     #tcp_nopush     on;

     #keepalive_timeout  0;
     keepalive_timeout  65;

     #client_body_timeout 10;
     #client_header_timeout 10;
     client_max_body_size 200M;
     client_body_buffer_size 50M;

     gzip  on;
     gzip_http_version 1.1;
     gzip_vary on;
     gzip_comp_level 1;
     gzip_proxied any;
     gzip_buffers 16 8k;
     gzip_disable .MSIE [1-6].(?!.*SV1).;

     #send_timeout 10;

     server {
         listen       80;
         server_name  localhost;

         charset utf-8;

         #access_log  logs/host.access.log  main;

         location / {
             root   html;
             index  index.html index.htm index.php;
         }

         #error_page  404              /404.html;

         # redirect server error pages to the static page /50x.html
         #
         error_page   500 502 503 504  /50x.html;
         location = /50x.html {
             root   html;
         }

         # proxy the PHP scripts to Apache listening on 127.0.0.1:80
         #
         #location ~ \.php$ {
         #    proxy_pass   <a href="http://127.0.0.1;" target="_blank">http://127.0.0.1;</a>
         #}
  	 location ~ \.php$ {
                 include /usr/local/nginx/conf/fastcgi_params;
                 keepalive_timeout 10;
                 fastcgi_param   SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
                 fastcgi_pass    127.0.0.1:9000;
 		  fastcgi_index   index.php;
         }

         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
         #
         #location ~ \.php$ {
         #    root           html;
         #    fastcgi_pass   127.0.0.1:9000;
         #    fastcgi_index  index.php;
         #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
         #    include        fastcgi_params;
         #}

         # deny access to .htaccess files, if Apache's document root
         # concurs with nginx's one
         #
         #location ~ /\.ht {
         #    deny  all;j
         #}
     }

     # another virtual host using mix of IP-, name-, and port-based configuration
     #
     #server {
     #    listen       8000;
     #    listen       somename:8080;
     #    server_name  somename  alias  another.alias;

     #    location / {
     #        root   html;
     #        index  index.html index.htm;
     #    }
     #}

     # HTTPS server
     #
     #server {
     #    listen       443;
     #    server_name  localhost;

     #    ssl                  on;
     #    ssl_certificate      cert.pem;
     #    ssl_certificate_key  cert.key;

     #    ssl_session_timeout  5m;

     #    ssl_protocols  SSLv2 SSLv3 TLSv1;
     #    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
     #    ssl_prefer_server_ciphers   on;

     #    location / {
     #        root   html;
     #        index  index.html index.htm;
     #    }
     #}

 }

BEFORE WE CAN STARTUP NGINX, WE NEED TO CREATE A STARTUP SCRIPT FOR IT MANUALLY.
vi /etc/init.d/nginx
and ADD THIS

Code:
#! /bin/sh

 ### BEGIN INIT INFO
 # Provides:          nginx
 # Required-Start:    $all
 # Required-Stop:     $all
 # Default-Start:     2 3 4 5
 # Default-Stop:      0 1 6
 # Short-Description: starts the nginx web server
 # Description:       starts nginx using start-stop-daemon
 ### END INIT INFO

 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 DAEMON=/usr/local/sbin/nginx
 NAME=nginx
 DESC=nginx

 test -x $DAEMON || exit 0

 # Include nginx defaults if available
 if [ -f /etc/default/nginx ] ; then
         . /etc/default/nginx
 fi

 set -e

 case "$1" in
   start)
         echo -n "Starting $DESC: "
         start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
                 --exec $DAEMON -- $DAEMON_OPTS
         echo "$NAME."
         ;;
   stop)
         echo -n "Stopping $DESC: "
         start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
                 --exec $DAEMON
         echo "$NAME."
         ;;
   restart|force-reload)
         echo -n "Restarting $DESC: "
         start-stop-daemon --stop --quiet --pidfile \
                 /usr/local/nginx/logs/$NAME.pid --exec $DAEMON
         sleep 1
         start-stop-daemon --start --quiet --pidfile \
                 /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
         echo "$NAME."
         ;;
   reload)
       echo -n "Reloading $DESC configuration: "
       start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
           --exec $DAEMON
       echo "$NAME."
       ;;
   *)
         N=/etc/init.d/$NAME
         echo "Usage: $N {start|stop|restart|force-reload}" >&2
         exit 1
         ;;
 esac

 exit 0

WOOT WOOT, WE HAVE NGINX, PHP5.2, APC, MEMCACHED, IMAGEMAGICK, and LET’S START ALL THIS STUFF UP!
service nginx start
php-fpm start
service memcached start

AND THAT’S IT! EVERYTHING SHOULD WORK WITHOUT QUESTION, LOL. I’VE DONE THIS 34038940 TIMES.. OF COURSE I’M EXAGGERATING ABOUT THE NUMBER, BUT STILL IT JUST WORKS. PHEWW I’M DONE TYPING. ANY QUESTIONS? JUST ASK AWAY!

OH BY THE WAY, THE WEB ROOT IS LOCATED -> /usr/local/nginx/html

MMM I THINK THATS EVERYTHING. KTHXBAI
IF THIS HAS HELPED YOU, LET ME KNOW!

=========== Answer 1 ===========

This is awesome, thank you! I was in the process of writing a cloud server set up guide for our company’s reference, and you just me a load of work.

Dave
Productiontrax.com

=========== Answer 2 ===========

Great Article! I’ll pass it along to our Technical Writer and see if we can get this included into the KB.

That said, one thing I would recommend is to make sure everything is enabled via chkconfig so that it starts itself up in the event that you reboot your server. This will solve a few headaches in troubleshooting in the event that you have an issue that requires a reboot. I know it’s typically done automatically, but it is always a good idea to double check!

=========== Answer 3 ===========

Thanks!

Of course I could have added MySQL along with all of this to make it complete with database support and fine tuned, but I didn’t think it was necessary. :/

I’ll add the MySQL later on and fine tune this.