Skip to content

Commit 69b792d

Browse files
committed
Merge upstream/master and add PostgreSQL 18/PostGIS 3.6
2 parents 4ac5e26 + 87635ad commit 69b792d

File tree

8 files changed

+506
-49
lines changed

8 files changed

+506
-49
lines changed

.github/workflows/ci.yaml

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
branches:
1111
- master
1212
schedule:
13-
# See https://crontab.guru/monthly
13+
# Monthly
1414
- cron: 0 0 1 * *
1515

1616
jobs:
@@ -19,35 +19,31 @@ jobs:
1919
strategy:
2020
fail-fast: false
2121
matrix:
22-
pg_version:
23-
- "16"
24-
- "15"
25-
# - "13"
26-
platform:
27-
- "amd64"
28-
- "arm64"
22+
pg_version: ["18", "17", "16", "15"]
23+
platform: ["amd64", "arm64"]
2924

3025
env:
31-
PG_LATEST: "16"
26+
PG_LATEST: "18"
27+
3228
steps:
3329
- uses: actions/checkout@v4
3430

3531
- name: Set up QEMU
36-
uses: docker/setup-qemu-action@v2
3732
if: matrix.platform != 'amd64'
33+
uses: docker/setup-qemu-action@v3
3834
with:
3935
platforms: ${{ matrix.platform }}
4036

4137
- name: Get build date
4238
id: date
43-
run: echo "date=$(date --rfc-3339 ns)" >> $GITHUB_OUTPUT
39+
run: echo "date=$(date --rfc-3339=ns)" >> "$GITHUB_OUTPUT"
4440

4541
- name: Get latest tag
4642
id: tag-latest
4743
if: matrix.pg_version == env.PG_LATEST
48-
run: echo "tag=${{ matrix.platform == 'amd64' && ' latest' || format(' latest-{0}', matrix.platform) }}" >> $GITHUB_OUTPUT
44+
run: echo "tag=${{ matrix.platform == 'amd64' && ' latest' || format(' latest-{0}', matrix.platform) }}" >> "$GITHUB_OUTPUT"
4945

50-
- name: Build image Postgres
46+
- name: Build Postgres image
5147
id: buildpg
5248
uses: redhat-actions/buildah-build@v2
5349
with:
@@ -62,7 +58,7 @@ jobs:
6258
VCS_REF=${{ github.sha }}
6359
BASE_TAG=${{ matrix.pg_version }}-alpine
6460
65-
- name: Push image Postgres to GHCR
61+
- name: Push Postgres image to GHCR
6662
uses: redhat-actions/push-to-registry@v2
6763
with:
6864
image: ${{ steps.buildpg.outputs.image }}
@@ -71,27 +67,26 @@ jobs:
7167
username: ${{ github.actor }}
7268
password: ${{ secrets.GITHUB_TOKEN }}
7369

74-
- name: Build image PostGIS
70+
- name: Build PostGIS image
7571
id: buildpgis
7672
uses: redhat-actions/buildah-build@v2
7773
with:
7874
image: postgis-autoconf
79-
tags: ${{ matrix.platform == 'amd64' && format('{0}-alpine', matrix.pg_version) || format('{0}-alpine-{1}', matrix.pg_version, matrix.platform) }}${{ steps.tag-latest.output.tag || '' }}
75+
tags: ${{ matrix.platform == 'amd64' && format('{0}-alpine', matrix.pg_version) || format('{0}-alpine-{1}', matrix.pg_version, matrix.platform) }}${{ steps.tag-latest.outputs.tag || '' }}
8076
context: .
8177
platforms: linux/${{ matrix.platform }}
8278
containerfiles: |
8379
Dockerfile-GIS
8480
build-args: |
85-
BUILD_DATE=${{ steps.date.output.date }}
81+
BUILD_DATE=${{ steps.date.outputs.date }}
8682
VCS_REF=${{ github.sha }}
8783
BASE_TAG=${{ matrix.pg_version }}-alpine
8884
89-
- name: Push image PostGIS to GHCR
85+
- name: Push PostGIS image to GHCR
9086
uses: redhat-actions/push-to-registry@v2
9187
with:
9288
image: ${{ steps.buildpgis.outputs.image }}
9389
tags: ${{ steps.buildpgis.outputs.tags }}
9490
registry: ghcr.io/openspp
9591
username: ${{ github.actor }}
9692
password: ${{ secrets.GITHUB_TOKEN }}
97-

Dockerfile

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
ARG BASE_TAG
22
FROM docker.io/postgres:${BASE_TAG}
3+
34
ENTRYPOINT [ "/autoconf-entrypoint" ]
45
CMD []
6+
57
ENV CERTS="{}" \
68
CONF_EXTRA="" \
79
LAN_AUTH_METHOD=md5 \
@@ -15,25 +17,46 @@ ENV CERTS="{}" \
1517
WAN_DATABASES='["all"]' \
1618
WAN_HBA_TPL="{connection} {db} {user} {cidr} {meth}" \
1719
WAN_TLS=1 \
18-
WAN_USERS='["all"]'
19-
RUN apk add --no-cache python3 \
20-
&& mkdir -p /etc/postgres \
21-
&& chmod a=rwx /etc/postgres
22-
RUN apk add --no-cache py3-netifaces
20+
WAN_USERS='["all"]' \
21+
HBA_EXTRA_RULES=""
22+
23+
# Base runtime deps + pgvector (if available) + writable config dir
24+
RUN set -eux; \
25+
apk add --no-cache python3 py3-netifaces; \
26+
if [ "${PG_MAJOR:-0}" -ge 12 ]; then \
27+
apk add --no-cache "postgresql${PG_MAJOR}-pgvector" || apk add --no-cache postgresql-pgvector || true; \
28+
if [ -d "/usr/share/postgresql${PG_MAJOR}/extension" ]; then \
29+
cp /usr/share/postgresql${PG_MAJOR}/extension/vector* /usr/local/share/postgresql/extension/; \
30+
elif [ -d "/usr/share/postgresql/extension" ]; then \
31+
cp /usr/share/postgresql/extension/vector* /usr/local/share/postgresql/extension/; \
32+
fi; \
33+
so_path=$(find /usr/lib -name vector.so | head -n 1); \
34+
if [ -n "${so_path}" ]; then \
35+
cp "${so_path}" /usr/local/lib/postgresql/; \
36+
fi; \
37+
fi; \
38+
mkdir -p /etc/postgres; \
39+
chmod a=rwx /etc/postgres
40+
2341
COPY autoconf-entrypoint /
2442

25-
RUN apk add --no-cache -t .build \
26-
postgresql-dev postgresql-contrib \
27-
curl-dev libcurl \
28-
wget jq cmake build-base ca-certificates py3-pip pipx && \
29-
pipx ensurepath && \
30-
pipx install pgxnclient && \
31-
export PATH=$PATH:/root/.local/bin && \
32-
pgxn install pg_qualstats && \
33-
pgxn install pg_stat_kcache && \
34-
pgxn install pg_track_settings && \
35-
pgxn install powa && \
36-
pgxn install postgresql_anonymizer && \
43+
# Optional pgxn extensions (best-effort to keep build working on new PG majors)
44+
RUN set -eux; \
45+
apk add --no-cache -t .build \
46+
"postgresql${PG_MAJOR}-dev" "postgresql${PG_MAJOR}-contrib" \
47+
curl-dev libcurl \
48+
wget jq cmake build-base ca-certificates py3-pip pipx \
49+
|| apk add --no-cache -t .build \
50+
postgresql-dev postgresql-contrib \
51+
curl-dev libcurl \
52+
wget jq cmake build-base ca-certificates py3-pip pipx; \
53+
pipx ensurepath; \
54+
export PATH="$PATH:/root/.local/bin"; \
55+
for ext in pg_qualstats pg_stat_kcache pg_track_settings powa postgresql_anonymizer; do \
56+
if ! pgxn install "$ext"; then \
57+
echo "WARN: skipping $ext (pgxn install failed)" >&2; \
58+
fi; \
59+
done; \
3760
apk del .build
3861

3962
# Metadata

Dockerfile-GIS

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ FROM ghcr.io/openspp/postgres-autoconf:${BASE_TAG}
1414
# pgxn install postgresql_anonymizer && \
1515
# apk del .build
1616

17-
ENV POSTGIS_VERSION 3.4.1
18-
ENV POSTGIS_SHA256 473c09cbeb68c6e39c882c35e716994d2f8c1e614611162ef3d2a54716cbb74c
19-
20-
ENV DOCKER_PG_LLVM_DEPS \
21-
llvm15-dev \
22-
clang15
17+
ENV POSTGIS_VERSION 3.6.1
18+
ENV POSTGIS_SHA256 849391e75488a749663fbc8d63b846d063d387d286c04dea062820476f84c8f6
2319

2420
RUN set -eux \
2521
&& apk add --no-cache --virtual .fetch-deps \
@@ -86,7 +82,7 @@ RUN set -eux \
8682
&& mkdir /tempdb \
8783
&& chown -R postgres:postgres /tempdb \
8884
&& su postgres -c 'pg_ctl -D /tempdb init' \
89-
&& su postgres -c 'pg_ctl -D /tempdb -c -l /tmp/logfile -o '-F' start ' \
85+
&& su postgres -c "pg_ctl -D /tempdb -c -l /tmp/logfile -o '-F' start" \
9086
&& cd regress \
9187
&& make -j$(nproc) check RUNTESTFLAGS=--extension PGUSER=postgres \
9288
\
@@ -132,4 +128,3 @@ RUN set -eux \
132128

133129
COPY ./initdb-postgis.sh /docker-entrypoint-initdb.d/10_postgis.sh
134130
COPY ./update-postgis.sh /usr/local/bin
135-

README.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
# PostgreSQL Auto-Conf
22

3+
OpenSPP-flavoured fork of [Tecnativa/docker-postgres-autoconf](https://github.com/Tecnativa/docker-postgres-autoconf) with:
4+
5+
- Support for PostgreSQL 18 (latest) plus 15/16/17 builds.
6+
- Optional PostGIS image built from source (3.6.x as of Nov 2025).
7+
- Extra pgxn extensions (powa, pg_qualstats, pg_stat_kcache, pg_track_settings, postgresql_anonymizer) preinstalled on the base image when available for the target PostgreSQL version.
8+
- New upstream features: pgvector packaged for PG ≥ 12 and `HBA_EXTRA_RULES` support.
9+
310
## What
411

512
Image that configures Postgres before starting it.
613

714
## Why
815

9-
To automate dealing with specific users accessing from specific networks to a postgres server.
16+
To automate dealing with specific users accessing from specific networks to a Postgres server.
1017

1118
## How
1219

@@ -35,7 +42,7 @@ JSON object with some or all of these keys:
3542
- `server.cert.pem`: PEM contents for Postgres' `ssl_cert_file` parameter. The Postgres server will identify himself and encrypt the connection with this certificate.
3643
- `server.key.pem`: PEM contents for Postgres' `ssl_key_file` parameter. The Postgres server will identify himself and encrypt the connection with this private key.
3744

38-
If you pass `server.cert.pem`, you should pass `server.key.pem` too, and viceversa, or TLS encryption will not be properly configured. You also need both of them if you use `client.ca.cert.pem`.
45+
If you pass `server.cert.pem`, you should pass `server.key.pem` too, and vice versa, or TLS encryption will not be properly configured. You also need both of them if you use `client.ca.cert.pem`.
3946

4047
It is safer to mount files with secrets instead of passing a JSON string in an env variable. You can mount the equivalents:
4148

@@ -67,7 +74,7 @@ Some placeholders can be expanded. See the [`Dockerfile`][] to know them.
6774

6875
#### `LAN_TLS`
6976

70-
Wether to enable or not TLS in LAN connections.
77+
Whether to enable or not TLS in LAN connections.
7178

7279
#### `LAN_USERS`
7380

@@ -93,8 +100,27 @@ Some placeholders can be expanded. See the [`Dockerfile`][] to know them.
93100

94101
#### `WAN_TLS`
95102

96-
Wether to enable or not TLS in WAN connections.
103+
Whether to enable or not TLS in WAN connections.
97104

98105
#### `WAN_USERS`
99106

100107
Users allowed to connect from WAN.
108+
109+
#### `HBA_EXTRA_RULES`
110+
111+
JSON array of additional `pg_hba.conf` rules to append. Each array element should be a string representing a valid `pg_hba.conf` line.
112+
113+
Example `HBA_EXTRA_RULES` format in an `.env` file:
114+
115+
```
116+
HBA_EXTRA_RULES=["host all all 192.168.1.0/24 md5", "hostssl mydb myuser 10.0.0.0/8 scram-sha-256"]
117+
```
118+
119+
This adds the following lines to `pg_hba.conf`:
120+
121+
```
122+
host all all 192.168.1.0/24 md5
123+
hostssl mydb myuser 10.0.0.0/8 scram-sha-256
124+
```
125+
126+
[`Dockerfile`]: https://github.com/openspp/docker-postgres-autoconf/blob/master/Dockerfile

autoconf-entrypoint

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ from itertools import product
99

1010
import netifaces
1111

12+
1213
SUPPORTED_CERTS = {
1314
"ssl_ca_file": "client.ca.cert.pem",
1415
"ssl_cert_file": "server.cert.pem",
@@ -33,6 +34,7 @@ WAN_USERS = json.loads(os.environ["WAN_USERS"])
3334
PGSSLCERT = os.environ.get("PGSSLCERT")
3435
PGSSLKEY = os.environ.get("PGSSLKEY")
3536
PGSSLROOTCERT = os.environ.get("PGSSLROOTCERT")
37+
HBA_EXTRA_RULES = os.environ.get("HBA_EXTRA_RULES", "")
3638

3739
# Configuration file templates
3840
CONF_FOLDER = "/etc/postgres"
@@ -50,17 +52,20 @@ local all all trust
5052
local replication all trust
5153
5254
# LAN/WAN autogenerated configurations
55+
{extra_hba}
5356
{extra_conf}
5457
"""
5558
WAN_CIDRS = ("0.0.0.0/0", "::0/0")
5659

5760
# Configuration helpers
5861
hba_conf = []
5962
ssl_conf = []
63+
extra_hba = []
6064

6165

6266
def permissions_fix(filename, client=False):
6367
"""Make :param:`filename` be owned by root user and postgres group."""
68+
6469
shutil.chown(filename, "root", "postgres")
6570
if client:
6671
os.chmod(filename, stat.S_IRUSR | stat.S_IWUSR)
@@ -86,6 +91,17 @@ for filen in (PGSSLCERT, PGSSLKEY, PGSSLROOTCERT):
8691
if ssl_conf:
8792
ssl_conf.append("ssl = on")
8893

94+
# Parse extra rules for pg_hba.conf
95+
extra_hba_rules = []
96+
if HBA_EXTRA_RULES:
97+
try:
98+
extra_hba_rules = json.loads(HBA_EXTRA_RULES)
99+
if not isinstance(extra_hba_rules, list):
100+
raise ValueError("HBA_EXTRA_RULES must be a JSON array")
101+
except json.JSONDecodeError:
102+
print("Invalid JSON in HBA_EXTRA_RULES", file=sys.stderr)
103+
sys.exit(1)
104+
89105
# Generate LAN auth configuration
90106
for interface in netifaces.interfaces():
91107
for type_, addresses in netifaces.ifaddresses(interface).items():
@@ -123,6 +139,13 @@ if WAN_CONNECTION != "hostssl" or ssl_conf:
123139
)
124140
)
125141

142+
# Append extra rules to extra_hba
143+
for rule in extra_hba_rules:
144+
if not isinstance(rule, str):
145+
print("Each rule in HBA_EXTRA_RULES must be a string", file=sys.stderr)
146+
sys.exit(1)
147+
extra_hba.append(rule)
148+
126149
# Write postgres configuration files
127150
with open(CONF_FILE, "w") as conf_file:
128151
conf_file.write(
@@ -132,7 +155,9 @@ with open(CONF_FILE, "w") as conf_file:
132155
)
133156
permissions_fix(CONF_FILE)
134157
with open(HBA_FILE, "w") as conf_file:
135-
conf_file.write(HBA_TPL.format(extra_conf="\n".join(hba_conf)))
158+
conf_file.write(
159+
HBA_TPL.format(extra_hba="\n".join(extra_hba), extra_conf="\n".join(hba_conf))
160+
)
136161
permissions_fix(HBA_FILE)
137162

138163
# Continue normal execution

tests/certgen

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
# See https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-CERTIFICATE-CREATION
3+
4+
domain="${1:-example.com}"
5+
client_name="${2:-test_user}"
6+
7+
### Server certificates (to encrypt connection)
8+
9+
# Generate server Certificate Signing Request (CSR) and Private Key (PK) for
10+
# the Certificate Authority (CA)
11+
openssl req -new -text -out server.ca.csr.pem -newkey rsa:4096 -nodes \
12+
-keyout server.ca.key.pem -subj "/CN=server.ca.$domain"
13+
# Generate server CA certificate
14+
openssl x509 -req -in server.ca.csr.pem -text -days 3650 -extensions v3_ca \
15+
-signkey server.ca.key.pem -out server.ca.cert.pem
16+
# Generate server CSR and private key
17+
openssl req -new -nodes -text -out server.csr.pem -newkey rsa:4096 \
18+
-keyout server.key.pem -subj "/CN=$domain"
19+
# Generate server certificate signed by the server CA
20+
openssl x509 -req -in server.csr.pem -text -days 3650 \
21+
-CA server.ca.cert.pem -CAkey server.ca.key.pem -CAcreateserial \
22+
-out server.cert.pem
23+
24+
### Client certificatess (for cert auth instead of password)
25+
26+
# Generate CSR and PK for client CA
27+
openssl req -new -text -out client.ca.csr.pem -newkey rsa:4096 -nodes \
28+
-keyout client.ca.key.pem -subj "/CN=client.ca.$domain"
29+
# Generate client CA certificate
30+
openssl x509 -req -in client.ca.csr.pem -text -days 3650 -extensions v3_ca \
31+
-signkey client.ca.key.pem -out client.ca.cert.pem
32+
# Generate client CSR and private key
33+
openssl req -new -nodes -text -out client.csr.pem -newkey rsa:4096 -nodes \
34+
-keyout client.key.pem -subj "/CN=$client_name"
35+
# Generate client certificate signed by the client CA
36+
openssl x509 -req -in client.csr.pem -text -days 3650 \
37+
-CA client.ca.cert.pem -CAkey client.ca.key.pem -CAcreateserial \
38+
-out client.cert.pem
39+
40+
### Final touches
41+
42+
# Fix permissions
43+
chmod u=rw,go= *.pem
44+
# Delete CSR, no longer needed
45+
rm *.csr.pem

tests/ci-requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
plumbum
2+
pre-commit

0 commit comments

Comments
 (0)