Use this when deciding how to host something that needs a public URL (webhooks, a Telegram bot, an API), without paying, and without handing over a credit card anywhere.
Steps
- Run the service locally in Docker, exposing it on a local port (e.g.
5678). - Use ngrok's free tier to tunnel that port to a stable public domain, no card required, no timeout on the endpoint.
- Point whatever needs to reach it (a webhook URL, a bot's callback config) at that ngrok domain instead of a cloud IP.
- Set the local service to auto-restart with Docker, and the tunnel to auto-launch on machine login, so the whole thing survives a reboot without manual intervention.
Gotcha
Most "free" cloud hosting either requires a card for identity verification (common with big providers, even though you won't be charged unless you upgrade) or sleeps after a period of inactivity, adding a delay before the first request wakes it back up. Running locally with a tunnel avoids both problems entirely, at the cost of the service only being reachable while your machine is on and connected.
For a personal project that doesn't need true 24/7 uptime independent of your own machine, this tradeoff is usually worth it. For something that needs to run even when your laptop is off, a paid or card-verified cloud option becomes the more honest choice.
Quick reference
Local service (Docker, restart: unless-stopped)
+
Free tunnel (ngrok, permanent domain)
=
Public URL, $0, no card, works as long as the machine is on