The guidelines for packaging nodejs apps for the Fedora EPEL repo can be found here. They are a good reference when packaging your own nodejs apps.
You don't mention what version or which distribution you are using, but I am going to assume it is a recent distribtion, so the service you want to start will be running under systemd. The Fedora systemd packaging guidlines can be found here.
I am also assuming you are using github to manage the code and it is a pure JS application.
For nodejs module/app that has no dependencies or only has dependencies on nodejs modules already packaged in the EPEL the following SPEC file (saved as SPECS/nodejs-myapp.spec) will work.
%define debug_package %{nil}
#
# automatically generate requires and provides from package.json
#
%{?nodejs_find_provides_and_requires}
#
# filter out any false provides created due to dependencies with native components
#
%{?nodejs_default_filter}
#
# name of zip file containing source without .zip extension
#
%define modname myapp
Summary: A nodejs app with a systemd daemon
Name: nodejs-%{modname}
Group: Applications/Tools
Version: 0.1
Release: 1
License: Unlicense
URL: https://github.com/myuser/myapp
Source0: %{modname}-%{version}.zip
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch: noarch
ExclusiveArch: %{nodejs_arches} noarch
BuildRequires: nodejs-packaging
BuildRequires: systemd
%description
A nodejs app that installs as a systemd service
%prep
%setup -q -n %{modname}-%{version}
%build
%{__rm} -f .gitignore
#
# Fedora guidlines do not allow bundled modules
# use nodejs_symlink_deps in the install section to generate
# links based on package.json contents
#
%{__rm} -rf node_modules
%install
rm -rf $RPM_BUILD_ROOT
#
# copy in the module source
#
%{__install} -d $RPM_BUILD_ROOT%{nodejs_sitelib}
%{__cp} -r $RPM_BUILD_DIR/%{modname}-%{version} $RPM_BUILD_ROOT%{nodejs_sitelib}/%{modname}
#
# link the daemon binaries into sbindir
#
%{__install} -d $RPM_BUILD_ROOT%{_sbindir}
%{__ln_s} %{nodejs_sitelib}/%{modname}/bin/myappd $RPM_BUILD_ROOT%{_sbindir}/myappd
#
# link in any dependent nodejs modules referenced in package.json
#
%nodejs_symlink_deps
#
# documents will be handled by %doc, so remove them from buildroot
#
%{__rm} -rf $RPM_BUILD_ROOT%{nodejs_sitelib}/%{modname}{CHANGELOG.md,LICENSE.md,README.md,docs}
#
# Create a systemd unit file
#
cat << __EOF > $RPM_BUILD_ROOT%{_unitdir}/myappd.service
[Unit]
Description=MyApp provides the best API
Documentation=man:myapp.service(8)
[Service]
Type=simple
ExecStart=/usr/sbin/myappd
[Install]
WantedBy=multi-user.target
__EOF
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc CHANGELOG.md LICENSE.md README.md docs
%{nodejs_sitelib}/%{modname}
%{_sbindir}/myappd
%{_unitdir}/myappd.service
%changelog
* Sun Mar 22 2015 BitByteDog
- Initial spec file for myapp
This spec file will also cope with nodejs modules that have dependencies that are already packaged as part of the EPEL. The auto requires/provides feature of RPM uses the package.json file in the module to create the necessary requires dependencies in the final RPM package.
The source zip should be downloaded from github into the SOURCES directory using a command such as:
wget -O SOURCES/myapp-0.1.zip https://github.com/myuser/myapp/archive/v0.1.zip
The RPM is built with the command:
rpmbuild -ba SPECS/nodejs-myapp.spec
The systemd unit file created is very simple, read the link provided plus the associated systemd documentation to customize to your requirements. You will need to enable and start the service with the following commands:
systemctl enable myappd.service
systemctl start myappd.service
It will automatically start after that.
If you want to include bundled modules in your JS app, it can be done using npm.
First add the tags:
BuildRequires: npm
AutoReq: no
AutoProv: no
To suppress auto requires/provides generation. Then remove the line
%{__rm} -rf node_modules
from the %build section. Also change the line
%nodejs_symlink_deps
in the %install for the lines
#
# npm will bundle in all dependent modules from the npm registry
# (bundling is OK for private packages but not for EPEL packages)
#
npm -g -q --production --prefix="${RPM_BUILD_ROOT}%{_prefix}" install
All modules bundled in the app and all dependencies listed in package.json will be bundled into your app, making it a standalone app.
Explanation of npm usage in the above command
- npm install is executed in the package/application directory and works on the package contained in that directory.
- -g install the package in the current working directory as a global package
- -q print warnings and errors only
- --production don't copy devDependencies
- --prefix= install in prefix directory
The effect is to copy the nodejs app in the local directory to ${RPM_BUILD_ROOT}%{_prefix} ready for packaging.