1. Challenges of Running n8n Locally (Why a Public Base URL is Needed)
Running n8n on a local machine (or local network) poses a challenge for trigger nodes like Telegram Trigger. These triggers rely on webhooks – URLs that Telegram (and other services) call back when an event occurs (e.g. a new message). By default, a local n8n instance uses URLs like http://localhost:5678/webhook/...
, which are not accessible from the internet. Key challenges include:
- Localhost is not publicly reachable: External services (like Telegram’s servers) cannot reach
localhost
or private IP addresses. This means Telegram cannot deliver webhook updates to your n8n if it’s only running locally. - Telegram requires HTTPS: The Telegram API specifically requires the webhook URL to be HTTPS (secured by a valid certificate) (Local install of n8n Telegram URL is http, cannot make it use https – Questions – n8n Community). If n8n is running on plain HTTP or an IP address with no valid SSL, Telegram will reject the webhook URL with an error (“an HTTPS URL must be provided for Webhook” (Local install of n8n Telegram URL is http, cannot make it use https – Questions – n8n Community)).
- Dynamic or changing addresses: Even if you configure your local network with a public IP or use a dynamic DNS, if the address changes or isn’t properly secured, the webhook may fail. Running locally behind NAT/firewall usually means no inbound connections from Telegram.
- n8n’s Webhook URL configuration: By default, n8n constructs webhook URLs from its internal host/port (e.g.
http://localhost:5678
). When running behind a proxy or tunnel, you need to override this to a public address. If you don’t, the Telegram Trigger will register an incorrect callback URL (oftenhttp://localhost
), causing Telegram’s webhook registration to fail or send updates to a non-routable address (Having trouble getting the Telegram Trigger node to work – Questions – n8n Community).
Why a public Base URL is needed: To solve these issues, you must provide n8n with a publicly accessible base URL. This is the URL that Telegram will use to reach your n8n. Essentially, you need to expose your local n8n to the internet securely. This typically involves:
- Obtaining an internet-accessible URL (with HTTPS) that forwards to your local n8n service.
- Configuring n8n to use that URL as its webhook base, so all trigger URLs (like the Telegram webhook) are formed with the public domain.
Telegram will then send updates to that public URL (which forwards to your machine), and n8n will receive the trigger events. Without this, the Telegram Trigger cannot function (the workflow can’t be activated or will never receive messages).
2. Configuring n8n with a Public Base URL
n8n allows you to specify the base URL for webhooks via configuration. You can set an environment variable or config setting to tell n8n what URL to use for its webhooks. This ensures that when you activate the Telegram Trigger node, n8n registers the correct HTTPS URL with Telegram.
A. Docker-Based n8n Setup (with Base URL)
If you’re running n8n in Docker (e.g. via docker run
or docker-compose
), you need to pass the appropriate environment variables to the container. Here’s how to do it:
- Choose/Obtain a Public URL: First set up a tunneling service or domain (discussed in the next section) so you have a public HTTPS URL that points to your n8n. For example, suppose you get a URL
https://example-tunnel.ngrok.io
. - Set
WEBHOOK_URL
Environment Variable: In your Docker environment, set theWEBHOOK_URL
to this public URL. This can be done in a Docker Compose file or via thedocker run
-e
flag. For example, in a docker-compose.yml:services: n8n: image: n8nio/n8n:latest ports: - "5678:5678" environment: - WEBHOOK_URL=https://example-tunnel.ngrok.io/ # (Add other n8n env vars like N8N_BASIC_AUTH if needed) volumes: - ~/.n8n:/home/node/.n8n
In this example, all webhook URLs n8n generates will start with
https://example-tunnel.ngrok.io/
. (Include the trailing slash after the domain) (Configure webhook URLs with reverse proxy | n8n Docs ). Make sure to use your actual tunnel/domain URL. This value can also be set in an.env
file and referenced in the compose file. - Launch the n8n container: If using docker-compose, run
docker-compose up -d
to start n8n with the new settings. If usingdocker run
, include-e WEBHOOK_URL=https://your-url/
in the command. - Verify Webhook URL in n8n: In the n8n Editor UI, add a Telegram Trigger node (or any webhook node) and look at the “Webhook URL” it shows. It should now reflect the public URL (e.g.
https://example-tunnel.ngrok.io/webhook/...
) instead oflocalhost
. This confirms n8n is using the public Base URL. For Telegram Trigger, n8n will attempt to register this URL with Telegram when you activate the workflow. - Activate the Workflow: Turn the workflow to “Active”. n8n will send the webhook info to Telegram’s API. If the base URL is correct and reachable, Telegram will accept it. (You can check Telegram’s response in n8n or via the Telegram Bot API
getWebhookInfo
to confirm it’s set).
Example: A Docker Compose snippet with environment variables might look like this (using an ngrok tunnel URL as the base): (N8N install on Proxmox VM with ngrok and trying to use telegram webhook – Questions – n8n Community)
environment:
- N8N_PROTOCOL=http
- N8N_PORT=5678
- WEBHOOK_URL=https://example-tunnel.ngrok.io/
# (Use https and your actual domain/tunnel URL)
Note:
WEBHOOK_URL
is the important variable. In some n8n versions/usage, you might seeN8N_WEBHOOK_URL
andN8N_WEBHOOK_TEST_URL
– these serve a similar purpose (for main and test webhooks). SettingWEBHOOK_URL
is usually sufficient for the production URL (Configure webhook URLs with reverse proxy | n8n Docs ). Ensure you use an HTTPS URL; Telegram will reject HTTP or IP addresses (Local install of n8n Telegram URL is http, cannot make it use https – Questions – n8n Community).
B. Non-Docker (Manual Local) n8n Setup (100% Local)
If you installed n8n via npm (npx n8n
) or as a binary and run it directly on your machine, the configuration is slightly different:
- Install n8n (if not already): Ensure you have n8n installed globally or accessible (e.g.
npm install -g n8n
or using npx). Also install any tunneling tool or set up a domain as needed (see next section for options). - Choose/Obtain Public URL: Same as before, set up a way to expose your local port 5678 to the internet with HTTPS. For example, get a URL from Cloudflare Tunnel or ngrok. Let’s say you got
https://mytunnel.trycloudflare.com
(Cloudflare’s tunnel domain) or you have a custom domain with SSL. - Set the
WEBHOOK_URL
: You can configure this in multiple ways:- Temporary via Command Line: Export the variable in your terminal session before starting n8n. For Linux/Mac:
export WEBHOOK_URL="https://mytunnel.trycloudflare.com/" n8n start
On Windows (Command Prompt):
set WEBHOOK_URL=https://mytunnel.trycloudflare.com/ n8n start
(Make sure to include the
https://
and trailing slash.) - Persistent via .env file: Create a file named
.env
in the directory where you run n8n, and add:WEBHOOK_URL=https://mytunnel.trycloudflare.com/
When you run
n8n
, it will load this configuration (n8n’s CLI respects environment variables and typically will load.env
by default). - Using n8n config file: Alternatively, you can set this in n8n’s config file. For instance, in
~/.n8n/config.json
, you could add:{ "baseUrl": "https://mytunnel.trycloudflare.com/webhook" }
This accomplishes the same thing (notice adding
/webhook
in the URL) (Having trouble getting the Telegram Trigger node to work – Questions – n8n Community). However, using the environment variable is usually simpler.
- Temporary via Command Line: Export the variable in your terminal session before starting n8n. For Linux/Mac:
- Start n8n: Now start n8n (
n8n start
). It will read theWEBHOOK_URL
config. - Verify in Editor: Open n8n in your browser (likely at http://localhost:5678 unless you configured n8n itself to run on HTTPS). Add a Telegram Trigger node. The Webhook URL it shows should start with your public URL (e.g.
https://mytunnel.trycloudflare.com/webhook/...
). If it still showshttp://localhost
, then the env var isn’t being picked up – double-check your steps. - Activate the Workflow: Turn it to active. If everything is correct, this will register the webhook URL with Telegram. The workflow should now be listening for messages.
Why this matters: If you skip the WEBHOOK_URL
setup, n8n will register a wrong URL (like http://127.0.0.1:5678/...
), and Telegram will respond with an error or simply not send updates to it (Having trouble getting the Telegram Trigger node to work – Questions – n8n Community). Setting the public base URL ensures Telegram knows where to send the message updates and that the URL is accessible (via the tunnel).
3. Options to Expose Your Local n8n to the Internet
Now that n8n is configured to use a public URL, the core piece is actually obtaining that public URL and forwarding traffic to your local n8n. Several tunneling or networking options are available to achieve this. Below are some common methods:
- Cloudflare Tunnel (Cloudflare Zero Trust): A free tunneling solution by Cloudflare (formerly Argo Tunnel) that can expose your local server to the internet through Cloudflare’s network, without opening ports on your router. This gives you a stable
*.trycloudflare.com
URL or a custom domain through Cloudflare. It’s secure and free/unlimited. - Ngrok: A popular tunneling service that gives you a public URL (usually
*.ngrok.io
or*.ngrok-free.app
) pointing to your local service. Easy to set up; free tier offers temporary URLs (they change each session). Paid plans can give custom subdomains or reserved domains for stability. - LocalTunnel (lt) or Expose: Open-source tunneling tools that can provide a quick public URL. LocalTunnel, for example, can be installed via npm and gives you a URL like
*.loca.lt
. These are simple to use for testing, though not as robust as Cloudflare or Ngrok. - Reverse Proxy with Your Own Domain: If you have control over a public domain and your network, you can forward a port (e.g. 80/443) to your machine running n8n. Using a reverse proxy (like Nginx, Traefik, or Caddy) with Let’s Encrypt for SSL, you could run n8n behind your own domain (e.g.
https://n8n.yourdomain.com
). This isn’t a “tunneling service” but is a viable route if you can set it up. (This requires a static IP or a dynamic DNS and opening firewall ports.) - n8n’s Built-in Tunnel (for testing): n8n has a built-in tunnel (
n8n start --tunnel
) which uses an n8n cloud service to provide a temporary URL (e.g.*.hooks.n8n.cloud
). This is very convenient for quick tests, but it’s intended for development only. It may be unstable for long-term use and, according to the n8n team, is likely to be removed in the future (Telegram api doesnt work with tunnel more then once – Questions – n8n Community). So, for a stable setup, prefer the above solutions.
Next, we’ll go through setting up the two most popular tunneling options (Cloudflare Tunnel and Ngrok), and briefly how to use others, in the context of n8n.
4. Setting up a Stable Base URL via Tunneling Services
Regardless of which service you use, the high-level steps are: install or sign up for the service, run the tunnel pointing to your local n8n, obtain the public URL, and configure n8n to use that URL (as done in section 2). Ensure your n8n is running and accessible locally (default is port 5678) before starting the tunnel.
A. Using Cloudflare Tunnel (Cloudflare Zero Trust)
Cloudflare Tunnel is a free solution that can expose your local server at an SSL-protected public domain without opening ports. You do not even need to own a domain (Cloudflare can provide a subdomain), though you can use your own domain if you have one.
Steps to set up Cloudflare Tunnel:
- Install Cloudflare’s Tunnel Client: Download and install
cloudflared
on your machine. (On Linux/Mac you can get it via package manager or direct download, on Windows there’s an exe). Cloudflare’s docs provide instructions. - Login or Create a Tunnel Token (optional): You can use Cloudflare Tunnel in two ways:
- Quick one-time tunnel: Without logging in, simply run
cloudflared tunnel --url http://localhost:5678
. This will connect to Cloudflare and output a URL likehttps://<randomname>.trycloudflare.com
. That URL will proxy tohttp://localhost:5678
. Copy that URL. - Named tunnel with account: For a more persistent setup, log in to Cloudflare (using
cloudflared login
) and create a tunnel through the Cloudflare Zero Trust dashboard. You can give it a name, and Cloudflare will provide you a credential file. You can then runcloudflared
to connect that tunnel. This method lets you use your own domain (Cloudflare DNS) or at least have a stable subdomain. For simplicity, we’ll assume the quick method.
- Quick one-time tunnel: Without logging in, simply run
- Run the Tunnel: For a quick test, run the command mentioned above:
cloudflared tunnel --url http://localhost:5678
Keep this process running. It will output something like:
INFO —> Route: tunnel will route from https://abcde12345.trycloudflare.com to http://localhost:5678
Now you have an external URL. (If you set up a named tunnel with your domain, use that domain URL.) - Configure n8n’s Base URL: Take the URL from step 3 (e.g.
https://abcde12345.trycloudflare.com
) and set it asWEBHOOK_URL
in n8n config (as described in section 2). For example, if running n8n via npm, exportWEBHOOK_URL="https://abcde12345.trycloudflare.com/"
before starting n8n. In Docker, update the env and redeploy. (Telegram api doesnt work with tunnel more then once – Questions – n8n Community). Cloudflare’s URL is already HTTPS, so it meets Telegram’s requirements. - Activate and Test: Start/Restart n8n with that environment. In the n8n UI, ensure the webhook URL shows the Cloudflare address. Activate the Telegram Trigger workflow. Telegram will be sent
https://abcde12345.trycloudflare.com/webhook/...
as the webhook. Send a test message to your bot and see if n8n catches it.
Cloudflare Tunnels are quite reliable for long-term usage (they can run continuously). If using the free trycloudflare.com
domain via the quick method, note that the URL might change each time you run the tunnel. For a more stable setup, consider creating a Cloudflare account and using a named tunnel with a fixed subdomain or your own domain name. With your own domain on Cloudflare, you can even set up a friendly URL like https://n8n.yourdomain.com
for your instance. In that case, set WEBHOOK_URL=https://n8n.yourdomain.com/
and Cloudflare will route traffic from that domain to your local n8n (Setup a webhook Url in n8n running on Docker Desktop Linux – Questions – n8n Community).
Cloudflare Zero Trust considerations: If you secure your Cloudflare tunnel with access control (Zero Trust policies like requiring login), the Telegram webhook will not be able to pass that (Telegram can’t log in). Make sure the specific webhook endpoint is accessible publicly (no auth). In Cloudflare’s Zero Trust settings, you may need to allow the
/webhook*
path to bypass authentication (Cloudflare Tunnel – Telegram Webhook not responding – Questions – n8n Community), or simply run the tunnel without additional access policies (open to the internet) (Cloudflare Tunnel – Telegram Webhook not responding – Questions – n8n Community) so that Telegram can reach it.
B. Using Ngrok
Ngrok is an easy-to-use tool to expose local servers. It’s great for quick tests and also usable for longer runs (with a stable subdomain if you have a paid plan).
Steps to use Ngrok:
- Install/Setup Ngrok: Sign up on ngrok.com and download the ngrok client. You’ll get an auth token. On your machine, run
ngrok config add-authtoken <YOUR_TOKEN>
(or as instructed by ngrok) to set up authentication (this is required for stable or longer sessions on the free tier). - Start an HTTP tunnel to n8n: Run:
ngrok http 5678
This will connect to ngrok’s service and you will see an output in the terminal. It typically shows something like:
Forwarding https://1234-56-78-90.ngrok-free.app -> http://localhost:5678
There will be a generated URL (sometimes two: one http and one https; use the https one). Copy the HTTPS URL (e.g.
https://1234-56-78-90.ngrok-free.app
). - Configure n8n with Ngrok URL: Set the
WEBHOOK_URL
for n8n to the copied ngrok URL (with a trailing slash). For example:- If using Docker Compose, update the env:
WEBHOOK_URL=https://1234-56-78-90.ngrok-free.app/
and redeploy. - If running locally, export the env var or put it in your
.env
file, then start n8n. Now n8n knows to use the ngrok URL as its base.
- If using Docker Compose, update the env:
- Activate Telegram Trigger: In n8n, the Telegram Trigger node’s webhook URL will now show the ngrok address. Activate the workflow. Behind the scenes, n8n calls Telegram’s
setWebhook
API with the ngrok URL. Telegram will verify it (ngrok provides a valid certificate). - Test the Trigger: Send a message to your Telegram bot. The webhook should go through ngrok’s cloud to your local n8n. You should see the workflow execute in n8n.
- Keep ngrok running: Keep the
ngrok
process running as long as you need the URL active. Stopping it will bring down the tunnel (and you’d need to reactivate the workflow with a new URL next time).
Ngrok tips: The free version gives you a random subdomain each session. This means every time you restart ngrok, you’ll get a new URL and need to update WEBHOOK_URL
and re-activate the trigger (Telegram needs the new URL). To avoid this, you can either keep ngrok running persistently, or use a reserved domain feature (paid plan) to get a fixed subdomain. For example, if you reserve mybot.ngrok.io
, your webhook could always be https://mybot.ngrok.io/...
and you wouldn’t have to change n8n’s config each time. If you use a custom domain with ngrok (enterprise feature), that’s even better. But for development, restarting and updating the URL is usually fine.
C. Other Tunneling Solutions and Considerations
Aside from Cloudflare and ngrok, there are other ways to expose your local instance:
- *LocalTunnel (localtunnel.me or .loca.lt): This is a free, open-source tunneling service. You can install it with
npm install -g localtunnel
. Then run, for example,lt --port 5678
(ornpx localtunnel --port 5678
). It will give you a URL likehttps://soft-dragon-12.loca.lt
. Use that as yourWEBHOOK_URL
. No signup needed. Keep in mind localtunnel URLs might be less stable and the service can occasionally be down, but it’s quick and easy. - Serveo or SSH local port forwarding: For developers, there are services like serveo.net which use SSH to forward ports. For instance,
ssh -R 80:localhost:5678 serveo.net
could give you aserveo.net
URL. Again, ensure it’s HTTPS (Serveo does support HTTPS). This is more of a niche approach. - Frp (Fast Reverse Proxy): If you have your own VPS or server, you could set up an FRP server and run an FRP client on your local machine to forward traffic. This is more involved but gives you full control (useful for self-hosting enthusiasts). Essentially, you’d be hosting your own tunneling service.
- Regional tunneling services: There are others like Expose by BeyondCode, Tunnelto, PageKite, etc. All operate similarly – you run a client that gives you an external URL. Use whichever you prefer, and configure the URL into n8n as done above.
No matter the service, the crucial part is that the URL must be HTTPS and accessible. Always test by opening the given webhook URL in a browser (you should see an n8n response like Webhook is listening
when the workflow is active). If that works, Telegram should be able to reach it too.
Also, remember that if your tunnel URL changes, you must update n8n’s config and re-activate the workflow so Telegram gets the new URL. If you forget, Telegram will still be sending updates to the old (now dead) address.
5. Configuration Snippets and Commands
Here is a summary of important configurations and commands from the steps above:
- Docker Compose Environment Example (ngrok or Cloudflare):
environment: - WEBHOOK_URL=https://<your-public-domain>/ - N8N_PORT=5678 - N8N_PROTOCOL=http # n8n runs internally on http - N8N_HOST=0.0.0.0 # bind all interfaces (standard for docker)
Ensure the domain has
https://
and a trailing slash. n8n will append its path (e.g./webhook/...
) automatically (Configure webhook URLs with reverse proxy | n8n Docs ). - Starting Cloudflared Tunnel (one-liner):
cloudflared tunnel --url http://localhost:5678
Output: a URL like
https://something.trycloudflare.com
. Use that in WEBHOOK_URL. - Starting Ngrok Tunnel:
ngrok http 5678
Output: copy the
https://xxxxx.ngrok.io
URL. Use in WEBHOOK_URL. Keep thengrok
process running. - Setting environment for n8n (non-docker):
Linux/macOS:export WEBHOOK_URL="https://<your-public-domain>/" n8n start
Windows CMD:
set WEBHOOK_URL=https://<your-public-domain>/ n8n start
(Alternatively, put this in an
.env
file or system environment.) - Telegram Bot Webhook (for reference): n8n handles registering the webhook for you when the workflow is activated. If needed, you can manually check the status via Telegram API:
curl "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getWebhookInfo"
This returns JSON with the current webhook URL Telegram has stored. It should match your public URL and show no error. If you ever need to manually set or delete the webhook:
.../setWebhook?url=<URL>
and.../deleteWebhook
endpoints exist (Telegram docs), but normally n8n’s Telegram node uses Telegram’s API under the hood when you activate/deactivate triggers. - n8n Activation: Always activate the workflow for the trigger to work in production (listening mode). In test mode (when you execute the node manually), n8n uses a different test webhook URL (with
/webhook-test/
in it). We also set the base for test URLs viaWEBHOOK_URL
(orWEBHOOK_TEST_URL
) similarly. The above configuration usually covers both.
6. Example n8n Workflow JSON with Telegram Trigger
Finally, here is an example workflow JSON that includes a Telegram Trigger node configured to listen for new messages, and a subsequent node that replies to the sender. You can import this JSON into n8n. Note: Before using it, set up your Telegram credentials in n8n (Telegram Bot API token) and name them appropriately. In the JSON below, the credential is referenced by name "Telegram Bot API"
. Replace it with the name of your credential (or adjust after import).
{
"name": "Telegram Message Echo",
"nodes": [
{
"id": "42b3bc4f-c2b5-4c43-8770-cab28530925f",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1,
"position": [400, 300],
"parameters": {
"updates": [
"message"
]
},
"webhookId": "d6f7e8b9-1a2b-400c-9dc4-123456789abc",
"credentials": {
"telegramApi": {
"id": "123",
"name": "Telegram Bot API"
}
}
},
{
"id": "ba5e1d0f-7f3e-4d2e-9b2e-9876543210ef",
"name": "Reply to Sender",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [800, 300],
"parameters": {
"operation": "sendMessage",
"chatId": "={{ $json[\"message\"][\"chat\"][\"id\"] }}",
"text": "={{\"Hello, you said: \" + $json[\"message\"][\"text\"]}}"
},
"credentials": {
"telegramApi": {
"id": "123",
"name": "Telegram Bot API"
}
}
}
],
"connections": {
"Telegram Trigger": {
"main": [
[
{
"node": "Reply to Sender",
"type": "main",
"index": 0
}
]
]
}
}
}
How this workflow works: The Telegram Trigger node listens for new messages (you can adjust the updates
array for other update types if needed). When a message is received by your bot, n8n will execute the workflow. The second node Reply to Sender uses the Telegram node to send a message back. It takes the chat ID from the incoming message ($json["message"]["chat"]["id"]
) and echoes back the text with a greeting.
After importing, edit the credentials: open each node and assign your Telegram Bot credential (the JSON’s "id": "123", "name": "Telegram Bot API"
is just a placeholder reference). Once set, save and activate the workflow. Ensure your n8n’s base URL is configured as described, so that the trigger’s webhook is registered properly.
By following the above steps, you will have a locally hosted n8n that can receive Telegram messages via a public webhook URL and trigger workflows. In summary, the critical steps are getting a public HTTPS endpoint (via Cloudflare Tunnel, Ngrok, etc.) and configuring n8n’s WEBHOOK_URL
to that endpoint (Telegram api doesnt work with tunnel more then once – Questions – n8n Community) (Setup a webhook Url in n8n running on Docker Desktop Linux – Questions – n8n Community). This bridges your local n8n to the outside world in a secure way, allowing services like Telegram to reach your workflow. Always consult the latest n8n documentation and the Telegram Bot API documentation for any changes. (As of now, Telegram’s requirements for HTTPS webhooks remain in place, and n8n’s configuration options are as described.) With a stable base URL configured, your Telegram trigger should work reliably on your self-hosted n8n instance.
Sources:
- n8n Community Forum – Various threads on Telegram trigger issues and solutions (Having trouble getting the Telegram Trigger node to work – Questions – n8n Community) (Local install of n8n Telegram URL is http, cannot make it use https – Questions – n8n Community) (Telegram api doesnt work with tunnel more then once – Questions – n8n Community) (Telegram api doesnt work with tunnel more then once – Questions – n8n Community).
- n8n Documentation – Configuring Webhook URL & environment variables (Configure webhook URLs with reverse proxy | n8n Docs ) (Setup a webhook Url in n8n running on Docker Desktop Linux – Questions – n8n Community).
- n8n Community (Jon’s responses) – Guidance on using tunnels (ngrok, Cloudflare) for self-hosted n8n (Telegram api doesnt work with tunnel more then once – Questions – n8n Community) (Setup a webhook Url in n8n running on Docker Desktop Linux – Questions – n8n Community).