Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to upload images to self hosted Minio S3 service #5143

Open
2 tasks done
Rami-Pastrami opened this issue Jul 31, 2024 · 6 comments
Open
2 tasks done

Unable to upload images to self hosted Minio S3 service #5143

Rami-Pastrami opened this issue Jul 31, 2024 · 6 comments

Comments

@Rami-Pastrami
Copy link

Rami-Pastrami commented Jul 31, 2024

Attempted Debugging

  • I have read the debugging page

Searched GitHub Issues

  • I have searched GitHub for the issue.

Describe the Scenario

I am trying to enable S3 image uploading to a private Minio instance, however every time I attempt to upload an image, I get an HTTP 500 error from book stack as well as an error fly-in on the top right stating that "An error occurred uploading the image"

In Debug mode, I caught the HTTP 500 error in the web console (which also appears out of debug mode but with less details). The full details from debug mode are:
League\Flysystem\UnableToCheckFileExistence
Unable to check existence for: uploads/images/gallery/2024-07/image.png

Stack trace (I believe this is the same as in the larvel log but including anyways)

Details

#0 /app/www/vendor/league/flysystem-aws-s3-v3/AwsS3V3Adapter.php(123): League\Flysystem\UnableToCheckExistence::forLocation()
#1 /app/www/vendor/league/flysystem/src/Filesystem.php(50): League\Flysystem\AwsS3V3\AwsS3V3Adapter->fileExists()
#2 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(181): League\Flysystem\Filesystem->has()
#3 /app/www/app/Uploads/ImageStorageDisk.php(47): Illuminate\Filesystem\FilesystemAdapter->exists()
#4 /app/www/app/Uploads/ImageService.php(77): BookStack\Uploads\ImageStorageDisk->exists()
#5 /app/www/app/Uploads/ImageService.php(45): BookStack\Uploads\ImageService->saveNew()
#6 /app/www/app/Uploads/ImageRepo.php(114): BookStack\Uploads\ImageService->saveNewFromUpload()
#7 /app/www/app/Uploads/Controllers/GalleryImageController.php(72): BookStack\Uploads\ImageRepo->saveNew()
#8 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\Uploads\Controllers\GalleryImageController->create()
#9 /app/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Illuminate\Routing\Controller->callAction()
#10 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(259): Illuminate\Routing\ControllerDispatcher->dispatch()
#11 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\Routing\Route->runController()
#12 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(806): Illuminate\Routing\Route->run()
#13 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\Routing\Router->Illuminate\Routing\{closure}()
#14 /app/www/app/Http/Middleware/Authenticate.php(23): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#15 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\Authenticate->handle()
#16 /app/www/app/Http/Middleware/Localization.php(32): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#17 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\Localization->handle()
#18 /app/www/app/Http/Middleware/RunThemeActions.php(26): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#19 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\RunThemeActions->handle()
#20 /app/www/app/Http/Middleware/CheckEmailConfirmed.php(47): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#21 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\CheckEmailConfirmed->handle()
#22 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#23 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle()
#24 /app/www/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#25 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\View\Middleware\ShareErrorsFromSession->handle()
#26 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#27 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest()
#28 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Session\Middleware\StartSession->handle()
#29 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#30 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle()
#31 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#32 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Cookie\Middleware\EncryptCookies->handle()
#33 /app/www/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#34 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\ApplyCspRules->handle()
#35 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#36 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(805): Illuminate\Pipeline\Pipeline->then()
#37 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(784): Illuminate\Routing\Router->runRouteWithinStack()
#38 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(748): Illuminate\Routing\Router->runRoute()
#39 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(737): Illuminate\Routing\Router->dispatchToRoute()
#40 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\Routing\Router->dispatch()
#41 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}()
#42 /app/www/app/Http/Middleware/PreventResponseCaching.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#43 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\PreventResponseCaching->handle()
#44 /app/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#45 /app/www/app/Http/Middleware/TrustProxies.php(41): Illuminate\Http\Middleware\TrustProxies->handle()
#46 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\Http\Middleware\TrustProxies->handle()
#47 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#48 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()
#49 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\TrimStrings->handle()
#50 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#51 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle()
#52 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(99): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#53 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle()
#54 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()
#55 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\Pipeline\Pipeline->then()
#56 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter()
#57 /app/www/public/index.php(52): Illuminate\Foundation\Http\Kernel->handle()
#58 {main}

This seems almost like an authentication issue?
I can see in the Minio logs the following:
image
In other words, I see a GetObject twice, I dont see any mention of files being uploaded (checking the bucket contents also show it to be empty).

I double checked that the authorized keys / credentials are valid for this bucket, and I have other software that uses this minio s3 instance on other buckets that work fine. I even tried setting the bucket read/write permissions to public (meaning no auth needed to read or write to the entire bucket, which obviously isnt a proper solution but even this did not work.

Uploading files directly/manually to the bucket via the minio Web GUI and then pulling them from the domain externally as a direct link works fine on this public setting

I configured the .env file as per the documentation for non-amazon s3
https://www.bookstackapp.com/docs/admin/upload-config/
I found a discord discussion a few months ago that mentioning commenting out STORAGE_URL helped but it was not effective for me

given the logs mention a 403 and not a 404, this could be an authentication issue but given I have set this bucket to be public I am not sure what could still be causing it.

Thank you for any help, and please let me know if more info is needed!

Exact BookStack Version

v24.05.3

Log Content

Details

[2024-07-31 06:42:43] production.ERROR: Unable to check existence for: uploads/images/gallery/2024-07/image.png {"userId":4,"exception":"[object] (League\\Flysystem\\UnableToCheckFileExistence(code: 0): Unable to check existence for: uploads/images/gallery/2024-07/image.png at /app/www/vendor/league/flysystem/src/UnableToCheckExistence.php:19)
[stacktrace]
#0 /app/www/vendor/league/flysystem-aws-s3-v3/AwsS3V3Adapter.php(123): League\\Flysystem\\UnableToCheckExistence::forLocation()
#1 /app/www/vendor/league/flysystem/src/Filesystem.php(50): League\\Flysystem\\AwsS3V3\\AwsS3V3Adapter->fileExists()
#2 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(181): League\\Flysystem\\Filesystem->has()
#3 /app/www/app/Uploads/ImageStorageDisk.php(47): Illuminate\\Filesystem\\FilesystemAdapter->exists()
#4 /app/www/app/Uploads/ImageService.php(77): BookStack\\Uploads\\ImageStorageDisk->exists()
#5 /app/www/app/Uploads/ImageService.php(45): BookStack\\Uploads\\ImageService->saveNew()
#6 /app/www/app/Uploads/ImageRepo.php(114): BookStack\\Uploads\\ImageService->saveNewFromUpload()
#7 /app/www/app/Uploads/Controllers/GalleryImageController.php(72): BookStack\\Uploads\\ImageRepo->saveNew()
#8 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\\Uploads\\Controllers\\GalleryImageController->create()
#9 /app/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Illuminate\\Routing\\Controller->callAction()
#10 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(259): Illuminate\\Routing\\ControllerDispatcher->dispatch()
#11 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\\Routing\\Route->runController()
#12 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(806): Illuminate\\Routing\\Route->run()
#13 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()
#14 /app/www/app/Http/Middleware/Authenticate.php(23): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#15 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Authenticate->handle()
#16 /app/www/app/Http/Middleware/Localization.php(32): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#17 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Localization->handle()
#18 /app/www/app/Http/Middleware/RunThemeActions.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#19 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\RunThemeActions->handle()
#20 /app/www/app/Http/Middleware/CheckEmailConfirmed.php(47): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#21 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\CheckEmailConfirmed->handle()
#22 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#23 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#24 /app/www/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#25 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#26 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#27 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#28 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Session\\Middleware\\StartSession->handle()
#29 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#30 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#31 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#32 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#33 /app/www/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#34 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\ApplyCspRules->handle()
#35 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#36 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(805): Illuminate\\Pipeline\\Pipeline->then()
#37 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(784): Illuminate\\Routing\\Router->runRouteWithinStack()
#38 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(748): Illuminate\\Routing\\Router->runRoute()
#39 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(737): Illuminate\\Routing\\Router->dispatchToRoute()
#40 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch()
#41 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#42 /app/www/app/Http/Middleware/PreventResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#43 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\PreventResponseCaching->handle()
#44 /app/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#45 /app/www/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#46 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\TrustProxies->handle()
#47 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#48 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#49 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#50 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#51 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#52 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(99): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#53 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#54 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#55 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then()
#56 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#57 /app/www/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()
#58 {main}

[previous exception] [object] (Aws\\S3\\Exception\\S3Exception(code: 0): Error executing \"HeadObject\" on \"https://DOMAIN/BUCKET_NAME/uploads/images/gallery/2024-07/image.png\"; AWS HTTP error: Client error: `HEAD https://DOMAIN/BUCKET_NAME/uploads/images/gallery/2024-07/image.png` resulted in a `403 Forbidden` response  (client): 403 Forbidden (Request-ID: 17E739186FADAE5C) -  at /app/www/vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php:196)
[stacktrace]
#0 /app/www/vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php(97): Aws\\WrappedHttpHandler->parseError()
#1 /app/www/vendor/guzzlehttp/promises/src/Promise.php(209): Aws\\WrappedHttpHandler->Aws\\{closure}()
#2 /app/www/vendor/guzzlehttp/promises/src/Promise.php(174): GuzzleHttp\\Promise\\Promise::callHandler()
#3 /app/www/vendor/guzzlehttp/promises/src/RejectedPromise.php(49): GuzzleHttp\\Promise\\Promise::GuzzleHttp\\Promise\\{closure}()
#4 /app/www/vendor/guzzlehttp/promises/src/TaskQueue.php(52): GuzzleHttp\\Promise\\RejectedPromise::GuzzleHttp\\Promise\\{closure}()
#5 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(163): GuzzleHttp\\Promise\\TaskQueue->run()
#6 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(189): GuzzleHttp\\Handler\\CurlMultiHandler->tick()
#7 /app/www/vendor/guzzlehttp/promises/src/Promise.php(251): GuzzleHttp\\Handler\\CurlMultiHandler->execute()
#8 /app/www/vendor/guzzlehttp/promises/src/Promise.php(227): GuzzleHttp\\Promise\\Promise->invokeWaitFn()
#9 /app/www/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\\Promise\\Promise->waitIfPending()
#10 /app/www/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#11 /app/www/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\\Promise\\Promise->waitIfPending()
#12 /app/www/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#13 /app/www/vendor/guzzlehttp/promises/src/Promise.php(69): GuzzleHttp\\Promise\\Promise->waitIfPending()
#14 /app/www/vendor/aws/aws-sdk-php/src/AwsClientTrait.php(58): GuzzleHttp\\Promise\\Promise->wait()
#15 /app/www/vendor/aws/aws-sdk-php/src/S3/S3ClientTrait.php(330): Aws\\AwsClient->execute()
#16 /app/www/vendor/league/flysystem-aws-s3-v3/AwsS3V3Adapter.php(121): Aws\\S3\\S3Client->doesObjectExistV2()
#17 /app/www/vendor/league/flysystem/src/Filesystem.php(50): League\\Flysystem\\AwsS3V3\\AwsS3V3Adapter->fileExists()
#18 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(181): League\\Flysystem\\Filesystem->has()
#19 /app/www/app/Uploads/ImageStorageDisk.php(47): Illuminate\\Filesystem\\FilesystemAdapter->exists()
#20 /app/www/app/Uploads/ImageService.php(77): BookStack\\Uploads\\ImageStorageDisk->exists()
#21 /app/www/app/Uploads/ImageService.php(45): BookStack\\Uploads\\ImageService->saveNew()
#22 /app/www/app/Uploads/ImageRepo.php(114): BookStack\\Uploads\\ImageService->saveNewFromUpload()
#23 /app/www/app/Uploads/Controllers/GalleryImageController.php(72): BookStack\\Uploads\\ImageRepo->saveNew()
#24 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\\Uploads\\Controllers\\GalleryImageController->create()
#25 /app/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Illuminate\\Routing\\Controller->callAction()
#26 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(259): Illuminate\\Routing\\ControllerDispatcher->dispatch()
#27 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\\Routing\\Route->runController()
#28 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(806): Illuminate\\Routing\\Route->run()
#29 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()
#30 /app/www/app/Http/Middleware/Authenticate.php(23): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#31 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Authenticate->handle()
#32 /app/www/app/Http/Middleware/Localization.php(32): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#33 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Localization->handle()
#34 /app/www/app/Http/Middleware/RunThemeActions.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#35 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\RunThemeActions->handle()
#36 /app/www/app/Http/Middleware/CheckEmailConfirmed.php(47): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#37 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\CheckEmailConfirmed->handle()
#38 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#39 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#40 /app/www/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#41 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#42 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#43 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#44 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Session\\Middleware\\StartSession->handle()
#45 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#46 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#47 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#48 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#49 /app/www/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#50 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\ApplyCspRules->handle()
#51 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#52 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(805): Illuminate\\Pipeline\\Pipeline->then()
#53 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(784): Illuminate\\Routing\\Router->runRouteWithinStack()
#54 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(748): Illuminate\\Routing\\Router->runRoute()
#55 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(737): Illuminate\\Routing\\Router->dispatchToRoute()
#56 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch()
#57 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#58 /app/www/app/Http/Middleware/PreventResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#59 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\PreventResponseCaching->handle()
#60 /app/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#61 /app/www/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#62 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\TrustProxies->handle()
#63 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#64 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#65 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#66 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#67 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#68 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(99): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#69 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#70 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#71 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then()
#72 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#73 /app/www/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()
#74 {main}

[previous exception] [object] (GuzzleHttp\\Exception\\ClientException(code: 403): Client error: `HEAD https://DOMAIN/BUCKET_NAME/uploads/images/gallery/2024-07/image.png` resulted in a `403 Forbidden` response at /app/www/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113)
[stacktrace]
#0 /app/www/vendor/guzzlehttp/guzzle/src/Middleware.php(72): GuzzleHttp\\Exception\\RequestException::create()
#1 /app/www/vendor/guzzlehttp/promises/src/Promise.php(209): GuzzleHttp\\Middleware::GuzzleHttp\\{closure}()
#2 /app/www/vendor/guzzlehttp/promises/src/Promise.php(158): GuzzleHttp\\Promise\\Promise::callHandler()
#3 /app/www/vendor/guzzlehttp/promises/src/TaskQueue.php(52): GuzzleHttp\\Promise\\Promise::GuzzleHttp\\Promise\\{closure}()
#4 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(163): GuzzleHttp\\Promise\\TaskQueue->run()
#5 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(189): GuzzleHttp\\Handler\\CurlMultiHandler->tick()
#6 /app/www/vendor/guzzlehttp/promises/src/Promise.php(251): GuzzleHttp\\Handler\\CurlMultiHandler->execute()
#7 /app/www/vendor/guzzlehttp/promises/src/Promise.php(227): GuzzleHttp\\Promise\\Promise->invokeWaitFn()
#8 /app/www/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\\Promise\\Promise->waitIfPending()
#9 /app/www/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#10 /app/www/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\\Promise\\Promise->waitIfPending()
#11 /app/www/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#12 /app/www/vendor/guzzlehttp/promises/src/Promise.php(69): GuzzleHttp\\Promise\\Promise->waitIfPending()
#13 /app/www/vendor/aws/aws-sdk-php/src/AwsClientTrait.php(58): GuzzleHttp\\Promise\\Promise->wait()
#14 /app/www/vendor/aws/aws-sdk-php/src/S3/S3ClientTrait.php(330): Aws\\AwsClient->execute()
#15 /app/www/vendor/league/flysystem-aws-s3-v3/AwsS3V3Adapter.php(121): Aws\\S3\\S3Client->doesObjectExistV2()
#16 /app/www/vendor/league/flysystem/src/Filesystem.php(50): League\\Flysystem\\AwsS3V3\\AwsS3V3Adapter->fileExists()
#17 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(181): League\\Flysystem\\Filesystem->has()
#18 /app/www/app/Uploads/ImageStorageDisk.php(47): Illuminate\\Filesystem\\FilesystemAdapter->exists()
#19 /app/www/app/Uploads/ImageService.php(77): BookStack\\Uploads\\ImageStorageDisk->exists()
#20 /app/www/app/Uploads/ImageService.php(45): BookStack\\Uploads\\ImageService->saveNew()
#21 /app/www/app/Uploads/ImageRepo.php(114): BookStack\\Uploads\\ImageService->saveNewFromUpload()
#22 /app/www/app/Uploads/Controllers/GalleryImageController.php(72): BookStack\\Uploads\\ImageRepo->saveNew()
#23 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\\Uploads\\Controllers\\GalleryImageController->create()
#24 /app/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Illuminate\\Routing\\Controller->callAction()
#25 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(259): Illuminate\\Routing\\ControllerDispatcher->dispatch()
#26 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\\Routing\\Route->runController()
#27 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(806): Illuminate\\Routing\\Route->run()
#28 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()
#29 /app/www/app/Http/Middleware/Authenticate.php(23): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#30 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Authenticate->handle()
#31 /app/www/app/Http/Middleware/Localization.php(32): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#32 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Localization->handle()
#33 /app/www/app/Http/Middleware/RunThemeActions.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#34 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\RunThemeActions->handle()
#35 /app/www/app/Http/Middleware/CheckEmailConfirmed.php(47): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#36 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\CheckEmailConfirmed->handle()
#37 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#38 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#39 /app/www/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#40 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#41 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#42 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#43 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Session\\Middleware\\StartSession->handle()
#44 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#45 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#46 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#47 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#48 /app/www/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#49 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\ApplyCspRules->handle()
#50 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#51 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(805): Illuminate\\Pipeline\\Pipeline->then()
#52 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(784): Illuminate\\Routing\\Router->runRouteWithinStack()
#53 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(748): Illuminate\\Routing\\Router->runRoute()
#54 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(737): Illuminate\\Routing\\Router->dispatchToRoute()
#55 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch()
#56 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#57 /app/www/app/Http/Middleware/PreventResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#58 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\PreventResponseCaching->handle()
#59 /app/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#60 /app/www/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#61 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\TrustProxies->handle()
#62 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#63 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#64 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#65 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#66 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#67 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(99): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#68 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#69 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#70 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then()
#71 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#72 /app/www/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()
#73 {main}
"}

Hosting Environment

Bookstack running in docker on ubuntu server, minio running on a separate truenas instance. Both go through the same nginx reverse proxy but under separate subdomains. Both subdomains are behind cloudflare.

@ssddanbrown
Copy link
Member

Hi @Rami-Pastrami,
Do those minio 403 logs occur each time you try to upload?
Just want to be sure they're connected here.

If so, It makes sense for the error thrown. BookStack will initially be doing a GET to check if a file already exists, which correlates with the error and logs.
Does your S3 key or secret contain any special characters? If so, which?

@Rami-Pastrami
Copy link
Author

Hi @Rami-Pastrami, Do those minio 403 logs occur each time you try to upload? Just want to be sure they're connected here.

If so, It makes sense for the error thrown. BookStack will initially be doing a GET to check if a file already exists, which correlates with the error and logs. Does your S3 key or secret contain any special characters? If so, which?

This happens every time, correct. Neither the key or secret contain any special characters, it is fully alphanumeric

@Rami-Pastrami
Copy link
Author

Still trying to figure out whats going on.
Pulled the docker image to get to bookstack v24.05.3, that didnt seem to do anything.

the name of my bucket had hyphens, so I switched to a bucket with a name consistent only of lower case letters, no change

I tried switching from using a user to login, to using a token to login to the user, and using a token directly. no change.

I changed the bucket back to "private" but customized the permissions so that anonymous public users can read the contents (the intended setup):

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "*" ] }, "Action": [ "s3:GetBucketLocation", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::[BUCKETNAME]" ] }, { "Effect": "Allow", "Principal": { "AWS": [ "*" ] }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::[BUCKETNAME]/*" ] } ] }

Please let me know if there is anything else to try, this is a perplexing issue

@ssddanbrown
Copy link
Member

@Rami-Pastrami I performed a test run with Minio since it had been a while since I last tested that combo.
Could get things working although I could get the same error if not using a key for an actual user entry that has write access to the bucket.

I recorded the process end-to-end from a fresh stack so you could see exactly what I do:
https://foss.video/w/9noJP3x5gnmQ4bNUAg47qs

@Rami-Pastrami
Copy link
Author

Rami-Pastrami commented Aug 9, 2024

@Rami-Pastrami I performed a test run with Minio since it had been a while since I last tested that combo. Could get things working although I could get the same error if not using a key for an actual user entry that has write access to the bucket.

I recorded the process end-to-end from a fresh stack so you could see exactly what I do: https://foss.video/w/9noJP3x5gnmQ4bNUAg47qs

Wow, thanks for the video walkthrough!

so TLDR I followed the steps provided and it fixed my issue in my particular use-case when connecting to Minio with a direct LAN IP, but it seems to error out in the above manner when connecting via external domain

Steps Taken:

  • Cleared all previous buckets related to Bookstack on my Minio instance, as well as accounts, API keys, and custom policies
  • Reset config for s3 on book stack
  • Created a new Bookstack bucket
  • to the bucket, added the anonymous access policy as per the documentation
  • created a new account on Minio, for the time being assigned it the global readwrite policy
    • I noticed the previous account name had a hyphen in it, however I do not believe this to be the cause of any issue. regardless the new account and all new objects on Minio created for Bookstacks are strictly alphanumeric
  • created an API access key under the new user
  • On the Bookstack .env file, filled in the user API key / secret and bucket name field
  • As per the video, this is where I believe the relevant change to be
    • I set the "STORAGE_URL" property to the external URL of the Minio API "[domain].com/[bucketname]", as I have previously
    • I set "STORAGE_S3_ENDPOINT" the the local IP/port of my Minio instance. Bookstack and Minio run on different physical servers on my end, but they are within the same LAN
  • Restarted the Bookstack container

At this point I confirmed that image uploading worked correctly, as well as viewing! I confirmed this test from both within the same LAN as the servers and externally over cellular.

I restored permissions instead of using global permissions on Minio account, everything continued working

However, if I change "STORAGE_S3_ENDPOINT" to use the external domain of my Minio instance, I end up with the same error. Switching back and forth between using the local IP and using the external one is the one singular value I can change to cause the error or not.

I am using the internal LAN IP for STORAGE_S3_ENDPOINT as per the video currently as it resolves the issue for my setup. However if Minio was being run externally, I am unsure if this work around would have worked.

If it means anything, my set up is as follows:
Minio / Bookstack running on 2 devices within the same lan -> shared NGINX reverse proxy -> NAT / router -> cloudflare -> each service has the same root domain but each have their own subdomain.

Cloudflare does have a limit of ~100 mb for single files, but my tested images were ~5 mb so I doubt that was any issue.

I am alright with having this Github issue be closed, but let me know if you have any questions.

Thanks for your help!

@ssddanbrown
Copy link
Member

However, if I change "STORAGE_S3_ENDPOINT" to use the external domain of my Minio instance, I end up with the same error. Switching back and forth between using the local IP and using the external one is the one singular value I can change to cause the error or not.

So that makes me suspicious of the cloudflare and NGINX proxies involved, more so of Cloudflare.

Something to note is that access is authenticated with the Authorization header.
This being dropped/altered would result in the error you're seeing.
This can often occur if there are redirects involved in HTTP requests (clients will drop this to avoid leaking secrets).
Ensure your STORAGE_S3_ENDPOINT provides a complete direct route to the MINIO system.
By that, I mean check things like protocol (https:// vs http://) and (with/without) trailing slashes.
If any parts inbetween (cloudflare/nginx) are performing redirects to handle these (to ensure slashes or upgrade to https) then that could be adding a redirect and potentially result in the Authorization header being dropped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants