# syntax=docker/dockerfile:1

# KeepOrg synchronization server.
#
# The server is a static binary with no third-party dependencies and no cgo,
# so the runtime image carries the binary, a certificate bundle for talking
# to an OIDC provider, and nothing else. There is no shell in it: the binary
# probes its own health.
#
#   podman build --format docker -t keeporgd:0.3.0 --build-arg VERSION=0.3.0 .
#   docker build -t keeporgd:0.3.0 --build-arg VERSION=0.3.0 .
#
# podman needs --format docker, because the OCI image format has no
# HEALTHCHECK field and drops it silently.
#
# or `make docker`, which takes the version from versions.mk.

FROM golang:1.24-alpine AS build

ARG VERSION=dev
WORKDIR /src

# Only what the server is built from, so a change to the clients, the
# Android app or the docs does not invalidate this layer.
COPY go.mod ./
COPY cmd/keeporgd ./cmd/keeporgd
COPY internal ./internal

RUN CGO_ENABLED=0 GOOS=linux go build \
        -trimpath \
        -ldflags "-s -w -X main.Version=${VERSION}" \
        -o /out/keeporgd ./cmd/keeporgd

# Empty directories to copy into the scratch image with the right owner.
# There is no shell there to create them later.
RUN mkdir -p /out/var/lib/keeporg /out/etc/keeporg


FROM scratch

ARG VERSION=dev
LABEL org.opencontainers.image.title="KeepOrg server" \
      org.opencontainers.image.description="Synchronization server for collaborative KeePass databases" \
      org.opencontainers.image.version="${VERSION}" \
      org.opencontainers.image.source="https://garage.rcmd.space/keeporg" \
      org.opencontainers.image.licenses="AGPL-3.0-or-later" \
      cc.tiredsysadmin.application="cc.tiredsysadmin.linux.keeporgd"

# Needed to reach an OIDC provider over TLS. Nothing else from the builder
# comes along.
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

# The data directory holds state.json and the KDBX blobs. The configuration
# directory holds server.json and, unless the key is supplied through
# KEEPORG_MASTER_KEY, the master key that unwraps the vault keys. They are
# separate on purpose: whoever holds both can read every merge vault.
#
# Give the master key somewhere durable, one of these two ways:
#
#   -e KEEPORG_MASTER_KEY="$(head -c 32 /dev/urandom | base64)"   (preferred)
#   -v keeporg-config:/etc/keeporg
#
# With neither, the server mints a key into the container's own layer on
# first start and loses it on the next `run`. It says so loudly at startup,
# and merging is all that stops working: clients still open their vaults.
COPY --from=build --chown=65532:65532 /out/var/lib/keeporg /var/lib/keeporg
COPY --from=build --chown=65532:65532 /out/etc/keeporg /etc/keeporg
VOLUME ["/var/lib/keeporg", "/etc/keeporg"]

COPY --from=build /out/keeporgd /keeporgd

# A fixed unprivileged id, matching the convention used by distroless.
USER 65532:65532
EXPOSE 8765

# The image has no shell, so the binary checks itself.
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
    CMD ["/keeporgd", "-healthcheck", "-addr", ":8765"]

ENTRYPOINT ["/keeporgd"]
CMD ["-addr", ":8765", "-data", "/var/lib/keeporg"]
