<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="82561" data-post-id="82561">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="stevedomin" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevedomin/120/7908_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  stevedomin
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="47" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Unless we strictly impose Mix to be a compile-time config only. This means that <code>MIX_ENV=prod PORT=4040 mix run</code> won’t have any effect if the project was already compiled with <code>PORT=8080</code> . But going down this path feels like we are breaking both approaches, instead of fixing them.</p>
</blockquote>
</aside>
<p><a class="mention" href="/u/josevalim" rel="nofollow">@josevalim</a> Is that feasible? Apologies if this is out of topic but I feel like a lot of the confusion comes from Mix and how it’s used, or at least how we started using it as a community.</p>
<p>Given that Mix is a build tool it seems logical to me that the configuration living in <code>config.exs</code> should be compile-time only. It should only contain the configuration useful to build my project (which pubsub adapter I want to use, etc.).</p>
<p>I’d argue that it’s the same for Mix tasks. In his <a href="https://dockyard.com/blog/2018/02/28/elixir-deployment-tools-update-february-2018" rel="noopener nofollow ugc">“Elixir Deployment tools update”</a>, <a class="mention" href="/u/bitwalker" rel="nofollow">@bitwalker</a> talks about adding support for Mix tasks, and while I like the idea I kinda feel like maybe we shouldn’t be using Mix tasks for what we are using them for (running migrations, etc.)</p>
<aside class="quote no-group" data-username="sasajuric" data-post="53" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>Personally I believe that a lot of the stuff which is managed by <code>config.exs</code> &amp; friends belongs to the code. For example <a href="https://github.com/sasa1977/erlangelist/blob/8467056729108b368484d71e9ff89da415434425/site/lib/erlangelist_web/endpoint_config.ex#L24-L61" rel="noopener nofollow ugc">these</a> are params which <code>mix phx.new</code> by default pushes into config script, spread across four files, bundled with unrelated data, but detached from the place where it logically belongs.</p>
</blockquote>
</aside>
<p>Completely agree with that, although I do think having a centralised place for operator configuration might be desirable. Or at least a centralised place to discover what’s configurable. As an operator I shouldn’t have to look at hundreds of file to know what I can configure and how.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82561" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/54">Post #53</a>
	                </div>
	            </div>
              <div id="likers-container-82561" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82561"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #53"></div>
  </section>
</div>
    <div class="postbit" id="82563" data-post-id="82563">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="stevedomin" data-post="54" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevedomin/48/7908_2.png" class="avatar"> stevedomin:</div>
<blockquote>
<p>I do think having a centralised place for operator configuration might be desirable. Or at least a centralised place to discover what’s configurable. As an operator I shouldn’t have to look at hundreds of file to know what I can configure and how.</p>
</blockquote>
</aside>
<p>I agree. If you want to assist operation, then it needs to be done. However, this will require an explicit effort to pick the things which are relevant to the operator and extract them into a separate place. Most of the stuff currently sitting in config scripts is plain noise for the operator, while some of the stuff they need might likely not be there.</p>
<p>I completely agree with <a class="mention" href="/u/michalmuskala" rel="nofollow">@michalmuskala</a> here:</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="17" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Things that are usually operator configuration - API keys, component addresses should not go in there.</p>
</blockquote>
</aside> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82563" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/55">Post #54</a>
	                </div>
	            </div>
              <div id="likers-container-82563" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82563"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #54"></div>
  </section>
</div>
    <div class="postbit" id="82565" data-post-id="82565">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cybrox" data-post="52" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cybrox/48/10045_2.png" class="avatar"> cybrox:</div>
<blockquote>
<p><strong>tl;dr</strong> : I really like <code>RUNTIME_CONFIG=config/myconfig.exs bin/myapp start</code></p>
</blockquote>
</aside>
<p>The problem with this approach, as far as I understand it, is that it does not solve the issue originally written in this proposal: which is the gap between Mix and releases. What you are proposing is that, once you assemble a release, you need to explicitly list all of the runtime configurations in a separate file, still causing confusion on why my release does not work and leading to duplication. For example, per your proposal above, imagine that I want to do this in a Phoenix app:</p>
<pre><code>config :my_app, Endpoint, port: System.get_env("PORT") || 9000
</code></pre>
<p>How would I make it work on both Mix and in a release? Does it mean that I have the line above in my <code>config/prod.exs</code> (which is compile time and Mix based) and then have the same line in a separate runtime config for releases?</p>
<aside class="quote no-group" data-username="sasajuric" data-post="53" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>No, but we could guide users to use approaches which make sense. I think that a lot of misuse of config scripts originates from the fact that generators promote them by default.</p>
</blockquote>
</aside>
<p>The config scripts are not the root cause. What is being misused is the application environment. The fault is in library authors using application environment or forcing compile time configurations when they don’t have to. If library authors don’t abuse the application environment, then the configuration issue is immediately solved because there will be nothing to configure. That’s why I am saying I would rather push the complexity to library authors. For users of libraries, configuration should be as simple as it gets.</p>
<aside class="quote no-group" data-username="sasajuric" data-post="53" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>Why should by default this data reside in config scripts, and why at runtime must it sit in a public global mutable storage in a separate memory space?</p>
</blockquote>
</aside>
<p>It doesn’t matter for this discussion. We had this discussion at the beginning of the thread. First, not everyone agrees with this line of thought (I can elaborate in a separate thread as I don’t think it belongs here). The second issue is that, regardless of how many libraries promote wrong usage of the application environment, we will still have valid use cases. We could talk about Phoenix all we want, but libraries like Logger and the MIME library still correctly use compile-time configuration, and for those libraries configuration should be as first class as possible.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82565" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/56">Post #55</a>
	                </div>
	            </div>
              <div id="likers-container-82565" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82565"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #55"></div>
  </section>
</div>
    <div class="postbit" id="82566" data-post-id="82566">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="56" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>The config scripts are not the root cause. What is being misused is the application environment.</p>
</blockquote>
</aside>
<p>But isn’t today the sole (or at least the main) purpose of config scripts to populate app env? What else are they used for?</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="56" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>First, not everyone agrees with this line of thought</p>
</blockquote>
</aside>
<p>It was not a line of thought, it’s an honest question. I seriously don’t get why should this be a recommended default?</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="56" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I can elaborate in a separate thread as I don’t think it belongs here</p>
</blockquote>
</aside>
<p>Yes please, I already opened a <a href="https://forum.elixirforum.com/t/rethinking-app-env/14315" rel="nofollow">separate thread</a> yesterday.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="56" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>libraries like Logger and the MIME library still correctly use compile-time configuration, and for those libraries configuration should be as first class as possible</p>
</blockquote>
</aside>
<p>I agree here. My impression is though that such situations are not all that frequent, and that config scripts are dominated by things which shouldn’t be there. I don’t have a significant sample though <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82566" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/57">Post #56</a>
	                </div>
	            </div>
              <div id="likers-container-82566" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82566"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #56"></div>
  </section>
</div>
    <div class="postbit" id="82569" data-post-id="82569">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cybrox" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cybrox/120/10045_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cybrox
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="56" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Does it mean that I have the line above in my <code>config/prod.exs</code> (which is compile time and Mix based) and then have the same line in a separate runtime config for releases?</p>
</blockquote>
</aside>
<p>No, I agree that duplication should be avoided and after thinking that approach through again, I can see the issues you pointed out. Especially the environment-dependent configuration in the <code>config/prod.exs</code> would cause a collision if it was just re-defined in an external config file.</p>
<p>After reading through the original proposal again, with the things discussed later on in mind, the idea is starting to grow on me. However, I still can’t help but think that it will become incredibly confusing for the user, especially if it is not implemented across all libraries consistently. Sensitise library authors for consistent usage is probably the single most important aspect to this proposal’s success.</p>
<p>Also, as <a class="mention" href="/u/hubertlepicki" rel="nofollow">@hubertlepicki</a> pointed out, I think the biggest challenge would be defining which values have to be changed on boot time. There are lots of obvious ones for sure, but also some gray areas.</p>
<p>Would <code>Application.Config</code> allow for incremental configuration? I very much like the idea of <code>config/config.exs</code> becoming a reference point for configurable options by setting all the required values and configurations loaded afterwards can overwrite these.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82569" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/58">Post #57</a>
	                </div>
	            </div>
              <div id="likers-container-82569" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82569"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #57"></div>
  </section>
</div>
    <div class="postbit" id="82570" data-post-id="82570">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="sasajuric" data-post="57" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>But isn’t today the sole (or at least the main) purpose of config scripts to populate app env? What else are they used for?</p>
</blockquote>
</aside>
<p>We only have to populate the app env because libraries read things from the app env. If libraries do not read from the app env, we won’t have anything to populate. Who is reading from the app env is the root issue, not who is writing to it.</p>
<p>Writing configuration (config.exs) should always be straight-forward. We can talk about ways to make library authors read from the env less frequently but that is a separate discussion.</p>
<aside class="quote no-group" data-username="cybrox" data-post="58" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cybrox/48/10045_2.png" class="avatar"> cybrox:</div>
<blockquote>
<p>Also, as <a class="mention" href="/u/hubertlepicki" rel="nofollow">@hubertlepicki</a> pointed out, I think the biggest challenge would be defining which values have to be changed on boot time. There are lots of obvious ones for sure, but also some gray areas.</p>
</blockquote>
</aside>
<p>Our goal with <code>on_boot</code> is to capture the user intent. It means the user would like those to be set at runtime. The user shouldn’t have to care what happens at compile time and what happens at runtime from the library side of things unless the user intent conflicts with the library behaviour. Ideally we will find ways in the future of checking the user intent with the actual implementation programatically.</p>
<aside class="quote no-group" data-username="cybrox" data-post="58" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cybrox/48/10045_2.png" class="avatar"> cybrox:</div>
<blockquote>
<p>Would <code>Application.Config</code> allow for incremental configuration? I very much like the idea of <code>config/config.exs</code> becoming a reference point for configurable options by setting all the required values and configurations loaded afterwards can overwrite these.</p>
</blockquote>
</aside>
<p>With we go with <code>on_boot</code>, that will continue to work the same as today. If we go with the original proposal, then we will need to slightly flip things around as outlined in the proposal.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82570" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/59">Post #58</a>
	                </div>
	            </div>
              <div id="likers-container-82570" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82570"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #58"></div>
  </section>
</div>
    <div class="postbit" id="82585" data-post-id="82585">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Qqwy" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Qqwy/120/1349_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Qqwy
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>TypeCheck Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I finally was able to find the time to read through this whole thread. The one thing everyone agrees on, is that the current way configuration happens could be improved. The exact opinions people then have about <em>how</em> to improve it and <em>what</em> to improve on exactly are then widely varying; I guess we might still for some of the proposed issues only be looking at a symptom rather than the underlying cause.</p>
<p>Of course, the proposal at hand is only about one single thing (there not being a real way to do currently writing runtime configuration for releases), so let me focus on that one now in more detail. The other issues that have been discussed so far (what to (not) put in a configuration file, other ways to configure an application, how applications ought to read configuration settings that the user put in, and some others) are I think very important, but definitely fall outside of this thread’s intended subject matter.</p>
<hr>
<p>It is an unmistakable fact that an Elixir project is first compiled, and then run. In some cases, the environment that the application is compiled on is different from the environment where the application is run. This is true for at least releases and Nerves projects. In all cases (not only in these two), both of these steps (compilation and booting+running) happen. Even when we run a project in a Mix project, it is first compiled and only then executed. However, since we usually happen to still be in the same folder with the same files (+environment) available, we can accidentally (e.g. without being conscious about it) depend in our run-time on things we decided during compile-time: re-use our configuration.</p>
<p>So currently, Mix configuration happens in both places in Mix projects because it works ‘by happy circumstance’ also during application startup, but it does not in the other cases (actually, I think this is regardless of the fact of having Mix still available to us at runtime or not, because we cannot depend on the locations of files or other things anymore when the runtime environment(/machine) is different from the compilation environment(/machine)).</p>
<p>To me, it thus feels like the current behaviour is implicit, and it can be made more explicit by making it clear that the difference between compile-time configuration and run-time configuration exists (and has always existed!) and needs to be kept in mind.</p>
<p>The two proposals we currently have, <code>Application.Config</code> and <code>on_boot</code> both only address this problem partially:</p>
<ul>
<li>
<p><code>Application.Config</code> solves the problem of <code>Mix</code> not always being available, but hides the fact that compile-time and run-time configuration might be different (or, maybe clearer phrasing: that some beam-applications might read parts of the configuration during compile-time and some others during boot-up or runtime).</p>
</li>
<li>
<p><code>on_boot</code> makes it more clear that certain pieces of configuration will only be executed during boot-up/runtime, but to be honest it does not feel very clean to me because of the following fact: It seems to indicate that something <em>different</em> needs to happen during boot-up/runtime rather than the compile-time configuration outside of it. it is the word <em>different</em> that I have issue with here.</p>
</li>
</ul>
<p>It feels to me that the ‘default’ of an application would be to read the configuration settings during boot-up/runtime, and only if the application requires special behaviour to happen during compilation-time (because of time- or space-optimizations), then <em>this</em> is where we would opt-in into a special compile-time configuration block, rather than compile-time being the default and opting-in into a special run-time configuration block.</p>
<p>It is only a thought however, because I do see that with the way how configurations currently work (Releases can act on config during compile-time but not during boot-up/runtime), that it might be difficult to build it with this order of specialization (compile-time config being a specialization of run-time config) in mind. But I do think that it is important to mention this, because personally, <code>on_compile</code> feels clearer to me than <code>on_boot</code>.</p>
<hr>
<p>But besides this, in essence I think the problem is not that ‘releases are broken’ but rather that Mix is able to pretend that the difference between compile-time and run-time configuration does not exist. So rather than building a ‘fix’ for releases, I think that improving on Mix’ behaviour to make it more clear that there <em>is</em> (and always has been) a difference is the way to go.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82585" data-batch-url="/posts/batch_likers">
                        15
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/60">Post #59</a>
	                </div>
	            </div>
              <div id="likers-container-82585" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82585"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="82609" data-post-id="82609">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="arturcygan" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/arturcygan/120/10050_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  arturcygan
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>At first I was quite enthusiastic about bringing mix config and releases closer together. I’ve struggled quite hard when we started with releases and getting nils on production from the <code>System.get_env/1</code> in prod.exs was very confusing. But now after giving it some thought, I’m no longer sure if we actually need to close the gap between mix project and a release. A release is a fundamentally different thing, it is not a project on a development machine, it is a build artifact with different structure, ready to be deployed on a production server. Whether the development team or a separate ops team operate the release I believe loading the prod mix config on the server provides a little value for them. Mix is a build tool and configs in <code>config/</code> directory are build configs. So I agree with Michał here:</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="17" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>I don’t agree with the premise that mix config is for operator configuration - it is most definitely not. Things that are usually operator configuration - API keys, component addresses should not go in there.</p>
</blockquote>
</aside>
<p>Instead of trying to make mix project and release transparent maybe we should embrace and document their differences? Better education on the topic, release tooling and defaults which guide a newcomer.  Take the <code>config/prod.secret.exs</code> for example. It is very strong suggestion that we should deploy a source code to the server, not a release, because only mix can load this config file. Making the build config a hybrid with a runtime config will maybe make the initial deploys a bit easier but in a longer run it might be even more confusing than the current situation.</p>
<p>I believe we need to treat runtime config seriously and explicitly, without ad-hoc solutions. If you look at most of services (like postgres, nginx etc.) we use, they provide strict configuration through external measures (file, env vars) which has well defined interface. Are the applications we build different?</p>
<p>What about the following solution? There is a <code>sys.config</code> which could be treated as static “readonly” config, a transpiled <code>prod.exs</code> with “safe defaults”. Loading configuration might grow to complex strategies as mentioned by OvermindDL1 and needs dedicated flexible approach with different backends forming fallback stack. Backends should be coded and tested as regular code, as they are general system ↔ operator (this can be even us during development) contract. In <code>dev.exs</code> and <code>test.exs</code> we can disable all the backends because we can simply put config “straight” from the mix config and enable in <code>prod.exs</code> config (this is a compile time decision). This would require injection in early stages of execution to put config from backends before the system starts (similarly as mix does). In case of enabling config backends in mix project, mix config provides a base which will be overrided by config backends, while running a release the base would be <code>sys.config</code>.</p>
<p>This is an awesome community discussion! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82609" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/61">Post #60</a>
	                </div>
	            </div>
              <div id="likers-container-82609" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82609"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #60"></div>
  </section>
</div>
    <div class="postbit" id="82617" data-post-id="82617">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ConnorRigby" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ConnorRigby/120/5964_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ConnorRigby
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Nerves Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><img src="https://forum.elixirforum.com/images/emoji/apple/wave.png?v=15" title=":wave:" class="emoji" alt=":wave:" loading="lazy" width="20" height="20"> I’m the primary author of the FarmbotOS Nerves project. I’m still reading thru this entire thread, but i also agree that Elixir has issues with configuration. I had always that was inherited from Erlang, since it suffers many of the same problems.</p>
<p>The following are my opinions on what I’ve read so far as an end user of the Mix/config system in varying use cases. I apologize in advance if it is a little jargony feel free to ask and i will try to clarify anything. I’ve separated it this way to make a point. Right now the current <code>Mix.Config</code> system is applicable to all of these very different deployment strategies, and being so I do not believe there will be a system that 100% envelops all of them.</p>
<h3><a name="p-82617-building-a-nerves-based-project-1" class="anchor" href="#p-82617-building-a-nerves-based-project-1" aria-label="Heading link" rel="nofollow"></a>Building a Nerves based project</h3>
<p>This is one of the situations i spend most of my time, and it may be a bit long winded.<br>
As the original post described I’ve had to do some weird things as to suit application requirements. One example of this is retrieving things<br>
in <code>Mix.Project.config()</code> such as:</p>
<ul>
<li>application version</li>
<li>application environment (<code>dev</code>, <code>prod</code>, <code>test</code> etc)</li>
<li>nerves target (<code>host</code>, <code>rpi3</code>, <code>my_custom_hardware</code>, etc)</li>
</ul>
<p>Now since those <em>are in fact</em> compile time things, it might look weird that i have a separate module tracking their values, this comes back to a shortcoming in Nerves currently - we don’t have a code reloader yet, so during development, i frequently do something a little scary that i wont go into detail here. The gist of it is that if i recompile a module while working on a nerves device, Mix is not available, so those fields are also not available.</p>
<p>The other thing that i would like to point out is that in my Nerves based projects i often find the need to not only retrieve config at runtime but also set it. For the most part i use something like Ecto/Sqlite for this, but i do have a bad habit of storing data globally in <code>Application.put_env</code> and getting it with <code>Application.get_env</code>. A tangible example of this is interfacing with hardware. Elixir lends itself to behaviours for hardware nicely. In the Farmbot project we interface with a UART device. it’s not always possible to have the device plugged in during development so doing something along the lines of <code>Application.get_env(:farmbot, :firmware_handler)</code> works really well. I can listen for the device being plugged in, replace that value with the <code>Firmware.UARTHandler</code> module and restart the firmware stack. When it’s unplugged, replace the value with <code>Firmware.StubHandler</code>. You get the idea. Now is reconfiguration at runtime something that Mix/this new thing needs to handle or even be aware of? i don’t know to be honest, but this <em>does</em> feel hacky to me anyway.</p>
<p>Those are the two main experiences i have with configuration of Nerves projects.</p>
<h3><a name="p-82617-building-a-library-specifically-targeting-nerves-projects-2" class="anchor" href="#p-82617-building-a-library-specifically-targeting-nerves-projects-2" aria-label="Heading link" rel="nofollow"></a>Building a library specifically targeting Nerves projects</h3>
<p>This section encapsulates projects such as <a href="https://github.com/nerves-project/nerves_network" rel="noopener nofollow ugc"><code>nerves_network</code></a>, <a href="https://github.com/nerves-project/nerves_init_gadget" rel="noopener nofollow ugc"><code>nerves_init_gadget</code></a> and the like. This is usually where i experience the most pain and it is not particularly the fault of Mix.Config, but it does allude to a big picture issue i have with Elixir/Erlang libraries. There are <em>to many</em> ways to configure an application, and end users of the library often expect to be able to configure how they see fit. Let’s take <code>nerves_network</code> as an example.</p>
<p>you can configure Nerves network in two different ways.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">use Mix.Config

config :nerves_network, :default, [
   eth0: settings
]
</code></pre>
<p>or you can do</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex()&gt; Nerves.Network.setup(:eth0, settings)
</code></pre>
<p>This is a nightmare handle as a library developer.</p>
<h3><a name="p-82617-building-a-general-use-elixir-library-3" class="anchor" href="#p-82617-building-a-general-use-elixir-library-3" aria-label="Heading link" rel="nofollow"></a>Building a general use Elixir library</h3>
<p>The Nerves specific issue i denoted above applies here, but I’ve found it is less of an issue for generic libs. One issue i have with this use case is that lib developers frequently use sub dependencies. If those sub dependencies need configuration, it is forced upon the end user of your library to configure them.</p>
<h3><a name="p-82617-building-a-generic-elixir-application-4" class="anchor" href="#p-82617-building-a-generic-elixir-application-4" aria-label="Heading link" rel="nofollow"></a>Building a generic Elixir application</h3>
<p>To me this is where the current system shines in my opinion. I don’t have many complaints with the caveat that i don’t usually “deploy” these applications. (so no distillery, or similar).</p>
<h3><a name="p-82617-building-a-phoenix-based-project-5" class="anchor" href="#p-82617-building-a-phoenix-based-project-5" aria-label="Heading link" rel="nofollow"></a>Building a Phoenix based  project</h3>
<p>I don’t have the most experience with Phoenix, but I do work on two production apps. One deployed on Heroku, one deployed on Gigalixir. Both share a common issue of using environment variables to replace the things in <code>Mix.Config</code>.</p>
<h1><a name="p-82617-closing-thoughts-6" class="anchor" href="#p-82617-closing-thoughts-6" aria-label="Heading link" rel="nofollow"></a>Closing thoughts</h1>
<p>After rereading this post it seems like i’m just crying and i don’t really have any offered solutions or ideas. Truth be told i don’t actually know what my ideal api would be for each of the listed use cases and i don’t actually believe there is one all encompassing api that would handle all of them 100%. There is certainly going to be trade offs and balances to be struck. I’m afraid that changing the current system will only fragment the issue rather than push toward a good solution for everyone.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82617" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/62">Post #61</a>
	                </div>
	            </div>
              <div id="likers-container-82617" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82617"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #61"></div>
  </section>
</div>
    <div class="postbit" id="82625" data-post-id="82625">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-Nerves-Core-Team" data-username="ConnorRigby" data-post="62" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/connorrigby/48/5964_2.png" class="avatar"> ConnorRigby:</div>
<blockquote>
<p>Elixir lends itself to behaviours for hardware nicely. In the Farmbot project we interface with a UART device. it’s not always possible to have the device plugged in during development so doing something along the lines of <code>Application.get_env(:farmbot, :firmware_handler)</code> works really well. I can listen for the device being plugged in, replace that value with the <code>Firmware.UARTHandler</code> module and restart the firmware stack. When it’s unplugged, replace the value with <code>Firmware.StubHandler</code> . You get the idea.</p>
</blockquote>
</aside>
<p>This is totally fine. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote group-Nerves-Core-Team" data-username="ConnorRigby" data-post="62" data-topic="14302">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/connorrigby/48/5964_2.png" class="avatar"> ConnorRigby:</div>
<blockquote>
<p>This is a nightmare handle as a library developer.</p>
</blockquote>
</aside>
<p>Yes! Libraries should only require application configuration if strictly necessary. Our recent library guideline discusses this: <a href="https://hexdocs.pm/elixir/master/library-guidelines.html" rel="nofollow">https://hexdocs.pm/elixir/master/library-guidelines.html</a></p>
<p>If the user of your library wants to use the app environment, that should be their choice. Library authors shouldn’t impose them.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82625" data-batch-url="/posts/batch_likers">
                        5
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302/63">Post #62</a>
	                </div>
	            </div>
              <div id="likers-container-82625" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82625"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #62"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/14302/load_more?page=7">Load more posts</a>
</div></template></turbo-stream>