AmazonLinuxでHAProxy1.6.6をrpmビルド


HAProxyが1.6.6になって動的名前解決がサポートされた。
RDSでHAProxyを使う場合、1.5以前ではMulti-AZフェイルオーバ発生時やインスタンスの再作成にはHAProxyを再起動する作業が必要だった。
1.6.6は動的名前解決が出来るのでそこに懸念する必要が無くなる。

20160711現在のAmazonLinuxの標準yumリポジトリでは1.5.2までしか公開されていない。

Fedora24ではRPMが公開されてる。
https://www.rpmfind.net/linux/RPM/fedora/updates/24/x86_64/h/haproxy-1.6.6-2.fc24.x86_64.html

AmazonLinuxのRPMとFedora24のRPMをマージしてビルドするのに成功したので手順を残す。

なお、HAProxy 1.6系からサポートされているluaには非対応。 AmazonLinuxのrpm/yumはlua 5.1に依存しているが
HAProxy 1.6系でluaを利用する場合、lua 5.3が必要になり苦しめられる未来しか見えない。


# RPMビルド環境の用意
rpmbuildコマンドを使ってrpmをビルドする。
ビルド環境を使い捨てる場合は気にする必要は無いが
システムに影響を出さないためにroot以外のユーザでビルドするのが推奨されてる。

`rpmbuilder` というような適当なユーザを作っておくのが望ましい。

```
# yum -y groupinstall "Development tools"
# yum -y install rpmdevtools
# useradd -s /sbin/nologin mockbuild
# useradd rpmbuilder
# su - rpmbuilder
$ rpmdev-setuptree
$ exit
```

# HAProxyのソースを集める
## haproxy-1.6.6-2.fc24.src.rpm
rpmfind.netにて提供されているFedora24のテストリポジトリから201607時点での最新版を取得

```
# cd ~rpmbuilder
# wget http://fr2.rpmfind.net/linux/fedora/linux/updates/24/SRPMS/h/haproxy-1.6.6-2.fc24.src.rpm
# chmod a+r haproxy-1.6.6-2.fc24.src.rpm
```

## haproxy-1.5.2-2.5.amzn1.src.rpm

AmazonLinuxで提供されているhaproxy-1.5.2のsrpmも取得する
get_reference_sourceではインストール済みパッケージしかソースをダウンロード出来ないため

```
# yum install haproxy-1.5.2-2.5.amzn1.x86_64
# get_reference_source -p haproxy-1.5.2-2.5.amzn1.x86_64

Requested package: haproxy-1.5.2-2.5.amzn1
Found package from local RPM database: haproxy-1.5.2-2.5.amzn1.x86_64
Corresponding source RPM to found package : haproxy-1.5.2-2.5.amzn1.src.rpm

Are these parameters correct? Please type 'yes' to continue: yes

```

`yes` と入力すると`/usr/src/srpm/debug/haproxy-1.5.2-2.5.amzn1.src.rpm` にSRPMが保存される

```
# mv /usr/src/srpm/debug/haproxy-1.5.2-2.5.amzn1.src.rpm ~rpmbuilder/
# chmod a+r haproxy-1.5.2-2.5.amzn1.src.rpm
```

あとはHAProxyをビルドするのに必要なパッケージを導入する

```
# yum install pcre-devel zlib-devel openssl-devel
```

# ビルド
```
# su - rpmbuilder
$ rpm -ivh haproxy-1.5.2-2.5.amzn1.src.rpm
$ rpm -ivh haproxy-1.6.6-2.fc24.src.rpm
```

## specファイル作成
~/rpmbuild/SPECS/haproxy.spec に以下を記載

```
%define haproxy_user    haproxy
%define haproxy_uid     188
%define haproxy_group   %{haproxy_user}
%define haproxy_gid     %{haproxy_uid}
%define haproxy_home    %{_localstatedir}/lib/haproxy
%define haproxy_confdir %{_sysconfdir}/haproxy
%define haproxy_datadir %{_datadir}/haproxy

%global _hardened_build 1

Name:           haproxy
Version:        1.6.6
Release:        1%{?dist}
Summary:        HAProxy reverse proxy for high availability environments

Group:          System Environment/Daemons
License:        GPLv2+

URL:            http://www.haproxy.org/
Source0:        http://www.haproxy.org/download/1.6/src/haproxy-%{version}.tar.gz
Source1:        %{name}.init
Source2:        %{name}.cfg
Source3:        %{name}.logrotate
Source4:        %{name}.sysconfig
Source5:        halog.1

Patch0:         halog-unused-variables.patch
Patch1:         iprange-return-type.patch

#BuildRequires:  lua-devel
BuildRequires:  pcre-devel
BuildRequires:  zlib-devel
BuildRequires:  openssl-devel

Requires(pre): /usr/bin/getent
Requires(pre): %{_sbindir}/groupadd
Requires(pre): %{_sbindir}/useradd
Requires(post): /sbin/chkconfig
Requires(preun): /sbin/chkconfig
Requires(preun): /sbin/service
Requires(postun): /sbin/service

%description
HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high
availability environments. Indeed, it can:
 - route HTTP requests depending on statically assigned cookies
 - spread load among several servers while assuring server persistence
   through the use of HTTP cookies
 - switch to backup servers in the event a main one fails
 - accept connections to special ports dedicated to service monitoring
 - stop accepting connections without breaking existing ones
 - add, modify, and delete HTTP headers in both directions
 - block requests matching particular patterns
 - report detailed status to authenticated users from a URI
   intercepted from the application

%prep
%setup -q
%patch0 -p0
%patch1 -p0

%build
regparm_opts=
%ifarch %ix86 x86_64
regparm_opts="USE_REGPARM=1"
%endif

%{__make} %{?_smp_mflags} CPU="generic" TARGET="linux2628" USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1 ${regparm_opts} ADDINC="%{optflags}" USE_LINUX_TPROXY=1

pushd contrib/halog
%{__make} ${halog} OPTIMIZE="%{optflags}"
popd

pushd contrib/iprange
%{__make} iprange OPTIMIZE="%{optflags}"
popd

%install
%{__make} install-bin DESTDIR=%{buildroot} PREFIX=%{_prefix} TARGET="linux2628"
%{__make} install-man DESTDIR=%{buildroot} PREFIX=%{_prefix}

%{__install} -p -D -m 0755 %{SOURCE1} %{buildroot}%{_initrddir}/%{name}
%{__install} -p -D -m 0644 %{SOURCE2} %{buildroot}%{haproxy_confdir}/%{name}.cfg
%{__install} -p -D -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
%{__install} -p -D -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
%{__install} -p -D -m 0644 %{SOURCE5} %{buildroot}%{_mandir}/man1/halog.1
%{__install} -d -m 0755 %{buildroot}%{haproxy_home}
%{__install} -d -m 0755 %{buildroot}%{haproxy_datadir}
%{__install} -d -m 0755 %{buildroot}%{_bindir}
%{__install} -p -m 0755 ./contrib/halog/halog %{buildroot}%{_bindir}/halog
%{__install} -p -m 0755 ./contrib/iprange/iprange %{buildroot}%{_bindir}/iprange
%{__install} -p -m 0644 ./examples/errorfiles/* %{buildroot}%{haproxy_datadir}


for httpfile in $(find ./examples/errorfiles/ -type f)
do
    %{__install} -p -m 0644 $httpfile %{buildroot}%{haproxy_datadir}
done

%{__rm} -rf ./examples/errorfiles/

find ./examples/* -type f ! -name "*.cfg" -exec %{__rm} -f "{}" \;

for textfile in $(find ./ -type f -name '*.txt')
do
    %{__mv} $textfile $textfile.old
    iconv --from-code ISO8859-1 --to-code UTF-8 --output $textfile $textfile.old
    %{__rm} -f $textfile.old
done

%pre
/usr/bin/getent group %{haproxy_group} >/dev/null || \
    %{_sbindir}/groupadd -g %{haproxy_gid} -r %{haproxy_group}
/usr/bin/getent passwd %{haproxy_user} >/dev/null || \
    %{_sbindir}/useradd -u %{haproxy_uid} -g %{haproxy_group} \
    -d %{haproxy_home} -s /sbin/nologin -r %{haproxy_user}
exit 0

%post
/sbin/chkconfig --add haproxy

%preun
if [ "$1" -eq 0 ]; then
    /sbin/service haproxy stop >/dev/null 2>&1
    /sbin/chkconfig --del haproxy
fi

%postun
if [ "$1" -ge 1 ]; then
    /sbin/service haproxy condrestart >/dev/null 2>&1 || :
fi

%files
%defattr(-,root,root,-)
%doc doc/* examples/*
%doc CHANGELOG LICENSE README ROADMAP VERSION
%dir %{haproxy_confdir}
%dir %{haproxy_datadir}
%{haproxy_datadir}/*
%config(noreplace) %{haproxy_confdir}/%{name}.cfg
%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
%{_initrddir}/%{name}
%{_sbindir}/%{name}
%{_sbindir}/%{name}-systemd-wrapper
%{_bindir}/halog
%{_bindir}/iprange
%{_mandir}/man1/*
%attr(-,%{haproxy_user},%{haproxy_group}) %dir %{haproxy_home}


%changelog
* Tue Jul 5 2016 Yuki Furukoshi <furukoshi@cloudpack.jp>
- initial build @1.6.6
```


## ビルド
```
$ rpmbuild -ba rpmbuild/SPECS/haproxy.spec
```

完了すると以下ディレクトリにrpmファイルが出来ている。

```
$ tree rpmbuild/RPMS/
rpmbuild/RPMS/
└── x86_64
    ├── haproxy-1.6.6-1.amzn1.x86_64.rpm
    └── haproxy-debuginfo-1.6.6-1.amzn1.x86_64.rpm
```

後はビルド出来たrpmを `rpm -ivh` で入れたり、煮るなり焼くなり好きにすれば良い。


# 参考
- https://www.rpmfind.net/linux/RPM/fedora/updates/testing/24/x86_64/h/haproxy-1.6.6-2.fc24.x86_64.html
- http://uorat.hatenablog.com/entry/2016/05/29/173717
- https://github.com/otabari/haproxy-rpmbuilder