# vim: ts=2 sw=2 et ft=org
#+STYLE: <LINK href="stylesheet.css" rel="stylesheet" type="text/css" />
#+TITLE: Configuration Options
#+AUTHOR: Jesse Gumm (@jessegumm)
#+OPTIONS:   H:2 num:1 toc:1 \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
#+EMAIL: 

#+TEXT: [[file:./index.org][Getting Started]] | [[file:./api.org][API]] | [[file:./elements.org][Elements]] | [[file:./actions.org][Actions]] | [[file:./validators.org][Validators]] | [[file:./handlers.org][Handlers]] | *Configuration Options* | [[file:./about.org][About]]
#+HTML: <div class=headline>Configuration Options</div>

* Configuration Overview

  Nitrogen configuration is done in a handful of different configuration files,
  and also varies slightly between backend servers. All of these files are found
  in the =etc/= directory of your Nitrogen installation.  Below we will go though
  the configuration options provided within each.

* Univeral Configuration Files (configs available in all Nitrogen intallations)

** etc/vm.args

  This is the file that sends sends options to the Erlang Virtual Machine.
  Basically, any of the usual 
  [[http://www.erlang.org/doc/man/erl.html][erl startup parameters]] will work
  here.  You'll define some standard options here, such as the node name,
  (=-name=), erlang cookie (=-cookie=), some miscellaneous environment options,
  and of course, to tell the system to launch the Nitrogen application upon
  startup.

  Here is the complete text of the default vm.args:

  #+BEGIN_SRC bash
    ## Name of the Nitrogen node
    -name nitrogen@127.0.0.1

    ## Cookie for distributed erlang
    -setcookie nitrogen

    ## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
    ## (Disabled by default..use with caution!)
    ##-heart

    ## Enable kernel poll and a few async threads
    +K true
    +A 5

    ## Increase number of concurrent ports/sockets
    -env ERL_MAX_PORTS 4096

    ## Tweak GC to run more often
    -env ERL_FULLSWEEP_AFTER 10

    ## If you run the sync application, this will switch it to
    ## nitrogen_mode for proper include file detection
    -sync sync_mode nitrogen

    ## Include .beam files for site.
    -pa ./site/ebin

    ## Include .beam files for dependencies.
    -pa ./deps/*/ebin

    ## Run code at startup.
    -eval "application:start(nitrogen)"
  #+END_SRC

** etc/app.config

  This file contains the configuration options for the Nitrogen application
  itself. It uses the standard Erlang config syntax: (a proplist of 
  ={applicationName, AppOptions}=).

  For the =nitrogen= application, the following =AppOptions= are recognized:

    + =signkey= - (/String/) :: =signkey= is the term that Nitrogen usees to "sign" the state information
      that's sent to the client, and then resent back to the server with requests.
      While Nitrogen's state info is not encrypted, this is used to help verify
      that the term generated is actually generated by Nitrogen, to prevent
      client-side tampering with the state.
    
    + =session_timeout= - (/integer/) :: =session_timeout= is the number of minutes
      a session can be idle before Nitrogen expunges it from memory
    
    + =cookie_name= - (/string/) :: =cookie_name= is the name of the HTTP Cookie to
      be used as the sesson tracking cookie. This is not to be confused with the
      Erlang Cookie, which is defined in the vm.args file above.
      
      Also typically defined in the app.config file here is the
      [[http://www.erlang.org/doc/man/sasl_app.html][SASL Configuration]], the
      default of which for Nitrogen can be seen here:
    
    + =module_prefix= - (/string/) :: This provides the user with the ability to
      route all Nitrogen web requests to modules that all share the same prefix. For
      example, if =module_prefix= was set to "abc", then a request for /mypage would
      be directed to the module "abc\_mypage".


  #+BEGIN_SRC erlang
      {sasl, [
          {sasl_error_logger, {file, "log/sasl-error.log"}},
          {errlog_type, error},
          {error_logger_mf_dir, "log/sasl"},      % Log directory
          {error_logger_mf_maxbytes, 10485760},   % 10 MB max file size
          {error_logger_mf_maxfiles, 5}           % 5 files max
      ]}
  #+END_SRC

** Notable mention: rebar.config

  The standard for Erlang distribution and building is the use of Basho's
  [[http://github.com/basho/rebar][rebar]]. Nitrogen takes advantage of this for
  simplifying the process of making releases and compiling Nitrogen even after
  a release is built and deployed.

  Generally, the main reason one would want to customize their installation is by
  adding additional dependency packages.  For example, if you wanted to include
  the [[https://github.com/erlware/erlware_commons][erlware\_commons]] package for
  improved date parsing and formatting, or the 
  [[https://github.com/shane42/erls3][erls3]] package to give your app an
  interface to Amazon S3, you would typically do it by adding the dependencies to
  rebar.config then running =make= in your Nitrogen installation.

  By default, the only dependencies are the core dependencies for Nitrogen:
  nitrogen\_core, nprocreg, sync, simple\_bridge, and a webserver (Yaws, Cowboy,
  etc).

  Also contained within the rebar.config are a handful of other compilation
  options: minimum Erlang version, where dependencies go, and debugging options.

  Below is the rebar.config file when used with webmachine:

  #+BEGIN_SRC erlang
  {sub_dirs, [
      "site",
      "deps"
  ]}.

  {require_otp_vsn, "R13B04|R14|R15"}.

  {cover_enabled, true}.

  {erl_opts, [debug_info, fail_on_warning]}.

  {deps_dir, ["lib"]}.

  {deps, [
      {webmachine, "1.8.*", {git, "git://github.com/basho/webmachine.git", {tag, "webmachine-1.8.1"}}},

      {nitrogen_core, "2.1.*", {git, "git://github.com/nitrogen/nitrogen_core", "HEAD"}},
      {nprocreg,      "0.2.*", {git, "git://github.com/nitrogen/nprocreg", "HEAD"}},
      {simple_bridge, "1.2.*", {git, "git://github.com/nitrogen/simple_bridge", "HEAD"}},
      {sync,          "0.1.*", {git, "git://github.com/rustyio/sync.git", "HEAD"}}
  ]}.
  #+END_SRC

  To add the above mentioned dependencies (=erlware_commons= and =erls3=), edit
  the rebar.config file and modify the =deps= list to look like this:

  #+BEGIN_SRC erlang
  {deps, [
      {webmachine, "1.8.*", {git, "git://github.com/basho/webmachine.git", {tag, "webmachine-1.8.1"}}},

      %% Add our two new dependencies below
      {erls3, "1.9.*", {git, "git://github.com/shane42/erls3.git", "HEAD"}},
      {erlware_commons, ".*", {git, "git://github.com/erlware/erlware_commons.git", "HEAD"}},

      {nitrogen_core, "2.1.*", {git, "git://github.com/nitrogen/nitrogen_core", "HEAD"}},
      {nprocreg,      "0.2.*", {git, "git://github.com/nitrogen/nprocreg", "HEAD"}},
      {simple_bridge, "1.2.*", {git, "git://github.com/nitrogen/simple_bridge", "HEAD"}},
      {sync,          "0.1.*", {git, "git://github.com/rustyio/sync.git", "HEAD"}}
  ]}.
  #+END_SRC

  Then run =make= from the root of your Nitrogen installation. This will download
  the new dependencies and install them into the =lib= directory of your
  installation.


* Server-specific Configuration (in alphabetical order)

** Common Configurations:

  In most of the configurations below, you'll find some general running themes.
  Almost all of the servers take same basic set of core instructions to for
  initialization and address binding, as well as some way to notify Nitrogen
  and SimpleBridge where to find static files.  These universal configuration
  settings are below:

    + =bind_address= - (/String/) :: The string of the IP address to bind.  If set to "0.0.0.0" or left blank, it'll
      bind to all available addresses. (Default: ="0.0.0.0"= )

    + =port= - (/Number/) :: The port number to bind. (Default: =8000=)

      *About Ports and Linux*: While port 80 is the standard HTTP port,port 80 is a
      privileged port in a Linux/Unix environment. This means that in order for
      Erlang to bind to port 80, it will need to be run with *root* privileges. This
      is generally unadvised. Instead, we recommend using a lightweight reverse
      proxy (such as nginx) in front of Nitrogen. Doing so will allow you to run
      Nitrogen with standard user privileges (for better system security), while
      presenting your Nitrogen website on the expected port 80.

      On some variants of Linux, it is possible to bind Nitrogen to port 80 without
      running as root. This is accomplished with the use of the
      [[http://linux.die.net/man/8/setcap][=setcap=]] application (which may need to
      be installed from your distro's package system).

      An example of =setcap= being run on your Erlang app:

      #+BEGIN_SRC bash
        sudo setcap cap_net_bind_service+ep ./erts-5.9.2/bin/beam
        sudo setcap cap_net_bind_service+ep ./erts-5.9.2/bin/beam.smp
      #+END_SRC

      This will give the =beam= and =beam.smp= programs privileges to bind to
      privileged ports (ports under 1024).

    + =server_name= - (/Erlang term/) :: What to name the server. (Default: =nitrogen=)

    + =document_root= - (/String/) :: The root of the location of static resources (ie, stylesheets, javascript
      files, images, etc). This will be passed to simple\_bridge for the serving of
      static files. (Default: ="./site/static"= )

      *Note:* this is relative to the root of the Nitrogen installation.

** Cowboy: etc/cowboy.config

  [[http://github.com/extend/cowboy][Cowboy]] is the web server made by
  [[http://twitter.com/lhoguin][Loïc Hoguin]]. The configuration for Cowboy
  provided with Nitrogen isn't the /official/ configuration file, but it works
  for our purposes.  The options we provide are read by Nitrogen and passed to
  the Cowboy server upon initialization.

  The default Cowboy configuration is as follows:

  #+BEGIN_SRC erlang
  [
      {cowboy,[
          {bind_address,"0.0.0.0"},
          {port,8000},
          {server_name,nitrogen},
          {document_root,"./site/static"},
          {static_paths, ["js/","images/","css/","nitrogen/"]}
      ]}
  ].
  #+END_SRC

  + =static_paths= - (/List of Strings/)

    This setting will be used to determine if a requested resource should be
    handled by Nitrogen and simple\_bridge, or if it should just be immediately
    served directly by the Cowboy server. 
    (Default: =["js/","images/","css/","nitrogen/"]=)

     *Note 1:* This is relative to the =document_root= above. So requests for =js/=
    will be served from =./site/static/js/= (using the default above).

     *Note 2:* it is *strongly* recommended to catch static files with the
    =static_paths= setting. simple\_bridge does not serve large static files in an
    optimal way (it loads the files into memory completely before sending).

** Inets: etc/inets.config and etc/inets\_httd.erlenv

  [[http://www.erlang.org/doc/man/inets.html][Inets]] is the web client and
  server included with the standard Erlang Install, and we use the Inets Web
  server as the "simple" solution for Nitrogen. Inets isn't as feature-rich as
  the other popular Erlang webservers, and because of this, we only recommend
  using Inets for development purposes, since it doesn't require any additional
  installation.

  Further, the Inets configuration is broken into two different files, one for
  the =inets= application itself, and one for the httpd server included in Inets.

**** etc/inets.config

  This is the file for configuring the =inets= application itself. By default, we
  simply use this file to tell the application to start the httpd and load the
  specified configuration file.

  The default inets.config provided with Nitrogen is as follows:

  #+BEGIN_SRC erlang
  [{inets, [
      {services, [
          {httpd, [
              {proplist_file, "./etc/inets_httpd.erlenv"}
          ]}
      ]}
  ]}].
  #+END_SRC

  Note that basically all it does it tell =inets= to load the inets_httpd.erlenv
  proplist file, using the =proplist_file= option.

**** etc/inets\_httpd.erlenv

  This file does the heavy lifting of configuring our inets configuration.

  #+BEGIN_SRC erlang
  [
      {port, 8000},
      {bind_address, {0,0,0,0}},
      {server_name, "nitrogen"},
      {server_root, "."},
      {document_root, "./site/static"},
      {error_log, "./log/inets.log"},
      {modules, [nitrogen_inets]},

      {mime_types, [
          {"css", "text/css"},
          {"js", "text/javascript"},
          {"html", "text/html"}
      ]}
  ].
  #+END_SRC

  + =bind_address= - (/IP Address as a 4-tuple/) :: Note that the =bind_address=
    for Inets is different than for the rest of the servers in that it expects the
    address to be in the form of a 4-tuple for example, instead of specifying the
    string (ie ="12.34.56.78"=, you would specify ={12,34,56,67}=).

  + =error_log= - (/String/) :: The name of the file to store the inets logs.

  + =modules= - (/List of module names/) :: For each request, Erlang will attempt
    to call =ModuleName:do/1= for each specified module. Typically, we just put in
    the atom =nitrogen_inets= as that's the default Nitrogen entry point for inets.

  + =mime_types= - (/[{Extension,Mimetype},...]/) :: This is simply a list of the
    Mime Types you wish to support along with the extensions that trigger those
    mime types. By default, it supports css, javascript, and html files. More types
    will have to be added by the user.


** Mochiweb: etc/mochiweb.config

  [[http://github.com/mochi/mochiweb][Mochiweb]] is a webserver written by Bob
  Ippolito. It's a very lightweight webserver and very easy to configure.

  The default configuration file for Mochiweb provided by Nitrogen is as follows:

  #+BEGIN_SRC erlang

  [{mochiweb, [
      {bind_address, "0.0.0.0"},
      {port, 8000},
      {server_name, nitrogen},
      {document_root, "./site/static"},

      %% Max Request size of 25MB. While this is a mochiweb env_var,
      %% it's actually only used in simple_bridge
      {max_request_size, 26214400}
  ]}].
  #+END_SRC

  + =max_request_size= - (/Integer/) :: Tells Mochiweb (in particular, it tells
    SimpleBridge) what the maximum request size to be honored. This is in bytes.
    The current default is 25 MB maximum request size.

** Webmachine: etc/webmachine.config

  [[http://wiki.basho.com/Webmachine.html][Webmachine]] is a web server written
  by [[http://basho.com][Basho]] (the makers of Riak), and it provides functions
  to specify detailed dispatch rules.

  The basic config file provided for Webmachine is very simple and minimal (it's
  basically the same as the one for cowboy)

  #+BEGIN_SRC erlang
  [{webmachine, [
      {bind_address, "0.0.0.0"},
      {port, 8000},
      {document_root, "./site/static"},
      {server_name,nitrogen},
      {static_paths, ["js/","images/","css/","nitrogen/"]}

  ]}].
  #+END_SRC 

  + =static_paths= - (/List of Strings/) :: Used to determine if a requested resource should be
    handled by Nitrogen, or if it should just be immediately served directly by
    Webmachine. (Default: =["js/","images/","css/","nitrogen/"]=)

    *Note 1:* This is relative to the =document_root= above. So requests for =js/=
    will be served from =./site/static/js/= (using the default above).

    *Note 2:* it is *strongly* recommended to catch static files with the
    =static_paths= setting. simple\_bridge does not serve large static files in an
    optimal way (it loads the files into memory completely before sending).

**** More Webmachine Dispatch Rules: site/src/nitrogen\_sup.erl

  Webmachine also provides a dispatch table to allow you to specify how requests
  are handled (beyond the basics covered by Nitrogen and the configuration
  above). If you're interested in diving into that, check out the
  =site/src/nitrogen_sup.erl= file in your Nitrogen installation.

** Yaws: etc/yaws.config

  [[http://yaws.hyber.org][Yaws]] is a high performance webserver created by
  [[https://github.com/klacke][Claes Wikstrom]] and is a unique addition to the
  Nitrogen's supported webserver line-up because it's one of the few that uses
  Apache-style configuration instead of the more usual Erlang proplist config 
  files.

**** etc/yaws.config

  This file is just tells Yaws where to load the actual configuration file,
  which you can probably deduce.

  #+BEGIN_SRC erlang
  [{yaws, [
      {conf, "./etc/yaws.conf"}
  ]}].
  #+END_SRC

**** etc/yaws.conf

  #+BEGIN_SRC bash
  logdir = ./log
  <server mydomain.org>
      port = 8000
      listen = 127.0.0.1

      #the static code to be served directly by yaws is found in ./site/static
      docroot = ./site/static

      # tell yaws to pass control to the nitrogen_yaws module
      # (specifically nitrogen_yaws:out/1) for all requests except for any request
      # that starts with "images/", "nitrogen/", "css/", or "/js".
      # Bear in mind, however, the caveat to this performance improvement:
      # this means that you cannot have any pages called "nitrogen_xxx" or "css_yyy" because
      # the yaws config will see the "exclude_paths" rule below and completely ignore nitrogen.
      # Should you wish to have yaws handle any more static files, for example, if you added
      # a videos directory in site/static/, you can simply add "videos" to the end of the list
      # Ex: appmods = </, nitrogen_yaws exclude_paths images nitrogen css js videos>
      appmods = </, nitrogen_yaws exclude_paths images nitrogen css js>
  </server>
  #+END_SRC

  You can find the [[http://yaws.hyber.org/yman.yaws?page=yaws.conf][complete documentation for the yaws.conf file]]
  on the official website, but for the sake of convenience, here's the a brief
  description of the default one provided by Nitrogen.

    + =logdir= :: tells where to store the Yaws log files
    
    + =<server mydomain.org> [...] </server>= :: Defines a virtual server. For use
      with Nitrogen, we recommend only specifying one. =mydomain.org= in our example
      is simply the name of the virtual server, and is not used for anything beyond
      a naming scheme.
    
    + =port= :: The port to listen on.
    
    + =listen= :: Which IP address to listen on.
    
    + =docroot= :: The location of the static files relative to the Nitrogen installation
    
    + =appmods = </, nitrogen_yaws exclude_paths images nitrogen css js>= :: While
      quite long and dense with information, this configuration setting tells Yaws to
      send all requests to the Erlang module =nitrogen_yaws=, except for any requests
      that start with /images, /nitrogen, /css, or /js, which will instead be
      handled by Yaws directly.


* Additional Configuration

** nginx - A lightweight reverse proxy

  [[http://wiki.nginx.org/Main][Nginx]] is high performance, lightweight web
  server and reverse proxy that is commonly used for load balancing, rewrite
  rules, SSL certificates, and more.

  Here's a sample configuration (this assumes a standard Ubuntu configuration):

**** /etc/nginx/nginx.conf

  #+BEGIN_SRC nginx
  user www-data;
  worker_processes  1;

  error_log  /var/log/nginx/error.log;
  pid        /var/run/nginx.pid;

  events {
              worker_connections  4096;
  }

  http {
          include       /etc/nginx/mime.types;
          default_type  application/octet-stream;

          access_log      /var/log/nginx/access.log;

          sendfile        on;

          keepalive_timeout  10;
          tcp_nodelay        on;

          gzip  on;

          proxy_set_header X-Forwarded-Host $host;
          proxy_set_header X-Forwarded-Server $host;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


          include /etc/nginx/conf.d/*.conf;
          include /etc/nginx/sites-enabled/*;
  }
  #+END_SRC

**** Non-SSL Sample: /etc/nginx/sites-enabled/my\_site

  #+BEGIN_SRC nginx
  server {
          listen   80;
          server_name  mysite.com www.mysite.com;
          access_log  /var/log/nginx/mysite.com.access.log;
          location / {
                  proxy_pass http://127.0.0.1:8000;
          }
  }
  #+END_SRC

**** SSL-Only Sample: /etc/nginx/sites/enabled/my\_secure\_site

  This configuration will server only SSL. It will redirect all requests
  from the HTTP port (port 80) to the HTTPS port (port 443) and load the certificates

  #+BEGIN_SRC nginx
  # My config for a site that I only want serving SSL content.
  server {
          listen   80;

          server_name www.mysite.com, mysite.com;
          access_log  /var/log/nginx/mysite.com.access.log;

    # rewrite all requests to be SSL
          rewrite ^(.*) https://$host$1 permanent;
  }

  server {
          listen 443;
          server_name mysite.com www.mysite.com
          access_log /var/log/nginx/mysite.ssl.access.log;

          ssl on;

          ssl_certificate ssl/mysite/mysite.com.crt;
          ssl_certificate_key ssl/mysite/mysite.com.key;
          ssl_client_certificate ssl/mysite/ca.crt;

          location / {
          # This installation is running on port 8021, as you can plainly see.
            proxy_pass http://127.0.0.1:8000;
          }
  }
  #+END_SRC
