7 ms·
I have always disagreed most with the config advice. Config ends up getting defined by a lot of different parties and quite often by developers and its often be
by PaulKeeble 3y ago
I have always disagreed most with the config advice. Config ends up getting defined by a lot of different parties and quite often by developers and its often best to ship the application with reasonable defaults and then allow overrides from environment specific files and then environment variables. This is the most flexible for most server side applications because you often know what a setup should be and its best source controlled but secrets need to be injected at run time. Configuration needs to have cascading levels to make life easiest in dev, test and production without enormous setup time.
- Kinrany 3y agoYou can, and probably should, have reasonable defaults. Configuration should be version controlled, but separately from source code because it describes deployments, not images used for deployments.
- willseth 3y agoWhy not also express the defaults as config, or is that what you meant? I don't think that runs afoul of 12 factor.
- schneems 3y ago> Configuration needs to have cascading levels to make life easiest in dev, test and production without enormous setup time. The backdrop of when the 12factor app was written is that you can toggle modes like that with RAILS_ENV=test (an environment variable). One way I think of the config section is “does your config strategy play well with containers?” Once you build an image you have a static disk state that doesn’t persist changes unless you make a new image. If your config is file based (only), then to toggle between test and production behavior you would have to build a whole new image. By allowing config to change without the underlying disk, it helps to isolate changes. Did the app break because something in the deploy (image generation) broke? Or is it a bad config? If you decouple image generation from configuration changes it eliminates that question.
- ahtihn 3y ago> Once you build an image you have a static disk state that doesn’t persist changes unless you make a new image. If your config is file based (only), then to toggle between test and production behavior you would have to build a whole new image. You could mount a volume with the config file. The nice thing is that this lets you change the config at runtime (assuming the app watches for file changes). Env vars cannot be changed at runtime.
- schneems 3y ago> Env vars cannot be changed at runtime You can specify env vars any time you boot up an image. I see this as a benefit. I use containers for production and don’t want wild ssh yolo modifications. I want to have very clear immutable inputs. > mount a volume with the config file Sure, but where? And what if you need multiple files for multiple different things to configure? What’s to prevent someone from accidentally putting non config files into that volume or accidentally changing the permissions on the file or any other host of things that we just don’t have to reinvent if we use env vars.
- CraigJPerry 3y agoSo long as you are systemically protecting against someone spinning up a QA instance against some Prod resource then it’s probably alright to ship most config with the app. You don’t want to allow a (entirely predictable) human error to cause 100k auth denied retries against a prod job submission queue from QA for example. Much config isn’t about infra though, it’s often what kind of ResolverStrategy (made up but plausible sounding name) bean do I want to wire in each env for example.
- sethammons 3y ago> application with reasonable defaults defaults for dev or defaults for prod :) If you say dev, you will eventually break prod. And prod defaults may not make _any_ sense for dev.
- berkes 3y ago> And prod defaults may not make _any_ sense for dev They are actually rather dangerous even. You certainly don't want your dev (or test CI) to reset the database if you are accidentally connected to prod. Same for email-endpoints, CDN, a message-bus, etc. I've had my share of near-heart-attacks where I send out 10k emails or thousands of payments on actual production services because of a spagetti config loaders with stuff that boils down to `if (getHostname() === "localhost") { include("dev.json") } else { include("prod.json") }`. I'd prefer a hundred .envs and whatnots to avoid just one of these scares.
- jameshart 3y agoMy approach is: - defaults are sensible (safe and secure) defaults for prod - prod secrets are only available in the prod environment So if you accidentally end up trying to run with the prod settings in a nonproduction environment it might try and access the prod database server... but it won't get anywhere because it doesn't have those secrets.