воскресенье, 30 марта 2014 г.

Настройка MiniDLNA для цифрового мультимедийного плеера WD TV Play

Не столь давно я решил отказаться от видеокарты с разъёмом S-Video, к которому у меня дома был подключен телевизор. Новых видеокарт с таким разъёмом сейчас не найти, везде только VGA, DVI и HDMI. Конвертеры из HDMI и DVI в композитный, компонентный сигнал или в S-Video стоят неоправданно больших денег, причём найти их в продаже - задача непростая. Покупать вместе с новой видеокартой ещё и новый телевизор с разъёмом HDMI мне не хотелось.

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

Единственным оставшимся решением, которое позволило бы смотреть фильмы с компьютера на старом телевизоре, были цифровые мультимедийные проигрыватели. Это небольшие устройства с жёстким диском или без него, умеющее воспроизводить видео, музыку с SATA-дисков, флеш-накопителей, карт памяти или из сети Ethernet или WiFi.

После сравнения доступных предложений мой выбор пал на устройство WD TV Play. Это устройство не имеет жёсткого диска или места под его установку, более того - у него даже нет интерфейса SATA, но зато у него есть всё нужное мне: композитный видеовыход, выход для аналогового стерео и сеть Ethernet. Кроме того, имеется поддержка WiFi и разъёмы, которые могут пригодиться в дальнейшем: USB, HDMI, оптический SPDIF.

Подробную инструкцию по настройке самого устройства можно найти на его странице. Для лентяев приведу прямую ссылку на руководство: Руководство пользователя.

Внешний видПульт

1. Как это работает

Итак, в целом автоконфигурирование сети на домашних устройствах работает примерно следующим образом.

Если устройству не назначен сетевой адрес вручную, то оно сначала пытается получить настройки у DHCP-сервера. Если DHCP-сервер не отвечает, устройство выбирает случайный адрес из диапазона 169.254.1.0-169.254.255.255 и проверяет, что он свободен, выполняя ARP-запрос. Если адрес занят, устройство выбирает другой случайный IP-адрес и повторяет процедуру до тех пор, пока не обнаружит свободный IP-адрес. С выбранным адресом используется маска подсети 255.255.0.0.

После того, как сеть настроена, устройство отправляет мультикаст-запрос на адрес 239.255.255.250, на UDP-порт 1900, пытаясь обнаружить по протоколу SSDP устройства в локальной сети. Каждое устройство, предоставляющее сервис, должно ответить на запрос, сообщив в ответе HTTP-ссылку на страницу управления устройством.

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

2. Как будем настраивать

Я не буду использовать автоконфигурирование и ручную настройку сети, а воспользуюсь более привычным для системного администратора способом раздачи настроек - при помощи DHCP-сервера ISC DHCP Server. Если у вас дома есть маршрутизатор, раздающий настройки по DHCP, или использующий самоназначенные адреса, то логично воспользоваться вместо DHCP-сервера DHCP-клиентом с поддержкой самоназначения адресов (APIPA), например из пакета dhcpcd5.

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

Наконец, я буду использовать лишь один DLNA-сервер, поэтому он самостоятельно будет отвечать на запросы по протоколу SSDP. Если планируется настроить несколько DLNA-серверов или интегрировать их с IGD-сервером, то скорее всего вам потребуется отдельный сервер протокола SSDP, например из пакета minissdp. Теоретически, остальные приложения можно настроить так, что они будут работать через minissdp как через посредника. На практике я этого не проверял.

3. Настройка сетевого интерфейса

Моя домашняя компьютерная сеть подключена к отдельной сетевой карте компьютера. Я использую сеть 169.254.254.0/24, которая входит в диапазон IP-адресов link-local 169.254.1.0-169.254.254.255, который описан в RFC 3927. Этот диапазон используется для автоматической настройки сети на устройствах, которые не смогли найти DHCP-сервер. Устройство выбирает случайный адрес из этого диапазона и делает ARP-запрос к нему. Если на ARP-запрос никто не отвечает, устройство присваивает этот адрес себе. Если адрес занят, то процедура поиска свободного адреса повторяется.

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

Настройки интерфейс eth1 описываются в файле /etc/network/interfaces и имеют следующий вид:
auto eht1
iface eth1 inet static
  address 169.254.254.1
  netmask 255.255.255.0
Всё просто. Чтобы настройки вступили в силу, можно воспользоваться следующими командами:
# ifdown eth1
# ifup eth1
4. Настройка DHCP-сервера

Устройство я включил в домашнюю локальную сеть, которая подключена к отдельной сетевой карте компьютера. Если у вас есть домашний маршрутизатор, можете воткнуть устройство в него - в таком случае можно воспользоваться DHCP-сервером, встроенным в сам маршрутизатор. Можно также настроить статические IP-адреса или попытать счастья с автоматической настройкой сетевого интерфейса без участия DHCP-сервера, например, при помощи демона avahi-autoipd.

Чтобы устройство могло получить настройки сети от компьютера автоматически, я настроила на своём компьютере DHCP-сервер. Мой выбор автоматически остановился на привычном мне ISC DHCP Server, что кому-то может показаться забиванием гвоздей микроскопом. Вы можете настроить другой DHCP-сервер.

Итак, установим пакет с DHCP-сервером:
# apt-get install isc-dhcp-server
Создадим файл конфигурации /etc/dhcp/dhcpd.conf со следующим содержимым:
# Не нужно пытаться обновлять данные на DNS-сервере
ddns-update-style none;

# Этот DHCP-сервер в сети - главный
authoritative;

# "Средство" syslog, которое DHCP-сервер будет использовать для отправки
# диагностических сообщений в syslog
log-facility local7;

subnet 169.254.254.0 netmask 255.255.255.0 {
  # Диапазон адресов, выдаваемый в аренду
  range 169.254.254.2 169.254.254.254;

  # Суффикс, используемый для решения запросов с неполным доменным именем
  option domain-name "stupin.su";

  # Локальный кэширующий DNS-сервер (настройка не описана)
  option domain-name-servers 169.254.254.1;

  # Клиент должен продлевать аренду по прошествии суток
  default-lease-time 86400;

  # Аренда считается истекшей по истечение двух суток
  max-lease-time 172800;

  # Локальный NTP-сервер (настройка не описана)
  option ntp-servers 169.254.254.1;
  
  # Маршрут по умолчанию
  option routers 169.254.254.1;
  
  # Широковещательный адрес сети
  option broadcast-address 169.254.254.255;
}

host wd {
  hardware ethernet 00:90:a9:62:b2:99;
  fixed-address 169.254.254.2;
}
В файл /etc/default/isc-dhcp-server впишем имя интерфейса, на котором DHCP-сервер должен принимать запросы:
INTERFACES="eth1"
Осталось перезапустить DHCP-сервер, чтобы его новые настройки вступили в силу:
# /etc/init.d/isc-dhcp-server restart
На самом деле устройство способно работать только с первым DNS-сервером, а NTP-серверы он попросту игнорирует, предпочитая всегда пользоваться серверами pool.ntp.org.

Мой плеер имеет MAC-адрес 00:90:a9:62:b2:99 - его я узнал при помощи tcpdump. Этому MAC-адресу всегда будет выдаваться один и тот же IP-адрес 169.254.254.2.

5. Настройка фаерволла

До сих пор у меня ещё не было повода расписывать, как я обычно настраиваю фаерволл, поскольку обычно мне приходится настраивать прохождение пакетов для классических интернет-протоколов, вроде HTTP, FTP, SMTP, POP3, IMAPv4, DNS, NTP. Там всё довольно просто - достаточно открыть TCP или UDP-порт в нужном направлении, а в случае FTP ещё загрузить несколько модулей ядра и прописать их в автозагрузку.

В этом случае речь идёт о протоколе под названием SSDP, который не назовёшь классическим. Поэтому я решил описать настроенные правила в этой заметке. Однако, для начала я опишу минимальную настройку фаерволла для рабочей станции, на которой не запущен ни один сетевой сервис. Обычно я ограничиваюсь всего тремя правилами и политикой по умолчанию для входящих пакетов DROP:
# iptables -A INPUT -s 127.0.0.1/32 -i lo -j ACCEPT
# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -p icmp -m icmp ! --icmp-type 5 -j ACCEPT
# iptables -P INPUT DROP
При такой конфигурации наш компьютер может инициировать обмен с кем угодно, получать от него ответы, но сам будет отвечать только на ICMP-запросы.

Для того, чтобы эти настройки восстанавливались при каждой загрузке, я сохраняю их при помощи команды iptables-save:
# iptables-save > /etc/network/iptables
И прописываю загрузку правил при настройке интерфейса lo в файле /etc/network/interfaces:
auto lo
iface lo inet loopback
  pre-up iptables-restore < /etc/network/iptables
Теперь перейдём к настройке доступа со стороны мультимедиа-центра к серверу MiniDLNA на нашем сервере:
# iptables -A INPUT -i eth1 -s 169.254.254.2 -d 169.254.254.1 -p tcp -m tcp --dport 8200 -j ACCEPT
# iptables -A INPUT -i eth1 -s 169.254.254.2 -d 169.254.254.1 -p udp -m udp --dport 1900 -j ACCEPT
# iptables -A INPUT -i eth1 -s 169.254.254.2 -d 239.255.255.250 -p udp -m udp --dport 1900 -j ACCEPT
UDP-порт 1900 - это порт протокола SSDP, позволяющего устройствам сети обнаруживать друг друга и обмениваться информацией. Для обнаружения используется мультикаст-адрес 239.255.255.250.

На TCP-порту 8200 работает встроенный в MiniDLNA веб-сервер. На нём есть всего одна страница, на которой можно увидеть количество доступных на сервере видео-, аудио- и графических файлов. В случае более сложных DLNA серверов там может быть, например, веб-интерфейс для управления устройством и т.п. Устройства узнают о веб-серверах друг друга по протоколу SSDP.

Кроме того, устройство обращается в сеть интернет для получения данных о времени, о погоде в выбранном городе и при использовании онлайн-сервисов. Настроим правила фаерволла для транзитных пакетов:
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -P FORWARD DROP
Эти правила разрешают проход пакетов, относящихся к уже открытым установленным соединениям. Всем остальным пакетам по умолчанию ход запрещён - такие пакеты будут просто отбрасываться. Любые разрешения должны быть прописаны в фаерволл явным образом.

Чтобы плеер не ждал истечения таймаута при обращении к серверам производителя при попытке проверить наличие обновлений, я запрещу плееру обращаться к веб-серверам так, чтобы в ответ на попытки установить подключение к веб-серверу, плееру приходил ICMP-пакет, сообщающий о том, что соответствующий порт сервера закрыт:
# iptables -A FORWARD -i eth1 -s 169.254.254.2 -p tcp -m multiport --dports 80,443 -j REJECT --reject-with icmp-port-unreachable
Закрываю доступ по одной простой причине - этим плеером можно управлять через интернет, с веб-сайта производителя, что я считаю огромной дырой в системе безопасности.

Так как плеер не умеет использовать NTP-сервер, выданный DHCP-сервером, а всегда обращается к серверам pool.ntp.org, добавим в правила фаерволла принудительное перенаправление всех пакетов, идущих со стороны плеера на UDP-порт 123, на UDP-порт 123 моего NTP-сервера и разрешим пакетам ходить в этом направлении:
# iptables -A PREROUTING -i eth1 -s 169.254.254.2 -p udp -m udp --dport 123 -j DNAT --to-destination 169.254.254.1:123
# iptables -A FORWARD -i eth1 -s 169.254.254.2 -d 169.254.254.1 -p udp -m udp --dport 123 -j ACCEPT
Поскольку моя домашняя сеть не будет маршрутизироваться в сети провайдера, я выполняю трансляцию исходного адреса на внешних, провайдерских интерфейсах:
# iptables -A POSTROUTING -o ppp0 -j MASQUERADE
# iptables -A POSTROUTING -o eth0 -j MASQUERADE
Ответные пакеты будут транслироваться в обратном направлении автоматически. Осталось запомнить новые настройки фаерволла в файле /etc/network/iptables и включить маршрутизацию:
# iptables-save > /etc/network/iptables
# sysctl -w net.ipv4.conf.all.forwarding=1
Чтобы маршрутизация автоматически включалась при перезагрузке, пропишем в файл /etc/sysctl.conf ту же самую настройку:
net.ipv4.conf.all.forwarding = 1
6. Настройка MiniDLNA

Остался финальный штрих - настройка самого сервера MiniDLNA. Для этого нужно прописать в файл /etc/minidlna.conf следующие настройки:
# Прописываем каталоги с видео-, аудио и графическими файлами
# Можно указывать произвольное количество каталогов, можно не указывать тип источника
media_dir=V,/home/video
media_dir=A,/home/music
media_dir=P,/home/photos

# Слушать будем указанный интерфейс и IP-адрес
network_interface=eth1
listening_ip=169.254.254.1

# TCP-порт встроенного веб-сервера
port=8200

# Имя хранилища, под которым его будет видно на других устройствах
friendly_name=stupin.su minidlna

# Серийный номер нашего хранилища, модель и номер модели
serial=12345678
model_name=Windows Media Connect compatible (MiniDLNA)
model_number=1

# Использовать механизм inotify:
# ядро Linux будет оповещать MiniDLNA об изменении интересующих файлов
inotify=yes

# В качестве обложек музыкальных альбомов использовать файлы с указанными именами
album_art_names=Cover.jpg/cover.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg
По умолчанию MiniDLNA сам открывает UDP-порт 1900 протокола SSDP. Но, если вы собрались запустить на компьютере несколько программ, которые используют протокол SSDP, можно настроить отдельный SSDP-сервер MiniSSDP. Сокет-файл этого сервера можно в дальнейшем указывать всем программам, которые пользуются протоколом SSDP. В случае MiniDLNA путь к сокет-файлу указывается в конфигурационном файле /etc/minidlna.conf, в настройке minissdpdsocket.

Осталось убедиться, что в файле /etc/default/minidlna разрешён запуск сервера:
START_DAEMON="yes"
И можно запустить его:
# /etc/init.d/minidlna restart
Задняя панельТелевизор

7. Ссылки

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

Ниже приведён небольшой список ссылок на краткое описание различных протоколов, имеющих отношение к автоматической настройке локальной сети:
  • Zeroconf - описание самой идеи собирательного названия Zeroconf, диапазона локальных адресов для самонастройки IPv4LL - IPv4 Link-Local, способа самонастройки локальных адресов APIPA - Automatic Private IP Addressing
  • RFC 3927 - формальное описание диапазона локальных адресов для самонастройки IPv4LL - IPv4 Link-Local
  • UPnP - описание группы протоколов Universal Plug and Play
  • SSDP - описание протокола обнаружения сервисов Simple Service Discovery Protocol, входящего в группу протоколов UPnP
  • DLNA - описание протокола Digital Living Network Alliance для обмена мультимедийными данными, входящего в группу протоколов UPnP
  • IGD - описание протокола настройки шлюза Internet Gateway Device Protocol
  • NAT-PMP - другой протокол управления шлюзом NAT Port Mapping Protocol
  • PCP - ещё один протокол управления шлюзом Port Control Protocol
P.S. 8 апреля 2018 года внесён ряд правок в настройки фаерволла: веб-трафик запрещён с ICMP-сообщением о закрытом порте, NTP-трафик перенаправляется на локальный NTP-сервер.

воскресенье, 23 марта 2014 г.

Установка и настройка TinyTinyRSS

TinyTinyRSS - это веб-приложение для чтения RSS-подписок. Оно использует MySQL для хранения учётных записей пользователей и информации из лент новостей. Для обновления лент используется отдельный демон или скрипт, запускаемый при помощи планировщика задач.

1. Скачивание и распаковка

Находим на странице http://tt-rss.org/redmine/projects/tt-rss/wiki ссылку на скачивание. Скачиваем тарболл и распаковываем:
$ wget https://github.com/gothfox/Tiny-Tiny-RSS/archive/1.11.tar.gz
$ tar xzvf Tiny-Tiny-RSS-1.11.tar.gz
Перемещаем каталог с приложением туда, откуда к нему будет обращаться веб-сервер:
# mv Tiny-Tiny-RSS-1.11 /usr/local/share/ttrss
И даём веб-серверу права доступа к каталогу с приложением:
# chown www-data:www-data /usr/local/share/ttrss
# find /usr/local/share/ttrss -type d -exec chmod u=rwx,g=rx,o= \{\} \;
# find /usr/local/share/ttrss -type f -exec chmod u=rw,g=r,o= \{\} \;
2. Настройка пула в php5-fpm

Если php5-fpm ещё не был установлен, время сделать это:
# apt-get install php5-fpm
По умолчанию в php5-fpm имеется общий пул, настройки которого находятся в файле /etc/php/fpm/pool.d/www.conf, но в данном случае я предпочту настроить для этого приложения отдельный пул, поскольку это приложение будет использоваться редко и я не хочу постоянно держать запущенными лишние процессы. Кроме того, разные пулы, даже будучи запущенными от имени одного и того же пользователя, позволяют снизить эффект взаимного влияния разных приложений друг на друга: если одно из приложений вдруг начнёт использоваться больше остальных, оно не займёт процессы других пулов, выделенные для обработки других приложений.

Создадим файл пула /etc/php5/fpm/pool.d/rss.conf со следующим содержимым:
[rss]
user = www-data
group = www-data
listen = /var/run/rss.sock

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = ondemand
pm.max_children = 2
pm.process_idle_timeout = 10m

access.log = /var/log/rss.access.log
Пул называется rss, процессы пула работают от имени пользователя www-data и группы www-data. Пул обрабатывают запросы, поступающие на юникс-сокет /var/run/rss.sock, доступный на чтение и запись только пользователю и группе www-data. Процессы пула порождаются только при обращении и завершаются, если к ним не было обращений более 10 минут. В пуле может быть не более 2 процессов. Журнал обработанных запросов будет вестись в файле /var/log/rss.access.log

Осталось перезагрузить php5-fpm, чтобы добавить новый пул:
# /etc/init.d/php5-fpm reload
3. Настройка веб-сервера nginx

Если в системе ещё не установлен веб-сервер nginx, поставим его:
# apt-get install nginx-light
Теперь можно отредактировать файл /etc/nginx/sites-available/default, добавив в него следующую секцию:
location /rss {
  alias /usr/local/share/ttrss;

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/rss.sock;
    fastcgi_index index.php;

    include fastcgi_params;
  }
}
Если нужно настроить TinyTinyRSS для работы на отдельном доменном имени, например rss.domain.tld, то можно создать файл /etc/nginx/sites-available/rss со следующим содержимым:
server {
  listen 80;

  server_name rss.domain.tld;

  root /usr/local/share/ttrss;

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/rss.sock;
    fastcgi_index index.php;

    include fastcgi_params;
  }
}
Чтобы вновь созданная конфигурация была задействована, нужно создать символическую ссылку на неё в каталоге /etc/nginx/sites-enabled/:
# cd /etc/nginx/sites-enabled/
# ln -s /etc/nginx/sites-available/rss rss
Осталось перезапустить веб-сервер:
# /etc/init.d/nginx restart
4. Подготовка базы данных

Разработчики TinyTinyRSS рекомендуют для хранения настроек и лент использовать СУБД PostgreSQL, но возможно использовать и MySQL. Именно его я и настрою. Если сервер MySQL ещё не установлен, сделайте это:
# apt-get install mysql-server-5.5
После установки СУБД, нужно подготовить пустую базу данных и пользователя, от имени которого приложение будет подключаться к базе данных. Соответственно, этот пользователь должен иметь полный доступ к своей базе данных. Создадим базу данных и пользователя:
$ mysql -uroot -p mysql
> CREATE DATABASE rss CHARSET UTF8;
> INSERT INTO user(user, password, host) VALUES('rss', PASSWORD('rss_password'), 'localhost');
> FLUSH PRIVILEGES;
> GRANT ALL ON rss.* TO rss@localhost;
> FLUSH PRIVILEGES;
Вместо пароля rss_password я подставил 16-символьный пароль, сгенерированный программой pwgen из одноимённого пакета:
$ pwgen 16
5. Веб-настройка приложения

Теперь перейдём на страницу настройки веб-сервера http://domain.tld/rss/install/ или http://rss.domain.tld/install/, в зависимости от выбранного вами варианта настройки веб-сервера:

Вводим настройки подключения к базе данных и нажимаем кнопку "Test configuration":
Ввод настроек подключения к базе данных

После успешной проверки подключения к базе данных нажимаем на кнопку "Initialize database":
Инициализация базы данных

Запоминаем имя созданного пользователя admin и его пароль password, а затем сохраняем сгенерированный файл конфигурации нажатием на кнопку "Save configuration":
Сохранение конфигурации

После того, как конфигурация сохранилась, можно перейти по ссылке с текстом "loading tt-rss now":
Переход по ссылке

Страница входа в приложение:
Вход в приложение

Не забудьте сразу же войти в систему и поменять пароль пользователя admin на нечто более сложное, нежели слово password.

6. Настройка демона обновлений

На странице http://tt-rss.org/redmine/projects/tt-rss/wiki/UpdatingFeeds описано несколько разных способов обновления RSS-лент. Я решил остановиться на многопроцессном демоне обновлений update_daemon2.php. Добавим демону права на запуск:
# chmod ug+x /usr/local/share/ttrss/update_daemon2.php
Теперь создадим init-файл /etc/init.d/ttrss для управления демоном (его можно скачать по ссылке http://stupin.su/files/ttrss):
#!/bin/sh
### BEGIN INIT INFO
# Provides:          ttrss
# Required-Start:    $syslog $remote_fs $network
# Required-Stop:     $syslog $remote_fs $network
# Should-Start:
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start the TinyTinyRSS updates daemon.
# Description:       Start the TinyTinyRSS updates daemon.
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/share/ttrss/update_daemon2.php
NAME=ttrss
DESC="TinyTinyRSS update daemon"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
USER=www-data
GROUP=www-data

test -x $DAEMON || exit 0

set -e

. /lib/lsb/init-functions

case "$1" in
    start)
        log_daemon_msg "Starting $DESC" $NAME
        if ! start-stop-daemon --start --oknodo --quiet --background --make-pidfile \
            --chuid $USER:$GROUP --pidfile $PIDFILE --exec $DAEMON
        then
            log_end_msg 1
        else
            log_end_msg 0
        fi
        ;;
    stop)
        log_daemon_msg "Stopping $DESC" $NAME
        if start-stop-daemon --stop --retry 30 --oknodo --quiet \
            --pidfile $PIDFILE --exec $DAEMON
        then
            rm -f $PIDFILE
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    restart|reload|force-reload)
        check_syntax
        $0 stop
        $0 start
        ;;
    status)
        status_of_proc -p "$PIDFILE" "$DAEMON" ttrss && exit 0 || exit $?
        ;;
    *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2
        exit 1
        ;;
esac

exit 0
Включим автоматический запуск и остановку демона в процессе загрузки, выключения и перезагрузки системы:
# insserv ttrss
И запустим демон обновлений прямо сейчас:
# /etc/init.d/ttrss start
Приложение настроено, дальнейшая процедура создания пользователей и добавления подписок уже выходит за рамки заметки.

воскресенье, 16 марта 2014 г.

Установка и настройка dokuwiki

На этот раз я опишу настройку dokuwiki - небольшой wiki-системы на PHP, не использующей базы данных SQL. Поскольку не так давно я начал использовать вместо Lighttpd веб-сервер nginx, я опишу два варианта настройки.

1. Вариант 1 - настройка Lighttpd

Установим веб-сервер Lighttpd и PHP:
# apt-get install lighttpd php5-cgi
Для того, чтобы dokuwiki работала на отдельном домене, нужно исправить файл конфигурации /etc/lighttpd/conf-available/50-dokuwiki.conf до следующего состояния:
$HTTP["host"] == "wiki.domain.tld" {
  server.document-root = "/usr/share/dokuwiki"

  $HTTP["url"] =~ "^/" {
    server.follow-symlink = "enable"
  }

  $HTTP["url"] =~ "/(\.|_)ht" {
    url.access-deny = ( "" )
  }

  $HTTP["url"] =~ "^/(bin|data|inc|conf)" {
    url.access-deny = ( "" )
  }
}
В случае, если dokuwiki должна работать из каталога сайта, можно создать такой файл конфигурации /etc/lighttpd/conf-available/50-dokuwiki.conf:
$HTTP["host"] == "domain.tld" {
  $HTTP["url"] =~ "^/wiki" {
    server.document-root = "/usr/share/dokuwiki"

    $HTTP["url"] =~ "^/" {
      server.follow-symlink = "enable"
    }

    $HTTP["url"] =~ "/(\.|_)ht" {
      url.access-deny = ( "" )
    }

    $HTTP["url"] =~ "^/(bin|data|inc|conf)" {
      url.access-deny = ( "" )
    }
  }
}
Осталось включить поддержку fastcgi, PHP в fastcgi и только что созданный файл конфигурации:
# lighty-enable-mod fastcgi
# lighty-enable-mod fastcgi-php
# lighty-enable-mod dokuwiki
Чтобы настройки веб-сервера вступили в силу, нужно его перезапустить:
# /etc/init.d/lighttpd restart
2. Вариант 2 - настройка nginx и php5-fpm

Установим веб-сервер и менеджер управления FastCGI-процессами PHP:
# apt-get install nginx-light php5-fpm
php5-fpm устанавливается с преднастроенным пулом процессов в файле /etc/php/fpm/pool.d/www.conf, так что дополнительные настройки не требуются. Но при желании можно настроить имеющийся пул или создать отдельный пул.

Теперь добавим файл /etc/nginx/sites-available/dokuwiki с настройками для dokuwiki, если нужно настроить её на отдельном домене:
server {
  listen 80;

  server_name wiki.domain.tld;

  root /usr/share/dokuwiki;
  index index.php;

  location /bin/ {
    deny all;
  }

  location /data/ {
    deny all;
  }

  location /inc/ {
    deny all;
  }

  location /conf/ {
    deny all;
  }

  location ~ \.ht {
    deny all;
  }

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/dokuwiki.sock;
    fastcgi_index index.php;

    include fastcgi_params;
  }
}
Или, если dokuwiki должна работать из отдельного каталога на имеющемся сайте, можно добавить в файл конфигурации этого сайта следующие настройки:
location /wiki/bin/ {
  deny all;
}

location /wiki/data/ {
  deny all;
}

location /wiki/inc/ {
  deny all;
}

location /wiki/conf/ {
  deny all;
}

location /wiki {
  alias /usr/share/dokuwiki;
  index index.php;

  location ~ \.ht {
    deny all;
  }

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;

    include fastcgi_params;
  }
}
Осталось включить использование конфигурации сайта, если вы настраивали dokuwiki на отдельном домене:
# cd /etc/nginx/sites-enabled
# ln -s /etc/nginx/sites-available/dokuwiki .
И перезапустить nginx, чтобы его новые настройки вступили в силу:
# /etc/init.d/nginx restart
Можно было бы написать ещё и третий вариант настройки - для использования Lighttpd совместно с php5-fpm, но я не стану этого делать. Кому понадобится такой вариант - тот разберётся в нём сам.

3. Установка dokuwiki

Установка dokuwiki проста - нужно лишь установить соответствующий пакет:
# apt-get install dokuwiki
В процессе установки будет задано несколько вопросов:







После установки можно зайти в веб-интерфейс с паролем администратора, который мы указали при установке:



Я также пользуюсь темой arctic для dokuwiki. Пакет с этой темой можно взять у меня: dokuwiki-arctic-theme_0.0.20081104_all.deb

4. Вариант 1 - настройка dokuwiki через файлы конфигурации

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

Для первичной настройки достаточно лишь прописать в файл /etc/dokuwiki/local.php несколько настроек:
$conf['title'] = 'wiki.domain.tld'; # Название wiki, которое будет на ней отображаться
$conf['license'] = '';              # Название лицензии, под которой выкладываются материалы
$conf['lang'] = 'ru';               # Язык интерфейса
$conf['useacl'] = 1;                # Включает использование списков ограничения доступом
$conf['superuser'] = '@admin';      # Группа для администраторов
$conf['template'] = 'arctic';       # Используемая тема
Любую из настроек можно не вписывать - у них у всех есть значения по умолчанию.

В файле /etc/dokuwiki/plugins.local.php я отключил использование плагина, отсылающего разработчикам статистику использования dokuwiki:
<?php
$plugins['popularity']      = 0;
?>
В файле acl.auth.php можно настраивать права доступа к определённым разделам wiki. Например, вот так можно ограничить доступ к разделу private для незарегистрированных пользователей:
*               @ALL          1
*               @user         8
private:*       @ALL          0
В теме arctic, которую я использую, в файле /etc/dokuwiki2/themes/arctic/default.php я удаляю из настроек всех правых и левых панелей страницу index, поскольку для каждого раздела я создаю вручную страницу sidebar, которая и выполняет роль оглавления раздела.

5. Вариант 2 - настройка dokuwiki через веб

Для того, чтобы можно было менять настройки из самой DokuWiki, нужно назначить права доступа веб-сервера к каталогу /etc/dokuwiki:
# chgrp www-data /etc/dokuwiki
# chmod ug=rwx,o=rx /etc/dokuwiki
Также нужно поменять права доступа веб-сервера к файлу /etc/dokuwiki/local.php и, по желанию, к другим файлам в этом каталоге:
# chown www-data /etc/dokuwiki/local.php
# chmod u=rw,go=r /etc/dokuwiki/local.php
После этих манипуляций можно настраивать dokuwiki через меню "Управление".

Вот так выглядит настроенная мной dokuwiki с темой arctic:

воскресенье, 9 марта 2014 г.

Установка MaxSite CMS

Одними из самых популярных систем управления наполнением сайтов являются Wordpress, Drupal и Joomla! Однако, хочется отметить отечественную разработку - MaxSite, за автором некоего Максима, фамилию которого я так и не смог нагуглить :) Из достоинств системы я отмечу использование фреймворка CodeIgniter, простоту настройки, нетребовательность к ресурсам.

В этой заметке я рассмотрю процесс установки MaxSite для совместной работы с веб-сервером Lighttpd.

1. Подготовка БД

Если в системе ещё не установлен MySQL, его сервер и клиент можно установить при помощи команды:
# apt-get install mysql-server mysql-client
Первым делом мы создадим для сайта пустую базу данных в MySQL:
CREATE DATABASE maxsite CHARSET UTF8;
INSERT INTO user(user, host, password) VALUES('maxsite', 'localhost', PASSWORD('maxsite_password'));
FLUSH PRIVILEGES;
GRANT ALL ON maxsite.* TO 'maxsite'@'localhost';
FLUSH PRIVILEGES;
Для генерации реального пароля я обычно пользуюсь программой pwgen из одноимённого пакета. Если пароль будет использоваться какой-то программой и его не нужно будет вводить руками, обычно я генерирую 16-символьные пароли:
$ pwgen 16
Один из паролей можно использовать в качестве замены для maxsite_password в командах выше.

2. Настройка CMS

Теперь скачиваем дистрибутив с официального сайта проекта и распаковываем его:
$ wget http://max-3000.com/download -O maxsite-cms-0.86x.zip
$ unzip maxsite-cms-0.86x.zip
$ cd cms-master
Теперь можно скопировать необходимое в каталог, к которому будет обращаться веб-сервер:
# cp -R application index.php system uploads /home/www/blog.domain.tld/
# cd /home/www
# chown -R www-data:www-data blog.domain.tld
# cd blog.domain.tld
Как выяснилось позднее, CMS требует наличия файлов .htaccess и sitemap.xml. Первый из них в моей системе будет пустым по той причине, что я не использую Apache. Пример второго файла, как оказалось, пустой и в самом дистрибутиве. Создадим эти файлы:
# touch .htaccess
# touch sitemap.xml
# chown www-data:www-data .htaccess sitemap.xml
Теперь пропишем в настройки CMS учётные данные для подключения к базе данных в файле application/config/database.php, взяв за его основу файл application/config/database.php-dist:
$ cd application/config
$ mv database.php-dist database.php
$ vim database.php
Достаточно лишь изменить три настройки:
$db['default']['username'] = 'maxsite';
$db['default']['password'] = 'maxsite_password';
$db['default']['database'] = 'maxsite';
Следующий файл, подлежащий настройке - application/config/mso_config.php. В нём я ничего не трогал, поэтому достаточно лишь переименовать его:
$ mv mso_config.php-dist mso_config.php
И, наконец, перед тем, как приступить к настройке веб-сервера настроим ещё один файл - application/maxsite/mso_config.php, за основу которого возьмём, как вы уже догадались, файл application/maxsite/mso_config.php-dist:
$ cd ../maxsite
$ mv mso_config.php-dist mso_config.php
В нём нужно прописать ключ, которым CMS будет шифровать Cookie:
$MSO->config['secret_key'] = 'secret_key';
Для его генерации я опять воспользовался pwgen, указав на этот раз 128 символов - слово "ключ" подразумевает под собой строчку в несколько раз длиннее того, что обычно используется в качестве пароля:
$ pwgen 128
После настройки сайта через веб-интерфейс можно будет также прописать в этот файл следующую настройку, которая отключит дальнейшую возможность повторно пройти процедуру инсталляции (делать это пока рано):
$mso_install = true;
3. Настройка веб-сервера Lighttpd

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

Если в системе ещё не установлены Lighttpd и PHP, их можно установить при помощи команды:
# apt-get install lighttpd php5-cgi
Создадим файл настройки Lighttpd, эквивалентный .htaccess - /etc/lighttpd/conf-available/50-maxsite.conf:
$HTTP["host"] == "max.stupin.su" {

  server.document-root  = "/home/www/blog.domain.tld"

  url.rewrite-once = ( "^(/(?!(index\.php|application|uploads|robots\.txt|favicon\.ico).*))" => "/index.php/$1" )

  $HTTP["url"] =~ "^/uploads" {
    fastcgi.server = ()
  }
}
Для работы этого файла понадобится включить модуль rewrite, который в Debian включается не при помощи обычной для этого утилиты lighty-enable-mod, а простым раскомментированием соответствующей строчки в файле /etc/lighttpd/lighttpd.conf

После этого можно включить необходимые модули и только что созданный файл с настройками для maxsite:
# lighty-enable-mod fastcgi
# lighty-enable-mod fastcgi-php
# lighty-enable-mod maxsite
Осталось сообщить веб-серверу о необходимости применить новые настройки:
# /etc/init.d/lighttpd force-reload
4. Настройка CMS через веб-интерфейс

Теперь можно перейти в браузере по адресу blog.domain.tld и завершить процедуру настройки.

Проверка правил rewrite:
Проверка правил rewrite
Ввод настроек блога и проверка правильности настройки веб-сервера:
Ввод настроек блога и проверка правильности настройки веб-сервера
Рекомендация отключить дальнейшую возможность веб-настройки:
Рекомендация отключить дальнейшую возможность веб-настройки
На этом этапе стоит воспользоваться рекомендацией и прописать в файл application/maxsite/mso_config.php настройку, запрещающую дальнейшую возможность изменения настроек сайта через веб:
$mso_install = true;
Установленная система:
Установленная система
5. Смена типа таблиц

Заметил, что автоматически создаются таблицы MyISAM, поэтому переконвертировал все таблицы в InnoDB. Мне такой выбор кажется несколько странным, т.к. в MyISAM нет внешних ключей, нет транзакций, все блокировки - на уровне таблиц, а не строк. Довольно ненадёжное решение. Если уж экономить на спичках, тогда лучше было бы использовать SQLite вместо MySQL.
ALTER TABLE mso_cat2obj ENGINE=InnoDB;
ALTER TABLE mso_category ENGINE=InnoDB;
ALTER TABLE mso_comments ENGINE=InnoDB;
ALTER TABLE mso_comusers ENGINE=InnoDB;
ALTER TABLE mso_groups ENGINE=InnoDB;
ALTER TABLE mso_links ENGINE=InnoDB;
ALTER TABLE mso_meta ENGINE=InnoDB;
ALTER TABLE mso_options ENGINE=InnoDB;
ALTER TABLE mso_page ENGINE=InnoDB;
ALTER TABLE mso_page_type ENGINE=InnoDB;
ALTER TABLE mso_users ENGINE=InnoDB;
Дальнейшая настройка CMS выходит за рамки этой заметки.

P.S. По прошествии некоторого времени использования системы хочется отметить недостатки:
  • неудобство управления заметками из админки, т.к. заметки выбираются из выпадающего списка, а не классическими галочками, из-за чего становится невозможным выбрать несколько заметок сразу,
  • встроенный редактор заметок, использующий свои собственные теги в квадратных скобках, которые не обрабатываются без установки дополнительного плагина. Уж лучше встроенный редактор использовал бы обычные HTML-коды или плагин был бы встроен основной функционал системы, а так как есть - не логично,
  • неудобство управления картинками. Нельзя одновременно выбрать и загрузить несколько картинок, не выбирая их по одной. Зачем-то приходится выбирать папку, в которую необходимо загрузить картинки. Нельзя только что загруженные картинки сразу вставить в текст - приходится искать их в списке загруженных и отмечать каждую отдельно.

воскресенье, 2 марта 2014 г.

Установка и настройка Wordpress

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

1. Установка

Wordpress будет работать под управлением веб-сервера Lighttpd и будет использовать базу данных в MySQL. Сам Wordpress написан на PHP. Перед тем как устанавливать сам Wordpress, установим необходимые пакеты, если они ещё не были установлены:
# apt-get install mysql-server mysql-client lighttpd php5-cgi
Ставим пакет с wordpress и пакет с локализациями:
# apt-get install wordpress wordpress-l10n
Смотрим, что есть полезного в пакете wordpress, что может помочь в настройке сервера:
$ dpkg -L wordpress
Я отметил три момента:
  • Файлы Wordpress располагаются в каталоге /usr/share/wordpress
  • Есть пример настройки Apache в файле /usr/share/doc/wordpress/examples/apache.conf
  • Есть пример настройки самого Wordpress в файле /usr/share/wordpress/wp-config-sample.php
2. Настройка Lighttpd

Меня заинтересовал вариант настройки "defined Virtual host" и я подготовил файл /etc/lighttpd/conf-enabled/50-wordpress.conf с таким содержанием:
$HTTP["host"] == "blog.domain.tld" {
  server.document-root = "/usr/share/wordpress"
  alias.url += ( "/wp-content" => "/var/lib/wordpress/wp-content" )
  $HTTP["url"] =~ "^/" {
    server.follow-symlink = "enable"
  }
}
Осталось включить модули fastcgi, fastcgi-php, новоиспечённый нами "модуль" wordpress и перезапустить веб-сервер:
# lighty-enable-mod fastcgi fastcgi-php wordpress
# /etc/init.d/lighttpd restart
На данный момент уже можно зайти в блог, однако будет выведено сообщение, что он ещё не настроен.

3. Настройка Wordpress

Для настройки блога скопируем заготовку настроек в файл /etc/wordpress/config-blog.domain.tld.php:
# cp /usr/share/wordpress/wp-config-sample.php /etc/wordpress/config-blog.domain.tld.php
Зададим настройки подключения к базе данных:
define('DB_NAME', 'database');
define('DB_USER', 'user');
define('DB_PASSWORD', 'blog_password');
Обычно для пользователей, которые не будут вводить пароль вручную, я генерирую случайный пароль длиной 16 символов при помощи программы pwgen, которую можно установить из одноимённого пакета:
$ pwgen 16
Сгенерированный пароль можно использовать вместо blog_password в примере выше.

Укажем, что таблицы блога blog.domain.tld должны иметь префикс blog_:
$table_prefix  = 'blog_';
Пропишем русский язык в настройки блога:
define('WPLANG', 'ru_RU');
Посмотреть, какие языки поддерживаются можно в пакете wordpress-l10n такой командой:
$ dpkg -L wordpress-l10n
Если там есть файл с расширением mo, то его имя можно прописать в настройки.

4. Настройка базы данных

Осталось создать базу данных и пользователя. Для этого подключаемся к базе данных с правами администратора:
$ mysql -uroot -p mysql
Создадим базу данных:
CREATE DATABASE blog CHARSET UTF8;
Создадим пользователя, от имени которого движок блога будет подключаться к базе данных, а вместо blog_password подставим сгенерированный пароль:
INSERT INTO user(user, password, host) VALUES('blog', PASSWORD('blog_password'), 'localhost');
FLUSH PRIVILEGES;
Дадим новому пользователю права на полный доступ к базе данных:
GRANT ALL ON blog.* TO blog@localhost;
FLUSH PRIVILEGES;
5. Настройка блога

Для окончательной настройки блога нужно перейти по ссылке http://blog.domain.tld/wp-admin/install.php и заполнить форму с информацией о блоге и учётными данными его администратора:

После отправки данных откроется страница следующего вида:

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

6. Темы и плагины

Я подготовил несколько deb-пакетов с темами и плагинами к Wordpress и поместил их в собственный репозиторий.

Чтобы подключить репозиторий, можно добавить его в файл /etc/apt/sources.list:
deb http://deb.stupin.su/ wheezy main
Обновим список пакетов в репозиториях:
# apt-get update
Теперь можно установить из репозитория любой из имеющихся пакетов:
  • Тема Fluid Blue - wordpress-theme-fluid-blue
  • Тема F2 - wordpress-theme-f2 - наследник темы Fluid Blue, пришедший ей на смену
  • Тема Indicator - wordpress-theme-indicator
  • Тема Restaurateur - wordpress-theme-restaurateur
  • Тема Rundown - wordpress-theme-rundown
  • Плагин Blogger Importer - wordpress-blogger-importer - импорт заметок из блогов на blogger.com в Wordpress
  • Плагин Categories to Tags Converter - wordpress-wpcat2tag-importer - позволяет превратить категорию в тег и наоборт
На этом пока всё.