VPN tunnel for apps
-
@girish
Goals for v0.4.0:
• Modifydocker.js
to use thecontainer:vpnContainerID
NetworkMode for all apps choosing to run their traffic through the VPN (presumably a drop-down box in the config option of an app which will need to be coded in the dashboard, hardcoded to the ovpn-client's manifest ID). Note: Need to removehostname
and anyport bindings
so that the container takes on the attributes of the VPN otherwise the NetworkMode will conflict with the VPN Client's Network.Goals for v0.5.0:
• Add an HTTP API endpoint to change and convert any .ovpn file a user supplies via POST into the container and disconnect from current to connect to the newly added .ovpnGoals for v1.0.0 (I'd consider it ready to upload to the official Cloudron Appstore at this point):
• Add a full web interface at the base URL of the app which uses the API endpoint in v0.5 to allow a user to submit any .ovpn file and convert it to what Cloudron needs to straight from a web interface (so they don't have to use the API or manually add it in the terminal / file manager, which would be confusing to new users using Cloudron). -
@girish And I will post on each app's wishlist forum post when I start work on converting.
I'm just really stuck on this NetworkMode code. No matter what I do, the NetworkMode stays
cloudron
even after restarting the container and hardcoding it to use the NetworkModecontainer:vpncontainerid
. Effectively making the app useless. The NetworkMode needs to change, but it's like once the NetworkMode is attached to an app, it stays on there no matter what. Still experimenting as that's the last piece of this puzzles aside from finding a function that can take a cloudron-manifest-id and translate it to a Docker Container ID (so I don't have todocker network inspect
and then hardcode it's ID). -
@mehdi My OpenVPN Client doesn't require any more edits to work on Cloudron. Or are you referring to the "other container" that I'm trying to attach to my OpenVPN Client (to then change it's public IP which I just check with
curl icanhazip.com
every new experiment)? So all apps / cloudron containers I just restart from the Cloudron dashboard since they are the one's who'sNetworkMode
needs to becontainer:vpn-docker-constainer-id-or-name-but-really-just-id
(it's hard to parse containters and networks because docker.js has to sent the app names to their container ids to prevent container naming conflicts) - which is abox
problem that needs to be solved (particularlydocker.js
).I see a lot of mentions of
appContainer
references andsubcontainer
references in REing thedocker.js
code. But they're all just regular containers (nothing is special about them except a flag is set if it's.a subcontainer) so that must be a Cloudron nomenclature.I think (really just hope) I found my issue:
function containersCreate(req, res, next) { safe.set(req.body, 'HostConfig.NetworkMode', 'cloudron'); // overwrite the network the container lives in
Now why are you doing that to me @girish?
-
THAT WAS IT! Well, there's more to box code changes than just proving the vpn client connection works. But @girish was overriding the network name in dockerproxy.js which took an entire day to figure out! but really
Alright, @mehdi, I'm glad you pushed me enter into box code realms. I'm still intimidated by it. But I've got (sub)container creation down pretty well now.
-
One of the worst parts of box code is that all these containers (aside from contained cloudron services and cloudron itself) have hshes for names. So, when trying to connect one to another and then inspecting the attributes of all of them is so confusing.
-
To get this app store ready, it might even need modifications to the nginx reverse proxy. @mehdi Maybe you can help? Is there a way, in cloudron to open more than one port? The manifest seems to be a way to publish a random port to forward to the specified-in-the-manifest port
Example:
Using
docker container ls --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}" -a
- I can look at all the "published" ports. They all seems to be going through a nginx reverse proxy to reach port 80 / 443. And their original port that forwards to that is random (?).NAMES ----------------------------------- PORTS
0b993ea5-85fc-4465-af5f-a1cd5ea5aeb7 127.0.0.1:43641->8080/tcp
57c94244-112d-4b98-abc4-0f15d6b07ca7 127.0.0.1:40875->8000/tcp
10a9ae64-689e-4765-a990-89a3d5e400d2 127.0.0.1:44749->80/tcp
-
I'm having a reverse proxy battle. Everything works now, but the "connected-to-the-vpn-client" app can't access the outside world. Cloudron doesn't publish ports in the standard way, there's some proxy between it all, and I have to RE that to get the apps connected to the
openvpn-client
to use the proxy somehow. It should just work by default looking at the code, but - there's always something. -
Okay, so there's a problem here:
appPortBindings.hostPort
needs to be set for all of Cloudron's containers or Cloudron turns them off. The only reason I know my OpenVPN client works is because Icurl icanhazip.com
beforebox
stops the container for not passing all of it's "checks."But this is a special case. To connect to the VPN Client - the app container can't have a hostPort as it inherits that from the VPN Client as part of the connection. But Cloudron requires the App published to have a port (I hardcode it not to), so even though the app works, Cloudron will stop it from running eventually once it fails enough checks until I figure out how to deal with this reverse proxy thing works.
-
I just have to figure out how to let
appdb.js
know that there's an actual http port set, it's just not in the **connected-to-vpn-client's`` app / container, it's defined in the OpenVPN Client's app / container.Barring figuring that out though, I have to have the openvpn-client app mirror the ports that are exposed for every app connnected to it (right now, I'm just letting one container connect since Cloudron doesn't support more than one exposed port). Ahhh, so basically the OpenVPN client's http port has to be variable depending on the connecting app (or apps if people want to connect more than one other app to it at a time - I only personally need one app connected to it). So that's
manifest.js
code to also modify to get this to work. -
The first step in making any tunnel is digging a hole
-
Nice metaphor for a VPN tunnel app. I’m so close to get this working. I found the SQL that inserts the httpPort into the DB so I’m going to try to have the container “attaching to the openvpn client” inherit the port and port type from the VPN Client while still having it be discoverable by the database. Let’s hope this works.
-
Alright, I got the container both running and entered into the database (I'm pretty sure). So Cloudron can "see" the app. I copied the exposed and host ports to the container returned at the end of
createContainer
while nulling them during the containers initialization.That seems to be enough for app discovery, now to see if I can get the reverse proxy working which will be the last piece of the puzzle I hope.
-
Dig, Forest, Dig!
-
@marcusquinn I’m not positive but I think the Nguni reverse proxy is being fed a null or 0 hostPort. The exposedPort is part of Cloudron’s environment variables. Maybe I’ll add the hostPort to that and read it back during reverse proxy configuration.
-
I hope nobody finds me logging my development on this app to be annoying. I needed a place to keep all of these new concepts in my head. I’ve never worked with Docker or Cloudron before this month and I’m trying to jot down my experiences for me to read later until I complete this.
If I hardcode the health checks to all pass. My app connected to the VPN stays connected and it’s terminal working but never gets past the “Starting” phase until it times out in like ten minutes (the reverse proxy doesn’t work so neither does Let’s Encrypt...which then times out the app). This is because it’s reverse proxy isn’t set up correctly. I believe that the NGINX reverse proxy either gets the wrong hostPort or the wrong exposedPort or both.
I’m actually amazed that I got this far. Because both the
hostPort
does make it into the database now for it to be discoverable by Cloudron. But why the reverse proxyWriteNginxReverseConfig
receives different info than `apps.js’ “add-to-db” function (since that happens first) is really confusing. I’ll keep working on it though. I can’t hardcode (wellll...I technically can for the same container but don’t want to).Another problem is that my NetworkMode to container changes only (for now) take effect upon installation. Have to figure out why that is - but I also have some guesses.
Nobody told me
box
code was this hard.