reconf_ng 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Config::General;
  5. use Data::Dumper;
  6. use Text::Xslate qw(mark_raw);
  7. use File::Slurp;
  8. use File::Copy;
  9. open STDERR, '>', "/dev/null";
  10. my $LCWM = '/etc/nginx/lcwm2';
  11. my $A2CFG = '/etc/httpd/conf/httpd.conf' ;
  12. my $NGCFG = '/etc/nginx/nginx.conf' ;
  13. my $NGCFGen = "$NGCFG.gen" ;
  14. my $NGCFGbak = "$NGCFG." . time() ;
  15. my $A2PORT = 81 ;
  16. my $A2PORTS = 8443 ;
  17. my $NGPORT = 80 ;
  18. my $NGPORTS = 443 ;
  19. my $NGCFGBASE = "$LCWM/nginx.base" ;
  20. my $NGCFGVHOSTSTAT = "$LCWM/vhost_static.conf" ;
  21. my $NGCFG_CUSTOM_DIR = "$LCWM/custom";
  22. my $A2CLEAN = "$LCWM/ap2_clean.conf" ;
  23. my $DEFLISTEN = " default sndbuf=98304 backlog=2048 deferred" ;
  24. my $template_def_ips = qq{
  25. # aka null.tld + $DEFLISTEN
  26. server {
  27. : for \$ipv4 -> \$ip {
  28. listen <: \$ip :>:$NGPORT $DEFLISTEN;
  29. : }
  30. : for \$ipv6 -> \$ip {
  31. listen <: \$ip :>:$NGPORT $DEFLISTEN;
  32. : }
  33. access_log off;
  34. error_log /dev/null;
  35. server_name "";
  36. return 444;
  37. }
  38. };
  39. my $template_ng_vhost = q{
  40. #---vhost for domain <: $server_name :> on IP <: $listen :> <: $ssl :> ----
  41. server {
  42. : for $ips.ipv4 -> $ip {
  43. listen <: $ip :>:<: $ngport :> <: $ssl :>;
  44. : }
  45. : for $ips.ipv6 -> $ip {
  46. listen <: $ip :>:<: $ngport :> <: $ssl :>;
  47. : }
  48. server_name <: $server_name :> <: $alias :> ;
  49. root <: $root :> ;
  50. access_log off; # /var/log/nginx/<: $server_name :>.access.log main buffer=32k;
  51. error_log /var/log/nginx/<: $server_name :>.error.log warn;
  52. : if $include_slash == "" {
  53. location @apache {
  54. proxy_pass http://<: $main_ip :>:<: $a2port :>;
  55. proxy_redirect http://<: $server_name :>:<: $a2port :> http://<: $server_name :>;
  56. proxy_redirect http://www.<: $server_name :>:<: $a2port :> http://www.<: $server_name :>;
  57. proxy_redirect http://webmail.<: $server_name :>:<: $a2port :> http://webmail.<: $server_name :>;
  58. proxy_redirect http://admin.<: $server_name :>:<: $a2port :> http://admin.<: $server_name :>;
  59. }
  60. location / {
  61. try_files maintenance.html @apache;
  62. }
  63. : } else {
  64. <: $include_slash :>
  65. : }
  66. <: $include_static :>
  67. : if $ssl != "" {
  68. ssl_certificate <: $ssl_certificate :> ;
  69. ssl_certificate_key <: $ssl_certificate_key :> ;
  70. ssl_session_timeout 1d;
  71. ssl_session_cache shared:SSL:50m;
  72. ssl_session_tickets off;
  73. ssl_dhparam /etc/ssl/certs/dhparam.pem;
  74. ssl_protocols TLSv1.2;
  75. 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';
  76. ssl_prefer_server_ciphers on;
  77. #ssl_stapling on;
  78. #ssl_stapling_verify on;
  79. resolver 8.8.8.8;
  80. : }
  81. }
  82. };
  83. sub update_pem {
  84. # Bash analog:
  85. # cat $SSLSERT > $SSLSERT".pem"
  86. # cat $SSLCA >> $SSLSERT".pem"
  87. #
  88. my ($SSLSERT, $SSLCA) = @_ ;
  89. my $OUT = $SSLSERT . ".pem";
  90. write_file( $OUT, {append => 0 }, read_file($SSLSERT) ) ;
  91. write_file( $OUT, {append => 1 }, read_file($SSLCA) ) if ( $SSLCA );
  92. return $OUT;
  93. }
  94. sub uniq {
  95. # remove duplicates from array
  96. #
  97. my %seen;
  98. return grep { !$seen{$_}++ } @_;
  99. }
  100. sub get_ips {
  101. # get array of ips from VirtualHost string, like this "IP1:http IP2:http [ipv6_1]:http [ipv6_2]:http"
  102. #
  103. my ($text) = @_ ;
  104. my %hash;
  105. my @ipv6 = uniq ( $text =~ m/\[.+?\]/sg ) ;
  106. my @ipv6_wo_local = grep ! /\[fe80/, @ipv6 ;
  107. @ipv6_wo_local = grep ! /\[2001/, @ipv6_wo_local ;
  108. my @ipv4 = uniq ( $text =~ m/[0-9.]{7,}/sg ) ;
  109. $hash{ipv6} = \@ipv6_wo_local ;
  110. $hash{ipv4} = \@ipv4 ;
  111. return \%hash ;
  112. }
  113. sub cook_ng_vhost {
  114. # convert [httpd.conf->Config::General]=>@vh_array->{$vhost} to %ng_hash=>[Text::Xslate->nginx.conf]
  115. #
  116. my ($vh, $ip_port) = @_ ;
  117. my $port = $vh->{SSLEngine} ? $NGPORTS : $NGPORT ;
  118. my %hash;
  119. my $server_name = $vh->{ServerName};
  120. my @statics = glob "/home/*/configs/$server_name.static /etc/nginx/*/custom/$server_name.static";
  121. my @slashes = glob "/home/*/configs/$server_name.slash /etc/nginx/*/custom/$server_name.slash";
  122. my $include_static = "/fake_path";
  123. my $include_slash = "/fake_path";
  124. $include_static = $statics[0] if $statics[0] ;
  125. $include_slash = $slashes[0] if $slashes[0] ;
  126. #print $server_name . " " . $include_static . " " . $include_slash . "\n";
  127. $hash{'alias'} = ref $vh->{ServerAlias} eq 'ARRAY' ? join(" ", @{$vh->{ServerAlias}}) : $vh->{ServerAlias} ;
  128. $hash{'root'} = $vh->{DocumentRoot} ;
  129. $hash{'server_name'} = $vh->{ServerName} ;
  130. $hash{'main_ip'} = get_ips($ip_port)->{ipv4}[0] ;
  131. $hash{'a2port'} = $A2PORT ;
  132. $hash{'ips'} = get_ips($ip_port) ;
  133. $hash{'ngport'} = $vh->{SSLEngine} ? $NGPORTS : $NGPORT ;
  134. $hash{'ssl'} = $vh->{SSLEngine} ? "ssl" : "";
  135. $hash{'ssl_certificate'} = $vh->{SSLEngine} ? update_pem( $vh->{SSLCertificateFile}, $vh->{SSLCACertificateFile} ) : "" ;
  136. $hash{'ssl_certificate_key'} = $vh->{SSLCertificateKeyFile} ;
  137. $hash{'include_static'} = (-f $include_static ) ? read_file( $include_static ) : "include $NGCFGVHOSTSTAT;" ;
  138. $hash{'include_slash'} = (-f $include_slash ) ? read_file( $include_slash ) : "" ;
  139. $hash{'include_static'} = mark_raw( $hash{'include_static'} ) ;
  140. $hash{'include_slash'} = mark_raw( $hash{'include_slash'} ) ;
  141. return \%hash;
  142. }
  143. sub cook_ng_array {
  144. open(my $a2cfg, '<:encoding(utf8)', $A2CFG ) or die "unable to open $A2CFG: $!\n";
  145. open(my $a2clean, "+>", $A2CLEAN) or die "$0: can't create temporary file: $!\n";
  146. while (<$a2cfg>) { print $a2clean "$_" if ( /^\<VirtualHost/ .. /\<\/VirtualHost\>/ ) } ;
  147. close $a2cfg;
  148. close $a2clean;
  149. my %conf = Config::General->new($A2CLEAN)->getall();
  150. unlink $A2CLEAN;
  151. my @ng_array = ();
  152. for my $ip_port (keys %{$conf{VirtualHost}}) {
  153. if ( ref $conf{VirtualHost}{$ip_port} eq 'ARRAY' ) {
  154. for my $vh ( @{$conf{VirtualHost}{$ip_port}} ) {
  155. if (exists $vh->{ServerName} and exists $vh->{ServerAlias}) {
  156. push @ng_array, cook_ng_vhost($vh, $ip_port);
  157. }
  158. }
  159. } else {
  160. my $vh = $conf{VirtualHost}{$ip_port} ;
  161. if (exists $vh->{ServerName} and exists $vh->{ServerAlias}) {
  162. push @ng_array, cook_ng_vhost( $vh, $ip_port);
  163. }
  164. }
  165. }
  166. return \@ng_array;
  167. }
  168. sub render_ng {
  169. my $tx = Text::Xslate->new();
  170. write_file($NGCFGen, {append => 0 }, read_file( $NGCFGBASE ) );
  171. #print Dumper @ng_array;
  172. ## TO DO, rm durty code
  173. my $get_string_with_all_ips = `grep VirtualHost $A2CFG`;
  174. write_file( $NGCFGen, {append => 1 }, $tx->render_string( $template_def_ips, get_ips ( $get_string_with_all_ips ) ) );
  175. ## /TO DO
  176. foreach my $vhost (values cook_ng_array){
  177. write_file( $NGCFGen, {append => 1 }, $tx->render_string( $template_ng_vhost, $vhost ) );
  178. }
  179. write_file( $NGCFGen, {append => 1 }, "\n\#close section http {\n}" ) ;
  180. print "Config done ... " ;
  181. }
  182. sub reconf_ng {
  183. my @args = ("/usr/sbin/nginx", "-t", "-c", "$NGCFGen" );
  184. # Debug
  185. copy($NGCFGen, '/etc/nginx/test.conf');
  186. # -----
  187. if ( system(@args) == 0 ) {
  188. print "syntax is ok ... ";
  189. } else {
  190. print "syntax check failed ...\n";
  191. die "system @args failed: $?";
  192. }
  193. move($NGCFG, $NGCFGbak);
  194. copy($NGCFGen, $NGCFG);
  195. print "backup done ... ";
  196. #@args = ("/usr/sbin/nginx", "-s", "reload" );
  197. @args = ("service", "nginx", "restart" );
  198. if ( system(@args) == 0 or system(@args) == 256) {
  199. print "nginx reloaded. ALL OK\n";
  200. } else {
  201. print system(@args);
  202. copy($NGCFGbak, $NGCFG);
  203. print "nginx reload failed, revert config done ...\n";
  204. die "system @args failed: $?";
  205. }
  206. }
  207. render_ng ;
  208. reconf_ng ;