Установка jail во FreeBSD

July 20th, 2009

Сначала скачиваем исходники системы.
Внимание на тэг обновления! Он обязательно должен совпадать с веткой установленной системы. Например, для системы FreeBSD 7.2-RELEASE-p2 тэг должен быть tag=RELENG_7_2.

cd /usr/share/examples/cvsup

Правим хост в standard-supfile на *default host=cvsup5.FreeBSD.org и запускаем:

csup ./standard-supfile

Затем:

mkdir /home/jail_sample
setenv D /home/jail_sample
mkdir -p $D
cd /usr/src
make buildworld
make installworld DESTDIR=$D
cd etc/ [1]
make distribution DESTDIR=$D
mount -t devfs devfs $D/dev

В rc.conf :

ifconfig_bge0="inet 1.2.3.1  netmask 255.255.255.0"
ifconfig_bge0_alias0="inet 1.2.3.2 netmask 255.255.255.255"

jail_enable="YES"
jail_list="sample"

jail_sample_rootdir="/home/jail_sample"
jail_sample_hostname="www.sample.com"
jail_sample_ip="1.2.3.2"
jail_sample_devfs_enable="YES"
jail_sample_sysvips_allow="YES"

Убедиться, что демоны на хост-машине и в jail не пересекаются по используемым IP-адресам.

Команды для управления jail-ом:

/etc/rc.d/jail start/stop/restart sample
jls # список запущенных jail
jexec 2 tcsh # запустить шелл внутри jail с ID=2

Возможно, потребуется поправить некоторые sysctl на хост-машине:

  • security.jail.set_hostname_allowed – если 1, то внутри jail можно поменять имя хоста;
  • security.jail.socket_unixiproute_only – если 1 , то сокет в jail можно создать только для доменов PF_LOCAL, PF_INET или PF_ROUTE, иначе, возвращается ошибка;
  • security.jail.sysvipc_allowed – если 1, то то в jail можно получить доступ к глобальному System V IPC;
  • security.jail.getfsstatroot_only – если 1, то в jail можно получить информацию (df)только о той файловой системе на которой создан jail;
  • security.jail.allow_raw_sockets – если 1, то в jail можно создавать raw sockets;
  • security.jail.chflags_allow – если 1, то процессы в jail могут модифицировать флаги ФС.

Наблюдение за загрузкой канала клиентами в реальном времени

July 15th, 2009

Часто возникает задача в реальном времени наблюдать за загрузкой интернет-канала по пользователям сидящими за nat-ом. С этим отлично справляется iftop. Он выдает вот такую картинку:
iftop

Ставим:

cd /usr/ports/net-mgmt/iftop && make install

Можно использовать такой конфиг (.iftoprc) где 2М это ширина входящего интернет-канала:

port-resolution: no
show-bars: yes
promiscuous: no
port-display: off
line-display: one-line-sent
max-bandwidth: 2M
hide-source: yes

Запускаем:

iftop -c ./.iftoprc

Dnsmasq для резолва любой зоны

July 13th, 2009

Понадобился DNS-сервер, который бы мог отвечать одинаковым IP-адресом на запрос о любой зоне.
Просто для того чтобы припарковать несколько доменов. С этим отлично справился dnsmasq.
Ставим:

cd /usr/ports/dns/dnsmasq && make install

или

yum install dnsmasq

В конфиге понадобится всего лишь одна строка:

address=/#/10.10.10.10

Кстати, подобным образом он так же может резолвить MX-запросы.

Если при запуске в OpenVZ-контейнере ругается:
dnsmasq: setting capabilities failed: Operation not permitted
то надо добавить в конфиг:

user=root

Для того чтобы dnsmasq заработал во FreeBSD jail надо добавить в конфиг:

bind-interfaces

Скрипт создания почтового ящика для Cyrus SASL Postfix

July 10th, 2009

Вызывать надо с параметром необходимого почтового ящика.

#!/usr/bin/perl -w

use Cyrus::IMAP::Admin;

my $server="mail.server.com";
my $admin="admin";
my $password="password";
my $quota="300000";
my $client = Cyrus::IMAP::Admin->new($server);

my $user=$ARGV[0];

if($user eq ""){
    print 'syntax: create_mail.pl test@test.com';
    die;
}

@chars = ("A" .. "Z", "a" .. "z", 0 .. 9);
$userpass = join("", @chars[ map{ rand @chars }(1 .. 10) ]);

system("/bin/echo $userpass | /usr/local/sbin/saslpasswd2 -p -c $user");
system("/bin/echo $user $user >> /usr/local/etc/postfix/virtual");
system("/usr/local/sbin/postmap /usr/local/etc/postfix/virtual");

$client->authenticate(-mechanism => "LOGIN",-user => $admin,-password => $password);
$rc = $client->create("user/$user");
$rc = $client->setacl("user/$user","$user" => 'all');
$rc = $client->setacl("user/$user",'admin' => 'all');
$rc = $client->setquota("user/$user",'STORAGE' => $quota);

print "User: $user Password: $userpass";

Примеры использования rsync

July 7th, 2009

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

rsync -avz --stats  /dir1 /dir2

Синхронизируем локальную и удаленную папки через ssh с выводом прогресс-бара:

rsync -avz --stats --progress /dir1 root@host.com:/dir2
rsync -e "ssh -p222"  --progress -lzuogthr --compress-level=9 --delete-after /usr/local/www/domain.ru root@server.com:/usr/local/www

Тоже синхронизируем локальную и удаленную папки. Через ssh на 222-порту.
l — пересоздание symlinks, это значит, что символические ссылки будут так же переноситься
z — использовать сжатие
u — update. Обновление, он будет пропускать файлы которые новей, чем на удалённом сервере
o — установить владельца конечного файла таким же, как и у исходного
g — установить группу конечного файла таким же, как и у исходного
t — передача времени модификации и его обновление на удаленной системе. Этот ключ должен быть установлен для точной синхронизации
h — вывод информации на терминал в удобном для чтения (human-readable) виде
v — verbose. Вывод сообщений в терминал.
r — рекурсивный режим
n — отладочный режим
compress-level — уровень сжатия
delete-after — удалять файлы, которые не были найдены на удалённом сервере, “-after” означает, что удалить их нужно, только после окончания синхранизации. Так-же есть delete-before, delete-during, delete-excluded и просто delete

Закачка больших файлов через PHP

July 7th, 2009

Вот что нужно поправить:
Во-первых, в nginx.conf надо

client_max_body_size 20m;

Иначе если запрос не будет пролазить в этот лимит nginx покажет 413 Request Entity Too Large для некоторых браузеров или просто сбросит соединение.

В apache убедиться что не определено LimitRequestBody или имеет подходящий лимит. Если установлен mod_security то проверить еще SecRequestBodyLimit.

И наконец, в php.ini:

post_max_size = 20M
upload_max_filesize = 20M

Скрипт автоматической установки типового веб-сервера на FreeBSD

July 5th, 2009

Задача: в автоматическом режиме установить основное ПО необходимое для работы веб-сервера: nginx/Apache/PHP/MySQL/vsftpd.
Скачать скрипт целиком

#!/bin/sh

### ver. 0.92 from 7.07.2009

### No need change in this script ###

os=`uname -a |grep -c FreeBSD`
if [ $os = "0" ]; then
    echo "This script work only on FreeBSD. Exit."
    exit
fi

echo "Enter username to create (default, admin):"
read USER
echo "This host is VPS? (yes/no. Default, no):"
read thisvps

if [ -z $USER ]; then
    USER=admin
fi
if [ -z $thisvps ]; then
    thisvps=no
fi

confighost=unix-notes.ru
USERPASS=`< /dev/urandom tr -dc A-Za-z0-9 | head -c15`
SQLPASS=`< /dev/urandom tr -dc A-Za-z0-9 | head -c15`
thiswebazilla=`uname -a | grep -c "webazilla"`

echo "WITHOUT_X11=yes" >> /etc/make.conf
echo "WITHOUT_IPV6=yes" >> /etc/make.conf
echo "WITHOUT_SAMBA=yes" >> /etc/make.conf

echo 'fsck_y_enable="YES"' >> /etc/rc.conf
echo 'icmp_drop_redirect="YES"' >> /etc/rc.conf
echo 'accounting_enable="YES"' >> /etc/rc.conf
echo 'syslogd_flags="-ss"' >> /etc/rc.conf
echo 'tcp_drop_synfin="YES"' >> /etc/rc.conf
echo 'tcp_restrict_rst="YES"' >> /etc/rc.conf
echo 'apache2_enable="YES"' >> /etc/rc.conf
echo 'mysql_enable="YES"' >> /etc/rc.conf
echo 'mysql_dbdir="/home/mysql"' >> /etc/rc.conf
echo 'nginx_enable="YES"' >> /etc/rc.conf
echo 'vsftpd_enable="YES"' >> /etc/rc.conf

# check to exist homedir
if [ ! -d /home ];  then
   echo "/home is no exist! setup canceled."
   exit
fi

# add additional dns servers, OpenDNS
echo "nameserver 208.67.222.222" >> /etc/resolv.conf

mkdir /root/.ssh
cd /root/.ssh
fetch http://$confighost/config/ssh/egor-pentarh/authorized_keys
chown -R root /root
chmod -R 400 /root

if [ $thisvps = "no" ]; then
    cd /etc
    rm -f /etc/sysctl.conf
    fetch http://$confighost/config/freebsd/sysctl.conf
    /etc/rc.d/sysctl restart

    ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime
    ntpdate pool.ntp.org
    echo "1 1 * * * root ntpdate pool.ntp.org" >> /etc/crontab
fi

if [ $thisvps = "yes" ]; then
    ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime
fi

freebsd-update fetch
freebsd-update install

portsnap fetch
portsnap extract
portsnap update

make WITHOUT_SAMBA=yes -DBATCH -C /usr/ports/misc/mc install clean
make WITH_RC_NG=yes -DBATCH -C /usr/ports/ftp/vsftpd install clean
make WITHOUT_IPV6=yes -DBATCH -C /usr/ports/www/apache20 install clean
make WITH_CHARSET=utf8 WITH_COLLATION=utf8_unicode_ci -DBATCH -C /usr/ports/databases/mysql51-server install clean
make WITH_APACHE=yes WITHOUT_IPV6=yes -DBATCH -C /usr/ports/lang/php5 install clean
make WITH_BUNDLED_PCRE=yes -DBATCH -C /usr/ports/devel/php5-pcre install clean
make WITH_MBSTRING=yes WITH_CURL=yes WITH_FTP=yes WITH_GD=yes WITH_MCRYPT=yes WITH_MYSQL=yes WITH_MYSQLI=yes WITH_OPENSSL=yes WITH_SOCKETS=yes WITH_ZLIB=yes -DBATCH -C /usr/ports/lang/php5-extensions install clean
make -DBATCH -C /usr/ports/www/mod_geoip2 install clean
make WITH_HTTP_FLV_MODULE=yes -DBATCH -C /usr/ports/www/nginx install clean
make -DBATCH -C /usr/ports/www/mod_rpaf2 install clean
make -DBATCH -C /usr/ports/devel/ZendOptimizer install clean

cd /usr/local/etc
rm -f /usr/local/etc/vsftpd.conf
fetch http://$confighost/config/linux/vsftpd.conf
chmod 400 /usr/local/etc/vsftpd.conf

cd /usr/local/etc/apache2/Includes
fetch http://$confighost/config/freebsd/mod_rpaf.conf
iplist=`ifconfig | grep inet | grep -v inet6 | awk '{print $2}' | grep -v '^$' | tr "\n" " "`
sed -I "" "s/127.0.0.1/$iplist/g" /usr/local/etc/apache2/Includes/mod_rpaf.conf
mkdir /var/log/httpd
chmod 777 /var/log/httpd

# Create user and setup user folders
pw user add $USER -d /home/$USER -m -s /sbin/nologin
echo "$USERPASS" |pw usermod $USER -h0
mkdir /home/$USER/domains
chmod -R 755 /home/$USER
chown -R $USER:www /home/$USER/domains

cd /home/$USER
fetch http://$confighost/config/freebsd/create_domain.sh
sed -I "" "s/testuser/$USER/g" /home/$USER/create_domain.sh
chmod +x /home/$USER/create_domain.sh
mkdir /usr/local/etc/apache2/vhosts
cd /usr/local/etc/apache2/vhosts
fetch http://$confighost/config/freebsd/sample

cd /home/$USER
fetch http://$confighost/config/freebsd/create_base.sh
sed -I "" "s/INSERTPASSHERE/$SQLPASS/g" /home/$USER/create_base.sh
chmod +x /home/$USER/create_base.sh

cd /home/$USER
fetch http://$confighost/config/freebsd/create_multi_bases.sh
sed -I "" "s/INSERTPASSHERE/$SQLPASS/g" /home/$USER/create_multi_bases.sh
sed -I "" "s/username/$USER/g" /home/$USER/create_multi_bases.sh
chmod +x /home/$USER/create_multi_bases.sh


cd /usr/local/etc/apache2
rm -f /usr/local/etc/apache2/httpd.conf
fetch http://$confighost/config/freebsd/httpd.conf

cd /usr/local/etc/
fetch http://$confighost/config/freebsd/php.ini

cd /usr/local/etc/nginx
rm -f /usr/local/etc/nginx/nginx.conf
fetch http://$confighost/config/freebsd/nginx.conf
iplist2=`ifconfig | grep inet | grep -v inet6 | awk '{print $2}' | grep -v '^$'|grep -v 127.0.0.1 | sed 's/\(.*\)/listen \1;/'`
sed -I "" "s/user_name/$USER/g" /usr/local/etc/nginx/nginx.conf
sed -I "" "s/IPADDR/$iplist2/g" /usr/local/etc/nginx/nginx.conf
mkdir /var/log/nginx/
chmod 777 /var/log/nginx/

mkdir /home/mysql
mkdir /home/mysql/tmp
chown -R mysql /home/mysql/
chmod -R 755 /home/mysql/
cd /etc
rm -f /etc/my.cnf
if [ $thisvps = "no" ]; then
    fetch http://$confighost/config/freebsd/my.cnf
fi
if [ $thisvps = "yes" ]; then
    fetch http://$confighost/config/freebsd/vps/my.cnf
fi
touch /var/log/mysqld.log
chmod 777 /var/log/mysqld.log
/usr/local/etc/rc.d/mysql-server start
/usr/local/bin/mysqladmin password $SQLPASS
echo "DELETE FROM mysql.user WHERE Password=''" | /usr/local/bin/mysql --password=$SQLPASS

/usr/local/etc/rc.d/apache2 start
/usr/local/etc/rc.d/nginx start
/usr/local/etc/rc.d/vsftpd start

echo "##############################"
echo "Setup ready!"
echo "FTP username: $USER"
echo "FTP password: $USERPASS"
echo "MySQL root password: $SQLPASS"
echo "##############################"

Настройки производительности VMWare Server 2

July 2nd, 2009

При достаточных аппаратных ресурсах рекомендуется установить следующие настройки.
Диски:
- Independent
- Persistent
- Optimize for performance
- Allocated сразу и полностью

Для памяти и свопа добавить в конфиг виртуальной машины:

MemTrimRate = "0"
sched.mem.pshare.enable = "FALSE"

В конфиге хоста:

Fit all virtual machine memory into reserved host RAM

Простая настройка SSL в Apache

July 1st, 2009

Сертификаты бывают на один домен (будет работать только для mydomain.com или только для www.mydomain.com) и мультидоменные (*.mydomain.com). Мультидоменные стоят много дороже. В нашем случае рассматриваются сертификаты на один домен.
Генерим закрытый ключ и запрос на сертификат:

openssl genrsa –des3 –out mydomain.com.key 1024
openssl req -new -key mydomain.com.key -out mydomain.com.csr

Самое важное это указать Common name = mydomain.com. Остальные поля не так важны. Всякие Optional-поля лучше вообще не указывать.
На данном этапе если хотим подписать сертификат доверенным центром сертификации то отправляем им mydomain.com.csr. А если будем подписывать сами, то:

openssl x509 -req -days 365 -in mydomain.com.csr -signkey mydomain.com.key -out mydomain.com.crt

И базовый ssl.conf для примера:

SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512

Listen 443

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
# If you use secret phrase
SSLPassPhraseDialog  exec:/usr/local/etc/apache2/certs/domain.com.pass
SSLSessionCache         dbm:/var/run/ssl_scache
SSLSessionCacheTimeout  300
SSLMutex  file:/var/run/ssl_mutex

<VirtualHost 192.168.0.1:443>
<Directory /home/domain.com/htdocs>
    Order Allow,Deny
    Allow from all
</Directory>

DocumentRoot "/home/domain.com/htdocs"
ServerName domain.com:443
ServerAdmin you@example.com
ErrorLog /home/logs/httpsd-error.log
TransferLog /home/logs/httpsd-access.log
SSLEngine on

SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

SSLCertificateFile /usr/local/etc/apache2/certs/domain.com.crt
SSLCertificateKeyFile /usr/local/etc/apache2/certs/domain.com.key

<FilesMatch "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/home/domain.com/htdocs">
    SSLOptions +StdEnvVars
</Directory>

SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog /home/logs/httpd-ssl_request.log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>

Простая настройка SSL на Apache

July 1st, 2009

Генерим закрытый ключ и запрос на сертификат.

openssl genrsa –des3 –out mydomain.com.key 1024
openssl req -new -key mydomain.com.key -out mydomain.com.csr

Когда генерим CSR то не надо указывать e-mail, challenge password и дополнительные опции.
Если мы хотим подписать сертификат доверенным центром сертификации, то отправляем им mydomain.com.csr. Если же будем подписывать сами то:

openssl x509 -req -days 365 -in mydomain.com.csr -signkey mydomain.com.key -out mydomain.com.crt

И базовый ssl.conf для примера:

SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512

Listen 443

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
# If you use secret phrase
SSLPassPhraseDialog  exec:/usr/local/etc/apache2/certs/domain.com.pass
SSLSessionCache         dbm:/var/run/ssl_scache
SSLSessionCacheTimeout  300
SSLMutex  file:/var/run/ssl_mutex

<VirtualHost 192.168.0.1:443>
<Directory /home/domain.com/htdocs>
    Order Allow,Deny
    Allow from all
</Directory>

DocumentRoot "/home/domain.com/htdocs"
ServerName secure.domain.com:443
ServerAdmin you@example.com
ErrorLog /home/logs/httpsd-error.log
TransferLog /home/logs/httpsd-access.log
SSLEngine on

SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

SSLCertificateFile /usr/local/etc/apache2/certs/domain.com.crt
SSLCertificateKeyFile /usr/local/etc/apache2/certs/domain.com.key

<FilesMatch "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/home/domain.com/htdocs">
    SSLOptions +StdEnvVars
</Directory>

SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog /home/logs/httpd-ssl_request.log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>

Простой скрипт бэкапа типового веб-сервера

June 23rd, 2009

Скрипт может создавать локальный архив из указанных каталогов, с указанными исключениями; архив mysql-баз. Может закачивать их на указанный FTP-сервер. Автоматически удаляет старые архивные копии (два варианта правил). Есть поддержка полного и инкрементального бэкапов. Работает под FreeBSD и Linux. Есть шифрование архивов и отправка уведомления о результатах на электронную почту.
Текст всех файлов ниже. Возможно удобнее будет скачатьархив:
файл backup.sh

#!/bin/sh

# Kiloservers.com sample backup script
# Last changes from: 23-07-2009

# Global backup tasks
mysql="YES" # need backup mysql bases? YES || NO
filebackup="YES" # need perform backup local files? YES || NO
savelocalbackup="YES" # need save backup on local drive? YES || NO
uploadbackup="YES" # need upload backup to FTP server? YES || NO
encryptbackup="NO" # need encrypt backup? YES || NO. If "YES" setup "encryptkey".
emailresult="YES" # need send e-mail with the results of backup? YES || NO. If "YES" setup "emailforresult".

# Common parametrs
backuptype="full" # 'full' or 'incremental'-files changed after last full backup
scriptdir="/etc/backup-complect" # homedir of this script
backupdir="/home/backup" # where save local backup
incfile="incfile" # file/dirs include to backup. Change content of this file
exfile="exfile" # file/dirs exclude from backup. Change content of this file
minfreespace="5000" # Minimal free space on backup slice in MB to start backup
encryptkey="" # Secret key to encrypt backup. Min 10 symbols recommended. Make sure that this key is kept in a safe place!
gpgpath="/usr/local/bin/" # path to gpg program
ftppath="/usr/bin/" # path to ftp client program
emailforresult="" # e-mail for backup results
sendmailpath="/usr/sbin/" # path to sendmail program

# FTP settings
ftphost="" # backup host
ftpuser=""
ftppass=""

# SQL settings
sqluser="root"
sqlpass=""
sqlhost="localhost"
allbases="YES" # 'YES' or 'NO'. Backup all bases or only from 'backupsqlbases' parametr
backupsqlbases="mysql" # bases list separate by space
mysqlutilspath="/usr/local/bin/" # path to 'mysql' and 'mysqldump' folder. No need to change.
sqldef="--single-transaction --skip-add-locks --skip-disable-keys --force" # parametrs for mysqldump


#######################
##### just do it! #####
#######################

salt=`< /dev/urandom tr -dc A-Za-z0-9 | head -c8` # random string for more secure ftp uploads
freespace=`df -m $backupdir | grep dev | awk '{print $4}'` # current free space on backupdir slice
hostn=`hostname`
backupstartdate=`date "+%Y-%m-%d %H:%M %Z%n"`

# check to exist backupdir
if [ ! -d $backupdir ];  then
   echo "$backupdir backupdir is no exist! Backup canceled."
   exit
fi

# check to exist mysql/mysqldump program
if [ $mysql = YES ]; then
    if [ ! -f $mysqlutilspath"/mysql" ];  then
        mysqlutilspath="/usr/bin/"
        if [ ! -f $mysqlutilspath"/mysqldump" ];  then
            echo "mysqldump program is not exist on this path $mysqlutilspath ! Backup canceled."
            exit
        fi
    fi
fi

# check to email setup
if [ $emailresult = YES ]; then
    if [ $emailforresult = "" ]; then
        echo "You should setup emailforresult parametr. Backup canceled."
        exit
    fi

    if [ ! -f $sendmailpath"/sendmail" ];  then
        echo "You should setup sendmail before. Backup canceled."
        exit
    fi
fi

# check to exist ftp client program
if [ $uploadbackup = YES ]; then
    if [ ! -f $ftppath"/ftp" ];  then
        ftppath="/usr/local/bin/"
        if [ ! -f $ftppath"/ftp" ];  then
            echo "FTP client program is not exist on this path $ftppath ! Backup canceled."
            echo "To install ftp client on CentOS/RHEL:"
            echo "yum install ftp"
            exit
        fi
    fi

    # remove old ftp logs
    if [ -f $scriptdir"/ftpdump.txt" ];  then
        rm $scriptdir"/ftpdump.txt"
    fi
fi

# check to free space on backupdir
if [ $minfreespace -ge $freespace ]; then
    echo "Free space not enought! Backup canceled."
    exit
fi

# check gpg and secret key
gpgext=""
if [ $encryptbackup = YES ]; then
    if [ $encryptkey = "" ]; then
        echo "You must install the encryption key. Exit."
        exit
    fi

    if [ ! -f $gpgpath"/gpg" ];  then
        gpgpath="/usr/bin/"
        if [ ! -f $gpgpath"/gpg" ];  then
            echo "GnuPG v.1 is not found. You must setup path to GnuPG v.1 in gpgpath or setup GnuPG v.1."
            echo "To setup GnuPG v.1 on FreeBSD use:"
            echo "pkg_add -r gnupg1"
            echo "or"
            echo "cd /usr/ports/security/gnupg1 && make install"
            echo ""
            echo "To setup GnuPG v.1 on CentOS/RHEL use:"
            echo "yum install gnupg"
            echo ""
            echo "Backup canceled."
            exit
        fi
    fi
    gpgext=".gpg"
fi

# check OS
checkos=`uname -a | grep -c "FreeBSD"`

# if FreeBSD
if [ $checkos = "1" ]; then
    newerparam=" --newer-mtime-than "$scriptdir"/metka"
fi

# if Linux
if [ $checkos = "0" ]; then
    newerparam=" --newer "$scriptdir"/metka"
fi

if [ $backuptype = full ]; then
    newerparam=""
fi


incfile=$scriptdir"/"$incfile
exfile=$scriptdir"/"$exfile
curdate=`date "+%Y-%m-%d%n"`
curdatewithhours=`date "+%Y-%m-%d-%H%n"`

# get list of all mysql bases
if [ $mysql = YES ]; then
    echo "Get MySQL databases list"
    if [ $allbases = YES ]; then
        backupsqlbases=`echo "show databases"|$mysqlutilspath'mysql' --user=$sqluser --password=$sqlpass --host=$sqlhost|grep -v "^D"`
    fi
fi

# create remote current day folder
if [ $uploadbackup = YES ]; then
    echo "Create remote current day folder"
    ftp -i -n $ftphost 2>&1 1>>$scriptdir/ftpdump.txt <<END_SCRIPT
    quote USER $ftpuser
    quote PASS $ftppass
    mkdir /$curdate
    quit
END_SCRIPT
fi


if [ ! -d $backupdir"/"$curdate ];  then
    echo "Creating "$backupdir"/"$curdate
    mkdir $backupdir"/"$curdate
    chmod 777 $backupdir"/"$curdate
fi
cd $backupdir"/"$curdate

# create and upload mysql bases backup
if [ $mysql = YES ]; then
    echo "Begin export databases"
    for base in $backupsqlbases
        do
        $mysqlutilspath'mysqldump' $sqldef --user=$sqluser --password=$sqlpass --host=$sqlhost $base > $backupdir/$curdate/$base.sql
    done

    echo "Begin compress databases"
    nice -n 15 tar -cz -f $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz $backupdir/$curdate/*.sql
    rm $backupdir/$curdate/*.sql

    # get filesize
    if [ $checkos = "1" ]; then
        sqlbackupfilesize=`stat -f %z $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz`
        else
        sqlbackupfilesize=`stat -c %s $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz`
    fi

    if [ $encryptbackup = YES ]; then
        echo "Begin encrypt databases archive"

        echo "$encryptkey" | $gpgpath/gpg --no-tty --passphrase-fd 0 --cipher-algo AES256  -cq $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz

        # get filesize for gpg files
        if [ $checkos = "1" ]; then
            sqlbackupfilesizegpg=`stat -f %z $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext`
            else
            sqlbackupfilesizegpg=`stat -c %s $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext`
        fi
    fi

    if [ $uploadbackup = YES ]; then
        echo "Begin upload databases archive"
        ftp -i -n $ftphost 2>&1 1>>$scriptdir/ftpdump.txt <<END_SCRIPT
        quote USER $ftpuser
        quote PASS $ftppass
        binary
        put $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext /$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext
        quit
END_SCRIPT
    fi

    if [ $savelocalbackup = NO ]; then
        echo "Remove local copy databases archive"
        rm $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext
    fi
fi

# create and upload file backup
if [ $filebackup = YES ]; then
    echo "Begin compress files archive"

    nice -n 15 tar -cz $newerparam -f $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz -T $incfile -X $exfile

    # get filesize
    if [ $checkos = "1" ]; then
        filebackupfilesize=`stat -f %z $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz`
        else
        filebackupfilesize=`stat -c %s $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz`
    fi

    if [ $encryptbackup = YES ]; then
        echo "Begin encrypt files archive"

        echo "$encryptkey" | $gpgpath/gpg --no-tty --passphrase-fd 0 --cipher-algo AES256  -cq $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz

        # get filesize for gpg files
        if [ $checkos = "1" ]; then
            filebackupfilesizegpg=`stat -f %z $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext`
            else
            filebackupfilesizegpg=`stat -c %s $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext`
        fi
    fi

    if [ $uploadbackup = YES ]; then
        echo "Begin upload files archive"
        ftp -i -n $ftphost 2>&1 1>>$scriptdir/ftpdump.txt <<END_SCRIPT
        quote USER $ftpuser
        quote PASS $ftppass
        binary
        put $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext /$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext
        quit
END_SCRIPT
    fi

    if [ $savelocalbackup = NO ]; then
        echo "Begin remove local copy files archive"
        rm $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz
        rm $backupdir/$curdate/$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext
    fi
fi


# update special file for incremental backup
touch $scriptdir/metka

backupenddate=`date "+%Y-%m-%d %H:%M %Z%n"`

# send result e-mail
if [ -f $backupdir/report ];  then
    rm $backupdir/report
fi

if [ $emailresult = YES ]; then
    echo "Send a e-mail with the results"

    echo "Subject: $hostn `date "+%Y-%m-%d%n"` backup result" >> $backupdir/report

    echo "Backup started: $backupstartdate
Backup ended: $backupenddate" >> $backupdir/report

    echo "After backup free space on "$backupdir" - "`df -m $backupdir | grep dev | awk '{print $4}'`" MB" >> $backupdir/report

    if [ $filebackup = YES ]; then
        echo "Current file backup - "$filebackupfilesize" bytes - "$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz >> $backupdir/report

        if [ $encryptbackup = YES ]; then
            echo "Current encrypted file backup - "$filebackupfilesizegpg" bytes - "$hostn-$backuptype-file-backup-$curdatewithhours-$salt.tar.gz$gpgext >> $backupdir/report
        fi
    fi

    if [ $mysql = YES ]; then
        echo "Current mysql backup - "$sqlbackupfilesize" bytes - "$hostn-sql-backup-$curdatewithhours-$salt.tar.gz >> $backupdir/report

        if [ $encryptbackup = YES ]; then
            echo "Current encrypted mysql backup - "$sqlbackupfilesizegpg" bytes - "$hostn-sql-backup-$curdatewithhours-$salt.tar.gz$gpgext >> $backupdir/report
        fi
    fi

    if [ $uploadbackup = YES ]; then
        echo "Error during ftp upload: " >> $backupdir/report
        cat $scriptdir"/ftpdump.txt" >> $backupdir/report
    fi

    echo "
Local backup folder statistics:" >> $backupdir/report
    if [ $checkos = "1" ]; then
        du -hc -d 1 $backupdir >> $backupdir/report
        else
        du -hc --max-depth=1 $backupdir >> $backupdir/report
    fi

    cat $backupdir/report | $sendmailpath"/sendmail" $emailforresult
    rm $backupdir/report
fi

echo "Backup complete"
exit

Файл exfile

/var/log/
/home/mysql
*.bz2
*.err
*.flv
*.log
*.zzz
*.rar
*.wmv
*.gz
*.bz2
*.avi
*.zip

Файл incfile

/etc
/usr/local/etc

файл install.txt

INSTALLATION:

1. Copy this folder to /etc/
2. Create "backupdir" folder
3. Edit "incfile" (dirs are included in the backup) and "exfile" (dirs deleted from the backup) files
4. If need - create SQL user for backup and set "mysql" to YES
5. If need - set "encryptbackup" to YES and set encryptkey. To decrypt use "gpg -o output_filename.tar.gz -d encrypted_filename.gpg"
6. Setup "emailforresult"
7. Configure spacer.sh to check the free space
8. Create cron task. For example, for full backup, at first day of month .. and check free space:
###################
5       7       1       *       *       root    /etc/backup-complect/spacer.sh 2> /dev/null
15       7       1       *       *       root    /etc/backup-complect/backup.sh 2> /dev/null
###################
9. Perform the test run:
cd /etc/backup-complect
./backup.sh


IMPORTANT!
Do not forget to do a test restore!

Файл spacer.sh

#!/bin/sh

# Kiloservers free space and count files checker.
# The script deletes old files from "backupdir" until not enough free space
# OR
# deletes old files from "backupdir" until number of files reaches the required
# Last changes from: 23-07-2009

# Settings
mode="space" # work mode: "space" or "count".
minfreespace="5000" # Minimal free space in MB. Actual for "space" mode
count="6" # how many files stored. Actual for "count" mode
backupdir="/home/backup" # directory to check

### Begin ###
echo "Mode $mode active"

# check OS
checkos=`uname -a | grep -c "FreeBSD"`

if [ $mode = "space" ]; then
    while [ `df -m $backupdir | grep dev | awk '{print $4}'` -lt $minfreespace ]
    do
        if [ $checkos = "1" ]; then
            filetodelete=`find $backupdir -type f -exec stat -f "%Sm %N" -t %Y%m%d%H%M%S {} \; | sort -n | head -1 | cut -d' ' -f2`
            else
            filetodelete=`find $backupdir -type f -exec stat -c "%Y %n" {} \; | sort -n | head -1 | cut -d' ' -f2`
        fi

        if [ -z $filetodelete ]; then
            echo "No files found. Exit"
            exit
            else
            rm $filetodelete
            echo "Deleted $filetodelete"
        fi
    done
fi

if [ $mode = "count" ]; then
    while [ `find $backupdir -type f | wc -l` -gt $count ]
    do
        if [ $checkos = "1" ]; then
            filetodelete=`find $backupdir -type f -exec stat -f "%Sm %N" -t %Y%m%d%H%M%S {} \; | sort -n | head -1 | cut -d' ' -f2`
            else
            filetodelete=`find $backupdir -type f -exec stat -c "%Y %n" {} \; | sort -n | head -1 | cut -d' ' -f2`
        fi

        if [ -z $filetodelete ]; then
            echo "No files found. Exit"
            exit
            else
            rm $filetodelete
            echo "Deleted $filetodelete"
        fi
    done
fi

echo "Check complete"

Скрипт добавления зон для tinydns

June 16th, 2009

Для добавления одной зоны:

#!/bin/bash

DIR="/service/srvdns/root"
cd $DIR

if [ "x$1" = "x" ]; then
    echo "Usage: domain.com owner ip"
    exit
fi
if [ "x$2" = "x" ]; then
    echo "Usage: domain.com owner ip"
    exit
fi
if [ "x$3" = "x" ]; then
    echo "Usage: domain.com owner ip"
    exit
fi

domainexist=`cat $DIR/data | grep -c $1`
if [ $domainexist != "0" ]; then
    echo "$1 already exist. Exit."
    exit
fi

sed -e "s/domain.com/$1/g" "$DIR/domain.com" > "$DIR/tmpfile"
sed -e "s/owner/$2/g" "$DIR/tmpfile" > "$DIR/tmpfile2"
sed -e "s/serverip/$3/g" "$DIR/tmpfile2" >> "$DIR/data"

rm $DIR/tmpfile
rm $DIR/tmpfile2
make

Для добавления нескольких зон из файла-списка:

#!/bin/bash

DIR="/service/srvdns/root"
cd $DIR

if [ "x$1" = "x" ]; then
    echo "Usage: owner ip"
    exit
fi
if [ "x$2" = "x" ]; then
    echo "Usage: owner ip"
    exit
fi

cat $DIR/domainsfile | while read domain; do

    domainexist=`cat $DIR/data | grep -c $domain`
    if [ $domainexist != "0" ]; then
        echo "$domain already exist. Skipped."
        continue
    fi

    sed -e "s/domain.com/$domain/g" "$DIR/domain.com" > "$DIR/tmpfile"
    sed -e "s/owner/$1/g" "$DIR/tmpfile" > "$DIR/tmpfile2"
    sed -e "s/serverip/$2/g" "$DIR/tmpfile2" >> "$DIR/data"

    rm $DIR/tmpfile
    rm $DIR/tmpfile2
done
make

Где файл domain.com такой:

###########################
#owner: domain.com
.domain.com::ns1.domainserver.com.:2500
&domain.com::ns2.domainserver.com.:2500
@domain.com::mail.domain.com.:10:2500
+domain.com:serverip:2500
+*.domain.com:serverip:2500

Добавление нового диска в Linux

June 10th, 2009

Проверяем, что диск виден в системе:

fdisk -l

Допустим, новый диск виден как /dev/sdb
Создаем раздел на нем:

fdisk /dev/sdb
n
p
2

Создаем фс:

mkfs.ext3 /dev/sdb1 -j

Создаем папку для монтирования, прописываем label новому диску, монтируем:

mkdir /mnt/newdisk
e2label /dev/sdb1 /mnt/newdisk
mount /dev/sdb1 /mnt/newdisk

Добавляем в fstab:

LABEL=/mnt/newdisk              /mnt/newdisk                    ext3    defaults        1 2

Автообновление базы GeoIP в CentOS

June 8th, 2009

Для базы по странам добавить в crontab:

cd /usr/share/GeoIP/ && wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz && gunzip -f GeoIP.dat.gz

Для базы по городам:

cd /usr/share/GeoIP/ && wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz && gunzip -f GeoLiteCity.dat && mv ./GeoLiteCity.dat ./GeoIPCity.dat

Установка eAccelerator, ionCube, ZendOptimizer на CentOS

June 8th, 2009

Основной принцип этой связки – ZendOptimizer должен загружаться последним, а eAccelerator первым.
Т.е. после того как мы поставили Zend из бинарника, скачали и поставили ionCube, поставили eAccelerator:

yum --enablerepo=remi install php-eaccelerator.x86_64

Надо задизаблить строчку:

zend_extension="/usr/lib64/php/modules/eaccelerator.so"

в /etc/php.d/eaccelerator.ini

и сделать так:

[Zend]
Zend_extension="/usr/lib64/php/modules/eaccelerator.so"

zend_extension_manager.optimizer=/usr/local/Zend/lib/Optimizer-3.3.3
zend_extension_manager.optimizer_ts=/usr/local/Zend/lib/Optimizer_TS-3.3.3
zend_optimizer.version=3.3.3
zend_extension=/usr/local/Zend/lib/ZendExtensionManager.so
zend_extension_ts=/usr/local/Zend/lib/ZendExtensionManager_TS.so

Базовая установка LAMP в Debian

June 7th, 2009

Ставим апач:

apt-get install apache2 php5 libapache2-mod-php5 php5-curl

Конфиги в /etc/apache2/
Для добавления виртуалхоста создаем его конфиг (domain.com) в /etc/apache2/sites-available/ и:

a2ensite domain.com

Для выключения:

a2dissite domain.com

Для включения модулей апача:

a2enmod rewrite

Ставим мускул:

apt-get install mysql-server mysql-client php5-mysql

Конфиги в /etc/mysql/

Ставим nginx:

apt-get install nginx

Базовая настройка ipfilter

June 3rd, 2009

К пакету применяется последнее подходящее правило.
Параметры в rc.conf:

ipfilter_enable="YES"             # Запуск межсетевого экрана ipf
ipfilter_rules="/etc/ipf.rules"   # Загрузка файла с правилами
gateway_enable="YES"              # Включение шлюза для локальной сети
ipnat_enable="YES"                # Если надо задействовать nat
ipnat_rules="/etc/ipnat.rules"    # Определение файла правил для ipnat

Примеры правил в ipf.rules:

pass out quick on lo0 proto ip from any to any
pass in quick on lo0 proto ip from any to any
pass in quick on fxp1 proto tcp from any to 1.2.3.1/32 port = 80 flags S keep state
pass out log quick on fxp1 from 1.2.3.1/32 to any
pass in quick on fxp1 proto icmp from any to any icmp-type 0
pass in quick on fxp1 proto icmp from any to any icmp-type 11
block in log quick on fxp1 proto icmp from any to any
block return-icmp(port-unr) in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 111

quick означает, что если анализируемый пакет подпадает под данное правило, то дальнейший просмотр правил прекращается.
keep state означает, что так же будут разрешены все пакеты, которые пойдут по этому же соединению в том числе в обратную сторону.

Примеры редиректов в ipnat.rules:

map tun0 192.168.1.0/24 -> 20.20.20.1/32
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000

Запускаем:

/etc/rc.d/ipfilter start
/etc/rc.d/ipnat start

Команды:

ipf -Fa -f /etc/ipf.rules # сбросить все правила и загрузить новые из файла                              
ipfstat -in # вывод правил для входящего трафика
ipfstat -on # вывод правил для исходящего трафика
ipfstat -t # просмотр текущей статистики в виде TOP-а
ipnat -l # смотрим текущие редиректы для ipnat
/etc/rc.d/ipnat reload #для перезагрузки правил ната

Изменение media для сетевухи под linux

June 3rd, 2009

Меняем:

ethtool --change eth0 autoneg off speed 10 duplex full

Чтобы действовало после перезагрузки добавляем в файл /etc/sysconfig/network-scripts/ifcfg-eth0:

ETHTOOL_OPTS="autoneg off speed 10 duplex full"

Обслуживание и восстановление баз MySQL

May 25th, 2009

Проверка и восстановление всех баз:

mysqlcheck --repair --analyze --all-databases --auto-repair

Оптимизация всех таблиц всех баз:

mysqlcheck --all-databases --optimize

Скрипт создания mysql-баз по списку из файла

May 18th, 2009

Скрипт читает построчно из файла и создает базы с таким именем и юзером. Пароли к ним генерит.
Внимание к длине имени базы! (не больше 16 символов)

#!/bin/bash

SQLUSER=root
SQLPASS=password

cat /home/admin/bases | while read base; do

    PASS=`< /dev/urandom tr -dc A-Za-z0-9 | head -c15`

    echo "CREATE DATABASE $base;"|mysql --password=$SQLPASS
    echo "GRANT ALL PRIVILEGES ON $base.* TO "$base"@"localhost" IDENTIFIED BY \"$PASS\";"|mysql --password=$SQLPASS

    echo "User: $base Password: $PASS"

done

echo "FLUSH PRIVILEGES;" | mysql --password=$SQLPASS

RSS-подписка