solidnerd/docker-bookstack

Forward proxy setup

Closed this issue · 6 comments

den5o commented

I have traefik running on a VPS listening on mydomain.tld and managing all certs. The VPS and a VM running on my home server are connected via NetBird. The VPS forward proxies all incoming requests to subdomain.mydomain.tld and *.subdomain.mydomain.tld to the VMs NetBird IP where NPM reverse proxies them to the correct service.

I have a few services running on the VM being served this way.

  • Bookstack: books.subdomain.mydomain.tld
  • SFTPgo: files.subdomain.mydomain.tld
  • Baikal: baikal.subdomain.mydomain.tld
  • Navidrome: music.subdomain.mydomain.tld

SFTPgo, Baikal, and Navidrome work without issue. Bookstack results in status code 500 strict-origin-when-cross-origin

As you can see in the compose file below I've included - APP_PROXIES=*. I also tried the VPS NetBird IP with the same result. I've also experimented with traefik headers with no success for a few days now. The config below does not include any of those as I've scrapped them.

I thought I'd post this issue here instead of traefik because I believe the APP_PROXIES environment variable should have taken care of this. Let me know if this would be more appropriate for traefik support.

Boockstack podman-compose.yml:

services:
  mysql:
    image: mysql:8.3
    environment:
    - MYSQL_ROOT_PASSWORD=/run/secrets/bookstack_root_pass
    - MYSQL_DATABASE=bookstack
    - MYSQL_USER=bookstack
    - MYSQL_PASSWORD=/run/secrets/bookstack_db_pass
    secrets:
    - bookstack_db_pass
    - bookstack_root_pass
    volumes:
    - bookstack_mysql-data:/var/lib/mysql
    networks:
    - bookstack

  bookstack:
    image: solidnerd/bookstack:24.10.3
    hostname: bookstack
    depends_on:
    - mysql
    
    environment:
    # DB
    - DB_HOST=mysql:3306
    - DB_DATABASE=bookstack
    - DB_USERNAME=bookstack
    - DB_PASSWORD=/run/secrets/bookstack_db_pass
    # APP
    - APP_URL=https://books.gfc.badhippo.xyz
    - APP_KEY=/run/secrets/bookstack_app_key
    - APP_ENV=production
    - APP_PROXIES=*
    
    volumes:
    - bookstack_uploads:/var/www/bookstack/public/uploads
    - bookstack_storage-uploads:/var/www/bookstack/storage/uploads
    
    secrets:
    - bookstack_app_key
    - bookstack_db_pass
    
    networks:
    - bookstack
    - frontend
    
networks:
  bookstack:
    external: true
  frontend:
    external: true

secrets:
  bookstack_app_key:
    external: true
  bookstack_db_pass:
    external: true
  bookstack_root_pass:
    external: true

volumes:
  bookstack_mysql-data:
    external: true
  bookstack_uploads:
    external: true
  bookstack_storage-uploads:
    external: true

Traefik labels:

      traefik.http.routers.subdomain.entrypoints: websecure
      traefik.http.routers.subdomain.rule: Host(`subdomain.${HOST_DOMAIN}`) || HostRegexp(`^.+\.subdomain\.mydomain\.tld`)
      traefik.http.routers.subdomain.tls: true
      traefik.http.routers.subdomain.tls.certresolver: porkbun
      traefik.http.routers.subdomain.tls.domains[0].main: "subdomain.${HOST_DOMAIN}"
      traefik.http.routers.subdomain.tls.domains[0].sans: "*.subdomain.${HOST_DOMAIN}"
      traefik.http.routers.subdomain.priority: 999
      traefik.http.routers.subdomain.service: subdomain@file

Traefik static config:

http:
    subdomain:
      loadBalancer:
        servers:
          - url: "http://netbirdIP:80"

NPM:
image
Screenshot:
Bookstack screenshot
Status code:
image
Bookstack log:

bookstack:80 10.89.0.3 - - [18/Dec/2024:10:20:47 +0000] "GET /login HTTP/1.1" 500 15309 "https://books.subdomain.mydomain.tld/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0"

bookstack:80 10.89.0.3 - - [18/Dec/2024:10:20:47 +0000] "GET /dist/app.js.map HTTP/1.1" 500 15329 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0"

@den5o It would be ideal to watch the actual app error log to understand what error is actually occurring.

I have not tested it, but I think for this kind of compose setup the logs could usually be read via:

docker compose exec bookstack tail -f /var/www/bookstack/storage/logs/laravel.log

Not sure about podman though.

den5o commented

@ssddanbrown thanks for the suggestion.

Here is the output of podman compose exec bookstack cat /var/www/bookstack/storage/logs/laravel.log.

[2024-12-18 12:54:07] production.ERROR: Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm. {"exception":"[object] (RuntimeException(code: 0): Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm. at /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php:55)
[stacktrace]
#0 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php(32): Illuminate\\Encryption\\Encrypter->__construct('/run/secrets/bo...', 'AES-256-CBC')
#1 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(908): Illuminate\\Encryption\\EncryptionServiceProvider->Illuminate\\Encryption\\{closure}(Object(BookStack\\App\\Application), Array)
#2 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\\Container\\Container->build(Object(Closure))
#3 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(963): Illuminate\\Container\\Container->resolve('encrypter', Array, true)
#4 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\\Foundation\\Application->resolve('encrypter', Array)
#5 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(948): Illuminate\\Container\\Container->make('encrypter', Array)
#6 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(1066): Illuminate\\Foundation\\Application->make('encrypter')
#7 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(982): Illuminate\\Container\\Container->resolveClass(Object(ReflectionParameter))
#8 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(943): Illuminate\\Container\\Container->resolveDependencies(Array)
#9 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\\Container\\Container->build('BookStack\\\\Http\\\\...')
#10 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(963): Illuminate\\Container\\Container->resolve('BookStack\\\\Http\\\\...', Array, true)
#11 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\\Foundation\\Application->resolve('BookStack\\\\Http\\\\...', Array)
#12 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(948): Illuminate\\Container\\Container->make('BookStack\\\\Http\\\\...', Array)
#13 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(172): Illuminate\\Foundation\\Application->make('BookStack\\\\Http\\\\...')
#14 /var/www/bookstack/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#15 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\ApplyCspRules->handle(Object(BookStack\\Http\\Request), Object(Closure))
#16 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#17 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(805): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#18 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(784): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(BookStack\\Http\\Request))
#19 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(748): Illuminate\\Routing\\Router->runRoute(Object(BookStack\\Http\\Request), Object(Illuminate\\Routing\\Route))
#20 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(737): Illuminate\\Routing\\Router->dispatchToRoute(Object(BookStack\\Http\\Request))
#21 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch(Object(BookStack\\Http\\Request))
#22 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(BookStack\\Http\\Request))
#23 /var/www/bookstack/app/Http/Middleware/PreventResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#24 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\PreventResponseCaching->handle(Object(BookStack\\Http\\Request), Object(Closure))
#25 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#26 /var/www/bookstack/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(BookStack\\Http\\Request), Object(Closure))
#27 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\TrustProxies->handle(Object(BookStack\\Http\\Request), Object(Closure))
#28 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#29 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(BookStack\\Http\\Request), Object(Closure))
#30 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(BookStack\\Http\\Request), Object(Closure))
#31 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#32 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(BookStack\\Http\\Request), Object(Closure))
#33 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(99): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#34 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(BookStack\\Http\\Request), Object(Closure))
#35 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(BookStack\\Http\\Request))
#36 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#37 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(BookStack\\Http\\Request))
#38 /var/www/bookstack/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle(Object(BookStack\\Http\\Request))
#39 {main}
"} 
[2024-12-18 12:54:08] production.ERROR: Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm. {"exception":"[object] (RuntimeException(code: 0): Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm. at /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php:55)
[stacktrace]
#0 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php(32): Illuminate\\Encryption\\Encrypter->__construct('/run/secrets/bo...', 'AES-256-CBC')
#1 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(908): Illuminate\\Encryption\\EncryptionServiceProvider->Illuminate\\Encryption\\{closure}(Object(BookStack\\App\\Application), Array)
#2 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\\Container\\Container->build(Object(Closure))
#3 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(963): Illuminate\\Container\\Container->resolve('encrypter', Array, true)
#4 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\\Foundation\\Application->resolve('encrypter', Array)
#5 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(948): Illuminate\\Container\\Container->make('encrypter', Array)
#6 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(1066): Illuminate\\Foundation\\Application->make('encrypter')
#7 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(982): Illuminate\\Container\\Container->resolveClass(Object(ReflectionParameter))
#8 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(943): Illuminate\\Container\\Container->resolveDependencies(Array)
#9 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\\Container\\Container->build('BookStack\\\\Http\\\\...')
#10 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(963): Illuminate\\Container\\Container->resolve('BookStack\\\\Http\\\\...', Array, true)
#11 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\\Foundation\\Application->resolve('BookStack\\\\Http\\\\...', Array)
#12 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(948): Illuminate\\Container\\Container->make('BookStack\\\\Http\\\\...', Array)
#13 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(255): Illuminate\\Foundation\\Application->make('BookStack\\\\Http\\\\...')
#14 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(213): Illuminate\\Foundation\\Http\\Kernel->terminateMiddleware(Object(BookStack\\Http\\Request), Object(Illuminate\\Http\\Response))
#15 /var/www/bookstack/public/index.php(56): Illuminate\\Foundation\\Http\\Kernel->terminate(Object(BookStack\\Http\\Request), Object(Illuminate\\Http\\Response))
#16 {main}
"} ```
den5o commented

Could it be my use of podman secrets that is causing those cipher errors?

The database env vars also use secrets and boostack establishes a connection to it.

echo $APP_KEY returns /run/secrets/bookstack_app-key and cat /run/secrets/bookstack_app-key returns the correct key. I tried using APP_KEY_FILE but that returns errors in the log and the container restarts.

den5o commented

I tried it without secrets and the log remains the same

den5o commented

So I got it working. I made a few mistakes in my compose. It should have worked the first time I tried it without secrets but I may have missed a step in resetting the config.

  1. I didn't use _FILE at the end of MYSQL_ROOT_PASSWORD and MYSQL_PASSWORD so the passwords ended up being /run/secrets/bookstack_root_pass and /run/secrets/bookstack_db_pass respectively.
  2. Because of 1, bookstack connected to the database because the password was set to /run/secrets/bookstack_db_pass
  3. Because of 1 & 2 I assumed the bookstack image supported secrets.
  4. APP_KEY was invalid as it was set to /run/secrets/bookstack_app_key

Is there any chance of adding support for secrets in the future?

Hi @den5o, thanks for raising this and updating as you made progress through sorting your issues. I'll happily review any PRs that add the ability to refer to secrets from _FILE, but it's not something that I'll be working on personally.