Skip to content

Instantly share code, notes, and snippets.

@jahio
Created March 29, 2014 03:20
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jahio/9847747 to your computer and use it in GitHub Desktop.
Save jahio/9847747 to your computer and use it in GitHub Desktop.
Example dna.json for Engine Yard Cloud
{
"alert_email": "email address where you want automated warnings to go",
"backup_interval": "int value for db backups, configurable on dashboard",
"backup_window": "int value for db backups, configurable on dashboard",
"ruby_version": "Ruby 1.9.3 - could be 2.0.0 or something else",
"db_host": "internal hostname of your database master",
"db_slaves": [
"db replica hosts appear here. only works with [Postgre|My]SQL"
],
"user_ssh_key": [
"ssh keys for each user will appear in this array",
"and they will be written out to /home/deploy/.ssh/authorized_keys"
],
"utility_instances": [
{
"hostname": "an internal amazon ip",
"name": "resque_1 (or whatever you named it in the dashboard)"
},
{
"hostname": "a different internal amazon ip",
"name": "elasticsearch_1 (or whatever you named it in the dashboard)"
}
],
"environment": {
"name": "the name of the env - could be 'prod', 'staging', 'wibble' etc.",
"framework_env": "actual framework env - staging, production, etc.",
"stack": "nginx_unicorn - internal variable specifying app server stack"
},
"haproxy": {
"username": "deploy (default for logging in at http://appmasterip/haproxy?stats)",
"password": "password for the deploy user for above url"
},
"users": [
{
"username": "deploy ('deploy' is always our default user)",
"password": "randomly generated password",
"gid": "1000",
"uid": "1000",
"comment": ""
}
],
"packages_to_install": [
"if you have it enabled in the dashboard (which is NOT recommended)",
"a list of packages to install via portage will be listed here.",
"we don't recommend this because that installation should be managed by,",
"and frankly is better suited to, chef. We may retire support for this",
"feature at any point in the future.",
"Normally this would look like any valid package atom, like this:",
"=www-servers/nginx-1.4.7",
"which is installed with emerge via a command like:",
"emerge -v =www-servers/nginx-1.4.7",
"however, one must be sure the package is UNMASKED in",
"/etc/portage/package.keywords/local by explicit, specific atom (the =...",
"...thing) before this will install. That's why chef is a better option."
],
"gems_to_install": [
{
"name": "jazor",
"version": "0.1.8"
},
{
"name": "other gems you list in the dashboard will also be installed",
"version": "here, however we STRONGLY recommend using bundler instead!"
},
{
"name": "because bundler will properly manage dependencies and help you",
"version": "avoid dependency hell!"
}
],
"applications": {
"my_application_name_here": {
"deploy_key": "the deploy key we generated for you and you've hopefully
added to your git repo host (e.g. GitHub)",
"repository_name": "git@github.com:youraccount/yourapp.git",
"type": "could be rails3, rails4, sinatra, rack, etc. (node.js, java)",
"branch": "which git branch you want to deploy - usually master",
"deploy_action": "deploy",
"migration_command": "command you want to use to migrate.
Usually like rake db:migrate but could be whatever
you want it to be, esp. for PHP, Node.js etc. apps",
"revision": "SHA for branch",
"run_deploy": false,
"run_migrations": false,
"newrelic": false,
"vhosts": [
{
"role": "staging - like framework_env",
"name": "valid DNS hostname entered in dashboard, e.x. example.com"
},
{
"role": "staging",
"name": "example2.com - remember, you can have more than one app
on an environment, but be sure to give them *different*
hostnames so as not to confuse nginx configuration."
}
],
"recipes": [
"memcached",
"monit",
"nginx",
"unicorn",
"These are the basic recipes that *our* platform will run from our own
cookbooks that we maintain on our own. You don't need to worry about
this one iota."
],
"http_bind_port": 80,
"https_bind_port": 443,
"auth": {
"active": false
},
"services": [
{
"resource": "mongrel",
"mongrel_base_port": 5000,
"mongrel_mem_limit": 150,
"mongrel_instance_count": 3,
"_comment": "This is left over from earlier versions of the product.
Just ignore it since nobody uses mongrel anymore."
},
{
"resource": "memcached",
"base_port": 11211,
"mem_limit": 128,
"_comment": "memcached comes installed out of the box by default, but
you can make changes to that configuration with custom
chef recipes."
}
]
}
},
"crons": [
"If you set up cron jobs in the dashboard, they'd go here. Instead of this",
"however, we recommend setting up cron in your own custom chef recipes.",
"Not a whole lot of customers make use of this because they'd like to have",
"revision control over their cron changes, which you get with custom chef,",
"so we might remove this feature in the future. Just use custom chef for",
"this instead. It's better all around."
],
"master_app_server": {
"public_ip": "public EC2 hostname, managed by their dns",
"private_dns_name": "EC2's internal hostname for the VM",
"_comment": "The application master is where the EIP (Elastic IP) for the
environment is anchored, meaning all traffic goes right there
on port 80 or 443, which is where haproxy runs and then
forwards requests to one of N nginx backends, where N is equal
to the number of application instances in your environment.
This is a round-robin load balancing scheme."
},
"members": [
"this array contains a list of known application machines in the",
"environment based on their internal IP from AWS. This is how haproxy",
"knows which backends (app servers) to send requests to later when that",
"recipe runs."
],
"engineyard": {
"environment": {
"alert_email": "where you want automated warning emails sent. This could
take the form of '<some server ip> using X% memory' to
warn you about memory/swap use (common with overnight
admin/backup tasks/cron jobs), or '<ip> CPU usage at
100%' or something similar. Recommend this is an alias
to your entire development team including your ops person
if you have one.",
"backup_interval": 24,
"backup_window": 10,
"stonith_endpoint": "https://cloud.engineyard.com/stonith - this is where
application machines in the environment will 'check
in' every so often to be sure they're up. If not,
Engine Yard Cloud will *automatically* 'shoot the
other node in the head' - STONITH. This is how
automated application server failover happens. If the
app master fails to check in with stonith, EY Cloud
kills it of its own volition then promotes one of
your app slaves to be the master. This is why we
always recommend running at minimum 2 app machines
in any given production environment. Instances can
become unstable or unresponsive for many reasons,
most commonly infrastructure failure (network, host)
or customer code not behaving as expected.",
"newrelic_key": null,
"ruby_version": null,
"stack_name": "nginx_unicorn",
"name": "staging - environment name, again (could just as easily be
'wibble' or 'foobar')",
"framework_env": "staging (or production, or something else)",
"stats_password": "password for haproxy stats as noted above",
"ssh_username": "deploy - always our default user",
"ssh_password": "password for the account, though you'll never use it
since we require using ssh keys instead",
"ssh_keys": [
"again, a list of ssh keys will appear in this array, one per user.",
"these are added in the dashboard under tools -> ssh keys. Once you",
"add an SSH key, you need to edit the environment you want it on, then",
"check the box for that key in that environment. Click update, then go",
"back to the environment overview page and click 'apply'. When done,",
"your SSH key should be installed in /home/deploy/.ssh/authorized_keys",
"and you should be able to SSH up as the deploy user to the EC2 host."
],
"db_stack_name": "postgres9_3 - could be mysql5_1 or something",
"monitoring": "monit (default, not changable w/o your own chef)",
"region": "us-east-1 (could be us-west-# or eu-west-# or whatever)",
"backup_bucket": "internal location where db backups are stored - note
that we don't mean snapshots here, we mean an
honest-to-god SQL dump from mysqldump or similar",
"components": [
{
"key": "ruby_193 (or ruby_200 or whatever)"
},
{
"key": "rubygems",
"version": "1.8.25"
},
{
"key": "lock_db_version
- This is a dashboard option that lets you prevent the
environment from upgrading the minor version of the db.
For example, if you're on PostgreSQL 9.2.4, and a platform
update comes from us to bump you to 9.2.7, if this is true
that update will not happen for you. Modifyable in env
edit page.",
"value": false
},
{
"key": "ext4 (whether or not you have the ext4 fs feature)",
"value": null
},
{
"key": "environment_metadata (internal stuff, ignore)",
"descriptive_hostname": "true"
},
{
"key": "metadata",
"clusters": [
]
}
],
"instances": [
{
"id": "i-xxxxxxxx (EC2 instance ID)",
"name": null,
"reporting_url": "internal, ignore",
"role": "db_master (could be app_master, app, util, db_master,
or db_slave)",
"enabled": true,
"public_hostname": "EC2 public hostname",
"private_hostname": "EC2 internal only hostname",
"awsm_token": "internal, ignore",
"stonith_config": {
"endpoint_uri": "https://cloud.engineyard.com/stonith",
"endpoint_token": "token for EY stonith to identify this machine",
"endpoint_id": "i-xxxxxxxx (internal, ignore)",
"monitor_host": "EC2 internal hostname (internal, ignore)"
},
"instance_api_config": {
"base_url": "https://cloud.engineyard.com/instance_api
This is where our API for instance configuration is",
"instance_id": "internal db id for the instance in question",
"token": "specific token for this instance",
"core_url": "https://api.engineyard.com/ - internal api url"
},
"components": [
{
"key": "ssmtp - used as a sendmail replacement"
},
{
"tags": [
"product=cloud",
"ey.domain=api.engineyard.com",
"ey.server.id=some number",
"ey.environment.id=some number",
"sso_id=internal uuid, ignore it"
],
"key": "appfirst"
},
{
"instance_id": 123456789101112,
"domain": "api.engineyard.com",
"key": "appfirst_tags - appfirst related stuff, ignore it"
}
]
},
{
"id": "i-xxxxxxxx",
"name": "resque_1 - specific name given to this instance in the dash",
"reporting_url": "https://cloud.engineyard.com/reporting/some id",
"role": "util (this one's a util machine named resque_1)",
"enabled": true,
"public_hostname": "EC2 public hostname",
"private_hostname": "internal private hostname",
"awsm_token": "internal uuid - ignore",
"stonith_config": {
"endpoint_uri": "https://cloud.engineyard.com/stonith",
"endpoint_token": "internal token to ID this machine",
"endpoint_id": "i-xxxxxxxx",
"monitor_host": "internal ec2 hostname, ignore"
},
"instance_api_config": {
"base_url": "https://cloud.engineyard.com/instance_api",
"instance_id": 1234567891011213,
"token": "some token",
"core_url": "https://api.engineyard.com/"
},
"components": [
{
"key": "ssmtp - sendmail replacement"
},
{
"tags": [
"product=cloud",
"ey.domain=api.engineyard.com",
"ey.server.id=some id",
"ey.environment.id=some id",
"sso_id=some id"
],
"key": "appfirst"
},
{
"instance_id": 1234567891011213,
"domain": "api.engineyard.com",
"key": "appfirst_tags"
}
]
},
{
"id": "i-xxxxxxxx",
"name": null,
"reporting_url": "https://cloud.engineyard.com/reporting/some id",
"role": "app_master - this is where requests first get to the
cluster. From here haproxy round robin balances them to
one of the other application machines in this cluster. The
app master is also responsible for running a 'git pull'
of your repository, then instead of running it from all
application machines, it does an rsync of the files over to
each app and utility machine instead. Cuts down on down on
deploy times and lowers load on git hosts",
"enabled": true,
"public_hostname": "public ec2 hostname",
"private_hostname": "private ec2 hostname",
"awsm_token": "some token, ignore it",
"stonith_config": {
"endpoint_uri": "https://cloud.engineyard.com/stonith",
"endpoint_token": "ignore",
"endpoint_id": "i-xxxxxxxx",
"monitor_host": "internal hostname"
},
"instance_api_config": {
"base_url": "https://cloud.engineyard.com/instance_api",
"instance_id": 3145798675309123,
"token": "ignore",
"core_url": "https://api.engineyard.com/"
},
"components": [
{
"key": "ssmtp - replacement for sendmail"
},
{
"tags": [
"product=cloud",
"ey.domain=api.engineyard.com",
"ey.server.id=some id",
"ey.environment.id=some id",
"sso_id=some id"
],
"key": "appfirst"
},
{
"instance_id": 123456789000001,
"domain": "api.engineyard.com",
"key": "appfirst_tags"
}
]
},
{
"id": "i-xxxxxxxx",
"name": "elasticsearch_1 - here's our elasticsearch util (example)",
"reporting_url": "https://cloud.engineyard.com/reporting/some id",
"role": "util",
"enabled": true,
"public_hostname": "public ec2 hostname",
"private_hostname": "internal hostname",
"awsm_token": "internal token, ignore",
"stonith_config": {
"endpoint_uri": "https://cloud.engineyard.com/stonith",
"endpoint_token": "internal token, ignore",
"endpoint_id": "i-xxxxxxxx",
"monitor_host": "internal ec2 hostname"
},
"instance_api_config": {
"base_url": "https://cloud.engineyard.com/instance_api",
"instance_id": 12345678900000000001,
"token": "internal token, ignore",
"core_url": "https://api.engineyard.com/"
},
"components": [
{
"key": "ssmtp sendmail replacement"
},
{
"tags": [
"product=cloud",
"ey.domain=api.engineyard.com",
"ey.server.id=some id",
"ey.environment.id=some id",
"sso_id=some token"
],
"key": "appfirst"
},
{
"instance_id": 123456789000000000000123,
"domain": "api.engineyard.com",
"key": "appfirst_tags"
}
]
}
],
"apps": [
{
"deploy_key": "This is the deploy key EYC creates for you",
"repository_name": "git@github.com:yourorg/yourapp.git",
"type": "rails3",
"branch": "master",
"deploy_action": "deploy",
"migration_command": null,
"revision": "revision",
"run_deploy": false,
"run_migrations": false,
"name": "name of the application in the dashboard. For example,
'bob_loblaws_law_blog' - note, this is NOT the runtime env,
e.g. 'staging' or 'production'",
"bundled": null,
"newrelic": false,
"database_name": "name of the database itself ([Postgre|My]SQL only)",
"components": [
{
"collection": [
{
"name": "New Relic",
"config": {
"label": "New Relic",
"vars": {
"new_relic_account_id": 11111111111111151111111111111111,
"license_key": "new relic license key - this is obtained
automatically through new relic's
partnership with engine yard; if you want
to bring your own, no problem, you'll
just have to use custom chef to install
it!",
"api_key": "new relic api key, also obtained
via partnership"
}
}
},
{
"name": "appfirst",
"config": {
"label": "appfirst",
"vars": {
"daily_supplement_path": "/etc/appfirst",
"api_key": 11111111111111151111111111111111
}
}
}
],
"key": "addons"
},
{
"key": "app_metadata"
}
],
"gems": [
{
"name": "jazor",
"version": "0.1.8",
"source": null,
"_comment": "This is the same as above - gems installed on the
machine by default - but applies at the *app* level"
}
],
"ebuilds": [
"ignore for now - part of internal portage/gentoo stuff",
"if you need a custom ebuild for something, submit a support",
"ticket at https://support.cloud.engineyard.com and we'll hook",
"you up as soon as possible. Then you'd use custom chef to",
"install it once the ebuild is in our portage tree."
],
"vhosts": [
{
"domain_name": "example.com - domain name for this app",
"ssl_cert": null,
"_comment": "If you had an SSL cert installed here, it would
show up as a string above instead of null. These
certs are installed in the dashboard under tools ->
ssl certificates. It would be applied by our nginx
recipe automatically."
}
]
}
],
"crons": [
"If you had cron jobs set up, they'd be listed here. However, note",
"that this is a deprecated practice and only here to support legacy",
"customers. Do this with custom chef instead, it's a lot better."
]
},
"this": "i-xxxxxxxx"
},
"instance_role": "util",
"reporting_url": "https://cloud.engineyard.com/reporting/some uuid",
"name": "resque_1",
"run_list": "recipe[ey-base]",
"_comment": "This run_list tells chef-solo on the server what recipes to run,
which in this case is the ey-base recipe which will bring in all
necessary and appropriate elements of our stack based on your
environment configuration selections. In a full chef run, our
'main' recipes are run first to configure a sane system. Then,
once that's done and successful, your custom recipes (if any)
are downloaded into /etc/chef-custom, obliterating anything
that was previously there (so don't try to run from on the
instance directly as we'll just nuke everything in
/etc/chef-custom and re-download a fresh copy) and run to
configure your environment to your liking, according to your
code."
}
Copy link

ghost commented Mar 29, 2014

JAH, this is really informative information and super helpful. Thanks for going through every line!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment