10

This is a follow up to my question here. I've set up a home server (just my other laptop running ubuntu and nginx) and I want to serve clojure files.

I am asking help for understanding how this process works. I am sorry at this point I am confused and I think I need to start over. I am asking a new question because I want to use nginx not lein ring server, as suggested in the answer for that question.

First I started a project guestbook with leiningen and I ran lein ring server and I see "Hello World" at localhost:3000. As far as I understand this has nothing to do with nginx!

How does nginx enter in this process? At first I was trying to create a proxy server with nginx and that worked too, but I did not know how serve clojure files with that setup.

This is what I have in my nginx.conf file adapted from this answer:

 upstream ring {
    server 127.0.0.1:3000 fail_timeout=0;
}

server {
    root /home/a/guestbook/resources/public;

    # make site accessible from http://localhost
    server_name localhost;

    location / {
        # first attempt to serve request as file
        try_files $uri $uri/ @ring;
    }

    location @ring {
        proxy_redirect off;
        proxy_buffering off;
        proxy_set_header Host $http_host;
        proxy_pass http://ring;
    }

    location ~ ^(assets|images|javascript|stylesheets|system)/ {
        expires    max;
        add_header Cache-Control public;
    }
}

So I want to use my domain example.com (not localhost); how do I go about doing this?


EDIT

As per @noisesmith's comment I will opt to go with lein uberjar option. As explained here, it appears very easy to create one:

$ lein uberjar
Unpacking clojure-1.1.0-alpha-20091113.120145-2.jar
Unpacking clojure-contrib-1.0-20091114.050149-13.jar
Compiling helloworld
      [jar] Building jar: helloworld.jar
$ java -jar helloworld.jar 
Hello world!

Can you also direct me to the right documentation about how I can use this uberjar with nginx?

Community
  • 1
  • 1
Zeynel
  • 13,145
  • 31
  • 100
  • 145

2 Answers2

11

Please try Nginx-Clojure module. You can run clojure Ring handlers with Nginx without any Java Web Server, eg. Jetty.

xfeep
  • 1,091
  • 11
  • 12
  • What is nginx-clojure exactly? Is it a dependency in my Clojure project that exposes some FFI for nginx, or is it a module for nginx that knows how to talk to my running Uberjar? The documentation does not explain why I need this. – Petrus Theron May 28 '20 at 08:45
8

For starters, don't use lein to run things in production. You can use lein uberjar to create a jar file with all your deps ready to run, and java -jar to run the app from the resulting jar. There is also the option of running lein ring uberwar to create a war archive to be run inside tomcat, which provides some other conveniences (like log rotation and integration with /etc/init.d as a service etc. on most Linux systems).

nginx sits in front of your app, on port 80. It will serve up the content by proxying your app. This is useful because nginx has many capabilities (especially regarding security) that you then don't need to implement in your own app, including optional integration with https and selinux integration. Using nginx in front of your app also prevents you from needing to run java as root (typically only the root user can use port 80). Furthermore you can let nginx serve static assets directly, rather than having to serve them from your app.

noisesmith
  • 20,076
  • 2
  • 41
  • 49
  • Ok, thanks. This gives me a better understanding. But how do I put these in practice? For instance, I found this document https://github.com/ddellacosta/Clojure-under-Jetty-and-Apache#rationale-and-other-approaches where the author lists many different approaches to deploy clojure applications including his own solution (for Apache). I thought that there would be one standard way to deploy. I am also considering switching to Python. As a beginner do you think I would have an easier time to deploy Python? Thanks. – Zeynel Dec 18 '13 at 19:43
  • 1
    The simplest option is to use `lein ring uberwar` and upload the result to an aws beanstalk. Second easiest is to use `lein uberjar` and upload the result to a Linux server and run it via `java -jar`. Using lein on production does not simplify things, because it requires a separate dev toolchain on production, and can lead to unpredictability because dependency resolution and packaging is not happening on your dev machine. – noisesmith Dec 18 '13 at 19:53
  • 1
    Regarding pyton, I would not trust python directly talking to the web any more than I would trust clojure talking directly to the web, and best practice would be to use nginx or an equivalent in front of it in that case as well. Making an uberjar results in a single file that runs your app, with no other configuration or installation needed beyond the jvm. Python does not offer anything simpler. – noisesmith Dec 18 '13 at 19:54
  • Great, thanks. I guess I will opt for using lein uberjar because I want to run it on my own home server (just for learning purposes). It seems easy to create lein uberjar and run it with java -jar on my Linux server. Now can you point me in the right direction what do I do when I create the uberjar? How do I run it with nginx? I edited my question also. – Zeynel Dec 18 '13 at 20:02
  • Tell nginx to proxy in front of the port ring is serving on. Optionally you can also have it look for static assets under a defined "public" directory on disk before forwarding the request to your ring app. – noisesmith Dec 18 '13 at 20:05
  • I tried to use nginx as proxy as explained here http://nginx.org/en/docs/beginners_guide.html#proxy but I could not make it work because I cannot figure out the settings. Where will my uberjar be? In the project directory? Do I need to run ring on my machine? An example would be helpful but I could not find it yet. – Zeynel Dec 18 '13 at 20:17
  • This document I referred above https://github.com/ddellacosta/Clojure-under-Jetty-and-Apache#setting-up-jetty-with-apache-httpd actually has this done for Apache; so instead of nginx I will use Apache and that may work for me at this stage.... – Zeynel Dec 18 '13 at 20:26
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43462/discussion-between-zeynel-and-noisesmith) – Zeynel Dec 18 '13 at 21:56
  • noisesmith wrote: "Second easiest is to use `lein uberjar` and upload the result to a Linux server and run it via `java -jar`." How do I upload this to the linux server? Application is on my Mac and linux server is on another laptop. If I understand correctly, I will have to create the lein project in the server and program remotely through ssh? Is this correct? Or what is the correct way of doing this? – Zeynel Dec 25 '13 at 11:48
  • No, the point of an uberjar is that it contains all the dependencies of your project. All you need on the other machine is the jvm, no need for lein or clojure to be installed. – noisesmith Dec 25 '13 at 13:12