Limitations
Before creating the infrastructure, consider the following:- Connect only one VM to each tunnel. Connecting multiple VMs to the same tunnel is not supported.
- Nebius Tunnels forwards incoming requests but does not authenticate their senders. Configure your webhook handler to verify the signature provided by the webhook provider.
Costs
Nebius AI Cloud charges you for the following billing items:- Compute virtual machine
- Boot disk attached to the VM
Steps
Create a tunnel
- Web console
- CLI
- In the web console, select the project where you want to create the infrastructure. All resources must be located in the same project.
- Go to Networking → Tunnels.
- Click Create tunnel.
- On the page that opens, set the tunnel name to
my-tunnel. - Click Create tunnel.
Configure access for the tunnel agent
To authorize the VM in the tunnel, prepare a service account with theapplicationtunnel.agent role. Later, you attach this service account to the VM.
-
Create the service account:
- Web console
- CLI
- In the sidebar, go to Administration → IAM.
- Click Create resource → Service account.
- In the window that opens, set the name to
tunnel-agent-saand select the project. - Click Create and continue.
-
Create a custom group in Identity and Access Management to assign the role to the service account:
- Web console
- CLI
- In the sidebar, go to Administration → IAM.
- Click Create resource → Group.
- In the window that opens, set the group name to
tunnel-agents. In the Scope field, select the project where you create all the resources. - Click Create.
-
Attach the tunnel and grant the
applicationtunnel.agentrole to this group. You can only grant this role by using the CLI.- CLI
-
Get the group ID:
The ID is specified in the
items.metadata.idparameter in the output. -
Get the tunnel ID:
-
Create an access permit in the custom group:
-
Add the service account to the group:
- Web console
- CLI
- Go to Administration → IAM.
- On the Groups tab, find and open the
tunnel-agentsgroup. - Click Add members.
- In the window that opens, add the
tunnel-agent-saservice account. - Once the account is added, close the window.
- The
tunnel-agent-saservice account is specified on the Members tab. - The tunnel and the
applicationtunnel.agentrole are specified on the Access permits tab.
Create a virtual machine
Create a VM without a public IP address and use a cloud-init configuration to install and start the tunnel agent and a sample webhook handler. Attach the service account you configured earlier so that the tunnel agent can connect to the tunnel.- Generate an SSH key pair.
-
Prepare the cloud-init configuration file. You’ll attach it to the VM.
In this file, specify two parameters:
users.ssh_authorized_keys: Public SSH key.write_files.content.tunnel_id: ID of the tunnel.
webhook.yaml
This configuration enables the following actions:- Add a username and a public SSH key to the VM.
- Install Docker on the VM.
- Authenticate by using the service account attached to the VM.
-
Create two Nebius Tunnels services:
hook: To receive incoming webhook requests on port 8080.ssh: To connect to the VM by using SSH.
- Deploy the tunnel agent on the VM.
-
Deploy
go-httpbinas a placeholder webhook receiver. Replace it with your own service and pointtargetat its port.
-
Create the VM:
- Web console
- CLI
- In the sidebar, go to Compute → Virtual machines.
- Click Create resource → Virtual machine. The creation flow is a step-by-step wizard. The sidebar shows your progress through the configuration sections. To move between sections, click Back and Next.
-
On the Compute step, configure computing resources:
-
In the Platform section, select:
- Without GPUs
- Regular
- Non-GPU AMD Epyc Genoa
-
In the Settings section, set:
- Preset: 2 CPUs - 8 GiB RAM.
- Project: The project where you create all resources for the tunnel.
- VM name:
tunnel-hook.
-
In the Platform section, select:
- On the Storage step, preserve the Ubuntu 24.04 LTS disk image and the SSD disk type, but change the disk size to 20 GiB.
- On the Network step, check the network and subnet. Keep None in the Public IP address field.
-
On the Configuration step, configure the access, identity and VM startup settings:
- In the Service account field, select the
tunnel-agent-saservice account. - Enable a custom cloud-init configuration file.
- In the field that appears, paste the contents of the
webhook.yamlfile prepared earlier.
- In the Service account field, select the
- On the Review step, check the full VM configuration. To change a section quickly, click next to the corresponding block. The wizard opens the relevant step with your current settings.
- Click Create VM.
Check the result
The tunnel agent starts as soon as the VM boots. Thewebhook-sink service starts shortly after Docker pulls the go-httpbin image.
To check that the webhook endpoint is working, send a test request from your local machine:
tunnel_masked_ID: Mask of the tunnel ID without theapplicationtunnel-prefix and regional routing code. Contains the last 15 characters of the tunnel ID. For example, forapplicationtunnel-e00abcdef123456789, the masked ID of the tunnel isabcdef123456789.region: Region of the project where you created the resources.
failed to connect to local service, the webhook-sink service hasn’t started yet. Wait a few moments and try again. If it still fails, see Troubleshooting.
Once the endpoint is working, paste the tunnel URL — https://hook-<tunnel_masked_ID>.tunnel.applications.<region>.nebius.cloud — into the webhook settings of your provider (GitHub, Stripe, Telegram, etc.). The tunnel URL is stable for the tunnel’s lifetime, so you only need to do this once.
To replace go-httpbin with your own webhook handler, update webhook.yaml, delete the VM and create it again. Configure your handler to listen on port 8080, or change the tunnel agent’s target to match your handler’s port.
Troubleshooting
If the test request fails, or the tunnel returnsfailed to connect to local service, connect to the VM and check the tunnel agent and the webhook handler. The VM has no public IP address. Connect through the ssh service of the tunnel.
Connect to the VM
Connect to the VM as described in Connecting to a virtual machine without a public IP address. If you still can’t open the session, use the serial console and run the checks below from there.Check the tunnel agent
On the VM, check the agent service and its logs:-f to follow new log lines, for example sudo journalctl -u nebius-tunnel-agent.service -f.
When the agent has registered with the tunnel, the logs include the public endpoint of each service.
If the agent doesn’t register, check for these common causes:
- The VM has no service account attached.
systemctl statusstill showsactive (running), but the agent retries indefinitely, showingIMDS token request failed: 404 Not Foundfollowed byconnection closed before registering. You can’t attach a service account to an existing VM. Delete the VM and create a new one with thetunnel-agent-saservice account attached. - The tunnel agent isn’t authorized to connect to the tunnel. Verify that the
tunnel-agent-saservice account belongs to thetunnel-agentsgroup and that the group includes theapplicationtunnel.agentrole for this tunnel. Check the steps in Configure access for the tunnel agent.
tunnel_id in the agent configuration is the ID of the tunnel you created:
applicationtunnel-e00abcdef123456789. If it is still the <tunnel_ID> placeholder, or it points at a different tunnel, delete the VM and create it again with the correct tunnel ID in webhook.yaml.
Check the webhook handler
Thehook service forwards requests to webhook-sink on port 8080. Check that service and its logs:
webhook-sink runs go-httpbin in Docker. If the unit is active and requests still fail, check the container:
webhook-sink. Its status should begin with Up, and the port mapping should be 127.0.0.1:8080->8080/tcp. This means that the container is running and its port 8080 is available through the VM’s loopback interface.
The output of the second command should contain the following message:
Check cloud-init
Use this check if eithersystemctl status command reports that the nebius-tunnel-agent.service or webhook-sink.service unit could not be found. This means that cloud-init might not have completed successfully.
Check the cloud-init output:
webhook-sink.service. Check it for errors related to downloading or installing the tunnel agent, installing Docker or starting the webhook handler. After resolving the error, delete the VM and create it again with the corrected webhook.yaml file because cloud-init runs only when the VM is created.