jasmins little space

Proxying S3 with NGINX to Backblaze B2

Sometimes a simple forward slash (/) can drive a lot of frustration. For the migration of our Mastodon instance from local storage to a S3-compatible one, I’ve wanted to do it without any bigger service disruptions. To do that, I’ve followed Leah’s post about Mastodon scaling. She states:

You can also build everything to allow migration in the background with new media directly uploaded and served to/by S3 and old media, that isn’t migrated yet, served as fallback by the old local storage.

Yes! This is exactly what I want! In the full config example that she’s linked to, this line caused the frustration.

proxy_pass https://s3.example.com/mastodon/$uri;

My assumption was that mastodon is the S3 bucket name. Fortunately, Backblaze provides hostnames where the bucket name is already included, like https://bucket.s3.example.com. Therefore I’ve updated the line to:

proxy_pass https://my-backblaze-bucket.s3.eu-central-003.backblazeb2.com/$uri;

Looks similar to the config above, right? Except: it doesn’t work. The reason for that is: $uri starts with a forward slash (/) and therefore the proxied URLs look like this:

https://my-backblaze-bucket.s3.eu-central-003.backblazeb2.com//something.jpg

You see that double slash? Normally this wouldn’t be a problem, as hosters can easily get rid of them. Backblaze doesn’t. Therefore, in order to make the proxy_pass setting work as intended, the line needs to look like this:

proxy_pass https://my-backblaze-bucket.s3.eu-central-003.backblazeb2.com$uri;

That’s all. That single character.

Sidenote: According to a comment made on StackOverflow you shouldn’t use $uri, but $request_uri, because $uri might open the instance up for HTTP header injection vulnerabilities. All in all, the config line should look like this now:

proxy_pass https://my-backblaze-bucket.s3.eu-central-003.backblazeb2.com$request_uri;