# syntax=docker/dockerfile:1.6
# Alpine-based slim PostgreSQL 17 image with Nix extensions

####################
# Stage 1: Nix builder
####################
FROM alpine:3.23 AS nix-builder

# Install dependencies for nix installer (coreutils for GNU cp, sudo for installer)
RUN apk add --no-cache \
    bash \
    coreutils \
    curl \
    shadow \
    sudo \
    xz

# Create users (Alpine syntax)
RUN addgroup -S postgres && \
    adduser -S -h /var/lib/postgresql -s /bin/bash -G postgres postgres && \
    addgroup -S wal-g && \
    adduser -S -s /bin/bash -G wal-g wal-g

# Create nix config
RUN cat <<EOF > /tmp/extra-nix.conf
extra-experimental-features = nix-command flakes
extra-substituters = https://nix-postgres-artifacts.s3.amazonaws.com
extra-trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI=
EOF
ARG NIX_VERSION=2.35.3
ARG NIX_INSTALLER_HASH=69d0fe8fba8fe88f94c98b09964691ac9950abc7ecbf2ba861dc0533cfd901e9
RUN curl -fsSL "https://releases.nixos.org/nix/nix-$NIX_VERSION/install" -o /tmp/nix-install && \
    echo "$NIX_INSTALLER_HASH  /tmp/nix-install" | sha256sum -c - && \
    sh /tmp/nix-install --daemon --no-channel-add --yes --nix-extra-conf-file /tmp/extra-nix.conf && \
    rm /tmp/nix-install
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
RUN nix --version

WORKDIR /nixpg
COPY . .

# Build PostgreSQL with extensions
RUN nix profile add path:.#psql_17_slim/bin

RUN nix store gc

# Build groonga and copy plugins
RUN nix profile add path:.#supabase-groonga && \
    mkdir -p /tmp/groonga-plugins && \
    cp -r /nix/var/nix/profiles/default/lib/groonga/plugins /tmp/groonga-plugins/

RUN nix store gc

####################
# Stage 2: Upstream entrypoint
####################
# Pinned to an image whose entrypoint matches docker-library/postgres@6edb0a8c.
FROM postgres:17.8-alpine3.23@sha256:3430fe182f5065a6ea505c3d432d2c7fff18fbab954df8f277c1dbf4c70124af AS entrypoint

# Upstream drops privileges with gosu; we use su-exec from Alpine instead
RUN sed -i 's/exec gosu postgres/exec su-exec postgres/' /usr/local/bin/docker-entrypoint.sh && \
    ! grep -q gosu /usr/local/bin/docker-entrypoint.sh

####################
# Stage 3: Final production image
####################
FROM alpine:3.23 AS production

# Install minimal runtime dependencies
RUN apk add --no-cache \
    bash \
    'ca-certificates-bundle>=20261020-r0' \
    curl \
    shadow \
    su-exec \
    tzdata \
    musl-locales \
    musl-locales-lang \
    && rm -rf /var/cache/apk/*

# Create postgres user/group
RUN addgroup -S postgres && \
    adduser -S -G postgres -h /var/lib/postgresql -s /bin/bash postgres && \
    addgroup -S wal-g && \
    adduser -S -G wal-g -s /bin/bash wal-g && \
    adduser postgres wal-g

# Copy Nix store and profiles from builder (profile already created by nix profile install)
COPY --from=nix-builder /nix /nix

# Copy groonga plugins
COPY --from=nix-builder /tmp/groonga-plugins/plugins /usr/lib/groonga/plugins

# Setup PostgreSQL directories
RUN mkdir -p /usr/lib/postgresql/bin \
    /usr/lib/postgresql/share/postgresql \
    /usr/share/postgresql \
    /var/lib/postgresql/data \
    /var/run/postgresql \
    && chown -R postgres:postgres /usr/lib/postgresql \
    && chown -R postgres:postgres /var/lib/postgresql \
    && chown -R postgres:postgres /usr/share/postgresql \
    && chown -R postgres:postgres /var/run/postgresql

# Create symbolic links for binaries
RUN for f in /nix/var/nix/profiles/default/bin/*; do \
        ln -sf "$f" /usr/lib/postgresql/bin/ 2>/dev/null || true; \
        ln -sf "$f" /usr/bin/ 2>/dev/null || true; \
    done

# Create symbolic links for PostgreSQL shares
RUN ln -sf /nix/var/nix/profiles/default/share/postgresql/* /usr/lib/postgresql/share/postgresql/ 2>/dev/null || true && \
    ln -sf /nix/var/nix/profiles/default/share/postgresql/* /usr/share/postgresql/ 2>/dev/null || true && \
    ln -sf /usr/lib/postgresql/share/postgresql/timezonesets /usr/share/postgresql/timezonesets 2>/dev/null || true

# Set permissions
RUN chown -R postgres:postgres /usr/lib/postgresql && \
    chown -R postgres:postgres /usr/share/postgresql

# Setup configs
COPY --chown=postgres:postgres ansible/files/postgresql_config/postgresql.conf.j2 /etc/postgresql/postgresql.conf
COPY --chown=postgres:postgres ansible/files/postgresql_config/pg_hba.conf.j2 /etc/postgresql/pg_hba.conf
COPY --chown=postgres:postgres ansible/files/postgresql_config/pg_ident.conf.j2 /etc/postgresql/pg_ident.conf
COPY --chown=postgres:postgres ansible/files/postgresql_config/conf.d /etc/postgresql-custom/conf.d
COPY --chown=postgres:postgres ansible/files/postgresql_config/postgresql-stdout-log.conf /etc/postgresql/logging.conf
COPY --chown=postgres:postgres ansible/files/postgresql_config/supautils.conf.j2 /etc/postgresql-custom/supautils.conf
COPY --chown=postgres:postgres ansible/files/postgresql_extension_custom_scripts /etc/postgresql-custom/extension-custom-scripts
COPY --chown=postgres:postgres ansible/files/pgsodium_getkey_urandom.sh.j2 /usr/lib/postgresql/bin/pgsodium_getkey.sh
COPY --chown=postgres:postgres ansible/files/postgresql_config/custom_walg.conf /etc/postgresql-custom/wal-g.conf
COPY --chown=postgres:postgres ansible/files/postgresql_config/custom_read_replica.conf /etc/postgresql-custom/read-replica.conf
COPY --chown=postgres:postgres ansible/files/walg_helper_scripts/wal_fetch.sh /home/postgres/wal_fetch.sh
COPY ansible/files/walg_helper_scripts/wal_change_ownership.sh /root/wal_change_ownership.sh

# Configure PostgreSQL settings
RUN sed -i \
    -e "s|#unix_socket_directories = '/tmp'|unix_socket_directories = '/var/run/postgresql'|g" \
    -e "s|#session_preload_libraries = ''|session_preload_libraries = 'supautils'|g" \
    -e "s|#include = '/etc/postgresql-custom/supautils.conf'|include = '/etc/postgresql-custom/supautils.conf'|g" \
    -e "s|#include = '/etc/postgresql-custom/wal-g.conf'|include = '/etc/postgresql-custom/wal-g.conf'|g" /etc/postgresql/postgresql.conf && \
    echo "pgsodium.getkey_script= '/usr/lib/postgresql/bin/pgsodium_getkey.sh'" >> /etc/postgresql/postgresql.conf && \
    echo "vault.getkey_script= '/usr/lib/postgresql/bin/pgsodium_getkey.sh'" >> /etc/postgresql/postgresql.conf && \
    chown -R postgres:postgres /etc/postgresql-custom

# Remove timescaledb and plv8 references (not in pg17)
RUN sed -i 's/ timescaledb,//g;' "/etc/postgresql/postgresql.conf" && \
    sed -i 's/db_user_namespace = off/#db_user_namespace = off/g;' "/etc/postgresql/postgresql.conf" && \
    sed -i 's/^#summarize_wal = off/summarize_wal = on/' "/etc/postgresql/postgresql.conf" && \
    sed -i 's/ timescaledb,//g; s/ plv8,//g' "/etc/postgresql-custom/supautils.conf"

# Include schema migrations
COPY migrations/db /docker-entrypoint-initdb.d/
COPY ansible/files/pgbouncer_config/pgbouncer_auth_schema.sql /docker-entrypoint-initdb.d/init-scripts/00-schema.sql
COPY ansible/files/stat_extension.sql /docker-entrypoint-initdb.d/migrations/00-extension.sql

# Add entrypoint script
COPY --from=entrypoint --chmod=0755 /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh

# Setup pgsodium key script
RUN mkdir -p /usr/share/postgresql/extension/ && \
    ln -s /usr/lib/postgresql/bin/pgsodium_getkey.sh /usr/share/postgresql/extension/pgsodium_getkey && \
    chmod +x /usr/lib/postgresql/bin/pgsodium_getkey.sh

# Environment variables
ENV PATH="/nix/var/nix/profiles/default/bin:/usr/lib/postgresql/bin:${PATH}"
ENV PGDATA=/var/lib/postgresql/data
ENV POSTGRES_HOST=/var/run/postgresql
ENV POSTGRES_USER=supabase_admin
ENV POSTGRES_DB=postgres
ENV POSTGRES_INITDB_ARGS="--allow-group-access --locale-provider=icu --encoding=UTF-8 --icu-locale=en_US.UTF-8"
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV GRN_PLUGINS_DIR=/usr/lib/groonga/plugins
# Point to minimal glibc locales included in slim Nix package for initdb locale support
ENV LOCALE_ARCHIVE=/nix/var/nix/profiles/default/lib/locale/locale-archive

ENTRYPOINT ["docker-entrypoint.sh"]
HEALTHCHECK --interval=2s --timeout=2s --retries=10 CMD pg_isready -U postgres -h localhost
STOPSIGNAL SIGINT
EXPOSE 5432

CMD ["postgres", "-D", "/etc/postgresql"]
