.. _advanced/cloudflare_tunnel: =========================================== Cloudflare Tunnel for Local Development =========================================== `Cloudflare Quick Tunnels `_ expose your local Django server to the internet — perfect for receiving Paystack webhooks during development. No account or login required. paystack-django provides a built-in management command that wraps ``cloudflared`` and prints the webhook URL you need to paste into your Paystack Dashboard. Installing cloudflared ====================== Linux ----- **Debian / Ubuntu (amd64):** .. code-block:: bash wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb sudo dpkg -i cloudflared-linux-amd64.deb **RHEL / CentOS / Fedora:** .. code-block:: bash sudo rpm -i \ https://pkg.cloudflare.com/cloudflared-linux-x86_64.rpm **Manual binary (any distro):** .. code-block:: bash curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \ -o cloudflared chmod +x cloudflared sudo mv cloudflared /usr/local/bin/ macOS ----- .. code-block:: bash brew install cloudflared Windows ------- **Winget:** .. code-block:: powershell winget install Cloudflare.cloudflared **Manual:** Download the latest ``.msi`` from `GitHub Releases `_. Verify the install: .. code-block:: bash cloudflared --version Quick Tunnel (Manual) ===================== You can always start a tunnel manually: .. code-block:: bash cloudflared tunnel --url http://localhost:8000 ``cloudflared`` prints output like: .. code-block:: text 2026-02-21T12:00:00Z INF +----------------------------+ 2026-02-21T12:00:00Z INF | Your quick Tunnel has been created! ... 2026-02-21T12:00:00Z INF +----------------------------+ 2026-02-21T12:00:00Z INF https://random-slug-here.trycloudflare.com Copy the ``https://....trycloudflare.com`` URL, append your webhook path, and paste it in the `Paystack Dashboard → Settings → API Keys & Webhooks `_: .. code-block:: text https://random-slug-here.trycloudflare.com/webhooks/paystack/ Using ``paystack_listen`` ========================= The built-in management command automates all of the above: .. code-block:: bash python manage.py paystack_listen This will: 1. Check that ``cloudflared`` is installed (prints install instructions if not). 2. Start a Cloudflare Quick Tunnel pointing at ``http://localhost:8000``. 3. Extract the generated public URL. 4. Print the complete **Webhook URL** ready to paste into the Paystack Dashboard. Example output: .. code-block:: text Starting Cloudflare Tunnel → http://localhost:8000 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Tunnel URL: https://random-slug-here.trycloudflare.com Webhook URL: https://random-slug-here.trycloudflare.com/webhooks/paystack/ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Next steps: 1. Make sure your Django server is running: python manage.py runserver 2. Add this webhook URL to your Paystack Dashboard: https://random-slug-here.trycloudflare.com/webhooks/paystack/ https://dashboard.paystack.com/settings/developer 3. Webhook signature verification uses your PAYSTACK['SECRET_KEY'] automatically — no extra configuration required. Press Ctrl+C to stop the tunnel. Command Options --------------- .. code-block:: text --host HOST Local server hostname (default: localhost) --port PORT Local server port (default: 8000) --webhook-path PATH Webhook URL path (default: /webhooks/paystack/) Examples: .. code-block:: bash # Custom port python manage.py paystack_listen --port 8080 # Custom host and webhook path python manage.py paystack_listen --host 0.0.0.0 --port 9000 \ --webhook-path /api/v1/webhooks/paystack/ Stopping the Tunnel ------------------- Press **Ctrl+C** in the terminal. The command catches the interrupt signal and cleanly terminates the ``cloudflared`` process. Troubleshooting =============== **"cloudflared is not installed"** Run the install command for your OS (see above) and make sure ``cloudflared`` is on your ``PATH``. **Tunnel starts but Django returns 403 / 400** - Check that your Django server is actually running (``python manage.py runserver``). - If you have IP whitelisting enabled (``PAYSTACK['ALLOWED_WEBHOOK_IPS']``), you may need to add the Cloudflare egress IPs or clear the list during local development. - Ensure ``PAYSTACK['SECRET_KEY']`` matches the key shown in your Paystack Dashboard. **"Connection refused"** The tunnel URL is correct but Django isn't listening on the expected host/port. Make sure ``--port`` matches the port you passed to ``runserver``. .. note:: Cloudflare Quick Tunnels are ephemeral — the URL changes every time you restart the command. This is by design for development use. Do **not** use Quick Tunnels in production.