Use symlinks fix logic

This commit is contained in:
alexbelgium
2025-05-30 13:49:50 +02:00
parent b0203a0d12
commit a9a4f432e6
9 changed files with 11 additions and 654 deletions

View File

@@ -39,5 +39,5 @@
"slug": "postgres",
"udev": true,
"url": "https://github.com/alexbelgium/hassio-addons/tree/master/postgres",
"version": "15.7-41"
"version": "15.7-42"
}

View File

@@ -272,11 +272,11 @@ upgrade_postgres_if_needed() {
exit 1
fi
drop_vectors_everywhere "$CLUSTER_VERSION"
cp -n --preserve=mode "/var/postgresql-conf-tpl/postgresql.hdd.conf" /etc/postgresql/postgresql.conf
sed -i "s@##PGDATA@$PGDATA@" /etc/postgresql/postgresql.conf
drop_vectors_everywhere "$CLUSTER_VERSION"
fix_permissions
bashio::log.info "Starting old Postgres ($CLUSTER_VERSION) to capture encoding/locale settings"
@@ -326,7 +326,9 @@ upgrade_postgres_if_needed() {
main() {
bashio::log.info "Checking for required PostgreSQL cluster upgrade before server start..."
upgrade_postgres_if_needed
if [ -f /config/database/PG_VERSION]; then
upgrade_postgres_if_needed
fi
start_postgres

View File

@@ -1,124 +0,0 @@
#============================#
# ALEXBELGIUM'S DOCKERFILE #
#============================#
# _.------.
# _.-` ('>.-`"""-.
# '.--'` _'` _ .--.)
# -' '-.-';` `
# ' - _.' ``'--.
# '---` .-'""`
# /`
#=== Home Assistant Addon ===#
#################
# 1 Build Image #
#################
ARG BUILD_FROM
ARG BUILD_VERSION
FROM $BUILD_FROM
##################
# 2 Modify Image #
##################
# Set S6 wait time
ENV S6_CMD_WAIT_FOR_SERVICES=1 \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_SERVICES_GRACETIME=0
RUN \
# Correct for access
for file in /usr/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample; do \
if [ -f "$file" ]; then sed -i "s|.*listen_addresses(.*)|listen_addresses = '*'(1)|g" "$file" && \
sed -i "s|.*data_directory(.*)|data_directory = '/config/database'(1)|g" "$file"; fi; done
##################
# 3 Install apps #
##################
# Add rootfs
COPY rootfs/ /
# Uses /bin for compatibility purposes
# hadolint ignore=DL4005
RUN if [ ! -f /bin/sh ] && [ -f /usr/bin/sh ]; then ln -s /usr/bin/sh /bin/sh; fi && \
if [ ! -f /bin/bash ] && [ -f /usr/bin/bash ]; then ln -s /usr/bin/bash /bin/bash; fi
# Modules
ARG MODULES="00-banner.sh 01-custom_script.sh 00-global_var.sh"
# Automatic modules download
ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_automodules.sh" "/ha_automodules.sh"
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
# Manual apps
ENV PACKAGES=""
# Automatic apps & bashio
ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_autoapps.sh" "/ha_autoapps.sh"
RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh
################
# 4 Entrypoint #
################
# Add entrypoint
ENV S6_STAGE2_HOOK=/ha_entrypoint.sh
ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_entrypoint.sh" "/ha_entrypoint.sh"
# Entrypoint modifications
ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_entrypoint_modif.sh" "/ha_entrypoint_modif.sh"
RUN chmod 777 /ha_entrypoint.sh /ha_entrypoint_modif.sh && /ha_entrypoint_modif.sh && rm /ha_entrypoint_modif.sh
RUN sed -i "/Termination signal received/a gosu postgres pg_ctl -D \"\$PGDATA\" -m fast stop" /ha_entrypoint.sh
WORKDIR /config
ENTRYPOINT [ "/usr/bin/env" ]
CMD [ "/ha_entrypoint.sh" ]
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
############
# 5 Labels #
############
ARG BUILD_ARCH
ARG BUILD_DATE
ARG BUILD_DESCRIPTION
ARG BUILD_NAME
ARG BUILD_REF
ARG BUILD_REPOSITORY
ARG BUILD_VERSION
ENV BUILD_VERSION="${BUILD_VERSION}"
LABEL \
io.hass.name="${BUILD_NAME}" \
io.hass.description="${BUILD_DESCRIPTION}" \
io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \
io.hass.version=${BUILD_VERSION} \
maintainer="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.title="${BUILD_NAME}" \
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
org.opencontainers.image.vendor="Home Assistant Add-ons" \
org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.url="https://github.com/alexbelgium" \
org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \
org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \
org.opencontainers.image.created=${BUILD_DATE} \
org.opencontainers.image.revision=${BUILD_REF} \
org.opencontainers.image.version=${BUILD_VERSION}
#################
# 6 Healthcheck #
#################
ENV HEALTH_PORT="" \
HEALTH_URL=""
HEALTHCHECK \
--interval=5s \
--retries=5 \
--start-period=90s \
--timeout=25s \
CMD pg_isready -d postgres || exit 1

1
postgres_17/Dockerfile Symbolic link
View File

@@ -0,0 +1 @@
../postgres_15/Dockerfile

View File

@@ -1,65 +0,0 @@
# Home assistant add-on: Postgres
[![Donate][donation-badge]](https://www.buymeacoffee.com/alexbelgium)
[![Donate][paypal-badge]](https://www.paypal.com/donate/?hosted_button_id=DZFULJZTP3UQA)
![Version](https://img.shields.io/badge/dynamic/json?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fpostgres%2Fconfig.json)
![Ingress](https://img.shields.io/badge/dynamic/json?label=Ingress&query=%24.ingress&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fpostgres%2Fconfig.json)
![Arch](https://img.shields.io/badge/dynamic/json?color=success&label=Arch&query=%24.arch&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fpostgres%2Fconfig.json)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9c6cf10bdbba45ecb202d7f579b5be0e)](https://www.codacy.com/gh/alexbelgium/hassio-addons/dashboard?utm_source=github.com&utm_medium=referral&utm_content=alexbelgium/hassio-addons&utm_campaign=Badge_Grade)
[![GitHub Super-Linter](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/weekly-supelinter.yaml?label=Lint%20code%20base)](https://github.com/alexbelgium/hassio-addons/actions/workflows/weekly-supelinter.yaml)
[![Builder](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/onpush_builder.yaml?label=Builder)](https://github.com/alexbelgium/hassio-addons/actions/workflows/onpush_builder.yaml)
[donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee%20(no%20paypal)-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white
[paypal-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee%20with%20Paypal-0070BA?logo=paypal&style=flat&logoColor=white
_Thanks to everyone having starred my repo! To star it click on the image below, then it will be on top right. Thanks!_
[![Stargazers repo roster for @alexbelgium/hassio-addons](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.github/stars2.svg)](https://github.com/alexbelgium/hassio-addons/stargazers)
![downloads evolution](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/postgres/stats.png)
## About
PostgreSQL, often simply "Postgres", is an object-relational database management system (ORDBMS) with an emphasis on extensibility and standards-compliance. As a database server, its primary function is to store data, securely and supporting best practices, and retrieve it later, as requested by other software applications, be it those on the same computer or those running on another computer across a network (including the Internet). It can handle workloads ranging from small single-machine applications to large Internet-facing applications with many concurrent users. Recent versions also provide replication of the database itself for security and scalability.
This addon is based on the official image : https://hub.docker.com/_/postgres
## Configuration
Postgres port is by default 5432 and is exposed to the host network.
default user: `postgres`
password: `set by POSTGRES_PASSWORD`
You can configure this options:
```yaml
POSTGRES_PASSWORD
POSTGRES_USER
POSTGRES_DB
POSTGRES_INITDB_ARGS
POSTGRES_HOST_AUTH_METHOD
```
For more info check [base image docs](https://hub.docker.com/_/postgres).
By default `postgresql.conf` is stored in volume accessible by other addons and Home Assistant, so you can conviniently modify it by e.g. File Editor addon. If you prefer better security change `CONFIG_LOCATION` to e.g. `/data/orig/postgresql.conf`, so it will be acessible only to this addon, but you will have to modify it by the [Hassio SSH](https://developers.home-assistant.io/docs/operating-system/debugging/).
## Installation
The installation of this add-on is pretty straightforward and not different in comparison to installing any other add-on.
1. Add my add-ons repository to your home assistant instance (in supervisor addons store at top right, or click button below if you have configured my HA)
[![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons)
1. Install this add-on.
1. Click the `Save` button to store your configuration.
1. Set the add-on options to your preferences, at least POSTGRES_PASSWORD is required.
1. Start the add-on.
1. Check the logs of the add-on to see if everything went well.
1. Use any Postgres client to connect, e.g. to `homeassistant.local:5432`
## Support
Create an issue on github
[repository]: https://github.com/alexbelgium/hassio-addons

1
postgres_17/README.md Symbolic link
View File

@@ -0,0 +1 @@
../postgres_15/README.md

View File

@@ -1,70 +0,0 @@
#include <tunables/global>
profile postgres_addon flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
capability,
file,
signal,
mount,
umount,
remount,
network udp,
network tcp,
network dgram,
network stream,
network inet,
network inet6,
network netlink raw,
network unix dgram,
capability setgid,
capability setuid,
capability sys_admin,
capability dac_read_search,
capability dac_override,
# capability sys_rawio,
# S6-Overlay
/init ix,
/run/{s6,s6-rc*,service}/** ix,
/package/** ix,
/command/** ix,
/run/{,**} rwk,
/dev/tty rw,
/bin/** ix,
/usr/bin/** ix,
/usr/lib/bashio/** ix,
/etc/s6/** rix,
/run/s6/** rix,
/etc/services.d/** rwix,
/etc/cont-init.d/** rwix,
/etc/cont-finish.d/** rwix,
/init rix,
/var/run/** mrwkl,
/var/run/ mrwkl,
/dev/i2c-1 mrwkl,
# Files required
/dev/fuse mrwkl,
/dev/sda1 mrwkl,
/dev/sdb1 mrwkl,
/dev/nvme0 mrwkl,
/dev/nvme1 mrwkl,
/dev/mmcblk0p1 mrwkl,
/dev/* mrwkl,
/udev/* mrwkl,
/tmp/** mrkwl,
/dev/fuse/** mrkwl,
/dev/** mrkwl,
/sys/firmware/** mrkwl,
# Data access
/data/** rw,
# suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
ptrace (trace,read) peer=docker-default,
# docker daemon confinement requires explict allow rule for signal
signal (receive) set=(kill,term) peer=/usr/bin/docker,
}

1
postgres_17/apparmor.txt Symbolic link
View File

@@ -0,0 +1 @@
../postgres_15/apparmor.txt

View File

@@ -38,5 +38,5 @@
"slug": "postgres_latest",
"udev": true,
"url": "https://github.com/alexbelgium/hassio-addons/tree/master/postgres",
"version": "17.1"
"version": "17.5-1"
}

1
postgres_17/rootfs/etc Symbolic link
View File

@@ -0,0 +1 @@
../../postgres_15/rootfs/etc

View File

@@ -1,21 +0,0 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
# Migration
if [ -d /data/database ]; then
bashio::log.warning "Database migrated to /config"
mv /data/database /config
fi
if [ -f /homeassistant/addons_config/postgres/config.yaml ]; then
bashio::log.warning "Config migrated to /config"
mv /homeassistant/addons_config/postgres/* /config/
rm -r /homeassistant/addons_config/postgres
# Correct database location
sed -i "s|/data/database|/config/database|g" /config/postgresql.conf
fi
# touch sql file
touch /setup_postgres.sql
chmod 755 /setup_postgres.sql

View File

@@ -1,369 +0,0 @@
#!/usr/bin/env bashio
# shellcheck shell=bash
set -euo pipefail
CONFIG_HOME="/config"
PGDATA="${PGDATA:-/config/database}"
export PGDATA
PG_MAJOR_VERSION="${PG_MAJOR:-15}"
RESTART_FLAG_FILE="$CONFIG_HOME/restart_needed"
fix_permissions() {
mkdir -p "$PGDATA"
chown -R postgres:postgres "$PGDATA"
chmod 700 "$PGDATA"
}
chmod -R 755 "$CONFIG_HOME"
RESTART_NEEDED=false
cd /config || true
get_pgdata_version() {
if [ -f "$PGDATA/PG_VERSION" ]; then
cat "$PGDATA/PG_VERSION"
else
bashio::log.error "FATAL: $PGDATA/PG_VERSION not found; cannot determine cluster version."
exit 1
fi
}
extract_so_from_deb() {
local debfile="$1"
local targetdir="$2"
local sofile="$3"
local tmpdir
tmpdir=$(mktemp -d)
dpkg-deb -x "$debfile" "$tmpdir"
find "$tmpdir" -name "$sofile" -exec cp {} "$targetdir" \;
rm -rf "$tmpdir"
}
install_vchord_and_vectors_for_old_pg() {
local old_pgver="$1"
local vectorchord_tag="${VECTORCHORD_TAG:-0.3.0}"
local pgvectors_tag="${PGVECTORS_TAG:-0.3.0}"
case "$(uname -m)" in
x86_64 | amd64 | AMD64 | x86-64)
targetarch=amd64
;;
aarch64 | arm64 | ARM64)
targetarch=arm64
;;
*)
echo "Unsupported architecture: $(uname -m)"
exit 1
;;
esac
local vchord_url
local vectors_url
local vchord_deb
local vectors_deb
local old_pg_lib="/usr/lib/postgresql/$old_pgver/lib"
mkdir -p "$old_pg_lib"
vchord_url="https://github.com/tensorchord/VectorChord/releases/download/${vectorchord_tag}/postgresql-${old_pgver}-vchord_${vectorchord_tag}-1_${targetarch}.deb"
vchord_deb="/tmp/vchord-${old_pgver}.deb"
bashio::log.info "Downloading $vchord_url"
wget -nv -O "$vchord_deb" "$vchord_url"
extract_so_from_deb "$vchord_deb" "$old_pg_lib" "vchord.so"
rm -f "$vchord_deb"
vectors_url="https://github.com/tensorchord/pgvecto.rs/releases/download/v${pgvectors_tag}/vectors-pg${old_pgver}_${pgvectors_tag}_${targetarch}.deb"
vectors_deb="/tmp/pgvectors-${old_pgver}.deb"
bashio::log.info "Downloading $vectors_url"
wget -nv -O "$vectors_deb" "$vectors_url"
extract_so_from_deb "$vectors_deb" "$old_pg_lib" "vectors.so"
rm -f "$vectors_deb"
}
drop_vectors_everywhere() {
local old_pgver="$1"
su - postgres -c "$BINARIES_DIR/$old_pgver/bin/pg_ctl \
-w -D '$PGDATA' -o \"-c config_file=/etc/postgresql/postgresql.conf \
-c listen_addresses='' -c port=65432\" start"
for db in $(su - postgres -c \
"$BINARIES_DIR/$old_pgver/bin/psql -Atc \
\"SELECT datname FROM pg_database WHERE datistemplate = false AND datallowconn\""); do
if su - postgres -c \
"$BINARIES_DIR/$old_pgver/bin/psql -d $db -Atc \
\"SELECT 1 FROM pg_extension WHERE extname='vectors'\"" \
| grep -q 1; then
bashio::log.warning "Dropping extension vectors from DB $db"
su - postgres -c \
"$BINARIES_DIR/$old_pgver/bin/psql -d $db -c \
'DROP EXTENSION vectors CASCADE;'"
fi
done
su - postgres -c "$BINARIES_DIR/$old_pgver/bin/pg_ctl -w -D '$PGDATA' stop"
}
start_postgres() {
bashio::log.info "Starting PostgreSQL..."
if [ "$(bashio::info.arch)" = "armv7" ]; then
bashio::log.warning "ARMv7 detected: Starting without vectors.so"
/usr/local/bin/immich-docker-entrypoint.sh postgres & true
exit 0
else
/usr/local/bin/immich-docker-entrypoint.sh postgres -c config_file=/etc/postgresql/postgresql.conf & true
fi
}
wait_for_postgres() {
local tries=0
while ! pg_isready -h "$DB_HOSTNAME" -p "$DB_PORT" -U "$DB_USERNAME" >/dev/null 2>&1; do
tries=$((tries+1))
if [ "$tries" -ge 60 ]; then
bashio::log.error "Postgres did not start after 2 minutes, aborting."
exit 1
fi
echo "PostgreSQL is starting up... ($tries/60)"
sleep 2
done
}
restart_immich_addons_if_flagged() {
if [ -f "$RESTART_FLAG_FILE" ]; then
bashio::log.warning "Detected pending Immich add-on restart flag. Restarting all running Immich add-ons..."
local addons slug found=0
addons=$(curl -s -H "Authorization: Bearer $SUPERVISOR_TOKEN" http://supervisor/addons)
if command -v jq >/dev/null; then
for slug in $(echo "$addons" | jq -r '.data.addons[] | select(.state=="started") | .slug'); do
if [[ "$slug" == *immich* ]]; then
bashio::log.info "Restarting addon $slug"
curl -s -X POST -H "Authorization: Bearer $SUPERVISOR_TOKEN" "http://supervisor/addons/$slug/restart"
found=1
fi
done
else
for slug in $(echo "$addons" | grep -o '"slug":"[^"]*"' | cut -d: -f2 | tr -d '"'); do
if [[ "$slug" == *immich* ]]; then
bashio::log.info "Restarting addon $slug"
curl -s -X POST -H "Authorization: Bearer $SUPERVISOR_TOKEN" "http://supervisor/addons/$slug/restart"
found=1
fi
done
fi
if [ "$found" -eq 0 ]; then
bashio::log.info "No Immich-related addon found running."
fi
rm -f "$RESTART_FLAG_FILE"
fi
}
get_available_extension_version() {
local extname="$1"
psql "postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOSTNAME:$DB_PORT/postgres" -v ON_ERROR_STOP=1 -tAc \
"SELECT default_version FROM pg_available_extensions WHERE name = '$extname';" 2>/dev/null | xargs
}
is_extension_available() {
local extname="$1"
local result
result=$(psql "postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOSTNAME:$DB_PORT/postgres" -v ON_ERROR_STOP=1 -tAc \
"SELECT 1 FROM pg_available_extensions WHERE name = '$extname';" 2>/dev/null | xargs)
[[ "$result" == "1" ]]
}
get_user_databases() {
psql "postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOSTNAME:$DB_PORT/postgres" -v ON_ERROR_STOP=1 -tAc \
"SELECT datname FROM pg_database WHERE datistemplate = false AND datallowconn = true;"
}
get_installed_extension_version() {
local extname="$1"
local dbname="$2"
psql "postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOSTNAME:$DB_PORT/$dbname" -v ON_ERROR_STOP=1 -tAc \
"SELECT extversion FROM pg_extension WHERE extname = '$extname';" 2>/dev/null | xargs
}
compare_versions() {
local v1="$1"
local v2="$2"
if [ "$v1" = "$v2" ]; then return 1; fi
if [ "$(printf '%s\n' "$v1" "$v2" | sort -V | head -n1)" = "$v1" ]; then
return 0
fi
return 1
}
show_db_extensions() {
bashio::log.info "==== PostgreSQL databases and enabled extensions ===="
for db in $(get_user_databases); do
bashio::log.info "Database: $db"
exts=$(psql "postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOSTNAME:$DB_PORT/$db" -tAc \
"SELECT extname || ' (v' || extversion || ')' FROM pg_extension ORDER BY extname;")
if [ -n "$exts" ]; then
while read -r ext; do
[ -n "$ext" ] && bashio::log.info " - $ext"
done <<< "$exts"
else
bashio::log.info " (no extensions enabled)"
fi
done
bashio::log.info "=============================================="
}
upgrade_extension_if_needed() {
local extname="$1"
if ! is_extension_available "$extname"; then
bashio::log.info "$extname extension not available on this Postgres instance."
return
fi
local available_version
available_version=$(get_available_extension_version "$extname")
if [ -z "$available_version" ]; then
bashio::log.info "Could not determine available version for $extname."
return
fi
for db in $(get_user_databases); do
local installed_version
installed_version=$(get_installed_extension_version "$extname" "$db")
if [ -n "$installed_version" ]; then
if compare_versions "$installed_version" "$available_version"; then
bashio::log.info "Upgrading $extname in $db from $installed_version to $available_version"
if psql "postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOSTNAME@$DB_PORT/$db" -v ON_ERROR_STOP=1 -c "ALTER EXTENSION $extname UPDATE;"; then
RESTART_NEEDED=true
else
bashio::log.error "Failed to upgrade $extname in $db. Aborting startup."
exit 1
fi
else
bashio::log.info "$extname in $db already at latest version ($installed_version)"
fi
fi
done
}
upgrade_postgres_if_needed() {
CLUSTER_VERSION=$(get_pgdata_version)
IMAGE_VERSION="$PG_MAJOR_VERSION"
if [ "$CLUSTER_VERSION" != "$IMAGE_VERSION" ]; then
bashio::log.warning "Postgres data directory version is $CLUSTER_VERSION but image wants $IMAGE_VERSION. Running upgrade..."
export DATA_DIR="$PGDATA"
export BINARIES_DIR="/usr/lib/postgresql"
export BACKUP_DIR="/config/backups"
export PSQL_VERSION="$IMAGE_VERSION"
export SUPPORTED_POSTGRES_VERSIONS="$CLUSTER_VERSION $IMAGE_VERSION"
apt-get update &>/dev/null
apt-get install -y procps rsync "postgresql-$IMAGE_VERSION" "postgresql-$CLUSTER_VERSION"
if [ ! -d "$BINARIES_DIR/$CLUSTER_VERSION/bin" ]; then
bashio::log.error "Old postgres binaries not found at $BINARIES_DIR/$CLUSTER_VERSION/bin"
exit 1
fi
if [ ! -d "$BINARIES_DIR/$IMAGE_VERSION/bin" ]; then
bashio::log.error "New postgres binaries not found at $BINARIES_DIR/$IMAGE_VERSION/bin"
exit 1
fi
install_vchord_and_vectors_for_old_pg "$CLUSTER_VERSION"
mkdir -p "$BACKUP_DIR"
backup_target="$BACKUP_DIR/postgresql-$CLUSTER_VERSION"
bashio::log.info "Backing up data directory to $backup_target..."
if ! rsync -a --delete "$PGDATA/" "$backup_target/"; then
bashio::log.error "Backup with rsync failed!"
exit 1
fi
drop_vectors_everywhere "$CLUSTER_VERSION"
cp -n --preserve=mode "/var/postgresql-conf-tpl/postgresql.hdd.conf" /etc/postgresql/postgresql.conf
sed -i "s@##PGDATA@$PGDATA@" /etc/postgresql/postgresql.conf
fix_permissions
bashio::log.info "Starting old Postgres ($CLUSTER_VERSION) to capture encoding/locale settings"
su - postgres -c "$BINARIES_DIR/$CLUSTER_VERSION/bin/pg_ctl -w -D '$PGDATA' -o \"-c config_file=/etc/postgresql/postgresql.conf\" start"
LC_COLLATE=$(su - postgres -c "$BINARIES_DIR/$CLUSTER_VERSION/bin/psql -d postgres -Atc 'SHOW LC_COLLATE;'")
LC_CTYPE=$(su - postgres -c "$BINARIES_DIR/$CLUSTER_VERSION/bin/psql -d postgres -Atc 'SHOW LC_CTYPE;'")
ENCODING=$(su - postgres -c "$BINARIES_DIR/$CLUSTER_VERSION/bin/psql -d postgres -Atc 'SHOW server_encoding;'")
bashio::log.info "Detected cluster: LC_COLLATE=$LC_COLLATE, LC_CTYPE=$LC_CTYPE, ENCODING=$ENCODING"
bashio::log.info "Stopping old Postgres ($CLUSTER_VERSION)"
su - postgres -c "$BINARIES_DIR/$CLUSTER_VERSION/bin/pg_ctl -w -D '$PGDATA' -o \"-c config_file=/etc/postgresql/postgresql.conf\" stop"
rm -rf "$PGDATA"
fix_permissions
bashio::log.info "Initializing new data cluster for $IMAGE_VERSION"
su - postgres -c "$BINARIES_DIR/$IMAGE_VERSION/bin/initdb --encoding=$ENCODING --lc-collate=$LC_COLLATE --lc-ctype=$LC_CTYPE -D '$PGDATA'"
fix_permissions
bashio::log.info "Running pg_upgrade from $CLUSTER_VERSION$IMAGE_VERSION"
chmod 700 "$PGDATA"
chmod 700 "$backup_target"
if ! su - postgres -c "$BINARIES_DIR/$IMAGE_VERSION/bin/pg_upgrade \
-b '$BINARIES_DIR/$CLUSTER_VERSION/bin' \
-B '$BINARIES_DIR/$IMAGE_VERSION/bin' \
-d '$backup_target' \
-D '$PGDATA' -o \"-c config_file=/etc/postgresql/postgresql.conf\" -O \"-c config_file=/etc/postgresql/postgresql.conf\""; then
bashio::log.error "pg_upgrade failed!"
exit 1
fi
if [ -f "$backup_target/postgresql.conf" ]; then
cp "$backup_target/postgresql.conf" "$PGDATA"
fi
bashio::log.info "Upgrade completed successfully."
RESTART_NEEDED=true
else
bashio::log.info "PostgreSQL data directory version ($CLUSTER_VERSION) matches image version ($IMAGE_VERSION)."
fi
}
main() {
bashio::log.info "Checking for required PostgreSQL cluster upgrade before server start..."
upgrade_postgres_if_needed
start_postgres
bashio::log.info "Waiting for PostgreSQL to start..."
DB_PORT=5432
DB_HOSTNAME=localhost
DB_PASSWORD="$(bashio::config 'POSTGRES_PASSWORD')"
DB_PASSWORD="$(jq -rn --arg x "$DB_PASSWORD" '$x|@uri')"
DB_USERNAME=postgres
if bashio::config.has_value "POSTGRES_USER"; then
DB_USERNAME="$(bashio::config "POSTGRES_USER")"
fi
export DB_PORT DB_HOSTNAME DB_USERNAME DB_PASSWORD
wait_for_postgres
restart_immich_addons_if_flagged
su - postgres -c "psql -d postgres -c 'DROP EXTENSION IF EXISTS vectors CASCADE;'"
upgrade_extension_if_needed "vectors"
upgrade_extension_if_needed "vchord"
show_db_extensions
if [ "$RESTART_NEEDED" = true ]; then
bashio::log.warning "A critical update (Postgres or extension) occurred. Will trigger Immich add-on restart after DB comes back up."
touch "$RESTART_FLAG_FILE"
bashio::addon.restart
exit 0
fi
bashio::log.info "All initialization/version check steps completed successfully!"
if [ -d /config/backups ]; then
echo "Cleaning /config/backups now that upgrade is done"
rm -r /config/backups
fi
}
main