Hosting at a port of an arbitrary host -- how?

I’ve hosted many Clojure apps and my typical method is to deploy the war or jar, which is visible on some internal port, and then reverse-proxy to that port with some host address, using Apache or nginx. Now I want a quick one-off solution, and I’m having a maddening time of it. I want to deploy a bare jar and make it publicly accessible on a given port, for any arbitrary server it’s on (assuming, of course, the server does not have the port firewalled). How can this be done without me specifying the host?

Sourecode example that works for the reverse-proxy or localhost situation:

(ns myapp.core
  (:require [family-map.handler :as handler]
            [luminus.http-server :as http]
            [family-map.nrepl :as nrepl]
            [luminus-migrations.core :as migrations]
            [family-map.config :refer [env]]
            [clojure.tools.cli :refer [parse-opts]]
            [clojure.tools.logging :as log]
            [mount.core :as mount])
  (:gen-class))

(def cli-options
  [["-p" "--port PORT" "Port number"
    :parse-fn #(Integer/parseInt %)]])

(mount/defstate ^{:on-reload :noop}
                http-server
                :start
                (http/start
                  (-> env
                  (assoc :host "127.0.0.1" ;; <-- Can I somehow wild-card this, so it will accept any host whose request gets to it? 
			     :handler #'handler/app)
                      (update :port #(or (-> env :options :port) %))))
                :stop
                (http/stop http-server))

(defn stop-app []
  (doseq [component (:stopped (mount/stop))]
    (log/info component "stopped"))
  (shutdown-agents))

(defn start-app [args]
  (doseq [component (-> args
                        (parse-opts cli-options)
                        mount/start-with-args
                        :started)]
    (log/info component "started"))
  (.addShutdownHook (Runtime/getRuntime) (Thread. stop-app)))

(defn -main [& args]
  (cond
    (some #{"migrate" "rollback"} args)
    (do
      (mount/start #'family-map.config/env)
      (migrations/migrate args (select-keys env [:database-url]))
      (System/exit 0))
    :else
    (start-app args)))
1 Like

Since writing this I read the docstring on immutant.web/run, which says:

Note the web server only binds to the loopback interface, by
default. To expose your handler to the network, set :host to an
external IP address, or use “0.0.0.0” to bind it to all interfaces.

I’m trying to use wikipedia power to understand what these interfaces are, but in the meantime even “0.0.0.0” is only exposing it locally, so I suspect my university has some kind of other firewalls messing things up.

The answer was twofold: first, set 0.0.0.0 to accept “all interfaces,” the, my being on SUSE Tumbleweed linux, I found my firewall service as “firewalld”. Shutting that off and setting to all interfaces, I was good. It was the interface thing that really has to do with Clojure, as that was in my core.clj.

Rubber duck debugging, eh!

Glad you got it solved, and took the time to post your solution :+1:

2 Likes