Symfony4: Access DEV environment on production server - php

In Symfony3, when I want to browse the website in DEV environment on the "live" server, I just enter my ip address in /web/app_dev.php and open http://www.example.com/app_dev.php/ in the browser.
Since in Symfony4, the environment is now set in /.env, how can I see the DEV environment on the production machine?
EDIT: I'm looking for a solution that works in production, so applying any global changes (like e.g. setting APP_ENV=dev in /.env) is not an option.

You can change inside your .env file APP_ENV to dev like this:
APP_ENV=dev
If you set that variable symfony load the system into dev enviroment because inside Kernel.php there is this line that check that variable:
$kernel = new Kernel($_SERVER['APP_ENV'] ?? 'dev', $_SERVER['APP_DEBUG'] ?? false);
If you want to do it without change .env file you can for example set a variable in the Apache vhost or Nginx FastCgi configuration, based on the URL you are visiting from - such as APP_ENV=/home/user/app-name/dev.env or on a live server: APP_ENV=/etc/app-name.prod.env
So in this case you have many .env file but you can use rule based on url

At first this is a bad idea and that's why it wasn't possible by default to access app_dev.php on production server (symfony < 4). You're giving a lot of internal information to public and especially to attackers.
From symfony docs:
After you deploy to production, make sure that you cannot access the app_dev.php or config.php scripts (i.e. http://example.com/app_dev.php and http://example.com/config.php). If you can access these, be sure to remove the DEV section from the above configuration.
You should be able to debug most of the things from logs.
But if you really want to do it, you can just remove public/index.php and create public/app.php and public/app_dev.php like it was in symfony 3 and make it work with env variables. - https://github.com/symfony/symfony-standard/tree/3.4/web
EDIT: To be clear: you can just remove public/index.php, create public/app.php, public/app_dev.php (copies of index.php). And get inspiration from symfony 3 standard edition to adjust it to your needs.
EDIT2: As #Cerad mentioned it's a better idea to have index.php and index_dev.php file names (following Symfony4 decisions).

Related

Laravel Dynamically load different .env file

I would like to ask how can I possibly dynamically load different env file setting?
I have read the documentation, I have created two files (.env and .env.uat)
.env for development and .env.uat for client testing environment, and it depends on the url to use different env file, eg: (company-dev) -> .env, (company-uat) -> .env.uat
I have added these two lines of code to bootstrap/app.php, actually it works, but when I want to execute php artisan migrate, then it said that HTTP_HOST couldn't found, so it will load the .env.uat as the fallback file. Can someone tell me where should I modify code please? Thanks!! (Actually I knew I can manually change the .env file in different environment everytime, I am seeking some automatic way to recognise the env file for me.
$envFile = $_SERVER['HTTP_HOST'] == 'xxx-dev-testing.com' ? '.env' : '.env-uat';
$app->loadEnvironmentFrom($envFile);
There's no HTTP_HOST in the command line. You'll need a different approach. Ultimately, though, .env shouldn't be in version control at all. Your UAT environment would just have a .env with different values.

How to switch between Symfony Environments?

I got my Symfony 3.4 application deployed using PROD environment following this guide: https://symfony.com/doc/3.4/deployment.html (seems that, by default, was running on PROD, since I does not selected any environment during installation...)
In the near future, this machine will take the PRE-PRODUCTION role, so I created a new environment called pre for my application following this guide: http://symfony.com/doc/3.4/configuration/environments.html#creating-a-new-environment
Now I'm wondering how to switch this machine to new PRE environment.
I read these guides, but I'm still confused:
1) http://symfony.com/doc/3.4/configuration/environments.html#executing-an-application-in-different-environments
2) http://symfony.com/doc/3.4/setup/web_server_configuration.html
On the current machine, I'm using Apache; but for production, and following updates, I'll considere to start using NGINX. So, both options are appreciated.
If you've followed the instructions in the documentation you've entered:
Because you'll want this environment to be accessible via a browser, you should also create a front controller for it. Copy the web/app.php file to web/app_benchmark.php and edit the environment to be benchmark
then you have app_pre.php front controller with this line:
$kernel = new AppKernel('pre', false);
Just point your Apache web server to use app_pre.php instead of app.php as the front controller and your environment is switched.

Symfony 4, .env files and production

.env files are very handy with docker, kubernetes, etc
But what if I have simple nginx server without any orchestration and a pack of cron workers and a pack of daemons(systemd/supervisord/etc)?
I can write these env variables to nginx server section, but I have to set up hundreds of env variables to each cron worker or daemon.
I found a quick solution: using symfony/dotenv component in production.
But it seems to me dirty. Who can suggest better solution?
First of all, not all variables need to be specified using environment variables. Keep variables that do not differ per system in a separate yaml file.
When you have just one environment per server you can specify the environment variables globally in /etc/environment. (Might be different depending on your Linux flavour)
Personally I find that using DotEnv poses more difficulties than solutions when you run multiple environments on the same server. Specifying the variables in a global configuration like /etc/environment doesn't work in that case.
Specifying the environment variables in nginx isn't a solution either since, as you mentioned, they won't be picked up by cron, supervisor, the console, etc. For me, this was the reason to completely remove DotEnv and work with the good old parameters.yaml file again. Nothing will stop you from doing that.
Another solution however is to keep using DotEnv in your development environment and to include a separate parameters.yaml in production. You can then define the environment variables as follows:
parameters:
env(APP_ENV): prod
env(APP_SECRET): 3d05afda019ed4e3faaf936e3ce393ba
...
A way to include this file is to put the following in your services.yaml file:
imports:
- { resource: parameters.yaml, ignore_errors: true }
This way, the import will be ignored when no parameters.yaml file exists. Another solution is to add a line to configureContainer() in your Kernel class:
$loader->load($confDir.'/parameters'.self::CONFIG_EXTS, 'glob');
if you want to centralize your environment variables for cli and fpm you can define them once in your system. And then reference them all in your php-fpm.conf:
....
[www]
env[APP_VAR1] = $APP_VAR1
env[APP_VAR2] = $APP_VAR2
...
In that way you can avoid using DotEnv in production which is encouraged by best practices.
Hope this helps.

Laravel 5 configuration - environments and overriding

I installed fresh Laravel 5 copy.
My detectEnvironment function is defined this way:
$app->detectEnvironment(function()
{
return 'local';
return getenv('APP_ENV') ?: 'production';
});
In config\local I've created database.php file:
<?php
return [
'nothing' => 'new',
];
I run php artisan clear-compiled.
My index method of WelcomeController is defined this way:
public function index(Application $app)
{
echo $app->environment();
var_dump($app['config']['database']);
//echo $app['config']['database'];
return view('welcome');
}
Application was imported this way: use Illuminate\Foundation\Application;
The result I get is:
local array(1) { ["nothing"]=> string(3) "new" }
whereas I would expect Laravel to cascade config file with production one (with the default config\database.php file.
The strange thing is that even if I comment the line return 'local'; run again php artisan clear-compiled it shows:
production array(1) { ["nothing"]=> string(3) "new" }
so it seems it always loads database.php file content (this one from local folder) and overrides main database.php file. It works fine again when I change this file name to for example aaa.php.
Is it a bug or maybe environment configuration shouldn't be stored inside config directory? But if not, where should they be store? I don't know if it's a bug or a feature so if anyone knows more about it, please give me a clue.
Although in documentation for Laravel dev (5.0) there is info that configuration will cascade it's not true. I have tested it about 2 weeks ago and it seems at the moment the only way to have different values for environments is using ENV file where you put custom values for current environment. Putting settings in directories won't work as it used to work however it's possible it will change or maybe has been already changed for last 2 weeks.
There's a package that brings the cascading config system back to Laravel 5.
Disclaimer: I am the author.
For me it looks like defect in Laravel 5 dev branch. I was able to work around by adding manual environment detection and configuration. This code does it.
'default' => $app->environment()=='testing'?'sqlite':'mysql',
It is easy to configure Laravel 5 environment.
Open your root application folder and find ".env.example",
Copy and rename into ".env",
Please fit ".env" file into your environment,
If you use GIT, make sure you don't push this file to your GIT repository.
For 'complete explanation', I write this configuration here.
Edited;
I quote from the developer in His github repository readme.md file;
phpdotenv is made for development environments, and generally should
not be used in production. In production, the actual environment
variables should be set so that there is no overhead of loading the
.env file on each request. This can be achieved via an automated
deployment process with tools like Vagrant, chef, or Puppet, or can be
set manually with cloud hosts like Pagodabox and Heroku.
So, you need to create ".env" file per machine and don't use ".env" file in your production server.

What is the right way to maintain a "version for the server" - with only config files changed, in Git?

I sometimes work with Codeigniter, and after I'm done developing on the local site, I need to migrate the files to the server. All the files in the /config/ folder need to be changed to match the Server settings. It's not right to make an entire commit for these changes, do I simply make Git ignore these files altogether, or is there a way to track these changes and apply them with Git at the right moment?
You could keep versioned:
two "value config files", with the right values for each environment
a template config file, with value placeholder in it (for instance, ##PORT_NUMBER##)
a script able to generate the actual config file depending on the current environment
a content filter driver which, on checkout, will trigger the script in order to generate the right config file.
Note: that supposes your template config file has a recognizable content (the filter doesn't have a name or path of the file). See "Git equivalent of subversion's $URL$ keyword expansion" for more on the limitation of git content filter driver).
It depends on Your needs. In my company we use other approach.
We've created several environments (where the asterix is internal project name):
devel - site runs on domain **.local.com*
test - site run on domain test.*.company.com
beta - beta.*.company.com
production - every other domain.
Based on the domain name we switch automatically configurations.
Basicly config file looks like:
<?php
return array(
'_env' => array(
'devel' => array(
// config for devel
),
'production' => array(
// config for production
)
)
);
?>
Some frameworks (AFAIR Zend) set the environment name in Virtual Host config (or .htaccess). You should look at: zend framework auto switch production staging test .. etc
Have You looked at CI documentation? There's a section about it.
Create two folders in the config folder. One is called development and the other is production. Now copy config.php, database.php etc to each of these folders. Now when you are on production server, CodeIgniter will first check the production folder for the files. If it is not there, then it uses the default file in the config folder. And if you are on development environment, CodeIgniter will first check the development folder.
If you want to keep any config file identical to the production and development environment, keep it in config folder.
If you want to set the environment then add the following code in .htaccess file:
#This code for Development Environment
SetEnv CI_ENV development
and
#This code for Production Environment
SetEnv CI_ENV production

Categories