Skip to content
This repository has been archived by the owner on Apr 23, 2019. It is now read-only.

Allow customization of nginx files #97

Open
michiels opened this issue Aug 20, 2014 · 5 comments
Open

Allow customization of nginx files #97

michiels opened this issue Aug 20, 2014 · 5 comments

Comments

@michiels
Copy link
Member

On some servers I have some custom configuration for nginx that cannot be handled abstractly by chef-repo or any other automated piece of software.

I think it would be a good idea to add include (http://nginx.org/en/docs/ngx_core_module.html#include) directives to each virtual host in the nginx config so people can customize their own domain name setups with custom rewrites, PHP sites, redirects or directory indexes. I currently use this for:

  • Proxying subURIs to WordPress (https://intercityup.com/blog/ is an example)
  • Setting specific SSL protocols
  • Serving assets from another location

Implementation would be pretty simple at first hand. We provide something like /etc/nginx/custom/<domain_name>.custom.confthat people can then edit themselves.

@michiels
Copy link
Member Author

Here's a Gist illustrating this with a sample from our server: https://gist.github.com/michiels/56e64dad9ecb21150de2

@berkes
Copy link
Collaborator

berkes commented Oct 20, 2014

The way I had this solved was to include all files from a few directories. This does slow down nginx-booting but not so much nginx after that (other than nginx having more rules, directives and whatnot to cover, slowing it down anyway; I guess that nginx simply keeps a compiled version of the file with all included files).

There's two things that might need to be covered:

  1. Including config files at particular places in the file.
  2. Reloading nginx on placement or changing of one of the included file (causing potentially a lot of reloads)

By placing all includes under the /u/apps/examplecom/shared/nginx directory, you can keep the application nicely contained. It is immediately clear that confs placed there will be included only in that applications vhost.

By adding a few subdirectories there, you can make sure that a certain files gets included only in certain parts of the vhost:

  • ./main included in the main, http, config.
  • ./ssl included in the https config.
  • ./app, stuff to be included in the @app{}-block (e.g. cookie-settings, etc.)
  • ./upstream, stuff added in the main upstream block (with unicorn/puma)

Problem is that after placing a file there, you need to give nginx a kick in order to reload and take your new/edited file. An alternative would be to manage these files with chef too, but that could potentially become a quite complex set of mirrored directory-trees in the local chef-repo.

See an example, edited from your sample: https://gist.github.com/berkes/a6ec56af9a3714453248

@berkes
Copy link
Collaborator

berkes commented Nov 13, 2014

I've just implemented a somewhat modified version, and sent that in as PR. Please let met know what you think of this direction. If this is the right direction, I'll create some tests and add some documentation in the wiki about when to use what custom-categories.

case at hand: I am moving a webshop from a dutch environment to become an english shop: a lot of paths will change. They need redirects, so I've got to add a bunch of lines with these redirects into the http and https server block.

This PR does a little more, since it allows users to place custom config before and after the template, and in several places inside the template.

I've chosen to follow the default that chef-repo already has: to include the contents in the json (rather than pointing to files and/or including these files). I had that implemented first, but that is somewhat awkward especially when you have multiple node configuration files and several apps in there; it then becomes a gigantic spagetti of files and includes of these files. Just to include a few redirects on the correct place.

Here's an example of what I'd have in the node-configuration:

    "nginx_custom": {
      "server_main": "rewrite ^/t/accessoires$ http://shop.example.com/t/small-leather-goods;\n"
    }

Other configs that are possible:

    "nginx_custom" => {
      "before" => "",
      "server_main" => "",
      "server_app" => "",
      "server_ssl"  => "",
      "server_ssl_app" => "",
      "upstream" => "",
      "after" => "",
    }

@michiels
Copy link
Member Author

@berkes Thanks for the awesome work and research so far.

I liked your approach in providing default file locations for putting custom nginx configuration files that could be app-specific. Putting the text in the chef-repo allows you to make it versioned and create custom callbacks (like reloading nginx). If you create custom files in the app directories, you would have to copy them over to new servers if you want to migrate or scale.

Since you've tried both approaches so far. Would your opinion be to take your last approach like you mention in the last sample of the nginx_custom key?

@berkes
Copy link
Collaborator

berkes commented Nov 24, 2014

Since you've tried both approaches so far. Would your opinion be to take your last approach like you mention in the last sample of the nginx_custom key?

Untill the moment that chef-repo has a more generic way to deal with files, I'd say the best option is to include the contents of a file in the node.json.

In my current approach, I went for the simplest solution that works: include content in the config.json, and have it write out that content in the template. So no new files and such.

I've tried with new files, and the result is theoretically nicer, but for all my cases way too complex. Debugging becomes really hard, since you have to hunt all over the disk on a server to find a broken file.

One case, where I needed about 30 rewrite rules would have been nicer with a file-based approach. But in this case I made a workaround: one custom recipe that uploads my rewrites.conf into a directory (/u/apps/example.com/shared/conf/rewrites.conf) and then in the nodes.json:

"nginx_custom": {
  "server_main": "include /u/apps/example.com/shared/conf/rewrites.conf;"
}

I think I like this approach most: because it is so simple, it is very predictable. Having chef-create all sorts of tiny files and when created, including these in the vhost file, makes it a lot more complex and harder to understand.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants