Ansible и подключение через промежуточный хост.

Потребовалось мне управлять при помощи Ansible серверами, у которых ssh доступен только во внутренней сети заказчика через подконтрольный мне сервер, который доступен через Интернет. Вариант на трёх или четырёх, как я их называю, центральных серврах поднимать Ansible и синхронизировать playbooks мне как-то не улыбалась. Решил поинтересоваться, как народ эту задачу решает при помощи Ansible, установленного на одной машине. В интернете много вопросов на эту тему. Ответов нормальных на этот вопрос я не нашёл. А вот мысль одна у меня в голове крутилась давно: ProxyCommand. В итоге занялся расширением своих познаний о ssh.
Оказалось, что ProxyCommand – это то что нужно!
Для получения желаемого результата достаточно было “подкрутить” ssh_args в ansible.conf и указать, что подключаться к машинам и списка хостов надо используя промежуточный хост:
-o ProxyCommand="ssh -q -A -x root@xxx.xxx.xxx.xxx -p 2022 -W %h:22,
где xxx.xxx.xxx.xxx – IP того самого подконтрольного сервера. Остальные ключи и параметры подробно описаны в man 1 ssh.
Как видно, тут есть одно ограничение – у опрашиваемых серверов sshd должен слушть на 22 порту (или каком-то другом), лишь бы у всех одинаковый был.
Для работоспособности этой схемы надо соблюсти некоторые условия:
– на центральном сервере и дирижируемых хостах надо в authorized_keys добавить открытый ключ учётной записи от имени которой запускается Ansible.
– в /etc/ssh/sshd на центральном сервере значение MaxSessions должно быть больше, чем значение forks в ansible.cfg, чтобы sshd не отбрасывал соединения.
А теперь небольшая ложка дёгтя. ssh_args нельзя указать в файле инвентаризации, так что для каждого случая с центральным сервером понадобится отдельный конфигурационный файл ansible.cfg. В нём можно указать путь к инвентаризационному файлу со списком внутренних IP дирижируемых хостов. Запускать ansible придётся с указанием переменной окружения ANSIBLE_CONFIG=/etc/ansible/ansible_intnet1.cfg.
Как показал дальнейший поиск, добавлять возможность указания ssh_args в инвентаризационном файле разработчики отказывабтся, мол и в конфиге достаточно.

Share

Списки IP адресов для iptables

Так как не все наши заказчики выполняют требование по защите наших серверов файрволлом (доступ по ssh только с доверенных IP), быстрым решением было ограничить подключения в /etc/ssh/sshd_config через AllowUsers. В целом задачу свою подобное решение выполняло, за исключением одного момента – подключение с неизвестного IP отвергается, а в логах записи, тем не менее, остаются. При активных bruteforce-атаках логи пухли как на дроджжах и в условиях ограниченного дискового пространства это вызывало определённые проблемы. В итоге, улучив минутку, сел переделывать по-человечески – настраивать iptables на подконтрольном сервере, раз заказчики не чешутся и не выполняют наши техтребования.
Как оказалось, сами iptables этого не умеют. Решение нашлось быстро – ipset. Конечно, в сравнении с pf, меня несколько удивляет, что для подобной элементарной задачи нужна отдельная утилита… Буду считать это ярчайшим проявлением unixway: одна задача – один инструмент.
Список для ipset готовится элементарно, потом экспотируется командой ipset save в понятный ipset формат и подгружается при помощи ipset restore.
В набор адресов для ipset я добавил внешние адреса офиса и внутренние подсети, определённые RFC. Вот что получилось:
create trusted hash:net family inet hashsize 1024 maxelem 65536
add trusted 192.168.0.0/16
add trusted 10.0.0.0/8
add trusted 172.16.0.0/12
add trusted xxx.xxx.xxx.0/24
add trusted yyy.yyy.yyy.yyy

Где trusted – это имя списка IP, точнее списка подсетей.
Правило для iptables трансформировалось из
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
в
-A INPUT -m state --state NEW -m set --set trusted src -m tcp -p tcp --dport 22 -j ACCEPT
т.е. добавил -m set --set trusted src, где -m set указание на использование списка ipset, --set trusted имя списка и параметр указывающий что это список источников – src.
А вот дальше началось самое интересное – как при загрузке ОС скормить эти списки iptables, т.к. если список не загружен, то правила iptables не применяются, ссылаясь на ошибку.
Т.е. комманда ipset restore должна выполняться ДО iptables rstore. Оказалось, что в Scientific Linux с этим проблема. В пакете ipset-6.11-1.el6.i686 службы ipset нет, а из /etc/rc.local комманды выполняются ПОСЛЕ iptables restore, что, как я писал выше, приводит к ошибке и правила не загружаются. Получается, что по умолчанию два варианта – писать свои скрипты инициализации (как вариант использовать найденные в интернете) или колхозить ещё более жутким образом, типа прописать ipset restore < /etc/ipset.rules в /etc/init.d/iptables. Оба этих варианта меня как-то не сильно радовали.
Выход таки нашёлся – в репозиториях CentOS есть пакет ipset-init, который содержит в себе необходимые для решения данной задачи скрипты init.d.
После установки пакета добавил вышеприведённый конфиг в /etc/sysconfig/ipset и все проблемы с подгрузкой списков разрешились.
К слову сказать, в Arch Linux пакет ipset идёт со скриптами для systemd и использование сторонних скриптов и пакетов не требуется.
UPDATE: В более позднем пакете ipset-6.11-3.el6.i686 из SL6.6 служба ipset всё-таки появилась и необходимость в стороннем пакете отпала.

Share

Munin SSH transport

Решил настроить munin сервер для опроса порядка 500 нод.
В штатном режиме сервер опрашивает ноду по дефолтному порту 4949. Это прекрасно и замечательно, когда этот порт доступен “напрямую”. В моём случае большинство серверов сидят за чужим NAT-ом и наружу проброшен только ssh, причём ещё на какой-нибудь высокий порт. Или есть второй распространённый вариант – проброшен порт от одного сервера, а остальные доступны только по внутренней сети.
Доступ по ssh открыт, так как это является нашим основным требованием к сети заказчика.
В официальной документации как-то не сильно рекламируют возможность работы через ssh, но, как оказалось, в munin 2.x она есть. О её существовании помог узнать большой брат, который вывел на ссылку http://munin-monitoring.org/wiki/Native_ssh.
В принципе всё понятно, за исключением конфигурации с нестандартным ssh портом, но об этом чуть позже.
Тестовый сервер у меня был поднят на OpenBSD и серверная часть munin запускалась с правами пользователя _munin, который по умолчанию вместо shell имеет /sbin/nologin. Продакшн настраивал на Scientific Linux, в котором munin запускается от пользователя munin. Соответственно для возможности подключения по ssh к нодам надо было в обоих случаях этому пользователю прописать рабочий шелл, например /bin/sh, создать домашнюю директорию, сгенерировать ключи при помощи ssh-keygen (ключ должен быть без passphrase) и переслать публичный ключ на ноду для той учётной записи, под которой планируется на неё заходить. Пусть учётка на ноде зовётся user. Соответственно в домашней директории пользователя user в .ssh/autorized_keys должен быть прописан публичный ключ пользователя munin с сервера.
На машине с munin-node должен быть установлен netcat (nc), который позволит обращаться к munin-node через:

nc localhost 4949
# munin node at ms13090624.domain
list
df mssversion uptime

То есть для подобного режима работы ноде достаточно слушать только на 127.0.0.1 и отвечать на запросы тоже только с локалхоста. Одним сервисом “глядящим” наружу будет меньше.
Значимые строки в munin-node.conf для подключения к ней при помощи nc с localhost:

host_name ms13090624.domain
allow ^127\.0\.0\.1$
host 127.0.0.1

Вручную ноду можно проверить запустив с сервера через ssh nc на ноде:
sudo -u munin ssh user@xxx.xxx.xxx.xxx nc localhost 4949
В ответ должны получить приглашение munin-node, как и при локальном подключении.
Кусок конфига munin.conf для опроса ноды по 22 порту (описан в документации к munin):

[ms13090624.domain]
use_node_name no
address ssh://user@xxx.xxx.xxx.xxx/usr/bin/nc localhost 4949

Про использование альтернативного порта ssh я в документации не увидел ни слова, но просмотр кода и дальейшие тесты на стенде показали, что в конфиге сервера порт указывается вот в таком формате:

[ms13090622.domain]
use_node_name no
address ssh://user@xxx.xxx.xxx.xxx:2022/usr/bin/nc localhost 4949

то есть через двоеточие сразу после IP.

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

[ms13090625.domain]
use_node_name no
address ssh://user@zzz.zzz.zzz.zzz:2022/usr/bin/ssh user1@192.168.xxx.yyy /usr/bin/nc localhost 4949

ms13090625.domain – имя внутренней машины, прописанное в конфиге ноды
192.168.xxx.yyy – IP ноды, которая находится во внутренней сети
zzz.zzz.zzz.zzz:2022 ИП и порт машины к которой мы имеем доступ по ssh извне и с которй по ssh можно попасть на машину во внутренней сети, т.е. на ноду.

Итого для работы через туннель к “обычному” конфигу доступа по ssh вида
address ssh://user@zzz.zzz.zzz.zzz:2022/usr/bin/nc localhost 4949
добавилась команда для подключения с внешнего сервера на внутреннюю ноду: /usr/bin/ssh user1@192.168.xxx.yyy

Надеюсь это понятно сразу, что user на внешнем сервере должен быть обменян ssh ключом с user1 на внутреннем (ноде) для беспарольного доступа.

Share

Кривой стартер. post-install

Эта секция позволяет заскриптовать практически любые действия, которые будут проведены по окончании инсталяции. В моём случае все скрипты идут отдельным инклудом post.cfg, кторый начинается со строчки %post --interpreter /bin/sh --nochroot --log /tmp/postinstall.log.
Большая часть моего post.cfg не представляет интереса, т.к. выполняет узкоспециализированные задачи, но часть может быть полезна.
Т.к. в kickstart’е я не нашёл способа, не возвращаясь в интерактивный режим, задать пароль для шифрованного раздела, то эту операцию я выполняю уже в post секции:
# Setup crypted partition.
umount /dev/sdb4
dmsetup remove mcrypt
cryptsetup -q luksFormat /dev/sdb4 --key-file /mnt/sysimage/etc/mss.key
cryptsetup luksOpen /dev/sdb4 mcrypt --key-file /mnt/sysimage/etc/mss.key
mkfs.ext4 -O dir_index /dev/mapper/mcrypt
# Installer adds a line to mount sdb4 as uncrypted partition to fstab. Remove it!
sed -i '/mss/d' /mnt/sysimage/etc/fstab
# And add correct data to fstab and crypttab.
echo "/dev/mapper/mcrypt /var/lib/mss ext4 defaults 1 3" >> /mnt/sysimage/etc/fstab
echo "mcrypt /dev/sda4 /etc/mss.key" > /mnt/sysimage/etc/crypttab

Ключ mss.key генерируется в %pre секции.

Затем я копирую различные конфиги. Общий принцип:
cp /mnt/isodir/configs/* /mnt/sysimage//

Как вариант – донастройка munin-node:
# Unhook unused munin plugins.
for i in df_inode diskstats entropy forks fw_packets if_err_eth0 \
if_eth0 interrupts threads irqstats netstat open_files users swap \
open_inodes selinux_avcstat sendmail* proc_pri vmstat processes
do
rm -r /mnt/sysimage/etc/munin/plugins/$i
done

# Enable usable munin plugins.
ln -s /usr/share/munin/plugins/sensors_ /mnt/sysimage/etc/munin/plugins/sensors_temp
ln -s /usr/share/munin/plugins/sensors_ /mnt/sysimage/etc/munin/plugins/sensors_fan
ln -s /usr/share/munin/plugins/proc /mnt/sysimage/etc/munin/plugins/proc

# Accept connections from our munin-server.
echo "cidr_allow ???.???.??.??/32" >> /mnt/sysimage/etc/munin/munin-node.conf

# Install munin-node configuretion.
cp /mnt/isodir/configs/munin-node-mss /mnt/sysimage/etc/munin/plugin-conf.d/

При помощи sed разрешаю пользователям из группы wheel повышать привилегии без ввода пароля:
# Let wheel users sudo without typing password every time.
sed -Ei 's/^#( %wheel.*NOPASSWD.*)/\1/' /mnt/sysimage/etc/sudoers

Т.к. процесс настройки сети был пропущен, то некоторые манипуляции с именем машины производим тут же:
# Setup hostname.
sed -i '/^HOSTNAME/d' /mnt/sysimage/etc/sysconfig/network
echo "HOSTNAME=`cat /tmp/hostname.txt`" >> /mnt/sysimage/etc/sysconfig/network

# Add hostname to /etc/hosts to prevent resolve timeouts.
#awk ‘{$(NF+1)=”`cat /tmp/hostname.txt`”;}1’ /mnt/sysimage/etc/hosts > /tmp/hosts.tmp && mv /tmp/hosts.tmp /mnt/sysimage/etc/hosts
awk ‘{getline HOST /tmp/hosts.tmp && mv /tmp/hosts.tmp /mnt/sysimage/etc/hosts

Т.к. наши сервера потом попадают в чужие руки, я удаляю улики, т.е. логи:
# Remove clues.
#rm /mnt/sysimage/root/anaconda-ks.cfg
rm /mnt/sysimage/tmp/ks-script-*

Обычная часть закончена. Теперь предстоит выполнить некоторые операции в свежеустановленной системе, для чего надо сделать chroot в /:
# Chrooted postinstall scripts to make local changes in fresh system.
%post --interpreter /bin/sh

Например можно добавить в загрузку службу, которая была установлена не из пакетов:
# Add mss player init.d script to runlevels.
/sbin/chkconfig --add mss

Или создать пользователя с заданным паролем:
adduser mss -m -U -u 1000 -G wheel -p sa************

Завершает процесс %end.

Share

Фоторамка из tabletpc и OpenBSD

В связи с изменениями в личной жизни у меня дома появилась фоторамка фирмы_DSCN1185, как это не противно, Sony. Обыкновенная маленькая чёрная рамка для любителей фотографий в формате 9х13.
Её основной минус – абсолютно отвратительный экран. Пиксели размером со слона при размере экрана 9х14см как-то ухудшают восприятие фото. На фоне этого все остальные характеристики можно вообще не рассматривать. _DSCN1189
Уже лет пять, если не больше, у меня пылится один гаджет – таблетка фирмы Compaq на базе Transmeta Crusoe, зачем-то купленная в своё время у друга. Как ноутбук/таблет в настоящее время её использовать бессмысленно – у неё хитромудрое перо с батарейкой (пальцем в экран тыкать бесполезно), мало памяти, дохленький проц, старый аккумулятор и заюзаный IDEшный жёсткий диск. В общем все прелести таблета десятилетней давности. Зато у неё недурственныё экран (по сравнению с фоторамкой), есть сеть, USB, кардридер…
_DSCN1191
$ dmesg
OpenBSD 5.4-current (GENERIC) #46: Mon Sep 2 13:54:44 MDT 2013
deraadt@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC
cpu0: Transmeta(tm) Crusoe(tm) Processor TM5800 ("GenuineTMx86" 586-class) 1 GHz
cpu0: FPU,V86,DE,PSE,TSC,MSR,CX8,SEP,CMOV,MMX
real mem = 376942592 (359MB)
avail mem = 358969344 (342MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 10/06/03, BIOS32 rev. 0 @ 0xfd6a0, SMBIOS rev. 2.3 @ 0xe7010 (20 entries)
bios0: vendor Phoenix version "4.06CJ15" date 10/06/2003
bios0: Compaq Compaq Tablet PC TC1000
acpi0 at bios0: rev 0
acpi0: sleep states S0 S1 S3 S4 S5
acpi0: tables DSDT FACP
acpi0: wakeup devices PWRB(S4) PCI0(S3) USB0(S3) USB1(S3) USB2(S3)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpiprt0 at acpi0: bus 0 (PCI0)
acpiec0 at acpi0
acpicpu0 at acpi0: C2, PSS
acpipwrres0 at acpi0: LRP0
acpipwrres1 at acpi0: LRP1
acpipwrres2 at acpi0: LRP2
acpitz0 at acpi0: critical temperature is 100 degC
acpiac0 at acpi0: AC unit online
acpibat0 at acpi0: CMB0 model "BAT1" serial 1234 type LION oem "COMPAQ"
acpibtn0 at acpi0: PWRB
acpivideo0 at acpi0: VIDO
bios0: ROM list: 0xc0000/0xe000 0xe7000/0x1000!
cpu0 at mainbus0: (uniprocessor)
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 "Transmeta LongRun Northbridge" rev 0x03
"Transmeta Mem1" rev 0x00 at pci0 dev 0 function 1 not configured
"Transmeta Mem2" rev 0x00 at pci0 dev 0 function 2 not configured
vga1 at pci0 dev 5 function 0 "NVIDIA GeForce2 Go" rev 0xb2
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
pcib0 at pci0 dev 7 function 0 "VIA VT82C686 ISA" rev 0x40
pciide0 at pci0 dev 7 function 1 "VIA VT82C571 IDE" rev 0x06: ATA100, channel 0 configured to compatibility, channel 1 configured to compatibility
wd0 at pciide0 channel 0 drive 0:
wd0: 16-sector PIO, LBA48, 76319MB, 156301488 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 5
pciide0: channel 1 ignored (disabled)
viapm0 at pci0 dev 7 function 4 "VIA VT82C686 SMBus" rev 0x40: SMI
iic0 at viapm0
iic0: addr 0x2d 00=01 01=0e 02=16 07=50 08=ad 09=5d 0b=55 13=fe 14=74 15=57 16=67 17=04 1d=ff 1e=fb 1f=86 20=01 21=01 22=fe 23=ff 24=c8 25=fe 26=fe 27=7d 28=7d 2b=ff 2c=bf 2d=7b 2e=fb 2f=fd 30=ff 31=ff 32=ff 33=ff 34=bf 35=5d 36=fd 37=ff 38=f7 39=be 3a=bd 3b=ff 3c=ff 3d=7f 3e=df 3f=a2 40=01 47=50 48=ad 49=5d 4b=55 53=86 54=6b 55=57 56=e5 57=80 5d=ff 5e=fb 5f=86 60=01 61=01 62=fe 63=ff 64=c8 65=fe 66=fe 67=7d 68=7d 6b=ff 6c=bf 6d=7b 6e=fb 6f=fd 70=ff 71=ff 72=ff 73=ff 74=bf 75=5d 76=fd 77=ff 78=f7 79=be 7a=bd 7b=ff 7c=ff 7d=7f 7e=df 7f=a2 80=01 87=50 88=ad 89=5d 8b=55 93=86 94=70 95=57 96=ee 97=80 9d=ff 9e=fb 9f=86 a0=01 a1=01 a2=fe a3=ff a4=c8 a5=fe a6=fe a7=7d a8=7d ab=ff ac=bf ad=7b ae=fb af=fd b0=ff b1=ff b2=ff b3=ff b4=bf b5=5d b6=fd b7=ff b8=f7 b9=be ba=bd bb=ff bc=ff bd=7f be=df bf=a2 c0=01 c7=50 c8=ad c9=5d cb=55 d3=86 d4=6c d5=57 d6=f6 d7=80 dd=ff de=fb df=86 e0=01 e1=01 e2=fe e3=ff e4=c8 e5=fe e6=fe e7=7d e8=7d eb=ff ec=bf ed=7b ee=fb ef=fd f0=ff f1=ff f2=ff f3=ff f4=bf f5=5d f6=fd f7=ff f8=f7 f9=be fa=bd fb=ff fc=ff fd=7f fe=df ff=a2 words 00=01ff 01=00ff 02=00ff 03=00ff 04=00ff 05=00ff 06=00ff 07=50ff
spdmem0 at iic0 addr 0x50: 128MB SDRAM non-parity PC133CL3
auvia0 at pci0 dev 7 function 5 "VIA VT82C686 AC97" rev 0x50: irq 10
ac97: codec id 0x41445372 (Analog Devices AD1981A)
ac97: codec features headphone, 20 bit DAC, No 3D Stereo
audio0 at auvia0
fxp0 at pci0 dev 8 function 0 "Intel PRO/100 M" rev 0x10, i82562: irq 9, address 00:08:02:92:e2:0e
inphy0 at fxp0 phy 1: i82555 10/100 PHY, rev. 4
iwi0 at pci0 dev 10 function 0 "Intel PRO/Wireless 2200BG" rev 0x05: can't map interrupt
cbb0 at pci0 dev 11 function 0 "TI PCI1520 CardBus" rev 0x01: irq 9, CardBus support disabled
cbb1 at pci0 dev 11 function 1 "TI PCI1520 CardBus" rev 0x01: irq 11, CardBus support disabled
ohci0 at pci0 dev 12 function 0 "NEC USB" rev 0x41: irq 9, version 1.0, legacy support
ohci1 at pci0 dev 12 function 1 "NEC USB" rev 0x41: irq 11, version 1.0, legacy support
ehci0 at pci0 dev 12 function 2 "NEC USB" rev 0x02: irq 10
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "NEC EHCI root hub" rev 2.00/1.00 addr 1
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
cardslot0 at cbb0 slot 0 flags 0
pcmcia0 at cardslot0
cardslot1 at cbb1 slot 1 flags 0
pcmcia1 at cardslot1
usb1 at ohci0: USB revision 1.0
uhub1 at usb1 "NEC OHCI root hub" rev 1.00/1.00 addr 1
usb2 at ohci1: USB revision 1.0
uhub2 at usb2 "NEC OHCI root hub" rev 1.00/1.00 addr 1
uhidev0 at uhub1 port 2 configuration 1 interface 0 "Jing-Mold USB K/B+Mouse" rev 1.10/3.20 addr 2
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes
wskbd1 at ukbd0 mux 1
wskbd1: connecting to wsdisplay0
uhidev1 at uhub1 port 2 configuration 1 interface 1 "Jing-Mold USB K/B+Mouse" rev 1.10/3.20 addr 2
uhidev1: iclass 3/1, 3 report ids
ums0 at uhidev1 reportid 1: 3 buttons, Z dir
wsmouse0 at ums0 mux 0
uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 3: input=3, output=0, feature=0
vscsi0 at root
scsibus0 at vscsi0: 256 targets
softraid0 at root
scsibus1 at softraid0: 256 targets
root on wd0a (eeaba327d78804c1.a) swap on wd0b dump on wd0b

Основная задача, которую надо было решить, заключалась в автоматическом логине и запуске X. Решить её помог логин менеджер SLiM из пакета x11/slim.
Конфигурация проще некуда – в /etc/slim.conf прописать имя пользователя по умолчанию default_user yason, прописать auto_login yes и добавить SLiM в автозапуск:
$ cat /etc/rc.conf.local
ntpd_flags= # enabled during install
pkg_scripts="dbus_daemon slim"

Для показа слайд-шоу сначала думал использовать graphics/shotwell, но у него нет возможности запуска сразу в режиме слайд-шоу. Да и слишком монструозен он для такой машины и таких задач. Хотя рейтинги фото были бы полезны…
Потом я попробовал graphics/feh. Он больше отвечает моим нуждам – есть рандомайз, возможность привязки различных комманд на цифровые клавиши, но нет автоориентации фото по информации из EXIF тэгов.
В итоге остановился я на graphics/qiv. У программы практически идентичные feh возможности, но в добавок есть опция ориентации фотографий исходя из EXIF информации.
Для моих задач я запускаю qiv с таким набором флагов: qiv -lfusrmd 1 /home/yason/Pictures > ~/qiv.log 2>&1
Выдержки из мануала:
-l, --autorotate
Autorotate JPEGs according to EXIF rotation tag.
-f, --fullscreen
Use fullscreen window on start-up.
-u, --recursivedir
Change the behavior of qiv to recursively descend into the
directories given on the command line.
-s, --slide
Start slideshow immediately. This can also be used for the
desktop background (x/y/z).
-r, --random
Randomize slideshow.
-m, --maxpect
Expand image(s) to fit screen size while preserving aspect
ratio.
-d, --delay x
Set slideshow delay to x seconds.

То есть qiv запускается в режиме слайд-шоу на полный экран с резайзом фотографий до размеров экрана заглядывая в поддиректории и показывая фотографии с правильной ориентацией в пространстве, в случайном порядке по одной секунде.
Для автоматического запуска qiv надо добавить вышеописанную строку в файл .xinitrc пользователя, под которым будет автоматический вход в систему. В моём случае пользователь yason.
Теперь при запуске будет происходить автоматический запуск X, логин и запуск слайд-шоу.
В процессе эксплуатации выяснился один нюанс – сначала запускается скринсейвер X, а через некоторое время монитор переходит в спящий режим. Чтобы его от этого отучить добавил ещё две строки в .xinitrc:
xset -dpms
xset s off

Первая отключает энергосбережение, а вторая – скринсейвер.

Share

Отключение console blanking в Linux

Долго и неспешно искал адекватное решение, позволяющее отключить энергосберегающие фишки, связанные с консолью. Мне не очень удобно, когда на сервере надо нажимать что-нибудь на клавиатуре, чтобы увидеть происходящее в консоли, если она успела погаснуть. Лучший способ энергосбережения – выключить монитор, если ничего не собираешься смотреть.
setterm -blank 0 отключает blanking консоли и решает проблему. Но только в текущей консоли. Чтобы эти настройки применились ко всем консолям, да ещё цеплялись при загрузке машины, самое элегантное решение из всех найденных следующее – добавить вывод этой комманды в файл /etc/issue. В этом файле, по умолчанию, содержится приветствие, которое отображается на незалогиненной консоли. Надо просто добавить вывот setterm в конец файла: echo `setterm -blank 0` >> /etc/issue. Проверено в Scientific Linux 6.4.

Share

Кривой стартер. Пакеты.

Самая простая и не интересная часть – выбор пакетов. Всегда “любил” Linux за то, что при установке он выносит мозг необходимостью выбора пакетов. Благо, благодаря kickstart’у, можно от этого избавиться. Но только для повторных установок, ха-ха.
Первоначальный спискок пакетов и групп пришлось выбирать вручную через UI anaconda. Всё выбранное потом будет отражено в /root/anaconda-ks.cfg, откуда его и следует скопировать в свой kickstart.cfg.
То что было выбрано группами (с префиксом @) и отдельные полезные пакеты из дистрибутива:

# List of packages to be installed.
%packages
@Base
@Core
@base
@client-mgmt-tools
@core
@dial-up
@hardware-monitoring
@misc-sl
@network-tools
@russian-support
@system-admin-tools
@system-management
SL_password_for_singleuser
autofs
device-mapper-persistent-data
dos2unix
lm_sensors
mc
nmap
pptp
rp-pppoe
screen
telnet
unix2dos

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

# Remove packages that were installed with @groups.
-at
-dmraid
-lvm2
-lvm2-libs
-fprintd-pam
-mdadm
-pcmciautils
-rng-tools
-sl-release-notes
-words
-libselinux
-libselinux-utils
-selinux-policy
-selinux-policy-targeted
-postfix
-mysql-libs
-procmail

Часть из них, например postfix, всё равно поставится, т.к. являются чьими-то зависимостями.
В общем пока всё стандартно.

А вот тут есть нюанс. В дистрибутиве уже есть пакеты gstreamer. Да-да, протухшие и с утечками памяти. Я собрал собственные пакеты с более свежим gsreamer’ом, скопировал их на флешку в директорию gst и при помощи creatrepo элегантно превратил директорию в репу с пакетами. Чтобы ставились более свежие версии, чем в самом дистрибе, надо отразить это:

# Install gstreamer python bindings and plugins needed for mss.
# Using versions in names forces installation of rpms with specified versions.
gstreamer-0.10.35-SS.2
gstreamer-python-0.10.22-SS.2
# plugins-good for reading id3tags
gstreamer-plugins-good-0.10.30-SS.2
# plugins-ugly for playing mp3.
gstreamer-plugins-ugly-0.10.18-SS.2

Ну и всякие опциональные полезности, которые ставятся из дополнительно созданного репозитория:

# Install munin-node for monitoring.
munin-node
# Install ntfs utils. They're quite usable in our windoze world.
ntfs-3g
# Install lshw. It would be helpful for inventory datatbase automatization.
lshw
%end

Всё, с пакетами закончили. Теперь установка переходит в завершающую стадию – %post секцию. О ней в следующей части.

Share

Кривой стартер. Интерактивность.

Мне была нужна возможность ввода дополнительной информации при установке. Долго бился и искал решение, но всё же нашёл. Довольно удобное и элегантное. Для решения подобных задач можно использовать секцию %pre. Скрипты из этой секции выполняются ДО запуска установки Linux на жёсткий диск.

%pre
mkdir /tmp/flash
mount /dev/sda4 /tmp/flash

Монтирую флешку в /tmp, так как на момент запуска %pre к ней ещё нет доступа. Манёвр нужен для разделения kickstart на файлы. В дополнительных файлах отдельно прописаны секции %packages и %post, чтобы не делать один большой километровый конфиг.


chvt 6
exec /dev/tty6 2>/dev/tty6

А вот это тот код, который позволяет добавить кастомной интерактивности в процесс установки. Я переключаюсь на шестой виртуальный терминал и перенаправляю на него stdin, stdout и stderr.
# Read MAC address and hostname from stdin.
echo "-- MAC configuration --"
mac=`ifconfig eth0 | awk '/HWaddr/{print $5}'`
echo -n "Current MAC address is $mac ( enter alternative MAC or press return ): "
read _altmac
# Convert MAC to uppercase as in ifconfig output.
altmac=`echo $_altmac | awk '{print toupper($0)}'`

[ -n “$altmac” ] && mac=$altmac
echo “MAC was set to $mac”
# Store variable in temporary file. It will be used in %post section.
echo “$mac” > /tmp/mac.txt
Запрашиваю MAC-адрес, который будет использоваться в роли ключа шифрования. Да, я знаю, это абсольютно не безопасно, но такой ключ шифрования – банальная защита от дурака.
Так как в выводе ifconfig MAC-адрес идёт в верхнем регистре, то я автоматом конвертирую введённую информацию в верхний регистр. Если не вводить MAC, то будет использоваться текущий MAC интерфейса eth0. Значение сохраняю в /tmp для дальнейшего использования.

echo "-- Hostanme configuration --"
echo -n "Enter hostname: "
read _host
# Store hostname in lower case. Upper case breaks at least munin-node.
host=`echo $_host | awk '{print tolower($0)}'`

# Store variable in temporary file. It will be used later in %post section.
echo “Hostname was set to $host”
echo “$host” > /tmp/hostname.txt
Дабы долго не тыркаться в сетевых настройках инсталлятора, я имя машины буду задавать так же скриптом. Плюс проверка чтобы имя было в нижнем регистре. Напирмер munin не опрашивает свои ноды, у которых имена содержат символы в верхнем регистре.

sleep 5
Даю возможность в течение пяти секунд созерцать содеянное и….
chvt 1
exec /dev/tty1 2> /dev/tty1
%end

… переключаюсь обратно на первую консоль, в которй запущенная anaconda приступает к дальнейшей работе.

%include /tmp/flash/ks/packages.cfg
%include /tmp/flash/ks/post.cfg

Вот для этого момента я монтировал флешку в /tmp/flash. Про %include с локального носителя в документации, ессно, ничего толком не написано.

Предварительный этап закончен, больше никаких вопросов установщик не задаст (если только на жёстком диске не было до этого RAID, или если жёсткий диск только из упаковки извлечён).
Можно идти кури^Wпить чай, пока создаются разделы, устанавливаются пакеты и шуршат скрипты из секции %post. Про пакеты писать особо нечего, хотя один нюанс есть. Наибольший интерес представляет секция %post, о которой речь пойдёт через главу.

Share

Кривой стартер. Начало.

В связи с новой работой возникла необходимость автоматизировать установку Linux на x86 железо. Из всего зоопарка пингвинов выбрал Scientific Linux, как наиболее мне привычный (уже имел с ним дело). Плюс SL является основным инструментом моего друга при решении большинства задач, так что будет к кому обратиться с вопросом, если что.
Плюсы, они же и минусы SL да и вообще всех RHEL – их стабильнось. Они не прикручивают всякие новомодные финтифлюшки тоннами и развиваются довольно планомерно, так что SL не сильно отличается от ASP Linux десятилетней давности :). Хотя эта стабильность оборачивается, как я написал, и минусами – в RHEL-based дистрибутивах большинство софта настолько протухшее… Сразу оговорюсь, что я не гонюсь слепо за версией программ. Но в ходе создания установочной флешки выяснил, что в SL (и RHEL) сидит довольно древняя версия gstreamer, у которой серьёзные проблемы с утечками памяти. Убил кучу времени на “отлов” причины. В итоге решил эту проблему сборкой собственных пакетов с более свежей версией gstreamer’a.
Ладно, буду последователен.
В красношапочных дистрибутивах есть такая вещь как kickstart, которая позволяет подготовить файл с ответами на вопросы инсталлятора и автоматизировать установку частично или полностью.
Моей задачей было сделать автономную и максимально автоматизированную установку. Под автономностью я подразумеваю отсутствие доступа к сети, только установочная флешка и минимальное количество вопросов, задаваемое установщиком.
Для моих задач хватает флешки на 8GiB. Чтобы её создать не заморачиваясь с dd и прочими юниксовыми утилитами, я, по совету друга, возпользовался UltraISO и её возможностью писать ISO образы на флешки. Причём она не просто пишет, но ещё и подсовывает корректный вайл syslinux.cfg Для этого надо в UltraISO открыть образ SL-64-i386-2013-03-18-boot.iso (т.е. минимальный загрузочный образ) и через меню выбрать запись образа диска. В роли destination выбираем флешку. Через энсколько минут получается флешка, с которой уже можно загрузиться и попасть в инсталлятор anaconda.
Теперь можно переходить к самому кикстарту. Шаблон этого файла можно получить сделав пробную установку. По окончании установки в домашней директории пользователя root появится файл anaconda-ks.cfg, который можно будет дорабатывать напильником. Я приведу выдержки из уже готового файла. Краткие комментарии мною уже сделаны в самом файле, так что более подробно буду комментировать только отдельные моменты.

install

# Force using textmode install. Why anyone will need GUI when smoking?
# But even in this case one may need more than 384M of RAM to run install.
text

# Tell installer where ISO image is.
harddrive --partition=sda4 --dir=/

Последней строчкой я указываю инсталлятору место нахождения DVD образа SL-64-i386-2013-03-18-Install-DVD.iso. Этот образ отличается от boot.iso тем, что содержит репозитории с пакетами. В моём случае этот путь указывает инсталлатору на то, что установочный образ находится в корне раздела sda4. sda4 – это сама флешка. Т.е. установочный образ надо скопировать в корень флешки.


# No russian in console!!! Learn to read, write and understand documentation in English.
lang en_US.UTF-8
keyboard us

# Configure interface to use DHCP by default.
network --onboot=yes --bootproto=dhcp --noipv6

# Do you want to know how it looks like in palintext? ;)
rootpw --iscrypted BLAH_BLAH_BLAH

В шифрованном виде пароль, естественно, выглядит иначе ;)

# Open SSH and munin-node by default.
firewall --service=ssh --port=4949

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

# Disable SElinux. It's evil in most cases.
selinux --disabled

SELinux я готовить не умею и воевать с ним не хочу, отключаю.

# Add reboot=bios fix for Acer netbooks.
bootloader --location=mbr --driveorder=sdb,sda --append="crashkernel=auto rhgb quiet reboot=bios"

На Acer Apire One вылезла проблема – при перезагрузке они висли. Помогало только нажатие на кнопку питания. Т.к. наше оборудование должно быть максимально автономным, то эту проблему надо было решить. Покопавшись на форумах узнал, что для решения проблемы надо указать загрузчику дополнительный параметр reboot=bios.

# Clear all existing partitions on destiation disk.
clearpart --all --drives=sdb

При загрузке с флешки ядро определяет флешку как диск sda, а жёсткий диск – как sdb. Соответственно жёсткий диск я предварительно очищаю от существующих разделов.

# Don't touch our installation usb stick.
part None --fstype=efi --label="Scientific" --onpart=sda4 --noformat

Anaconda автоматом создала строчку, предотвращающую изменеия на флешке при установке. Я, естественно, решил её оставить.

# Create partitions. Set --asprimary to prevent creating extended partition.
part /boot --asprimary --fstype=ext4 --size=100
part swap --asprimary --size=256
part / --asprimary --fstype=ext4 --size=2000
# We should create this partition for further use as crypto partition.
# I can't find a way to create it without formatting.
part /var/lib/mss --asprimary --fstype=ext4 --grow --size=1024

В моём случае нужны четыре раздела – /boot, swap, / и раздел с данными /var/lib/mss. Чтобы при установке не плодились ненужные мне extended разделы, я для каждого раздела указал параметр --asprimary. Раздел /var/lib/mss в пост-инсталляционном скрипте будет сделан шифрованым. Создаю я его штаными средствами чтобы потом не развлекаться со скриптованием для fdisk. Не делаю его шифрованым штаными средствами, т.к. ключом шифрования будет являться файл с MAC-адресом и автоматизацию этого процесса так же удобнее делать в %post секции.

# Configure list of services.
services --disabled pppoe-server,mdmonitor,ip6tables,kdump
# Enable autofs for automounting flash drives with updates.
# Enable ntpd so machine can obtain correct time from NTP server if Internet connection is available.
# Enable munin-node for monitoring machines with Internet access.
services --enabled autofs,ntpd,munin-node

Тут всё понятно. Отключаю лишнее, добавляю нужное. Через services --enabled добавить можно только сервисы из базового дистрибутива или из дополнительных репозиториев. Я писал init.d скрипт для собственной программы и его добавлял уже в %post скрипте.

# Add local repos for extra packages (i.e. munin-node and gstreamer-plugins-ugly).
repo --name=SSextras --baseurl=file:///mnt/isodir/extras
repo --name=SSgst --baseurl=file:///mnt/isodir/gst

Методом тыка выяснил, как же нативно добраться до флешки во время установки. Оказалось, что инсталлятор её монтирует в /mnt/isodir. Тут я добавил два репозитория с дополнительными пакетами, которых нет в базовом дистрибутиве.
Чтобы директорию с пакетами сделать репозиторием, надо натравить на неё программу createrepo – она создаст всю необходимую структуру, понятную пакетному менеджеру. Прога есть в родном репозитории SL.

Дальше начинается более интересная часть, на которую я потратил существенное количество сил и времени. Данная информация, по большей части, была почерпнута из форумов. В официальном руководстве по kickstart’у ничего полезного про предустановочные скрипты не пишут. Результаты изысканий в следующей части.

Share