Symfony - Terminal Command to generate a new APP_SECRET

Viewed 5685

I writing a public Symfony app. So I need to expose it on Packagist. How can I run a post-install-cmd to automatically set a new random APP_SECRET?

This would be nice to know and I think it's important. I did not found anything about that in the internet.

2 Answers

You can use the symfony/console,

Create for example:

php bin/console make:command regenerate-app-secret

in src/Command/RegenerateAppSecretCommand.php

<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class RegenerateAppSecretCommand extends Command
{
    protected static $defaultName = 'regenerate-app-secret';

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        $a = '0123456789abcdef';
        $secret = '';
        for ($i = 0; $i < 32; $i++) {
            $secret .= $a[rand(0, 15)];
        }

        $r = shell_exec('sed -i -E "s/^APP_SECRET=.{32}$/APP_SECRET=' . $secret . '/" .env');

        $io->success('New APP_SECRET was generated: ' . $secret);

        return 0;
    }
}

Run:

php bin/console regenerate-app-secret

I took this idea, and updated it to symfony5. One thing that didn't work for me in the original, was the dependency of shell_exec('sed..') which isn't available in windows or as in my case, in the official php docker container environment I'm using.

I also grouped it under the existing secret commands group.

Here's my take on it for anyone else who wants to grab it.

<?php
namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use sixlive\DotenvEditor\DotenvEditor;

#[AsCommand(
    name: 'secret:regenerate-app-secret',
    description: 'Regenerate a random value and update APP_SECRET',
)]
class RegenerateAppSecretCommand extends Command
{
    protected function configure(): void
    {
        $this->addArgument('envfile', InputArgument::REQUIRED, 'env File {.env, .env.local}');   
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $envname = $input->getArgument('envfile');

        if ($envname && ($envname == '.env' || $envname == '.env.local')) {
            $io->note(sprintf('You chose to update: %s', $envname));
            $secret = bin2hex(random_bytes(16));
            $filepath = realpath(dirname(__file__).'/../..') . '/' . $envname;
            $io->note(sprintf('Editing file: %s', $filepath));

            $editor = new DotenvEditor();
            $editor->load($filepath);
            $editor->set('APP_SECRET', $secret);
            $editor->save();
            $io->success('New APP_SECRET was generated: ' . $secret);
            return Command::SUCCESS;
        }
        $io->error("You did not provide a valid environment file to change");
        return Command::INVALID;       
    }
}
Related