Waxx In Production

Waxx is very stable and performant in production. This is how to get the best performance.

Things to change for production (or if you want to see how fast it runs)

When you are ready to put an app in production, you should change the following config options. See the section on threads below.

Things to change in opt/prod/config.yaml

server:
  min_threads: 4
  max_threads: 16
  idle_thread_timeout: 300
debug:  level: 3
  on_screen: false
  send_email: true
  email: you-or-your-dev-team@example.com
  auto_reload_code: false
file:
  serve: false

How many threads to use

The min_thread and max_thread options depend heavily on how your app is used and the number of cores on your server. The fastest setup for pure speed is to have the min_threads and max_threads equal to the number of (virtual) CPU cores on your system. This is the best setting if your reqests are delivered in 1 - 2 ms. If you have a lot of slow database queries or are pulling in data from external web services, then you want to increase the max_threads significantly. This allows other threads to work while a thread is waiting for a response from an external service. The CPU will handle all of the timing of threads waiting and working.

NOTE: Every thread will make a database connection (or connections if you have multiple database connections defined). If your database has limited connections available don't allow max_threads to exceed the number of available database connections.

Thread Process

As requests come into Waxx, they are place d in a first-in-first-out (FIFO) queue. If your min_threads is set to "4", then your app will spin up four threads and as requests come in, one thread after the next will handle each requests. If a request comes in and no threads are available, Waxx will spin up another thread until the total max_threads are reached. After this, the request will sit in the queue until a busy thread is free. As the queue shrinks, extra idle threads will be terminated automatically after they have not done anything for idle_thread_timeout in seconds.

NGINX Production Example

Waxx works great behind NGINX.

The following nginx.conf file will support getting a LetsEncrypt cert as well. You may have to change your .well-known alias.

/waxx/root/opt/prod/nginx.conf (change /waxx/root/ to your waxx root)

Change www.example.com to your address.

server {
  listen www.example.com:80;
  server_name www.example.com;
  # This is setup for LetsEncrypt using Dehydrated on FreeBSD
  location /.well-known/acme-challenge/ {
    alias /usr/local/www/dehydrated/;
  }
  location / {
    rewrite ^ https://www.example.com$request_uri?;
  }
}
server {
  listen       www.example.com:443;
  server_name  www.example.com;
  access_log  /var/log/nginx/www.example.com.access.log  main;

  location / {
    root   /waxx/root/public;
    index index.html;
    try_files $uri /$uri/index.html @app;
  }
  location @app {
    proxy_pass http://127.0.0.1:7777;
    proxy_redirect default ;
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_buffering on; # For direct writes to the client, this needs to be removed
    proxy_read_timeout 300s; # 5 minutes
  }
  location = /_.gif {
    empty_gif;
  }
  location /tmp {
    internal;
    alias /waxx/root/tmp;
  }
  location /waxx_root {
    internal;
    alias /waxx/root;
  }
  location /private {
    internal;
    alias /waxx/root/private;
  }

  error_page  404              /404.html;

  # redirect server error pages to the static page /50x.html
  # You may want to have you own 50x.html file
  error_page 500 502 503 504  /50x.html;
  location = /50x.html {
      root   /usr/local/www/nginx-dist;
  }

  # deny access to .files
  location ~ /\. {
      deny  all;
  }

  ssl on;
  ssl_certificate      /usr/local/etc/dehydrated/certs/www.example.com/fullchain.pem;
  ssl_certificate_key  /usr/local/etc/dehydrated/certs/www.example.com/privkey.pem;
  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;
  ssl_protocols        TLSv1.1 TLSv1.2;
  ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4';
  ssl_prefer_server_ciphers on;
  # Run if dhparam.pem does not exist: sudo openssl dhparam -out /etc/ssl/dhparam.pem 2048
  ssl_dhparam /etc/ssl/dhparam.pem;

  add_header X-Content-Type-Options nosniff;
  add_header X-XSS-Protection "1; mode=block";
  add_header X-Frame-Options SAMEORIGIN;

  # Optional (Be careful! The following will require HTTPS on all of your hosts)
  # add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
  # add_header Content-Security-Policy "default-src 'self' data:; script-src 'self' 'unsafe-inline'";
}

Then include in the main /etc/nginx/nginx.conf or /usr/local/etc/nginx/nginx.conf file like so:

http {
  # Your other http settings here.
  # Add this line (change /waxx/root to your waxx root):
  include /waxx/root/opt/prod/nginx.conf;
}

Restart NGINX

sudo service nginx restart