Building Debian Packages for Java Applications with jdeb
Distributing Java applications in enterprise and server environments often involves more than simply shipping a JAR file. Production deployment environments generally require native OS packages that work seamlessly with system utilities, support versioned upgrades, resolve dependencies automatically, and adhere to filesystem hierarchy standards. On Debian-based systems (Debian, Ubuntu, Linux Mint, etc.), this means providing .deb packages.
jdeb is a build tool that bridges the gap between Java build systems and Debian packaging. It allows us to produce .deb packages directly from Maven or Ant, without writing low-level Debian control files by hand. This article walks through how jdeb works, how to integrate it into Java builds, and how to structure a Debian package for a Java application.
1. What is jdeb?
jdeb is a Java-based packaging utility that generates Debian .deb archives directly from Java builds, with native integration into Maven and Ant. It supports detailed packaging configuration, including file mappings, permissions and ownership, pre- and post-installation scripts, system user and group creation, and dependency and metadata definitions.
Rather than maintaining a separate Debian packaging project, we specify how build artifacts should be installed on the target system, and jdeb assembles the complete Debian package automatically as part of the build process.
2. Using jdeb with Maven
With Maven, jdeb integrates into the standard build lifecycle and generates the .deb package during the package phase alongside the executable JAR. Packaging configuration, versioning, and installation paths are defined within the project, making Debian packaging a consistent part of the build and CI pipeline.
Configure the jdeb plugin in your pom.xml to integrate Debian packaging into the Maven build lifecycle.
<plugin>
<artifactId>jdeb</artifactId>
<groupId>org.vafer</groupId>
<version>1.14</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jdeb</goal>
</goals>
<configuration>
<compression>gzip</compression>
<controlDir>${basedir}/src/main/resources/deb/control</controlDir>
<dataSet>
<data>
<src>${project.build.directory}/${project.build.finalName}.jar</src>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>/opt/${project.artifactId}</prefix>
</mapper>
</data>
<data>
<src>src/main/resources/${project.artifactId}</src>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>/usr/bin</prefix>
<filemode>755</filemode>
</mapper>
</data>
<data>
<type>template</type>
<paths>
<path>/var/log/${project.artifactId}</path>
</paths>
</data>
<data>
<type>link</type>
<linkName>/opt/${project.artifactId}/current</linkName>
<linkTarget>/opt/${project.artifactId}/${project.version}</linkTarget>
<symlink>true</symlink>
</data>
</dataSet>
</configuration>
</execution>
</executions>
</plugin>
This configuration adds the jdeb plugin to the Maven build and binds it to the package phase, so a Debian .deb file is generated automatically after the JAR is built. The plugin uses gzip compression and reads Debian control metadata from src/main/resources/deb/control, which contains package information and optional install scripts.
The <dataSet> section defines how files are installed on the target system. The built JAR is placed under /opt/<artifactId>, while a launcher script from src/main/resources/<artifactId> is installed into /usr/bin with executable permissions (755) so the application can be started from the command line.
Debian Control Files
Debian control files define the package’s metadata, dependencies, and installation behaviour. jdeb reads these files during the build to populate the .deb package with the required control information and lifecycle scripts.
Create this directory:
src/main/resources/deb/control/control
Example: src/main/resources/deb/control/control
Package: simple-java-app Version: 1.0 Section: utils Priority: optional Architecture: all Depends: openjdk-17-jre-headless Maintainer: JavaCodeGeeks Team <dev@javacodegeeks.com> Description: Simple Java application packaged with jdeb
Startup Script
A small wrapper script is used to launch the application with the correct JAR path and to forward any command-line arguments, allowing the app to be executed like a standard system command. Create the directory:
src/main/resources/simple-java-app
Example: src/main/resources/simple-java-app
#!/bin/sh java -jar /opt/simple-cal/simple-java-app-1.0.jar "$@"
3. Build the Debian Package
mvn clean package
When the build completes successfully, Maven produces the Debian package and reports its location in the build output, confirming that the .deb artifact has been created.
Example output:
[INFO] Building conffiles [INFO] Skipping 'conffiles' generation. No entries defined in maven/pom or ant/build.xml. [INFO] Adding control: control [INFO] Adding control: md5sums [INFO] Creating changes file: /Users/omozegieaziegbe/NetBeansProjects/simple-java-app/target/simple-java-app_1.0_all.changes [INFO] Attaching created debian package /Users/omozegieaziegbe/NetBeansProjects/simple-java-app/target/simple-java-app_1.0_all.deb [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
This log indicates that jdeb has assembled the package and written the final .deb file to the target directory, ready for installation or distribution.
Install and Run
Once the package is built, it can be installed using standard Debian package tools, after which the application is available as a system command.
Install locally:
sudo dpkg -i simple-java-app_1.0_all.deb
Run:
simple-java-app
If your project is built with Gradle rather than Maven, the ospackage-plugin is a strong alternative worth considering. It provides native support for generating OS-level packages directly from Gradle builds and integrates well with typical CI/CD workflows, making it a practical option for teams standardizing on Gradle-based packaging and deployment pipelines.
4. Conclusion
In this article, we explored how to build Debian .deb packages directly from Java projects using jdeb, integrating OS-level packaging into the standard Maven build lifecycle. By mapping build artifacts to Linux filesystem locations, defining control metadata, and automating package creation, jdeb enables consistent, repeatable, and CI-friendly distribution of Java applications on Debian-based systems.
5. Download the Source Code
This article explored how to build Debian deb packages for Java applications using jdeb.
You can download the full source code of this example here: Java debian deb packages jdeb

