VPN tunnel for apps
@robi Well, the thing is. The second app should pass all the health checks just fine. It’s a web app after all that is exposed to the web (right now testing with the LAMP stack’s homepage). The only reason it doesn’t pass the check (which makes Cloudron stop the container) is because Cloudron is setting up the reverse nginx config incorrectly due to it believing the Cloudron app just installed has no hostPort even though it really does.
The nginx reverse config needs to account for this to make the second app connected to the VPN Client app to even work. Because right now all I can do is use its terminal to prove its working. But the Cloudron network is setup in such a way that it’s needed to reverse proxy it’s
My newest idea is to write the Docker randomized
hostPortas part of the Cloudron environment variables it holds and then use that in the Nginx Reverse Proxy config if the starting app doesn’t appear to have one.
boxcode is harder than app code (especially because I can’t access its database outside of the command line and, well...I don’t really know SQL syntax). But shoutout to @nebulon for making it easier for me!
This also leads to the discussion of exposedPorts in the OpenVPN Client app's side of things. Right now, it has to mirror each of it's connected containers (their can be multiple) exposed ports, but Cloudron (for good reason) has restricted app's exposed ports to one.
Dynamically assigning just the OpenVPN's exposed port(s) on demand (to logically sync up with the app that's connecting to it) is needed here and does 100% require a restart of the OpenVPN Client app unless we decide to go the route of opening
xamount of the common ports and restricting multiple Cloudron app's from connecting to the OpenVPN Client to one exposed port per app (which ironically could be worked around with a dynamically assigned port forwarding to the real second containers port which then finally reverse proxies onto the hostPort + port 80 / 443 - but that seems like two much work just to connect more than one app per
exposedPortat a time).
(Disclaimer: I am no expert on docker networking magic)
I think instead of trying to find a way to expose the ports from the OpenVPN container, you should instead try and find a way to make it work directly from the app container itself.
Even if you do make it work for the exposedPort (which, I think, refers to the main web port exposed by the app, the one which is behind the reverse proxy, to expose its web interface and such, that's why there's only one: there's only one web interface), you're gonna have trouble with the extra ports (the ones defined in the manifest here https://docs.cloudron.io/custom-apps/manifest/#tcpports ) for apps that use these.
@mehdi Well, that would only need to be a
boxdiscussion if we wanted more than one other Cloudron app to connect to it at a time. It'd be an interesting discussion on how to make it work with no caveats. But I personally don't see a need to have more than one container connect to the OpenVPN Client container. It's not like you can't add a secondary VPN Client Cloudron app and connect it to another app if you really need more than one VPN connection, ya know?
Since that's how I'll be coding it, as soon as someone tells me how to use the
boxto "get" the cloudron manifest ID. I'm assuming only girish or nebulon know that off the top of their head though so I'll have to reverse engineer that as soon as I figure out how to get the app passed this reverse nginx configuration barrier (which from the code looks like it's reading
nullwhich is why no apps are working). It would be nice in that situation to know the function to get the hostPort of another container based on manifest id (my OpenVPN Client app to be exact). But once I RE those last two functions, I can do this.
Maybe these functions exist, maybe they don't. REing is hard. I've never really coded in Node (or used Docker) before this month so these are all new concepts to me.
Oh, I think the answer to my first question was really simple: app.manifest.id. ️
Last thing is - I still need to find a way to get either container environment variables or the app object via only knowing the the cloudron manifest id. Then this should work perfectly.
I mean, actually that would create a possible more than one object returned scenario.
That's fine though, I'll just take the first app of that mainfest id (since more than one Cloudron app with the same manifest id can be installed simultaneously).
My bad, nginx is writting the
httpPortfine and it's configuration looks perfect. I'm missing something related to nginx though because all my HTTP requests to the Cloudron app that is supposed to be routed through the OpenVPN Client app just ends in a "502 Bad Gateway".
Other than this mysterious nginx issue (that I think has to do with the exposed port not being available somewhere
boxassumes it's supposed to be), the app will continue to work and it's terminal will run. So this is all working as it should, except for something about nginx.
You know the crazy part, it's even getting an SSL cert (it must be using some DNS validation for that since the proxy isn't working).
@p44 I built the OpenVPN Client you can use to change your IP for your app. @girish offered to add a custom feature to Cloudron specifically to allow Cloudron apps to
network connectto my OpenVPN Client app. So, not much longer now! I might try to dive into the network code myself but I'll admit, Cloudron's base code intimidates me.
@Lonk Thank's a lot this is a very good feature to use. I'm following this thread. I'll wait for first release with a good web interface
@p44 It won't be put on the Cloudron Store without a web interface for you to change VPN credentials. That's my 1.0 "this is a finished app" final goal.
Right now, I'm just trying to make Cloudron's reverse proxy for the "app-connected-to-the-vpn-client" work correctly.
So, as it stands, reverse proxy is forwarding requests to port 80, 443 to
app.httpPort(a randomized container port, for example 34222), and then what's supposed to happen is port "34222" is supposed to proxy to the real
exposedPortbut that last step is what it's missing so I just get a "502 Bad Gateway". I can't find any references in the code to how to make the reverse proxy take that
exposedPortfrom another app (the OpenVPN Client app) and use it to continue the proxy-ing. In fact, I can't even RE how official apps are doing so.
This may be secret knowledge that only @girish knows and he'll have to tell me so I can fix this final proxy issue.
It's funny because I'm doing so much work in
boxright now to get this working. But I'm mainly just REin
boxcode. The changes required to make the OpenVPN client work / function (which it already does...just without a web interface because I can't figure out how to proxy to it's exposedPort) - like, literally the changes to
boxamount to 5 new lines of code. I'm guessing fixing this last "proxy-to-exposed-port" issue will be a single line of code fix making the total 6 lines of code. So the changes are so simple, it's the knowledge of
boxnetworking I'm lacking in. Cloudron uses an NPM library called
dockerodeto do it's Docker stuff. I thought it was the problem, but it's not - it's working just fine. It's this silly proxy issue. I'm so close...yet so far.
Talked to @girish a little bit to confirm that the
ExposedPortbinds to the
dockerode.createContainermagic. Soooo...there's only one solution. Use
dockerode'sown library to fix this problem. How to do so...I'm not sure, time to look into
dockerode'slibrary. But, the
.runcommand looks promising.
I can't believe this whole time it wasn't a Reverse Nginx Issue. I had a sneaking suspicion it was a
dockerodeissue but I didn't want it to be. I'm scared of making any dockerode changes.
This is likely what I need to use (conditionally when connecting the OpenVPN Client app to another Cloudron app):
Closer than I've ever been now. But I still don't know how to use that command yet.
Or...or, what if I forced the
ExposedPortto mirror the
httpPort. That would solve the Nginx "502 Bad Gateway" issue (which is the last hurdle for a perfectly working PoC). I mean, is there really any reason for an exposed port in a Cloudron sense since it just reverse proxies all apps exposed ports to 80, 443 anyway. I think I'm going to try this first instead of the whole diving into
Okay...there is a tiny reason. More like a medium reason. More like a BIG reason. Which is, the web apps themselves most-of-the-time choose to listen only on their exposed port (which means, I'd still need to manually proxy their exposed port to their
app.httpPort...somehow). But I'll deal with that later. Gotta try this "mirror ports" experiment first to even see if it works.
Making a PoC is more important than those logistics rn tho.
robi last edited by
@Lonk what if you virtualized the exposed port? another nginx that you control?
@robi That's a great idea. I've thought about it before, and I'm 99% sure it would work...I just can't wrap my head around it (it's roughly what I meant in my last post when I said " I'd still need to manually proxy their exposed port to their app.httpPort...somehow").
Tbh, I think I burnt myself out because I know you're right. I mean, putting another nginx reverse proxy behind the randomized
app.httpPort(say 32344) to
proxy_passto an exposed port (say 8080) would so work. My brain is just having trouble processing the concept rn (as in, where I'd need to put that code since I think it would still have to be created at the
So, your idea is my next attempt at making the OpenVPN client universal.
Oh, and I need to find a way to make Cloudron expose all of OpenVPN Client's internal ports. Or at least the common ones - because the second app inherits the exposed ports of OpenVPN Client app (so the two apps would need to match up their exposed ports somehow, and a wildcard, open all ports on the OpenVPN Client's side seems like the only way to do so).
I feel like I live-blogged my entire RE and development process with this thread.