With the VPS expansion you can now get a (very) small virtual private server (VPS) for a very affordable price. However, when you get a server with something like 256MB or 512MB RAM and a portion of CPU power, using default MySQL/PHP/Apache settings is a pretty bad idea.

Performance and scalability tuning of a server is more of an art than science, in the sense that there’re no ready-to-use formulas. Optimal server settings depend on many unique factors: web-app code, traffic to the site, site’s information architecture among other things. It’s virtually impossible to really optimize server settings without thorough understanding of the web application and a lot of testing.

That said, you are not going to run newsweek.com or huffingtonpost.com on a 256MB slice. Also, the default settings are typically so off that it is possible to give you a much better starting point. I’d like to share with you some settings that have worked well for me. I am assuming you are running a small site or a blog, with the traffic of several thousand page-views/day, using Wordpress, Drupal or something of that kind. I highly recommend getting at least a 512MB VPS, but these settings are better than the default for a 256MB server, as well.

Following are some variables for various settings files that have been modified from their default values.

/etc/my.cnf:\

thread_cache_size=4

# Skip bdb if your install has it.
# skip-bdb
skip-locking

query_cache_type=1
query_cache_size=64M
query_cache_limit=8M

# Reduce max_connections to 16 for a 256M server
max_connections=32
key_buffer_size=4M

# Reduce the following two settings to 32M for a 256M server
tmp_table_size=48M
max_heap_table_size=48M

join_buffer_size=4M
max_allowed_packet=8M

innodb_additional_mem_pool_size=8M
innodb_buffer_pool_size=16M
innodb_flush_log_at_trx_commit    = 1

# Server/Storage Engine Settings
default-storage-engine=INNODB

# for MySQL 5.0:
default-character-set= utf8
# for MySQL 5.1, use the following instead:
# skip-character-set-client-handshake
# collation_server = utf8_unicode_ci
# character_set_server = utf8

/etc/php.ini:\

; Drupal is memory-hungry, you will need at least 64M or 92M for Drupal,
; but 40M should be fine for barebones Wordpress
memory_limit = 48M
realpath_cache_ttl=300
realpath_cache_size=1M

/etc/php.d/apc.ini\

extension=apc.so

apc.enabled=1
apc.shm_segments=1
; Reduce shm_size to 32 for 256M server
apc.shm_size=48
apc.ttl=7200
apc.user_ttl=7200
apc.num_files_hint=1024
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.enable_cli=1

/etc/httpd/conf/httpd.conf\

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 3

# Replace /var/www with whatever directory you keep your virtualhost folders under.

AllowOverride all
Options all
Order allow,deny
Allow from all
Deny from none

# Insert filter
  SetOutputFilter DEFLATE

  # Netscape 4.x has some problems...
  BrowserMatch ^Mozilla/4 gzip-only-text/html

  # Netscape 4.06-4.08 have some more problems
  BrowserMatch ^Mozilla/4\.0[678] no-gzip

  # MSIE masquerades as Netscape, but it is fine
  # BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

  # NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48
  # the above regex won't work. You can use the following
  # workaround to get the desired effect:
  BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

  # Don't compress images, videos and audio
  SetEnvIfNoCase Request_URI \
  \.(?:gif|jpe?g|png|flv|mp4|m4v|mp3|zip|gz)$ no-gzip dont-vary

  # Make sure proxies don't deliver the wrong content
  Header append Vary User-Agent env=!dont-vary

Disabling Swap

Another thing that can adversely affect performance is if a server decides to start using swap partition for memory. On Linux, swap space is there to prevent running out of memory. However, Linux is somewhat frivolous in swapping, in that it may use swap even in the cases when it would not have ran out of memory. When linux uses swap for MySQL or Apache/PHP performance degrades significantly.

If you want to be absolutely sure that swapping never happens you can disable swap. This is dangerous because if you don’t properly project your maximum memory allocation you may run out of space and server will crash. But sometimes the risk is worth the benefit of running the server at top speed. To disable swap: edit the /etc/fstab file and find a record that looks like:

/dev/sda2               swap                    swap    defaults        0 0

The first column shows the partition used for swap: /dev/sda2. It may be different in your case. To disable swap put a comment character (“#” pound character) in front of that line and run the following command as root:

swapoff /dev/sda2

where the argument of “swapoff” should be the partition which swap was mounted on.

Static Cache

Another thing that could be a great idea for a blog on a small server is to put it behind a static-HTTP-cache like Varnish. That can really boost your scalability. Configuring Varnish is a complex and large topic that requires its own blog post, however.