Create an RPM Package
As of December 2, 2022, there were no rpm packages for NGINX Prometheus Exporter which could be easily installed in Alma Linux 9 (or other RHEL clones). I built a package for my needs and thanks to Open Build Service (OBS) made it available to others.
RPM Package
There is lots and lots of documentation on what an rpm package is and how to create one. You can follow the links at the end of this post for further reading. I will only talk about the steps I needed to take to get this package built.
- Download the latest release of NGINX Prometheus Exporter. I chose amd64 and arm64 because those are the only ones I was interested in.
- Create a spec file.
- Create a systemd service file.
- Create a default configuration file.
You will find all these files in my OBS subproject: nginx-prometheus-exporter.
I am posting these files here, too, to explain what they mean and where I learned how to create them.
nginx-prometheus-exporter.spec
Name: nginx-prometheus-exporter Version: 0.11.0 Release: 1 License: Apache-2.0 Group: System/Management Summary: NGINX Prometheus exporter Url: https://github.com/nginxinc/nginx-prometheus-exporter Source0: nginx-prometheus-exporter_%{version}_linux_amd64.tar.gz Source1: nginx-prometheus-exporter_%{version}_linux_arm64.tar.gz Source2: nginx-prometheus-exporter.service Source3: nginx-prometheus-exporter.default BuildRequires: systemd-rpm-macros BuildRoot: %{_tmppath}/%{name}-%{version}-build Requires: systemd-rpm-macros %description NGINX Prometheus exporter makes it possible to monitor NGINX or NGINX Plus using Prometheus. %ifarch aarch64 %prep %setup -a 1 -b 1 -c -n %{name}_%{version} %endif %ifarch x86_64 %prep %setup -a 0 -b 0 -c -n %{name}_%{version} %endif %build %install rm -rf $RPM_BUILD_ROOT install -dp %{buildroot}%{_bindir} install -dp %{buildroot}/etc/default install -dp %{buildroot}%{_unitdir} install -p -m 755 %{name} %{buildroot}%{_bindir} install -p -m 644 %{SOURCE2} %{buildroot}%{_unitdir}/%{name}.service install -p -m 644 %{SOURCE3} %{buildroot}/etc/default/%{name} %pre %systemd_pre nginx-prometheus-exporter.service getent group prometheus >/dev/null || %{_sbindir}/groupadd -r prometheus getent passwd prometheus >/dev/null || %{_sbindir}/useradd -r -g prometheus -d %{_localstatedir}/lib/prometheus -M -s /sbin/nologin prometheus %post %systemd_post nginx-prometheus-exporter.service %preun %systemd_preun nginx-prometheus-exporter.service %postun %systemd_postun nginx-prometheus-exporter.service %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{_bindir}/%{name} %{_unitdir}/%{name}.service /etc/default/%{name} %changelog
I took direct help from the sources below to write this spec file.
Multiple Architectures
I was interested in two architectures and so downloaded the release tarballs for both. Thankfully the releases are pre-built binaries so I didn't have to build them from scratch. I just needed to wrap them in an RPM package.
Notice Source0 and Source1 in the spec file. They are the two release
tarballs. I downloaded them with curl
.
$ curl -LO https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_darwin_amd64.tar.gz $ curl -LO https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_darwin_arm64.tar.gz
In the %pre
section I used ifarch
to determine which architecture was used
to build the package and used the corresponding tarball. OBS spins up the
appropriate architecture to build the package so it works beautifully there.
I learned that
rpm --eval %{arm}
, when run
in a newer version of Alma Linux (or other RHEL clones), will show all
supported ARM architectures. Unfortunately, instead of armv8, aarch64 is
the right name. I found that in OBS. If I run rpm --eval %{_arch}
on my
Raspberry Pi 3, its output is aarch64. The output on a Linode VM is x86_64
as well as on OBS. These are the values I used.
Since both tarballs have the same files, after unpacking them in %setup
, I
didn't need to use %ifarch
in other sections.
%systemd_*
Since the package was meant for a systemd-enabled OS I had to use %systemd_
macros. These are provided by the systemd-rpm-macros package.
User prometheus
I had to run the exporter service as some user. So I created the prometheus group and user.
nginx-prometheus-exporter.service
[Unit] Description=NGINX Prometheus Exporter Documentation=https://github.com/nginxinc/nginx-prometheus-exporter After=network-online.target nginx.service Wants=network-online.target [Service] User=prometheus EnvironmentFile=/etc/default/nginx-prometheus-exporter ExecStart=/usr/bin/nginx-prometheus-exporter $ARGS ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target
I took direct help from the sources below to write this service file.
nginx-prometheus-exporter.default
ARGS="" # Usage of /usr/bin/nginx-prometheus-exporter: # -nginx.plus # Start the exporter for NGINX Plus. By default, the exporter is started for NGINX. The default value can be overwritten by NGINX_PLUS environment variable. # -nginx.retries uint # A number of retries the exporter will make on start to connect to the NGINX stub_status page/NGINX Plus API before exiting with an error. The default value can be overwritten by NGINX_RETRIES environment variable. # -nginx.retry-interval value # An interval between retries to connect to the NGINX stub_status page/NGINX Plus API on start. The default value can be overwritten by NGINX_RETRY_INTERVAL environment variable. (default 5s) # -nginx.scrape-uri string # A URI or unix domain socket path for scraping NGINX or NGINX Plus metrics. # For NGINX, the stub_status page must be available through the URI. For NGINX Plus -- the API. The default value can be overwritten by SCRAPE_URI environment variable. (default "http://127.0.0.1:8080/stub_status") # -nginx.ssl-ca-cert string # Path to the PEM encoded CA certificate file used to validate the servers SSL certificate. The default value can be overwritten by SSL_CA_CERT environment variable. # -nginx.ssl-client-cert string # Path to the PEM encoded client certificate file to use when connecting to the server. The default value can be overwritten by SSL_CLIENT_CERT environment variable. # -nginx.ssl-client-key string # Path to the PEM encoded client certificate key file to use when connecting to the server. The default value can be overwritten by SSL_CLIENT_KEY environment variable. # -nginx.ssl-verify # Perform SSL certificate verification. The default value can be overwritten by SSL_VERIFY environment variable. (default true) # -nginx.timeout value # A timeout for scraping metrics from NGINX or NGINX Plus. The default value can be overwritten by TIMEOUT environment variable. (default 5s) # -prometheus.const-labels value # A comma separated list of constant labels that will be used in every metric. Format is label1=value1,label2=value2... The default value can be overwritten by CONST_LABELS environment variable. # -version # Display the NGINX exporter version. # -web.listen-address string # An address or unix domain socket path to listen on for web interface and telemetry. The default value can be overwritten by LISTEN_ADDRESS environment variable. (default ":9113") # -web.secured-metrics # Expose metrics using https. The default value can be overwritten by SECURED_METRICS variable. # -web.ssl-server-cert string # Path to the PEM encoded certificate for the nginx-exporter metrics server(when web.secured-metrics=true). The default value can be overwritten by SSL_SERVER_CERT variable. # -web.ssl-server-key string # Path to the PEM encoded key for the nginx-exporter metrics server (when web.secured-metrics=true). The default value can be overwritten by SSL_SERVER_KEY variable. # -web.telemetry-path string # A path under which to expose metrics. The default value can be overwritten by TELEMETRY_PATH environment variable. (default "/metrics") #
This file is used by nginx-prometheus-exporter.service (see EnvironmentFile)
to provide the default arguments to the service. It's placed under /etc/default
directory and admins can modify it to suit their needs. I had to use the
-nginx.scrape-uri
flag because my nginx stub site was configured differently
than what the exporter expects by default.
Open Build Service
I used
Open Build Service
(OBS) to create this package and make it available in a repository. It works
differently from if you built an RPM package locally. For example, I didn't
have to organize the files in a specific directory structure that rpmbuild
expects. All files lived in the same directory.
Create an account on OBS.
Install osc
, e.g. on macOS with Homebrew.
$ brew install osc
Configure osc
.
Create a subproject in the OBS web UI.
Configure repositories in the web UI. There was no RHEL 9 repository (environment) available, only RHEL 7 and older. I chose Fedora 37 because it was the newest available. Since I'm not building the binaries and only wrapping pre-built binaries in a package, this was good enough. It feels weird to build on Fedora 37 and have that as part of the repository name but it works fine. I also only included x86_64 and aarch64 architectures as discussed above. Get a list of all supported distributions here: https://api.opensuse.org/distributions?format=json (Build Service supported build targets). Use API docs for more information.
# https://build.opensuse.org/projects/home:aikchar:nginx-prometheus-exporter/meta <project name="home:aikchar:nginx-prometheus-exporter"> <title>nginx-prometheus-exporter</title> <description>NGINX Prometheus exporter makes it possible to monitor NGINX or NGINX Plus using Prometheus.</description> <person userid="aikchar" role="maintainer"/> <repository name="Fedora_37"> <path project="Fedora:37" repository="standard"/> <arch>x86_64</arch> <arch>aarch64</arch> </repository> </project>
Check out the project,
$ osc checkout home:aikchar:nginx-prometheus-exporter
Create new package in the checked out project workspace,
$ cd home:aikchar:nginx-prometheus-exporter $ osc mkpac nginx-prometheus-exporter
Add all files to the package,
$ osc add nginx-prometheus-exporter.default nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz nginx-prometheus-exporter.service nginx-prometheus-exporter_0.11.0_linux_arm64.tar.gz nginx-prometheus-exporter.spec
Commit (push) the files and trigger a build,
$ osc commit -m 'My commit'
Use the web UI to get the repository information. For example, this package is available from nginx-prometheus-exporter.
On my Alma Linux 9 (x86_64) and Oracle Linux 9 (aarch64) machines I ran these commands to install nginx-prometheus-exporter,
$ sudo dnf config-manager --add-repo https://download.opensuse.org/repositories/home:aikchar:nginx-prometheus-exporter/Fedora_37/home:aikchar:nginx-prometheus-exporter.repo $ sudo dnf install -y nginx-prometheus-exporter
More Reading
- Create RPM Package
- Build Packages with Openbuild Service
- Fedora Packaging Guidelines - systemd
- How to execute a script at %pre, %post, %preun or %postun stage (spec file) while installing/upgrading an rpm
- Launchpad prometheus-nginx-exporter
- [libvirt] [PATCH] rpm: fix incorrect expansion of %systemd_preun macro
- OBS User Guide
- Packaging and distributing software - Advanced topics
- Packaging Conventions - RPM Macros
- RPM Conditionals
- RPM Guide
- RPM Macros
- RPM SPEC Systemd enable and start
- Systemd packaging guidelines
- What is a spec file