Should server/database config files, including passwords, be stored in source control?

SvnGitVersion ControlPasswordsConfig

Svn Problem Overview


I'm looking to hear some best practices...

Assuming a web application that interacts with a few different production servers (databases, etc.)... should the configuration files that include database passwords be stored in source control (e.g., git, svn)?

If not, what's the best way to keep track of server database (or other related) passwords that your application needs access to?

Edit: added a bounty to encourage more discussion and to hear what more people consider best practice.

Svn Solutions


Solution 1 - Svn

There's no single "silver bullet" answer here and it would all greatly depend on details.

First of all, I consider best practice to separate all source code from configuration in separate repository. So, source code remains source code, but it's installation or deployment (with configuration, passwords, etc) is the whole other thing. This way you'll firmly separate developers' tasks from sysadmins' tasks and can ultimately build 2 distinct teams doing what's they're good at.

When you have separate source code repository + deployment repository, your best next bet is considering deployment options. Best way I see here is using deployment procedures typical for a chosen OS (i.e. building autonomous packages for a chosen OS the way that OS's maintainers do).

For example, Red Hat or Debian packaging procedures usually mean grabbing a tarball of software from external site (that would be exporting sources from your source code VCS), unpacking it, compiling and preparing packages ready for deployment. Deployment itself should ideally mean just doing a quick & simple command that would install the packages, such as rpm -U package.rpm, dpkg --install package.deb or apt-get dist-upgrade (given that your built packages go to a repository where apt-get would be able to find them).

Obviously, to get it working this way, you'll have to supply all configuration files for all components of a system in a fully working state, including all addresses and credentials.

To get more concise, let's consider a typical "small service" situation: one PHP application deployed across n application servers running apache / mod_php, accessing m MySQL servers. All these servers (or virtual containers, that doesn't really matter) reside in a protected private network. To make this example easier, let's assume that all real internet connectivity is fronted by a cluster of k http accelerators / reverse proxies (such as nginx / lighttpd / apache) which have very easy configuration (just internal IPs to forward to).

What do we have for them to be connected and fully working?

  • MySQL servers: set up IPs/hostnames, set up databases, provide logins & passwords
  • PHP application: set up IPs/hostnames, create configuration file that will mention MySQL servers IPs, logins, passwords & databases

Note that there are 2 different "types" of information here: IPs/hostnames is something fixed, you'd likely want to assign them once and for all. Logins & passwords (and even database names), on the other hand, are purely for connectivity purposes here - to make sure for MySQL that it's really our PHP application connecting to it. So, my recommendations here would be splitting these 2 "types":

  • "Permanent" information, such as IPs, should be stored in some VCS (different from source code VCS)
  • "Transient" information, such as passwords between 2 applications, should be never stored, but generated during generation of deployment packages.

The last and the toughest question remains here: how to create deployment packages? There are multiple techniques available, 2 main ways are:

  • Exported source code from VCS1 + "permanent" configuration from VCS2 + building script from VCS3 = packages
  • Source code is in VCS1; VCS2 is a distributed version control (like git or hg) which essentially contains "forks" of VCS1 + configuration information + building scripts which can generate . I personally like this approach better, it's much shorter and ultimately easier to use, but learning curve may be a bit steeper, especially for admin guys who'll have to master git or hg for it.

For an example above, I'd create packages like:

  • my-application-php - which would depend on mod_php, apache and would include generated file like /etc/my-php-application/config.inc.php that will include MySQL database IPs/hostnames and login / password generated as md5(current source code revision + salt). This package would be installed on every of n application servers. Ideally, it should be able install on a cleanly installed OS and make a fully working application cluster node without any manual activity.
  • my-application-mysql - which would depend on MySQL-server and would include post-install script that:
    • starts MySQL server and makes sure it will start automatically on OS start
    • connects to MySQL server
    • checks if required database exists
    • if no - creates the database, bootstraps it with contents and creates login with password (the same logins & passwords as generated in /etc/my-php-application/config.inc.php, using md5 algorithm)
    • if yes - connects to the database, applies migrations to bring it up to the new version, kills all older logins / passwords and recreates the new login/password pair (again, generated using md5(revision + salt) method)

Ultimately, it should bring the benefit of upgrading your deployment using single command like generate-packages && ssh-all apt-get dist-upgrade. Also, you do not store inter-applications passwords anywhere and they get regenerated on every update.

This fairly simple example illustrates a lot of methods you can employ here - but, ultimately, it's up to you to decide which solution is better here and which one is overkill. If you'll put more details here or as a separate question, I'll gladly try to get into details.

Solution 2 - Svn

Leaving aside the point that passwords should never be stored in plain text anywhere (other than someone's cranium or a locked vault accessible only to the CEO, CFO and CIO (and needing all three keys at once)), you should store everything into source control that's required to build your product.

That means not just your source, but even the specifications for the build machines, compiler options, the compilers themselves and so on.

If we could find a way to check in the physical hardware, we'd do that too :-)

Everything that can be reproduced by the build process itself, or anything for running rather than building the software (such as your passwords) does not generally belong under source control but some shops will do that for their executables, generated docs and so on, just so that they can quickly get a specific release out for installation.

Solution 3 - Svn

Passwords should not be stored in source control. At all. Ever. See How to keep secrets secret

Passwords, servernames, etc. are part of the deployment configuration as performed by the server administrator. It is essential to document this procedure and place the documented procedure under control.

Alternatively the deployment configuration could be performed by a script that the sysadmin would run to perform the configuration, and during the script execution it would ask the sysadmin to provide the required information. Again this script must be kept in version control.

Everything else, apart from server configuration must be in source control.

Storing server configuration in source control is generally a bad idea because it gets in the way of deployments and can cause small disasters (e.g. when someone doesn't realise that their test version deployed from source control is communicating with a live service).

Always keep these configuration files outside of the webroot.

Trusted connections may be an option, allowing known IP addresses to connect to services by configuration of that service..

Solution 4 - Svn

In general, I agree with paxdiablo: put everything you possibly can under source control. That includes production configuration files with database credentials.

Think about the situation where your server crashes, the backups turn out to be bad and you need to get that server back up. I think you and your customer (or boss) would definitely agree that having everything needed to deploy the site in source control is a big plus.

If you want to build easily deployable packages from your sources using continuous integration (another best practice) you'll have to put the configuration files under source control.

Also consider that in most cases the devs that have source control access cannot access the production database server directly. The production passwords are useless to them.

If the wrong people gained access to your sources, they still need to gain access to the production server in order to do harm with the passwords. So, if your production environment is properly protected, the security risks of passwords in source control are very limited.

Solution 5 - Svn

I think this question is more about information ownership, trust and organization. You should ask yourself, what part of your organization would you trust to keep your system passwords safe from disclosure and misuse?

I've been in organizations where they were kept by the people responsible for the business. In others they've been delegated to the operations team that also owned the processes around creation and usage etc.

The most important thing is that it is clearly defined in your organization who should have access to system passwords. After that you can decide on appropriate technical solutions for protecting the passwords.

Solution 6 - Svn

No. Production password should be configured directly on the server. You should create a deployment instructions for the deployment team/person to change the right properties file during deployment.

Solution 7 - Svn

In my Subversion repos for PHP, configuration files that contain passwords are checked in as config.php.sample with hints to what has to be provided and scripts relying require a config.php to be present at the same location.

The repository is configured to ignore config.php for that directory to avoid "accidental" adds or check-ins.

Solution 8 - Svn

Sample configurations file, sure, I would put them under version control. But usually not with realworld access data such as server addresses or passwords. More somethinglike

program.conf

mysql option for $myprog.

#SERVER_ADDR=127.0.0.1 #SERVER_USER=mysql #SERVER_PASSWD=abcdef

Solution 9 - Svn

Problems with passwords in source code:

  • hard to vary from one deployment to another (I don't want to have to modify source code in production)
  • increased likelyhood of accidentally corrupting production database when doing development
  • security issue (in most shops there is no reason for code/developers to know prod passwords)
  • changed password requires redeployment

What I have found works the best is having a config checked in that uses mixture sane defaults and placeholders for deployment specific data. Our apps always look for a system config which allows the override of any variable. This allows the production machine to have a config appropriate for it's deployment.

Note: When I function as an admin I always manage configs separately from code (for good reason).

Solution 10 - Svn

I would always exclude vital config files that contain passwords or other access details (like for databases), it's purely best practice. Plus on top of that source- and version-control serves usually more than one user and not all of them work with the same database details or even with the same server config (domains etc) and for this purpose config files should stay excluded fromt he whole lot.

Solution 11 - Svn

Without a proper build process, I'm using this strategy (for PHP apps):

  1. Make a folder /etc/companyname

  2. In it, place two files:

    <?php // env.php
    return 'prod'; 
    

    <?php // appname-prod.php
    return array(
      'db' => array( /* credentials */ ),
      /* other host-specific conf data */
    ); 
    
  3. Make both files readable only by your PHP process

Now your app's config file will be something like:

<?php // config.php
$env = (require "/etc/companyname/env.php");
$creds = (require "/etc/companyname/appname-{$env}.php");

With this in place, the environment defines the credentials used, and you can move code between pre-configured environments (and control some options with $env). This, of course, can be done with server environment variables, but this a) is simpler to setup and b) doesn't expose credentials to every script on the server (won't show up in a stray debugging junk like phpinfo()).

For easier reading outside PHP you could make the credential files JSON or something and just put up with the tiny performance hit (APC won't cache them).

Solution 12 - Svn

I prefer to have a local_settings file beside the main settings file. This local_settings shouldn't be added to the repository, but I will add a sample.local_setting to the repository to show the structure of this file.

In run time if a local_settings exists, its values will override the values of main settings file.

For example in python:

settings.py:

log='error.log'
db=lambda:None
db.host='localhost'
db.user=''
db.password=''

try:
    import local_settings
except ImportError:
    pass

local_settings.py:

from settings import *

db.user='abcd'
db.password='1234'

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionphilfreoView Question on Stackoverflow
Solution 1 - SvnGreyCatView Answer on Stackoverflow
Solution 2 - SvnpaxdiabloView Answer on Stackoverflow
Solution 3 - SvnRichard HarrisonView Answer on Stackoverflow
Solution 4 - SvnMarnix van ValenView Answer on Stackoverflow
Solution 5 - Svn8DHView Answer on Stackoverflow
Solution 6 - SvnJinesh ParekhView Answer on Stackoverflow
Solution 7 - SvnLinus KleenView Answer on Stackoverflow
Solution 8 - Svnuser502515View Answer on Stackoverflow
Solution 9 - SvndietbuddhaView Answer on Stackoverflow
Solution 10 - SvnMatthew MorekView Answer on Stackoverflow
Solution 11 - SvnSteve ClayView Answer on Stackoverflow
Solution 12 - SvnimanView Answer on Stackoverflow