Creating a Secure Tunnel Between My Home and The Internet

Hi all,

I'm seeking your advice on if Zrok is a good fit for my desired configuration, and if so, what is the best way of configuring it?

I currently rent a dedicated machine from OVHCloud that runs my Minecraft server, website, and other websites and services. Each runs in a separate Docker container under different docker-compose.yml files. Except for the Minecraft server, each container is networked together under a Docker bridge network and managed by Traefik. Thus, the two routes into my public facing services are my Minecraft server and my Traefik proxy.

I want to move those services from my OVHCloud system to my computer at home and host them from there. While I could open 25565 for Minecraft and 80 for Traefik on my AT&T gateway and call it a day, I do not want to expose my home IP address and thus doxx my location. It seems like the best solution is to route public traffic through the OVH system that then connects to my home network. I saw a video (https://youtu.be/Duz-ya_iwu4) that seems to be doing that (masking the home IP from the public while still allowing traffic to flow into the home server).

Would it be possible for me to run Zrok in a Docker container on both ends (home and OVH) and have the home Zrok container be able to access the local Traefik and Minecraft containers through a virtual Docker network?

Thank you for reading my post! All thoughts and ideas are appreciated. If there are any useful pre-made configs for this situation, please feel free to link them.

Hey and welcome, @itsmcb!

I see what you're going for and I know it will work. To summarize, you want to do what Clint was showing in the video with zrok running in two places, but run both zrok processes in a container:

  • a zrok share private running on/near the private Minecraft server at your home
  • a zrok access private running on your Linux VM in your OVHCloud provider to publish a raw TCP proxy on a public IP.

zrok works great in a Docker container. There are a couple of ways to enable zrok in Docker.

The simplest way to use zrok shares and accesses with Docker is to run zrok enable on the Docker host, then mount ~/.zrok:/.zrok and set --user "$UID" when you run the container. Here are some examples. That way, zrok runs as your Linux user inside the container, which has permission to read/write files in your mounted zrok environment.

Another way to use zrok shares and accesses with Docker is to isolate the enabled zrok environment from the Docker host with a Docker-named volume. That's how these example Docker compose YAML files work.

Both of these approaches have a Docker networking aspect to consider. For the zrok share private on your home system, it must be able to reach the Minecraft server and the internet. For the zrok access private running on your Linux VPS, the firewall must allow incoming TCP on the port (e.g., 25565) and that same port must be published (forwarded) to the container (e.g., --publish 0.0.0.0:25565:25565.

Thank you for your prompt response! I've finally had the time to set things up.

I've successfully got a website configured the way I want with Zrok (routing from my home to my server and working with Traefik to display on a particular sub domain). However, I'm running into a small problem. I wish to use the same Zrok share container on my desktop PC to share multiple services at once (versus creating multiple share container config sections). For testing purposes, I wish to share both a website and a Minecraft server. However, this does not seem possible with the way the way Docker and the Zrok container are setup. I'll try to illustrate my point below.

The following is a portion of my current docker-compose.yml from my desktop PC.

  zrok-share:
    image: ${ZROK_CONTAINER_IMAGE:-docker.io/openziti/zrok}
    entrypoint:
    - bash
    - -euxc
    - |
      echo "DEBUG: HOME=$${HOME}"
      ls -lA /mnt/.zrok/
      exec zrok $${@}
    command:
      - share private --headless --backend-mode proxy ${ZROK_TARGET:-http://ai:7860/}
      - share private --headless --backend-mode tcpTunnel test_server:25565
    depends_on:
      zrok-enable:
        condition: service_completed_successfully
    volumes:
      - ./zrok_env:/mnt
    environment:
      HOME: /mnt
      PFXLOG_NO_JSON: "true"
    networks:
      - servnet

Please observe how the only difference from what I had working before is the addition of the second line under command. When Docker launches the container, only the second line is read and thus only the Minecraft server is published. The previous line publishing the AI web UI is ignored. I attempted to work around this by changing the command to use bash. That unfortunately didn't work as it seems command can only accept a single set of Zrok arguments.

To clarify what I'm saying, when command is set to as follows...

command: bash -c "zrok share private --headless --backend-mode proxy ${ZROK_TARGET:-http://ai:7860/} && zrok share private --headless --backend-mode tcpTunnel test_server:25565"

These are the logs from zrok-zrok-share-1:

+ echo 'DEBUG: HOME=/mnt'
+ ls -lA /mnt/.zrok/
DEBUG: HOME=/mnt
total 12
-rw------- 1 ziggy ziggy  52 May 27 07:48 config.json
-rw------- 1 ziggy ziggy 116 May 27 07:48 environment.json
drwx------ 1 ziggy ziggy  32 May 27 07:48 identities
-rw------- 1 ziggy ziggy  12 May 27 07:48 metadata.json
+ exec zrok -c zrok share private --headless --backend-mode proxy http://ai:7860/ '&&' zrok share private --headless --backend-mode proxy localhost:25565
Error: unknown shorthand flag: 'c' in -c
Usage:
  zrok share private [<target>] [flags]

Flags:
      --access-grant stringArray   zrok accounts that are allowed to access this share (see --closed)
  -b, --backend-mode string        The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn} (default "proxy")
      --basic-auth stringArray     Basic authentication users (<username:password>,...
      --closed                     Enable closed permission mode (see --access-grant)
      --headless                   Disable TUI and run headless
  -h, --help                       help for private
      --insecure                   Enable insecure TLS certificate validation for <target>

Global Flags:
  -p, --panic     Panic instead of showing pretty errors
  -v, --verbose   Enable verbose logging

[ERROR]: an error occurred (unknown shorthand flag: 'c' in -c)

While I guess creating copies of the zrok-share section may be the way to go, I'm wondering if I can simply the config by achieving execution of multiple Zrok share commands under a single section.

I see you decided to mount the enabled zrok environment on the container and set the run-as user's HOME to the mount point.

That'll work! You must run a separate container for each zrok share and zrok access command. I expect a future version of zrok will have a multi-share option, but currently, it's one share per process, and there should generally be only one process per container.

If some of the env vars are shared by all containers in the compose file, you can specify them in the common .env file. You can set the unique values for each share in each container's environment or command.

1 Like