tlietz

tlietz

Connection refused while connecting to upstream. Phoenix server behind Nginx on a single VPS

I’m trying to deploy a Phoenix liveview app behind Ngnix on a single VPS. I tried to get Phoenix to serve HTTP, while Ngnix handles HTTPS/SSL. However, I’m getting 502 bad gateway with a “Connection refused while connecting to upstream” error. Both the Phoenix server and Ngnix are running in docker containers. Does anybody know what could be going wrong?

Elixir: 1.13.4-otp-25
Phoenix: 1.6.11
Phoenix_live_view: 0.17.11

Logs from sudo docker logs --tail 50 --follow --timestamps <nginx-container-hash> when I go to my.site.com:

2025-05-11T08:51:05.331109428Z 2025/05/11 08:51:05 [error] 21#21: *52 connect() failed (111: Connection refused) while connecting to upstream, client: 208.123.61.54, server: my.site.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:4001/", host: "my.site.com"
2025-05-11T08:51:05.331152962Z 2025/05/11 08:51:05 [warn] 21#21: *52 upstream server temporarily disabled while connecting to upstream, client: 208.123.61.54, server: my.site.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:4001/", host: "my.site.com"
2025-05-11T08:51:05.331160447Z 2025/05/11 08:51:05 [error] 21#21: *52 connect() failed (111: Connection refused) while connecting to upstream, client: 208.123.61.54, server: my.site.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:4001/", host: "my.site.com"
2025-05-11T08:51:05.331247276Z 2025/05/11 08:51:05 [warn] 21#21: *52 upstream server temporarily disabled while connecting to upstream, client: 208.123.61.54, server: my.site.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:4001/", host: "my.site.com"
2025-05-11T08:51:05.331262155Z 208.123.61.54 - - [11/May/2025:08:51:05 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 17_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/138.0  Mobile/15E148 Safari/605.1.15" "-"


prod.exs:

config :mysite, MysiteWeb.Endpoint,
  cache_static_manifest: "priv/static/cache_manifest.json",
  url: [host: "my.site.com", port: 4000]
  http: [ip: {0, 0, 0, 0}, port: 4000],
  check_origin: false,
  server: true,
  check_origin: ["https://my.site.com"],
  secret_key_base: Map.fetch!(System.get_env(), "SECRET_KEY_BASE")

config :mysite, MySite.Repo,
  start_apps_before_migration: [:ssl],
  adapter: Ecto.Adapters.Postgres,
  url: System.get_env("DATABASE_URL"),
  ssl: true,
  pool_size: 10


Nginx:

server {
    listen 443 default_server ssl;
    listen [::]:443 ssl;

    server_name my.site.com;

    ssl_certificate /etc/nginx/ssl/live/my.site.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/live/my.site.com/privkey.pem;

    location / {
             proxy_set_header Host $host;
             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  $scheme;
             proxy_set_header X-Forwarded-Host  $host;
             proxy_set_header X-Forwarded-Port  $server_port;
             proxy_pass http://localhost:4001/;
             proxy_redirect off;
    }
    # required for websocket
    location /live {
             proxy_http_version 1.1;
             proxy_set_header Upgrade $http_upgrade;
             proxy_set_header Connection "upgrade";
             proxy_set_header Host $host;
             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  $scheme;
             proxy_set_header X-Forwarded-Host  $host;
             proxy_set_header X-Forwarded-Port  $server_port;
             proxy_pass http://localhost:4001/live;
             # raise the proxy timeout for the websocket
             proxy_read_timeout 6000s;
    }
}


Starting Phoenix server:

$ sudo docker run -p 4001:4000  --env-file .env collaborlist:v1
09:25:15.666 [info] Running CollaborlistWeb.Endpoint with cowboy 2.9.0 at :::4000 (http)
09:25:15.667 [info] Access CollaborlistWeb.Endpoint at http://0.0.0.0:4000
09:25:15.797 [warning] Description: 'Server authenticity is not verified since certificate path validation is not enabled'
     Reason: 'The option {verify, verify_peer} and one of the options \'cacertfile\' or \'cacerts\' are required to enable this.'

Marked As Solved

tlietz

tlietz

The solution required 2 steps (a combination of Egis and FlyingNoodle’s comments).

  1. Adding the Phoenix application as another service to the docker-compose.yml
  2. Creating an upstream block for the Phoenix sever in Nginx conf file.

These are the working docker-compose.yml and nginx.conf files:

nginx.conf

upstream docker-web {
    server web:4000;
      }

server {
    listen 443 default_server ssl;
    listen [::]:443 ssl;

    server_name my.site.com;

    ssl_certificate /etc/nginx/ssl/live/my.site.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/live/my.site.com/privkey.pem;

    location / {
             proxy_set_header Host $host;
             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  $scheme;
             proxy_set_header X-Forwarded-Host  $host;
             proxy_set_header X-Forwarded-Port  $server_port;
             proxy_pass http://docker-web;
             proxy_redirect off;
    }
    # required for websocket
    location /live {
             proxy_http_version 1.1;
             proxy_set_header Upgrade $http_upgrade;
             proxy_set_header Connection "upgrade";
             proxy_set_header Host $host;
             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  $scheme;
             proxy_set_header X-Forwarded-Host  $host;
             proxy_set_header X-Forwarded-Port  $server_port;
             proxy_pass http://docker-web/live;
             # raise the proxy timeout for the websocket
             proxy_read_timeout 6000s;
    }
}


docker-compose.yml

services:
  web:
    image: mysite:v1
    ports:
      - 4000:4000
    env_file: "webapp.env"
    networks:
        main:
            aliases:
                - web
  proxy:
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    restart: always
    links:
      - web:web
    depends_on:
      - web
    volumes:
      - ./nginx/conf/:/etc/nginx/conf.d/:ro
      - ./certbot/conf/live:/etc/nginx/ssl/live/:ro
      - ./certbot/conf/archive:/etc/nginx/ssl/archive/:ro
      - ./certbot/www/:/var/www/certbot/:ro
    networks:
        main:
            aliases:
                - proxy
  certbot:
    image: certbot/certbot:latest
    volumes:
      - ./certbot/www/:/var/www/certbot/:rw
      - ./certbot/conf/:/etc/letsencrypt/:rw

networks:
  main:

Also Liked

Egis

Egis

I am not a docker expert (far from it), but at first glance it looks like you’re trying to connect to localhost (from nginx), but since nginx is running inside it’s own container - localhost is not the same as phoenix uses (since phoenix runs inside other container).

Maybe some “reverse port forwarding” (or however it’s called in docker-land) between those two containers?

I’m sorry if my bad english and lack of proper docker knowledge confused you even more :sweat_smile:

FlyingNoodle

FlyingNoodle

If you run them with compose then you can refer to their names. So you nginx config is http://my-elixir-service-name.

Sorry on phone right now

tlietz

tlietz

No worries! You were correct about what the issue was. Your reply was able to lead me down the correct path to solve the problem :blush:

Last Post!

tlietz

tlietz

No worries! You were correct about what the issue was. Your reply was able to lead me down the correct path to solve the problem :blush:

Where Next?

Popular in Questions Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New

Other popular topics Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement