Yesterday, I took the plunge, changed my DNS, and am now on Mosso. Dreamhost was getting slow, and having intermittent outages, so I needed the switch. Not to mention Mosso is another division of Rackspace, just like Mailtrust.
I am super happy with Mosso so far. The blog is faster than ever, and I have had almost no problems. What’s even crazier is I am using CDN Tools to host a lot of my static content on the Cloud Files CDN. I could have done this while on Dreamhost, but it was easier since I already have a Mosso account.
Automation
Setting up Mosso is quite different than Dreamhost, since SSH access isn’t permitted. FTP or SFTP is really the only means to get your code uploaded, so automation is a must. Luckily I love automation, so I got to work on an MSBuild script.
Just to give some background on how my Wordpress blog works. I have a SVN checkout of the latest Wordpress tag. I also have a few custom files that I want uploaded, in addition to to the Wordpress code. Instead of interminginly the custom code with Wordpress, I created a custom directory.
My idea for the build was to follow a fairly simple workflow.
Update Wordpress
Export Wordpress checkout to a deployment directory
Copy custom files to deployment directory
SFTP deployment directory
Here is how the majority of the build script came out. You will need MSBuild Community tasks as well as SVN installed somewhere.
<project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" defaulttargets="Upload">
<import project="lib\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"></import>
<propertygroup>
<cloudsiteftp></cloudsiteftp>
<cloudsitedbhost></cloudsitedbhost>
<cloudsitedb></cloudsitedb>
<cloudsitedbuser></cloudsitedbuser>
<cloudsitedbpass></cloudsitedbpass>
<cloudsiteftpuser></cloudsiteftpuser>
<cloudsiteftppass></cloudsiteftppass>
<svnsource></svnsource>
<svntoolpath></svntoolpath>
<deploymentdir></deploymentdir>
<customsourcedir></customsourcedir>
<cloudsitedir></cloudsitedir>
</propertygroup>
<target name="DeleteDeploymentDir">
<message importance="normal" text="Deleting directory $(DeploymentDir)"></message>
<removedir directories="$(DeploymentDir)"></removedir>
<message text="Done."></message>
<message text=""></message>
</target>
<target name="UpdateSource">
<message text="Updating $(SvnSource)..."></message>
<svnupdate toolpath="$(SvnToolPath)" localpath="$(SvnSource)"></svnupdate>
<message text="Done."></message>
<message text=""></message>
</target>
<target dependsontargets="DeleteDeploymentDir" name="ExportSource">
<message text="Exporting $(SvnSource) to $(DeploymentDir)..."></message>
<svnexport toolpath="$(SvnToolPath)" localpath="$(DeploymentDir)" repositorypath="$(SvnSource)"></svnexport>
<message text="Done."></message>
<message text=""></message>
</target>
<target name="MergeCustomSourceCode">
<message text="Copying custom files..."></message>
<exec command="xcopy $(CustomSourceDir) $(DeploymentDir) /E /Y"></exec>
<message text="Done."></message>
<message text=""></message>
</target>
</project>
Uploading the data from a Windows machine required a tool for SFTP or FTP. MSBuild Community Tasks have FTP tasks, but I wanted to make sure my data was transfered securely, so I chose SFTP. pscp was the obvious tool because it is the simplest solution to SFTP file transfer on Windows, in my opinion.
<target dependsontargets="UpdateSource; ExportSource; MergeCustomSourceCode" name="Upload">
<exec command="lib\pscp -r -pw $(CloudSiteFtpPass) $(DeploymentDir)\* $(CloudSiteFtpUser)@$(CloudSiteFtp):$(CloudSiteDir)"></exec>
</target>
The next step was getting the database working. The database and database user have to be created from the web interface before anything can be done from the client. Once it is created, you can execute commands remotely, so automation is pretty easy. Word of warning, I am one of those crazy’s that run MySQL on my laptop, so access to mysql and mysqldump is required for these tasks to work.
<target name="ImportDb">
<error text="No ImportFileName specificed (msbuild /p:ImportFileName ...)" condition="'$(ImportFileName)' == ''"></error>
<exec command="mysql -h $(CloudSiteDbHost) -u $(CloudSiteDbUser) -p$(CloudSiteDbPass) $(CloudSiteDb) < $(ImportFileName)"></exec>
</target>
<target name="BackupDb">
<error text="No backupfile specified" condition="'$(BackupFile)' == ''"></error>
<exec command="mysqldump -h $(CloudSiteDbHost) -u $(CloudSiteDbUser) -p$(CloudSiteDbPass) $(CloudSiteDb) > $(BackupFile)"></exec>
<zip files="$(BackupFile)" zipfilename="$(BackupFile).zip"></zip>
<delete files="$(BackupFile)"></delete>
</target>
What next…?
I am still somewhat unhappy that my upload process. It uploads everything, each time. rsync, or something similar, would be awesome if SSH access was allowed. I am pretty sure I can accomplish a dumb rsync over SFTP, but I haven’t devoted enough time to it. The other downside to this is wordpress’s automatic upgrade feature will get overwritten with the next upload. So be wary about automatically upgrading through the wordpress interface.
After that, I want to incorporate data backups before the upload and allow for easy rollback if something fails. After that, I should be set.