123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Config::General;
- use Data::Dumper;
- use Text::Xslate qw(mark_raw);
- use File::Slurp;
- use File::Copy;
- open STDERR, '>', "/dev/null";
- my $LCWM = '/etc/nginx/lcwm2';
- my $A2CFG = '/etc/httpd/conf/httpd.conf' ;
- my $NGCFG = '/etc/nginx/nginx.conf' ;
- my $NGCFGen = "$NGCFG.gen" ;
- my $NGCFGbak = "$NGCFG." . time() ;
- my $A2PORT = 81 ;
- my $A2PORTS = 8443 ;
- my $NGPORT = 80 ;
- my $NGPORTS = 443 ;
- my $NGCFGBASE = "$LCWM/nginx.base" ;
- my $NGCFGVHOSTSTAT = "$LCWM/vhost_static.conf" ;
- my $NGCFG_CUSTOM_DIR = "$LCWM/custom";
- my $A2CLEAN = "$LCWM/ap2_clean.conf" ;
- my $DEFLISTEN = " default sndbuf=98304 backlog=2048 deferred" ;
- my $template_def_ips = qq{
- # aka null.tld + $DEFLISTEN
- server {
- : for \$ipv4 -> \$ip {
- listen <: \$ip :>:$NGPORT $DEFLISTEN;
- : }
- : for \$ipv6 -> \$ip {
- listen <: \$ip :>:$NGPORT $DEFLISTEN;
- : }
- access_log off;
- error_log /dev/null;
- server_name "";
- return 444;
- }
- };
- my $template_ng_vhost = q{
- #---vhost for domain <: $server_name :> on IP <: $listen :> <: $ssl :> ----
- server {
- : for $ips.ipv4 -> $ip {
- listen <: $ip :>:<: $ngport :> <: $ssl :>;
- : }
- : for $ips.ipv6 -> $ip {
- listen <: $ip :>:<: $ngport :> <: $ssl :>;
- : }
- server_name <: $server_name :> <: $alias :> ;
- root <: $root :> ;
- access_log off; # /var/log/nginx/<: $server_name :>.access.log main buffer=32k;
- error_log /var/log/nginx/<: $server_name :>.error.log warn;
- : if $include_slash == "" {
- location @apache {
- proxy_pass http://<: $main_ip :>:<: $a2port :>;
- proxy_redirect http://<: $server_name :>:<: $a2port :> http://<: $server_name :>;
- proxy_redirect http://www.<: $server_name :>:<: $a2port :> http://www.<: $server_name :>;
- proxy_redirect http://webmail.<: $server_name :>:<: $a2port :> http://webmail.<: $server_name :>;
- proxy_redirect http://admin.<: $server_name :>:<: $a2port :> http://admin.<: $server_name :>;
- }
- location / {
- try_files maintenance.html @apache;
- }
- : } else {
- <: $include_slash :>
- : }
- <: $include_static :>
- : if $ssl != "" {
- ssl_certificate <: $ssl_certificate :> ;
- ssl_certificate_key <: $ssl_certificate_key :> ;
- ssl_session_timeout 1d;
- ssl_session_cache shared:SSL:50m;
- ssl_session_tickets off;
- ssl_dhparam /etc/ssl/certs/dhparam.pem;
- ssl_protocols TLSv1.2;
- ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
- ssl_prefer_server_ciphers on;
- #ssl_stapling on;
- #ssl_stapling_verify on;
- resolver 8.8.8.8;
- : }
- }
- };
- sub update_pem {
- # Bash analog:
- # cat $SSLSERT > $SSLSERT".pem"
- # cat $SSLCA >> $SSLSERT".pem"
- #
- my ($SSLSERT, $SSLCA) = @_ ;
- my $OUT = $SSLSERT . ".pem";
- write_file( $OUT, {append => 0 }, read_file($SSLSERT) ) ;
- write_file( $OUT, {append => 1 }, read_file($SSLCA) ) if ( $SSLCA );
- return $OUT;
- }
- sub uniq {
- # remove duplicates from array
- #
- my %seen;
- return grep { !$seen{$_}++ } @_;
- }
- sub get_ips {
- # get array of ips from VirtualHost string, like this "IP1:http IP2:http [ipv6_1]:http [ipv6_2]:http"
- #
- my ($text) = @_ ;
- my %hash;
- my @ipv6 = uniq ( $text =~ m/\[.+?\]/sg ) ;
- my @ipv6_wo_local = grep ! /\[fe80/, @ipv6 ;
- @ipv6_wo_local = grep ! /\[2001/, @ipv6_wo_local ;
- my @ipv4 = uniq ( $text =~ m/[0-9.]{7,}/sg ) ;
- $hash{ipv6} = \@ipv6_wo_local ;
- $hash{ipv4} = \@ipv4 ;
- return \%hash ;
- }
- sub cook_ng_vhost {
- # convert [httpd.conf->Config::General]=>@vh_array->{$vhost} to %ng_hash=>[Text::Xslate->nginx.conf]
- #
- my ($vh, $ip_port) = @_ ;
- my $port = $vh->{SSLEngine} ? $NGPORTS : $NGPORT ;
- my %hash;
- my $server_name = $vh->{ServerName};
- my @statics = glob "/home/*/configs/$server_name.static /etc/nginx/*/custom/$server_name.static";
- my @slashes = glob "/home/*/configs/$server_name.slash /etc/nginx/*/custom/$server_name.slash";
- my $include_static = "/fake_path";
- my $include_slash = "/fake_path";
- $include_static = $statics[0] if $statics[0] ;
- $include_slash = $slashes[0] if $slashes[0] ;
- #print $server_name . " " . $include_static . " " . $include_slash . "\n";
- $hash{'alias'} = ref $vh->{ServerAlias} eq 'ARRAY' ? join(" ", @{$vh->{ServerAlias}}) : $vh->{ServerAlias} ;
- $hash{'root'} = $vh->{DocumentRoot} ;
- $hash{'server_name'} = $vh->{ServerName} ;
- $hash{'main_ip'} = get_ips($ip_port)->{ipv4}[0] ;
- $hash{'a2port'} = $A2PORT ;
- $hash{'ips'} = get_ips($ip_port) ;
- $hash{'ngport'} = $vh->{SSLEngine} ? $NGPORTS : $NGPORT ;
- $hash{'ssl'} = $vh->{SSLEngine} ? "ssl" : "";
- $hash{'ssl_certificate'} = $vh->{SSLEngine} ? update_pem( $vh->{SSLCertificateFile}, $vh->{SSLCACertificateFile} ) : "" ;
- $hash{'ssl_certificate_key'} = $vh->{SSLCertificateKeyFile} ;
- $hash{'include_static'} = (-f $include_static ) ? read_file( $include_static ) : "include $NGCFGVHOSTSTAT;" ;
- $hash{'include_slash'} = (-f $include_slash ) ? read_file( $include_slash ) : "" ;
- $hash{'include_static'} = mark_raw( $hash{'include_static'} ) ;
- $hash{'include_slash'} = mark_raw( $hash{'include_slash'} ) ;
- return \%hash;
- }
- sub cook_ng_array {
- open(my $a2cfg, '<:encoding(utf8)', $A2CFG ) or die "unable to open $A2CFG: $!\n";
- open(my $a2clean, "+>", $A2CLEAN) or die "$0: can't create temporary file: $!\n";
- while (<$a2cfg>) { print $a2clean "$_" if ( /^\<VirtualHost/ .. /\<\/VirtualHost\>/ ) } ;
- close $a2cfg;
- close $a2clean;
- my %conf = Config::General->new($A2CLEAN)->getall();
- unlink $A2CLEAN;
- my @ng_array = ();
- for my $ip_port (keys %{$conf{VirtualHost}}) {
- if ( ref $conf{VirtualHost}{$ip_port} eq 'ARRAY' ) {
- for my $vh ( @{$conf{VirtualHost}{$ip_port}} ) {
- if (exists $vh->{ServerName} and exists $vh->{ServerAlias}) {
- push @ng_array, cook_ng_vhost($vh, $ip_port);
- }
- }
- } else {
- my $vh = $conf{VirtualHost}{$ip_port} ;
- if (exists $vh->{ServerName} and exists $vh->{ServerAlias}) {
- push @ng_array, cook_ng_vhost( $vh, $ip_port);
- }
- }
- }
- return \@ng_array;
- }
- sub render_ng {
- my $tx = Text::Xslate->new();
- write_file($NGCFGen, {append => 0 }, read_file( $NGCFGBASE ) );
- #print Dumper @ng_array;
- ## TO DO, rm durty code
- my $get_string_with_all_ips = `grep VirtualHost $A2CFG`;
- write_file( $NGCFGen, {append => 1 }, $tx->render_string( $template_def_ips, get_ips ( $get_string_with_all_ips ) ) );
- ## /TO DO
- foreach my $vhost (values cook_ng_array){
- write_file( $NGCFGen, {append => 1 }, $tx->render_string( $template_ng_vhost, $vhost ) );
- }
- write_file( $NGCFGen, {append => 1 }, "\n\#close section http {\n}" ) ;
- print "Config done ... " ;
- }
- sub reconf_ng {
- my @args = ("/usr/sbin/nginx", "-t", "-c", "$NGCFGen" );
- # Debug
- copy($NGCFGen, '/etc/nginx/test.conf');
- # -----
- if ( system(@args) == 0 ) {
- print "syntax is ok ... ";
- } else {
- print "syntax check failed ...\n";
- die "system @args failed: $?";
- }
- move($NGCFG, $NGCFGbak);
- copy($NGCFGen, $NGCFG);
- print "backup done ... ";
- #@args = ("/usr/sbin/nginx", "-s", "reload" );
- @args = ("service", "nginx", "restart" );
- if ( system(@args) == 0 or system(@args) == 256) {
- print "nginx reloaded. ALL OK\n";
- } else {
- print system(@args);
- copy($NGCFGbak, $NGCFG);
- print "nginx reload failed, revert config done ...\n";
- die "system @args failed: $?";
- }
- }
- render_ng ;
- reconf_ng ;
|