External Connections
Fly Postgres databases can be used by applications outside their Fly.io internal private network; this means in a different private network belonging to your organization, in another Fly organization, or outside Fly.io altogether.
We don’t expose Postgres apps to the internet by default. To get this working, you’ll need to make two adaptations: configuring your Postgres app to accept connections from the Fly proxy, and providing a publicly-resolvable hostname to your app.
Allocate an IP address
If you haven’t already, you will need to allocate a public IP address to your Postgres app. You can view your list of IPs by running the following command from your application directory:
fly ips list --app <pg-app-name>
You can allocate an IPv4 address by running the following:
fly ips allocate-v4 --app <pg-app-name>
If your network supports IPv6:
fly ips allocate-v6 --app <pg-app-name>
Configure an external service
Now that you have an IP address, it’s time to configure your app to accept connections on an external port, and direct incoming requests to your Postgres instance.
Pull down a fly.toml
configuration file for your Postgres app, if you don’t have it:
fly config save --app <pg-app-name>
Note that this could overwrite a fly.toml
in the current directory, so be careful!
Open up your fly.toml
file.
This may come with a default services
section for internal_port
8080. Replace that with the following to configure your port mappings to work with Postgres:
[[services]]
internal_port = 5432 # Postgres instance
protocol = "tcp"
[[services.ports]]
handlers = ["pg_tls"]
port = 5432
Note the use of the pg_tls
handler to manage the specific requirements of Postgres connections.
For additional information on services and service ports: The services sections
Deploy with the new configuration
Once your service has been set up in fly.toml
, it’s time to deploy with the new configuration.
Verify the version of Postgres you are running. This step is important, because there can be changes in the internal storage format between major versions of Postgres.
Figure out which image and tag (Postgres version) you’re on:
fly image show --app <pg-app-name>
Image Details
Registry = docker-hub-mirror.fly.io
Repository = flyio/postgres-flex
Tag = 16.4
Version = v0.0.62
Deploy your cluster, using --image
with the image:tag
found in the previous step:
fly deploy . --app <pg-app-name> --image flyio/postgres-flex:<major-version>
As an example, if you are running Postgres 16.x you would specify flyio/postgres-flex:16
as your target image.
After the deployment completes, you can verify your services
configuration by running the fly services list
command:
fly services list
Services
PROTOCOL PORTS FORCE HTTPS
TCP 5432 => 5432 [PG_TLS] False
TCP 5433 => 5433 [PG_TLS] False
You should then be able to access your Postgres cluster via psql like:
psql "sslmode=require host=<pg-app-name>.fly.dev dbname=<db name> user=<username>"
Password for user <username>:
psql (14.5 (Homebrew), server 13.6 (Debian 13.6-1.pgdg110+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
<db name>=#
Adapting the connection string
The connection string that fly pg create
outputs for use in consuming apps is in the form:
postgres://{username}:{password}@{hostname}:{port}/{database}?options
where the hostname
is an internal one. Substitute your newly publicly reachable hostname (<pg-app-name>.fly.dev
) here to get a connection string an external app can use.