How to Deploy Clojure Web Application on Debian 9

Clojure is a modern general-purpose programming language for the JVM that focuses on concurrent programming found in operating systems. Clojure enables you to make use of the existing JVM infrastructure, including tools, libraries and application servers.

This guide will walk through the process of deploying a simple web application in Clojure using supervisor and Nginx.

Requirements

  • A server running Ubuntu 16.04.
  • A root-password setup on your server.

Getting Started

Before starting, it is recommended to update your package to the latest version with the following command:

apt-get update -y
apt-get upgrade -y

Once all the packages are updated, restart your server to apply all these changes.

reboot

Next, install some required packages like, git, curl, Java to your server with the following command:

apt-get install git curl openjdk-8-jre-headless -y

Once all the required packages are installed, you can verify the version of the JAVA with the following command:

java -version

You should see the JAVA version in the following output

openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-8u131-b11-2-b11)
OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)

Once you are done, you can proceed to install Nginx and Supervisor.

Install Nginx and Supervisor

By default, Nginx and Supervisor is available in Ubuntu 16.04 repository. You can install them by just running the following command:

apt-get install nginx supervisor -y

Once installation is complete, start Nginx and Supervisor service and enable them to start on boot time with the following command:

systemctl start nginx
systemctl start supervisor
systemctl enable nginx
systemctl enable supervisor

Once you are done, you can proceed to the next step.

Download Clojure App

First, you will need to download the sample Clojure project from the git repository. You can easily download it with the git clone command line utility as shown below:

git clone https://github.com/do-community/do-clojure-web.git

Next step is to compile and run this Clojure project using the Leiningen. Leiningen is a dependency management and build automation tool that can be used to compile Clojure app. You can download it with the curl command as shown below:

curl https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein -o /usr/bin/lein

Next, give the proper permissions to the downloaded tool with the following command:

chmod 755 /usr/bin/lein

Now, run the following command to compile the Closure project:

cd do-clojure-web
lein uberjar

You should see the following output:

WARNING: You're currently running as root; probably by accident.
Press control-C to abort or Enter to continue as root.
Set LEIN_ROOT to disable this warning.

Downloading Leiningen to /root/.lein/self-installs/leiningen-2.7.1-standalone.jar now...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   618    0   618    0     0    309      0 --:--:--  0:00:02 --:--:--   207
100 14.6M  100 14.6M    0     0   326k      0  0:00:46  0:00:46 --:--:--  279k
Retrieving lein-ring/lein-ring/0.8.13/lein-ring-0.8.13.pom from clojars
Retrieving org/clojure/clojure/1.2.1/clojure-1.2.1.pom from central
Retrieving org/clojure/data.xml/0.0.6/data.xml-0.0.6.pom from central
Retrieving org/clojure/pom.contrib/0.0.25/pom.contrib-0.0.25.pom from central
Retrieving org/sonatype/oss/oss-parent/5/oss-parent-5.pom from central
Retrieving org/clojure/clojure/1.3.0/clojure-1.3.0.pom from central
Retrieving leinjacker/leinjacker/0.4.1/leinjacker-0.4.1.pom from clojars
Retrieving org/clojure/core.contracts/0.0.1/core.contracts-0.0.1.pom from central
Retrieving org/clojure/pom.contrib/0.0.26/pom.contrib-0.0.26.pom from central
Retrieving org/clojure/core.unify/0.5.3/core.unify-0.5.3.pom from central
Retrieving org/clojure/clojure/1.4.0/clojure-1.4.0.pom from central
Retrieving org/clojure/clojure/1.2.1/clojure-1.2.1.jar from central
Retrieving org/clojure/core.contracts/0.0.1/core.contracts-0.0.1.jar from central
Retrieving org/clojure/data.xml/0.0.6/data.xml-0.0.6.jar from central
Retrieving org/clojure/core.unify/0.5.3/core.unify-0.5.3.jar from central
Retrieving org/clojure/clojure/1.2.1/clojure-1.2.1.jar from clojars

Once the Clojure project is compiled, you can proceed to the next step.

Setup Clojure Web App Environment

Next, you will need to create a directory structure for the Clojure web application. You can do this with the following command:

mkdir -p /var/www/html/do-clojure-web/app/db

Next, copy Clojure application files into the above directory:

cp /root/do-clojure-web/target/do-clojure-web-0.1.0-standalone.jar /var/www/html/do-clojure-web/app/

Next, give proper permissions to the Clojure app directory with the following command:

chown -R www-data:www-data /var/www/html/do-clojure-web/

Next, create a symbolink of clojure web application with the following command:

cd /var/www/html/do-clojure-web/app/
ln -s do-clojure-web-0.1.0-standalone.jar do-clojure-web.jar

Clojure web app is now ready for use. You can check whether it is running or not with the following command:

java -jar do-clojure-web.jar

If everything is fine, you should see the following output:

2017-10-01 10:30:48.349:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
2017-10-01 10:30:48.590:INFO:oejs.AbstractConnector:Started [email protected]:5000

Configure Nginx and Supervisor

Next, you will need to configure Supervisor to manage Clojure applications as a service. You can do this by creating do-clojure-web.conf file under Supervisor config directory as shown below:

nano /etc/supervisor/conf.d/do-clojure-web.conf

Add the following lines:

[program:do-clojure-web]
command=/usr/bin/java -jar do-clojure-web.jar
directory=/var/www/html/do-clojure-web/app
user=www-data
autostart=true
autorestart=true
startretries=3
redirect_stderr=true
stdout_logfile=/var/log/log/do-clojure-web.app.log

Save and close the file when you are finished.

Next, you will also need to configure Nginx to use as a reverse proxy. Because Clojure web application accepts connections only from the localhost. You can access it from remote location using Nginx. To do so, you will need to configure Nginx default configuration file:

nano /etc/nginx/sites-available/default

Change the file as shown below:

upstream http_backend {
    server 127.0.0.1:5000;
    keepalive 32;
}
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;

        server_name _;

    location / {
        proxy_pass http://http_backend;

        proxy_http_version 1.1;
        proxy_set_header Connection "";

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        access_log /var/log/do-clojure-web.access.log;
        error_log /var/log/do-clojure-web.error.log;
    }
}

Save and close the file when you are finished, then restart Nginx and Supervisor service to apply all the changes:

systemctl restart nginx
systemctl restart supervisor

You can verify the status of both Nginx and Supervisor with the following command:

systemctl status supervisor

If everything is fine, you should see the following output:

? supervisor.service - Supervisor process control system for UNIX
   Loaded: loaded (/lib/systemd/system/supervisor.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2017-10-02 10:19:32 EDT; 22min ago
     Docs: http://supervisord.org
 Main PID: 397 (supervisord)
    Tasks: 19 (limit: 4915)
   CGroup: /system.slice/supervisor.service
           ??397 /usr/bin/python /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
           ??446 /usr/bin/java -jar do-clojure-web.jar

Oct 02 10:19:32 debian systemd[1]: Started Supervisor process control system for UNIX.
Oct 02 10:19:39 debian supervisord[397]: 2017-10-02 10:19:39,656 CRIT Supervisor running as root (no user in config file)
Oct 02 10:19:39 debian supervisord[397]: 2017-10-02 10:19:39,665 INFO Included extra file "/etc/supervisor/conf.d/do-clojure-web.conf" during p
Oct 02 10:19:39 debian supervisord[397]: 2017-10-02 10:19:39,821 INFO RPC interface 'supervisor' initialized
Oct 02 10:19:39 debian supervisord[397]: 2017-10-02 10:19:39,823 CRIT Server 'unix_http_server' running without any HTTP authentication checkin
Oct 02 10:19:39 debian supervisord[397]: 2017-10-02 10:19:39,825 INFO supervisord started with pid 397
Oct 02 10:19:40 debian supervisord[397]: 2017-10-02 10:19:40,890 INFO spawned: 'do-clojure-web' with pid 446
Oct 02 10:19:41 debian supervisord[397]: 2017-10-02 10:19:41,893 INFO success: do-clojure-web entered RUNNING state, process has stayed up for 
systemctl status nginx

Output:

? nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2017-10-02 10:19:35 EDT; 26min ago
     Docs: man:nginx(8)
  Process: 425 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 401 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 427 (nginx)
    Tasks: 2 (limit: 4915)
   CGroup: /system.slice/nginx.service
           ??427 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ??429 nginx: worker process

Oct 02 10:19:32 debian systemd[1]: Starting A high performance web server and a reverse proxy server...
Oct 02 10:19:35 debian systemd[1]: nginx.service: Failed to read PID from file /run/nginx.pid: Invalid argument
Oct 02 10:19:35 debian systemd[1]: Started A high performance web server and a reverse proxy server.

Access Clojure Web App

Once everything is configured properly, it's time to access the Clojure web application through a web browser.

Open your web browser and type the URL http://your-ip-address, you will be redirected to the Clojure web app home page as shown below:

Clojure app start page

Now, click on Add Location button, you should see the following image:

Form file

Here, provide the values in x value and the y value field then click on the submit location button. You can now view your submitted locations by clicking on the View All Locations button. You should see the following image:

Result page

Conclusion

In the above article, we learned how to deploy Clojure web application using Supervisor and lein. We also learned how to a access Clojure web application from remote location by setting up Nginx as a reverse proxy server. I hope you can now easily deploy your custom application using Clojure, Supervisor, and lein. Feel free to ask anything if you have any questions.

Share this page:

0 Comment(s)