[bug]: USE_MINIO and AWS_S3_CUSTOM_DOMAIN do not align semantically when using external Minio / S3
Is there an existing issue for this?
- [x] I have searched the existing issues
Current behavior
When setting USE_MINIO to 1 while using an external instance at another domain, omitting the route through the Plane web proxy, asset URLs are malformed. This stops them from being loaded.
This is due to assuming an external S3 endpoint would always be served behind the Plane web proxy. For decoupling the two services in a distributed system, it would be preferred being able to differentiate between these cases:
USE_MINIO/USE_INTERNAL_MINIOUSE_EXTERNAL_S3
It appears USE_MINIO actually means USE_INTERNAL_MINIO. It's naming is further complicated, since setting the variable is required to use other S3 providers as well.
https://github.com/makeplane/plane/blob/9ee1d8cb03dc3ee061534e7a0acb18c6e1ae31d3/apiserver/plane/settings/common.py#L230-L233
The common settings always assumes we deploy a non-AWS S3 behind the Plane web proxy
This works when AWS_S3_ENDPOINT_URL points to the internal http://plane-minio:9000. It fails when setting it to https://s3.example.com.
https://github.com/makeplane/plane/blob/9ee1d8cb03dc3ee061534e7a0acb18c6e1ae31d3/apiserver/plane/app/views/project/base.py#L603-L609
The cover image endpoint only recognises the AWS_S3_ENDPOINT_URL when USE_MINIO is set.
This leaves out the case where we want to set a custom AWS_S3_ENDPOINT_URL, but do not want to serve the bucket behind the same load balancer, e.g. via another host. This is useful for independently scaling out application and backing services.
There is a PR which only partially resolves this situation, by allowing to configure the Minio URL in the web proxy:
- https://github.com/makeplane/plane/pull/3278
In the cover image example below, we receive this URL:
- https://plane.example.org/org.example.plane/d41f7590-e557-407c-b171-f58d24030874/c51d301a972b430db7afbebdb41bc54a-ac7183d975acc2e9.png?response-content-disposition=inline&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=org.example.plane/20250310/eu-central-1/s3/aws4_request&X-Amz-Date=20250310T202619Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=ac7f088b1991817246f5ae339e970ec67c9cf973a0fb1ea903354d426d32c9dc
While we would like to see this:
- https://s3.example.com/org.example.plane/d41f7590-e557-407c-b171-f58d24030874/c51d301a972b430db7afbebdb41bc54a-ac7183d975acc2e9.png?response-content-disposition=inline&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=org.example.plane/20250310/eu-central-1/s3/aws4_request&X-Amz-Date=20250310T202619Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=ac7f088b1991817246f5ae339e970ec67c9cf973a0fb1ea903354d426d32c9dc
The URLs are generated in:
https://github.com/makeplane/plane/blob/9ee1d8cb03dc3ee061534e7a0acb18c6e1ae31d3/apiserver/plane/bgtasks/export_task.py#L92-L99
The wrong assumption in common.py about AWS_S3_CUSTOM_DOMAIN is, that we always want to serve Minio/other S3 providers that are not AWS behind the Plane load balancer. This assumption is also present in the proposed partial fix https://github.com/makeplane/plane/pull/3278.
There should be cases possible in which we do not replace the AWS_S3_CUSTOM_DOMAIN, even when USE_MINIO is set.
Related issues:
- https://github.com/makeplane/plane/issues/1318
- https://github.com/makeplane/plane/issues/2345
- https://github.com/makeplane/plane/issues/3490
- https://github.com/makeplane/plane/issues/4248
- https://github.com/makeplane/plane/issues/5680
Steps to reproduce
- Upload a cover image to a new project
- Save the project
- Find a 404 GET request in the browser console.
Environment
Production
Browser
Mozilla Firefox
Variant
Self-hosted
Version
v0.25.1
A common workaround will be to hardcode one's own S3 host into nginx.conf or as an environmental variable into the template.
To avoid an error with upstream sent too big header while reading response header from upstream, it might also be necessary to increase the proxy buffer size in nginx.conf:
12c12,18
< client_max_body_size ${FILE_SIZE_LIMIT};
---
> client_max_body_size 5242880;
>
> proxy_busy_buffers_size 512k;
> proxy_buffers 4 512k;
> proxy_buffer_size 256k;
>
> resolver 127.0.0.11;
Adding a custom DNS resolver, here the one from Docker, helps to resolve external hostnames.
Unfortunately configuring a custom route in nginx.conf will not produce correct pre-signed URLs from Plane, since they will not use the same host as the S3 service.
Files can be uploaded, but yield a SignatureDoesNotMatch error:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><Key>d41f7590-e557-407c-b171-f58d24030874/5eb155db82eb47448e4e8708388ff506-631b59cfe24a1f34380940cd_rule1.gif</Key><BucketName>org.example.plane</BucketName><Resource>/org.example.plane/d41f7590-e557-407c-b171-f58d24030874/5eb155db82eb47448e4e8708388ff506-631b59cfe24a1f34380940cd_rule1.gif</Resource><Region>eu-central-1</Region><RequestId>182B8EC94980966B</RequestId><HostId>3a9ca849-6ea6-446d-834b-b6f51a709522</HostId></Error>
These location blocks both worked for saving files to the external Minio.
- Once via its internal network name:
location /org.example.plane {
proxy_set_header Host s3.example.com;
proxy_pass http://minio_service_1:9000;
}
- Once via its external network name:
location /org.example.plane {
proxy_pass https://s3.example.com;
}
Here Minio is configured with MINIO_SERVER_URL=https://s3.example.com and MINIO_DOMAIN=s3.example.com.
Loading files is not possible, due to a mismatch of the FQDN used for signing the URL.
Native support of external S3 hosts, such as Minio, without configuring it to use the same hostname as Plane, will be highly appreciate to circumvent this behaviour.
@almereyda it should work with USE_MINIO=0. Agreeing with you on changing the naming convention to USE_INTERNAL_MINIO to indicate use of the attached minio instance.
The setting file in common.py configuration shared above is old and will be removed in upcoming releases. The new storage configuration is present here.
Setting USE_MINIO=0 should work please let me know if you are still facing the issue.
I have same issue on 0,28.0 version. If I use USE_MINIO=0, I can upload, but then I get <Error> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> ..... I am using selfhosted plane in docker
@pablohashescobar I am using the docker-compose of the last version: https://github.com/makeplane/plane/releases/download/v1.0.0/docker-compose.yml
And I can not use an external minio, inclusive assgined the enviroment variables USE_MINIO=0, and AWS_...