Bad Gateway - Self Hosted

We have built an app that runs on Umbrel, using Docker to manage ZROK Reserved Shares on our own hosted ZROK platform. The app works flawlessly during our in-house testing. But when we have others attempt to use the App, their frontend endpoint returns a Bad Gateway (502) error.

Here is the Docker Compose file we have defined for our app; users install it on their Umbrel.Local machine. We got most of this code from the ZROK documentation page.

server:
image: ourlink/mintsolo:latest@sha256:e8ecdfa70c4d0935b20d59e0d731ebda1b6c53531dee5f0842ee82f1da942398
restart: unless-stopped
ports:
- 3067:3067/tcp
- 3068:3068/tcp
volumes:
- ${APP_DATA_DIR}/data/database:/mintsolo/DB
environment:
NODE_ENV: production
BITCOIN_RPC_URL: http://${APP_BITCOIN_NODE_IP}
BITCOIN_RPC_USER: ${APP_BITCOIN_RPC_USER}
BITCOIN_RPC_PASSWORD: ${APP_BITCOIN_RPC_PASS}
BITCOIN_RPC_PORT: ${APP_BITCOIN_RPC_PORT}
DEV_FEE_ADDRESS: 13h...87qeL
BITCOIN_RPC_TIMEOUT: 10000
STRATUM_PORT: 3067
API_PORT: 3068
NETWORK: mainnet
API_SECURE: false
ENABLE_SOLO: true
ENABLE_PROXY: false
POOL_IDENTIFIER: MintSolo Umbrel
zrok-init:
image: busybox:latest@sha256:e3652a00a2fabd16ce889f0aa32c38eec347b997e73bd09e69c962ec7f8732ee
command: chown -Rc 2171:2171 /mnt/
user: root
volumes:
- zrok_env:/mnt
zrok-enable:
image: docker.io/openziti/zrok:latest@sha256:ce807816d16a0975763ef5537a58aa3f63fd6d08c8fdc6c882a2d92aa35dac11
depends_on:
zrok-init:
condition: service_completed_successfully
entrypoint: zrok-enable.bash
volumes:
- zrok_env:/mnt
environment:
HOME: /mnt
ZROK_ENABLE_TOKEN: F...wn9
ZROK_API_ENDPOINT: https://zrok.shared.mintsolo.app
ZROK_ENVIRONMENT_NAME: MintSolo
zrok-share:
image: docker.io/openziti/zrok:latest@sha256:ce807816d16a0975763ef5537a58aa3f63fd6d08c8fdc6c882a2d92aa35dac11
restart: unless-stopped
entrypoint: zrok-share.bash
depends_on:
zrok-enable:
condition: service_completed_successfully
volumes:
- zrok_env:/mnt
environment:
HOME: /mnt
ZROK_BACKEND_MODE: proxy
ZROK_TARGET: http://server:3068
ZROK_INSECURE: null
PFXLOG_NO_JSON: "true"

The generated endpoint for each user looks something like the following.

https://lwkmvoxwh8rc.shared.mintsolo.app:443

Unfortunately, as you can see, the endpoint returns a 502 error, and instead of displaying the proper information, it shows the ZROK Bad Gateway page.

Unsure of what to look for next. Any assistance would be greatly appreciated.

BTW, the ZROK_ENABLE_TOKEN in the Docker Compose source above has been redacted for security.

Hi @mintsolo, welcome to the community and to zrok self-hosting!

Umbrel sounds fun. Have you looked at the logs for the zrok controller and the zrok front end? Looking at the code, it should have an error in there. Anything useful in there that helps determine the issue?

In the ZROK frontend logs, I see these error lines
2025-12-02T20:12:54.593Z ERR file=/__w/zrok/zrok/endpoints/publicProxy/http.go:117 ``func=github.com/openziti/zrok/endpoints/publicProxy.newServiceProxy.func3`` msg=error proxying: unable to dial service 'lwkmvoxwh8rc' (dial failed: service 1IrUEVCkOKcrOjG6WaeXEF has no terminators)

The lwkmvoxwh8rc is one of the endpoints I see when I visit the ZROK API Console.

This OpenZiti-related error would be an indicator to me that there's no zrok "share" for whatever was trying to be accessed. There's nothing for zrok to send that traffic to.

Thank You, let me ensure that the Server: component of our Docker Compose file is working as expected then. We are exposing one of the Ports from that service within the ZROK Share as noted in the code.
environment:
HOME: /mnt
ZROK_BACKEND_MODE: proxy
ZROK_TARGET: ``http://server:3068``
ZROK_INSECURE: null
PFXLOG_NO_JSON: "true"

At least this will let me know where to start looking.

unable to dial service 'lwkmvoxwh8rc'

Is it possible that your external users are using a different zrok account than you are sharing with? If so, you might need to add access grants to allow their account to access your share… which will create the required policies in OpenZiti.

Not sure, but we do have the ZROK_ENABLE_TOKEN included as an environment variable for the Zrok-share: service in the Docker Compose.

So I would assume that would have them using the same account since I do see their frontend-endpoint showing in my Zrok API console.

If the container running zrok share is using the same enable token as the container running zrok access, then no-cross account permission issues would be a factor.

If you’re using different enable tokens (different accounts) involved, then you might need to make sure you’re using appropriate access grants.

I think you were onto the issue with this statement.

I’m looking at the customer logs that have the endpoint share issue, and I see they are getting some errors from the Server: service in our Docker Compose. I am trying to determine what is causing those for them.

“has no terminators” would imply that there is no zrok share running for that reserved share.

So I am to assume that if the Server: container failed, and it was not responding, then the share we have defined using these environment variables would also fail.

environment:
HOME: /mnt
ZROK_BACKEND_MODE: proxy
ZROK_TARGET: ``http://server:3068``
ZROK_INSECURE: null
PFXLOG_NO_JSON: "true"

Correct?

That was my expectation/guess. It's hard to know for sure of course without having access of my own. :slight_smile: @michael.quigley also offered a couple of scenarios that might cause related issues to check too

We have a container which runs zrok share but we do not have any containers running zrok access. Instead, we just use the URL created in the zrok share step to gain access. The zrok share generates URLS like this.

https://lwkmvoxwh8rc.shared.mintsolo.app:443

The thing that hosts those shared URLs is a zrok access public command. There must be one running somewhere, or you would not be able to access any public shares.

Never used the zrok access command. The Zrok Documentation does not mention it either when using the Docker Share for Public shares.

If you’re running a self-hosted environment, and you’re able to access your completely self-hosted zrok instance through a URL, then there is a zrok access public running in a container somewhere. That’s how zrok works. It’s probably just running in a docker container that you’re running.

I went back and looked our environment to see if I could find a zrok access public instance or command anywhere. I was not able to find anything.
So, I went and reviewed the documentation to see if it mentioned anything and I found this clip.

Every share is identified by a share token. Public shares can be accessed through either a frontend instance offered through the zrok instance, or through the zrok access command. Private shares can only be accessed through the zrok access command.

I am assuming this would mean that we don’t need the zrok access public since we have the frontend endpoint.

A “frontend endpoint” is zrok access public. There is no other mechanism that makes a share available to web browsers in a zrok installation.

The term “public frontend” and zrok access public are effectively synonyms.

I don’t know that this has anything to do with your problem anyway.

If you’re getting a no terminators message, and you’re using the same account (enable) token everywhere… then the most likely answer is that there isn’t a zrok share process running (in a container or otherwise) for the share that you’re trying to access.

That’s why I was wondering if the issue could be due to the server: container having an issue, because we are trying to establish a proxy share from that container. Does that sound reasonable?