пятница, 30 октября 2015 г.

Установка нескольких версий Redmine с конкретными версиями ruby (nginx + passenger + rvm + Ubuntu 14.04)


Статья недоработана, но в плане справочной уже вполне себе :-)

 

Установка Nginx и Passenger


Установим PGP-ключ:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7

Добавим поддержку HTTPS для APT (APT репозиторий Phusion Passenger хранится на HTTPS-сервере):
sudo apt-get install apt-transport-https ca-certificates

Добавим сам репозиторий. В /etc/apt/sources.list.d/passenger.list поместим:
deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main

Затем установим соответствующие права и обновим списки пакетов:
sudo chown root: /etc/apt/sources.list.d/passenger.list
sudo chmod 600 /etc/apt/sources.list.d/passenger.lis
sudo apt-get update

Установим Nginx и Passenger:
sudo apt-get install nginx-extras passenger

Раскомментируем passenger_root и passenger_ruby в конфиге nginx: /etc/nginx/nginx.conf.

Перезапустим nginx:
sudo service nginx restart
 
Настроим nginx (пример): 
cat /etc/nginx/sites-available/redmine-test 
server {
  listen  8080;
  server_name project-t.centrofinans.ru;
  root /opt/redmine-3.1/public;
  passenger_user www-data;
  passenger_group www-data;
  passenger_enabled on;
  passenger_ruby /usr/local/rvm/gems/ruby-1.9.3-p551/wrappers/ruby;
  allow all;
  client_max_body_size      10m; # Max attachemnt size
}


Установка RVM и Rails


RVM нам нужен по нескольким причинам. Во-первых, велика вероятность, что в репозиториях убунты нету версии Ruby, которую вы используете в своём проекте. Во-вторых, через него удобнее установить Rails (чем через gem install rails), т.к. он подтягивает необходимые пакеты автоматически. В-третьих, если на сервере будет висеть несколько проектов, то вероятно, что они будут использовать разные версии Ruby, и тут нам поможет RVM.

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable --rails

После установки нужно выйти и зайти в шелл.

P.S. Если где-то в окружении не хватает rvm или rails, выполним "source /usr/local/rvm/scripts/rvm" или пропишем эту строку в profile (~/.profile или для всех /etc/profile).

 Нам нужна версия руби:


$ rvm install 1.9.3
 
Для удобства создадим для каждого проекта свой набор гемов:
$ rvm use 1.9.3
$ rvm gemset create redmine-3.1
 
Для того, чтобы rvm автоматически переключался на нужную версию руби и набор гемов делаем следующее:

$ echo "rvm use 1.9.3@redmine-3.1" > /opt/redmine-3.1/.rvmrc
 
Теперь в консоли при смене каталога проекта будет автоматически подключена нужная версия руби и набор 
гемов для проекта. 


Установка Redmine


cd /opt
svn co http://svn.redmine.org/redmine/branches/3.1-stable redmine-3.1
cd /opt/redmine-3.1
 
 
Чтобы указать необходимую версию Ruby выполним:

rvm use <версия Ruby>
passenger-config --ruby-command

На строке с префиксом "To use in Nginx :" скопируем оставшуюся часть и добавим в соответствующую запись server конфигурации nginx, завершив точкой с запятой (пример выше).



Add following lines
production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: redmine
  encoding: utf8
 

Plugins installation

Unarchive plugins to /plugins/ folder
cd /var/data/redmine bundle install

Configuring redmine

Setup redmine folder permissions

cd /var/data/redmine mkdir public/plugin_assets
chown -R www-data:www-data files log tmp public/plugin_assets config.ru chmod -R 755 files log tmp public/plugin_assets

Create database

mysql -u root -p Execute following lines to MySQL
CREATE DATABASE redmine character SET utf8; CREATE user 'redmine'@'localhost' IDENTIFIED BY 'redmine'; GRANT ALL privileges ON redmine.* TO 'redmine'@'localhost'; exit

Migrate database

cd /var/data/redmine bundle exec rake db:migrate bundle exec rake redmine:plugins

Generate session store

bundle exec rake generate_secret_token

Start web server

service nginx start

Restart Redmine

touch /var/data/redmine/tmp/restart.txt
 
 

RVM - несколько версий Ruby на одном сервере

Источник, спасибо автору.

Идея

Идея Ruby Version Manager состоит в разработке, где требуется иметь одновременно несколько версий Ruby и различные варианты Rails под ними.

Общая схема:

Представляет собой стандартную схему frontend + backend. В качестве backend выступает nginx с модулем passenger
  1. nginx (frontend) - проксирование, стандарт;
  2. nginx (backend's) - работа приложений через passenger:
    • каждый backend работает на порту 8<Ruby-version> (например, 8191, 8192);
    • каждое приложение, работая под версией Ruby, может использовать требуемый Rails (через gemset).
Сервер на котором производилась установка: Debian 5.0.8 i686.

Установка

Устанавливаем пакеты необходимые для компиляции:
apt-get install git-core git curl file   \
                gcc make automake autoconf automake1.9 \
                binutils g++ g++-multilib checkinstall
apt-get install libssl-dev libxslt-dev libxml2-dev
apt-get install libcurl4-openssl-dev libmysql++-dev
apt-get install libpcre3 libpcre3-dev

RVM

Установка RVM:
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
/etc/rvmrc
umask g+w
export rvm_path="/usr/local/rvm"
export rvm_source_path="${rvm_path}/src"
export rvm_log_path="${rvm_path}/log"
export rvm_bin_path="${rvm_path}/bin"
export rvm_gems_path="$rvm_path/gems"
export rvm_tmp_path="${rvm_tmp_path:-"$rvm_path/tmp"}"
export rvm_install_on_use_flag=0
export rvm_gemset_create_on_use_flag=0
# export rvm_make_flags="-j7"
export rvm_trust_rvmrcs_flag=1
export rvm_pretty_print_flag=1
~/.bashrc
if [ -s "$HOME/.rvm/scripts/rvm" ]; then
  source "$HOME/.rvm/scripts/rvm" # This loads RVM into a shell session.
elif [ -s "/usr/local/rvm/scripts/rvm" ]; then
  source "/usr/local/rvm/scripts/rvm"
fi

Ruby в RVM

Установка Ruby:
rvm package install zlib
rvm install 1.9.1-p378 --with-zlib-dir=$rvm_path/usr
rvm install 1.9.2-p180 --with-zlib-dir=$rvm_path/usr
Проверка выбора Ruby
# rvm --default use 1.9.1
# rvm list

rvm rubies
=> ruby-1.9.1-p378 [ i386 ]
   ruby-1.9.2-p180 [ i386 ]

Системный Passenger

Сборка и установка passenger:
cd /usr/local/src
wget http://rubyforge.org/frs/download.php/74471/passenger-3.0.5.tar.gz
tar -xzvf ./passenger-3.0.5.tar.gz
mv -f passenger-3.0.5 /usr/local/
Passenger установлен в /usr/local/passenger-3.0.5

Поддержка SSL в Ruby

Добавление поддержки SSL:
rvm gem install rack
rvm package install openssl
rvm use ruby-1.9.1-p378
cd /usr/local/rvm/src/ruby-1.9.1-p378/ext/openssl/
ruby extconf.rb
make
make install 
rvm use ruby-1.9.2-p180
cd /usr/local/rvm/src/ruby-1.9.2-p180/ext/openssl/
ruby extconf.rb
make
make install

Сборка backend (nginx + passenger-module)

Собираем nginx с модулем passenger. Исходники помещаем в /usr/local/src :
cd /usr/src
wget http://sysoev.ru/nginx/nginx-1.0.2.tar.gz
tar xzvf nginx-1.0.2.tar.gz
Далее необходимо скачать и развернуть исходники pcre-8.10
cd /usr/local/src/nginx-1.0.2
Сконфигурировать сборку:
sh ./configure \
 --prefix='/usr/local/nginx' \
 --with-http_ssl_module  \
 --with-pcre='/usr/local/src/pcre-8.10' \
 --add-module='/usr/local/passenger-3.0.5/ext/nginx' \
 --user=www-data \
 --group=www-data \
 --error-log-path=/var/log/nginx-rb/error.log \
 --pid-path=/var/run/nginx-rb.pid \
 --lock-path=/var/lock/nginx-rb.lock \
 --http-client-body-temp-path=/var/lib/nginx-rb/body \
 --http-proxy-temp-path=/var/lib/nginx-rb/proxy \
 --http-fastcgi-temp-path=/var/lib/nginx-rb/fastcgi \
 --with-http_ssl_module \
 --with-http_dav_module \
 --with-http_gzip_static_module \
 --with-http_stub_status_module \
 --without-mail_pop3_module \
 --without-mail_smtp_module \
 --without-mail_imap_module
В результате подготовлена сборка nginx-ruby-backend в каталог /usr/local/nginx Выполнить сборку debian-пакета:
checkinstall -D make install
Указать имя пакета "nginx-rb" и описание пакета "Nginx-1.0.2 (backend) with passenger-3.0.5 module"

Настройка

frontend

Стандартная настройка. Варианты проксирования:
  1. по количеству backends/приложений;
  2. "универсально" - в зависимости от $request_uri/$server_name переводить на тот или иной upstream.
Второй вариант потребует меньше конфигураций и изменений во frontend.

backend

На примере backend ruby-1.9.2. Настроим для запуска дополнительный экземпляр nginx-backend:
/usr/local/nginx/etc/nginx-rb-192.conf:
  • пути к pid/лог-файлам;
  • пути к sites-enabled;
  • порт листинга (например, 8192 = 8<ruby-version>);
  • глобальные настройки passenger/ruby:
      http {
          ...
          passenger_root /usr/local/passenger-3.0.5;
          passenger_ruby /path-to-ruby;
          ...
      }
    
Узнать путь к конфигурационному файлу nginx-rb-192.conf (pass-to-ruby):
# rvm use ruby-1.9.2-p180 && which ruby
/etc/init.d/nginx-rb-192:
Включить в автозапуск:
# update-rc.d nginx-rb-192 defaults

Passenger

В конфигурации виртуального хоста backend необходимо указать (минимально):
server {
    listen          8192;
    server_name     <app_name>.domain.tld;
    root            /home/applications/<app_name>/prod/bin/public;
    rails_env       production;
    passenger_user  <app_name_user>;
    passenger_group <app_name_user>;
    passenger_enabled on;
}

Ruby

Gemsets

Принципиально возможно использовать несколько версий Rails под каждой развернутой Ruby. Достигается это манипуляциями с RVM/Gemset. Пример. Для Ruby-1.9.2 необходимо иметь rails-2.3.5 и rails-3.0.5 Формируем 2 gemset'а:
# rvm ruby-1.9.2-p180
# rvm gemset create rails235 rails305
ERROR: Gemset 'rails305' does not exist, rvm gemset create 'rails305' first.
'rails235' gemset created (/usr/local/rvm/gems/ruby-1.9.2-p180@rails235).
'rails305' gemset created (/usr/local/rvm/gems/ruby-1.9.2-p180@rails305).
Ошибка в выводе не принципиальна, появляется не всегда.
В итоге под ruby-1.9.2 имеется 3 gemset'а:
  • global - набор по-умолчанию (gem'ы из него автоматически доступны из всех наборов)
  • rails235
  • rails305
В дальнейшем возможны следующий манипуляции:
  • в global устанавливать gem'ы, необходимые для базовой поддержки приложений (не требующие вариаций по версиям и т.п.);
  • в railsNNN - устанавливать непосредственно rails требуемой версии и связанные с ним gem'ы.
Возможно более разветвленное дерево gemset'ов (в данной статье не рассматривается). Установка gem в gemset (важен выбор назначения — ruby-<version>@<gemset>):
# rvm 1.9.2-p180@rails305
# gem install rails -v 2.3.5
# rvm 1.9.2-p180@rails306
# gem install rails -v 3.0.5
Информация по выбранному gemset'у:
# rvm gemset list
gemsets for ruby-1.9.2-p180 (found in /usr/local/rvm/gems/ruby-1.9.2-p180)
   global
   rails235
=> rails305

Приложения

Для использования возможностей RVM необходимо выдержать следующую схему размещения приложений:
Структура каталогов: /home/applications/<app_name>/<app_type> - корневой каталог (app_root) - домашний каталог пользователя-владельца приложений;
/home/applications/<app_name>/<app_type>/bin - каталог приложения (app_home) В каталогах создать (dot)rvmrc — файлы:
  • для app_root (непосредственно позволяет использовать RVM):
    rvm_path="/usr/local/rvm"
    rvm_trust_rvmrcs_flag=1
    rvm_install_on_use_flag=1
    
  • для app_home (позволяет автоматически выбирать при входе в этот каталог версию Ruby и, при необходимости, gemset под RVM):
    #!/usr/bin/env bash
    environment_id="ruby-1.9.2-p180@rails305"
    if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
      && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] ; then
      \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
    
      [[ -s ".rvm/hooks/after_use" ]] && . ".rvm/hooks/after_use"
    else
      rvm --create use "$environment_id"
    fi
    
Собственно выбор версии - environment_id. В app_home, в configure/ поместить файл setup_load_paths.rb:
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
  begin
    rvm_path     = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
    rvm_lib_path = File.join(rvm_path, 'lib')
    $LOAD_PATH.unshift rvm_lib_path
    require 'rvm'
    RVM.use_from_path! File.dirname(File.dirname(__FILE__))
  rescue LoadError
    # RVM is unavailable at this point.
    raise "RVM ruby lib is currently unavailable."
  end
end
# Select the correct item for which you use below.
# If you're not using bundler, remove it completely.
# If we're using a Bundler 1.0 beta
ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
require 'bundler/setup'
# Or Bundler 0.9...
if File.exist?(".bundle/environment.rb")
  require '.bundle/environment'
else
  require 'rubygems'
  require 'bundler'
  Bundler.setup
end

Контроль

Nginx

Штатные методы, с учетом наличия нескольких экземпляров.

Ruby

Вывод текущей версии Ruby:
# rvm list
Вывод текущего gemset:
# rvm gemset list
Вывод списка установленных gem:
# rvm gem list

Rails

Для перезапуска rails-процесса достаточно сделать в каталоге приложения:
# touch tmp/restart.txt

Passenger

Проверка статуса passenger:
  • /usr/local/passenger-3.0.5/bin/passenger-status
    
    Выдает несколько PID (по количеству backends);
  • /usr/local/passenger-3.0.5/bin/passenger-status <PID>
    
    Выдает статус rails-процессов по выбранному backend.

Ограничения

GEM могут быть установлены только от привилегированного пользователя. Для установки gem от имени непривилегированного пользователя требуется доработка.

Литература

  1. Phusion Passenger users guide, Nginx version
  2. NGINX
  3. Using RVM rubies with Passenger

пятница, 16 октября 2015 г.

Примеры использования nmap — сканера портов

Источник информации тут: = IT word =

Несколько примеров использования nmap.
TCP-Сканирование.
Методом TCP connect nmap будет сканировать диапазон портов (1-65535) компьютера с IP-адресом, опция -sV служит для получения версий запущенных сервисов:

$ nmap -sV ххх.ххх.ххх.ххх -p 1-65535
Так же стоит обратить внимания что у нас в поле SERVICE и STATE.
В поле SERVICE — всегда отображается значение из файла /etc/services, соответствующее номеру порта. Это отнюдь не означает, что по данному порту будет запущен тот сервис, который указан в поле SERVICE. Можно запустить Web-сервер по 22 порту, а сервер SSH — по 80, но nmap все будет писать, что 22 порт — это ssh, a 80 — это HTTP.
В поле STATE — В одном случае порт ssh открыт (open), другом — отфильтрован (filtered). Значение Filtered значит, что порт отклоняет (reject) или отбрасывает (drop) трафик. Это не говорит о том, запущен ли на этом порту сервис или нет.
UDP-сканирование.
UDP-порты надо обязательно сканировать. При поиске уязвимостей UDP-сервисы обычно упускают из виду, но многие UDP-сервисы (echo, chargen, DNS — работает как по TCP, так и по UDP, а также RPC (Remote Procedure Call)) работают по протоколу UDP. Некоторые из них известны своим огромным списком эксплоитов, позволяющим получить права root’a. UDP-сканирование делается с помощью опции -sU сканера nmap:

$ nmap -sU xxx.xxx.xxx.xxx -p 1-65535
Время сканирования UDP-портов довольно большое примерно 1 секунда на порт.Отчего так долго ? Система ограничила отправку ICMP-ответов: не более 1 в секунду. При UDP-сканировании нужно использовать опцию -Т. Она позволяет указать агрессивность сканирования. Есть 6 скоростей сканирования: Paranoid, Sneaky, Polite, Normal, Aggressive и Insane ( -T Polite). Первая скорость самая медленная, последняя — самая быстрая.

Описания методов типов сканирования.
-sT — сканирование TCP портов в обычном режиме. Сканирование происходит на основе функции connect() присутствующей во всех полноценных ОС. Если соединение с удалённым портом установлено, то данный порт открыт, иначе порт закрыт либо фильтруется.
-sS — использование метода TCP CYN. Это так называемое стелс сканирование. Nmap отправляет на удалённый порт SYN-пакет и ожидает ответа. В зависимости от ответа определяется состояние порта. При этом полноценное соединение не устанавливается. Благодаря этому определить факт сканирования очень сложно. Для запуска этого метода требуются рутовские привилегии на Вашей тачке.
-sF,-sX,-sN (scan FIN, scan Xmas, scan NULL) — эти совместные методы используется например если если не помогло -sS или -sT сканирование.
-sU — сканирование UDP портов. На удалённый порт отправляется UDP-пакет и ожидается ответ. Если ответ содержит ICMP-сообщение «порт недоступен» значит порт закрыт либо режется файерволом, иначе порт открыт. Для запуска опять же требуются рутовские привилегии на вашем компе.
-sО — похоже на -sU, только для IP портов.
-sR — использование RCP-сканированиея. Этот метод позволяет определить прогу обслуживающую RCP-порт и её версию. При этот если на удалённом серваке установлен файервол, Nmap его пробивает не оставляя логов.
-sP — ping-сканирование. Данный метод позволяет узнать все адреса активных хостов в сети. Nmap отправляет на указанный IP ICMP-запрос, если в сети есть активные хосты, они отправят нам ответ, тем самым указав на свою активность. Если Вы пингуете сети лучше не указывать больше никаких методов сканирования.
Описания некоторых опций.
Они служат для тонкой настройки сканирования и задания дополнительных функций. Опции не обязательны, работа сканера будет нормальной и без них. Но все они будут полезны в том или ином случае. Основные опции:
-O — так называемый режим «снятия отпечатков» TCP/IP для определения удалённой ОС (OS fingerprints). Работает это следующим образом: Nmap отправляет удалённой системе запросы и в зависимости от ответов («отпечатков» стека) определяется ОС и её версия.
-p «диапазон» — сканирование определённого диапазона портов. Например: ‘-p 21, 22, 25, 80, 31337’. Это уменьшает время сканирования за счёт уменьшения диапазона портов.
-F — сканирование стандартных портов записанных в файл services (1-1024). Это так называемое быстрое сканирование.
-P0 — отмена ping-опросов перед сканированием портов хоста. Полезна в тех случаях, если Вы сканируете сети типа microsoft.com, так как в них ICMP-запрос режется файерволом.
-6 — сканирование через протокол IPv6. Работает значительно быстрее чем через IPv4.
-T «Paranoid|Sneaky|Polite|Normal|Aggressive|Insane» — настройка временных режимов. При «Paranoid» сканирование будет длиться очень долго, но тогда у Вас больше шансов остаться не обнаруженными скан-детекторами. И наоборот «Insane» используёте при сканировании быстрых либо слабо защищённых сетей.
-oN/-oM «logfile» — вывод результатов в logfile в нормальном (-oN) или машинном (-oM) виде.
-oS «logfile» — эта опция позволяет возобновить сканирование если оно было по каким-либо причинам прервано и результат записывался в файл (была включена опция -oN «logfile» или -oM «logfile»). Для продолжения работы нужно запустить Nmap с указанием только этой функции и файла в которой записывалось предыдущее сканирование («logfile»).
-D «host_1, host_2,…,host_n» — это очень полезная функция. Она позволяет запутать удалённую систему и сделать видимость что её сканируют с нескольких хостов («host_1, host_2,…,host_n»), тем самым стараясь скрыть Ваш реальный адрес.

Еще примеры:
nmap -A -T4 192.168.100.123
— самый распространенный метод сканирования.
nmap -sS -O -p 21, 25, 80 www.site.com
— сканируем www.site.com проверяем только 21, 25, 80 порты, используем определение удалённой ОС (метод OS fingerprints) и стелс сканирование.
nmap -sT -F -P0 -oN scan.txt www.site.com
-сканируем www.site.com применяем обычное сканирование стандартных портов (1-1024), с отменой ping-опросов и заносим результат в файл scan.txt
nmap -sU -D 143.121.84.12 132.154.156.6 localhost www.site.com
— сканируем www.site.com проводим сканирование UDP-портов, при этом маскируемся двумя хостами (третий наш).
Дополнительно можно почитать Сетевой сканер Nmap. Руководство пользователя.

пятница, 2 октября 2015 г.

StorageServerTuning

Source!

Tips and Recommendations for Storage Server Tuning


Here are some tips and recommendations on how to improve the performance of your storage servers. As usual, the optimal settings depend on your particular hardware and usage scenarios, so you should use these settings only as a starting point for your tuning efforts.

Note: Some of the settings suggested here are non-persistent and will be reverted after the next reboot. To keep them permanently, you could add the corresponding commands to /etc/rc.local, use /etc/sysctl.conf or create udev rules to reapply them automatically when the machine boots.

Partition Alignment & RAID Settings of Local File System


To get the maximum performance out of your RAID arrays and SSDs, it is important to set the partition offset according to the native alignment. See here for a walk-through about partition alignment and creation of a RAID-optimized local file system: Partition Alignment Guide

A very simple and commonly used method to achieve alignment without the challenges of partition alignment is to completely avoid partitioning and instead create the file system directly on the device, e.g.:
 
$ mkfs.xfs /dev/sdX

Storage Server Throughput Tuning


In general, BeeGFS can be used with any of the standard Linux file systems.

Using XFS for your storage server data partition is generally recommended, because it scales very well for RAID arrays and typically delivers a higher sustained write throughput on fast storage, compared to alternative file systems. (There also have been significant improvements of ext4 streaming performance in recent Linux kernel versions).

However, the default Linux kernel settings are rather optimized for single disk scenarios with low IO concurrency, so there are various settings that need to be tuned to get the maximum performance out of your storage servers.

Formatting Options
Make sure to enable RAID optimizations of the underlying file system, as described in the last section here: Create RAID-optimized File System

While BeeGFS uses dedicated metadata servers to manage global metadata, the metadata performance of the underlying file system on storage servers still matters for operations like file creates, deletes, small reads/writes, etc. Recent versions of XFS (similar work in progress for ext4) allow inlining of data into inodes to avoid the need for additional blocks and the corresponding expensive extra disk seeks for directories. In order to use this efficiently, the inode size should be increased to 512 bytes or larger.

Example: mkfs for XFS with larger inodes on 8 disks (where the number 8 does not include the number of RAID-5 or RAID-6 parity disks) and 128KB chunk size:
 
$ mkfs.xfs -d su=128k,sw=8 -l version=2,su=128k -isize=512 /dev/sdX
Mount Options
Enabling last file access time is inefficient, because it means that the file system needs to update the timestamp by writing data to the disk even though the user only actually read file contents or even when the file contents were already cached in memory and actually no disk access would have been necessary at all. (Note: Recent Linux kernels have switched to a new "relative atime" mode, so setting noatime might not be necessary in these cases.)
If your users don't need last access times, you should disable them by adding "noatime" to your mount options.

Increasing the number of log buffers and their size by adding logbufs and logbsize mount options allows XFS to generally handle and enqueue pending file and directory operations more efficiently.

There are also several mount options for XFS that are intended to further optimize streaming performance on RAID storage, such as largeio, inode64, and swalloc.

If you are using XFS and want to go for optimal streaming write throughput, you might also want to add the mount option allocsize=131072k to reduce the risk of fragmentation for large files.

If your RAID controller has a battery-backup-unit (BBU), adding the mount option nobarrier for XFS or ext4 can significantly increase throughput.

Example: Typical XFS mount options for an BeeGFS storage server with a RAID controller battery:
 
$ mount -onoatime,nodiratime,logbufs=8,logbsize=256k,largeio,inode64,swalloc,allocsize=131072k,nobarrier /dev/sdX <mountpoint>
 
 
IO Scheduler

First, set an appropriate IO scheduler for file servers:
$ echo deadline > /sys/block/sdX/queue/scheduler


Now give the IO scheduler more flexibility by increasing the number of schedulable requests:
$ echo 4096 > /sys/block/sdX/queue/nr_requests


To improve throughput for sequential reads, increase the maximum amount of read-ahead data. The actual amount of read-ahead is adaptive, so using a high value here won't harm performance for small random access.
$ echo 4096 > /sys/block/sdX/queue/read_ahead_kb



Virtual memory settings

To avoid long IO stalls (latencies) for write cache flushing in a production environment with very different workloads, you will typically want to limit the kernel dirty (write) cache size:
 
$ echo 5 > /proc/sys/vm/dirty_background_ratio
$ echo 10 > /proc/sys/vm/dirty_ratio
Only for special use-cases: If you are going for optimial sustained streaming performance, you may instead want to use different settings that start asynchronous writes of data very early and allow the major part of the RAM to be used for write caching. (For generic use-cases, use the settings described above, instead.)
 
$ echo 1 > /proc/sys/vm/dirty_background_ratio
$ echo 75 > /proc/sys/vm/dirty_ratio
Assigning slightly higher priority to inode caching helps to avoid disk seeks for inode loading:
 
$ echo 50 > /proc/sys/vm/vfs_cache_pressure
Buffering of file system data requires frequent memory allocation. Raising the amount of reserved kernel memory will enable faster and more reliable memory allocation in critical situations. Raise the corresponding value to 64MB if you have less than 8GB of memory, otherwise raise it to at least 256MB:
 
$ echo 262144 > /proc/sys/vm/min_free_kbytes
 
 Transparent huge pages can cause performance degradation under high load, due to the frequent change of file system cache memory areas. For RedHat 6.x and derivatives, it is recommended to disable transparent huge pages support, unless huge pages are explicity requested by an application:
$ echo madvise > /sys/kernel/mm/redhat_transparent_hugepage/enabled
$ echo madvise > /sys/kernel/mm/redhat_transparent_hugepage/defrag

With recent mainline kernel versions:

$ echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
$ echo madvise > /sys/kernel/mm/transparent_hugepage/defrag
 
Controller Settings

Optimal performance for hardware RAID systems often depends on large IOs being sent to the device in a single large operation. Please refer to your hardware storage vendor for the corresponding optimal size of /sys/block/sdX/max_sectors_kb. It is typically good if this size can be increased to at least match your RAID stripe set size (i.e. chunk_size x number_of_disks):
 
$ echo 1024 > /sys/block/sdX/queue/max_sectors_kb
Furthermore, high values of sg_tablesize (/sys/class/scsi_host/*/sg_tablesize) are recommended to allow large IOs. Those values depend on controller firmware versions, kernel versions and driver settings.

System BIOS & Power Saving

To allow the Linux kernel to correctly detect the system properties and enable corresponding optimizations (e.g. for NUMA systems), it is very important to keep your system BIOS updated.

The dynamic CPU clock frequency scaling feature for power saving, which is often enabled by default, has a high impact on latency. Thus, it is recommended to turn off dynamic CPU frequency scaling. Ideally, this is done in the machine BIOS (see Intel SpeedStep or AMD PowerNow), but it can also be done at runtime, e.g. via:
 
$ echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor >/dev/null