суббота, 30 апреля 2011 г.

BIND, CNAME and other data

Такая ошибка появлятся, если для ресурса определить дополнительно к записи типа CNAME любую другую. Например, следующая схема работать не будет:

ns1  IN  A  4.4.4.4
www  IN CNAME ns1
www IN TXT "some text"

Нужно либо убрать запись TXT, либо заменить CNAME на A:

www  IN  A 4.4.4.4
www IN TXT "some text"

Простой бекап баз PostgreSQL

Порт postgresql устанавливает скрипт /usr/local/etc/periodic/daily/502.pgsql, который предназначен для локального резервного копирования баз через pg_dump.
По умолчанию бекапы не делаются, для их включения нужно прописать

daily_pgsql_backup_enable="YES"

в /etc/periodic.conf
Есть и другие параметры, полный список в самом скрипте.
От себя добавлю, что хранить дампы исключительно на локальной машине не очень хорошая идея. Желательно, чтобы эти дампы дублировались где-то еще, например с помощью rsync.

пятница, 29 апреля 2011 г.

Бесплатный secondary DNS

Как известно, для поддержки домена согласно RFC требуется минимум 2 неймсервера. Также желательно, чтобы они находились в разных сетях и имели независимое электропиние (читай: находились в разных зданиях). А что делать, если сервер всего один

четверг, 28 апреля 2011 г.

exim frozen messages

При возникновении фатальных ошибок при доставке сообщения помещаются в отдельную очередь - замораживаются. Последующих попыток доставки замороженных сообщений не предпринимается. Поэтому после устранения причины их необходимо "разморозить".
Делается это командой:
exim -Mt <идентификатор сообщения>
Идентификатор можно узнать из вывода mailq 

Автозавершение сеанса по таймауту

Иногда открываешь сессию по ssh и оставляешь ее открытой, а ведь враг может этим воспользоваться, если имеет физический доступ в вашей машине. Чтобы этого не допустить можно установить таймаут неактивности, скажем 30 мин, по истечении которого сессия будет автоматически завершаться.

java плагин для firefox

Как известно, для FreeBSD нет родных java пакетов, а порт java/jdk16 мало того, что старый и дырявый, так еще и не работает с firefox старше 3.5, но можно установить openjdk:

среда, 27 апреля 2011 г.

/etc/fstab во FreeBSD

За редким исключением я стараюсь не использовать дефолтный fstab. Ниже привожу конфиг с одного из боевых серверов:

Использование шаблонов skel для новых пользователей (FreeBSD)

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

вторник, 26 апреля 2011 г.

ssh, авторизация по ключам

Несмотря на то, что тема достаточно хорошо разжевана, не все используют ключи для авторизации. Ключ состоит из двух частей: открытой и закрытой. Открытый ключ (public) должен быть размещен на удаленном сервере, закрытый - на локальной машине.

Прибить запрос к PostgreSQL, залочивший базу

Столкнулся с ситуацией блокировки таблицы в боевой базе, все клиенты естественно отвалились. Пришлось прибивать процесс.
Сначала его нужно найти, для этого выполняем запрос:
SELECT procpid, current_query FROM pg_stat_activity;
Ищем в результатах запрос-вредитель (в моем случае это был CREATE INDEX), смотрим в первой колонке его PID, а дальше прибиваем процесс с помощью команды kill.

Обязательный комментарий при комитте в subversion

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

Пишем свой плагин для Nagios

Разработка плагинов для Nagios - дело нехитрое. Прочитав официальный мануал http://nagiosplug.sourceforge.net/developer-guidelines.html я переписал вчерашний скрипт для проверки состояния репликации для использования из под Nagios.

воскресенье, 24 апреля 2011 г.

Простой скрипт для проверки состояния репликации mysql


#!/usr/local/bin/perl -w
# usage is ./mysql_replication.pl --user user --password password
use strict;
use DBI;
use Getopt::Long;
my $user   = "";
my $password = "";
GetOptions ("user=s" => \$user,
            "password=s"   => \$password );

my $dsn="DBI:mysql:";
my $dbh=DBI->connect($dsn, $user, $password) or die ($!);
my ($sql_running, $io_running);
my $sth=$dbh->prepare("SHOW SLAVE STATUS") or die($!);
my %status = ();
$sth->execute() or die ($!);
while (my $ref = $sth->fetchrow_hashref()) {
    for (keys %{$ref}) {
        $status{$_}=$ref->{$_} || "n/a" if /Slave_IO_Running/;
        $status{$_}=$ref->{$_} || "n/a" if /Slave_SQL_Running/;
        $status{$_}=$ref->{$_} || "n/a" if /Seconds_Behind_Master/;
    }
}
$sth->finish;
$dbh->disconnect();
printf("%s: %s\n", "Slave_IO_Running", $status{"Slave_IO_Running"});
printf("%s: %s\n", "Slave_SQL_Running", $status{"Slave_SQL_Running"});
printf("%s: %s\n", "Seconds_Behind_Master", $status{"Seconds_Behind_Master"});

Состояние репликации MySQL

В предыдущей заметке я рассказывал о настройке репликации, теперь же более подробно расскажу о запросе > SHOW SLAVE STATUS\G. Наибольший интерес с точки зрения мониторинга представляют собой поля:

Slave_IO_Running - выполняется ли выгрузка двоичного лога с мастера. При нормальной работе должно быть Yes, значение No говорит о каких-либо проблемах на мастере, чаще всего отстуствие прав, сетевые проблемы или же отсутствие самих логов. Точная причина указана в поле Last_IO_Error.
Slave_SQL_Running - выполняются ли запросы выгруженные с мастера. Здесь все немного сложнее. Если в этом поле No, то нужно смотреть значение Last_SQL_Error.
Seconds_Behind_Master - отставание слейва от мастера в секундах. Чем меньше, тем лучше.

Master-Slave репликация в MySQL

Это самый простейший случай масштабирования: один ведущий сервер и один ведомый. В этом случае все обновления пишутся на ведущий (master) и реплицируются на ведомый (slave).
Репликация в mysql работает следущим образом: ведущий логирует все измения базы в двоичный лог, ведомый подключаясь в ведущему выгружает этот самый лог и затем выполняет его.
Настройка репликции в общем случае состоит из нескольких этапов

суббота, 23 апреля 2011 г.

SPF и с чем его едят

Изначально электронная почта не предусматривала какого-либо механизма проверки подлинности адреса отправителя и поэтому можно подставить любой домен и любой адрес, чем благополучно пользуются спамеры.
Одним из предложенных решений проблемы является SPF, описанный в документе RFC 4408. В нем предложено публиковать через запись типа TXT список хостов авторизованных отправлять почту с домена.
Пример записи:

IN TXT "v=spf1 ipv4:4.4.4. -all"

Данная запись говорит, что хост 4.4.4.4 может отправлять почту с домена, а все остальные - нет. Более подробно синтаксис описан на странице http://www.openspf.org/SPF_Record_Syntax.
В настоящее время все популярные MTA имеют в том или ином виде поддержку SPF, однако используется он лишь на 10% доменов.

Отключение coredump во FreeBSD

Core файлы могут содержать конфеденциальную информацию (логины, пароли), поэтому в боевой среде имеет смылс их отключить. Делается это просто: в /etc/login.conf находим строчку :coredumpsize=unlimited:\ и заменяем ее на :coredumpsize=0:\.
Потом чтобы изменения вступили в силу выполняем
# cap_mkdb /etc/login.conf

VirtualBox и DHCP

В одной из предыдущих заметок я обещал рассказать про выдачу айпишников гостевым машинам из DHCP. Делается это достаточно просто:
1. Нужно назначить mac-адрес гостевой машине
2. Прописать его в конфиг dhcp.

Cyrus Database backends mismatch

После обновления сайруса тот стал ругаться на несоотвествие типов внутренней БД.
Решение нагуглилось очень быстро:

# cd /var/lib && cp -Rp cyrus cyrus.old
# ctl_mboxlist -d > /tmp/mailboxes.txt && rm mboxlist
# cvt_cyrusdb /tmp/mailboxes.txt flat /var/lib/cyrus/mailboxes.db skiplist
# rm /usr/lib/cyrus/cyrus-db-types.active
# chown cyrus:mail *
# dpkg-reconfigure cyrus-common-2.2


пятница, 22 апреля 2011 г.

Обновление PostgreSQL до нового минорного релиза

Как известно, в разных версиях двочный формат базы несовместим и поэтому при переходе на более новую (или старую) приходится делать дамп и релоад всех таблиц. Сделать это достаточно просто.
Для начала нужно отредактировать pg_hba.conf, таким образом, чтобы не дать обычным пользователям обращаться к базе, только после этого можно начинать делать дамп. Далее запускаем дамп:
# pg_dumpall > pg_dump.sql
следующим шагом останавливаем демон:
# /usr/local/etc/rc.d/postgesql stop
После этого можно перейти непосредственно к обновлению. Я предпочитаю portuupgrade
env DISABLE_CONFLICTS=YES portupgrade -o databases/postgresql90-server postgresql-server databases/postgresql90-client postgresql-client
Далее нужно проинициализировать каталог с данными, старый желательно сохранить на всякий поражный, поэтому удалять мы его не будем, а лишь переименуем в data.bak, создадим новый и поставим владельца pgsql:pgsql

# cd $DATADIR
# mv data data.old
# mkdir data
# chown pgsql:pgsql data
# /usr/local/etc/rc.d/postgesql initdb

Кластер проинициализирован, теперь скопируем файлы конфигурации (postgresql.conf, pg_hba.conf) из старого каталога в новый. Вносим необходимые изменения, для этого нужно заранее ознакомиться с информацией о релизе новой версии.

Когда с этим покончено запускаем новую версию и восстанавливаем дамп:

# /usr/local/etc/rc.d/postgresql start
# psql -U pgsql template1 -f  pg_dump.sql

Дамп восстановился, теперь можно открыть доступ клиентам в pg_hba.conf.
После этого желательно обновить и клиенсткие библиотеки, ну и удалить старый каталог данных.

nging как ssl фронтэнд

Nginx можно использовать в качестве https фронтэнда, на на бакедны передавать незафированный трафик. Конфиг достаточно простой:

    server {
        listen       443;
        ssl_session_timeout  5m;
        ssl             on;

        server_name *.domain.tld;

        ssl_certificate      domain.pem;
        ssl_certificate_key  domain.key;
        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
        ssl_prefer_server_ciphers   on;
        keepalive_timeout    60;
        location / {
            proxy_pass http://localhost:80;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_redirect     off;
        }

        location ~ /\.ht {
            deny  all;
        }
        location ~ /\.svn {
            deny  all;
        }

    }

Здесь бакенд слушает на локалхосте на порту 80. Нужно иметь ввиду, что в текущей версии на момент написания заметки (1.0.0) nginx не поддерживает keep-alive соединения с бакендами, поэтому данная схема не рассчитана на большую нагрузку.

Деплой django с uwsgi и nginx

В продолжение темы деплоя php-приложений делюсь опытом выкладки приложений django.

Нам понадобиться uwsgi, который без проблем устанавливается из портов
# make install clean -C /usr//ports/www/uwsgi
Следующий шаг - подготовка конфига nginx

        server_name  site.domain.tld;

        location / {                uwsgi_pass      unix:///tmp/uwsgi.sock;
                include         uwsgi_params;

                uwsgi_param     UWSGI_CHDIR             /usr/local/www/$host/deploy;
                uwsgi_param UWSGI_SCHEME $http_x_forwarded_proto;
                uwsgi_param     UWSGI_SCRIPT            uwsgi;
                uwsgi_intercept_errors on;
        }

Параметр UWSGI_SCRIPT - указывает на точку входа в django приложение. Нужно иметь ввиду, что этот файл должен быть импортирован, поэтому не может иметь точки в названии. Сам файл должен находится в директории UWSGI_CHDIR
Теперь можно выкладывать проект в директорию /usr/local/www/$host. После этого создается файл uwsgi.py с обычно стандартным содержимым:

import os
import sys
import django.core.handlers.wsgi

DIR_PROJECT = os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) )
sys.path.append( DIR_PROJECT )

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
application = django.core.handlers.wsgi.WSGIHandler()


Запускаем uwsgi:

# echo 'uwsgi_enable="YES"'  >> /etc/rc.conf
# echo 'uwsgi_flags="-L -M --vhost"' >> /etc/rc.conf
# service uwsgi start

И если все было сделано правильно, то nginx передаст запрос uwscgi, а тот вызовет uwsgi обработчик, который в свою очередь отдаст запрос на обработку в django.
Важно иметь ввиду, что для корректной работы пользователю, из под которого запускается uwsgi необходимы права на запись в директорию со скриптами, иначе интерпретатор не сможет записать скомпилированный байт-код (файлы *.pyc)

Мониторинг скриптовых процессов в Nagios

Мониторить скрипты через стандартный для snmp способ proc process_name
Не удается, поскольку имя процесса у них - это имя исполняемого файла интерпретатора. Но выход есть.
Нам понадобиться плагин check_snmp_extend
Конфигурирование nagios подробно описано на сайте проекта:

define command{
    command_name    check_snmp_extend
    command_line    $USER1$/check_snmp_extend.sh $HOSTADDRESS$ $ARG1$
    }

Далее на целевой машине создаем следующий скрипт и сохраним его в /root/check_script.sh

#!/bin/sh
. /etc/rc.subr
# $1 - script name
# $2 - pidfile
# $3 - interpreter
r=`check_pidfile $1 $2 $3`
if [ ! $r  ]; then
     echo "CRITICAL $1 is not running"
else
     echo "OK $1 is running as pid $r"
fi

Скрипт принимает три агрумента и отвечает OK/CRITICAL в зависимости от возвращаемого значениея функции check_pidfile.
Теперь самое главное: преположим есть скрипт /home/www/something.pl, который пишет пид в /tmp/somthing.pid, а путь к перлу - /usr/local/bin/perl. Тогда добавим в конфиг snmpd такую строку:
extend something /root/check_scrint.sh /home/www/something.pl /tmp/somthing.pid /usr/local/bin/perl
Перезапускаем snmpd и прописываем проверку в нагиос:
define service{
    use            generic-service
    host_name        remote.server
    service_description    SomeService status
    check_command        check_snmp_extend!something
}

четверг, 21 апреля 2011 г.

3g модем мегафон во FreeBSD

Понадобилось подключиться к инету через 3г модем. Выбрал мегафон, из-за лучшего покрытия в моем городе. Вот рабочий конфиг

default:
 set log Phase Chat LCP IPCP CCP tun command
 ident user-ppp VERSION (built COMPILATIONDATE)

megafon3g:
 set device /dev/ttyU0.0
 set speed 460800
 set dial "\"\" \
 AT OK \
 AT OK \
 ATS0=0 OK \
 AT OK \
 AT&FE0V1X1&D2&C1S0=0 OK \
 AT OK \
 AT+CGDCONT=1,\\\"IP\\\",\\\"internet\\\" OK \
 ATDT*99***1\# CONNECT"
 set login
 set authname "megafon"
 set authkey "megafon"
 disable ipv6cp
 disable pap
 disable chap
 enable dns
 set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
 add default HISADDR


Сохраняем в /etc/ppp/ppp.conf и подключаемся
# ppp -ddial megafon3g

FreeBSD и VirtualBox bridged networking

Не нашел в сети внятного объяснения (не там искал?), как настроить bridged сеть в гостевой системе под FreeBSD и решил восполнить этот пробел.

Деплой большого количества сайтов на php и nginx

Когда количество сайтов на сервере переваливает за несколько десятков, начинаешь задумываться, как бы упростить себе жизнь. Я создал для себя простой шаблон, использующий переменную Host из запроса:

    server {
        listen       80;
        server_name  site1.domain.tld;

        server_name  site2.domain2.tld;

        root   /home/$host;
        location / {
           index  index.php index.html index.htm;
        }

        location ~ \.php$ {
            fastcgi_pass   localhost:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        location ~ /\.ht {
            deny  all;
        }
        location ~ /\.svn {
            deny  all;
        }

    }

Тут предпологается, что php-fpm запущен на локалхосте на порту 9000.
Таким образом остается лишь выложить скрипты и статику в директорию /home/$host и добавить соответсвующую директиву server_name.