Navigation Menu

Skip to content

Cowboy without Nginx

Fabian Zitter edited this page Nov 1, 2019 · 3 revisions

Running Cowboy without Nginx

Phoenix is using a webserver called Cowboy, or more accurately the newest version Cowboy2 - which supports http2.

The usual approach would be to run cowboy, and then reverse-proxy requests through Nginx to port 4000 or whatever cowboy is configured to listen to.

🔥 Running cowboy on its own is possible, but does not provide many advantages over using Nginx. Especially static file serving is faster when using Nginx, but if you want to run a bare-bone Phoenix application on a server, you will have to make a few adjustments. 🔥

You should only consider setting up a server without Nginx if you have a rather simple API, without any HTML / Javascript / other static files. It does remove one of the moving parts with nginx though.

Most of the approaches in this wiki came from this blog post

Server settings in prod.secret.ex or prod.ex

The linux permission system will not let you run an app listening on ports < 1000 when not running under root. For security reasons, we do not want to run the app under root, so the easiest way around this is to configure iptables to redirect incoming requests on port 80 (http) and 443 (https) to - for example - 4080 and 4443 and have cowboy listen to those ports.

# prod.exs or prod.secret.exs
  url: [host: "your_app.com", port: 4000, scheme: "https"],
  server: true,
  http: [:inet6, port: 4080],
  https: [
    port: 4443,
    otp_app: :your_app,
    cipher_suite: :strong,
    keyfile: "/etc/letsencrypt/live/your_app.com/privkey.pem",
    certfile: "/etc/letsencrypt/live/your_app.com/cert.pem",
    cacertfile: "/etc/letsencrypt/live/your_app.com/chain.pem",
    dhfile: "/etc/letsencrypt/dhparam.pem"
  ]

SSL certificates with certbot

As you can see, you have to create the certificates yourself and tell cowboy where to find them. You can create certificates running certbot in standalone mode - you might have to change access rights to /etc/letsencrypt/live/your_app.com/* files. If your application does not start with the error message "/etc/letsencrypt/live/your_app.com/privkey.pem" does not exist or can not be accessed run

sudo chmod 0775 /etc/letsencrypt/ -R

You will probably have to create DH parameters (the dhparam.pem file). This is a very CPU heavy and long running process (can take up to 10 minutes), so make sure your server is not doing anything meaningful while running this:

openssl dhparam -out /etc/letsencrypt/dhparam.pem 4096

Forwarding requests from port 80 / 443 to your app

An easy way of doing this is using iptables which comes preinstalled on Ubuntu servers.

# Forward requests to 443:
sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 443 -j REDIRECT --to-ports 4443
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 4443

# Forward requests to 80:
sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 4080
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 4080
TODO: How do renewals work, and will cowboy load the new cert files after a renewal?