linuxserver / docker-bookstack

A Docker container for the BookStack documentation wiki
GNU General Public License v3.0
747 stars 108 forks source link

TLS certificate verification does not work when S3 is used for storage #145

Closed BluemediaGER closed 1 year ago

BluemediaGER commented 1 year ago

linuxserver.io


Expected Behavior

The Let's Encrypt TLS certificate of an S3 HTTPS endpoint should be validated successfully. Bookstack should be able to use the S3 service for media storage.

Current Behavior

Communication with the S3 endpoint fails due to a certificate validation error.

Explicit configuration of a CA file in /config/php/php-local.ini also doesn`t work:

curl.cainfo = "/etc/ssl/certs/ca-certificates.crt"
openssl.cafile = "/etc/ssl/certs/ca-certificates.crt"

Querying the endpoint with curl inside the container is possible without any problems.

Steps to Reproduce

  1. Setup MinIO behind an nginx reverse proxy using a Let's Encrypt TLS certificate for HTTPS
  2. Configure bookstack to use S3 storage using /conf/www/.env:
    
    STORAGE_TYPE=s3
    STORAGE_S3_KEY=<redacted>
    STORAGE_S3_SECRET=<redacted>
    STORAGE_S3_BUCKET=bookstack-media
    STORAGE_S3_REGION=eu-west-1

STORAGE_S3_ENDPOINT=https:// STORAGE_URL=https://bookstack-media.

4. Restart the container
5. Try uploading media (e.g. changing a profile picture or inserting a picture on a page)

## Environment
**OS:** Debian 11 (Bullseye)
**CPU architecture:** x86_64
**How docker service was installed:** Official apt repository

## Command used to create docker container (run/create/compose/screenshot)
Docker compose definition (part of a bigger compose file):
```yaml
bookstack:
    image: ghcr.io/linuxserver/bookstack
    container_name: vps03-bookstack
    networks:
      internal:
    volumes:
      - bookstack:/config
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    restart: unless-stopped
    depends_on:
      - mariadb

Docker logs

Error from laravel.log:

[2022-11-08 20:05:06] production.ERROR: Error executing "ListObjectsV2" on "https://<s3-service-endpoint>/bookstack-media?list-type=2&prefix=uploads%2Fimages%2Fuser%2F2021-10%2F"; AWS HTTP error: cURL error 60: SSL certificate problem: self signed certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://<s3-service-endpoint>/bookstack-media?list-type=2&prefix=uploads%2Fimages%2Fuser%2F2021-10%2F {"userId":3,"exception":"[object] (Aws\\S3\\Exception\\S3Exception(code: 0): Error executing \"ListObjectsV2\" on \"https://<s3-service-endpoint>/bookstack-media?list-type=2&prefix=uploads%2Fimages%2Fuser%2F2021-10%2F\"; AWS HTTP error: cURL error 60: SSL certificate problem: self signed certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://<s3-service-endpoint>/bookstack-media?list-type=2&prefix=uploads%2Fimages%2Fuser%2F2021-10%2F at /app/www/vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php:195)
[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(204): Aws\\WrappedHttpHandler->Aws\\{closure}()
#2 /app/www/vendor/guzzlehttp/promises/src/Promise.php(169): GuzzleHttp\\Promise\\Promise::callHandler()
#3 /app/www/vendor/guzzlehttp/promises/src/RejectedPromise.php(42): GuzzleHttp\\Promise\\Promise::GuzzleHttp\\Promise\\{closure}()
#4 /app/www/vendor/guzzlehttp/promises/src/TaskQueue.php(48): GuzzleHttp\\Promise\\RejectedPromise::GuzzleHttp\\Promise\\{closure}()
#5 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(159): GuzzleHttp\\Promise\\TaskQueue->run()
#6 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(184): GuzzleHttp\\Handler\\CurlMultiHandler->tick()
#7 /app/www/vendor/guzzlehttp/promises/src/Promise.php(248): GuzzleHttp\\Handler\\CurlMultiHandler->execute()
#8 /app/www/vendor/guzzlehttp/promises/src/Promise.php(224): GuzzleHttp\\Promise\\Promise->invokeWaitFn()
#9 /app/www/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\\Promise\\Promise->waitIfPending()
#10 /app/www/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#11 /app/www/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\\Promise\\Promise->waitIfPending()
#12 /app/www/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#13 /app/www/vendor/guzzlehttp/promises/src/Promise.php(62): 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/ResultPaginator.php(131): Aws\\AwsClient->execute()
#16 /app/www/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(293): Aws\\ResultPaginator->valid()
#17 /app/www/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(276): League\\Flysystem\\AwsS3v3\\AwsS3Adapter->retrievePaginatedListing()
#18 /app/www/vendor/league/flysystem/src/Filesystem.php(272): League\\Flysystem\\AwsS3v3\\AwsS3Adapter->listContents()
#19 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(674): League\\Flysystem\\Filesystem->listContents()
#20 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(687): Illuminate\\Filesystem\\FilesystemAdapter->files()
#21 /app/www/app/Uploads/ImageService.php(421): Illuminate\\Filesystem\\FilesystemAdapter->allFiles()
#22 /app/www/app/Uploads/ImageService.php(406): BookStack\\Uploads\\ImageService->destroyImagesFromPath()
#23 /app/www/app/Uploads/ImageRepo.php(178): BookStack\\Uploads\\ImageService->destroy()
#24 /app/www/app/Http/Controllers/UserController.php(159): BookStack\\Uploads\\ImageRepo->destroyImage()
#25 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\\Http\\Controllers\\UserController->update()
#26 /app/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Illuminate\\Routing\\Controller->callAction()
#27 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(262): Illuminate\\Routing\\ControllerDispatcher->dispatch()
#28 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\\Routing\\Route->runController()
#29 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(721): Illuminate\\Routing\\Route->run()
#30 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()
#31 /app/www/app/Http/Middleware/Authenticate.php(23): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#32 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\Authenticate->handle()
#33 /app/www/app/Http/Middleware/Localization.php(45): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#34 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\Localization->handle()
#35 /app/www/app/Http/Middleware/RunThemeActions.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#36 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\RunThemeActions->handle()
#37 /app/www/app/Http/Middleware/CheckEmailConfirmed.php(47): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#38 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\CheckEmailConfirmed->handle()
#39 /app/www/app/Http/Middleware/PreventAuthenticatedResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#40 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\PreventAuthenticatedResponseCaching->handle()
#41 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#42 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#43 /app/www/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#44 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#45 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#46 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#47 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Session\\Middleware\\StartSession->handle()
#48 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#49 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#50 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#51 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#52 /app/www/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#53 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\ApplyCspRules->handle()
#54 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#55 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(723): Illuminate\\Pipeline\\Pipeline->then()
#56 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(698): Illuminate\\Routing\\Router->runRouteWithinStack()
#57 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(662): Illuminate\\Routing\\Router->runRoute()
#58 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(651): Illuminate\\Routing\\Router->dispatchToRoute()
#59 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Illuminate\\Routing\\Router->dispatch()
#60 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#61 /app/www/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#62 /app/www/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#63 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\TrustProxies->handle()
#64 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#65 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#66 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#67 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#68 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#69 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#70 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#71 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#72 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\\Pipeline\\Pipeline->then()
#73 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#74 /app/www/public/index.php(53): Illuminate\\Foundation\\Http\\Kernel->handle()
#75 {main}

[previous exception] [object] (GuzzleHttp\\Exception\\RequestException(code: 0): cURL error 60: SSL certificate problem: self signed certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://<s3-service-endpoint>/bookstack-media?list-type=2&prefix=uploads%2Fimages%2Fuser%2F2021-10%2F at /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:211)
[stacktrace]
#0 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(158): GuzzleHttp\\Handler\\CurlFactory::createRejection()
#1 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(110): GuzzleHttp\\Handler\\CurlFactory::finishError()
#2 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(245): GuzzleHttp\\Handler\\CurlFactory::finish()
#3 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(169): GuzzleHttp\\Handler\\CurlMultiHandler->processMessages()
#4 /app/www/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(184): GuzzleHttp\\Handler\\CurlMultiHandler->tick()
#5 /app/www/vendor/guzzlehttp/promises/src/Promise.php(248): GuzzleHttp\\Handler\\CurlMultiHandler->execute()
#6 /app/www/vendor/guzzlehttp/promises/src/Promise.php(224): GuzzleHttp\\Promise\\Promise->invokeWaitFn()
#7 /app/www/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\\Promise\\Promise->waitIfPending()
#8 /app/www/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#9 /app/www/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\\Promise\\Promise->waitIfPending()
#10 /app/www/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\\Promise\\Promise->invokeWaitList()
#11 /app/www/vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttp\\Promise\\Promise->waitIfPending()
#12 /app/www/vendor/aws/aws-sdk-php/src/AwsClientTrait.php(58): GuzzleHttp\\Promise\\Promise->wait()
#13 /app/www/vendor/aws/aws-sdk-php/src/ResultPaginator.php(131): Aws\\AwsClient->execute()
#14 /app/www/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(293): Aws\\ResultPaginator->valid()
#15 /app/www/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(276): League\\Flysystem\\AwsS3v3\\AwsS3Adapter->retrievePaginatedListing()
#16 /app/www/vendor/league/flysystem/src/Filesystem.php(272): League\\Flysystem\\AwsS3v3\\AwsS3Adapter->listContents()
#17 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(674): League\\Flysystem\\Filesystem->listContents()
#18 /app/www/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(687): Illuminate\\Filesystem\\FilesystemAdapter->files()
#19 /app/www/app/Uploads/ImageService.php(421): Illuminate\\Filesystem\\FilesystemAdapter->allFiles()
#20 /app/www/app/Uploads/ImageService.php(406): BookStack\\Uploads\\ImageService->destroyImagesFromPath()
#21 /app/www/app/Uploads/ImageRepo.php(178): BookStack\\Uploads\\ImageService->destroy()
#22 /app/www/app/Http/Controllers/UserController.php(159): BookStack\\Uploads\\ImageRepo->destroyImage()
#23 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\\Http\\Controllers\\UserController->update()
#24 /app/www/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Illuminate\\Routing\\Controller->callAction()
#25 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Route.php(262): 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(721): Illuminate\\Routing\\Route->run()
#28 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): 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(167): BookStack\\Http\\Middleware\\Authenticate->handle()
#31 /app/www/app/Http/Middleware/Localization.php(45): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#32 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): 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(167): 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(167): BookStack\\Http\\Middleware\\CheckEmailConfirmed->handle()
#37 /app/www/app/Http/Middleware/PreventAuthenticatedResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#38 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\PreventAuthenticatedResponseCaching->handle()
#39 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#40 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#41 /app/www/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#42 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#43 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#44 /app/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#45 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Session\\Middleware\\StartSession->handle()
#46 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#47 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#48 /app/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#49 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#50 /app/www/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#51 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): BookStack\\Http\\Middleware\\ApplyCspRules->handle()
#52 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#53 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(723): Illuminate\\Pipeline\\Pipeline->then()
#54 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(698): Illuminate\\Routing\\Router->runRouteWithinStack()
#55 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(662): Illuminate\\Routing\\Router->runRoute()
#56 /app/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php(651): Illuminate\\Routing\\Router->dispatchToRoute()
#57 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Illuminate\\Routing\\Router->dispatch()
#58 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#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(167): 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(167): 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(167): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#67 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#68 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#69 /app/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#70 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\\Pipeline\\Pipeline->then()
#71 /app/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#72 /app/www/public/index.php(53): Illuminate\\Foundation\\Http\\Kernel->handle()
#73 {main}
"}
github-actions[bot] commented 1 year ago

Thanks for opening your first issue here! Be sure to follow the bug or feature issue templates!

ssddanbrown commented 1 year ago

Strange to see curl fail for an lets-encrypt certificate. Might be worth doing the following:

BluemediaGER commented 1 year ago

Wow, thanks for the quick reply!

I'm currently running several other services (Pixelfed, Hedgedoc, ...) using the same MinIO S3 endpoint without any issues. Therefore, I would not expect a problem on this end.

ssddanbrown commented 1 year ago

Thanks for the info. Nothing obvious then. Might be good to try a raw out-of-app php request from inside the container. If possible, could you run the below inside the container?:

php -r '$ch = curl_init("https://self-signed.badssl.com/"); curl_exec($ch); echo curl_error($ch);'

Replace the URL between the first double quotes with your S3 endpoint URL. It should output an ssl error message if still a problem there, or may show response data of the URL if successful.

BluemediaGER commented 1 year ago

I think I've found the underlying issue. DNS resolution seems to be partially broken inside the container. Maybe because my S3 endpoint is a sub-sub domain. It resolves to localhost inside the container where nginx is listening with a self signed certificate (surprise!). Looks like Docker is messing around with /etc/resolve.conf inside the container again.

I will have a look at this tomorrow and if it's in fact an issue with Docker, I will close the issue.

BluemediaGER commented 1 year ago

The problem was indeed caused by the broken name resolution inside the container. I have adjusted the settings in /etc/resolv.conf on the host. After restarting the Docker daemon, the name resolution now works correctly and the S3 service can be used by Bookstack. Therefore, I am closing this issue.