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.

    Source