Rémy Schumm blog ingénieur

kassandra: part II: a simple java application behind a reverse proxy with apache httpd

publiziert am 10. 04. 2024 um 17:05

Since 1998, «kassandra» is my experimental WebServer. The goal was to reactivate it as kassandra.schumm.ch on my Rapsberry Pi I got from Matthieu - which is running at home on an old porcellaine dish. Originally, I wanted to run my stuff using k3s, but I found that it was too much for this Raspberry Pi 2. So I decided to do it the old-fashioned way: with apache httpd, by hand, as a small exercise. This is my note to myself how I did it: Part II - the Java Application - behind the Reverse Proxy.

Components Overview

graph LR; Internet-->DNS DNS--A Record-->W[Wingo Router] W--NAT-->Apache L[Let's Entrypt]<--ACME-->W W<--ACME-->Certbot Certbot--Write Cert-->Apache subgraph Raspberry Pi Apache--Reverse Proxy-->Java Certbot Java-->PostgreSQL end

The Main Components are: the Apache2 Web Server that acts both as a WebServer and a ReverseProxy, and the Java Application that does some fun stuff and is hidden behind the ReverseProxy.

In this Part II, I am showing how to run a lightweight Java-Application on the Raspberry - using this apache2 as a reverse proxy and without without using kubernetes as described Part I of this blog post.

Reverse Proxy for Java Application

To configure the Apache as a reverse proxy for a Java Application, I need to add some lines to the kassandra.conf file described in Part I.

Here you can see the example for my App that responds to the URL http://kassandra.schumm.ch/find/... and http://kassandra.schumm.ch/find/info and forwards the requests to the Java Application running on the Raspberry on Port 8084.

    ... 
    RewriteEngine On
    RewriteRule "^/find/(.*)" "http://raspberrypi.local:8084/find/$1" [P]
    RewriteRule "^/find$" "http://raspberrypi.local:8084/find/info" [P]


    ProxyPassReverse "/find/" "http://raspberrypi.local:8080/"
    ...

the [P] flag in the RewriteRule directive tells Apache to proxy the request to the given URL. The ProxyPassReverse directive is used to fix the URLs in the response headers on the way back.

Note: the RewriteRule gives a bit more flexibility than the ProxyPass directive, as it allows to rewrite the URL before it is proxied.

Adittionally, I need to enable the mod_rewrite and mod_proxy_http modules in Apache:

a2enmod rewrite
a2enmod proxy_http

Run the Java Application

Finally, to run the Java Application on the Raspberry, I just copy the Jar-File to the Raspberry and run it within a Systemd Service.

For this, I made the File java_server.service that needs to be copied to /etc/systemd/system/ with sudorights, with the following content:

[Unit]
Description=Schumm Find Java Server Service 
After=network.target

[Service]
Environment="JDBC_DATABASE_URL=jdbc:postgresql://localhost:5432/mydb?sslmode=disable"
Environment="JDBC_DATABASE_USERNAME=mydbuser"
Environment="JDBC_DATABASE_PASSWORD=mydbpw"
Environment="SCHUMM_MAILTO=r@schumm.ch"
Environment="SCHUMM_MAILUSER=r@schumm.ch"
Environment="PORT=8084"
ExecStart=/usr/bin/java -jar /home/pi/javaprod/myapp/myjar.jar
WorkingDirectory=/home/pi/javaprod/myapp
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=my_java_server

[Install]
WantedBy=multi-user.target

You can see some expample Environment Variables that are used in the Java Application, e.g. the Port Number and DB Connection stuff.

To enable the service and start it:

systemctl daemon-reload  
# Reload systemd to read the new service file

systemctl enable my_java_server.service  
# Enable the service to start on boot

systemctl start my_java_server.service  
# Start the service

To Check the status ans logs:

systemctl stop my_java_server.service  
systemctl status my_java_server.service 
sudo journalctl -u my_java_server.service -f 

The Java Service will now run on the Raspberry and expose the port 8084. It will automatically restart if it crashes or the system reboots. The Port will be open to the local network only as we have the Router configured to forward only 80 and 443 to the Raspberry and other ports are closed from the outside internet.

The reverse proxy will now forward the requests from the public Interent to the Java Application and adjust the URLs in the response headers on the way back.

That’s it - the Java Application is running on the Raspberry Pi and exposed to the public internet - exactly it is described in the diagram at the beginning of this blog post.

Not Covered in this Blog Post: Java Build and Deployment

The Java Application itself is not covered in this blog post. It is built by maven using the maven-assembly-plugin and uses the Sparkjava framework. The Application is a simple REST-API with some Server-Rendered GUI that connects to a PostgreSQL Database. The Database is also running on the Raspberry Pi and is not covered in this blog post.

To redeploy the application after a new build, I just copy the new Jar-File to the Raspberry and restart the systemd service. This could be automated with a CI/CD Pipeline or with Ansible, but this is not covered in this blog post.

Hinweis: dieser Blog wiederspiegelt meine persönliche Meinung und hat nichts mit meiner Anstellung als Dozent der zhaw noch mit anderen Anstellungen zu tun.


zurück zum Seitenanfang