Category Archives: server

GitLab Installation on CentOS with nginx integration

Installation gitlab

S1. Follow the local installation guideline: https://about.gitlab.com/downloads/

wget https://downloads-packages.s3.amazonaws.com/centos-6.5/gitlab-7.1.1_omnibus-1.el6.x86_64.rpm
yum install openssh-server
yum install postfix # Select 'Internet Site', using sendmail instead also works, exim has problems
rpm -ivh gitlab-7.1.1_omnibus-1.el6.x86_64.rpm

S2. Initial basic gitlab config in /etc/gitlab/gitlab.rb

For troubleshooting and configuration options please see the Omnibus GitLab readme

# Change the external_url to the address your users will type in their browser
external_url 'http://git.iallex.com'
#git_data_dir '/home/git/git-data'

S3. Setup gitlab services configurations

gitlab-ctl reconfigure

That’s all if your server just for gitlab standalone.

You can login as an admin user with username root and password 5iveL!fe

Separation Nginx Server from gitlab Suite kit

Stop gitlab service first:

gitlab-ctl stop

Give nginx access to git group:

ensure your Nginx running with a specific user www in /etc/nginx/nginx.conf

usermod -a -G git www

Change some gitlab permissions:

# ensure gitlab-rails is owner by git group
chown git.git /var/opt/gitlab/gitlab-rails/ -R

# ensure `/var/opt/gitlab/gitlab-rails/tmp/sockets/gitlab.socket` and `uploads` accessable by nginx
chmod g+rwx /var/opt/gitlab/gitlab-rails/ -R

# link gitlab nginx config
ln -sf "/var/opt/gitlab/nginx/etc/gitlab-http.conf" /etc/nginx/conf.d/

# disable gitlab internal nginx service and symbolics link to global nginx config 
rm -f /opt/gitlab/service/nginx
ln -sf "/var/opt/gitlab/nginx/etc/gitlab-http.conf" /etc/nginx/conf.d/

# test permission
sudo -u www ls "/var/opt/gitlab/gitlab-rails/tmp/sockets/gitlab.socket"

Restart gitlab services and nginx

gitlab-ctl start
/etc/init.d/nginx restart

Enjoy! http://git.iallex.com

Related Links:

PHP_FPM of unix sockets vs TCP ports

When setup PHP-FPM for nginx pass_proxy, we may setup the php-fpm.conf include one of the config below:

listen = /var/run/php5-fpm.sock –> [nginx.conf] fastcgi_pass unix:/var/run/php5-fpm.sock;

listen = 127.0.0.1:9000 –> [nginx.conf] fastcgi_pass 127.0.0.1:9000;

Performance of unix sockets vs TCP ports

When you are using TCP, you are also using the whole network stack. Even if you are on the same machine, this implies that packets are encapsulated and decapsulated to use the network stack and the related protocols.

If you use unix domain sockets, you will not be forced to go through all the network protocols that are required otherwise. The sockets are identified solely by the inodes on your hard drive.

Make PHP-FPM Listen at “IPAddress:Port” Instead of “/var/run/php5-fpm.sock;”

Sockets are slightly faster as compared to TCP/IP connection. But they are less scalable by default.

If you start getting errors like below

connect() to unix:/var/run/php5-fpm.sock failed or **apr_socket_recv: Connection reset by peer (104)**

Then it means you need to either switch to TCP/IP or tweak with linux-system parameter so that your OS can handle large number of connections.

So, for high-load cases this is what it’s supposed to be: listen = 127.0.0.1:9000 and that fixed everything!

Reference Links

Remove PHP X-Powered-By & Nginx Version

For some website’s security reason, we need remove X-Powered-By and NGINX Version from response headers.

PHP:

To remove X-Powered-By completely, search line in php.ini.

expose_php = Off

or add the following directive to the Nginx configuration:

# Prevent version info leakage
fastcgi_hide_header X-Powered-By;

Nginx:

To remove Server Version from Header, server_tokens should be disabled in nginx.conf.

# http://wiki.nginx.org/HttpCoreModule#server_tokens
server_tokens off;

Change server string by recompiling Nginx source:

vim +49 src/http/ngx_http_header_filter_module.c

Find the lines:

static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;

see also: Customize Your Nginx Server Name After Compiling From Source

Rotate Nginx log files

Nginx is a great web server, however a default install will not rotate log files for you. there’s no size limit, it will keep getting bigger until your disk is full.

this is a problem especially on busy sites, as the access log can eat up disc space quite quickly.

In this tutorial, I will show you how to rotate ngnix log files automatically, my version is nginx/1.4.3. but any modern distribution should function in a similar way.

Manual rotating nginx log files via Cron

First we need to create the job bash script for cron that will do the log rotation.

sudo vi /usr/local/sbin/rotate_nginx_log.sh

Here are the contents of the script (this is based off the example from the Nginx wiki):

#!/bin/bash
# <https://gist.github.com/allex/10360845>

# Set variable
logs_path="/var/log/nginx/"
old_logs_path=${logs_path}/old
nginx_pid=`cat /var/run/nginx.pid`

time_stamp=`date -d "yesterday" +%Y-%m-%d`

mkdir -p ${old_logs_path}

# Main
for file in `ls $logs_path | grep log$ | grep -v '^20'`
do
    if [ ! -f ${old_logs_path}/${time_stamp}_$file ]
    then
        dst_file="${old_logs_path}/${time_stamp}_$file"
    else
        dst_file="${old_logs_path}/${time_stamp}_$file.$$"
    fi
    mv $logs_path/$file $dst_file
    gzip -f $dst_file  # do something with access.log.0
done

kill -USR1 $nginx_pid

Note:

First, we move the current log to a new file for archiving. A common scheme is to name the most recent log file with a suffix of current time stamp. e.g, $(date "+%Y-%m-%d").

The command that actually rotates the logs is kill -USR1 $(cat /var/run/nginx.pid). This does not kill the Nginx process, but instead sends it a SIGUSR1 signal causing it to re-open its logs.

THen execute sleep 1 to allow the process to complete the transfer. We can then zip the old files or do whatever post-rotation processes we would like.

Next please make sure that the script file is executable by running

chmod +x /usr/local/sbin/rotate_nginx_log.sh

In our final step we will create a crontab file to run the script we just created.

sudo crontab -e

In this file let’s create a cron job to run every day at 1am

Add the following lines to the file as follows:

00 01 * * * /usr/local/sbin/rotate_nginx_log.sh &> /dev/null

Also we can config suppressing cron jobs status email notifications. see Suppressing Cron Job Email Notifications


Log Rotation With Logrotate

The logrotate application is a simple program to rotate logs.

sudo vim /etc/logrotate.d/nginx

Put this content inside and modify the first line to match your Nginx log file

/var/log/nginx/*.log {
    daily
    missingok
    rotate 30
    dateformat .%Y-%m-%d
    compress
    delaycompress
    notifempty
    create 640 nginx adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] &amp;&amp; kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

Wait 24 hours until cron daily runs and check out if you see any .gz file inside your logs directory, if you see some gzipped files, your Nginx rotation is working fine :D


Related References:

CentOS LOG – Safety optimizations

Kernel optimization vi /etc/sysctl.conf

We can view the system kernel settings by sysctl -a.

# Not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Do not send ICMP redirects (we are not a router)
net.ipv4.conf.all.send_redirects = 0

优化内核阻挡SYN洪水攻击 sysctl -a | grep syn

# 设置syncookies:
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_max_syn_backlog=3072
sysctl -w net.ipv4.tcp_synack_retries=0
sysctl -w net.ipv4.tcp_syn_retries=0
sysctl -w net.ipv4.conf.all.send_redirects=0
sysctl -w net.ipv4.conf.all.accept_redirects=0
sysctl -w net.ipv4.conf.all.forwarding=0
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1

# 防止PING:
sysctl -w net.ipv4.icmp_echo_ignore_all=1

Add iptables to avoid Sync Flood Attack

# 防止Sync Flood, 缩短SYN- Timeout时间 (-limit 1/s 限制SYN并发数每秒1次,可以根据自己的需要修改)
iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -i eth0 -m limit --limit 1/sec --limit-burst 5 -j ACCEPT

# 防止各种端口扫描
iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

# 防止 Ping of Death 攻击
iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

# 每秒 最多3个 syn 封包 进入
iptables -N syn-flood
iptables -A INPUT -p tcp --syn -j syn-flood
iptables -A syn-flood -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables -A syn-flood -j REJECT

# 拦截具体IP范围 (eg. 10.0.0.0/8)
iptables -A INPUT -s 10.0.0.0/8 -i eth0 -j Drop

开防火墙,不用的端口都禁止掉

iptables -F
iptables -A INPUT -p tcp -i vnet0 –dport ssh -j ACCEPT
iptables -A INPUT -p tcp -i vnet0 –dport 80 -j ACCEPT
iptables -A INPUT -i vnet0 -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p ICMP -j DROP
iptables -A INPUT -i vnet0 -j DROP

修改好之后重启iptables

/etc/init.d/iptables restart

Nginx install and configuration skills

Compile and installation

Get latest source code from http://nginx.org/en/download.html

Some 3rd-party modules here

tar xzf nginx-1.4.3.tar.gz
cd nginx-1.4.3
./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/tmp/nginx/body --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-proxy-temp-path=/var/tmp/nginx/proxy --http-scgi-temp-path=/var/tmp/nginx/scgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid
make
make install

Some optional options for advanced features:

--with-http_gzip_static_module

Sending precompressed files with the .gz filename extension instead of regular files by gzip_static on.

--add-module=/path/to/echo-nginx-module

Compile with module for bringing the power of echo, sleep, time and more to nginx’s config file. see more

location /test {
  echo "uri = $uri";
  echo "args = $args";
  ...
}

Nginx compile issues

./configure: error: the HTTP rewrite module requires the PCRE library. You can either disable the module by using --without-http_rewrite_module option, or install the PCRE library into the system, or build the PCRE library statically from the source with nginx by using --with-pcre option.

[Solution]

yum install pcre-devel.x86_64

[Note]

If pcre already installed, but still cannot find the pcre references:

In this case, when compiling nginx against a custom compiled library, such as pcre, zlib and OpenSSL, you must use the options --with-cc-opt and --with-ld-opt

--with-cc-opt="-I/usr/local/pcre/include" --with-ld-opt="-L/usr/local/pcre/lib"

./configure: error: SSL modules require the OpenSSL library. You can either do not enable the modules, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl option.

[Solution]

yum install openssl.x86_64 openssl-devel.x86_64

Nginx configuration guidlines

First understand IfIsEvil

set customize header

Add customize header for upstream identify when development environment (add variable$hostname to http headers).

add_header X-Original-Via $hostname;

Fastcgi normalize SCRIPT_FILENAME

With fastcgi_split_path_info we can customize the $fastcgi_path_info and $fastcgi_script_name

fastcgi_split_path_info regex; Defines a regular expression that captures a value for the $fastcgi_path_info variable. The regular expression should have two captures: the first becomes a value of the $fastcgi_script_name variable, the second becomes a value of the $fastcgi_path_info variable. For example, with these settings

location ~ ^(.+\.php)(.*)$ {
   fastcgi_split_path_info       ^(.+\.php)(.*)$;
   fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;
   fastcgi_param PATH_INFO       $fastcgi_path_info;
}

and the “/show.php/article/0001” request, the SCRIPT_FILENAME parameter will be equal to “/path/to/php/show.php”, and the PATH_INFO parameter will be equal to “/article/0001”.

Related Links: