Настройка связки Graphite+uwsgi+nginx

Задача: Установить и настроить Graphite для последующей его интеграции с icinga1/icinga2/Nagios/Grafana.
Мануалы предлагают установить это посредством pip и прикрутить с боку apache+mod_wsgi. На мой взгляд это ресурсоемко, да и не для того придумали бинарные дистрибутивы, чтобы из сырцов что то собирать.

Итак

Гуглим установку и настройку Graphite на любимый дистрибутив, благо мануалов по его установке, как говна за баней. Единственно там предлагается установить apache+mod_wsgi, который я и заменяю на nginx+uwsgi. Приведу свои конфиги с Debian 9.

/etc/uwsgi/apps-enabled/graphite.ini
[uwsgi]
processes = 2
uid = _graphite
gid = _graphite
chdir = /usr/share/graphite-web
pythonpath = "['/usr/share/graphite-web'] + sys.path"
manage-script-name = true
mount = /graphite=/usr/share/graphite-web/graphite.wsgi
socket = 127.0.0.1:3031
plugins = python
module = wsgi:application

plugins = carbon
enable-metrics = true
carbon-use-metrics = true
carbon-id = %n
carbon = 127.0.0.1:2003
/etc/nginx/sites-enabled/graphite.local`
server {
        listen      80;
        server_name graphite.local;
        charset     utf-8;
        location / {
                include uwsgi_params;
                uwsgi_pass 127.0.0.1:3031;
        }
}
Так же предлагаю обмазаться вот этим циклом статей.

Phing, запрос перед выполнением

Изобретая очередной костыль, сирчеь deploy-конфиг, выпилил базу данных и конфиги с рабочего проекта.
Благо предыдущий таск бэкапил все и вся. Теперь буду осторожнее и напишу таск, который спрашивает, уверен ли я в том, что делаю.
Собственно вот:
<target name="test">
    <!-- propertyname есть аргмент arg1, с которым идет сравнение в equals -->
        <input propertyname="confirm" defaultValue="no" validargs="yes,no">This action will erase the database. Are you sure? </input>
        <if>
            <equals arg1="${confirm}" arg2="yes" />
            <then>
                <!-- Последовательно вызываем нужные таски, как если бы использовали depends-->
                <phingcall target="clean" />
                <phingcall target="composer" />
                <phingcall target="db" />
                <phingcall target="migrate" />
            </then>
            <else>
                <!-- Иначе прерываем исполнение -->
                <echo>Execution stopped</echo>
            </else>
        </if>
    </target>
Теперь Phing попробует разубедить нас в нашей правоте, тем самым экономя вазелин разнородного начальства.

Раздача IPv6 по OpenVPN туннелю

IPv6 когда то придет в массы. Быть может к нашей пенсии. Мы же, как можем, приближаем этот момент. С выделенными адресами ситуация все ухудшается. В некоторых регионах страны Ростелеком перестал выдавать белые адреса физическим лицам. А белый адрес страсть как нужен, для адекватной работы 4to6. Можно периодически дергать API туннельного брокера, сообщая свой IPv4, но кому это нужно, когда проще купить виртуалку со статикой?
IPv6 это круто, модно, молодежно. И порой даже быстро. Но нафиг не нужно провайдерам.
Задача: Выпустить корпоративную сеть в мир по IPv6.
Имеется: VDS на flops.ru со статикой и туннель от he.net.
Настройка тунеля хорошо описана на сайте he.net, при создании туннеля даже выдается конфиг под разные ОС. Дополнительно нужно получить /48 подсеть.
Шаманим на сервере:
apt-get install openvpn radvd iptables-persistent
echo ipv6 >> /etc/modules
echo net.ipv6.conf.all.forwarding=1 >> /etc/sysctl.conf
echo net.ipv6.conf.default.forwarding=1 >> /etc/sysctl.conf
iptables -A FORWARD -s 10.0.1.0/24 -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -o eth0 -j MASQUERADE
service iptables-persistent save
touch /etc/openvpn/route.sh
chmod +x /etc/openvpn/route.sh
Как генерировать сертификаты описано в документации к OpenVPN, приводить не буду.
Конфиг OpenVPN /etc/openvpn/server.conf:
# Тип севера
tls-server
# Порт сервера
port 1194
# Разработчик OpenVPN рекомендует UDP, но его не умеет Mikrotik, который я юзаю.
proto tcp
# Интерфейс
dev tap
# Сертификаты сервера
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/server.crt
key /etc/openvpn/keys/server.key
dh /etc/openvpn/keys/dh1024.pem
tls-auth /etc/openvpn/keys/ta.key 0
# Список заблокированых сертификатов
crl-verify /etc/openvpn/keys/crl.pem
# Директория с конфигами статических клиентов
client-config-dir /etc/openvpn/ccd
# Адрес внутренней VPN сети
server 10.0.1.0 255.255.255.0
ifconfig 10.0.1.1 255.255.255.0
# DNS сервер
push "dhcp-option DNS 10.0.1.1"
# Адрес I
Pv6 шлюза в мир
push "route-ipv6 2001:470:xxxx:1::/64"
# Не «передергивать» сетевое устройство при перезапуске демона
persist-tun
#
script-security 3
# Скрипт который правит роутинг при запуске сервера
up /etc/openvpn/route.sh
#
client-to-client
# Каждые 10 секунд посылать ping на удаленный хост, и, если за 30 секунд не было получено ни одного пакета - то перезапускать туннель
keepalive 10 30
# Шифрование
cipher BF-CBC
# Файл статуса сервера
status /var/log/openvpn-stat
# Файл лога сервера
log-append /var/log/openvpn.log
Файл /etc/openvpn/route.sh:
#!/bin/sh
ip addr add 2001:470:xxxx:1::1/64 dev tap0
Конфиг radvd /etc/radvd.conf:
interface tap0
{
    AdvSendAdvert on;
    prefix 2001:470:xxx:1::/64
    {
        AdvOnLink on;
        AdvAutonomous on;
        };
};
Конфиг сети (eth0 смотрит в мир) /etc/network/interfaces:
auto eth0
iface eth0 inet static
	# IP адрес 
	address xxx.xxx.xxx.xxx
	# Маска сети
	netmask 255.255.255.0
	# Широковещательный адрес
	broadcast xxx.xxx.xxx.xxx
	# Шлюз 
	gateway xxx.xxx.xxx.xxx
	# DNS
	dns-nameserver 127.0.0.1
	# IPv6 адрес
	up ip addr add 2001:470:xxxx:0::1/64 dev eth0
Конфиг OpenVPN клиента выглядит примерно так:
tls-client
client
proto tcp
remote xxx.xxx.xxx.xxx 1194
dev tap
tls-auth /etc/openvpn/keys/ta.key 1
dh /etc/openvpn/keys/dh1024.pem
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/10.0.1.2.crt
key /etc/openvpn/keys/10.0.1.2.key
cipher BF-CBC
keepalive 10 30
log-append /var/log/openvpn.log
persist-tun
Перезагружаем сервер. Для фанатов работы без перезагрузки могу сказать, что устройство sit0 (на котором поднимается туннель) не придет, даже если включить модуль ipv6 руками. Ну вот не придет, хоть ты тресни. Ну или я ниасилил.
Подключаемся клиентом к vpn и проверяем:
ping6 -n ya.ru -c 4
Должно выйти примерно так:
PING ya.ru(2a02:6b8::3) 56 data bytes
64 bytes from 2a02:6b8::3: icmp_seq=1 ttl=56 time=158 ms
64 bytes from 2a02:6b8::3: icmp_seq=2 ttl=56 time=123 ms
64 bytes from 2a02:6b8::3: icmp_seq=3 ttl=56 time=121 ms
64 bytes from 2a02:6b8::3: icmp_seq=4 ttl=56 time=122 ms

--- ya.ru ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 121.274/131.460/158.149/15.443 ms
Как уже писалось ранее, есть такая штука как Phing. Бывает, что проекту для работы требуется сторонние файлы.
В моем случае это сторонняя база данных. Весит она много и распространять ее с проектом нет особого смысла, т.к. данные меняются от релиза к релизу.
Но есть Phing!
Принесем ему зависимости:
composer global require  pear/http_request2: dev-master
На момент публикации нужна именно master-ветка, т.к. Phing споткнется об Pear.
Собственно таск:
<target name="getSde" desription="Download EVE SDE">
        <httpget url="https://www.fuzzwork.co.uk/dump/latest/eve.db.bz2" dir="${src}/data" sslverifypeer="false">
        <if>
            <os family="unix">
            <then>
                <echo>Exec bzip2 -dfsv ${src}/data/eve.db.bz2</echo>
                <exec executable="bzip2" passthru="true" checkreturn="true">
                    <arg value="-dfvs">
                    <arg value="${src}/data/eve.db.bz2">
                </arg></arg></exec>
            </then>
            <else>
                <echo level="error">Extract base ${src}/data/eve.db.bz2 in directory ${src}/data!</echo>
            </else>
        </os></if>
    </httpget>
</target>
Данный таск скачивает базу своими средствами и распаковывает ее средствами ОС.
Можно было сделать таск с wget-ом или curl-ом, но я спотыкался об отсутсвие того и другого в production-окружении, куда я не имею root-доступа.

Vagrant на NTFS разделе

Vagrant под Linux не хочет работать с ssh-ключами на ntfs-разделе. В момент развертывания виртуалки он говорит примерно так:

Key inserted! Disconnecting and reconnecting using new SSH key...
The private key to connect to the machine via SSH must be owned
by the user running Vagrant. This is a strict requirement from
SSH itself. Please fix the following key to be owned by the user
running Vagrant:

/media/sda3/home/devchroot/.vagrant/machines/default/virtualbox/private_key

Все потому что раздел по умолчанию монтируется не с теми правами. Дабы все было хорошо, монтировать диск надо вот с такими опциями:

mount /dev/sda3 /media/sda3 -t ntfs-3g -o uid=1000,gid=1000,dmask=002,fmask=0177

где uid и gid соотвествуют вашему пользователю в системе (можно посмотреть позвав id в консоли).

Можно принести шаблон в /home, но у меня директория с проектами слинкована в ntfs-раздел.

Убираем "No valid subscription" в Proxmox 3.3

Proxmox это прекрасно. Но на подписку пока нет финансов, а просьба "подписаться" на этапе настройки несколько утомляет. В сети есть патч для 3.2, но он не подойдет.

Лечится это вот таким патчем:

--- /usr/share/pve-manager/ext4/pvemanagerlib.js.orig   2014-09-08 12:32:15.000000000 +0400
+++ /usr/share/pve-manager/ext4/pvemanagerlib.js        2015-03-23 02:53:46.000000000 +0400
@@ -458,23 +458,7 @@
            },
            success: function(response, opts) {
                var data = response.result.data;
-
-               if (data.status !== 'Active') {
-                   Ext.Msg.show({
-                       title: gettext('No valid subscription'),
-                       icon: Ext.Msg.WARNING,
-                       msg: PVE.Utils.noSubKeyHtml,
-                       buttons: Ext.Msg.OK,
-                       callback: function(btn) {
-                           if (btn !== 'ok') {
-                               return;
-                           }
-                           orig_cmd();
-                       }
-                   });
-               } else {
-                   orig_cmd();
-               }
+               orig_cmd();
            }
        });
     },

Включение IPv6 в Proxmox

Разжился IPv6 подсетью. Это удобно. Встала задача выпускать OpenVZ/KVM контейнеры в мир по v6. Обычно для этой операции хватает одного radvd. В Proxmox он по умолчанию отключен. И включить его надо до загрузки radvd. Либо libhands.so сегфолтится, либо еще какая причина, но modprobe мне не помог.

Включается оно так:

echo ipv6 >> /etc/modules
echo net.ipv6.conf.all.forwarding=1 >> /etc/sysctl.d/ipv6.conf

После таких манипуляций radvd не будет возмущаться на отключенный v6-форвардинг.


Phing, cron task

Есть такая штука как Phing. Это как Ant только Phing.
Позволяет совершать тривиальные задачи по развертыванию проекта на сервере, как то: настройка прав доступа к директориям/файлам, копирование чего то куда то, миграции и т.д. Но вот с заданиями для cron там беда.
Существующие, легко нагугливаемые примеры предлагают писать задания в /etc/cron.d/, куда на обычном shared-хостинге мы естественно не имеем доступа. Ну или предлагают нам sudo, что тоже слегка не то.

Но есть task exec!
Итак:
$ touch build.xml
$ nano build.xml
Приведем наш build к следующему виду:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Phing build config -->
<project name="test" basedir="." default="deploy">
    <target name="set_crontab" description="Set Crontab">
        <exec
            command='/bin/echo -en "`crontab -l 2>/dev/null`\n0 * * * *  php `pwd`/protected/yiic update\n\n" | crontab - 2>/dev/null'
            passthru="true" checkreturn="true" />
    </target>
    
    <!-- Default target -->
    <target name="deploy" depends="set_crontab"></target>
</project>
Запустим phing и увидим нечто такое:
$ phing
Buildfile: /home/vagrant/build.xml

test > set_crontab:


test > deploy:


BUILD FINISHED

Total time: 0.0925 seconds
Выполнится буквально следующий код:
/bin/echo -en "`crontab -l 2>/dev/null`\n0 * * * *  php `pwd`/protected/yiic update\n\n" | crontab - 2>/dev/null
Сказав в той же консоли 'crontab -l' увидим нечто такое:
$ crontab -l

0 * * * *  php /home/vagrant/protected/yiic update
Congratulations!

Есть ли брак после 35-и?

Серфя сегодня интернетики, набрел на знатное чтиво в тему гендерного срача

Прогрессбар для MySQL

Вот тут мы попросили dd говорить о прогрессе действий, и поняли, что это хорошо. Давайте попросим то же самое сделать и MySQL.

Заливаем дамп из файла:
pv -n dump.sql | mysql -u user -ppassword database
Вариант с zcat (можно заливать дампы в *.gz архивах):
zcat dump.sql.gz | pv -cN zcat | mysql -u user -ppassword database
И рюшечки, куда же без них:
(pv -n dump.sql | mysql -u user -ppassword database) 2>&1 | dialog --gauge "Restore database, please wait..." 10 70 0