I am new to chef and have been struggling to find best practices on how to configure application configuration in an environment cookbook [source #1].
The environment cookbook I'm working on should do the following:
- Prepare the node for a custom application deployment by creating directories, users, etc. that are specific for this deployment only.
- Add initialization and monitoring scripts specific for the application deployment.
- Define the application configuration settings.
This last responsibility has been a particularly tough nut to crack.
An example configuration file of an application deployment might look as follows:
{
"server": {
"port": 9090
},
"session": {
"proxy": false,
"expires": 100
},
"redis": [{
"port": 9031,
"host": "rds01.prd.example.com"
}, {
"port": 9031,
"host": "rds02.prd.example.com"
}],
"ldapConfig": {
"url": "ldap://example.inc:389",
"adminDn": "CN=Admin,CN=Users,DC=example,DC=inc",
"adminUsername": "user",
"adminPassword": "secret",
"searchBase": "OU=BigCustomer,OU=customers,DC=example,DC=inc",
"searchFilter": "(example=*)"
},
"log4js": {
"appenders": [
{
"category": "[all]",
"type": "file",
"filename": "./logs/myapp.log"
}
],
"levels": {
"[all]": "ERROR"
}
},
"otherService": {
"basePath" : "http://api.prd.example.com:1234/otherService",
"smokeTestVariable" : "testVar"
}
}
Some parts of this deployment configuration file are more stable than others. While this may vary depending on the application and setup, things like port numbers and usernames I prefer to keep the same across environments for simplicity's sake.
Let me classify the configuration settings:
Stable properties
- session
- server
- log4js.appenders
- ldapConfig.adminUsername
- ldapConfig.searchFilter
- otherService.basePath
- redis.port
Environment specific properties
- log4js.levels
- otherService.smokeTestVariable
Partial-environment specific properties
- redis.host:
rds01.[environment].example.com
- otherService.basePath:
http://api.[environment].example.com:1234/otherService
Encrypted environment specific properties
- ldapConfig.adminPassword
Questions
- How should I create the configuration file? Some options: 1) use a file shipped within the application deployment itself, 2) use a cookbook file template, 3) use a JSON blob as one of the attributes [source #2], 4)... other?
- There is a great diversity of variability in the configuration file; how best to manage these using Chef? Roles, environments, per-node configuration, data-bags, encrypted data-bags...? Or should I opt for environment variables instead?
Some key concerns in the approach:
- I would prefer there is only 1 way to set the configuration settings.
- Changing the configuration file for a developer should be fairly straightforward (they are using Vagrant on their local machines before pushing to test).
- The passwords must be secure.
- The chef cookbook is managed within the same git repository as the sourcecode.
- Some configuration settings require a great deal of flexibility; for example the
log4js
setting in my example config might contain many moreappender
s with dozens of fairly unstructured variables.
Any experiences would be much appreciated!
Sources
- http://blog.vialstudios.com/the-environment-cookbook-pattern/
- http://lists.opscode.com/sympa/arc/chef/2013-01/msg00392.html
- http://jtimberman.housepub.org/blog/2013/01/28/local-templates-for-application-configuration/
- http://realityforge.org/code/2012/11/12/reusable-cookbooks-revisited.html