Saturday, March 26, 2011

Sensitive Web.config Settings + GitHub + AppHarbor

So I learned some lessons with having an open source project (WatchedIt.net) on GitHub that is also being deployed to AppHarbor using the same Git repository.

Number one tip. Do NOT save any sensitive information in any source file that you check into the repository. Even if you make a single commit locally with the sensitive info and then undo it with another commit, do NOT push it to GitHub without removing the history because your history will be sent to GitHub with a normal push. This page on GitHub can help you with that.

Once we make sure our application does not have any sensitive info we need a way for AppHarbor to know our settings. The easy settings to handle are the Application Settings. AppHarbor has a Configuration Variables page where you define Key/Value pairs in your Web.Config you want AppHarbor to replace. For instance for WatchedIt I store my Twitter Key and Secret tokens like this in the Web.Config that is checked into Git and pushed to GitHub.

<appSettings>
    <!--Site Settings-->
    <add key="ApplicationName" value="WatchedIt" />
    <add key="Twitter_Consumer_Key" value="YOUR_KEY" />
    <add key="Twitter_Consumer_Secret" value="YOUR_KEY" />
</appSettings>

Then I configure AppHarbor to replace Twitter_Consumer_Key and Twitter_Consumer_Secret with the real values and everything just works. This is pretty straight forward and covered by AppHarbor here.

The setting that challenged me though was the connection string. I use Entity Framework Code First running on SQL CE to develop WatchedIt locally. My connection string in the Web.Config I check into Git looks like this:

<connectionStrings>
    <add name="SiteDB" connectionString="Data Source=|DataDirectory|SiteDB.sdf" providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>


If you use an AppHarbor SQL or MySQL DB, AppHarbor says it will replace your connection string based on the name property. For some reason this didn't work for me and I think it's because it doesn't change the providerName property. So since AppHarbor also supports Web.Config transformations and even has a nice littler tester for them I decided to combine the two features and see what would happen. To my delight it worked! Here is the code I placed in Web.Release.config to make it work:

<connectionStrings>
    <add name="SiteDB" connectionString="" providerName="System.Data.SqlClient" xdt:Transform="Replace" />
</connectionStrings>

Now I don't have to worry about accidently pushing my database connection string to GitHub for the world to see and while developing locally Visual Studio will use my SQL CE DB.

This is just another example of why I love AppHarbor! I strongly recommend trying them out if you haven't yet!

....And one more thing. A big thanks to Michael Friis of AppHarbor for changing by DB password after "the incident". These guys rock at customer service!