#jinja2: lstrip_blocks: "True"
{% macro render_nginx_status_location_block(addresses) %}
	{# Empty first line to make indentation prettier. #}

	location /nginx_status {
		stub_status on;
		access_log off;
		{% for address in addresses %}
		allow {{ address }};
		{% endfor %}
		deny all;
	}
{% endmacro %}


{% macro render_vhost_directives() %}
	gzip on;
	gzip_types text/plain application/json;

	{% if matrix_nginx_proxy_floc_optout_enabled %}
		add_header Permissions-Policy interest-cohort=() always;
	{% endif %}

	{% if matrix_nginx_proxy_hsts_preload_enabled %}
		add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
	{% else %}
		add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
	{% endif %}

	add_header X-XSS-Protection "{{ matrix_nginx_proxy_xss_protection }}";

	location /.well-known/matrix {
		root {{ matrix_static_files_base_path }};
		{#
			A somewhat long expires value is used to prevent outages
			in case this is unreachable due to network failure or
			due to the base domain's server completely dying.
		#}
		expires 4h;
		default_type application/json;
		add_header Access-Control-Allow-Origin *;
	}

	{% if matrix_nginx_proxy_proxy_matrix_nginx_status_enabled %}
		{{ render_nginx_status_location_block(matrix_nginx_proxy_proxy_matrix_nginx_status_allowed_addresses) }}
	{% endif %}

	{% if matrix_nginx_proxy_proxy_matrix_metrics_enabled %}
	location /metrics {
		{% if matrix_nginx_proxy_proxy_matrix_metrics_basic_auth_enabled %}
			auth_basic "protected";
			auth_basic_user_file {{ matrix_nginx_proxy_proxy_matrix_metrics_basic_auth_path }};
		{% endif %}

		{% for configuration_block in matrix_nginx_proxy_proxy_matrix_metrics_additional_location_configuration_blocks %}
			{{- configuration_block }}
		{% endfor %}
	}
	{% endif %}

	{% if matrix_nginx_proxy_proxy_matrix_corporal_api_enabled %}
	location ^~ /_matrix/corporal {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_matrix_corporal_api_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_corporal_api_addr_sans_container }};
		{% endif %}

		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
		proxy_set_header X-Forwarded-Proto {{ matrix_nginx_proxy_x_forwarded_proto_value }};
	}
	{% endif %}

	{% if matrix_nginx_proxy_proxy_matrix_identity_api_enabled %}
	location ^~ /_matrix/identity {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_matrix_identity_api_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_identity_api_addr_sans_container }};
		{% endif %}

		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
		proxy_set_header X-Forwarded-Proto {{ matrix_nginx_proxy_x_forwarded_proto_value }};
	}
	{% endif %}

	{% if matrix_nginx_proxy_proxy_media_repo_enabled %}
	# Redirect all media endpoints to the media-repo
	location ^~ /_matrix/media {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
		{% endif %}

		# Make sure this matches your homeserver in media-repo.yaml
		# You may have to manually specify it if using delegation or the
		# incoming Host doesn't match.
		proxy_set_header Host {{ matrix_domain }};

		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;

		client_body_buffer_size {{ ((matrix_media_repo_max_bytes | int) / 4) | int }};
		client_max_body_size {{ matrix_media_repo_max_bytes }};
	}

	# Redirect other endpoints registered by the media-repo to its container
	# /_matrix/client/r0/logout
	# /_matrix/client/r0/logout/all
	location ~ ^/_matrix/client/(r0|v1|v3|unstable)/(logout|logout/all) {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
		{% endif %}

		# Make sure this matches your homeserver in media-repo.yaml
		# You may have to manually specify it if using delegation or the
		# incoming Host doesn't match.
		proxy_set_header Host {{ matrix_domain }};

		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
	}

	# Redirect other endpoints registered by the media-repo to its container
	# /_matrix/client/r0/admin/purge_media_cache
	# /_matrix/client/r0/admin/quarantine_media/{roomId:[^/]+}
	location ~ ^/_matrix/client/(r0|v1|v3|unstable)/admin/(purge_media_cache|quarantine_media/.*) {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
		{% endif %}

		# Make sure this matches your homeserver in media-repo.yaml
		# You may have to manually specify it if using delegation or the
		# incoming Host doesn't match.
		proxy_set_header Host {{ matrix_domain }};

		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
	}

	# Redirect other endpoints registered by the media-repo to its container
	location ^~ /_matrix/client/unstable/io.t2bot.media {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
		{% endif %}

		# Make sure this matches your homeserver in media-repo.yaml
		# You may have to manually specify it if using delegation or the
		# incoming Host doesn't match.
		proxy_set_header Host {{ matrix_domain }};

		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
	}
	{% endif %}

	{% if matrix_nginx_proxy_proxy_matrix_user_directory_search_enabled %}
	location ~ ^/_matrix/client/(r0|v3)/user_directory/search {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_matrix_user_directory_search_addr_with_container }}";
			{% if matrix_nginx_proxy_proxy_matrix_user_directory_search_v3_to_r0_redirect_enabled %}
			rewrite ^(.*?)/v3/(.*?)$  $1/r0/$2 break;
			{% endif %}
			proxy_pass http://$backend;
		{% else %}
			{% if matrix_nginx_proxy_proxy_matrix_user_directory_search_v3_to_r0_redirect_enabled %}
			rewrite ^(.*?)/v3/(.*?)$  $1/r0/$2 break;
			{% endif %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_user_directory_search_addr_sans_container }};
		{% endif %}

		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
	}
	{% endif %}

	{% if matrix_nginx_proxy_proxy_matrix_3pid_registration_enabled %}
	location ~ ^/_matrix/client/(r0|v3)/register/(email|msisdn)/requestToken$ {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_matrix_3pid_registration_addr_with_container }}";
			{% if matrix_nginx_proxy_proxy_matrix_3pid_registration_v3_to_r0_redirect_enabled %}
			rewrite ^(.*?)/v3/(.*?)$  $1/r0/$2 break;
			{% endif %}
			proxy_pass http://$backend;
		{% else %}
			{% if matrix_nginx_proxy_proxy_matrix_3pid_registration_v3_to_r0_redirect_enabled %}
			rewrite ^(.*?)/v3/(.*?)$  $1/r0/$2 break;
			{% endif %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_3pid_registration_addr_sans_container }};
		{% endif %}

		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
		proxy_set_header X-Forwarded-Proto {{ matrix_nginx_proxy_x_forwarded_proto_value }};
	}
	{% endif %}

	{% for configuration_block in matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks %}
		{{- configuration_block }}
	{% endfor %}

	{#
		This handles the Matrix Client API only.
		The Matrix Federation API is handled by a separate vhost.
	#}
	location ~* ^({{ matrix_nginx_proxy_proxy_matrix_client_api_forwarded_location_prefix_regexes|join('|') }}) {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_client_api_addr_sans_container }};
		{% endif %}

		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
		proxy_set_header X-Forwarded-Proto {{ matrix_nginx_proxy_x_forwarded_proto_value }};

		client_body_buffer_size 25M;
		client_max_body_size {{ matrix_nginx_proxy_proxy_matrix_client_api_client_max_body_size_mb }}M;
		proxy_max_temp_file_size 0;
	}

	{#
		We only handle the root URI for this redirect or homepage serving.
		Unhandled URIs (mostly by `matrix_nginx_proxy_proxy_matrix_client_api_forwarded_location_prefix_regexes` above) should result in a 404,
		instead of causing a redirect.
		See: https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/1058
	#}
	location ~* ^/$ {
		{% if matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain %}
			return 302 {{ matrix_nginx_proxy_x_forwarded_proto_value }}://{{ matrix_nginx_proxy_proxy_matrix_client_redirect_root_uri_to_domain }}$request_uri;
		{% else %}
			rewrite ^/$ /_matrix/static/ last;
		{% endif %}
	}
{% endmacro %}

server {
	listen {{ 8080 if matrix_nginx_proxy_enabled else 80 }};
	listen [::]:{{ 8080 if matrix_nginx_proxy_enabled else 80 }};

	server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }};

	server_tokens off;
	root /dev/null;

	{% if matrix_nginx_proxy_https_enabled %}
		location /.well-known/acme-challenge {
			{% if matrix_nginx_proxy_enabled %}
				{# Use the embedded DNS resolver in Docker containers to discover the service #}
				resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
				set $backend "matrix-certbot:8080";
				proxy_pass http://$backend;
			{% else %}
				{# Generic configuration for use outside of our container setup #}
				proxy_pass http://127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }};
			{% endif %}
		}

		{% if matrix_nginx_proxy_proxy_matrix_nginx_status_enabled %}
			{{ render_nginx_status_location_block(matrix_nginx_proxy_proxy_matrix_nginx_status_allowed_addresses) }}
		{% endif %}

		location / {
			return 301 https://$http_host$request_uri;
		}
	{% else %}
		{{ render_vhost_directives() }}
	{% endif %}
}

{% if matrix_nginx_proxy_https_enabled %}
server {
	listen {{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2;
	listen [::]:{{ 8443 if matrix_nginx_proxy_enabled else 443 }} ssl http2;

	server_name {{ matrix_nginx_proxy_proxy_matrix_hostname }};

	server_tokens off;
	root /dev/null;

	ssl_certificate {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/fullchain.pem;
	ssl_certificate_key {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/privkey.pem;

	ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }};
	{% if matrix_nginx_proxy_ssl_ciphers != '' %}
	ssl_ciphers {{ matrix_nginx_proxy_ssl_ciphers }};
	{% endif %}
	ssl_prefer_server_ciphers {{ matrix_nginx_proxy_ssl_prefer_server_ciphers }};

	{% if matrix_nginx_proxy_ocsp_stapling_enabled %}
		ssl_stapling on;
		ssl_stapling_verify on;
		ssl_trusted_certificate {{ matrix_ssl_config_dir_path }}/live/{{ matrix_nginx_proxy_proxy_matrix_hostname }}/chain.pem;
	{% endif %}

	{% if matrix_nginx_proxy_ssl_session_tickets_off %}
		ssl_session_tickets off;
	{% endif %}
	ssl_session_cache {{ matrix_nginx_proxy_ssl_session_cache }};
	ssl_session_timeout {{ matrix_nginx_proxy_ssl_session_timeout }};

	{{ render_vhost_directives() }}
}
{% endif %}

{% if matrix_nginx_proxy_proxy_matrix_federation_api_enabled %}
{#
	This federation vhost is a little special.
	It serves federation over HTTP or HTTPS, depending on `matrix_nginx_proxy_https_enabled`.
#}
server {
	{% if matrix_nginx_proxy_https_enabled %}
		listen {{ matrix_nginx_proxy_proxy_matrix_federation_port }} ssl http2;
		listen [::]:{{ matrix_nginx_proxy_proxy_matrix_federation_port }} ssl http2;
	{% else %}
		listen {{ matrix_nginx_proxy_proxy_matrix_federation_port }};
	{% endif %}

	server_name {{ matrix_nginx_proxy_proxy_matrix_federation_hostname }};
	server_tokens off;

	root /dev/null;

	gzip on;
	gzip_types text/plain application/json;

	{% if matrix_nginx_proxy_https_enabled %}
		ssl_certificate {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate }};
		ssl_certificate_key {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_certificate_key }};

		ssl_protocols {{ matrix_nginx_proxy_ssl_protocols }};
		{% if matrix_nginx_proxy_ssl_ciphers != '' %}
			ssl_ciphers {{ matrix_nginx_proxy_ssl_ciphers }};
		{% endif %}
		ssl_prefer_server_ciphers {{ matrix_nginx_proxy_ssl_prefer_server_ciphers }};

		{% if matrix_nginx_proxy_ocsp_stapling_enabled %}
			ssl_stapling on;
			ssl_stapling_verify on;
			ssl_trusted_certificate {{ matrix_nginx_proxy_proxy_matrix_federation_api_ssl_trusted_certificate }};
		{% endif %}

		{% if matrix_nginx_proxy_ssl_session_tickets_off %}
			ssl_session_tickets off;
		{% endif %}
		ssl_session_cache {{ matrix_nginx_proxy_ssl_session_cache }};
		ssl_session_timeout {{ matrix_nginx_proxy_ssl_session_timeout }};
	{% endif %}

	{% if matrix_nginx_proxy_proxy_media_repo_enabled %}
		# Redirect all media endpoints to the media-repo
		location ^~ /_matrix/media {
			{% if matrix_nginx_proxy_enabled %}
				{# Use the embedded DNS resolver in Docker containers to discover the service #}
				resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
				set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
				proxy_pass http://$backend;
			{% else %}
				{# Generic configuration for use outside of our container setup #}
				proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
			{% endif %}

			# Make sure this matches your homeserver in media-repo.yaml
			# You may have to manually specify it if using delegation or the
			# incoming Host doesn't match.
			proxy_set_header Host {{ matrix_domain }};

			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $remote_addr;

			client_body_buffer_size {{ ((matrix_media_repo_max_bytes | int) / 4) | int }};
			client_max_body_size {{ matrix_media_repo_max_bytes }};
		}

		# Redirect other endpoints registered by the media-repo to its container
		# /_matrix/client/r0/logout
		# /_matrix/client/r0/logout/all
		location ~ ^/_matrix/client/(r0|v1|v3|unstable)/(logout|logout/all) {
			{% if matrix_nginx_proxy_enabled %}
				{# Use the embedded DNS resolver in Docker containers to discover the service #}
				resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
				set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
				proxy_pass http://$backend;
			{% else %}
				{# Generic configuration for use outside of our container setup #}
				proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
			{% endif %}

			# Make sure this matches your homeserver in media-repo.yaml
			# You may have to manually specify it if using delegation or the
			# incoming Host doesn't match.
			proxy_set_header Host {{ matrix_domain }};

			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $remote_addr;
		}

		# Redirect other endpoints registered by the media-repo to its container
		# /_matrix/client/r0/admin/purge_media_cache
		# /_matrix/client/r0/admin/quarantine_media/{roomId:[^/]+}
		location ~ ^/_matrix/client/(r0|v1|v3|unstable)/admin/(purge_media_cache|quarantine_media/.*) {
			{% if matrix_nginx_proxy_enabled %}
				{# Use the embedded DNS resolver in Docker containers to discover the service #}
				resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
				set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
				proxy_pass http://$backend;
			{% else %}
				{# Generic configuration for use outside of our container setup #}
				proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
			{% endif %}

			# Make sure this matches your homeserver in media-repo.yaml
			# You may have to manually specify it if using delegation or the
			# incoming Host doesn't match.
			proxy_set_header Host {{ matrix_domain }};

			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $remote_addr;
		}

		# Redirect other endpoints registered by the media-repo to its container
		location ^~ /_matrix/client/unstable/io.t2bot.media {
			{% if matrix_nginx_proxy_enabled %}
				{# Use the embedded DNS resolver in Docker containers to discover the service #}
				resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
				set $backend "{{ matrix_nginx_proxy_proxy_media_repo_addr_with_container }}";
				proxy_pass http://$backend;
			{% else %}
				{# Generic configuration for use outside of our container setup #}
				proxy_pass http://{{ matrix_nginx_proxy_proxy_media_repo_addr_sans_container }};
			{% endif %}

			# Make sure this matches your homeserver in media-repo.yaml
			# You may have to manually specify it if using delegation or the
			# incoming Host doesn't match.
			proxy_set_header Host {{ matrix_domain }};

			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $remote_addr;
		}
	{% endif %}

	location / {
		{% if matrix_nginx_proxy_enabled %}
			{# Use the embedded DNS resolver in Docker containers to discover the service #}
			resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
			set $backend "{{ matrix_nginx_proxy_proxy_matrix_federation_api_addr_with_container }}";
			proxy_pass http://$backend;
		{% else %}
			{# Generic configuration for use outside of our container setup #}
			proxy_pass http://{{ matrix_nginx_proxy_proxy_matrix_federation_api_addr_sans_container }};
		{% endif %}

		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
		proxy_set_header X-Forwarded-Proto {{ matrix_nginx_proxy_x_forwarded_proto_value }};

		client_body_buffer_size 25M;
		client_max_body_size {{ matrix_nginx_proxy_proxy_matrix_federation_api_client_max_body_size_mb }}M;
		proxy_max_temp_file_size 0;
	}
}
{% endif %}