As of December 2, 2022, there were no rpm packages for [NGINX Prometheus Exporter](https://github.com/nginxinc/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](https://openbuildservice.org/) (OBS) made it available to others. [TOC] # 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. 1. Download the [latest release](https://github.com/nginxinc/nginx-prometheus-exporter/releases) of NGINX Prometheus Exporter. I chose amd64 and arm64 because those are the only ones I was interested in. 2. Create a spec file. 3. Create a systemd service file. 4. Create a default configuration file. You will find all these files in my OBS subproject: [nginx-prometheus-exporter](https://build.opensuse.org/package/show/home:aikchar:nginx-prometheus-exporter/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. - [prometheus-node_exporter.service](https://build.opensuse.org/package/view_file/systemsmanagement:Uyuni:Stable:SLE15-Uyuni-Client-Tools/golang-github-prometheus-node_exporter/prometheus-node_exporter.service?expand=1) - [prometheus-nginx-exporter_0.5.0+ds-2.debian.tar.xz](https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/prometheus-nginx-exporter/0.5.0+ds-2/prometheus-nginx-exporter_0.5.0+ds-2.debian.tar.xz) ### 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}`](https://stackoverflow.com/a/49889396/4196049), 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. - [prometheus-node_exporter.service](https://build.opensuse.org/package/view_file/systemsmanagement:Uyuni:Stable:SLE15-Uyuni-Client-Tools/golang-github-prometheus-node_exporter/prometheus-node_exporter.service?expand=1) - [prometheus-nginx-exporter_0.5.0+ds-2.debian.tar.xz](https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/prometheus-nginx-exporter/0.5.0+ds-2/prometheus-nginx-exporter_0.5.0+ds-2.debian.tar.xz) ## 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](https://openbuildservice.org/help/manuals/obs-user-guide/art.obs.bg.html) (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`](https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.osc.html). 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](https://en.opensuse.org/openSUSE:Build_Service_supported_build_targets)). Use [API docs](https://build.opensuse.org/apidocs-new/) for more information. # https://build.opensuse.org/projects/home:aikchar:nginx-prometheus-exporter/meta nginx-prometheus-exporter NGINX Prometheus exporter makes it possible to monitor NGINX or NGINX Plus using Prometheus. x86_64 aarch64 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](https://software.opensuse.org//download.html?project=home%3Aaikchar%3Anginx-prometheus-exporter&package=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](https://software.opensuse.org//download.html?project=home%3Aaikchar%3Anginx-prometheus-exporter&package=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](https://www.redhat.com/sysadmin/create-rpm-package) - [Build Packages with Openbuild Service](https://www.sidorenko.io/post/2016/05/build-packages-with-openbuild-service/) - [Fedora Packaging Guidelines - systemd](https://docs.fedoraproject.org/en-US/packaging-guidelines/Systemd/) - [How to execute a script at %pre, %post, %preun or %postun stage (spec file) while installing/upgrading an rpm](https://www.golinuxhub.com/2018/05/how-to-execute-script-at-pre-post-preun-postun-spec-file-rpm/) - [Launchpad prometheus-nginx-exporter](https://launchpad.net/ubuntu/+source/prometheus-nginx-exporter/0.5.0+ds-2) - [[libvirt] [PATCH] rpm: fix incorrect expansion of %systemd_preun macro](https://listman.redhat.com/archives/libvir-list/2018-March/161108.html) - [OBS User Guide](https://openbuildservice.org/help/manuals/obs-user-guide/art.obs.bg.html) - [Packaging and distributing software - Advanced topics](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/packaging_and_distributing_software/advanced-topics) - [Packaging Conventions - RPM Macros](https://en.opensuse.org/openSUSE:Packaging_Conventions_RPM_Macros) - [RPM Conditionals](http://ftp.rpm.org/max-rpm/s1-rpm-inside-conditionals.html) - [RPM Guide](https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html-single/RPM_Guide/index.html#id366540) - [RPM Macros](https://docs.fedoraproject.org/en-US/packaging-guidelines/RPMMacros/) - [RPM SPEC Systemd enable and start](https://stackoverflow.com/questions/55378760/rpm-spec-systemd-enable-and-start) - [Systemd packaging guidelines](https://en.opensuse.org/openSUSE:Systemd_packaging_guidelines) - [What is a spec file](https://rpm-packaging-guide.github.io/#what-is-a-spec-file)