Serve ports through URL using lighttpd
Settings and goal
On a raspberry pi, I'm running a Lighttpd server (version: lighttpd/1.4.53 (ssl)). This server was initially installed by pi-hole, a DNS I'm starting to use to manage my network. I already managed to associate http://raspi.home
to my raspberry pi IP.
This device already runs several services, for instance an R-shiny server on port 3838 and a homeassistant installation on port 8123, that I can thus access through http://raspi.home:3838/
and http://raspi.home:8123
respectively.
My goal is now to be able to access my services through user-friendly addresses, such as http://raspi.home/shiny
(port 3838) and http://raspi.home/homeassistant
(port 8123).
Since the lighttpd server was configured for pi-hole, /var/www/html/
contains only two folders: "pihole" and "admin". I can access pi-hole admin panel through http://raspi.home/admin
and http://raspi.home/pihole
is accessible but not of much use.
My goal is to make that browsing http://raspi.home/shiny/...
serves http://raspi.home:3838/...
(and same for homeassistant).
Advance so far
I'm modifying /etc/lighttpd/external.conf
, which adds on /etc/lighttpd/lighttpd.conf
(code here). I tried various things but lighttpd conf files are quite confusing to me, and I'm never sure what should I put at the root level or in a $HTTP["url"]
.
What worked the most so far was adding an URL mapping with the server definition:
$HTTP["url"] =~ "^/shiny" {
proxy.header = (
"map-urlpath" => ( "/shiny" => "/" ),
"upgrade" => "enable"
)
proxy.server = ( "" => ( ( "host" => "localhost", "port" => 3838) ) )
}
Unfortunately, this changed all the relative URLs as well so that any image in http://raspi.home/shiny/index.html
is searched in http://raspi.home/images/image.png
instead of http://raspi.home/shiny/images/image.png
. Therefore, no resource could be found.
If I remove the condition, the mapping is global so the app is usable, but since everything is mapped all other sites are now unusable. This is described in this bug but I couldn't make the solution provided work.
I tried with "map-urlpath" => ( "/shiny(.*)$" => "/$1" )
but inexpectedly this throws a 404 error (with or without the condition).
resources
Here are more resources that might be related/useful:
- Proxy URL to different port via Lighttpd
- Lighttpd proxy redirect by port
- https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModProxy
- https://redmine.lighttpd.net/boards/2/topics/1946 (redirection worked though)
- Rewrite URL before passing to proxy Lighttpd
- https://redmine.lighttpd.net/boards/2/topics/8322
They didn't work for me, either because I didn't put the code on the right place or not adapted to my case, who knows...
$HTTP["url"] =~ "^/shiny" {
proxy.server = ( "" => ( ( "host" => "192.168.1.138", "port" => 3838 ) ) )
}
Delete proxy.header
until you better understand what it does and does not do.
https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModProxy
proxy.header
"map-urlpath"
will modify the request-line of the HTTP headers, but lighttpd does not rewrite the response body, so your R-shiny server will have to understand it is rooted under /shiny/. I have not looked at R-shiny to see if that is possible.
A different alternative is to create DNS names shiny.raspi.home and homeassistant.raspi.home, which you can then configure lighttpd to reverse proxy
$HTTP["host"] =~ "shiny.raspi.home" {
proxy.server = ( "" => ( ( "host" => "192.168.1.138", "port" => 3838 ) ) )
}
Please note that I changed the target "port"
in my examples above, as I am guessing that is the reverse-proxy target host and port to which you would like lighttpd to reverse-proxy the request to http://shiny.raspi.home/