TOML different headers for different contexts

I would like to use basic-auth on all deployments EXCEPT production. This has been covered before by Selective Password Protection but that involves copying the _headers file during build which is a bit messy:

  • Requires multiple configuration files (netlify.toml, _headers) so you can’t know the complete configuration by looking at the TOML file. (Aside from a comment).
  • Requires an extra step in every build, has to be set up in every repository.
  • If you want some common headers and some unique headers, I’m not sure what the optimum settings would be? Shared headers in .TOML and different _headers files for production and others?

Ideally we would be able to nest [[headers]] within [context...] sections in netlify.toml, and Netlify would choose the appropriate value for a given header following the same override hierarchy as other settings.

I tried a couple different formats in netlify.toml but was unable to find something that worked, and the docs don’t speak to nesting headers. Is there something I’m missing, or is it just not possible?

Hi @df-1, you can modify headers and redirect in the toml file at build time using something like sed and your header can be set in an ENV VAR. For example:

sed -i s/HEADER_PLACEHOLDER/${BASIC_AUTH_HEADER}/g netlify.toml && yarn build

Let me know if that works for you.

1 Like

@df-1 100% agreed that something like…

context.branch-deploy.headers
context.branch-deploy.headers.values

Would be amazing

2 Likes

Hi,

We agree, and we have an open feature request that I’ve added your info to so we’ll let you know as soon as we have more information on this!

2 Likes

Hi @Dennis @futuregerald

I just wanted to follow up on this to make sure I’m doing it as you would expect. I have my headers for basic auth setup with a key placeholder:

  for = "/*"
    [headers.values]
      BASIC_AUTH_PLACEHOLDER = "user:password"

an environment variable set as:

environment = { BASIC_AUTH = "Basic-Auth" }

and an example of the command is:

[context.branch-deploy]
  command = "sed -i s/BASIC_AUTH_PLACEHOLDER/${BASIC_AUTH}/g netlify.toml && yarn build

I originally had the header like so:

for = "/*"
    [headers.values]
      Basic-Auth = BASIC_AUTH_USER_PASSWORD

but this was still setting a basic auth for all deploy contexts and the branch deploy had the username and password working okay but all the other context would have nothing set for their username and password so I couldn’t get access.

I now have it working as expected but I just wanted to double check the way I have done it is correct or is there a better way to do this in the netlify.toml file? I specifically wanted to double check that having a blank key on the non branch deploys wasn’t going to cause any unforeseen consequences.

Cheers

I’d probably do this differently, as documented in our article on the topic:

You definitely don’t have to use make and sed, but you DO need to:

  • set per-context build commands to manage your headers differently (I like “no headers” by default and applying the headers in branch deploys and/or deploy preview contexts, but you can do it however you like)
  • keep that header in _headers rather than in netlify.toml, since there are no context-specific headers; everything in that file is used for every deploy, as you found :slight_smile:
1 Like

Thank you for the pointers @fool, I’m getting a better understanding of how to customise the config more to my needs.

I’ve moved my build commands out into rake commands which is simplifying the toml file itself and also getting rid of a lot of the code repetition I was getting with the various build contexts.

Now I have removed that context specific header and my branch context command looks as follows:

command = "rake netlify_build:branch"

My rake file is then similar to:

namespace :netlify_build do
  desc "Run build commands on Netlify"

  add_non_production_headers = "cp config/netlify/non_production_headers public/_headers"
  yarn_test = "yarn test"
  rspec_test = "RUBYOPT=-W0 parallel_rspec -n 2 spec"
  middleman_build = "NO_CONTRACTS=true RUBYOPT='-W0' middleman build"

  task :production do
    sh "#{yarn_test} && #{rspec_test} && #{middleman_build} --verbose"
  end

  task :branch do
    sh "#{add_non_production_headers} && #{yarn_test} && #{rspec_test} && #{middleman_build} --verbose"
  end

  task :cms, [:build_option] do |_task, args|
    sh "#{add_non_production_headers} && #{middleman_build} #{args[:build_option]}"
  end
end

I have all my headers that are shared with every context within the toml file. Then, before the build I am copying the additional headers I need per context into the _headers file.

1 Like