Phoenix on Fly.io: This site can’t be reached

I’m having trouble getting my Phoenix app running on Fly.io. The machines are running, the server has no errors, and the database is connected, but I don’t seem to be able to connect to it. I’ve been following this guide from the documentation.

Without any errors to go off of, this feels like it might be a problem with how my server is configured. I’ve tried both enabling and disabling SSL and a bunch of other tweaking, but I haven’t had any luck. I’m hoping someone on here with more experience can point out my issue. :slightly_smiling_face:

Here’s my config/prod.exs file:

import Config

# Do not print debug messages in production.
config :logger, level: :info

# Configure CORS.
config :cors_plug,
  origin: [
    "https://www.chessercise.xyz",
    "http://localhost:3000",
    "http://localhost:8000",
    "https://localhost:3000",
    "https://localhost:8000"
  ]

And my config/runtime.exs file:

import Config

if System.get_env("PHX_SERVER") && System.get_env("RELEASE_NAME") do
  config :chessercise, ChesserciseWeb.Endpoint, server: true
end

if config_env() == :prod do
  config :chessercise, Chessercise.Repo,
    pool_size: String.to_integer(System.fetch_env!("POOL_SIZE")),
    url: System.fetch_env!("DATABASE_URL"),
    socket_options: if(System.get_env("ECTO_IPV6"), do: [:inet6], else: [])

  # Configure the endpoint.
  config :chessercise, ChesserciseWeb.Endpoint,
    secret_key_base: System.fetch_env!("SECRET_KEY_BASE"),
    http: [
      # Enable IPv6 and bind on all interfaces. Set it to  {0, 0, 0, 0, 0, 0, 0, 1} for local
      # network only access.
      ip: {0, 0, 0, 0, 0, 0, 0, 0},
      port: String.to_integer(System.fetch_env!("PORT"))
    ],
    url: [scheme: "https", host: System.fetch_env!("PHX_HOST")]

  # Configure Bamboo to use the application's mailer.
  config :chessercise, ChesserciseWeb.Mailer,
    adapter: Bamboo.SendGridAdapter,
    api_key: System.fetch_env!("SEND_GRID_API_KEY")
end

Here’s my Dockerfile (mostly generated from fly launch):

# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
# instead of Alpine to avoid DNS resolution issues in production.
#
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
# https://hub.docker.com/_/ubuntu?tab=tags
#
# This file is based on these images:
#
#   - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
#   - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20231009-slim - for the release image
#   - https://pkgs.org/ - resource for finding needed packages
#   - Ex: hexpm/elixir:1.16.0-erlang-26.2.1-debian-bullseye-20231009-slim
#
ARG ELIXIR_VERSION=1.16.0
ARG OTP_VERSION=26.2.1
ARG DEBIAN_VERSION=bullseye-20231009-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# prepare build dir
WORKDIR /app

# install hex + rebar
RUN mix local.hex --force && \
  mix local.rebar --force

# set build ENV
ENV MIX_ENV="prod"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config

# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv
COPY data data
COPY lib lib

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}

RUN apt-get update -y && \
  apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR "/app"
RUN chown nobody /app

ENV MIX_ENV="prod"
ENV ECTO_IPV6 true
ENV ERL_AFLAGS "-proto_dist inet6_tcp"

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/chessercise ./

USER nobody

# If using an environment that doesn't automatically reap zombie processes, it is
# advised to add an init process such as tini via `apt-get install`
# above and adding an entrypoint. See https://github.com/krallin/tini for details
# ENTRYPOINT ["/tini", "--"]

CMD ["/app/bin/server"]

And finally here’s my fly.toml:

app = 'chessercise-api'
primary_region = 'sea'
kill_signal = 'SIGTERM'

[build]

[deploy]
release_command = '/app/bin/migrate'

[env]
PHX_HOST = 'chessercise-api.fly.dev'
PORT = '8080'

[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ['app']

[http_service.concurrency]
type = 'connections'
hard_limit = 1000
soft_limit = 1000

Hi… It looks like there aren’t any public IPs allocated to give access to your application.

(This sometimes happens to people after multiple attempts at launching.)

What does fly ips list show?

@mayailurus Nice catch! It looks like there aren’t any dedicated IP addresses for the app. The command returns an empty table.

VERSION IP      TYPE    REGION  CREATED AT

Following the guide you linked, I allocated a shared IPv4 for the site.

fly ips allocate-v4 --shared

That seems to have done the trick and now I can access my server.

Thank you for the help! :pray: