Nginx 虛擬主機 配置 支持獨立urlwrite 文件, php-fpm獨立用戶和php....

Nginx 虛擬主機 環境配置。

最近租了臺服務器,準備作一些網站。糾結apache/nginx好久,最後選定了Nginx+php-fpm。

由於可能會有幾個站,爲了安全,我但願每一個站點直接都能儘可能獨立,避免互相影響。

主要實現功能:

  • -可以相對快捷的添加虛擬主機。
  • -每一個虛擬主機直接相對獨立,避免一個網站有漏洞,全服務器手影響
  • -可以方便的配置urlrewrite,仍是須要reload或restart ( 誰讓nginx 不支持像 .htaccess 這樣嗎方便的東西呢?)
  • -每一個虛擬主機能獨立配置php.ini


上面是廢話,下面就是大概實現方法。

1、主要環境


CentOS 5.7, Nginx 1.06 PHP 5.2.17(php-fpm)
安裝過程省略,我基本都是編譯安裝在 /usr/local/ 下面。
php

2、Web目錄結構&權限


/home/$USER$/            用戶
|-- $DOMAIN$            域名
    |-- logs
    |   |-- access.log        訪問日誌
    |   `-- .nginx        用戶Nginx,能夠定義urlrewrite 即便不須要也要建立,空內容,由於 nginx 配置文件中要include~。
    `-- wwwroot            用戶存放web文件
         `-- index.html

權限:

Home目錄下的所有目錄(除了用戶後來建立的)都是711, 用戶組和其餘用戶都只能進入目錄,不能查看目錄有什麼文件。

home下的全部文件文件(除了用戶後來建立的)都是644,目錄全部者能讀寫,用戶組內的和其餘用戶只能讀。

將 umask 都設置成 0022,這樣的話用戶建立的目錄就是 755,能訪問,能讀取(顯示目錄下的文件)。建立的文件則是644,全部者能讀寫,用戶組的和其餘用戶只能讀取。


3、基本實現


1.在/(也能夠是其餘)目錄下建立vhost目錄。
2.在 /vhost 目錄下建立logs目錄用於記錄日誌(php-fpm)。
3.在 /vhost 目錄下對應每一個虛擬主機的用戶建立一個用戶目錄。
4.在用戶目錄內建立該用戶的虛擬主機的目錄,目錄名稱爲主域名(好比:qq.com)。
5.再在域名目錄下建立 nginx.conf 和 php-fpm.conf 。nginx.conf 會被 主的nginx.conf 包含,裏面指定了web目錄等配置。php-fpm.conf 是php-fpm啓動時讀取的配置文件,指定了執行php的用戶和組,socket端口等配置。
6.在 /vhost 目錄下建立 chHosts.sh,該文件用戶遍歷/vhost目錄下存在那些虛擬主機,記錄下來,寫入到 /vhost/hosts 文件,以便使用。 hosts 內容大概以下:

user1/qq.com
user2/yahoo.com
user3/google.com
user3/yahoo.com

7.在 /vhost 目錄下建立 php-fpm 文件,該文件用於啓動每一個虛擬主機的php-fpm 修改自默認的php-fpm,藉助hosts的內容,讀取每一個主機的php-fpm配置文件啓動各自的php-fpm。

8.在主 nginx 的配置文件中的 http{ } 中添加下面內容,我是刪了全部的server{}的~

# VHOST
    include   /vhost/*/*/nginx.conf;

vhost 目錄結構大體以下:
.
|-- user1
|   `-- qq.com
|       |-- nginx.conf
|       |-- php-fpm.conf
|       |-- php-fpm.pid
|       `-- php-fpm.socket
|-- chHosts.sh
|-- hosts
|-- logs
|   `-- user1_qq.com.log
`-- php-fpm

php-fpm.conf 文件內容大體以下:

<?xml version="1.0" ?>
<configuration>
    <section name="global_options">
        <value name="pid_file">/vhost/user1/qq.com/php-fpm.pid</value>  <!-- 記錄主進程pid -->
        <value name="error_log">/vhost/logs/user1_qq.com.log</value>    <!-- 記錄php-fpm錯誤日誌 -->
        <value name="log_level">warn</value>                            <!-- 日誌記錄級別 -->
        <value name="emergency_restart_threshold">10</value>
        <value name="emergency_restart_interval">1m</value>
        <value name="process_control_timeout">5s</value>
        <value name="daemonize">yes</value>
    </section>
    <workers>
        <section name="pool">
            <value name="name">user1_qq.com</value>            <!-- 該pool名稱,日誌中使用 -->
            <value name="listen_address">/vhost/user1/qq.com/php-fpm.socket</value>   <!-- 使用socket 文件,要和和nginx中一致 -->
            <value name="listen_options">
                <value name="backlog">-1</value>
                <value name="owner"></value>
                <value name="group"></value>
                <value name="mode">0666</value>
            </value>
            <value name="php_defines">
                <!-- 這裏能夠設置php.ini中的參數,指定的php.ini沒法覆蓋。 -->
                <!--<value name="disable_functions">phpinfo,exec,passthru,shell_exec,system,proc_open,popen,show_source</value>
                <value name="open_basedir">/tmp/:./:/home/user1/qq.com/</value>-->
            </value>
            <value name="user">user1</value>        <!-- 執行php時的用戶該用戶有什麼權限php就有什麼權限~ -->
            <value name="group">user1</value>        <!-- 執行php是的用戶組 -->
            <value name="pm">
                <value name="style">static</value>
                <value name="max_children">128</value>
                <value name="apache_like">
                    <value name="StartServers">10</value>
                    <value name="MinSpareServers">5</value>
                    <value name="MaxSpareServers">35</value>
                </value>
            </value>
            <value name="request_terminate_timeout">0s</value>
            <value name="request_slowlog_timeout">0s</value>
            <value name="slowlog">/vhost/logs/user1_qq.com_slow.log</value>   
            <value name="rlimit_files">65535</value>
            <value name="rlimit_core">0</value>
            <value name="chroot"></value>
            <value name="chdir"></value>
            <value name="catch_workers_output">yes</value>
            <value name="max_requests">1024</value>
            <value name="allowed_clients">127.0.0.1</value>
            <value name="environment">
                <value name="HOSTNAME">$HOSTNAME</value>
                <value name="PATH">/usr/local/bin:/usr/bin:/bin</value>
                <value name="TMP">/tmp</value>
                <value name="TMPDIR">/tmp</value>
                <value name="TEMP">/tmp</value>
                <value name="OSTYPE">$OSTYPE</value>
                <value name="MACHTYPE">$MACHTYPE</value>
                <value name="MALLOC_CHECK_">2</value>
            </value>

        </section>

    </workers>

</configuration>
有簡單的註釋,其餘看 官方文檔
主要的是執行php時的用戶和用戶組,必須是 nginx 中 web目錄的全部者 和 全部者的組,這樣能夠隔離開每一個用戶的虛擬主機,保證了基本的安全。
php_defines 中能夠配置disable_functions 和 open_basedir 這樣更加安全點。

nginx.conf的內容大體以下:
server {
  server_name www.qq.com qq.com;
  root   /home/user1/qq.com/wwwroot/;
  access_log  /home/user1/qq.com/logs/access.log;
 
  include /home/user1/qq.com/.nginx;
  location ~ \.php$ {
    fastcgi_pass   unix:/vhost/user1/qq.com/php-fpm.socket;
    fastcgi_index  index.php;
    include       fcgi.conf;
  }

  include   cache.conf;
  error_page   404 403 500 503 505 504 502
  error_page   500 503 505 504 502
}

php-fpm.socket 文件用於和 php-fpm 通訊,固然也能夠指向到/tmp目錄下。
.nginx 上面說了,能夠用做urlrewrite等配置。

cache.conf 內容:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
      expires       30d;
    }

    location ~ .*\.(js|css)?$
    {
      expires       1h;
    }

fcgi.conf 內容大體以下:
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    'Apache/2.2.17 (Unix) DAV/2 PHP/5.2.17';

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect

fastcgi_param  REDIRECT_STATUS    200;

php-fpm 內容以下:
#!/bin/sh
#
# php-fpm - this script starts and stops the php-fpm daemin
#
# chkconfig: - 85 15
# description: php-fpm
# processname: php-fpm
# config:      /usr/local/php/etc/php-fpm.conf

vhost=$2

php_fpm_BIN=/usr/local/php/bin/php-cgi
php_fpm_CONF=/vhost/$vhost/php-fpm.conf
php_fpm_PID=/vhost/$vhost/php-fpm.pid
php_INI=/home/$vhost/php.ini


php_opts="--fpm-config $php_fpm_CONF"

if [ ! $vhost ]; then
    cat /vhost/hosts|while read line;do
         $0 $1 $line
    done
    exit
fi

if [ ! -r $php_fpm_CONF ]; then
    echo -n "不存在配置文件; $php_fpm_CONF"
    exit
fi

if [ -r $php_INI ]; then
    php_opts="$php_opts -c $php_INI"
fi


wait_for_pid () {
    try=0

    while test $try -lt 35 ; do

        case "$1" in
            'created')
            if [  -f "$2" ] ; then
                try=''
                break
            fi
            ;;

            'removed')
            if [ ! -f "$2" ] ; then
                try=''
                break
            fi
            ;;
        esac

        echo -n .
        try=`expr $try + 1`
        sleep 1

    done

}

case "$1" in
    start)
        if [ -f $php_fpm_PID ]; then
                echo 'Has started!'
                exit
        fi
        echo -n "Starting php_fpm ($vhost) "

        $php_fpm_BIN --fpm $php_opts

        if [ "$?" != 0 ] ; then
            echo " failed"
            exit 1
        fi

        wait_for_pid created $php_fpm_PID

        if [ -n "$try" ] ; then
            echo " failed"
            exit 1
        else
            echo " done"
        fi
    ;;

    stop)
        echo -n "Shutting down php_fpm ($vhost)"

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -TERM `cat $php_fpm_PID`

        wait_for_pid removed $php_fpm_PID

        if [ -n "$try" ] ; then
            echo " failed"
            exit 1
        else
            echo " done"
        fi
    ;;

    quit)
        echo -n "Gracefully shutting down php_fpm "

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -QUIT `cat $php_fpm_PID`

        wait_for_pid removed $php_fpm_PID

        if [ -n "$try" ] ; then
            echo " failed"
            exit 1
        else
            echo " done"
        fi
    ;;

    restart)
        $0 stop $2
        $0 start  $2
    ;;

    reload)

        echo -n "Reload service php-fpm "

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -USR2 `cat $php_fpm_PID`

        echo " done"
    ;;

    logrotate)

        echo -n "Re-opening php-fpm log file "

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -USR1 `cat $php_fpm_PID`

        echo " done"
    ;;

    *)
        echo "Usage: $0 {start|stop|quit|restart|reload|logrotate}"
        exit 1
    ;;

esac


會判斷 虛擬主機目錄下是否有php.ini有的話則讀取用戶的php.ini 啓動php-fpm 沒有則是默認的。
使用方法:
php-fpm start user1/qq.com 啓動 user1 的qq.com 的php-fpm
或者
php-fpm start 啓動全部虛擬主機的php-fpm

能夠將該文件複製到/etc/init.d/ 中 用 service php-fpm start 的方式開啓動,或者設置成開機啓動。

大致就是這樣了。

4、其餘


可使用下面的命令遞歸修改權限:
find /home/ -type f -exec chmod 0644 {} \;  #設置文件問644
find /home/ -type d -exec chmod 0711 {} \;  #設置目錄問711

下面的shell能夠用來建立目錄和文件還有修改文件權限等:

mkdir /home/$OWNER$/$DOMAIN$/
mkdir /home/$OWNER$/$DOMAIN$/logs/
mkdir /home/$OWNER$/$DOMAIN$/wwwroot/
touch /home/$OWNER$/$DOMAIN$/.nginx
echo "$DOMAIN$" > /home/$OWNER$/$DOMAIN$/wwwroot/index.html
chown $OWNER$:$OWNER$ /home/$OWNER$/ -R
find /home/$OWNER$/ -type f -exec chmod 0644 {} \;
find /home/$OWNER$/ -type d -exec chmod 0711 {} \;

------------------------- 上面是 shell ---------------------------------

要配置默認主機的話在 虛擬主機的nginx.conf 文件中在server_name 下添加 :

listen 80 default

另外我寫了個簡單的php程序用於建立虛擬主機的配置文件,還寫了個簡單的shell用於移動配置文件到 /vhost (生成的文件目前是放在web目錄下~), 而且執行chHosts.sh 從新遍歷查看有那些虛擬主機,而後重啓 nginx 和 啓動 php-fpm,讓配置生效。就不放出來了,呵呵。

看到網上有人說 php-fpm 和 nginx 最好用no-body執行,而後那些須要寫權限的目錄要用戶手動設置(能夠用ftp)成777。nobody彷佛確實相對會安全點,可是這樣就會虛擬主機常出現權限問題。
我使用目錄全部者確實是爲了方便(不須要設置777)。 並且也獨立了每一個虛擬主機的php權限,這樣即時知道了其餘用戶的 777 目錄也修改不了。這樣保證了各個虛擬主機的獨立,但不保證該虛擬主機的安全。 見仁見智,或者看需求了,也多是我沒理解透徹權限問題。


而後 /tmp 安全:  Google搜索  Linux臨時文件目錄安全配置實例 , 不知道哪裏是原創因此搜索吧。


我試傳了個 webshell phpspy 彷佛妥妥的。


最後但願有人能指出這樣配置會不會有什麼問題?
特別是安全方面的!或者是有什麼建議都請指出來!

原文:http://bee.glroomy.com/nginx-php-fpm-urlwrite-php-ini.htmlcss

ps:彷佛這邊排版好看點~我要update下我blog了~    html

相關文章
相關標籤/搜索