Практический Debian

Практическое использование Debian

Grunt

Введение

Надоело мне как-то перепроверять все CSS-файлы при изменении дизайна. Поискав немного, я остановился на LESS. Вместо того, чтобы управлять одним огромным файлом styles.css, LESS позволяет создать множество мелких файлов, каждый из которых отвечает за свою часть общей таблицы стилей. Однако, собирать всё вручную мне было лень, поэтому я решил для своего проекта использовать Grunt. Для него есть множество модулей, которые способны сильно облегчить жизнь Web-разработчика, в частности, компилировать множество LESS файлов автоматически, собирать и сжимать JavaScript'ы и т.д.

В данной статье пойдёт рассказ о том, зачем нужен Grunt, показаны примеры его использования и базовой настройки, а также мимоходом захвачено использование LESS для разработки каскадных таблиц стилей.

Для проекта, над которым я работаю, было принято решение создать в корневом каталоге папку /less, куда поместить следующие файлы:

  • bootstrap.less - объединяет в себе все остальные файлы. Изменяя содержимое этого файла легко управлять результирующей таблицей стилей.
  • colors.less - содержит переменные, описывающие цвета, используемые на страницах, например, @red: #FF0000;.
  • fonts.less - описывает используемые на страницах шрифты. В своём проекте я решил использовать символьный шрифт FontAwesome вместо того, чтобы рисовать иконки.

а также по одному файлу на каждый отдельный блок, например, визуальный компонент или целую страницу.

Установка

Целевой системой сегодня будет не Debian, а Windows 8. Установка всех средств в Debian, кроме NodeJS, производится аналогично - командами в консоли. Если хотите NodeJS в Debian Wheezy - прочитайте вот эту статью.

Скачиваем установщик с сайта проекта NodeJS и запускаем, при установке не забываем указать, что нам также понадобится менеджер пакетов (Node Package Manager - NPM).

Настройка проекта для использования Grunt

Существует два способа установки Grunt'а - глобально и локально, в проект. Я рекомендую сам Grunt установить глобально, а необходимые модули - в папку проекта. Её всегда можно добавить в исключения вашей СКВ.

Запускаем командную строку от имени администратора и вводим следующие команды:

npm install grunt -g
npm install grunt-cli -g

Первый пакет - это собственно Grunt, второй - утилиты командной строки, позволяющие работать с ним. Ключ -g означает, что установленные пакеты должны быть доступны глобально.

Перейдём в каталог нашего проекта (вместо %project_root_folder% подставьте нужное) и инициализируем его для использования Grunt'а:

cd %project_root_folder%
grunt init

Будет задано несколько вопросов, касающихся проекта, в частности, имя автора, версия, лицензия и т.д. На основе ответов будет составлен файл package.json, который при необходимости всегда можно изменить. например, в моём проекте он выглядит вот так:

{
  "name": "tester",
  "version": "0.0.0",
  "description": "Система тестирования",
  "main": "index.html",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Dunaevsky Maxim",
  "license": "MIT",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-concat": "^0.5.0",
    "grunt-contrib-less": "^0.11.4",
    "grunt-contrib-uglify": "^0.5.1"
  }
}

Теперь нам нужно будет установить необходимые модули, я ограничусь всего тремя:

  • concat - собирает несколько указанных файлов в один.
  • less - компилирует LESS-файлы в каскадные таблицы стилей CSS.
  • uglify - оптимизирует и сжимает JavaScript-код.

Установка производится очень просто:

npm install grunt-contrib-concat --save-dev
npm install grunt-contrib-less --save-dev
npm install grunt-contrib-uglify --save-dev

Ключ --save-dev означает, что пакеты должны быть также прописаны в файле package.json.

Пакеты установлены, самое время дать Grunt'у задание - скомпилировать LESS-файлы, склеить вместе все JavaScript'ы из каталога /src/ и сжать итоговый файл. Для этого нам понадобится файл Gruntfile.js. Обратите внимание, первая буква в названии файла должна быть большой. Создать его следует в корневом каталоге проекта.

Рассмотрим Gruntfile.js, которым пользуюсь я сам:

"use strict";
module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        less: {
            dev: {
                files: {
                    'css/styles.css': 'less/bootstrap.less'
                }
            },
            min: {
                options: {
                    ieCompat: true,
                    compress: 2,
                    optimization: true
                },
                files: {
                    'css/styles.min.css': 'less/bootstrap.less'
                }
            }
        },
        concat: {
            js: {
                src: [
                    'src/*.js'
                ],
                dest: 'js/ui.js'
            }
        },
        uglify: {
            build: {
                src: 'js/ui.js',
                dest: 'js/ui.min.js'
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask('default', ['less:dev', 'concat:js', 'uglify']);
};

Первым делом определяются настройки для задач, а также указывается, откуда брать информацию о проекте (файл package.json).

Задание для сборки CSS из LESS-файлов содержит две секции - настройки для разработки (dev) и для релиза (min), когда важен маленький размер файла и оптимизация кода. В обоих заданиях указано, что нужно на основе файла bootstrap.less из каталога less собрать файл styles.css в каталоге css.

Задание для concat'а небольшое - ему нужно всего навсего взять все js-файлы в каталоге src и склеить в один - ui.js, положив его в каталог js.

Самое последнее задание - оптимизация и сжатие получившегося при склеивании файла с помощью утилиты uglify.

В конце файла производится загрузка необходимых модулей и выполнение их в порядке перечисления аргументов функции grunt.registerTask. Изменяя порядок следования аргументов можно управлять процессом сборки.

Закончив редактирование файла Gruntfile.js, запустите командую строку в текущем каталоге и выполните команду grunt. В случае ошибки в конфигурации или одном из файлов проекта будет выдано соответствующее сообщение. В противном случае вывод на экран будет выглядеть примерно так:

Running "less:dev" (less) task
File css/styles.css created: 0 B → 251 B

Running "concat:js" (concat) task
File js/ui.js created.

Running "uglify:build" (uglify) task

Done, without errors.

Минимальная настройка SSH в Debian

Цели

В этой статье я расскажу о минимальных настройках, необходимых для того, чтобы на вашем сервере заработала служба OpenSSH, позволяющая удалённо подключаться к нашей машине и выполнять нужные команды. Кроме того, будут рассмотрены вопросы использования ключей для доступа к серверу.

Все действия выполняются от имени root, если это не оговорено особо.

Установка пакетов

Установить сервер OpenSSH в Debian очень просто:

apt-get install openssh-server -y

Вместе с самим сервером ставится несколько зависимостей. В моём случае (Debian 7.5) это openssh-client и ncurses-term.

Служба сервера sshd будет автоматически запущена после установки. Обращаться к ней в терминале следует по имени ssh:

service ssh start
service ssh stop
service ssh restart

Минимальная настройка

Все найстроки сервера OpenSSH хранятся в файле /etc/ssh/sshd_config. Откроем его для редактирования и рассмотрим минимально необходимые опции, которые не рекомендуется трогать либо наоборот настоятельно рекомендуется изменить.

  • Port 22 - лучше всего сразу сменить порт на другой, однако, номер порта желательно выбрать больше 1024, чтобы случайно не создать конфликт с какой-нибудь другой программой, работающей на этом порту.
  • ListenAddress 0.0.0.0 - по умолчанию закомментировано. Можно указать, какой интерфейс должен слушать наш сервер. Если на сервере несколько интерфейсов, один из которых торчин наружу, например, предоставляет доступ к WEB-серверу, а работа с сервером будет производиться только из внутренней сети, я советую указать здесь адрес сервера во внутренней сети, чтобы заблокировать доступ из Интернета.
  • UsePrivilegeSeparation yes - ни в коем случае не отключать разделение привилегий!
  • LoginGraceTime 120 - время в секундах, в течение которого следует авторизоваться на сервере. По истечение указанного интервала сервер автоматически разорвёт соединение.
  • PermitRootLogin yes - настоятельно рекомендую сменить на no! Пользователь root не должен подключаться к серверу! Для выполнения команд, требующих повышения привилегий, следует использовать sudo!
  • PubkeyAuthentication yes - включаем, т.к. дальше будет рассматриваться использование публичных ключей для подключения к серверу.
  • AuthorizedKeysFile %h/.ssh/authorized_keys - следует раскомментировать для доступа с помощью открытых ключей шифрования. По умолчанию эта настройка указывает на то, что открытые ключи каждого пользователя следует искать в его домашнем каталоге, в файле authorized_keys, лежащем в подкаталоге .ssh.

Изменив эти минимальные настройки, перезапустите сервер.

Проверка работоспособности

Попробуйте подключиться к своему серверу с него самого:

ssh user@localhost

где user - ваш настоящий логин в системе.

При самом первом подключении ваш SSH-клиент будет спрашивать, следует ли доверять указанному хосту и принять от него ключ шифрования. Отвечаем yes (нужно написать слово полностью). Сервер предложит ввести пароль для авторизации в системе. Вводим его. Если всё правильно, вы окажетесь в консоли, где сможете вводить команды.

Генерация и размещение ключей

Генерация ключей

При шифровании с открытым ключом потребуется создать пару из двух ключей - открытого и закрытого. В *nix-системах стандартным средством для их генерации является программа ssh-keygen. Запуск её с различными параметрами приводит к созданию различных ключей. В нашем случае будет использован минимум настроек.

Запустите в терминале команду указанную ниже команду для создания ключа длиной 2048 бит и с комментарием "New generated key". Я советую добавить комментарий для ключа - в этом случае при подключении с его помощью в логах сервера будет отображаться этот комментарий. Можете ввести сюда свои имя и фамилию.

ssh-keygen -b 2024 -C "New generated key"

Система предложит указать имя для новых файлов. Для примера будем использовать new_key

Затем будет задан вопрос, какая парольная фраза будет использоваться для ключа. Если не заполнять это поле, то ключ не будет защищён паролем. Рекомендую ввести сюда что-нибудь. После первого ввода парольной фразы будет предложено ввести её ещё раз.

После этого в текущем каталоге (если вы ввели имя файла выше) будут созданы два файла - new_key и new_key.pub

Файл new_key - это закрытый ключ. Его нужно сохранить в надёжное место на вашем компьютере и не давать никому.

Файл new_key.pub - это открытый ключ. Его также следует сохранить на вашем компьютере, однако, именно его следует распространять на серверах, к которым вы будете подключаться.

Размещение ключей на целевой системе

Если в домашнем каталоге пользователя не существует каталога .ssh, создайте его, а внутри него разместите пустой файл authorized_keys.

    cd ~
    mkdir .ssh
    cd .ssh/
    touch authorized_keys

Теперь в этот файл мы добавим наш открытый ключ с помощью стандартной команды >>

    cat ~/new_key.pub >> authorized_keys

Теперь следует скопировать закрытый ключ на ваш компьютер. Его мы будем использовать для подключения к нашему серверу.

Использование закрытых ключей и Putty

Формат закрытых ключей, используемых программой Putty, несколько отличается от того, который используется в *nix-системах. Тем не менее, в комплекте идёт программа puttygen. Запустите её.

В меню выберите пункт Conversion, а в нём - Import key.

Найдите ваш закрытый ключ и откройте его.

Если ранее вы указали парольную фразу, сейчас её нужно будет ввести для открытия ключа.

Нажмите кнопку Save private key

Дайте подходящее имя закрытому ключу и сохраните его куда-нибудь. Как видите, формат файла изменился - теперь он ppk

Создайте в Putty новое подключение. В настройках найдите пункт Auth. На этой странице в поле Private key file for authentication выберите сохранённый ключ.

Сохраните подключение.

Нажмите Open

Теперь при подключении вам нужно будет вводить не пароль пользователя системы, а пароль от вашего ключа. Удобство заключается в том, что можно создать один публичный ключ и разместить его на десятке серверов. Теперь вместо того, чтобы помнить 10 разных паролей, достаточно помнить всего один и хранить его и секретный ключ в надёжном месте, исключающем доступ посторонних лиц.

Использование ключей для авторизации не отменяет ввода пароля пользователя при вызове команды sudo!

Настройка Redmine на Debian 7

Установка и настройка Redmine в Debian 7 (nginx + postgresql + thin)

В данной статье рассматривается установка и настройка Redmine версии 1.x в Debian 7 с помощью apt. Если вам нужна инструкция по настройке Redmine версии 2.x, то эта статья не для вас.

Краткое содержание:

  • Введение
  • Список используемых пакетов.
  • Порядок установки и настройки пакетов.
    • Предварительная настройка PostgreSQL
    • Установка пакетов
    • Создание базы данных
  • Увязка Redmine с nginx через thin.

Введение

Redmine - система для управления проектами. Если говорить простым языком, эта система служит для того, чтобы можно было вести учёт обращений, заявок, багрепортов и известных проблем о каждом продукте компании. Помимо этого в системе есть встроенная Wiki, база знаний, диаграммы Ганта, разделение по проектам и ролям и т.д. Если вы работаете в фирме, которая занимается разработкой ПО, то этот или аналогичный продукт вам жизненно необходим. С помощью Redmine можно оперативно отслеживать ход работы, исправления обнаруженных ошибок и т.д. В общем, на выходе получается целый комбайн.

Список используемых пакетов

Для работы Redmine требуется установка Ruby On Rails. К нашему удовольствию разработчики Debian'а включили все необходимые пакеты в список зависимостей, значительно упростив установку. Исключение сделано лишь для двух пакетов - сервер, который будет запускать Redmine, и пакет для соединения с БД.

Ниже приведён минимальный список пакетов, которые нам потребуются:

  • thin - сервер для запуска продуктов, написанных на Ruby
  • redmine - сама система
  • ruby-pg - драйвер для подключения программ, написанных на Ruby On Rails, к СУБД PostgreSQL.

Установка Ruby будет выполнена автоматически

Предварительная настройка базы в PostgreSQL

Запустим интерпретатор psql от имени суперпользователя postgres:

sudo su -c psql postgres

Создадим нового пользователя и базу данных, к которой он будет иметь полный доступ, после чего закроем интерпретатор:

CREATE ROLE redmine WITH PASSWORD 'redmine' LOGIN;
CREATE DATABASE redmine WITH OWNER redmine;
\q

Естественно, вы можете дать пользователю и базе любое нужное имя. Кроме того, на одном сервере можно развернуть несколько экземпляров Redmine - для этого нужно будет создать несколько баз (и, возможно, пользователей) и настроить несколько конфигураций для thin, но я сейчас этого делать не буду.

Установка пакетов и настройка параметров Redmine

Установка пакетов

Для установки всех необходимых пакетов нужно от имени root выполнить команду:

apt-get install redmine ruby-pg thin -y

Во время установки менеджер пакетов предложит настроить базу данных. Отвечаем отрицательно. Базу данных лучше настраивать через правку конфигурационных файлов, т.к. установщик Redmine предлагает дать ему административный доступ к PostgreSQL.

Настройка доступа к БД

Перейдём в каталог /etc/redmine/default

cd /etc/redmine/default

Здесь находится всего два файла - database.yml и session.yml. Нам нужен только первый, отвечающий за настройки доступа к БД.

Содержимое database.yml:

production:
  adapter: postgresql
  database: redmine
  host: localhost
  port:
  username: redmine
  password: redmine
  encoding: utf8

Все настройки, полагаю, понятны без комментариев. Отмечу только, что первая строка, production:, указывает на то, что данная конфигурация должна использоваться при запуске сервера в рабочем режиме. Также доступны режимы development и test.

Настройка сервера thin

Теперь нужно настроить thin. В Debian 7 при установке thin ставятся сразу две его версии, 1.8 и 1.9.1, мы будем использовать последнюю. Переходим в каталог настроек и создаём файл для запуска Redmine:

cd /etc/thin1.9.1/
touch redmine.yml
chmod 644 redmine.yml

Открываем созданный файл в любимом текстовом редакторе и вносим туда следующие данные:

---
chdir: /usr/share/redmine
environment: production
timeout: 30
log: /var/log/thin/redmine.log
pid: /var/run/redmine/redmine.pid
max_conns: 1024
max_persistent_conns: 512
require: []

wait: 30
socket: /var/run/redmine/redmine.sock
daemonize: true
user: www-data
group: www-data
servers: 1
prefix: /redmine

socket указывает путь и имя сокетов, создаваемых thin при запуске Redmine.

Параметр servers указывает, сколько серверов следует запустить. Другими словами, он определяет количество сокетов, которые будут созданы в указанном каталоге. К имени сокета, указанному выше, будет добавлен порядковый номер.

Servers: 1

ls /var/run/redmine
redmine.sock.0

Servers: 2

ls /var/run/redmine
redmine.sock.0
redmine.sock.1

prefix указывает на то, по какому адресу на сервере будут обрабатываться запросы к Redmine. Поясню на примере. Допустим, адрес нашего сайта - http://sharkon.ru/ . При переходе к этому адресу человек будет получать главную страницу нашего сайта. Пусть при переходе по ссылке http://sharkon.ru/redmine/ открывается Redmine. Именно за часть адреса, идующую после указания доменного имени, отвечает этот параметр. Если сайт используется для внутренних нужд и не торчит наружу, можно дать ему, например, такое доменное имя: http://redmine.lo/ , прописав в настройках сервера DNS, к какой машине в локальной сети нужно подключаться для работы с этим сайтом. В этом случае строку с параметром prefix следует удалить из файла конфигурации полностью!

Настройка nginx.

В каталоге /etc/nginx/ следует создать файл proxy_params.conf. На моих серверах он выглядит примерно так:

proxy_redirect                          off;
proxy_set_header Host                   $http_host;
proxy_set_header X-Real-IP              $remote_addr;
proxy_set_header X-Url-Scheme           $scheme;
proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto      $scheme;
client_max_body_size                    20m;
client_body_buffer_size                 1m;
proxy_buffering                         off;
proxy_send_timeout                      180;
proxy_read_timeout                      180;
proxy_connect_timeout                   180;
proxy_buffer_size                       4k;
proxy_buffers                           32 32k;
proxy_busy_buffers_size                 64k;
proxy_temp_file_write_size              1m;
add_header X-Frame-Options "SAMEORIGIN";

При необходимости измените настройки, исходя из параметров вашего сервера. Указанные в примере данные хорошо себя показали на не очень мощной машине с 2 GB RAM.

В каталоге /etc/nginx/conf.d/ создадим файл redmine.conf со следующим содержимым:

upstream redmine {
        server unix:/var/run/redmine/redmine.0.sock;
}

server {
    listen 80;
    server_name sharkon.ru;
    access_log off;
    error_log /var/log/redmine/nginx_error.log;
    include /etc/nginx/proxy_params.conf;
    proxy_redirect off;

    location / {
        root /var/www/sharkon.ru;
    }
    
    location /redmine {
        root /usr/share/redmine/public;
        error_page 404 404.html;
        error_page 500 502 503 504 500.html;
        try_files $uri/index.html $uri.html $uri @redmine_server;
    }

    location @redmine_server {
        proxy_pass http://redmine;
    }
}

Здесь указано, что следует использовать для соединения с Redmine сокет, расположенный по пути /var/run/redmine/. Имя сокета формируется из строки, указанной ранее в параметрах thin плюс порядковый номер созданного сокета, начиная с нуля. Далее идёт указание имени нашего сервера и пути, по которому расположен Redmine. Все запросы к нему автоматически будут переадресовываться к созданному ранее сокету.

Миграции

Т.к. мы настраивали доступ к БД вручную, создание её структуры мы будем производить вручную. Это не сложно:

cd /usr/share/redmine
rake db:migrate RAILS_ENV=production

Права на сокет

Так как сокет для redmine будет создаваться пользователем www-data, следует сделать так, чтобы после перезагрузки системы Redmine мог создать его заново. Для этого мы сменим владельца папки с сокетами и pid-файлом.

cd /var/run
mkdir redmine
chown www-data:www-data redmine/

Кодировка CSV-файлов

По-умолчанию Redmine генерирует все отчёты в кодировке UTF-8. Пакет Microsoft Office использует кодировку Win1251, поэтому CVS-отчёт, открытый с помощью Excel, будет показывать кракозябры. Следует всего лишь в одном месте изменить настройки:

cd /usr/share/redmine/config/locale
nano ru.yml

Здесь следует найти строку:

general_csv_encoding: UTF-8

и заменить её на

general_csv_encoding: CP1251

При необходимости здесь же можно изменить и другие параметры локализации Redmine, например, перевод некоторых слов и кодировку файлов pdf.

Запуск

Все подготовительные операции выполнены, можно запустить сам Redmine и перезапустить nginx.

service thin start
service nginx restart

Redmine будет доступен по адресу http://sharkon.ru/redmine/

jQuery-плагин для отслеживания событий колёсика мыши

Частенько приходится заниматься Front-End-разработкой, поэтому JS - один из основных языков, которые я использую. Встала задача отслеживать событие, возникающее при вращении колёсика мыши.

Первым делом я нашёл вот этот плагин.

Плагин хороший, но у него есть один фатальный недостаток - его писал не я. Вторым недостатком стало его ориентирование на старую версию jQuery. Съезжать с 2.x на 1.x мне не хотелось, поэтому я написал свой плагин, который можно скачать здесь.

Особенности моего плагина:

  • можно повесить на элемент один обработчик или целый массив, при этом обработчики будут вызываться строго в указанном порядке;
  • в переменной event, которая передаётся обработчикам, присутствуют параметры dx и dy, которые указывают смещение в относительных единицах, т.е. каждая из этих переменных может быть равна только -1, 0 или 1, что исключает несовместимость между браузерами;
  • добавляет в пространство имён jQuery всего лишь два новых метода: wheel и unwheel.

Если не трудно, пожалуйста, напишите в комментариях отзывы и сообщения об ошибках.

Установка Debian на RAID-контроллер (перевод)

Введение

Решили на работе поднять собственный сервер, на котором будет располагаться служба поддержки пользователей. Начальник выделил машинку, на которой был аппаратный RAID-1. Выбор системы был предрешён изначально, но по ходу установки пришлось столкнуться с некоторыми сложностями.

Во-первых, при запуске процедуры разметки диска вместо одного НЖМД выводился список из всех имеющихся в распоряжении жёстких дисков. При этом установщик Windows видел RAID-массив как одно устройство.

Во-вторых, только на первом из этих дисков можно было создавать разделы, но не любого типа, а только определённого.

Наконец, при установке всё шло хорошо до этапа конфигурирования загрузчика. При попытке прописать нужные данные GRUB2 в загрузочный сектор система выдавала сообщение, что указанное устройство не существует.

Решение

Долгие поиски увенчались успехом. Решение всех описанных проблем описывается в официальном руководстве по установке Debian, расположенном здесь (англ)

Выражаю признательность авторам официального руководства. Для тех, у кого некоторые трудности с пониманием английского языка, я привожу свой перевод оригинальной статьи.

Перевод статьи

Эта страница описывает процесс установки Debian на устройство, подключенное с использованием функции контроллера Serial ATA RAID (также известные как псевдо-RAID, BIOS RAID). Это контроллеры, которые эмулируют функции RAID, но при этом не имеют специального чипа для его аппаратной поддержки.

Не следует путать это с программной функцией поддержки RAID ядром Linux (Многодисковое устройство). Это предпочтительный и более надёжный метод установки ПО для поддержки массивов RAID.

Используйте описанный ниже метод только в том случае, если Вы хотите использовать на Вашем Serial ATA RAID функцию двойной загрузки Debian и другой операционной системы.

  1. Создайте псевдо-RAID с помощью утилиты BIOS (смотрите в инструкции изготовителя)

  2. Загрузитесь с установочного носителя Debian

  3. Переместите курсор на пункт Install меню загрузки (но НЕ нажимайте клавишу Enter)

    1. Нажмите клавишу Tab для изменения параметров загрузки ядра.
    2. Добавьте в конец строки запись "dmraid=true" без кавычек
    3. Нажмите Enter
  4. Установливайте Debian как обычно, пока не дойдёте до процедуры разметки диска. Вы должны будете увидеть Ваш псевдо-RAID как один диск с запутанным длинным именем. Используйте его как обычный диск и настройте разделы любым удобным способом, включая LVM и друзей.
  5. Завершите установку. При установке GRUB система может выдать сообщение об ошибке, но так и должно быть; GRUB будет установлен другим путём. Если установка GRUB не удастся, выберите "continue without butloader" (продолжить без загрузчика) для завершения установки.
  6. Перезагрузите систему, когда установщик Debian попросит об этом.
  7. Снова загрузитесь с установочного носителя.
  8. В загрузочном меню перейдите к пункту "Advanced Options", затем к пункту "Rescue system" (но НЕ нажимайте клавишу Enter):
    1. Нажмите клавишу Tab для изменения параметров загрузки ядра.
    2. Добавьте в конец строки запись "dmraid=true" без кавычек
    3. Нажмите Enter
  9. Будут показаны те же экраны, что и при обычной установке. Переходите по ним до тех пор, пока не будет выдан вопрос о том, какую корневую файловую систему следует смонтировать для работы.
  10. Выберите первую строку вида /dev/dm-?, где ? - число. Вы окажетесь в командной строке.
  11. (Дополнительно)Введите bash в командной строке для облегчения ввода команд и сохранения их истории.
  12. Откройте для редактирования файл /etc/default/grub (например, с помощью редактора nano: nano /etc/default/grub) и раскомментируйте строку GRUB_DISABLE_LINUX_UUID=true. Сохраните изменения и закройте редактор.
  13. Введите update-grub и нажмите Enter. Это очень важно, потому что в противном случае в меню загрузки GRUB Вы не сможете увидеть свежеустановленные ядра!
  14. Введите grub-install /dev/mapper/и нажмите клавишу Tab дважды, чтобы получить список имён псевдо-RAID разделов.
    1. Дополните команду grub-install /dev/mapper/ полным именем Вашего псевдо-RAID

      Например, grub-install /dev/mapper/isw-jggdha7s-SYS (Обратите внимание на отсутствие цифры в конце имени). Вы также можете увидеть такие имена, как grub-install /dev/mapper/isw-jggdha7s-SYS1, grub-install /dev/mapper/isw-jggdha7s-Volume1 и т.д. Выберите тот раздел, в конце имени которого нет числа, и нажмите Enter.

    2. Сейчас всё должно установиться без ошибок.

  15. Введите команду exit (дважды, если сделали действия из 11 пункта). Сейчас Вы должны вернуться в меню восстановления системы. Выберите опцию Reboot system. Теперь GRUB сможет загрузить с Вашего псевдо-RAID новоустановленный Debian.

Non Unicode character at position...

Введение

Как я уже писал ранее, моя компания использует множество проектов, написанных на Python. В качестве платформы для некоторых продуктов используется M3, построенная на основе популярного фреймворка Django. При первоначальной установке проектов на боевые сервера я столкнулся с тем, что при загрузке на сервер файлов, в имени которых встречается кириллица, система выдаёт невнятные сообщения. Оказалось, что проблема заключается в неправильной работе Python с кодировками, в которых хранятся имена файлов. В частности, от этого постоянно падали PIL и Pillow, а в некоторые разделы файлы не загружались вовсе.

В поисках решения

Первым делом я отправился в гугл, конечно же.

Введя в поиск заголовок этой статьи, я наткнулся на кучу статей, в большинстве которых предлагались следующие варианты решения проблемы:

  1. Использовать в коде явное преобразование строк из одной кодировки в другую с помощью встроенных функций языка либо сторонних пакетов.
  2. Установить в систему нужные локали.
  3. Прописать настройки в конфигах Django.
  4. Перейти с этого вашего Python'а на PHP или Ruby On Rails.

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

Установка в систему нужных локалей.

При установке Debian 7 предлагается выбрать язык системы и кодировку по умолчанию. Если Вы указали свою национальную кодировку (уверен, меня читают не только жители России, но и других стран СНГ), можете этот пункт пропустить. Если же нет, то приступим к установке:

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

apt-get install locales

После установки этого пакета становится доступна следующая команда:

dpkg-reconfigure locales

Откроется окно, в котором нужно с помощью пробела отметить локали, которые следует держать в системе (можно выбрать вариант "Все локали", но я не рекомендую - чем меньше в системе лишнего, тем лучше). Я оставил там две локали: en_US.UTF-8 и ru_RU.UTF-8.

После нажатия кнопки OK будет предложено выбрать локаль по-умолчанию. Я использую ru_RU.UTF-8.

В самом конце система приступит к генерации недостающих локалей и их установке в систему.

Настройка окружения для работы Python

Как я писал в одной из статей, для запуска проектов на Python лучшим выбором является виртуальное окружение, созданное с помощью virtualenv, в которое установлен Gunicorn. При этом управление всем приложением осуществляется с помощью Supervisor'а. Здесь же сразу перейдём к делу.

Переходим в каталог настроек приложений Supervisor'а:

cd /etc/supervisor/conf.d/

Открываем файл настроек нашего приложения и приводим его к следующему виду:

[program:project]
environment=PROJECT_CONFIG_PATH="/var/www/project/conf/",DJANGO_SETTINGS_MODULE="project.settings",PYTHONIOENCODING="UTF-8",LANG="ru_RU.UTF-8",LC_ALL="ru_RU.UTF-8",LC_LANG="ru_RU.UTF-8"
command=/var/www/.virtualenvs/project/bin/gunicorn_django -c /var/www/project/conf/gunicorn.conf.py

user=myuser
group=mygroup

daemon=false
debug=false

autostart=true
autorestart=true

redirect_stderr=true
stdout_logfile=/var/www/project/log/supervisor.log

Самая важная строка здесь - та, в которой задаётся значение параметра environment. Именно там указывается, какие локали использовать Python'у для работы с файлами, языком и т.д. Именно эта небольшая строка предотвращает ошибки вида "Non Unicode character at position..." и "Non-ASCII character at position..."

При необходимости к окружению можно добавить новые переменные, однако, после запятых не должно быть пробелов, а все значения должны быть заключены в кавычки или апострофы.

После того, как файл настройки будет изменён, следует уведомить об этом Supervisor:

supervisorctl update

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

Nginx + PHP-FPM в Debian 7

Введение

В статье рассматривается настройка сервера Debian 7 для размещения проектов PHP в связке с Nginx и PHP-FPM.

Долгое время мне вполне хватало возможностей Apache для разработки моих проектов на PHP. Были некоторые трудности с .htaccess и перенаправлением всех запросов на Front Controller, однако, чуть позже я понял, что Apache уже не может полностью удовлетворить моей тяги к максимальной производительности и начал искать другие пути. Почитав, я выяснил, что доля интернет-серверов под управлением Apache неуклонно снижается на протяжении уже нескольких лет, на замену ему приходят другие, которые дают бОльшую произодительность с меньшей затратой машинных ресурсов. Среди множества решений я выбрал PHP-FPM. Судя по тестам производительности, произведённым многими энтузиастами, именно он в связке с Nginx является наиболее перспективным способом размещения сайтов на PHP.

Цели

  • Увязка PHP-FPM с nginx
  • Конфигурирование параметров сайта для его корректной работы через Front Controller

Установка необходимого ПО

Добавим в список репозитории nginx, предварительно создав файл nginx.list в каталоге /etc/apt/sources.list.d/
cd /etc/apt/sources.list.d/
touch nginx.list

Содержимое nginx.list:

deb http://nginx.org/packages/debian/ wheezy nginx
deb-src http://nginx.org/packages/debian/ wheezy nginx

Скачиваем ключ репозитория:

wget http://nginx.org/keys/nginx_signing.key

Установка ключей в deb-системах делается так:

apt-key add nginx_signing.key

Теперь можно выполнить установку всех необходимых программ:

apt-get update && apt-get install php5 php5-fpm nginx
Кратко по списку:
  • php5 php5-fpm - интерпретатор и FastCGI-сервер для него
  • nginx - проксирующий сервер, будет нашим Front-End, т.е. сервером, принимающим запросы пользователя. Не путать с Front Controller, это совершенно разные вещи!

Настройка PHP и PHP-FPM

При установке PHP-FPM создаёт внутри каталога /etc/php5 подкаталог fpm. Внутри этого каталога находится несколько нужных нам файлов и подкаталогов. Первым делом вносим изменения в файл /etc/php5/fpm/php.ini
cd /etc/php5/fpm
nano php.ini

Здесь множество настроек, которые влияют на поведение PHP. В качестве символа комментария следует использовать точку с запятой. Самыми полезными я считаю следующие настройки:

  • short_open_tag = Off - использование коротких тегов считать ошибкой. Официальная документация по PHP рекомендует не использовать короткие теги.
  • asp_tags = Off - мы тут всё-таки на PHP пишем, а не на ASP.NET
  • max_execution_time = 60 - для некоторых CMS, например, Drupal, стандартных 30 секунд часто не хватает для выполнения некоторых скриптов, например, обновления
  • error_reporting = E_ALL - разработчику нужно видеть все ошибки. Если сервер боевой, нужно выставить в значение E_ALL & ~E_DEPRECATED & ~E_STRICT
  • display_errors = On - для разработки, для боевых условий - Off
  • display_startup_errors = On - аналогично
  • post_max_size = 16M - можно и больше, если через POST будут передаваться достаточно большие объёмы данных
  • default_charset = "UTF-8" - обязательно, если хочется избавиться от большинства проблем с кодировкой. Осторожно! Настройка влияет на весь сервер. Также кодировку можно задать в самом скрипте!
  • cgi.fix_pathinfo=1 - пригодится, если приложение работает через Front Controller
  • upload_max_filesize = 32M - можно и больше, если на сервер будут загружаться большие файлы
  • default_socket_timeout = 60 - в нашем случае связь с Nginx будет именно через сокет. Не стоит выставлять слишком большие значения, это приведёт к падению производительности.

Остальные настройки в этом файле можете делать по своему усмотрению.

Теперь нужно подредактировать файл www.conf в каталоге pool.d/www.conf

nano pool.d/www.conf

Следует изменить user и group на те, от имени которых будут выполняться скрипты. Не следует выполнять их от имени root, это дыра в безопасности. Я рекомендую указывать здесь владельца каталога /var/www

user = www-data
group = www-data

Не менее важная настройка:

listen = /var/run/php5-fpm.sock

Именно через этот сокет будет производиться обмен данными с Nginx. Остальные настройки я рекомендую оставить по-умолчанию. Их тонкая настройка заслуживает отдельной подробной статьи.

После сохранения изменений следует перезапустить php-fpm:

service php5-fpm restart

Настройка Nginx

Перейдём в каталог настроек nginx, здесь нам нужны 2 файла:

  • nginx.conf - основной файл конфигурации сервера
  • fastcgi_params - настройки Nginx для работы с FastCGI-серверами, например, PHP-FPM

Я изменил привёл содержимое этих файлов к следующему виду:

nginx.conf
user nginx;
worker_processes 2;         #По числу ядер/процессоров, либо эмпирическим путём
worker_priority  -5;        #Отрицательные числа задают более высокий приоритет
worker_rlimit_nofile 2048;  #Можно открыть сразу 2048 подключений без изменения параметров ядра

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

    keepalive_timeout  60; #Поддерживать подключение 1 минуту

    client_max_body_size 20m; #Разрешить загрузку файлов до 20 МБ
    server_tokens off;

    #Сжатие передаваемых данных
    gzip  on;               
    gzip_disable "msie6";
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types text/plain text/css application/x-javascript text/xml application/xml+rss text/javascript;

    include /etc/nginx/conf.d/*.conf;
}
В конец файла fastcgi_params нужно добавить всего одну строчку, вот эту:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Теперь в каталоге /etc/nginx/conf.d/ создадим файл site.conf

nano /etc/nginx/conf.d/site.conf
index index.php;
server {
    server_name www.site.ru;
    rewrite ^ $scheme://site.ru$request_uri? permanent;
}
server {
    server_name site.ru;
    access_log /var/www/site.ru/log/access.log;
    error_log /var/www/site.ru/log/error.log;
    root /var/www/site.ru;

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

    location ^~ /protected/ {
        deny all;
    }

    location ~ \.php$ {
        try_files $uri = 404;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
}

Разберём по частям этот файл:

index index.php;

Считать страницей по-умолчанию index.php

server {
    server_name www.site.ru;
    rewrite ^ $scheme://site.ru$request_uri? permanent;
}

Все запросы на http://www.site.ru автоматически переадресовывать к http://site.ru/

server_name site.ru;
access_log /var/www/site.ru/log/access.log;
error_log /var/www/site.ru/log/error.log;
root /var/www/site.ru;

Собственно наш сервер, с указанием его имени, логов и указанием корневого каталога

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

Тут указано, что все запросы вида http://site.ru/login/auth следует переадресовывать к http://site.ru/index.php - как раз то, что нужно для Front Controller'а

location ^~ /protected/ {
    deny all;
}

Запрещаем любые обращения к папке protected нашего сайта. Там лежат исходные коды, к которым будет обращаться только index.php, веб-сервер их отдавать не должен.

location ~ \.php$ {
    try_files $uri = 404;
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

Выдавать ошибку 404, если запрошенный php-файл не найден. В остальном - просто переадресовать запрос на наш PHP-FPM-сервер. Также в этих строках выполняется подключение файла настроек /etc/nginx/fastcgi_params.

После выполнения всех операций следует перезапустить сервис Nginx

service nginx restart

Если исходные файлы сайта размещены в каталоге /var/www/site.ru/, а также этот каталог содержит подкаталог log, владельцем которого является www-data, то при обращении к сайту мы увидим главную страницу.