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)))