ring: specifying a port (80 for production) - clojure

Based on some apprentice-level googling I've found that in project.clj
:ring {:handler pach.handler/app
:port 4004}
Will work fine, but trying to set the default port to 80 does not seem to play nicely.
How would I set this value for a production server?

Related

Connect Cider to Luminus +CLJS Figwheel repl

I've had pretty simple use of Cider REPL in the past; within a project's clj file I use cider-jack-in and I'm good to go (assuming the following in my .lein/profiles.clj
;; ~/.lein/profiles.clj
{:user {:plugins [[lein-localrepo "0.5.2"]
[cider/cider-nrepl "0.10.0-SNAPSHOT"]]
:dependencies [[org.clojure/tools.nrepl "0.2.7"]]
}}
Now out of the box I do:
<user> Clojure/ 17:44$ lein new luminus wants-cider +cljs
Generating a Luminus project.
<user> Clojure/ 17:45$ cd wants-cider/
<user> wants-cider/ 17:45$ lein run
15-Sep-17 17:45:59 user-linuxbox INFO [wants-cider.core] - nREPL server started on port 7000
15-Sep-17 17:45:59 user-linuxbox INFO [wants-cider.handler] -
-=[wants-cider started successfully using the development profile]=-
17:45:59.789 INFO [org.projectodd.wunderboss.web.Web] (main) Registered web context /
15-Sep-17 17:45:59 user-linuxbox INFO [wants-cider.core] - server started on port: 3000
# new shell
<user> wants-cider/ 17:50$ lein figwheel
Figwheel: Starting server at http://localhost:3449
Focusing on build ids: app
Compiling "resources/public/js/app.js" from ["src-cljs" "env/dev/cljs"]...
Successfully compiled "resources/public/js/app.js" in 5.757 seconds.
Started Figwheel autobuilder
WARNING: unable to load "cemerick.piggieback/wrap-cljs-repl" middleware
Launching ClojureScript REPL for build: app
# ... insructions ...
Prompt will show when figwheel connects to your application
To quit, type: :cljs/quit
cljs.user=>
From here, how can I connect my Cider REPL?
You must have figwheel nrepl options to be specified, in :profiles :dev section of project.clj:
:profiles {:dev {
;; ....
:figwheel {:nrepl-port 7888 }
Then connect to nrepl from CIDER:
C-c M-c <or> M-x cider-connect
;; enter figwheel host, port, in this case -- localhost, 7888
;; then, in appeared REPL buffer:
user> (use 'figwheel-sidecar.repl-api)
user> (cljs-repl)
cljs.user=>
info:
https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl

Failed to find a usable hardware address from the network interfaces

I'm getting the following warning when running Aleph (which uses Netty) as a websever inside a Docker container:
WARNING: Failed to find a usable hardware address from the network interfaces; using random bytes: 75:62:7f:9b:c6:52:63:4b
I'm starting the server using:
(defn -main [& args]
(http/start-server app {:port 3000}))
And I've also tried:
(defn -main [& args]
(http/start-server app {:socket-address (java.net.InetSocketAddress. "0.0.0.0" 3000)}))
but still I get the same warning.
The warning only happens inside a docker container. I can run the server in my host without the warning. I also won't get the warning if when I run the container I use docker run --net host webserver.
The really weird thing is, despite the warning everything looks to be running fine. The correct ports are bound and the server is running correctly. Does anyone have any idea why I get this warning?

How to set ring port based on profile

I have a clojure ring project and I want to be able to set the port number based on the profile. Currently I have the following snippet from project.clj
:plugins [[lein-ring "0.8.13"]]
:ring {:handler project.handler/webServer
:init project.init/initialize
:port 80}
:profiles {:dev {:jvm-opts ["-Dproperty-file=dev.properties"]}
:ci {:jvm-opts ["-Dproperty-file=ci.properties"]}
:uberjar {:aot :all}})
What I would like to do is to set the port to 8080 for development environments and then port 80 for the production environment. I would run on port 80 all the time but that requires root privilege and not something I want to do for a dev run. I have tried (blindly) to put the ring port into the uberjar profile but that didn't work. I also tried to use the environ project to set the ring port based on the environment variable but that didn't work either.
I am open to a solution that passes command line arguments to the java -jar [...]-standalone.jar command but I am stuck on how to get any approach to work.
You don't need environ. Use it when you need to access configuration variables in the source code. In project.clj you could directly do this:
:profiles {:dev {:jvm-opts ["-Dproperty-file=dev.properties"]
:ring {:port 8080}}
:ci {:jvm-opts ["-Dproperty-file=ci.properties"]
:ring {:port 80}}
:uberjar {:aot :all
:ring {:port 80}}})
I have tested this (without jvm-opts and port 8081 instead of 80) and it works.
Alternative: if they are different machines, you could use the OS's environment variables:
:ring {:handler project.handler/webServer
:init project.init/initialize
:port ~(System/getenv "RING_PORT")}
And then set RING_PORT to 8080 in your dev machine and 80 on the production machine.
$ export RING_PORT=80
It seems the alternative version doesn't work as stated. I get the exception "java.lang.String cannot be cast to java.lang.Number". Apparently we have to explicitly parse the value environment variable as integer, but then we also have to catch possible errors. Code that works for me
:port ~(try
(Integer/valueOf
(System/getenv "RING_PORT"))
(catch Exception e 3000))

Running Noir web framework at port 80

[Meta notes: the following question is not answered, but the problem that the question is involved in is considered solved. Thanks to #georgek]
I am experimenting Noir web framework on a home machine running Ubuntu linux. I followed the "Getting started" part from the Noir site and got the demo server up and running. But that example was running at the testing port 8080. I wanted it to run at the default http port (port 80), so I edited the "8080" part of the clojure file my-website/src/my_website/server.clj:
(ns my-website.server
(:require [noir.server :as server]))
(server/load-views "src/my_website/views/")
(defn -main [& m]
(let [mode (keyword (or (first m) :dev))
port (Integer. (get (System/getenv) "PORT" "80"))] ; <- I changed "8080" to "80"
(server/start port {:mode mode
:ns 'my-website})))
And tried to run the demo again, but I got the following:
$ lein run
Starting server...
2011-11-27 13:26:27.183:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2011-11-27 13:26:27.189:INFO::jetty-6.1.25
2011-11-27 13:26:27.242:WARN::failed SocketConnector#0.0.0.0:80: java.net.BindException: Permission denied
2011-11-27 13:26:27.242:WARN::failed Server#111ded2: java.net.BindException: Permission denied
Exception in thread "main" java.lang.RuntimeException: java.net.BindException: Permission denied
at clojure.lang.Util.runtimeException(Util.java:165)
at clojure.lang.Compiler.eval(Compiler.java:6476)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$eval_opt.invoke(main.clj:296)
...
...
I have root access to the machine, I just don't know where to start to solve this problem. Could anybody help?
What I have tried:
I tried to run lein run as su, but it didn't work either.
I stopped the Apache2 server for releasing port 80 (Is this the right way to do it?):
$ sudo /etc/init.d/apache2 stop
Still doesn't work.
I did it all over again on a macbook, it worked for port 80 ("sudo" is needed). Don't know why it doesn't work for Ubuntu.
The solution that I took
A practical solution to the problem (not an answer to the question):
I followed this web page, and used 8080 port as a service, and then configured the "httpd.conf" file of the Apache2 server to let port 8080 listen all the requests to port 80. This solution is provided by #georgek .
[I am sorry if this post is not valuable to some people, I'm new in this field. Thank you again everyone!]
An alternative solution
#ivant provides an alternative solution which also works!
Only root can use ports lower than 1024. If you say you tried running it as root or with sudo and still didn't work then most probably port 80 is already in use by some other application.
LE: This should show you which process is using the port 80
ps -eo pid,user,group,args,etime,lstart | grep `lsof -i :80 | grep LISTEN | head -1 | cut -f4 -d' '`
I would recommend running Noir as a non-root user on 8080 and using a rule to forward that domain and port to your Apache running on 80. Is there another reason you don't want to do that?
There is also privbind and authbind, which grant the privilege to bind to low ports (< 1024) to non-root apps. They are both available in ubuntu and may be a viable alternative to apache, especially while developing. To install (both) use the following:
$ sudo apt-get install privbind authbind
and check the man pages for usage instructions.
P.S. I know I'm a bit late for the party, but thought that these might still be useful.

How to make jetty server (ring.adapter.jetty) accessible from external hosts

I'm trying to run a web server using the following invocation
(run-jetty #'handler {:host "hostname" :port 8080})
This starts a server which I can access from the same host, but not externally. I am doing this on an EC2 instance and I use the internal IP of that machine as the "hostname", port 8080 is open for external access. I also tried using "0.0.0.0" as the hostname, but that resulted in the same behavior.
I'm using a slightly outdated version of ring-jetty-adapter (0.2.5) but I can't change that.
Any help is greatly appreciated!
to get access and keep it private you can run
ssh -L 8080:localhost:8080 your.ec2.instance
then open a browser to http://localhost:8080/myapp/
for your original question:
perhaps using the external ip or host name as "hostname" may help?
Just don't specify the :host option at all; Jetty seems to listen on all interfaces in that case. For example, I help with 4clojure. The webserver there is really running on port 8080 of the server raynes.me, with some nginx magic to forward port 80 if the host HTTP requests is 4clojure.com. You can access it directly if you like: http://raynes.me:8080 works fine, and here's our jetty call:
(run-jetty (var app) {:join? false :port 8080})
Thanks for your replies guys, it turns out that it was not a problem with jetty, I was running this on EC2, and had been applying port access permissions to a different security group than the one this particular instance belonged to :)