diff --git a/MANIFEST b/MANIFEST index a4fee32..ab9da25 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,9 +1,17 @@ Changes lib/Server/Toaster.pm +lib/Server/Toaster/Modules/Apache.pm +lib/Server/Toaster/Modules/Base.pm +lib/Server/Toaster/Defaults.pm Makefile.PL MANIFEST This list of files README t/00-load.t +t/01-load.t +t/02-load.t +t/03-load.t t/manifest.t t/pod-coverage.t t/pod.t +share/Apache/domain.tt +share/Apache/httpd.conf.tt diff --git a/Makefile.PL b/Makefile.PL index 5d8aade..0a9f786 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -23,8 +23,18 @@ my %WriteMakefileArgs = ( 'Template::Plugin::JSON' => '0.08', 'File::ShareDir' => '0', }, - dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, - clean => { FILES => 'Server-Toaster-*' }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Server-Toaster-*' }, + META_MERGE => { + "meta-spec" => { version => 2 }, + resources => { + repository => { + type => 'git', + url => 'git@github.com:VVelox/Server-Toaster.git', + web => 'https://github.com/VVelox/Server-Toaster', + }, + }, + }, ); # Compatibility with old versions of ExtUtils::MakeMaker diff --git a/lib/Server/Toaster.pm b/lib/Server/Toaster.pm index e3440fa..25261f9 100644 --- a/lib/Server/Toaster.pm +++ b/lib/Server/Toaster.pm @@ -3,8 +3,9 @@ package Server::Toaster; use 5.006; use strict; use warnings; -use Template; use File::ShareDir ':ALL'; +use Hash::Merge; +use Server::Toaster::Defaults; =head1 NAME @@ -78,7 +79,8 @@ sub new { my $self = { dir => $opts{dir}, output => $opts{output}, - templates => $opts{templates}, + templates => $opts{templates}, + defaults=>Server::Toaster::Defaults->get, share => dist_dir('Server-Toaster'), }; bless $self; @@ -92,7 +94,9 @@ This filles in the templates for the specified module. The required values are as below. - module - The module to process the templates for. + module - The module to process the templates for. This is relevant to + Sever::Toaster::Modules. So 'Sever::Toaster::Modules::Apache' + becomes 'Apache'; hostname - The hostname of the system being processed. @@ -103,7 +107,41 @@ This will die upon error. =cut sub fill_in { - my ( $blank, %opts ) = @_; + my ( $self, %opts ) = @_; + + # make sure we have a module specified + if (!defined( $opts{module} )) { + die( 'No module defined' ); + } + + # make sure we have a hostname + if (!defined( $opts{hostname} )) { + die( 'No hostname defined' ); + } + + # make sure we have a config to use + if (!defined( $opts{config} )) { + die( 'No config defined' ); + } + + # do a very basic check to make sure we have something that appears to atleast be sane + # for the name of the module + if ($opts{module}!~/^[A-Za-z0-9\_\:]+$/) { + die('"'.$opts{module}.'" does not appear to be a valid module name'); + } + + my $merger=Hash::Merge->new('LEFT_PRECEDENT'); + + my $config=$merger->merge( $opts{config}, $self->{defaults} ); + + my $to_eval='use Server::Toaster::Modules::'.$opts{module}.'; '. + 'my $st_module=Server::Toaster::Modules::'.$opts{module}.'->new(', + 'dir=>$self->{dir}, '. + 'output=>$self->{output}, '. + 'templates=>$self->{templates} );'. + '$st_module->fill_in(%opts);'; + + } @@ -115,7 +153,7 @@ As long as the specified module exists, this should never die. The returned value is a hash with the keys being the template names and the value being the full path to the file. -sq + One value is required and that is the name of the module, relevant to Sever::Toaster::Modules. So 'Sever::Toaster::Modules::Apache' becomes 'Apache'; diff --git a/lib/Server/Toaster/Defaults.pm b/lib/Server/Toaster/Defaults.pm index 5b5a850..f378dd5 100644 --- a/lib/Server/Toaster/Defaults.pm +++ b/lib/Server/Toaster/Defaults.pm @@ -1,4 +1,4 @@ -package Server::Toaster; +package Server::Toaster::Defaults; use 5.006; use strict; @@ -20,17 +20,24 @@ our $VERSION = '0.0.1'; use Server::Toaster::Defaults; use Data::Dumper; + + my %defaults=Server::Toaster::Defaults->get; + + print Dumper \%defaults; - print Dumper Server::Toaster::Defaults->get; =head1 METHODS =head2 get +Gets the defaults. + + my %defaults=Server::Toaster::Defaults->get; + =cut sub get { - my $self = { + my %defaults = ( ssl_ciphers => 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384', ssl_min_protocol => 'TLSv1.2', @@ -41,12 +48,13 @@ sub get { server_admin_name => 'Who Ever', ssl_cert_path => '/usr/local/etc/letsencrypt/live/%%%DOMAN%%%/', Apache => { - listen => [ '80', '443' ], + listen => [], http_port => '80', https_port => '443', server_root => '/usr/local', default_https_redirect => '0', enable_https => '0', + include_optional => 1, ssl_stapling => '1', ssl_stapling_cache => 'shmcb:logs/ssl_stapling(32768)', modules => { @@ -147,8 +155,8 @@ sub get { modules_d => 1, user => 'www', group => 'www', - doc_root => '/usr/local/www/apache24/data', - cgi=>0, + doc_root => '/usr/local/www/apache24/data', + cgi => 0, mpm_event => { StartServers => 3, MinSpareThreads => 75, @@ -174,10 +182,9 @@ sub get { } } - }; - bless $self; + ); - return $self; + return %defaults; } =head1 AUTHOR diff --git a/lib/Server/Toaster/Modules/Apache.pm b/lib/Server/Toaster/Modules/Apache.pm index f4b6d25..542011e 100644 --- a/lib/Server/Toaster/Modules/Apache.pm +++ b/lib/Server/Toaster/Modules/Apache.pm @@ -3,8 +3,7 @@ package Server::Toaster::Modules::Apache; use 5.006; use strict; use warnings; -use Template; -use File::ShareDir ':ALL'; +use base 'Server::Toaster::Modules::Base'; =head1 NAME @@ -32,68 +31,38 @@ Perhaps a little code snippet. =head1 METHODS -=head2 new - -This initiates the module. - - dir - The base dir to use. If not spoecified, - 'stoaster' is ued. - - output - The output dir to use. If not specified, - $dir.'/output' is used. - - templates - The template dir to use. If not specified, - $dir.'/templates' is used. - -$templates and $output will be created as needed, but $dir must -exist upon module init or it will die. - - -=cut - -sub new { - my ( $blank, %opts ) = @_; - - # set the default dir if non is specified - if ( !defined( $opts{dir} ) ) { - $opts{dir} = 'stoaster'; - } - - # die if the base dir is not a directory or does not exist - if ( !-d $opts{dir} ) { - die '"' . $opts{dir} . '" does not exist or is not a directory'; - } - - # set the default output dir if non is specified - if ( !defined( $opts{output} ) ) { - $opts{output} = $opts{dir} . '/output'; - } - - # set the default template dir if non is specified - if ( !defined( $opts{templates} ) ) { - $opts{templates} = $opts{dir} . '/templates'; - } - - # init the object - my $self = { - dir => $opts{dir}, - output => $opts{output}, - templates => $opts{templates}, - share => dist_dir('Server-Toaster'), - }; - bless $self; - - return $self; -} - =head2 fill_in +This filles in the templates. + +The required values are as below. + + hostname - The hostname of the system being processed. + + config - The config hash ref for the use with filling the templates. + +This will die upon error. + =cut sub fill_in { my ( $self, %opts ) = @_; - + # make sure we have a hostname + if (!defined( $opts{hostname} )) { + die( 'No hostname defined' ); + } + + # make sure we have a config to use + if (!defined( $opts{config} )) { + die( 'No config defined' ); + } + + my $vars={ + hostname=>$opts{hostname}, + d=>Server::Toaster::Defaults->get, + c=>%opts{config}, + } } @@ -117,7 +86,6 @@ sub get_files { 'Apache/doc_root.conf.tt'=>$dir.'/Apache/doc_root.conf.tt', ); - return %returned; } diff --git a/lib/Server/Toaster/Modules/Base.pm b/lib/Server/Toaster/Modules/Base.pm new file mode 100644 index 0000000..0637a06 --- /dev/null +++ b/lib/Server/Toaster/Modules/Base.pm @@ -0,0 +1,201 @@ +package Server::Toaster::Modules::Base; + +use 5.006; +use strict; +use warnings; +use Template; +use Server::Toaster::Defaults; +use File::ShareDir ':ALL'; + +=head1 NAME + +Server::Toaster::Modules::Apache - Apache helper for Server::Toaster + +=head1 VERSION + +Version 0.0.1 + +=cut + +our $VERSION = '0.0.1'; + +=head1 SYNOPSIS + +Quick summary of what the module does. + +Perhaps a little code snippet. + + use Server::Toaster::Modules::Apache; + + my $st = Server::Toaster->new(); + + + +=head1 METHODS + +=head2 new + +This initiates the module. + + dir - The base dir to use. If not spoecified, + 'stoaster' is used. + + output - The output dir to use. If not specified, + $dir.'/output' is used. + + templates - The template dir to use. If not specified, + $dir.'/templates' is used. + +$templates and $output will be created as needed, but $dir must +exist upon module init or it will die. + + +=cut + +sub new { + my ( $blank, %opts ) = @_; + + # set the default dir if non is specified + if ( !defined( $opts{dir} ) ) { + $opts{dir} = 'stoaster'; + } + + # die if the base dir is not a directory or does not exist + if ( !-d $opts{dir} ) { + die '"' . $opts{dir} . '" does not exist or is not a directory'; + } + + # set the default output dir if non is specified + if ( !defined( $opts{output} ) ) { + $opts{output} = $opts{dir} . '/output'; + } + + # set the default template dir if non is specified + if ( !defined( $opts{templates} ) ) { + $opts{templates} = $opts{dir} . '/templates'; + } + + # init the object + my $self = { + dir => $opts{dir}, + output => $opts{output}, + templates => $opts{templates}, + share => dist_dir('Server-Toaster'), + }; + bless $self; + + return $self; +} + +=head2 fill_in + +This filles in the templates. + +The required values are as below. + + hostname - The hostname of the system being processed. + + config - The config hash ref for the use with filling the templates. + +This will die upon error. + +=cut + +sub fill_in { + my ( $self, %opts ) = @_; + + # make sure we have a hostname + if (!defined( $opts{hostname} )) { + die( 'No hostname defined' ); + } + + # make sure we have a config to use + if (!defined( $opts{config} )) { + die( 'No config defined' ); + } + + my $vars={ + hostname=>$opts{hostname}, + d=>Server::Toaster::Defaults->get, + c=>%opts{config}, + } + +} + +=head2 get_files + +Fetches a list of templates a module uses. + +The returned value is a hash with the keys being the template names +and the value being the full path to the file. + +=cut + +sub get_files { + my ( $self ) = @_; + + my $dir=dist_dir('Server-Toaster'); + + my %returned=( + 'Apache/domain.tt'=>$dir.'/Apache/domain.tt', + 'Apache/httpd.conf.tt'=>$dir.'/Apache/httpd.conf.tt', + 'Apache/doc_root.conf.tt'=>$dir.'/Apache/doc_root.conf.tt', + ); + + return %returned; +} + +=head1 AUTHOR + +Zane C. Bowers-Hadley, C<< >> + +=head1 BUGS + +Please report any bugs or feature requests to C, or through +the web interface at L. I will be notified, and then you'll +automatically be notified of progress on your bug as I make changes. + + + + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Server::Toaster + + +You can also look for information at: + +=over 4 + +=item * RT: CPAN's request tracker (report bugs here) + +L + +=item * CPAN Ratings + +L + +=item * Search CPAN + +L + +=back + + +=head1 ACKNOWLEDGEMENTS + + +=head1 LICENSE AND COPYRIGHT + +This software is Copyright (c) 2021 by Zane C. Bowers-Hadley. + +This is free software, licensed under: + + The Artistic License 2.0 (GPL Compatible) + + +=cut + +1; # End of Server::Toaster diff --git a/share/Apache/httpd.conf.tt b/share/Apache/httpd.conf.tt index e69de29..d746946 100644 --- a/share/Apache/httpd.conf.tt +++ b/share/Apache/httpd.conf.tt @@ -0,0 +1,182 @@ +ServerRoot "[% c.Apache.server_root %]" + +Listen 80 +Listen 443 + +[% IF c.Apache.modules.mpm_prefork %] +LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so +[% END %] +[% IF c.Apache.modules.authn_file %] +LoadModule authn_file_module libexec/apache24/mod_authn_file.so +[% END %] +[% IF c.Apache.modules.authn_core %] +LoadModule authn_core_module libexec/apache24/mod_authn_core.so +[% END %] +[% IF c.Apache.modules.authz_core %] +LoadModule authz_host_module libexec/apache24/mod_authz_host.so +[% END %] +[% IF c.Apache.modules.authz_groupfile %] +LoadModule authz_groupfile_module libexec/apache24/mod_authz_groupfile.so +[% END %] +[% IF c.Apache.modules.authz_user %] +LoadModule authz_user_module libexec/apache24/mod_authz_user.so +[% END %] +[% IF c.Apache.modules.authz_core %] +LoadModule authz_core_module libexec/apache24/mod_authz_core.so +[% END %] +[% IF c.Apache.modules.access_compat %] +LoadModule access_compat_module libexec/apache24/mod_access_compat.so +[% END %] +[% IF c.Apache.modules.auth_basic %] +LoadModule auth_basic_module libexec/apache24/mod_auth_basic.so +[% END %] +[% IF c.Apache.modules.reqtimeout %] +LoadModule reqtimeout_module libexec/apache24/mod_reqtimeout.so +[% END %] +[% IF c.Apache.modules.filter %] +LoadModule filter_module libexec/apache24/mod_filter.so +[% END %] +[% IF c.Apache.modules.deflate %] +LoadModule deflate_module libexec/apache24/mod_deflate.so +[% END %] +[% IF c.Apache.modules.mime %] +LoadModule mime_module libexec/apache24/mod_mime.so +[% END %] +[% IF c.Apache.modules.log_config %] +LoadModule log_config_module libexec/apache24/mod_log_config.so +[% END %] +[% IF c.Apache.modules.env %] +LoadModule env_module libexec/apache24/mod_env.so +[% END %] +[% IF c.Apache.modules.headers %] +LoadModule headers_module libexec/apache24/mod_headers.so +[% END %] +[% IF c.Apache.modules.setenvif %] +LoadModule setenvif_module libexec/apache24/mod_setenvif.so +[% END %] +[% IF c.Apache.modules.version %] +LoadModule version_module libexec/apache24/mod_version.so +[% END %] +[% IF c.Apache.modules.remoteip %] +LoadModule remoteip_module libexec/apache24/mod_remoteip.so +[% END %] +[% IF c.Apache.modules.proxy %] +LoadModule proxy_module libexec/apache24/mod_proxy.so +[% END %] +[% IF c.Apache.modules.proxy_http %] +LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so +[% END %] +[% IF c.Apache.modules.fcgi %] +LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so +[% END %] +[% IF c.Apache.modules.scgi %] +LoadModule proxy_scgi_module libexec/apache24/mod_proxy_scgi.so +[% END %] +[% IF c.Apache.modules.wstunnel %] +LoadModule proxy_wstunnel_module libexec/apache24/mod_proxy_wstunnel.so +[% END %] +[% IF c.Apache.modules.ssl %] +LoadModule ssl_module libexec/apache24/mod_ssl.so +[% END %] +[% IF c.Apache.modules.unixd %] +LoadModule unixd_module libexec/apache24/mod_unixd.so +[% END %] +[% IF c.Apache.modules.status %] +LoadModule status_module libexec/apache24/mod_status.so +[% END %] +[% IF c.Apache.modules.autoindex %] +LoadModule autoindex_module libexec/apache24/mod_autoindex.so +[% END %] +[% IF c.Apache.modules.suexec %] +LoadModule suexec_module libexec/apache24/mod_suexec.so +[% END %] +[% IF c.Apache.modules.vhost_alias %] +LoadModule vhost_alias_module libexec/apache24/mod_vhost_alias.so +[% END %] +[% IF c.Apache.modules.dir %] +LoadModule dir_module libexec/apache24/mod_dir.so +[% END %] +[% IF c.Apache.modules.actions %] +LoadModule actions_module libexec/apache24/mod_actions.so +[% END %] +[% IF c.Apache.modules.alias %] +LoadModule alias_module libexec/apache24/mod_alias.so +[% END %] +[% IF c.Apache.modules.rewrite %] +LoadModule rewrite_module libexec/apache24/mod_rewrite.so +[% END %] +[% IF c.Apache.modules.fcgid %] +LoadModule fcgid_module libexec/apache24/mod_fcgid.so +[% END %] +[% IF c.Apache.modules.fastcgi %] +LoadModule fastcgi_module libexec/apache24/mod_fastcgi.so +[% END %] +[% IF c.Apache.modules.wsgi %] +LoadModule wsgi_module libexec/apache24/mod_wsgi.so +[% END %] +[% IF c.Apache.modules.auth_openidc %] +LoadModule auth_openidc_module libexec/apache24/mod_auth_openidc.so +[% END %] + +[% IF c.Apache.modules.include_optional %] +IncludeOptional etc/apache24/modules.d/[0-9][0-9][0-9]_*.conf +[% END %] + + +User [% c.Apache.user %] +Group [% c.Apache.group %] + + + +ServerAdmin you@example.com + + + AllowOverride none + Require all denied + + +DocumentRoot "[% c.Apache.doc_root %]" + + Options Indexes FollowSymLinks + + AllowOverride None + + Require all granted + + + + DirectoryIndex index.html + + + + Require all denied + + +ErrorLog "|/usr/local/sbin/rotatelogs -n 7 /var/log/httpd-error.log 86400" + +LogLevel warn + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b" commonvhost +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedvhost + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + CustomLog "|/usr/local/sbin/rotatelogs -n 7 /var/log/httpd-access.log 10G" combinedvhost + HostnameLookups Off + + + + + + + TypesConfig etc/apache24/mime.types + + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + diff --git a/t/01-load.t b/t/01-load.t new file mode 100644 index 0000000..e688331 --- /dev/null +++ b/t/01-load.t @@ -0,0 +1,13 @@ +#!perl +use 5.006; +use strict; +use warnings; +use Test::More; + +plan tests => 1; + +BEGIN { + use_ok( 'Server::Toaster::Defaults' ) || print "Bail out!\n"; +} + +diag( "Testing Server::Toaster::Defaults $Server::Toaster::Defaults::VERSION, Perl $], $^X" ); diff --git a/t/02-load.t b/t/02-load.t new file mode 100644 index 0000000..2965f2f --- /dev/null +++ b/t/02-load.t @@ -0,0 +1,13 @@ +#!perl +use 5.006; +use strict; +use warnings; +use Test::More; + +plan tests => 1; + +BEGIN { + use_ok( 'Server::Toaster::Modules::Base' ) || print "Bail out!\n"; +} + +diag( "Testing Server::Toaster::Modules::Base $Server::Toaster::Modules::Base::VERSION, Perl $], $^X" ); diff --git a/t/03-load.t b/t/03-load.t new file mode 100644 index 0000000..5a45e12 --- /dev/null +++ b/t/03-load.t @@ -0,0 +1,13 @@ +#!perl +use 5.006; +use strict; +use warnings; +use Test::More; + +plan tests => 1; + +BEGIN { + use_ok( 'Server::Toaster::Modules::Apache' ) || print "Bail out!\n"; +} + +diag( "Testing Server::Toaster::Modules::Apache $Server::Toaster::Modules::Apache::VERSION, Perl $], $^X" );