I am trying to migrate an application to a local DB connection (via Unix socket) with scram-sha-256 authentication.
I’ve seen some discussions about how to connect to PostgreSQL server over Unix socket, with probably the most revealing one being this one (from 2022), and the response by @josevalim himself:
This however doesn’t really solve the problem as standard Phoenix runtime.exs contains the following lines:
database_url =
System.get_env("DATABASE_URL") ||
raise """
environment variable DATABASE_URL is missing.
For example: ecto://USER:PASS@HOST/DATABASE
"""
which means that DATABASE_URL has to be available. And if so then what does one set it to so that it does not conflict with other options when passed to url:?
Anything changed since then? How does one connect via local Unix socket these days?
I understand. Yet I’d still prefer to know better what I am doing before changing things that might be there for a reason, especially if they are guarded by an exception
The other thing is that I am having hard time finding what socket_options: are available. One :inet6 is mentioned in the line below above quoted snippet:
maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: []
All in all it doesn’t instil much confidence when doing it the first time. Not mentioning even that I would very much prefer not to (have to) fiddle with standard config/bolierplate unless absolutely necessary.
The socket stuff in Erlang is a little dense. Easy to miss, but that type also lists the option type at the end. The :inet6 comes from this type - also linked from that :gen_tcp.connect_options() type. Very DRY types.
I’m just gonna go on the record here and say that the default Phoenix configs are crusty and could use a bit of a refresher, particularly in regards to the database configuration.
Case in point: Most of the database config should (IMO) be done in runtime.config.exs. There is no good reason to set the DB username and password in e.g. dev.config.exs, and I suspect that the current default layout is a holdover from before runtime config was even an option (which I believe came out circa 2020 with Elixir 1.11).
All this to say, I would encourage you to modify the configs until you have something that works for you. You can always refer back to the defaults later if you blow something up.
Agreed. Since Config.config/2,3 deep merges, it’s way nicer to have, for example, a test.exs that looks like this:
import Config
# Only in tests, remove the complexity from the password hashing algorithm
config :bcrypt_elixir, :log_rounds, 1
# Use Ecto sandbox during tests
config :my_app, MyApp.Repo,
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: System.schedulers_online() * 2
# In test we don't send emails
config :my_app, MyApp.Mailer, adapter: Swoosh.Adapters.Test
# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false
# Print only warnings and errors during test
config :logger, level: :warning
# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime
# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
enable_expensive_runtime_checks: true
and have the URL set for {dev,prod,test}.exs in runtime.exs.
The URL option is nice because it combines all the distinct fields you’d set on a tcp based database connection into one well structured string. It’s however not really useful for a unix socket based connection – I think it can be done, but would likely feel a bit bend over backwards. That’s why I’d suggest changing the config file to fit your needs – which might still mean raising if important system env values are not set.