Archives pour la catégorie ‘Nginx’

Nginx : création d’un fichier htpasswd avec openssl

boris@debian:~$ printf "USER:$(openssl passwd -crypt PASSWORD)\n" > vhost.htpasswd

Nginx : forcer le retry en configuration single upstream

upstream gitlab_ci {
  server unix:/tmp/sockets/gitlab-ci.socket fail_timeout=0;
}

Nginx : modifier le contenu HTML à la volée

Le module ngx_http_sub_module de Nginx permet la modification du contenu des réponses envoyées au client.

L’idée ici est de changer le titre des pages des sites hébergés sur un serveur de développement :

root@dev ~ # cat /etc/nginx/conf.d/environment.conf
sub_filter  </title> ' [DEV]</title>';
sub_filter_once on;

Nginx : limitation bruteforce

limit_conn_zone $binary_remote_addr zone=floodip:100m;
limit_conn floodip 10;

limit_req_zone $binary_remote_addr zone=flood:100m rate=5r/s;
limit_req zone=flood burst=10;

Nginx : support des Etags

Depuis sa version 1.3.3, Nginx intégre enfin le support des Etags. Ca tombe bien la version 1.4.1 est disponible dans les backports Wheezy et les packages Dotdeb Squeeze/Wheezy. Il n’est donc plus nécessaire d’utiliser un module dédié comme celui-ci.

Mise en place

Il est nécessaire d’ajouter l’option d’activation dans la directive http, server ou location. Ainsi, pour une application globale :

http {
   [...]

   etag on;
}

Test

bhuisgen@muse:~$ wget --no-check-certificate --spider --server-response https://localhost/backuppc/image/logo.gif
Spider mode enabled. Check if remote file exists.
--2013-07-18 12:35:59--  https://localhost/backuppc/image/logo.gif
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:443... connected.
WARNING: The certificate of ‘localhost’ is not trusted.
WARNING: The certificate of ‘localhost’ hasn't got a known issuer.
HTTP request sent, awaiting response...
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 18 Jul 2013 10:36:00 GMT
Content-Type: image/gif
Content-Length: 1394
Last-Modified: Fri, 07 Jun 2013 10:44:12 GMT
Connection: keep-alive
ETag: "51b1b97c-572"
Accept-Ranges: bytes
Length: 1394 (1.4K) [image/gif]
Remote file exists.

Nginx : exécution FastCGI Perl

Je vous joins ici la dernière version des scripts que j’utilise pour permettre l’exécution Perl en FastCGI avec Nginx (pour SmokePing, BackupPC, etc …)

Le script du démon Perl fcgi-perl.pl est à adapter à votre environnement système (utilisateur d’exécution, chemin de la socket UNIX). Le script de démarrage est à présent intégrable avec Heartbeat/Corosync …

Dépendances logicielles

root@muse:~# aptitude install libfcgi-perl libfile-pid-perl

Script FastCGI Perl

root@muse:~# cat /etc/nginx/fcgi-perl.pl
#!/usr/bin/perl
#
# FastCGI perl daemon
#
# Boris HUISGEN <bhuisgen@hbis.fr>
#

my ($pid_file) = "/var/run/fcgi-perl.pid";       # PID filename
my ($socket_file) = "/var/run/fcgi-perl.sock";   # UNIX socket filename
my ($socket_backlog) = 10;                       # socket backlog
my ($socket_uid) = 33;                           # socket UID
my ($socket_gid) = 33;                           # socket GID
my ($socket_perms) = 0600;                       # socket permissions

#
# script
#

use File::Pid;
use FCGI;
use Socket;
use POSIX qw(setsid);

require 'syscall.ph';

my ($pid_fd);

&daemonize;

*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; };
eval q{exit};
if ($@) {
   exit unless $@ =~ /^fakeexit/;
};

&main;

sub cleanup() {
   $pid_fd->remove if defined $pid_fd;
   unlink($socket_file);
}

sub daemonize() {
   chdir '/' or die "Failed to chdir to /: $!";
   defined(my $pid = fork) or die "Failed to fork: $!";
   exit if $pid;
   setsid or die "Failed to start a new session: $!";
   umask 0022;

   $pid_fd = File::Pid->new({
      file => $pid_file,
   });

   if ($pid_fd->running) { die "Instance already running" };

   $pid_fd->write;
}

sub main {
   $socket = FCGI::OpenSocket($socket_file, $socket_backlog);
   $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket);

   chown($socket_uid, $socket_gid, $socket_file);
   chmod($socket_perms, $socket_file);

   if ($request) {
      request_loop()
   };

   FCGI::CloseSocket($socket);
}

sub request_loop {
   while($request->Accept() >= 0) {

      $stdin_passthrough ='';
      $req_len = 0 + $req_params{'CONTENT_LENGTH'};
      if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){
         my $bytes_read = 0;
         while ($bytes_read < $req_len) {
            my $data = '';
            my $bytes = read(STDIN, $data, ($req_len - $bytes_read));
            last if ($bytes == 0 || !defined($bytes));
            $stdin_passthrough .= $data;
            $bytes_read += $bytes;
         }
      }

      if ( (-x $req_params{SCRIPT_FILENAME}) &&
           (-s $req_params{SCRIPT_FILENAME}) &&
           (-r $req_params{SCRIPT_FILENAME}) ){
         pipe(CHILD_RD, PARENT_WR);
	 my $pid = open(KID_TO_READ, "-|");
         unless(defined($pid)) {
            print "Content-type: text/plain\r\n\r\n";
            print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";
            next;
         }

         if ($pid > 0) {
            close(CHILD_RD);
            print PARENT_WR $stdin_passthrough;
            close(PARENT_WR);

	    while(my $s = <KID_TO_READ>) { print $s; }
	    close KID_TO_READ;
	    waitpid($pid, 0);
	 } else {
            foreach $key ( keys %req_params){
               $ENV{$key} = $req_params{$key};
            }

            if ($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) {
               chdir $1;
            }

	    close(PARENT_WR);
	    close(STDIN);
	    #fcntl(CHILD_RD, F_DUPFD, 0);
	    syscall(&SYS_dup2, fileno(CHILD_RD), 0);
	    #open(STDIN, "<&CHILD_RD");
	    exec($req_params{SCRIPT_FILENAME});
	    die("exec failed");
	}
     }
     else {
        print "Content-type: text/plain\r\n\r\n";
        print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";
     }
  }
}

END {
   $pid_fd->remove if defined $pid_fd;
   unlink($socket_file);
}

Script de démarrage init.d

root@muse:~# cat /etc/init.d/fcgi-perl
#! /bin/sh
### BEGIN INIT INFO
# Provides:          fcgi-perl
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: fcgi-perl
# Description:       start the fcgi-perl daemon
### END INIT INFO

# Author: Boris HUISGEN <bhuisgen@hbis.fr>

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=fcgi-perl
NAME=fcgi-perl

DAEMON=/etc/nginx/$NAME.pl
PIDFILE=/var/run/fcgi-perl.pid
SOCKETFILE=/var/run/fcgi-perl.sock

[ -x "$DAEMON" ] || exit 0

[ -r /etc/default/$NAME ] && . /etc/default/$NAME

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_start()
{
	[ -e $PIDFILE ] && return 1

	echo "Starting $PROVIDES..."
	$DAEMON &

	[ ! -e $PIDFILE ] && sleep 1
	[ ! -e $PIDFILE ] && return 2

	return 0
}

do_stop()
{
	[ ! -e $PIDFILE ] && return 1

	echo "Stopping $PROVIDES..."
	kill `cat $PIDFILE`

	rm -f $PIDFILE
	rm -f $SOCKETFILE

	return 0
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
       status_of_proc -p $PIDFILE "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  restart)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;;
			*) log_end_msg 1 ;;
		esac
		;;
	  *)
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
	exit 3
	;;
esac

:

Configuration Nginx

server {
   listen 80;
   server_name localhost;

   location / {
      root /var/www/default;
      index index.cgi index.html;
   }

   location ~ \.cgi$ {
      fastcgi_pass unix:/var/run/fcgi-perl.sock;
      fastcgi_index index.cgi;
      fastcgi_param HTTP_ACCEPT_ENCODING gzip,deflate;
      include fastcgi_params;
   }
}

Nginx : configuration reverse-proxy

root@nginx1:~# cat /etc/nginx/conf.d/proxy.conf
proxy_redirect            off;
proxy_set_header          Host $host;
proxy_set_header          X-Real-IP $remote_addr;
proxy_set_header          X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size      16m;
client_body_buffer_size   128k;
client_header_buffer_size 64k;
proxy_connect_timeout     10;
proxy_send_timeout        60;
proxy_read_timeout        60;
proxy_buffer_size         16k;
proxy_buffers             32 16k;
proxy_busy_buffers_size   64k;
proxy_cache_key           "$scheme://$host$request_uri";
proxy_cache_path          /var/cache/nginx levels=1:2 keys_zone=cache:10m inactive=7d max_size=512m;
root@nginx1:~# cat /etc/nginx/sites-enabled/monsite
server {
   listen      80;
   listen      [::]:80 default ipv6only=on;
   server_name monsite.fr *.monsite.fr;
   access_log  /var/log/nginx/localhost.access.log;

   location / {
      proxy_pass            http://192.168.10.4/;
      proxy_cache           cache;
      proxy_cache_valid     12h;
      proxy_cache_use_stale error timeout invalid_header updating;
   }
}

Nginx : configuration d’hôte avec root virtuel

L’intérêt de cette configuration est de gérer plusieurs sites par un unique hôte virtuel.

server
{
 listen          127.0.0.1:80;
 listen          192.168.0.1:80;
 server_name ~(?.+).bhuisgen.dev.my.domain$;
 root            /mnt/home/bhuisgen/www/html/$site;
 access_log      /mnt/home/bhuisgen/www/logs/access.log main;
 error_log       /mnt/home/bhuisgen/www/logs/error.log;
 index           index.php;

 location ~ \.php$ {
 fastcgi_pass    unix:/var/run/php-bhuisgen.sock;
 fastcgi_index   index.php;
 fastcgi_param   SCRIPT_FILENAME  /mnt/Users/bhuisgen/Sites/html/$site$fastcgi_script_name;
 include         fastcgi_params;
 }
}

Nginx : configuration pour site PHP Symfony

http://www.symfony-project.org/

server {
   listen        192.168.0.1:80;
   server_name   www.site.fr;
   root          /home/site.fr/web/;

   location / {
      index index.php;
      try_files $uri $uri/ /index.php?$args;
   }

   location ^~ /sf/ {
      alias /home/site.fr/lib/vendor/symfony/data/web/sf/;
   }

   location ~ "^(.+\.php)($|/)" {
      fastcgi_split_path_info   ^(.+\.php)(.*)$;
      fastcgi_param             SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param             SCRIPT_NAME $fastcgi_script_name;
      include                   fastcgi_params;
      fastcgi_pass              unix:/var/run/php-site_fr.sock;
      fastcgi_index             index.php;
   }
}

Nginx : configuration reverse proxy pour serveur GlassFish

server {
   listen 80;
   server_name shorturl.my.domain;
   root /opt/local/www/;

   # proxy glassfish
   location / {
      # Proxy all requests to Glassfish
      proxy_pass http://127.0.0.1:8080/shorturl/;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;

      proxy_cache one;
      proxy_cache_min_uses 1;
      proxy_cache_valid  200 302 1m;
      proxy_cache_valid  404 1m;
      proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
   }

   # serve static resources directly
   location ~ ^/resources/(components|css|images|javascript?)/(.*)$ {
      alias /opt/local/www/shorturl/$1/$2;
   }

   location ~ ^/favicon.ico$ {
      alias /opt/local/www/shorturl/favicon.ico;
   }
}
Haut de page