Skip to Content

Ngrok Implementation Guide

Learn how to get tunnel URLs in your code and use management commands effectively.

Getting Tunnel URL

Django-CFG provides multiple ways to get the current tunnel URL in your code.

The recommended way to get tunnel URLs is through the DjangoNgrok service helper functions:

from django_cfg.modules.django_ngrok import ( get_tunnel_url, get_webhook_url, get_api_url, is_tunnel_active ) # Check if tunnel is active if is_tunnel_active(): print("✅ Ngrok tunnel is running!") # Get base URL tunnel_url = get_tunnel_url() # Returns: "https://abc123.ngrok.io" or None if not active # Get webhook URL with automatic fallback webhook_url = get_webhook_url("/payments/callback/") # If ngrok active: "https://abc123.ngrok.io/payments/callback/" # If not: "http://localhost:8000/payments/callback/" (fallback) # Get API URL api_url = get_api_url() # If ngrok active: "https://abc123.ngrok.io" # If not: api_url from DjangoConfig

Function Reference

get_tunnel_url() -> Optional[str]

  • Returns current ngrok tunnel URL
  • Returns None if tunnel is not active
  • Example: "https://abc123.ngrok.io"

get_webhook_url(path: str = "/webhooks/") -> str

  • Returns webhook URL with automatic fallback
  • Always returns a valid URL (tunnel or fallback)
  • Automatically adds path to tunnel URL
  • Example: "https://abc123.ngrok.io/api/webhooks/stripe/"

get_api_url() -> str

  • Returns API URL (tunnel if active, otherwise from config)
  • Always returns a valid URL
  • Example: "https://abc123.ngrok.io" or "http://localhost:8000"

is_tunnel_active() -> bool

  • Check if ngrok tunnel is currently active
  • Returns True if tunnel is running
  • Use before tunnel-dependent operations

Method 2: Via Environment Variables

After starting runserver_ngrok, tunnel info is available via environment variables:

import os # Tunnel URL ngrok_url = os.environ.get('NGROK_URL') # "https://abc123.ngrok.io" or None # Tunnel host ngrok_host = os.environ.get('NGROK_HOST') # "abc123.ngrok.io" or None # Scheme (http/https) ngrok_scheme = os.environ.get('NGROK_SCHEME') # "https" or None # Build webhook URL manually if ngrok_url: webhook_url = f"{ngrok_url}/api/webhooks/stripe/" else: webhook_url = "http://localhost:8000/api/webhooks/stripe/"

Method 3: Via Django Settings

Django-CFG automatically updates ALLOWED_HOSTS when tunnel starts:

from django.conf import settings # After runserver_ngrok starts: print(settings.ALLOWED_HOSTS) # ['localhost', '127.0.0.1', 'abc123.ngrok.io'] # Check if ngrok host is in allowed hosts ngrok_host = os.environ.get('NGROK_HOST') if ngrok_host and ngrok_host in settings.ALLOWED_HOSTS: print("✅ Ngrok tunnel is configured")

Usage Patterns

Pattern 1: Simple Webhook URL

from django_cfg.modules.django_ngrok import get_webhook_url def create_payment(request): # Get webhook URL (with automatic fallback) webhook_url = get_webhook_url("/api/payments/webhook/") # Use in payment provider payment = create_stripe_payment( amount=1000, webhook_url=webhook_url ) return JsonResponse({"payment_id": payment.id})

Pattern 2: Conditional Tunnel Usage

from django_cfg.modules.django_ngrok import is_tunnel_active, get_webhook_url def setup_external_service(request): if is_tunnel_active(): # Use ngrok URL for webhook webhook_url = get_webhook_url("/webhooks/service/") print("✅ Using ngrok tunnel for webhooks") else: # Use production URL webhook_url = "https://api.myapp.com/webhooks/service/" print("⚠️ Using production URL") # Configure external service external_service.set_webhook(webhook_url)

Pattern 3: Multiple Webhook Paths

from django_cfg.modules.django_ngrok import get_webhook_url # Different webhooks for different providers stripe_webhook = get_webhook_url("/webhooks/stripe/") nowpayments_webhook = get_webhook_url("/webhooks/nowpayments/") telegram_webhook = get_webhook_url("/webhooks/telegram/") print(f"Stripe: {stripe_webhook}") print(f"NowPayments: {nowpayments_webhook}") print(f"Telegram: {telegram_webhook}") # Output (if ngrok active): # Stripe: https://abc123.ngrok.io/webhooks/stripe/ # NowPayments: https://abc123.ngrok.io/webhooks/nowpayments/ # Telegram: https://abc123.ngrok.io/webhooks/telegram/

Pattern 4: Dynamic Configuration

from django_cfg.modules.django_ngrok import get_api_url, is_tunnel_active class PaymentService: def __init__(self): # Automatically use correct base URL self.base_url = get_api_url() self.is_local = is_tunnel_active() def get_callback_url(self, endpoint: str) -> str: """Build callback URL with correct base.""" return f"{self.base_url}{endpoint}" def create_payment(self, amount: int): callback_url = self.get_callback_url("/api/payments/callback/") if self.is_local: print(f"💡 Testing locally via ngrok: {callback_url}") # Create payment with callback URL # ...

Management Commands

runserver_ngrok

Runs Django development server with automatic ngrok tunnel creation.

Basic Usage

# Start server with ngrok tunnel python manage.py runserver_ngrok # Start on specific port python manage.py runserver_ngrok 8080 # Start on specific host:port python manage.py runserver_ngrok 0.0.0.0:8000

Advanced Options

# Use custom ngrok domain (paid plan) python manage.py runserver_ngrok --domain myapp.ngrok.io # Disable ngrok (run as regular runserver) python manage.py runserver_ngrok --no-ngrok # Force HTTPS python manage.py runserver_ngrok --bind-tls # Enable debug output python manage.py runserver_ngrok --verbosity 2

Command Output

$ python manage.py runserver_ngrok 🚇 Starting ngrok tunnel... Waiting for tunnel to be established... Tunnel check 1/10... Tunnel check 2/10... Ngrok tunnel ready: https://abc123.ngrok.io Django version 5.0, using settings 'myproject.settings' Starting development server at http://127.0.0.1:8000/ Public URL: https://abc123.ngrok.io Quit the server with CONTROL-C. Environment variables set: NGROK_URL=https://abc123.ngrok.io NGROK_HOST=abc123.ngrok.io NGROK_SCHEME=https ALLOWED_HOSTS updated: ['localhost', '127.0.0.1', 'abc123.ngrok.io']

Integration Patterns

Django Views

from django.http import JsonResponse from django_cfg.modules.django_ngrok import get_webhook_url def create_stripe_payment(request): """Create Stripe payment with ngrok webhook.""" import stripe # Get webhook URL automatically webhook_url = get_webhook_url("/api/webhooks/stripe/") # Create payment intent intent = stripe.PaymentIntent.create( amount=1000, currency="usd", metadata={"webhook_url": webhook_url} ) return JsonResponse({ "client_secret": intent.client_secret, "webhook_url": webhook_url })

Django REST Framework

from rest_framework.decorators import api_view from rest_framework.response import Response from django_cfg.modules.django_ngrok import get_webhook_url @api_view(['POST']) def create_payment_api(request): """API endpoint for payment creation.""" amount = request.data.get('amount') # Get webhook URL webhook_url = get_webhook_url("/api/webhooks/payment/") # Create payment payment = PaymentService().create( amount=amount, webhook_url=webhook_url ) return Response({ "payment_id": payment.id, "webhook_url": webhook_url })

Management Commands

from django.core.management.base import BaseCommand from django_cfg.modules.django_ngrok import get_webhook_url, is_tunnel_active class Command(BaseCommand): help = "Setup Telegram bot webhook" def handle(self, *args, **options): if not is_tunnel_active(): self.stdout.write( self.style.WARNING("⚠️ Ngrok tunnel is not active!") ) return # Get webhook URL webhook_url = get_webhook_url("/api/webhooks/telegram/") # Setup Telegram webhook from telegram import Bot bot = Bot(token=settings.TELEGRAM_BOT_TOKEN) bot.set_webhook(url=webhook_url) self.stdout.write( self.style.SUCCESS(f"✅ Webhook set to: {webhook_url}") )

Background Tasks (Django-RQ)

import django_rq from django_cfg.modules.django_ngrok import get_webhook_url @task async def send_webhook_notification(user_id: int): """Send webhook URL to user via email.""" from django.core.mail import send_mail # Get current webhook URL webhook_url = get_webhook_url("/api/webhooks/user/") send_mail( subject="Your Webhook URL", message=f"Use this URL for testing: {webhook_url}", from_email="[email protected]", recipient_list=["[email protected]"], )

Best Practices

1. Always Use Helper Functions

# ✅ CORRECT - automatic fallback from django_cfg.modules.django_ngrok import get_webhook_url webhook_url = get_webhook_url("/webhooks/") # Always returns valid URL (tunnel or fallback) # ❌ WRONG - manual check import os ngrok_url = os.environ.get('NGROK_URL') webhook_url = f"{ngrok_url}/webhooks/" if ngrok_url else "http://localhost:8000/webhooks/"

2. Check Tunnel Status Before Critical Operations

# ✅ CORRECT - check before using from django_cfg.modules.django_ngrok import is_tunnel_active, get_webhook_url if is_tunnel_active(): webhook_url = get_webhook_url("/webhooks/") setup_external_service(webhook_url) else: print("⚠️ Tunnel not active, using fallback")

3. Use Type Hints

# ✅ CORRECT - type hints from typing import Optional from django_cfg.modules.django_ngrok import get_tunnel_url def get_public_url() -> Optional[str]: """Get public URL for webhooks.""" return get_tunnel_url()

4. Log Tunnel Info

# ✅ CORRECT - log for debugging import logging from django_cfg.modules.django_ngrok import is_tunnel_active, get_tunnel_url logger = logging.getLogger(__name__) if is_tunnel_active(): logger.info(f"✅ Ngrok tunnel active: {get_tunnel_url()}") else: logger.warning("⚠️ Ngrok tunnel not active")

Next Steps

See Also

Ngrok Integration

Core Documentation:

Implementation Guides

Practical Examples:

Related Features:

Configuration & Setup

Getting Started:

Advanced:

Tools & Development

CLI & Management: