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
The solution required 2 steps (a combination of Egis and FlyingNoodle’s comments).
- Adding the Phoenix application as another service to the
docker-compose.yml - Creating an
upstreamblock 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
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 ![]()
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
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 ![]()
Last Post!
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 ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









