host an nginx site from single configuration file on internal / external networks at the same time
Posted by merpkz@reddit | linuxadmin | View on Reddit | 14 comments
I am trying to host a dokuwiki site from an nginx web server by using only single configuration file, but no matter what I try, it just doesn't work right. Requirements are pretty simple, the site should work like following:
-
- Be configured in single config file for 80/443 with TLS.
-
- On local network work as wiki.local and it should not redirect to https, but just use plain http.
-
- On external network work as wiki.example.com and on port 80 redirect https scheme.
things I have tried so far, but each failing in different way.
-
- Combined mode with both listen 80; listen 443 ssl; and server_name wiki.local wiki.example.com in single server block - this works, almost, I can't redirect to https when scheme = https and $host = wiki.example.com, because nginx has no logical && or || in if conditions. so this will work on external network without https redirect - which is not optimal.
-
- Reverse proxy mode - separate config on 443 which reverse proxies to itself on port 80 and resets Host header to wiki.local. That works, but breaks links in wiki, when POSTing an article it will redirect external visiting browser to wiki.local because that was in HTTP Host header.
-
- Many server {} blocks in single config file for port 80 for local wiki and port 443 for external site. This works, but I need to duplicate all dokuwiki related configuration in two places for each port which is highly annoying to do. It basically makes them two sites which is not what I am looking for.
My config also has satisfy any clause with whitelisted local network IPs and a basic auth for everyone else - that part at least works reliably. So what am I doing wrong? Can't be that nginx is not capable of doing this simple local/external setup of a site in more straightforward way.
symcbean@reddit
This would not be my starting point. I'd have the same hostname for both access but require HTTPS for non-local clients. Doing this nicely probably means split horizon DNS (or just reflect from your router for a quick and dirty solution).
rhavenn@reddit
Just do 2 and do Host rewrites. Your docuwiki shouldn't even know about "wiki.example.com". nginx rewrite wiki.example.com to wiki.local and does a proxypass to the "wiki.local" site. Take any responses and re-write the Host back to wiki.example.com via proxy_redirect directive.
merpkz@reddit (OP)
yea, with proxy_redirect this works fine with my number two option - I just didn't knew that nginx can rewrite location headers - this fixes dokuwiki redirects and I can reverse proxy to myself all my internal / external services - nice. Thanks!
Gendalph@reddit
You're creating problems for yourself. You shouldn't mix secure and insecure hosts.
What would likely work is chaining
if
statements ormap
shenanigans, but it would be a bit fragile.A better solution is to create a local DNS record pointing to wiki.example.com and use the external domain with TLS.
rhavenn@reddit
This is a bitch to manage though since you'll have to duplicate any other DNS settings in 2 places so stuff like email works, etc... This really only is a good idea if you're dual-homing your DNS servers and run DNS locally for both external and internal queries.
Gendalph@reddit
If you're managing your LAN, you should already have a local DNS resolver that all clients use, just have that override the DNS record for
wiki.example.com
.Then:
wiki.local CNAME wiki.example.com
server
section in Nginx host config that redirects all requests on port 80 forserver_name wiki.example.com wiki.local
tohttps://wiki.example.com$request_uri
Upkeep: updating local record for
wiki.example.com
whenever it changes.But now I'm also concerned: what other DNS records would you maintain for your LAN? Web servers aren't supposed to be receiving any mail, and you need to maintain SPF/DKIM/DMARC only for your WAN addresses. The only thing you really care about is A/AAAA.
rhavenn@reddit
If you're setting up a zone "example.com" on the local server as authorative you will also need to match your public zone entries otherwise your local clients will get SERVFAIL responses when they lookup, for example, the MX record for "example.com" as the local server is authoratative for it and it's now not defined.
Any DNS server I'm familiar with requires you to set a "zone" and then add a host entry, ie: wiki.example.com is a host entry in the example.com zone. You could, I suppose, set the zone to be "wiki.example.com", but then you're limited to a A record only for the root zone record.
Personally, you should keep your zones 100% seperate. In this case using nginx with a proxy setup and a proxy_response rewrite should take care of any Host rewrites docuwiki is doing for external clients and internal clients just use wiki.local.
Gendalph@reddit
You are not setting up an authoritative zone. You are setting up overrides. And any decent DNS server acting as a local resolver would provide options to override a single record, without messing with the whole zone.
You can do this with dnsmasq, bind and unbound, hell, even just modifying
/etc/hosts
locally.rhavenn@reddit
Hugh. Didn't know that was a thing. Read the docs for unbound. Good to know. Thanks.
zakabog@reddit
What does your config look like? You should have one server block for the internal name, and one for the external fqdn. Super simple basic nginx configuration.
merpkz@reddit (OP)
That will fail my point number 3 - which will duplicate all dokuwiki specific settings in two files.
zakabog@reddit
It would be in one file, you can define as many server blocks as you'd like in one file
jaymef@reddit
try something like this
merpkz@reddit (OP)
Yea, this will most likely work. This is the combined config mode, but with tree if clauses just to make nginx redirect on external hostname http scheme. Guess I will use this, thanks. P.S. Are you chatgpt btw?