monicahq/docker

APP_KEY and Docker secrets error: Unsupported cipher or incorrect key length

josephbadow opened this issue · 1 comments

Docker secrets have recently been added to this project (#93), which is awesome, but I can't figure out how to get the variable APP_KEY to work.

version: "3.9"

services:
  app:
    container_name: monica-app
    depends_on:
      - db
    environment:
      - APP_ENV=production
      - APP_KEY=/run/secrets/monica-app-key
      - APP_TRUSTED_PROXIES=172.21.0.2
      - APP_URL=https://my-super-secret-domain.com
      - DB_HOST=db
      - DB_DATABASE=monica
      - DB_USERNAME=monica
      - DB_PASSWORD_FILE=/run/secrets/monica-mysql-password
      - LOG_CHANNEL=stderr
      - CACHE_DRIVER=database
      - SESSION_DRIVER=database
      - QUEUE_DRIVER=sync
      - TZ=Europe/Berlin
    image: monica:apache
    networks:
      - proxy
      - monica
    restart: always
    secrets:
      - monica-app-key
      - monica-mysql-password
    volumes:
      - data:/var/www/html/storage

  db:
    container_name: monica-db
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=true
      - MYSQL_DATABASE=monica
      - MYSQL_USER=monica
      - MYSQL_PASSWORD_FILE=/run/secrets/monica-mysql-password
      - TZ=Europe/Berlin
    image: mysql:8.0
    networks:
      - monica
    restart: always
    secrets:
      - monica-mysql-password
    volumes:
      - mysql:/var/lib/mysql

secrets:
  monica-mysql-password:
     file: ./.secrets/mysql.txt
  monica-app-key:
     file: ./.secrets/appkey.txt

networks:
  proxy:
    external: true
  monica:

volumes:
  data:
  mysql:

My docker-compose.yml file works in general. However, when I access https://my-super-secret-domain.com it shows the following error:

monica-app  | [2023-02-12 21:08:40] 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/html/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php:55)
monica-app  | [stacktrace]
monica-app  | #0 /var/www/html/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php(32): Illuminate\\Encryption\\Encrypter->__construct('/run/secrets/mo...', 'AES-256-CBC')
monica-app  | #1 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(889): Illuminate\\Encryption\\EncryptionServiceProvider->Illuminate\\Encryption\\{closure}(Object(Illuminate\\Foundation\\Application), Array)
monica-app  | #2 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(774): Illuminate\\Container\\Container->build(Object(Closure))
monica-app  | #3 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(860): Illuminate\\Container\\Container->resolve('encrypter', Array, true)
monica-app  | #4 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(710): Illuminate\\Foundation\\Application->resolve('encrypter', Array)
monica-app  | #5 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(845): Illuminate\\Container\\Container->make('encrypter', Array)
monica-app  | #6 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(1047): Illuminate\\Foundation\\Application->make('encrypter')
monica-app  | #7 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(963): Illuminate\\Container\\Container->resolveClass(Object(ReflectionParameter))
monica-app  | #8 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(924): Illuminate\\Container\\Container->resolveDependencies(Array)
monica-app  | #9 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(774): Illuminate\\Container\\Container->build('App\\\\Http\\\\Middle...')
monica-app  | #10 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(860): Illuminate\\Container\\Container->resolve('App\\\\Http\\\\Middle...', Array, true)
monica-app  | #11 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(710): Illuminate\\Foundation\\Application->resolve('App\\\\Http\\\\Middle...', Array)
monica-app  | #12 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(845): Illuminate\\Container\\Container->make('App\\\\Http\\\\Middle...', Array)
monica-app  | #13 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(239): Illuminate\\Foundation\\Application->make('App\\\\Http\\\\Middle...')
monica-app  | #14 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(203): Illuminate\\Foundation\\Http\\Kernel->terminateMiddleware(Object(Illuminate\\Http\\Request), Object(Illuminate\\Http\\Response))
monica-app  | #15 /var/www/html/public/index.php(60): Illuminate\\Foundation\\Http\\Kernel->terminate(Object(Illuminate\\Http\\Request), Object(Illuminate\\Http\\Response))
monica-app  | #16 {main}
monica-app  | "}

I checked several issues within this repository, as well as the main monica repo, and found similar issues like #6449. They suggest, as well as the documentation command for APP_KEY, that the 32 character string should be prefixed with base64:.

Quick side question: Why does openssl rand -base64 32 create a string with more than 32 characters?

Using APP_KEY directly in the docker-compose.yml file

docker-compose.yml

services:
  app:
    container_name: monica-app
    depends_on:
      - db
    environment:
      - APP_ENV=production
      - APP_KEY=base64:!-A-RANDOM-32-CHARACTER-STRING-!

This example works, but I don't want to have my environment variables available just like that.

Using APP_KEY in a env_file

docker-compose.yml

services:
  app:
    container_name: monica-app
    depends_on:
      - db
    env_file: .env
    environment:
      - APP_ENV=production

.env

APP_KEY=base64:!-A-RANDOM-32-CHARACTER-STRING-!

This example works as well, but I still don't want to have my environment variables available just like that.

Using Docker secrets

docker-compose.yml

services:
  app:
    container_name: monica-app
    depends_on:
      - db
    environment:
      - APP_ENV=production
      - APP_KEY=/run/secrets/monica-app-key
    secrets:
      - monica-app-key

secrets:
  monica-app-key:
     file: .secrets/appkey.txt

.secrets/appkey.txt

APP_KEY=base64:!-A-RANDOM-32-CHARACTER-STRING-!

It doesn't work with the same syntax as the .env file

.secrets/appkey.txt

APP_KEY=!-A-RANDOM-32-CHARACTER-STRING-!

It also won't work when I remove the prefix base64:.

Setting the path for the Docker secret to the env_file doesn't work either.

docker-compose.yml

secrets:
  monica-app-key:
     file: .env

  • Docker Secrets work for the MySQL Password.
  • The application also works when I omit the whole APP_KEY variable. However, I assume that I can't recover data in a recovery process without that key.

I am currently using the env_file as a workaround but would appreciate any input that you might have.

asbiin commented

Hi @josephbadow

To use secrets, you need to

  1. Read the documentation at https://docs.docker.com/engine/swarm/secrets/

  2. Generate the APP_KEY with this command:

    echo -n 'base64:'; openssl rand -base64 32
    

    Indeed, openssl is generating a 32 char random string, but we need to convert it as base64 string, hence the base64: prefix.
    Example: base64:P0Ayg89cUUr0c/15nRzGEkVcPsXQPrOjmG2vO526b8U=
    The key can also be an ASCII 32 string, without the base64: prefix then.

  3. Store this key in a file:

    echo -n 'base64:'; openssl rand -base64 32 > monica_app_key.txt
    

    Important: the file must contain the raw value of the key, no APP_KEY= prefix!

  4. Then run your monica instance with a docker-compose.yml file like this:

    services:
      app:
        image: monica
        environment:
          - APP_KEY_FILE=/run/secrets/monica_app_key
        secrets:
          - monica_app_key
    
    secrets:
      monica_app_key:
         file: monica_app_key.txt
    

    Important: the environment variable is APP_KEY_FILE, with the _FILE suffix. All variable that support secrets can and must be defined with a *_FILE equivalent.

Please tell me if it's working or not!