From e1a2d427c63f185fcb5de27f32c69f5f129813f9 Mon Sep 17 00:00:00 2001
From: Slavi Pantaleev <slavi@devture.com>
Date: Sat, 29 Mar 2025 08:01:27 +0200
Subject: [PATCH] Use multi-stage Dockerfile for building customized Synape

This also reverts e5574a405e43a51ab152e0e4cf760a3cc021adbe because:
- it was causing issues on some servers (not clear why)
- such workarounds are no longer necessary when doing multi-stage building.
---
 roles/custom/matrix-synapse/defaults/main.yml | 20 -----
 .../synapse/customizations/Dockerfile.j2      | 83 +++++++++----------
 2 files changed, 40 insertions(+), 63 deletions(-)

diff --git a/roles/custom/matrix-synapse/defaults/main.yml b/roles/custom/matrix-synapse/defaults/main.yml
index 4edb31d4e..335f1d0d2 100644
--- a/roles/custom/matrix-synapse/defaults/main.yml
+++ b/roles/custom/matrix-synapse/defaults/main.yml
@@ -52,26 +52,6 @@ matrix_synapse_container_image_customizations_s3_storage_provider_installation_e
 # https://github.com/aws/aws-cli/issues/9214
 matrix_synapse_container_image_customizations_s3_storage_provider_installation_old_boto_workaround_enabled: true
 
-# Controls whether to install libldapXX explicitly when installing s3-storage-provider.
-# This is to work around it potentially not being there (after `autoremove` invoked by other scripts cleans it up, etc.)
-#
-# Some scripts in the custom Dockerfile may install and then autoremove git/ssh/openssh-client.
-# This has the side-effect of removing the libldap library that s3-storage-provider depends upon indirectly (via psycopg2).
-#
-# If this should happen, s3-storage-provider (the `s3_media_upload` script) will fail to start with an error like this:
-# > Traceback (most recent call last):
-# >   File "/usr/local/bin/s3_media_upload", line 10, in <module>
-# >     import psycopg2
-# >   File "/usr/local/lib/python3.12/site-packages/psycopg2/__init__.py", line 51, in <module>
-# >     from psycopg2._psycopg import (                     # noqa
-# > ImportError: libldap-2.5.so.0: cannot open shared object file: No such file or directory
-#
-# The library (e.g. `/usr/lib/x86_64-linux-gnu/libldap-2.5.so.0`) appears to be available by default in the upstream Synapse image for some reason,
-# but it doesn't seem to be installed through a Debian package. Autoremoval would remove it, causing s3-storage-provider to fail.
-# Given that this is a dependency for s3-storage-provider (psycopg2), we prefer to install it explicitly.
-matrix_synapse_container_image_customizations_s3_storage_provider_installation_explicit_libldap_installation_enabled: true
-matrix_synapse_container_image_customizations_s3_storage_provider_installation_explicit_libldap_installation_package_name: libldap-2.5
-
 # Controls whether custom build steps will be added to the Dockerfile for installing auto-accept-invite module.
 # The version that will be installed is specified in `matrix_synapse_ext_synapse_auto_accept_invite_version`.
 matrix_synapse_container_image_customizations_auto_accept_invite_installation_enabled: "{{ matrix_synapse_ext_synapse_auto_accept_invite_enabled }}"
diff --git a/roles/custom/matrix-synapse/templates/synapse/customizations/Dockerfile.j2 b/roles/custom/matrix-synapse/templates/synapse/customizations/Dockerfile.j2
index d937b8a02..094a63cac 100644
--- a/roles/custom/matrix-synapse/templates/synapse/customizations/Dockerfile.j2
+++ b/roles/custom/matrix-synapse/templates/synapse/customizations/Dockerfile.j2
@@ -1,4 +1,43 @@
 #jinja2: lstrip_blocks: "True"
+{% if matrix_synapse_container_image_customizations_templates_enabled %}
+FROM {{ matrix_synapse_docker_image }} AS templates-builder
+
+{#
+This ugly script below does quite a lot:
+	- installs git and other dependencies temporarily, just so we could do a shallow-clone
+	- prepare the SSH config: keyscanning (if enabled), private key (if enabled)
+	- performs a git shallow clone with just the branch we need
+	- makes sure the files are owned by the user that will actually run the container later
+#}
+{% set dependencies = ['git', 'ssh', 'openssh-client'] %}
+{% if matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key %}
+RUN echo '{{ matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key | b64encode }}' | base64 -d > /custom-templates-private-key
+RUN chmod 400 /custom-templates-private-key
+{% endif %}
+
+RUN apt-get update && apt-get install --no-install-recommends -y {{ dependencies | join(' ') }}
+
+{% if matrix_synapse_container_image_customizations_templates_git_repository_keyscan_enabled %}
+RUN mkdir ~/.ssh
+RUN chmod 700 ~/.ssh
+RUN ssh-keyscan -t rsa {{ matrix_synapse_container_image_customizations_templates_git_repository_keyscan_hostname }} >> ~/.ssh/known_hosts
+{% endif %}
+
+RUN {% if matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key %}GIT_SSH_COMMAND='ssh -i /custom-templates-private-key'{% endif %} git \
+	clone \
+		--branch={{ matrix_synapse_container_image_customizations_templates_git_repository_branch }} \
+		--depth=1 \
+		--single-branch \
+		--no-tags \
+		{{ matrix_synapse_container_image_customizations_templates_git_repository_url }} \
+		{{ matrix_synapse_container_image_customizations_templates_in_container_base_path }}
+
+RUN /bin/sh -c 'cd {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }} && git rev-parse HEAD > git-revision.txt'
+RUN rm -rf {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }}/.git
+
+RUN chown -R {{ matrix_synapse_uid }}:{{ matrix_synapse_gid }} {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }}
+{% endif %}
+
 FROM {{ matrix_synapse_docker_image }}
 
 {% if matrix_synapse_container_image_customizations_auto_accept_invite_installation_enabled %}
@@ -11,52 +50,10 @@ RUN pip install 'boto3<1.36.0' 'botocore<1.36.0' synapse-s3-storage-provider=={{
 {% else %}
 RUN pip install synapse-s3-storage-provider=={{ matrix_synapse_ext_synapse_s3_storage_provider_version }}
 {% endif %}
-{% if matrix_synapse_container_image_customizations_s3_storage_provider_installation_explicit_libldap_installation_enabled %}
-RUN apt-get update && apt-get install --no-install-recommends -y {{ matrix_synapse_container_image_customizations_s3_storage_provider_installation_explicit_libldap_installation_package_name }}
-{% endif %}
 {% endif %}
 
 {% if matrix_synapse_container_image_customizations_templates_enabled %}
-{#
-This ugly script below does quite a lot:
-	- installs git and other dependencies temporarily, just so we could do a shallow-clone
-	- prepare the SSH config: keyscanning (if enabled), private key (if enabled)
-	- performs a git shallow clone with just the branch we need
-	- makes sure the files are owned by the user that will actually run the container later
-	- removes the `.git` directory to save space, but keeps git revision in `git-revision.txt`, should we need it for debugging
-	- finally, verifies that the templates path can indeed be found within the base path (sanity check)
-#}
-{% set dependencies = ['git', 'ssh', 'openssh-client'] %}
-RUN \
-	{% if matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key %}
-	echo '{{ matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key | b64encode }}' | base64 -d > /custom-templates-private-key && \
-	chmod 400 /custom-templates-private-key && \
-	{% endif %}
-	apt-get update && \
-	apt-get install --no-install-recommends -y {{ dependencies | join(' ') }} && \
-	{% if matrix_synapse_container_image_customizations_templates_git_repository_keyscan_enabled %}
-	mkdir ~/.ssh && \
-	chmod 700 ~/.ssh && \
-	ssh-keyscan -t rsa {{ matrix_synapse_container_image_customizations_templates_git_repository_keyscan_hostname }} >> ~/.ssh/known_hosts && \
-	{% endif %}
-	{% if matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key %}GIT_SSH_COMMAND='ssh -i /custom-templates-private-key'{% endif %} git \
-		clone \
-			--branch={{ matrix_synapse_container_image_customizations_templates_git_repository_branch }} \
-			--depth=1 \
-			--single-branch \
-			--no-tags \
-			{{ matrix_synapse_container_image_customizations_templates_git_repository_url }} \
-			{{ matrix_synapse_container_image_customizations_templates_in_container_base_path }} && \
-	/bin/sh -c 'cd {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }} && git rev-parse HEAD > git-revision.txt' && \
-	rm -rf {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }}/.git && \
-	chown -R {{ matrix_synapse_uid }}:{{ matrix_synapse_gid }} {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }} && \
-	apt-get autoremove -y {{ dependencies | join(' ') }} && \
-	{% if matrix_synapse_container_image_customizations_templates_git_repository_ssh_private_key %}
-	rm /custom-templates-private-key && \
-	{% endif %}
-	true
-
-RUN /bin/sh -c 'stat {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }}/{{ matrix_synapse_container_image_customizations_templates_in_container_template_files_relative_path }} || exit 1'
+COPY --from=templates-builder {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }} {{ matrix_synapse_container_image_customizations_templates_in_container_base_path }}
 {% endif %}
 
 {{ matrix_synapse_container_image_customizations_dockerfile_body_custom }}