Problems with deployment (AWS Ubuntu and Nginx)

Hi all.

I’ve been trying to deploy a Phoenix app with a Ubuntu 18.04 instance on AWS, and things have gone well up to the point when I actually try and access the site. I’m using Nginx for the web server and proxying the requests to localhost:4000.

If I run curl localhost:4000 on the remote server, I can see HTML being returned. However Nginx is returning 400s if I try and access it from a browser or any HTTP client.

Deployment is an area I’m pretty inexperienced in, so let me know if this is the wrong place to ask this kind of question. However, I was hoping that someone who has experience with this or has solved the same problem may be able to help, or whether the problems are on the Phoenix config side of things.

I was following this guide: https://medium.com/@zek/deploy-early-and-often-deploying-phoenix-with-edeliver-and-distillery-part-one-5e91cac8d4bd

prod.secret.exs

use Mix.Config

database_url =
  System.get_env("DATABASE_URL") ||
    raise """
    environment variable DATABASE_URL is missing.
    For example: ecto://USER:PASS@HOST/DATABASE
    """

config :deploy_phoenix, DeployPhoenix.Repo,
  # ssl: true,
  url: database_url,
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")

secret_key_base =
  System.get_env("SECRET_KEY_BASE") ||
    raise """
    environment variable SECRET_KEY_BASE is missing.
    You can generate one by calling: mix phx.gen.secret
    """

config :deploy_phoenix, DeployPhoenixWeb.Endpoint,
  http: [:inet6, port: String.to_integer(System.get_env("PORT") || "4000")],
  secret_key_base: secret_key_base

config :deploy_phoenix, DeployPhoenixWeb.Endpoint, server: true

prod.exs

use Mix.Config

config :deploy_phoenix, DeployPhoenixWeb.Endpoint,
  url: [host: "localhost"],
  cache_static_manifest: "priv/static/cache_manifest.json"

config.exs

config :deploy_phoenix, DeployPhoenixWeb.Endpoint,
  url: [host: "localhost", port: 80]

/etc/nginx/sites-available/deploy_phoenix / /etc/nginx/sites-enabled/deploy_phoenix

upstream deploy_phoenix {
  server 127.0.0.1:4000;
}

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {
  listen 80;
  server_name [AWS IP];
  location / {
    try_files $uri @proxy;
  }
  location @proxy {
    include proxy_params;
    proxy_redirect off;
    proxy_pass http://deploy_phoenix;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
}

Hi, I’m the author of that guide. I should be able to find a solution when I have some time tonight/tomorrow. The issue should be in the nginx config.

1 Like

I have one working for me…

upstream calabrese_4000 {
	server 127.0.0.1:4000 max_fails=5 fail_timeout=60s;
}
server {
	listen 80;
	listen [::]:80;
	index index.html index.htm index.nginx-debian.html;
	server_name xxx.ch www.xxx.ch;
	location / {
		# Proxy
		proxy_pass http://calabrese_4000;
		proxy_pass_header Server;
		proxy_set_header Host $http_host;
		proxy_redirect off;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Scheme $scheme;

		# WebSocket support
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}
}
3 Likes

This works for me:

upstream deploy_phoenix {
  server localhost:4000;
}

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {
  listen 80;
  server_name www.yoursite.com;
  location / {  
    try_files $uri @proxy;
  }
  location @proxy {
    # include proxy_params; <<< comment this out.
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_redirect off;
    proxy_pass http://deploy_phoenix;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
}

Let me know how it goes.

2 Likes

Here is a blog post I wrote about serving apps using Nginx: https://www.cogini.com/blog/serving-your-phoenix-app-with-nginx/

I don’t actually think it is necessary. I normally redirect port 80 to port 4000 in the firewall: https://www.cogini.com/blog/port-forwarding-with-iptables/

I have a number of blog posts as well on deploying, e.g. https://www.cogini.com/blog/deploying-an-elixir-app-to-digital-ocean-with-mix_deploy/

4 Likes

@kokolegorille @ziazek

Thanks so much guys, I tried both of these configs and they work perfect. I was banging my head against the wall for hours trying to solve this issue.

@jakemorrison Thanks, will give your articles a read as I’d like to learn more about this stuff!

That’s great!