Skip to content

About

A Linux-based application deployment and automated rollback tool built with Bash, demonstrated using a Java HTTP service on Ubuntu.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

19 Commits

Folders and files

Repository files navigation

DeployLatch

A Bash tool for deploying a Java service on Linux and recovering from failed updates.
Operating Systems course project · UBIT, University of Karachi

Demo  ·  Workflow  ·  Run it  ·  Project notes

Deployment demo

The course demonstration ran on Ubuntu 26.04.1 LTS in VMware. Starting from v1, v2 deploys successfully. v3 deliberately returns HTTP 503, triggering a rollback to v2.

Ubuntu terminal showing successful v2 deployment, failed v3 deployment, recovery to v2, active service with healthy status, and SUCCESS and ROLLED_BACK history records.
Click the screenshot to inspect the commands and deployment history at full size.

Text version of the demonstration
Deploying v2
Deployment successful: v2

Deploying v3
Deployment failed: v3
Restored v2

Current: v2
Previous: v1
Service: active
Health: OK

Tux, the Linux mascot

The v3 deployment command returns a non-zero exit status even after successful recovery: the requested update failed, while the old service was restored.

Why I built this

I built DeployLatch for my Operating Systems course to use the Linux and Bash skills from the lab alongside Java backend development. I wanted to work through how an application starts as a service, how an update is checked, and how to recover when something goes wrong.

The result is a small deployment tool for one Java service on one Ubuntu VM. It brings together shell scripting, Linux services, permissions, HTTP checks, and release management.


How it works

Each JAR gets its own release directory. A current symbolic link selects the running release; previous identifies the manual rollback target. systemd runs the application under a dedicated, non-root account.

Install a versioned JAR, switch the active release, restart the service, and check health and release ID. Restore and verify the old release if deployment fails.

The script accepts an update only when /health returns OK and /version matches the requested release ID. If startup or verification fails, it switches back to the old release, restarts it, and checks recovery. A file lock prevents concurrent deployments; outcomes are recorded with UTC timestamps.

Run it

The demonstrated setup builds the JARs on Windows with PowerShell and JDK 25, then runs them on Ubuntu with Java 25, Bash, curl, flock, and systemd. SSH/SCP transfers the files to the VM.

Build and run the course demo

In Windows PowerShell:

git clone https://github.com/codewithmahad/deploylatch.git
cd deploylatch
.\scripts\build-demo.ps1

The build creates demo-app-v1.jar, demo-app-v2.jar, and demo-app-v3.jar in demo-app/dist/. v1 and v2 are healthy; v3 is intentionally unhealthy.

Next, follow the Ubuntu setup guide to transfer the files, install v1, create the service account, and enable the systemd service. The commands below assume that setup is complete.

On Ubuntu, deploy v2, then try the failing v3 release:

sudo bash ~/deploylatch-staging/deploylatch.sh deploy \
  ~/deploylatch-staging/demo-app-v2.jar v2

sudo bash ~/deploylatch-staging/deploylatch.sh deploy \
  ~/deploylatch-staging/demo-app-v3.jar v3

After v3 fails and restores v2, inspect the result:

sudo bash ~/deploylatch-staging/deploylatch.sh status
sudo bash ~/deploylatch-staging/deploylatch.sh history

Each deployment needs a unique release ID. Existing release directories, including failed ones, are retained, so rerunning the same release ID is refused.

Java

The operations guide contains the complete setup, file-transfer commands, manual rollback, and troubleshooting.

Inside the project

The Java app uses the JDK's built-in HTTP server. A release.properties file packaged into each JAR supplies its version and health behavior, so the same source produces all three demo releases.

It binds to the VM's loopback address, 127.0.0.1:8080. GET /health returns HTTP 200 with OK for v1/v2, or HTTP 503 with UNHEALTHY for v3. GET /version returns the release ID. Unknown paths return 404; other methods on these endpoints return 405.

Bash owns the deployment and recovery steps. systemd owns the Java process. Keeping the application small leaves the OS behavior easy to follow.


Project notes

Use deploy, rollback, status, and history to manage releases and inspect results. Updates must pass health and version checks within eight attempts; a failed update returns a non-zero status even if recovery succeeds. The tool covers one local service with brief restart downtime, HTTP-level checks, and no guarantee of recovery after an interrupted deployment.

Project structure and entry points
deploylatch/
├── scripts/
│   ├── build-demo.ps1             # Build the three demo JARs on Windows
│   └── deploylatch.sh             # Deploy, verify, recover, inspect history
├── systemd/
│   └── deploylatch-demo.service   # Run the Java process as deploylatch
├── demo-app/src/main/java/dev/deploylatch/demo/
│   └── DemoServer.java            # Health and version endpoints
├── docs/
│   ├── OPERATIONS.md              # Ubuntu setup and demonstration
│   └── assets/                    # README artwork and source notices
├── .gitattributes
├── .gitignore
└── README.md

Start with the Bash script, the service unit, or the Java application. Generated JARs and classes are excluded from Git.

Commands, release paths, and logs

All actions below run on Ubuntu using sudo bash ~/deploylatch-staging/deploylatch.sh followed by:

Action Result
deploy JAR RELEASE_ID Install and verify a new release; recover on failure
rollback Switch to previous; on success, make the replaced release the new rollback target
status Show current/previous release, service state, and HTTP health
history Show the last 20 deployment records
help Print command usage; sudo is not required for help
Path Purpose
/opt/deploylatch/releases/<id>/app.jar Stored release
/opt/deploylatch/current Active release link
/opt/deploylatch/previous Manual rollback target
/opt/deploylatch/.deploy.lock Deployment lock
/var/log/deploylatch/deployments.log Timestamped deployment outcomes

For Java startup errors or process output:

journalctl -u deploylatch-demo.service -n 40 --no-pager
Verification and failure behavior

Verification makes up to 8 attempts, with a 2-second timeout per HTTP request and a 1-second pause after each unsuccessful attempt. Both the health body and expected version must match. These are fixed values in the script.

The terminal demonstration shows a healthy update and automatic rollback. The table below describes the script's handling of these and other failure cases.

Situation Script behavior
Unreadable JAR, invalid ID, or existing release ID Refuse the deployment before switching the active release
Another command holds the deployment lock Exit instead of running concurrently
New service fails to start or pass verification Restore the old release and verify it
The new deployment fails and no valid old release exists Stop the service, remove current, and record FAILED
Automatic recovery also fails Record ROLLBACK_FAILED and report failure
Manual rollback target fails Restore the original active link, attempt a restart, and report failure

A successful update records SUCCESS; successful automatic recovery records ROLLED_BACK; a successful manual rollback records MANUAL_ROLLBACK. Failed deployments keep a non-zero exit status.

Design choices and boundaries
  • Separate release directories: retain old JARs rather than overwrite the running artifact.
  • Atomic link replacement: prepare a temporary symlink, then rename it over current. This makes the pointer change atomic, not the whole deployment.
  • Version-aware verification: a healthy response alone does not prove the requested release is running.
  • Dedicated service user: deployment commands use sudo; the Java process runs as deploylatch, with NoNewPrivileges=true.
  • Local HTTP service: loopback binding keeps the demonstration inside the VM.

Service restarts cause brief downtime. HTTP checks cover availability and release identity, not complete application correctness. The tool targets one local service, retains releases without automatic cleanup, and does not guarantee recovery from an interrupted deployment or a machine failure. Deployment paths, port, and retry settings are fixed in the source.

Tools and environment
Tool Role
Ubuntu / Linux Processes, files, permissions, and release paths
Bash Deployment control flow, verification, and recovery
Java 25 Demo HTTP service and JAR packaging
systemd Service lifecycle and process logs
curl Local HTTP requests
flock Exclusive deployment lock
PowerShell Windows build script
VMware Ubuntu virtual machine
Git / GitHub Source history
Course context and learning Department of Computer Science, UBIT, University of Karachi

Operating Systems · SE-458
Department of Computer Science, UBIT, University of Karachi.

Built for my fourth-semester Operating Systems course in 2026. I handled the implementation, integration, and Ubuntu demonstration.

The project gave the lab concepts a practical purpose: file permissions protect the releases, symlinks select the active version, exit codes report failures, locking prevents overlapping commands, and systemd manages the process. The Java work connects HTTP responses and JAR packaging to those Linux operations.


Let's connect

I'm Shaikh Mahad Ud Din, @codewithmahad. I build Java backend projects and share what I learn. Working with Java or Linux, or have a project you'd like to build together? I'd be glad to connect.

Follow on GitHub Connect on LinkedIn Visit my portfolio Send me an email

About

A Linux-based application deployment and automated rollback tool built with Bash, demonstrated using a Java HTTP service on Ubuntu.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages