Сборка Nginx в DEB-пакет

Date April 8th, 2014 Author Vitaly Agapov

И тут на Ёжика, шурша и осыпаясь, обрушилась тишина.

Сергей Козлов «Ёжик в тумане»

nginx deb package

Нижеследующий текст не претендует на полноту, объективность и, может быть, даже на полезность. Это просто очередной кусок скомканных заметок, которые я для себя оставляю в Evernote, а потом изредка достаю оттуда, разбавляю бестолковыми комментариями и переношу в бложик в беспочвенной надежде, что кому-нибудь пригодится. В данном случае это будет статья по сборке Nginx из исходников в Debian-пакет для размещения его на своём локальном репозитории. Этот навык полезен в том случае, когда Nginx работает на нескольких машинах и хочется удобно обновлять его сразу везде.

Впрочем, и не обязательно иметь несколько машин. Даже если речь идёт об одном сервере, хорошим тоном будет устанавливать программы через менеджер пакетов. В будущем эта привычка сможет оградить от многих проблем и добавить удобства упраления файлами. В Debian/Ubuntu от make && make install стоит отказаться ради душевного спокойствия и очистки кармы.

Так-то в большинстве случаев можно просто ставить Nginx из официальных репозиториев (или даже с LaunchPad'а, где всегда можно найти распоследнюю версию), но Nginx не умеет подключать внешние модули. Хочешь нестандартный модуль – компилируй. Этим и займёмся.

 

ModSecurity

В моём случае этим нестандартным модулем будет ModSecurity. Про его сборку я уже писал ранее, так что всё кратко:

wget https://www.modsecurity.org/tarball/2.7.7/modsecurity-apache_2.7.7.tar.gz
tar -xzvf modsecurity-apache_2.7.7.tar.gz
cd modsecurity-apache_2.7.7
apt-get install apache2-dev libxml2-dev libcurl4-openssl-dev
./configure --enable-standalone-module
make

Подготовка

Установим нужные для сборки пакеты:

apt-get install devscripts build-essential dpkg-dev debhelper autotools-dev dh-make libgeoip-dev libperl-dev libcap-dev
 
Скачаем исходники:

wget http://nginx.org/download/nginx-1.4.7.tar.gz
tar -xzvf nginx-1.4.7.tar.gz
mv nginx-1.4.7 nginx-my-1.4.7
cd ../nginx-1.4.7/

Особенностью моей истории является то, что я меняю название пакета. То есть хочу, чтобы моя сборка Nginx была в репозитории под названием, скажем, nginx-my и не пересекалась с обычными пакетами nginx-full, nginx-light, nginx-naxsi о прочими. Поэтому я заодно и меняю название папки с исходниками.

Дебианизация

Слово дурацкое, но что поделаешь. Фактически нам тут нужно сделать специальную директорию debian, содержащую набор файлов, определяющих все свойства пакета, включая инструкции для сборщика, changelog и прочее. Вот здесь можно прочитать об основных файлах подробнее.

И тут можно пойти двумя путями: прямым и весьма читерско-окольным.

Первый способ – это создание рыбы всех файлов с помощью команды

dh_make --createorig

Предполагается, что директория имеет вид "имя-версия". А опция –createorig создаёт архивный файл имя-версия.orig.tar.gz. Если такой файл там уже есть, то опция не нужна.
После создания каталога debian файлы в нём нужно под свои цели править вручную.

Второй способ – это использование каталога debian из исходников в репозитории. Для этого надо скачать из репозитория пакет:

apt-get source nginx

и скопировать всю папку debian оттуда. Но её придётся должным образом доработать, так что оба способа потребуют определённых трудозатрат. Я выбрал всё-таки второй.

Итак, что нужно сделать по порядку:

1. Положить ModSecurity в debian/modules:

cp -r modsecurity-apache_2.7.7 nginx-my-1.4.7/debian/modules/

2. Удалить старые патчи:

cd nginx-my-1.4.7/debian/
rm patches/*

3. Поправить файл control. Этот файл содержит общую информацию о пакете, и если за основу взят файл control из репозитория, то его нужно сильно сократить. Мой вариант выглядит так:

Source: nginx-my
Section: httpd
Priority: optional
Maintainer: Vitaly Agapov <mymail>
Build-Depends: autotools-dev,
               debhelper (>= 7),
               dpkg-dev (>= 1.15.5),
               libexpat-dev,
               libgeoip-dev,
               libpcre3-dev,
               libssl-dev,
               po-debconf,
               libegl1-mesa,
               libgl1-mesa-glx,
               zlib1g-dev
Standards-Version: 3.9.4
Homepage: http://nginx.net

Package: nginx-my
Architecture: all
Depends: lsb-base (>= 3.2-14), ${misc:Depends}, ${shlibs:Depends}
Conflicts: nginx, nginx-common, nginx-full, nginx-light, nginx-naxsi, nginx-extras
Description: Nginx with ModSecurity

Для определения списка зависимостей можно воспользоваться утилитой dpkg-depcheck из пакета devscripts:

dpkg-depcheck -d ./configure --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/sbin/nginx --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --without-http_fastcgi_module --without-http_uwsgi_module --without-http_scgi_module --without-http_memcached_module --with-http_geoip_module --with-http_stub_status_module --with-http_ssl_module --with-ipv6 --add-module=debian/modules/modsecurity-apache_2.7.7/nginx/modsecurity/

Packages needed:
  srvadmin-omcommon
  libpcre3-dev:amd64
  libegl1-mesa:amd64
  srvadmin-isvc
  libgeoip-dev
  srvadmin-omacore
  srvadmin-storelib
  libgl1-mesa-glx:amd64
  srvadmin-storage
  libssl1.0.0:amd64
  srvadmin-realssd
  zlib1g-dev:amd64
  srvadmin-hapi
  libssl-dev:amd64
  srvadmin-deng

Эти пакеты и нужно поместить в Build-Depends файла control.

4. Поправить changelog. Тут две главные тонкости. Во-первых, имя пакета в changelog должно совпадать с именем пакета в control и в названии каталога, в котором мы работаем. Во вторых, версия в последней записи будет соответствовать версии пакета, которая получится при сборке.

Поэтому нужно в начало файла changelog дописать секцию вида:

nginx-my (1.4.7-build1) saucy; urgency=low

  * Initial release for myrepo.example.com

 -- Vitaly Agapov Fri, 04 Apr 2014 15:00:00 +0400

Старый записи можно либо удалить, либо оставить. Чтобы не ошибиться с синтаксисом, можно для добавления секции воспользоваться утилитой dch из того же пакета devscripts:

dch -v 1.4.7-build2

5. Переименовать служебные файлы.

В каталоге debian здесь лежат файлы, необходимые для работы отдельных команд из файла rules. Если имя пакета меняется, то эти файлы нужно переименовать. Например, команда dh_install использует файл packagename.install. Команда dh_installdirs – файл packagename.dirs.

Вот быстрый вариант:

for a in `ls nginx-common*`; do mv $a `echo $a | sed 's/nginx-common/nginx-my/'`; done

Плюс в конец файла nginx-my.install нужно добавить строчку 

debian/build/objs/nginx usr/sbin

Так как сборку мы будем производить в каталог build (и для этого ещё соответствующим образом нужно будет поправить файл rules). Плюс в файл nginx-my.dirs добавить строчку

usr/sbin

6. Поправить дефолтные конфиги.

В файле nginx-my.install указано, что в etc/nginx при инсталляции будут положены файлы из debian/conf/. И это отличная возможность поправить конфиги на более вменяемые. Это уж на своё усмотрение.

Вообще свои грязные ручки тут можно запустить куда угодно. Хоть в конфиг для logrotate, хоть в описание сервиса для SystemD (nginx-my.service).

7. Поправить файл rules.

Это почти обычный Makefile и он при сборке является основным руководством к действию для сборщика. В самом простом случае, когда мы не меняем название пакета и нам наплевать на то, что в репозиторном файле прописана сразу россыпь разных пакетов nginx с разным набором модулей, мы можем просто поправить в нём ключи для скрипта configure и сразу перейти к следующему шагу.

В нашем же случае файл rules можно привести примерно к такому виду:

#!/usr/bin/make -f

CFLAGS = `dpkg-buildflags --get CFLAGS`
CFLAGS += -Wall -DFORTIFY_SOURCE=2 -fstack-protector
CFLAGS += `dpkg-buildflags --get CPPFLAGS`
LDFLAGS = `dpkg-buildflags --get LDFLAGS`
export CFLAGS LDFLAGS

BUILDDIR = $(CURDIR)/debian/build
MODULESDIR = $(CURDIR)/debian/modules
BASEDIR = $(CURDIR)

DEB_BUILD_ARCH ?=$(shell dpkg-architecture -qDEB_BUILD_ARCH)

ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
	NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
	ifeq (${NUMJOBS}, 0)
		NUMJOBS = 1
	endif
else
	NUMJOBS = 1
endif

config.sub:
	dh_testdir
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
		cp -f /usr/share/misc/config.sub config.sub
endif

config.guess:
	dh_testdir
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
		cp -f /usr/share/misc/config.guess config.guess
endif

config.env:
	dh_testdir
	mkdir -p $(BUILDDIR)
	cp -Pa $(CURDIR)/auto $(BUILDDIR)/
	cp -Pa $(CURDIR)/conf $(BUILDDIR)/
	cp -Pa $(CURDIR)/configure $(BUILDDIR)/
	cp -Pa $(CURDIR)/contrib $(BUILDDIR)/
	cp -Pa $(CURDIR)/src $(BUILDDIR)/
	cp -Pa $(CURDIR)/man $(BUILDDIR)/

config.status: config.env config.sub config.guess
	cd $(BUILDDIR) && CFLAGS="$(CFLAGS)" CORE_LINK="$(LDFLAGS)" ./configure  \
	    --prefix=/etc/nginx \
	    --conf-path=/etc/nginx/nginx.conf \
            --sbin-path=/usr/sbin/nginx \
	    --error-log-path=/var/log/nginx/error.log \
	    --http-client-body-temp-path=/var/lib/nginx/body \
	    --http-log-path=/var/log/nginx/access.log \
	    --http-proxy-temp-path=/var/lib/nginx/proxy \
	    --lock-path=/var/lock/nginx.lock \
	    --pid-path=/var/run/nginx.pid \
	    --without-mail_pop3_module \
            --without-mail_imap_module \
            --without-mail_smtp_module \
            --without-http_fastcgi_module \
            --without-http_uwsgi_module \
            --without-http_scgi_module \
            --without-http_memcached_module \
	    --with-http_geoip_module \
	    --with-http_stub_status_module \
	    --with-http_ssl_module \
	    --with-ipv6 \
	    --add-module=$(MODULESDIR)/modsecurity-apache_2.7.7/nginx/modsecurity \
            $(CONFIGURE_OPTS) >$@
	touch $@

build-arch: config.status
	dh_testdir
	touch $@
	dh_prep
	$(MAKE) -j$(NUMJOBS) -C $(BUILDDIR) build

build-dbg: install
	dh_testdir
	touch $@
	dh_strip --package=nginx-my

build-indep:

build: build-indep build-arch
	dh_testdir
	touch $@

clean:
	dh_testdir
	dh_testroot
	rm -f build-stamp
	rm -f config.sub config.guess
	dh_clean
	rm -rf $(CURDIR)/debian/build
mime-types:
	

install: mime-types
	dh_testdir
	dh_testroot
	dh_prep
	dh_installdirs
	dh_install

binary-indep: build install
	dh_testdir
	dh_testroot
	dh_installman -i
	dh_installchangelogs -i -k CHANGES
	dh_installdocs -i
	dh_installdebconf
	dh_installexamples -i
	dh_installinit -r --no-start -i --name=nginx
	cp debian/logrotate debian/nginx-my/etc/logrotate.d/nginx
	mkdir -p debian/nginx-my/lib/systemd/system
	cp debian/nginx-my.service debian/nginx-my/lib/systemd/system/nginx.service
	dh_link -i
	dh_compress -i
	dh_fixperms -i
	dh_installdeb -i
	dh_gencontrol -i
	dh_md5sums -i
	dh_builddeb -i

binary-arch: install build-dbg
	dh_testdir
	dh_testroot
	dh_installchangelogs -a -k CHANGES
	dh_installdocs -a
	dh_link -aA
	dh_compress -a
	dh_perl -a
	dh_fixperms -a
	dh_installdeb -a
	dh_shlibdeps -a
	dh_gencontrol -a
	dh_md5sums -a
	dh_builddeb -a

binary: binary-indep binary-arch

.PHONY: build clean binary-indep binary-arch binary install

Сборка пакета

dpkg-buildpackage -b -rfakeroot -us -uc

Проект сконфигурируется, скомпилируется и соберётся в DEB-пакет. Дальше останется просто положить пакет в репозиторий. Для этого скопируем файл в папку репозитория, dpkg-scanpackages в руки и вперёд. Но это уже другая история.

Tags: ,
Category: Linux, Nginx | No comments »

Comments

Leave a comment

 Comment Form