Can't connect to a database hosted on DigitalOcean from Phoenix

Hey, I am trying to get my Phoenix app running on fly.io!

But it seems like I can’t connect to the database hosted on DigitalOcean (DbaaS).

I set the environment variable DATABASE_URL to the one I copy from DigitalOcean and it seems like fly.io servers can’t resolve the DNS entry for it?

This is what I get in the logs:

[error] Postgrex.Protocol (#PID<0.3781.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (xxxxxxxxxx.db.ondigitalocean.com:25060): non-existing domain - :nxdomain

But if I ping it on my machine it resolves the IP.

I also disabled trusted sources on DO to be able to connect to it. DO does not support IPv6 for this, unfortunately.

This is the configuration I have in Phoenix:

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

config :app, App.Repo,
  url: database_url,
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
  socket_options: [:inet6],
  ssl: true

Huh that’s interesting. nxdomain makes it seem like there’s no zone file for that db.ondigitalocean.com host. Will you try connecting to your vm with ssh and see if you can get anything out of dig xxxxxxxxxx.db.ondigitalocean.com on there?

This is odd. When I connect with flyctl ssh console and ping or use dig it can resolve the host and I see the IP address :sweat_smile:

I tried to set DATABASE_URL again, but seems it is already the correct one, because I get back Error No change detected to secrets.

From my Postico app I can connect to this connection strings without any problems.

Can it be of some setting in the fly.toml file:

app = ""

kill_signal = "SIGINT"
kill_timeout = 2

[env]

[experimental]
  auto_rollback = true
  private_network = true

[[services]]
  http_checks = []
  internal_port = 4000
  protocol = "tcp"
  script_checks = []

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [[services.tcp_checks]]
    grace_period = "30s"
    interval = "10s"
    restart_limit = 3
    timeout = "2s"

Got it working!

It was my fault. I set the socket_options to IPv6 only and I guess DigitalOcean does not have an IPv6 for the database server.

I think I just copied the settings from a previous answer I saw on the forum :sweat_smile:

For the databases hosted on fly.io I will have to set the socket_options to [:inet6] probably :smiley:

This is the final config I have for connection to a database hosted on DigitalOcean with Phoenix:

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

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

Wow that’s interesting. That socket_options change shouldn’t disable IPv4, I don’t think! We’ll have to look at that.