Skip to content

Commit

Permalink
reverse proxy shared db
Browse files Browse the repository at this point in the history
  • Loading branch information
fabio-ivona committed Dec 15, 2023
1 parent 3a0bc55 commit a692a3d
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 117 deletions.
283 changes: 166 additions & 117 deletions app/Recipes/ReverseProxy/ReverseProxyRecipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,155 +4,204 @@
namespace App\Recipes\ReverseProxy;


use App\Containers\CertbotCloudflare;
use App\Containers\Container;
use App\Containers\Nginx;
use App\Contracts\SSLService;
use App\Exceptions\ContainerException;
use App\Exceptions\DuplicateNetworkException;
use App\Exceptions\DuplicateServiceException;
use App\Recipes\DockerComposeRecipe;
use App\Recipes\ReverseProxy\Commands\ProxyAdd;
use App\Recipes\ReverseProxy\Commands\ProxyDisable;
use App\Recipes\ReverseProxy\Commands\ProxyEnable;
use App\Recipes\ReverseProxy\Commands\ProxyReload;
use App\Recipes\ReverseProxy\Exceptions\ProxyTargetInvalidException;
use App\Recipes\ReverseProxy\Services\TargetsService;
use App\Services\SSL\Certbot;
use App\Services\SSL\SelfSigned;
use App\Traits\InteractsWithEnvContent;
use Illuminate\Console\Command;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Filesystem\FileNotFoundException;

class ReverseProxyRecipe extends DockerComposeRecipe{

const LABEL = 'ReverseProxy';

const PROXY_NETWORK = 'reverse_proxy_network';


protected function customize_init(Command $parent_command, string $env_content): string{
/** @var TargetsService $targets */
$targets = app()->make(TargetsService::class);
$targets->init_targets_file();

return $this->init_ssl_configuration($parent_command, $env_content);
use App\Containers\CertbotCloudflare;
use App\Containers\Container;
use App\Containers\MySql;
use App\Containers\Nginx;
use App\Contracts\SSLService;
use App\Exceptions\ContainerException;
use App\Exceptions\DuplicateNetworkException;
use App\Exceptions\DuplicateServiceException;
use App\Recipes\DockerComposeRecipe;
use App\Recipes\ReverseProxy\Commands\ProxyAdd;
use App\Recipes\ReverseProxy\Commands\ProxyDisable;
use App\Recipes\ReverseProxy\Commands\ProxyEnable;
use App\Recipes\ReverseProxy\Commands\ProxyReload;
use App\Recipes\ReverseProxy\Exceptions\ProxyTargetInvalidException;
use App\Recipes\ReverseProxy\Services\TargetsService;
use App\Services\SSL\Certbot;
use App\Services\SSL\SelfSigned;
use App\Traits\InteractsWithEnvContent;
use Illuminate\Console\Command;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Filesystem\FileNotFoundException;

class ReverseProxyRecipe extends DockerComposeRecipe
{

const LABEL = 'ReverseProxy';

const PROXY_NETWORK = 'reverse_proxy_network';
const DB_NETWORK = 'shared_db_network';


protected function customize_init(Command $parent_command, string $env_content): string
{
/** @var TargetsService $targets */
$targets = app()->make(TargetsService::class);
$targets->init_targets_file();

if ($parent_command->confirm('Would you like to a shared DB service?')) {
$this->set_env($env_content, 'ENABLE_MYSQL', 1);

$parent_command->question("MySql configuration");

$mysql_port = $parent_command->ask("Enter MySQL exposed port", 3306);
if ($mysql_port == 'x') {
$this->comment_env($env_content, 'MYSQL_PORT');
} else {
$this->set_env($env_content, "MYSQL_PORT", $mysql_port);
}
$this->set_env($env_content, 'MYSQL_DATABASE', $parent_command->ask("Database Name", "database"));
$this->set_env($env_content, 'MYSQL_USER', $parent_command->ask("Database User", "dbuser"));
$this->set_env($env_content, 'MYSQL_PASSWORD', $parent_command->ask("Database Password", "dbpassword"));
$this->set_env($env_content, 'MYSQL_ROOT_PASSWORD', $parent_command->ask("Database Root Password", "root"));
}

private function ssl_provider(): SSLService
{
return app()->make(env('SSL_PROVIDER'));
}
return $this->init_ssl_configuration($parent_command, $env_content);
}

private function init_ssl_configuration(Command $parent_command, string $env_content): string{
$parent_command->question('SSL Configuration');
private function ssl_provider(): SSLService
{
return app()->make(env('SSL_PROVIDER'));
}

$ssl_provider_class = $parent_command->choice('Select SSL Provider', [
SelfSigned::class => 'self-signed',
Certbot::class => 'certbot',
], Certbot::class);
private function init_ssl_configuration(Command $parent_command, string $env_content): string
{
$parent_command->question('SSL Configuration');

$this->set_env($env_content, 'SSL_PROVIDER', $ssl_provider_class);
$ssl_provider_class = $parent_command->choice('Select SSL Provider', [
SelfSigned::class => 'self-signed',
Certbot::class => 'certbot',
], Certbot::class);

/** @var SSLService $ssl_service */
$ssl_service = app()->make($ssl_provider_class);
return $ssl_service->init_recipe($parent_command, $env_content);
}
$this->set_env($env_content, 'SSL_PROVIDER', $ssl_provider_class);

/** @var SSLService $ssl_service */
$ssl_service = app()->make($ssl_provider_class);
return $ssl_service->init_recipe($parent_command, $env_content);
}


/**
* @inheritDoc
* @throws BindingResolutionException
* @throws FileNotFoundException
* @throws ProxyTargetInvalidException
*/
public function build(){
/**
* @inheritDoc
* @throws BindingResolutionException
* @throws FileNotFoundException
* @throws ProxyTargetInvalidException
*/
public function build()
{

$nginx = $this->build_nginx($this->ssl_provider()->reserved_ports());
$nginx = $this->build_nginx($this->ssl_provider()->reserved_ports());

$this->build_targets($nginx);
$this->build_targets($nginx);

$this->build_ssl_providers();
$this->build_ssl_providers();

}
$this->build_mysql();
}

private function build_nginx(array $reserved_ports): Nginx{
/** @var Nginx $nginx */
$nginx = $this->add_container(Nginx::class);
private function build_nginx(array $reserved_ports): Nginx
{
/** @var Nginx $nginx */
$nginx = $this->add_container(Nginx::class);

foreach ([80, 443, 6001] as $port){
if(!in_array($port, $reserved_ports)){
$nginx->map_port($port);
}
foreach ([80, 443, 6001] as $port) {
if (!in_array($port, $reserved_ports)) {
$nginx->map_port($port);
}
}

$nginx->unset_service_definition('working_dir');
$nginx->unset_php_service();
$nginx->unset_service_definition('working_dir');
$nginx->unset_php_service();

$nginx->enable_backend_not_found_page();
$nginx->enable_backend_not_found_page();

$nginx->set_volume(Container::HOST_CONFIG_VOLUME_PATH . 'certbot/letsencrypt', '/etc/letsencrypt');
$nginx->set_volume(Container::HOST_CONFIG_VOLUME_PATH.'certbot/letsencrypt', '/etc/letsencrypt');

$nginx->add_network(self::PROXY_NETWORK);
$nginx->add_network(self::PROXY_NETWORK);

return $nginx;
}
return $nginx;
}

/**
* @param Nginx $nginx
*
* @throws FileNotFoundException|ProxyTargetInvalidException
*/
private function build_targets(Nginx $nginx): void{
/**
* @param Nginx $nginx
*
* @throws FileNotFoundException|ProxyTargetInvalidException
*/
private function build_targets(Nginx $nginx): void
{

/** @var TargetsService $targets */
$targets = app()->make(TargetsService::class);

collect($targets->get_targets())
->each(function ($target) {
if (in_array($target->port, $this->ssl_provider()->reserved_ports())) {
throw new ProxyTargetInvalidException("Target in target.json can't use port [$target->port]: it is reserved from ssl provider");
}
});

/** @var TargetsService $targets */
$targets = app()->make(TargetsService::class);
$targets->make_proxies($nginx);
}

collect($targets->get_targets())
->each(function($target){
if(in_array($target->port, $this->ssl_provider()->reserved_ports())){
throw new ProxyTargetInvalidException("Target in target.json can't use port [$target->port]: it is reserved from ssl provider");
}
});
/**
* @throws BindingResolutionException
*/
private function build_ssl_providers(): void
{

$targets->make_proxies($nginx);
}
/** @var SSLService $ssl_provider */
$ssl_provider = app()->make(SSLService::class);
$ssl_provider->build_ssl_provider($this);

/**
* @throws BindingResolutionException
*/
private function build_ssl_providers(): void{
}

/** @var SSLService $ssl_provider */
$ssl_provider = app()->make(SSLService::class);
$ssl_provider->build_ssl_provider($this);

}
/**
* @throws ContainerException
* @throws DuplicateNetworkException
* @throws DuplicateServiceException
*/
public function setup(): void
{
parent::setup();
$this->docker_service->add_network(self::PROXY_NETWORK, self::PROXY_NETWORK, 'bridge');
}

/**
* @inheritDoc
*/
protected function recipe_commands(): array
{
return [
ProxyEnable::class,
ProxyDisable::class,
ProxyAdd::class,
ProxyReload::class,
];
}

private function build_mysql(): MySql
{
if(env('ENABLE_MYSQL'))

/**
* @throws ContainerException
* @throws DuplicateNetworkException
* @throws DuplicateServiceException
*/
public function setup(){
parent::setup();
$this->docker_service->add_network(self::PROXY_NETWORK, self::PROXY_NETWORK, 'bridge');
}
/** @var MySql $mysql */
$mysql = $this->add_container(MySql::class)->add_network($this->internal_network());

/**
* @inheritDoc
*/
protected function recipe_commands(): array{
return [
ProxyEnable::class,
ProxyDisable::class,
ProxyAdd::class,
ProxyReload::class,
];
$mysql->set_database(env('MYSQL_DATABASE', 'database'));
$mysql->set_user(env('MYSQL_USER', 'dbuser'));
$mysql->set_password(env('MYSQL_PASSWORD', 'dbpassword'));
$mysql->set_root_password(env('MYSQL_ROOT_PASSWORD', 'root'));

if (!empty(env('MYSQL_PORT'))) {
$mysql->map_port(env('MYSQL_PORT'), 3306);
}

$mysql->add_network(self::DB_NETWORK);

return $mysql;
}
}


15 changes: 15 additions & 0 deletions storage/app/env/ReverseProxy
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,18 @@ NGINX_PORT_SSL=443

#CERTBOT_CHALLENGE_MODE=dns-cloudflare
#CLOUDFLARE_TOKEN=


#######################
# MySql #
#######################

ENABLE_MYSQL=0

#MySql exposed ports
#MYSQL_PORT=3306

#MYSQL_DATABASE=database
#MYSQL_USER=dbuser
#MYSQL_PASSWORD=dbpassword
#MYSQL_ROOT_PASSWORD=root

0 comments on commit a692a3d

Please sign in to comment.