Summary
In the nginx (ngx.socket) code path, pgmoon performs its TLS handshake without sending the SNI (Server Name Indication) extension. The server_name argument to tcpsock:sslhandshake is passed as nil:
https://github.com/leafo/pgmoon/blob/master/pgmoon/init.moon#L1078
when "nginx"
@sock\sslhandshake false, nil, @config.ssl_verify
Managed PostgreSQL services that route connections by SNI cannot identify the target instance when the extension is absent, so they reject the connection during the handshake. libpq has sent SNI by default since PostgreSQL 14 (sslsni), so psql connects to the same endpoint while pgmoon does not.
The fix is one line: pass the host pgmoon already holds as the server_name.
when "nginx"
@sock\sslhandshake false, @config.host, @config.ssl_verify
Environment
| Component |
Version |
| pgmoon |
1.17.0-1 (LuaRocks) |
| Debian |
13 (trixie), debian:trixie-slim |
| nginx |
1.26.3 (Debian package) |
| libnginx-mod-http-lua |
1:0.10.28-2 (OpenResty lua-nginx-module, Debian package) |
| lua-resty-core / lua-resty-lrucache |
0.1.31-1 / 0.15-2 |
| LuaJIT |
2.1.0+openresty20250117-2 |
Reproduction against a real SNI-routed service (Scaleway Serverless SQL)
This confirms the connection failure on a service that requires SNI. Following the Scaleway Serverless SQL quickstart, using the scw CLI:
1. Create a database:
scw sdb-sql database create name=pgmoon-sni-repro cpu-min=0 cpu-max=1 region=fr-par
scw sdb-sql database list region=fr-par
The database ID forms part of the hostname ({database-id}.pg.sdb.fr-par.scw.cloud), which is what the service routes on via SNI
2. Generate credentials in the console (Connect, then Generate API key). The IAM key id and secret become the PostgreSQL user and password.
3. Put the connection details in .env:
PGHOST={database-id}.pg.sdb.fr-par.scw.cloud
PGPORT=5432
PGDATABASE={database name}
PGUSER={IAM key id}
PGPASSWORD={IAM secret key}
4. psql connects, because libpq sends SNI:
$ set -a; . ./.env; set +a
$ PGSSLMODE=require psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE -tAc "select version()"
PostgreSQL 16.14 (Debian 16.14-1.pgdg12+1) on x86_64-pc-linux-gnu, ...
5. pgmoon 1.17.0 under nginx fails on the same endpoint
There is a complete demo of pgmoon with OpenResty implementing the GoThinkster API that has to manually patch around htis error at https://codeberg.org/simbo1905/realworld-openresty-lua/src/tag/2026-07-06_0825_main/app/db.lua#L33-L53 so to reproduce comment out those lines.
connect failed: FATAL: Database hostname wasn't sent to server. Either add "?options=databaseid%3D{databaseid}"
at the end of your connection string, or use another client supporting TLS ServerNameIndication.
More solutions: https://www.scaleway.com/en/docs/faq/serverless-sql-databases/
The error names the cause directly: no TLS Server Name Indication. Note that Serverless SQL scales to zero, so the first connection after idle can be slow or time out once before the instance wakes; retry if that happens.
Summary
In the nginx (
ngx.socket) code path, pgmoon performs its TLS handshake without sending the SNI (Server Name Indication) extension. Theserver_nameargument totcpsock:sslhandshakeis passed asnil:https://github.com/leafo/pgmoon/blob/master/pgmoon/init.moon#L1078
Managed PostgreSQL services that route connections by SNI cannot identify the target instance when the extension is absent, so they reject the connection during the handshake. libpq has sent SNI by default since PostgreSQL 14 (
sslsni), sopsqlconnects to the same endpoint while pgmoon does not.The fix is one line: pass the
hostpgmoon already holds as theserver_name.Environment
debian:trixie-slimlua-nginx-module, Debian package)Reproduction against a real SNI-routed service (Scaleway Serverless SQL)
This confirms the connection failure on a service that requires SNI. Following the Scaleway Serverless SQL quickstart, using the
scwCLI:1. Create a database:
The database ID forms part of the hostname (
{database-id}.pg.sdb.fr-par.scw.cloud), which is what the service routes on via SNI2. Generate credentials in the console (Connect, then Generate API key). The IAM key id and secret become the PostgreSQL user and password.
3. Put the connection details in
.env:PGHOST={database-id}.pg.sdb.fr-par.scw.cloud PGPORT=5432 PGDATABASE={database name} PGUSER={IAM key id} PGPASSWORD={IAM secret key}4. psql connects, because libpq sends SNI:
5. pgmoon 1.17.0 under nginx fails on the same endpoint
There is a complete demo of pgmoon with OpenResty implementing the GoThinkster API that has to manually patch around htis error at https://codeberg.org/simbo1905/realworld-openresty-lua/src/tag/2026-07-06_0825_main/app/db.lua#L33-L53 so to reproduce comment out those lines.
The error names the cause directly: no TLS Server Name Indication. Note that Serverless SQL scales to zero, so the first connection after idle can be slow or time out once before the instance wakes; retry if that happens.