Profile pic of Tommy KuTommy Ku's Blog

Reading and thinking

Persistent .env configurations across deployments on OpenShift for Laravel 5

Posted on September 28, 2015

People get hacked easily when they include the environmental files or passwords in version control. Yet keeping it all local makes each and every deployment to OpenShift troublesome as you will need to scp the environmental file .env onto server every time you deploy.

You can set up an action hook to create a symbolic link inside the deployment directory to $OPENSHIFT_DATA_DIR which keeps the .env persistently. I know this has been covered in a previous tutorial but it doesn’t hurt repeating myself as a reminder of this security trick.

Img. Tried my luck with some keywords, obviously people still do that nowadays

Moreover, a team of students from a class I am mentoring got themselves a $10,000 AWS bill because they published the .pem files on GitHub and somehow got hacked.

Img. I told them to use OpenShift instead of AWS for educational purpose

Now you see how important and trouble-free it is if your server and your local environments keep their configurations to themselves. Let’s see how you can do it.


First you should prepare an OpenShift instanace and a Laravel build on your local machine. My previous tutorial should get this part well covered.

Managing multiple .env locally

To cover the basics, you should first try to have multiple .env locally. You may use an artisan command I made before or archieve the same effect with symbolic link.

In command line, create a couple of environmental configuration files from your Laravel directory by copying the default .env.example.

$ cp .env.example .local.env
$ cp .env.example .testing.env

Then make sure this line is inside your .gitignore file.


By default Laravel does not come with .env file, so there is nothing to ignore yet. Then create a symbolic link to .local.env named .env.

$ ln -s .local.env .env
$ ls -lah
lrwxrwxrwx  1 user user   10 Sep 28 18:21 .env -> .local.env
-rw-rw-r--  1 user user  306 Jul  2 02:30 .local.env

So .env is now a symbolic link to .local.env, modifying either of them changes both. How do you switch to testing environment locally?

$ rm .env
$ ln -s .testing.env .env

That’s it. Don’t worry, removing symbolic link doesn’t remove the actual file.

Uploading .env to server

Provided that yout have SSH access to the server (you do so by submitting your public key to OpenShift web panel), first SSH into the server to locate $OPENSHIFT_DATA_DIR.

# figure out the user name and hostname of your OpenShift instance
$ git remote -v
origin  ssh://[email protected]/~/git/blog.git/ (fetch)
origin  ssh://[email protected]/~/git/blog.git/ (push)
# ssh into the instance to find where the data dir is
$ ssh [email protected]
# on remote server
[ xxxxxxxxxxxxxxxxxxxxxxxx]\> echo $OPENSHIFT_DATA_DIR
# this is the path to data dir where you should store the .env

Now scp the current .env you use locally to server. Note that .local.env is renamed to .production.env when it is uploaded. You could make .production.env locally, edit the configuration then upload instead.

$ scp .local.env [email protected]:/var/lib/openshift/xxxxxxxxxxxxxxxxxxxxxxxx/app-root/data/.production.env

Now .production.env is on the server, next you should create a symbolic link to it whenever you deploy a new version of your software.

Creating a build hook

Git runs a post-receive hook if you write it in .git/hooks/. OpenShift plays a different rule, it runs the scripts located in .openshift/action_hooks/ as well. From your project root folder, create folders .openshift/action_hooks/ if they weren’t there already, then make a build file and flip the execute bit.

$ mkdir -p .openshift/action_hooks
$ touch .openshift/action_hooks
$ chmod +x .openshift/action_hooks

Then, make sure your build file has these content.



if [ ! -f "$OPENSHIFT_DATA_DIR/composer.phar" ]; then
    echo 'Installing Composer'
        curl -s | php -- --quiet --install-dir=$OPENSHIFT_DATA_DIR
    echo 'Updating Composer'
    php $OPENSHIFT_DATA_DIR/composer.phar -q --no-ansi self-update

if [ -d "$OPENSHIFT_REPO_DIR/vendor" ]; then
    echo 'Laravel dependencies already installed, Moving on...'
    echo 'Hang in there, we are getting ready to Install/Update Laravel dependencies'
    # Activate composer install for Laravel on Git Push
    ( echo 'Installing/Updating Laravel'; unset GIT_DIR ; cd $OPENSHIFT_REPO_DIR ; php $OPENSHIFT_DATA_DIR/composer.phar -q --no-ansi install ; )   

( echo 'Loading environmental configurations'; ln -s "$OPENSHIFT_DATA_DIR/.production.env" "$OPENSHIFT_REPO_DIR/.env"; cd $OPENSHIFT_REPO_DIR; )

The first couple lines will fetch the dependencies automatically, and the last line with words Loading environmental configurations makes sure a symbolic link .env pointing to .production.env is created each time you push to server.

Why it has to be so cryptic?

Albeit a little bit off-topic, this question keeps popping up in my mind as I wrote this article. From my experience with Ruby on Rails, you can deploy and do the symbolic link thing all inside the confines of your project; i.e. no need for a sneaky hook in .openshift or .git.

Then when I looked it up, someone did use a Ruby gem Capistrano to deploy his Laravel application.

Deploying a PHP project, using a Ruby gem. That’s ingenius.

And it goes no further than that, no automatic push-from-local ways of deploying a Laravel application except for bunch of hacks and cryptic scripts.

Yeah, next time, let’s talk about a simplier Laravel deployment.