Blog

Get up and running quickly with Amazon SES on your php website


Note: if you want to setup SES in a way that scales much better and functions even with non-PHP sites, please read this more recent HowTo: How to configure your Postfix server to relay email through Amazon Simple Email Service (SES)


Here’s how you can start using Amazon’s new SES (Simple Email Service) without having to actually implement it in the php of your website:

  • Extract the files and create a new one named “aws-credentials” with your key data in it; for example:

AWSAccessKeyId=022QF06E7MXBSH9DHM02
AWSSecretKey=kWcrlUX5JEDGM/LtmEENI/aVmYvHNif5zB+d9+ct

  • Verify an email address to use with SES

./ses-verify-email-address.pl -k ./aws-credentials -v [email protected]

  • Check the email account for the address you’re verifying and click on the provided link.
  • Send a test email:

echo "This is only a test." | ./ses-send-email.pl -k ./aws-credentials -s "test subject for email" -f [email protected] [email protected]
(Note – Until you receive production access to Amazon SES, you can only send to addresses you have verified. You can request production access here.)

  • Edit the sendmail_path config in your php.ini as follows:

sendmail_path = /path/to/ses-send-email.pl -k /path/to/aws-credentials -f [email protected] -r

  • Restart/reload Apache and that’s it!

(Additional notes – The “From” address you set in your php.ini file will override any mail headers you set in php.  Sending will fail if you try to set the “From” header to an unverified address or when setting the “Reply-To” header at all in php.)


	

Update your website directly from your git repository

Here is a php script you can use to update your website from your git repository.  You can pass 2 parameters to it:

  • “r” – revision you want checked out from git (r=head works also)
  • “l” – number of log entries you want to view

For example, if I was running it on this site here is what each URL would do:

You need to make sure that the directory structure is owned by the HTTP daemon user (so that the files can be updated.)  It is best to run it initially from the command line as that user on the server to make sure everything is working properly.

One word of caution; you should restrict access to who can run this script (maybe with HTTP-Auth over HTTPS) because the script isn’t perfect and you don’t want to let anyone make changes to your site.  There are also certain security risks that are increased when you have your website files owned by the webserver user.  It is recommended that you only use this script in a protected environment.

/gitpull.php – show current status and last 3 log entries (make no changes)

MySQL Replication to EC2

Servers die.  People make mistakes. Solar flares, um, flare.  There are many things that can cause you to lose your your data.  Fortunately, there is a pretty easy way to protect yourself from data loss if you use MySQL.

My preferred solution is to store a copy on EC2 through replication.  One big reason I like to replicate to EC2 is that it becomes a pretty easy warm-failover site.  All of your database data will be there, to switch over you’ll just need to start up webservers or other systems required by your architecture and make a DNS change.  If your datacenter became a smoking hole in the ground, you could be back up and running on EC2 in 15 minutes or less with proper planning.

No matter where your MySQL master server is hosted, you can replicate to an EC2 instance over the internet.  Latency generally isn’t an issue when compared to the lag that may be introduced by the replication process itself.  I typically see a max of 5-10 second replication lag during general use.  That lag is due to the replication process being single-threaded (only one modification is made to the database at a time.)

Here are a few things to keep in mind when setting up replication:

  • Use a separate EBS volume partition for your mysql data directory
  • There is good replication documentation for MySQL
  • Use SSL
  • Set expire_logs_days to an acceptable value on the slave and server.  The value of this setting will vary depending on the volume of data you send to the slave each day.  Don’t make it so small that recovery with the binlogs will be difficult or impossible.
  • Store your binlogs on the same partition as the mysql data directory.  This simplifies the snapshot and recovery process.

Here’s a sample EBS snapshot perl script for MySQL that can be modified and used to create snapshots of the mysql data on the slave server:

Since this is a mysql slave server, you can create volume snapshots whenever you want without any impact on your master database. By default, AWS imposes a 500 volume snapshot limit.  If you have that many snapshots, you’ll have to delete some before you will be able to create more.

With the periodic snapshots and binlogs, you can recover to any point in time.  I’ve been able to recover from a “bad” query that unintentionally modified all rows in a table as well as accidentally dropped tables.

Can you replicate from multiple database servers to a single server?  Yes, but a rule of replication is that a slave can only have one master.  To make it possible for one server to be a slave to multiple master servers you need to run multiple mysql daemons.  Each daemon runs with its own configuration and separate data directory.  I’ve used this method to run 20 mysql slaves on a single host and I’m sure you could run many more than that.

Millcreek Systems is available to help you setup and maintain MySQL replication for you.  Please contact us if you’d like to discuss our services further.

Tips for programming a website from scratch

I’ve seen the backend of quite a few websites written from scratch and quite a few of the challenges that arise as a result.  I’m going to share a few suggestions I have for you due to some of the issues that I’ve seen come up.

  • Use a config file – A central location for any configuration options is essential.  I’ve seen some sites created where the database connection was defined at the beginning of each php file.  It was quite an ordeal to make all of the code changes necessary when they needed to move their database to its own server instead of ‘localhost’  Also, you can include options in there for specific environments (i.e. dev, qa, production)
  • Don’t ever trust any data sent to your server from web browsers – It doesn’t matter if you validated it with javascript, if you don’t validate your data on the server side and sanitize it before storing it, someone will figure out how to break it.  Those ‘someones’ usually don’t have the best of intentions. (see http://xkcd.com/327/ for a humorous example)
  • Don’t store plaintext passwords in your database – This goes for any sensitive information.  Passwords can be stored and validated with a one-way hash.  Other sensitive data should be encrypted prior to storage in the database.
  • Don’t store user uploaded files on the webserver – For example, if you allow your users to upload photos.  If you store those photos on the webserver, what will happen when you scale and add another webserver, or you add 10 webservers?  You’ll have to some how synchronize the files across all of the webservers which is time consuming and error prone.  An easier solution is to use a service like Amazon’s S3 to store and serve up files.  One additional bonus of using an external service is you don’t have to worry about users filling up the disks on your webservers.
  • Isolate your static content – As usage of your site increases, you’ll be looking for ways to make it faster for your user.  One of the best things to do is move your static content to a CDN.  You don’t need to use a CDN from the beginning, but you can set your site up to make it an easy transition when the time comes.  You can initially just use a vhost on your webserver as a pseudo CDN.
  • Be very nice to your database – I can’t emphasize this one enough.  As you grow, your database will be the most difficult thing to scale.  Do your JOINs in your code, don’t make the DB do them.  Make sure you’re using indexes properly.  Avoid table scans like the plague and eliminate any slow queries that come up during development.
  • Plan to scale – I’ve said this before.  Have a long term scaling plan drawn out but only execute on it as needed.  You don’t want to waste time and resources solving issues that may not exist down the road for you anyway.  Without a long-term plan, you can easily paint yourself into a non-scalable corner which will result in poor performance and downtime as you fix things.

Most of these things are already addressed if you use a framework.  The ones that aren’t can usually be easily taken care of.

Another advantage of using a framework is that it will force your developers to write code a certain way (which hopefully adheres to the framework’s standard)  This will allow you to enlist the help of other developers in the future without requiring them to spend time sifting through what otherwise could be messy code.  Code written from the ground up by a single developer is more difficult to learn.  And don’t forget, there will be a certain level of support with a framework.  If a vulnerability is found in a framework, it will usually get fixed quickly and released so you can use the update.

Be sure to have more than one person review your code and your plan for scaling.  If you need help, contact us and we can do both for you.