<p>We ended up writing to a .env file and using <code>vlucas/phpdotenv</code> to read it in at app start.  Getting the php-fpm process to access environment variables was otherwise too complicated:  The PHP process would need a login shell and source <code>/etc/environment</code> in addition to the above configuration.  Then, each variable would have to be defined in <code>www.conf</code>, pointing to the environment variable.</p>
<p>Since we were writing variables out to <code>/etc/environment</code> at app server instance creation anyway, we just wrote out to <code>.env</code> instead and avoided the problem altogether.</p>

CC BY-SA 4.0
2022-03-29T20:59:31.277Z
2022-03-29T20:59:31.277Z
Micah Henning
<p>Our new Craft CMS instance in the AWS cloud won't load the security key from an environment variable.  (We do not use a .env file.)</p>
<pre class="lang-bash prettyprint-override"><code>$ curl http://localhost/actions/app/health-check
An internal server error occurred.

$ tail -n 50 /app/storage/logs/phperrors.log
...
Next Twig\Error\RuntimeError: An exception has been thrown during the rendering of a template (&quot;craft\web\Request::cookieValidationKey must be configured with a secret key.&quot;). in /app/vendor/craftcms/cms/src/templates/_layouts/base.html:63
Stack trace:
#0 /app/vendor/twig/twig/src/Template.php(378): Twig\Template-&gt;displayWithErrorHandling()
#1 /app/storage/runtime/compiled_templates/9e/9e97d03dbc595add011bcf027de03e51.php(48): Twig\Template-&gt;display()
#2 /app/vendor/twig/twig/src/Template.php(405): __TwigTemplate_54cbc54ad2a53aab200b46bb9cdf59b5-&gt;doDisplay()
#3 /app/vendor/twig/twig/src/Template.php(378): Twig\Template-&gt;displayWithErrorHandling()
#4 /app/storage/runtime/compiled_templates/b7/b7bfcc96c0d5436ed2de6531041c624b.php(46): Twig\Template-&gt;display()
#5 /app/vendor/twig/twig/src/Template.php(405): __TwigTemplate_b556258081d6ccb36bcd554f2672ce05-&gt;doDisplay()
#6 /app/vendor/twig/twig/src/Template.php(378): Twig\Template-&gt;displayWithErrorHandling()
#7 /app/vendor/twig/twig/src/Template.php(390): Twig\Template-&gt;display()
#8 /app/vendor/twig/twig/src/TemplateWrapper.php(45): Twig\Template-&gt;render()
#9 /app/vendor/twig/twig/src/Environment.php(318): Twig\TemplateWrapper-&gt;render()
#10 /app/vendor/craftcms/cms/src/web/View.php(408): Twig\Environment-&gt;render()
#11 /app/vendor/craftcms/cms/src/web/View.php(461): craft\web\View-&gt;renderTemplate()
#12 /app/vendor/craftcms/cms/src/web/Controller.php(201): craft\web\View-&gt;renderPageTemplate()
#13 /app/vendor/craftcms/cms/src/controllers/TemplatesController.php(233): craft\web\Controller-&gt;renderTemplate()
#14 [internal function]: craft\controllers\TemplatesController-&gt;actionRenderError()
#15 /app/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array()
#16 /app/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction-&gt;runWithParams()
#17 /app/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller-&gt;runAction()
#18 /app/vendor/craftcms/cms/src/web/Application.php(293): yii\base\Module-&gt;runAction()
#19 /app/vendor/yiisoft/yii2/web/ErrorHandler.php(109): craft\web\Application-&gt;runAction()
#20 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(192): yii\web\ErrorHandler-&gt;renderException()
#21 /app/vendor/yiisoft/yii2/base/ErrorHandler.php(135): craft\web\ErrorHandler-&gt;renderException()
#22 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(71): yii\base\ErrorHandler-&gt;handleException()
#23 [internal function]: craft\web\ErrorHandler-&gt;handleException()
#24 {main}
Previous exception:
craft\web\ServiceUnavailableHttpException in /app/vendor/craftcms/cms/src/web/Application.php:571
Stack trace:
#0 /app/vendor/craftcms/cms/src/web/Application.php(201): craft\web\Application-&gt;_processInstallRequest()
#1 /app/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application-&gt;handleRequest()
#2 /app/web/index.php(21): yii\base\Application-&gt;run()
#3 {main}
</code></pre>
<h4><code>/app/config/general.php</code></h4>
<pre class="lang-php prettyprint-override"><code>&lt;?php
/**
 * General Configuration
 *
 * All of your system's general configuration settings go in here. You can see a
 * list of the available settings in vendor/craftcms/cms/src/config/GeneralConfig.php.
 *
 * @see \craft\config\GeneralConfig
 */

return [
  // Global settings
  '*' =&gt; [
    // Default Week Start Day (0 = Sunday, 1 = Monday...)
    'defaultWeekStartDay' =&gt; 1,

    // Whether generated URLs should omit &quot;index.php&quot;
    'omitScriptNameInUrls' =&gt; true,

    // Control Panel access via environment variable
    'baseCpUrl' =&gt; craft\helpers\App::env('BASE_CP_URL') ?: null,

    // Control Panel trigger word
    'cpTrigger' =&gt; 'admin',

    // The secure key Craft will use for hashing and encrypting data
    'securityKey' =&gt; craft\helpers\App::env('SECURITY_KEY'),

    // Whether to save the project config out to config/project.yaml
    // (see https://docs.craftcms.com/v3/project-config.html)
    'useProjectConfigFile' =&gt; false,

    // dont set X-Powered-By server-side header
    'sendPoweredByHeader' =&gt; false,

    // account lockouts require admin to unlock
    'cooldownDuration' =&gt; 0,

    // set cookie attribute samesite to lax
    'sameSiteCookieValue' =&gt; 'Lax',
  ],

  // Dev environment settings
  'development' =&gt; [
    // Dev Mode (see https://craftcms.com/guides/what-dev-mode-does)
    'devMode' =&gt; true,
  ],

  // Staging environment settings
  'staging' =&gt; [
    // Set this to `false` to prevent administrative changes from being made on staging
    'allowAdminChanges' =&gt; false,
  ],

  // Production environment settings
  'production' =&gt; [
    // Set this to `false` to prevent administrative changes from being made on production
    'allowAdminChanges' =&gt; false,
  ],
];
</code></pre>
<h4>Configuration details</h4>
<p>We have the default PHP systemd service loading <code>/etc/environment</code>, which contains variable <code>SECURITY_KEY</code>.  Craft CMS config file <code>/app/config/general.php</code> gets the security key from the environment.  PHP is configured to use environment variables first, and to not override them.  Furthermore, when I enter the PHP console and output the environment variables, I can see it in the list.</p>
<pre class="lang-bash prettyprint-override"><code>$ cat /etc/systemd/system/multi-user.target.wants/php8.1-fpm.service 
[Unit]
Description=The PHP 8.1 FastCGI Process Manager
Documentation=man:php-fpm8.1(8)
After=network.target

[Service]
EnvironmentFile=/etc/environment
Type=notify
ExecStart=/usr/sbin/php-fpm8.1 --nodaemonize --fpm-config /etc/php/8.1/fpm/php-fpm.conf
ExecStartPost=-/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/8.1/fpm/pool.d/www.conf 81
ExecStopPost=-/usr/lib/php/php-fpm-socket-helper remove /run/php/php-fpm.sock /etc/php/8.1/fpm/pool.d/www.conf 81
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
</code></pre>
<pre class="lang-bash prettyprint-override"><code>$ cat /etc/environment | grep SEC
SECURITY_KEY=tjsg6CzzuHBCNF9smvSA_5WKqA-5VJTl
</code></pre>
<pre class="lang-bash prettyprint-override"><code>$ cat /etc/php/8.1/fpm/php-fpm.conf | grep &quot;^[^;]&quot;
[global]
pid = /run/php/php-fpm.pid
error_log = /var/log/php-fpm.log
include=/etc/php/8.1/fpm/pool.d/*.conf
</code></pre>
<pre class="lang-bash prettyprint-override"><code>$ cat /etc/php/8.1/fpm/pool.d/www.conf | grep &quot;^[^;]&quot;
[www]
user = www-data
group = www-data
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
clear_env = no
</code></pre>
<pre class="lang-bash prettyprint-override"><code>$ cat /etc/php/8.1/fpm/php.ini | grep variables_order\ =
variables_order = &quot;EGPCS&quot;
</code></pre>
<pre class="lang-php prettyprint-override"><code>$ php -a
Interactive shell

php &gt; print_r(getenv());
Array
(
    // ...
    [SECURITY_KEY] =&gt; tjsg6CzzuHBCNF9smvSA_5WKqA-5VJTl
    // ...
)
</code></pre>
<h4>Environment details</h4>
<pre class="lang-bash prettyprint-override"><code>$ cat composer.json | grep craftcms/cms
    &quot;craftcms/cms&quot;: &quot;3.7.36&quot;,
</code></pre>
<pre class="lang-bash prettyprint-override"><code>$ echo $(which php)
/usr/bin/php

$ php --version
PHP 8.1.3 (cli) (built: Feb 21 2022 14:48:42) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.3, Copyright (c), by Zend Technologies

$ php --modules
[PHP Modules]
bcmath
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gettext
hash
iconv
imagick
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
readline
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zip
zlib

[Zend Modules]
Zend OPcache
</code></pre>
<pre class="lang-bash prettyprint-override"><code>$ uname -a
Linux ip-10-14-32-107 5.13.0-1017-aws #19~20.04.1-Ubuntu SMP Mon Mar 7 12:55:31 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux
</code></pre>

CC BY-SA 4.0
2022-03-21T11:10:23.447Z
Which version of `vlucas/phpdotenv` do you use?
Oli
CC BY-SA 4.0
2022-03-21T12:08:34.837Z
@Oli thanks for your reply! `composer.lock` shows `vlucas/phpdotenv` at v3.6.10
Micah Henning
CC BY-SA 4.0
2022-03-21T12:50:32.720Z
Not sure it will work but could you update to `^5.4.0` then change the call in your `web/index.php` to [this](https://github.com/craftcms/craft/blob/main/bootstrap.php#L15).
Oli
CC BY-SA 4.0
2022-03-21T17:45:53.287Z
I updated the library and changed the call in `web/index.php` but am still getting the same error.  :(
Micah Henning
<craft3><php><deployment>
Security Key Not Loading from Environment: Next Twig\Error\RuntimeError: craft\web\Request::cookieValidationKey must be configured with a secret key
# Security Key Not Loading from Environment: Next Twig\Error\RuntimeError: craft\web\Request::cookieValidationKey must be configured with a secret key

(Asked by: username_0 on 2022-03-16)

Our new Craft CMS instance in the AWS cloud won't load the security key from an environment variable.  (We do not use a .env file.)
$ curl http://localhost/actions/app/health-check
An internal server error occurred.

$ tail -n 50 /app/storage/logs/phperrors.log
...
Next Twig\Error\RuntimeError: An exception has been thrown during the rendering of a template ("craft\web\Request::cookieValidationKey must be configured with a secret key."). in /app/vendor/craftcms/cms/src/templates/_layouts/base.html:63
Stack trace:
#0 /app/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling()
#1 /app/storage/runtime/compiled_templates/9e/9e97d03dbc595add011bcf027de03e51.php(48): Twig\Template->display()
#2 /app/vendor/twig/twig/src/Template.php(405): __TwigTemplate_54cbc54ad2a53aab200b46bb9cdf59b5->doDisplay()
#3 /app/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling()
#4 /app/storage/runtime/compiled_templates/b7/b7bfcc96c0d5436ed2de6531041c624b.php(46): Twig\Template->display()
#5 /app/vendor/twig/twig/src/Template.php(405): __TwigTemplate_b556258081d6ccb36bcd554f2672ce05->doDisplay()
#6 /app/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling()
#7 /app/vendor/twig/twig/src/Template.php(390): Twig\Template->display()
#8 /app/vendor/twig/twig/src/TemplateWrapper.php(45): Twig\Template->render()
#9 /app/vendor/twig/twig/src/Environment.php(318): Twig\TemplateWrapper->render()
#10 /app/vendor/craftcms/cms/src/web/View.php(408): Twig\Environment->render()
#11 /app/vendor/craftcms/cms/src/web/View.php(461): craft\web\View->renderTemplate()
#12 /app/vendor/craftcms/cms/src/web/Controller.php(201): craft\web\View->renderPageTemplate()
#13 /app/vendor/craftcms/cms/src/controllers/TemplatesController.php(233): craft\web\Controller->renderTemplate()
#14 [internal function]: craft\controllers\TemplatesController->actionRenderError()
#15 /app/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array()
#16 /app/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams()
#17 /app/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction()
#18 /app/vendor/craftcms/cms/src/web/Application.php(293): yii\base\Module->runAction()
#19 /app/vendor/yiisoft/yii2/web/ErrorHandler.php(109): craft\web\Application->runAction()
#20 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(192): yii\web\ErrorHandler->renderException()
#21 /app/vendor/yiisoft/yii2/base/ErrorHandler.php(135): craft\web\ErrorHandler->renderException()
#22 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(71): yii\base\ErrorHandler->handleException()
#23 [internal function]: craft\web\ErrorHandler->handleException()
#24 {main}
Previous exception:
craft\web\ServiceUnavailableHttpException in /app/vendor/craftcms/cms/src/web/Application.php:571
Stack trace:
#0 /app/vendor/craftcms/cms/src/web/Application.php(201): craft\web\Application->_processInstallRequest()
#1 /app/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest()
#2 /app/web/index.php(21): yii\base\Application->run()
#3 {main}

/app/config/general.php
 [
    // Default Week Start Day (0 = Sunday, 1 = Monday...)
    'defaultWeekStartDay' => 1,

    // Whether generated URLs should omit "index.php"
    'omitScriptNameInUrls' => true,

    // Control Panel access via environment variable
    'baseCpUrl' => craft\helpers\App::env('BASE_CP_URL') ?: null,

    // Control Panel trigger word
    'cpTrigger' => 'admin',

    // The secure key Craft will use for hashing and encrypting data
    'securityKey' => craft\helpers\App::env('SECURITY_KEY'),

    // Whether to save the project config out to config/project.yaml
    // (see https://docs.craftcms.com/v3/project-config.html)
    'useProjectConfigFile' => false,

    // dont set X-Powered-By server-side header
    'sendPoweredByHeader' => false,

    // account lockouts require admin to unlock
    'cooldownDuration' => 0,

    // set cookie attribute samesite to lax
    'sameSiteCookieValue' => 'Lax',
  ],

  // Dev environment settings
  'development' => [
    // Dev Mode (see https://craftcms.com/guides/what-dev-mode-does)
    'devMode' => true,
  ],

  // Staging environment settings
  'staging' => [
    // Set this to `false` to prevent administrative changes from being made on staging
    'allowAdminChanges' => false,
  ],

  // Production environment settings
  'production' => [
    // Set this to `false` to prevent administrative changes from being made on production
    'allowAdminChanges' => false,
  ],
];

Configuration details
We have the default PHP systemd service loading /etc/environment, which contains variable SECURITY_KEY.  Craft CMS config file /app/config/general.php gets the security key from the environment.  PHP is configured to use environment variables first, and to not override them.  Furthermore, when I enter the PHP console and output the environment variables, I can see it in the list.
$ cat /etc/systemd/system/multi-user.target.wants/php8.1-fpm.service 
[Unit]
Description=The PHP 8.1 FastCGI Process Manager
Documentation=man:php-fpm8.1(8)
After=network.target

[Service]
EnvironmentFile=/etc/environment
Type=notify
ExecStart=/usr/sbin/php-fpm8.1 --nodaemonize --fpm-config /etc/php/8.1/fpm/php-fpm.conf
ExecStartPost=-/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/8.1/fpm/pool.d/www.conf 81
ExecStopPost=-/usr/lib/php/php-fpm-socket-helper remove /run/php/php-fpm.sock /etc/php/8.1/fpm/pool.d/www.conf 81
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

$ cat /etc/environment | grep SEC
SECURITY_KEY=tjsg6CzzuHBCNF9smvSA_5WKqA-5VJTl

$ cat /etc/php/8.1/fpm/php-fpm.conf | grep "^[^;]"
[global]
pid = /run/php/php-fpm.pid
error_log = /var/log/php-fpm.log
include=/etc/php/8.1/fpm/pool.d/*.conf

$ cat /etc/php/8.1/fpm/pool.d/www.conf | grep "^[^;]"
[www]
user = www-data
group = www-data
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
clear_env = no

$ cat /etc/php/8.1/fpm/php.ini | grep variables_order\ =
variables_order = "EGPCS"

$ php -a
Interactive shell

php > print_r(getenv());
Array
(
    // ...
    [SECURITY_KEY] => tjsg6CzzuHBCNF9smvSA_5WKqA-5VJTl
    // ...
)

Environment details
$ cat composer.json | grep craftcms/cms
    "craftcms/cms": "3.7.36",

$ echo $(which php)
/usr/bin/php

$ php --version
PHP 8.1.3 (cli) (built: Feb 21 2022 14:48:42) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.3, Copyright (c), by Zend Technologies

$ php --modules
[PHP Modules]
bcmath
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gettext
hash
iconv
imagick
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
readline
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zip
zlib

[Zend Modules]
Zend OPcache

$ uname -a
Linux ip-10-14-32-107 5.13.0-1017-aws #19~20.04.1-Ubuntu SMP Mon Mar 7 12:55:31 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux

**Tags:** craft3, php, deployment
> **Comments:**
> **username_1**: Which version of `vlucas/phpdotenv` do you use?  
> **username_0**: @Oli thanks for your reply! `composer.lock` shows `vlucas/phpdotenv` at v3.6.10  
> **username_1**: Not sure it will work but could you update to `^5.4.0` then change the call in your `web/index.php` to [this](https://github.com/craftcms/craft/blob/main/bootstrap.php#L15).  
> **username_0**: I updated the library and changed the call in `web/index.php` but am still getting the same error.  :(  

---

## 1 answers

### Answer by username_0 on 2022-03-29. Score: 2 | Accepted answer

We ended up writing to a .env file and using `vlucas/phpdotenv` to read it in at app start. Getting the php-fpm process to access environment variables was otherwise too complicated: The PHP process would need a login shell and source `/etc/environment` in addition to the above configuration. Then, each variable would have to be defined in `www.conf`, pointing to the environment variable.

Since we were writing variables out to `/etc/environment` at app server instance creation anyway, we just wrote out to `.env` instead and avoided the problem altogether.


---

