Перейти к собственно контенту

Архив

Метка: nginx

Данная статья описывает настройку Redmine+Unicorn+Nginx на ОС FreeBSD. Данные будем хранить в MySQL

Установка Web сервера

Ставим nginx
# cd /usr/ports/www/nginx
# make config-recursive
# make install clean

в /etc/rc.conf добавляем:
nginx_enable=YES

Ставим MySQL ( я выбрал MariaDB 10.1 )
# cd /usr/ports/databases/mariadb101-server
# make config-recursive
# make install clean

в /etc/rc.conf добавляем:
mysql_enable=YES
Запускаем MySQL
# /usr/local/etc/rc.d/mysql-server start

Задаем пароль для root в MySQL ( в скобках сам пароль )
# mysqladmin -u root password 'password'

Установка Redmine

# cd /usr/ports/www/redmine
# make config-recursive
# make install clean

Создаем пользователя и базу для redmine:
# mysql -p
CREATE DATABASE redmine CHARACTER SET utf8;
CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'PASSWORD';
GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';

Переходим в директорию с Redmine, копируем и редактируем конфиг подключения к БД в соотвествии ранее созданного пользователя:
cd /usr/local/www/redmine/
cp config/database.yml.example config/database.yml
nano config/database.yml

Установка Unicorn:
Редактируем файл Gemfile
# ee Gemfile
и добавляем в конце
gem 'unicorn'

Выполняем команду
# bundle install --without development test

Генерируем ключи и инициализируем базу данных
# bundle exec rake generate_secret_token
# rake db:migrate RAILS_ENV=production
# rake redmine:load_default_data RAILS_ENV=production

Создаем и редактируем конфиг unicorn
# touch config/unicorn.rb
# ee config/unicorn.rb

и приводим его к такому виду
worker_processes 3 # Numbers CPU + 1
working_directory "/usr/local/www/redmine/"
preload_app true
timeout 300
listen "/usr/local/www/redmine/tmp/sockets/unicorn.sock", :backlog => 64
pid "/usr/local/www/redmine/tmp/pids/unicorn.pid"
stderr_path "/usr/local/www/redmine/log/unicorn.stderr.log"
stdout_path "/usr/local/www/redmine/log/unicorn.stdout.log"

before_fork (далее…)

Имеем свежеустановленую FreeBSD 11. Задача: поднять Gitlab.
Обновляем дерево портов
portsnap fetch && portsnap extract && portsnap update

1) Устанавливаем MariaDB
cd /usr/ports/databases/mariadb101-server/
make config-recursive
make install clean
,
добавляем в автозапуск, запускаем и производим настройку ( установку root пароля и так далее )
sysrc mysql_enable=YES
service mysql_server start
/usr/local/bin/mysql_secure_installation

Создаем базу для Gitlab:

Заходим в MySQL
mysql -u root -p

Вводим ранее установленный пароль для root

Создаем пользователя для Gitlab
CREATE USER 'git'@'localhost' IDENTIFIED BY 'password';

Устанавливаем тип таблиц и прочие настройки
SET storage_engine=INNODB;
SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda, innodb_large_prefix=1;

Создаем базу
CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_general_ci`;

Предоставляем привелегии на базу для пользователя git
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES, REFERENCES, TRIGGER ON `gitlabhq_production`.* TO 'git'@'localhost';

Вызодим из MySQL
\q

2) Устанавливаем Gitlab и настраиваем Redis
cd /usr/ports/www/gitlab
make config-recursive
( отмечаем MySQL )
make install
sysrc gitlab_enable=YES

Включаем чтоб Redis слушался по сокуту
echo 'unixsocket /var/run/redis/redis.sock' >> /usr/local/etc/redis.conf

Выставляем права на сокет
echo 'unixsocketperm 770' >> /usr/local/etc/redis.conf

Добавляем в автозагрузку и запускаем Redis
sysrc redis_enable=YES
service redis restart

Добавляем пользователя git в группу redis
pw groupmod redis -m git

3) Настраиваем Gitlab
Изменяем домашний каталог пользователя git
vipw -d /etc

Находим строку
git:*:211:211::0:0:gitosis user:/usr/local/git:/bin/sh

и меняем на
git:*:211:211::0:0:gitosis user:/home/git:/bin/sh

Идем в директорию с Gitlab
cd /usr/local/www/gitlab

И (далее…)

Случилось так, что у одного из сайтов появилось какое-то «левое» зеркало,  которое сильно подбило позиции в поисковике. Я думал что домен просто направили на IP того сервера, на который ссылался домен. Прописал в конфиг виртуального хоста строки, запрещающие доступ к сайту по IP адресу

if ($host !~ ^(example.com|www.example.com)$ ) {
return 403;
}

Но не помогло, так как выяснилось что сайт на «левом» зеркале парсился PHP скриптами через CURL. Сразу возникла идея просто запретить доступ по User Agent, но он был изменен на GoogleBot/2.1 , и если его забанить то и поисковые боты не смогут попасть на сайт. Осталось только 1 решение, сравнивать User Agent и IP адрес, с которого был запрос, и если это реальные IP адреса гуглобота, то пропускать, иначе отдавать ошибку 403. В конфиг nginx добавляем в секцию http следующие строки ( это все IP адреса и подсети, которые использует гуглобот и которые мне удалось найти, если есть чем дополнить пишите в коментариях ):

geo $googlebotip {
default 0;
64.18.0.0/20 1;
64.233.160.0/19 1;
66.102.0.0/20 1;
66.249.80.0/20 1;
72.14.192.0/18 1;
74.125.0.0/16 1;
108.177.8.0/21 1;
172.217.0.0/19 1;
173.194.0.0/16 1;
207.126.144.0/20 1;
209.85.128.0/17 1;
216.58.192.0/19 1;
216.239.32.0/19 1;
203.208.60.0/24 1;
66.249.64.0/20 1;
72.14.199.0/24 1;
209.85.238.0/24 1;
66.249.90.0/24 1;
66.249.91.0/24 1;
66.249.92.0/24 1;
2001:4860:4000::/36 1;
2404:6800:4000::/36 1;
2607:f8b0:4000::/36 1;
2800:3f0:4000::/36 1;
2a00:1450:4000::/36 1;
2c0f:fb50:4000::/36 1;
2001:4860:4801:1::/64 1;
2001:4860:4801:2::/64 1;
2001:4860:4801:3::/64 1;
2001:4860:4801:4::/64 1;
2001:4860:4801:5::/64 1;
2001:4860:4801:6::/64 1;
2001:4860:4801:7::/64 1;
2001:4860:4801:8::/64 1;
2001:4860:4801:9::/64 1;
2001:4860:4801:a::/64 1;
2001:4860:4801:b::/64 1;
2001:4860:4801:c::/64 1;
2001:4860:4801:d::/64 1;
2001:4860:4801:e::/64 1;
2001:4860:4801:2001::/64 1;
2001:4860:4801:2002::/64 1;
104.132.0.0/21 1;
104.132.12.0/24 1;
104.132.128.0/24 (далее…)

В дополнение к этой статье я напишу как установить Redmine и при необходимости перенести данные на сервер с ОС CentOS 6.5 и панелью ISPmanager Lite.

У нас имеется один сервер с рабочим Redmine и второй с ISPmanager Lite на котороый и будет делать перенос.

1) Ставим пакеты для сборки сорцов:

# yum install gcc-c++ patch readline readline-devel zlib zlib-devel
# yum install libyaml-devel libffi-devel openssl-devel make
# yum install bzip2 autoconf automake libtool bison iconv-devel mysql-devel

2) Устанавливаем RVM ( Ruby Version Manager ):

# curl -L get.rvm.io | bash -s stable

3) Выставляем переменные окружения:

# source /etc/profile.d/rvm.sh

4) Ставим Ruby 1.9.3 и назначаем дефолтным в системе, проверяем работоспособность:

# rvm install 1.9.3
# rvm use 1.9.3 --default

Провеверям:

# ruby --version
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux]

5) Ставим Passenger и добавляем поддержку в Nginx:

# gem install passenger

Качаем исходный код nginx:

# cd /tmp
# wget http://nginx.org/download/nginx-1.7.9.tar.gz && tar xvzf nginx-1.7.9.tar.gz

Смотри с какими параметрами был уже бинарик у нас собран:

# nginx -V
nginx version: nginx/1.7.9
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/share/nginx --sbin-path=/usr/sbin/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/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/subsys/nginx --with-debug --with-http_secure_link_module --with-http_random_index_module --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module (далее…)

В дополнение к статье по настройке почтового сервера на FreeBSD решил написать как настроить тоже самое, но на ОС CentOS 6.

Подключаем репозиторий Remi и Epel

rpm --import https://fedoraproject.org/static/0608B895.txt
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-7.noarch.rpm
yum install yum-priorities
rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

Приводим файл /etc/yum.repos.d/epel.repo к такому виду

[epel]
name=Extra Packages for Enterprise Linux 6 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=1
priority=10
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

и файл /etc/yum.repos.d/remi.repo к такому виду:

[remi]
name=Les RPM de remi pour Enterprise Linux $releasever - $basearch
#baseurl=http://rpms.famillecollet.com/enterprise/$releasever/remi/$basearch/
mirrorlist=http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror
enabled=1
priority=10
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi
failovermethod=priority

[remi-test]
name=Les RPM de remi en test pour Enterprise Linux $releasever - $basearch
#baseurl=http://rpms.famillecollet.com/enterprise/$releasever/test/$basearch/
mirrorlist=http://rpms.famillecollet.com/enterprise/$releasever/test/mirror
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi

Ставим MySQL , добавляем в атозагрузку и стартуем:

yum install mysql mysql-server
chkconfig --levels 235 mysqld on
/etc/init.d/mysqld start

Установим пароь для root в MySQL следующей командой:

mysql_secure_installation

Устанавливаем nginx ( да да, как и в прошлый раз мы обойдемся без тяжеловесного Apache и сделаем все на NGINX + PHP-FPM ), добавим в автозагрузку и стартуем
yum install nginx
chkconfig --levels (далее…)

Добавляем в конфиг nginx в секцию http такие строки:

## FastCGI Cache
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
fastcgi_cache_path /tmp/nginx/cache levels=2 keys_zone=sites:100m inactive=1d max_size=10g;

и в описание вирт хоста в секцию сервер пишем:

### Fast-CGI Cache

location / {
if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png)$") {
expires max;

}
}

if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
set $do_not_cache 1;
}

fastcgi_cache_bypass $do_not_cache;
fastcgi_no_cache $do_not_cache;
fastcgi_pass_header Cookie;
fastcgi_cache sites;
fastcgi_cache_key $request_method|$host|$request_uri;
fastcgi_cache_valid 301 8h;
fastcgi_cache_valid 404 1h;
fastcgi_cache_valid 200 1h;

Создаем каталог для кеша и выставляем права:
mkdir -p /tmp/nginx/cache
chmod -R 777 /tmp/nginx/cache

Перезапускаем nginx :

/usr/local/etc/rc.d/nginx restart

Лазаем по сайту и смотри в каталог с кешем:

deathstar# ls /tmp/nginx/cache
00 0e 1c 2a 38 46 54 62 70 7e 8c 9a a8 b6 c4 d2 e0 ee fc
01 0f 1d 2b 39 47 55 63 71 7f 8d 9b a9 b7 c5 d3 e1 ef fd
02 10 1e 2c 3a 48 56 64 72 80 8e 9c aa b8 c6 d4 e2 f0 fe
03 11 1f 2d 3b 49 57 65 73 81 8f 9d ab b9 c7 d5 e3 f1 ff
04 12 20 2e 3c 4a 58 66 74 82 (далее…)

!!!! Из-за неправильного отображения данных конфигов в WordPress выложил их здесь.
Устанавливаем fail2ban
deathstar# cd /usr/ports/secuity/py-fail2ban && make install clean
Правим конфиг
deathstar# ee /usr/local/etc/fail2ban/jail.conf
У меня он выглядит так
[DEFAULT]
# Какие IP игнорировать
ignoreip = 127.0.0.1
# Время бана в секундах
bantime = 600
# время проверки,за которое событие успеет повторится, чтоб отловить и забанить
findtime = 600
# кол-во неверных попыток
maxretry = 1
backend = auto

[ssh-ipfw]
enabled = true
# использовать фильтр из примеров
filter = bsd-sshd
# использовать /action.d/bsd-ipfw.conf
action = ssh-ipfw[localhost=78.24.219.97]
# Уведомление в Jabber :))
jabber-whois[name="SSH,IPFW", dest=deathstar@deathstar.name]
# Какой лог парсить
logpath = /var/log/auth.log
# Какой Ip игнорировать
ignoreip = 127.0.0.1

[exim-ipfw]
enabled = true
filter = exim
action = exim-ipfw[localhost=78.24.219.97]
jabber-whois[name="Exim,IPFW", dest=deathstar@deathstar.name]
logpath = /var/log/exim/mainlog
ignoreip = 127.0.0.1

[nginx-ipfw]
enabled = true
filter = nginx
action = nginx-ipfw[localhost=127.0.0.1]
jabber-whois[name="Nginx,IPFW", dest=deathstar@deathstar.name]
logpath = /home/deathstar/www/deathstar.name.access.log
ignoreip = 127.0.0.1

Для уведомления в Jabber должен быть установлен и настроен sendxmpp ( о нем я писал в предыдущих статьях)
Создаем файл /usr/local/etc/fail2ban/action.d/jabber-whois.conf с таким содержимым

[Definition]
actionstart = printf %%b "[Fail2Ban] : started
The jail
has been started successfully.\n
" | /usr/local/bin/sendxmpp ""

actionstop = printf %%b "[Fail2Ban] : stopped
The jail
has been stopped.\n
" | /usr/local/bin/sendxmpp ""

actioncheck =

actionban = printf %%b "[Fail2Ban] : banned
The IP
has just been banned by Fail2Ban after
(далее…)

Активируем IPFW
Добавим в /etc/rc.conf

firewall_enable="YES"
firewall_script="/etc/ddos.sh"
firewall_logging="YES"

Создаем наш файерволл в файл /etc/ddos

#!/bin/sh
ipfw='/sbin/ipfw -q'
${ipfw} flush
${ipfw} add check-state
${ipfw} table 1 flush
${ipfw} add deny ip from table\(1\) to me
${ipfw} add allow all from any to any

Пишем парсер логов и добавляем их в черный список
Создадим файл /etc/ban.sh, который будет собирать IP и добавлять их в table1

#!/bin/sh
echo '' > /etc/bl
cat /var/log/nginx/deathstar.name.access.log | awk ' match($0, /(\d*.\d*.\d*.\d*).*"-" "-"/) {print $1}' | sort | uniq >> /etc/bl
/sbin/ipfw table 1 flush
cat /etc/bl | awk '{ if ($1!="") {system("/sbin/ipfw table 1 add "$1"")} }' > /dev/null

Добавить в cron задание

*/1 * * * * root /etc/ban.sh

Не плохо бы добавить в конфиг nginx следующее:

if ($http_user_agent ~* "(vaginamook|2003100|ODI3|Hotbar|4.75|DigExt|20030718|Q312461|H010818|inktomi|googlebawt|FAST-WebCrawler|Microsoft-WebDAV-MiniRedir|F
return 403;
}

В дополнение к предыдущей статье решил описать как настроить это дело без Apache.
Пересобираем php5 с поддержкой php-fpm

deathstar# cd /usr/ports/lang/php5
deathstar# make config
deathstar# make deinstall clean && make install clean

Настраиваем PHP-FPM
deathstar# cp /usr/local/etc/
deathstar# cp php-fpm.conf.default php-fpm.conf
deathstar# ee php-fpm.conf

И приводим примерно к такому виду

;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP's install
; prefix (/usr/local). This prefix can be dynamicaly changed by using the
; '-p' argument from the command line.

; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
; Relative path can also be used. They will be prefixed by:
; - the global prefix if it's been set (-p arguement)
; - /usr/local otherwise
;include=etc/fpm.d/*.conf

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
; Pid file
; Note: the default prefix is /var
; Default Value: none
pid = run/php-fpm.pid

; Error log file
; Note: the default prefix is /var
; Default Value: log/php-fpm.log
;error_log = log/php-fpm.log

; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
;log_level = notice

; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0

; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated. This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;emergency_restart_interval (далее…)

Зачем нужен Nginx?
Это веб-сервер, предназначенный в основном для отдачи статики и использования в качестве фронтендов. Apache при этом можно использовать в качестве бэкенда для генерации динамического контента.

Ставим Apache:

cd /usr/ports/www/apache22
make config
make install clean

Ставим Nginx:

cd /usr/ports/www/nginx
make config
make install clean

Настройка Nginx
Отредактируем файл /usr/local/etc/nginx/nginx.conf

user www www;
worker_processes 3;
error_log logs/error.log;
events {
worker_connections 1024;
use kqueue;
}

http {
include mime.types;
default_type application/octet-stream;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
keepalive_timeout 2m;
sendfile on;

upstream backend {

server 127.0.0.1:88;
}

server {
listen 80;
server_name deathstar.name;
client_max_body_size 101M;
location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|swf|js)$ {
root /home/deathstar/www/;
}

location ~ /\.ht {
deny all;
}

location / {
proxy_pass https://deathstar.name:88/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

proxy_connect_timeout 120;
proxy_send_timeout 120;
proxy_read_timeout 180;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {

root /usr/local/www/nginx-dist;
}
}
}

Добавляем nginx_enable=»YES в /etc/rc.conf и выполняем

/usr/local/etc/rc.d/nginx restart

Настройка Apache
Редактируем файл (далее…)