Chapter 01 · Section III · 24 min read
Your first Nepal-hosted deployment
From 'runs on my laptop' to 'runs on a real URL a real user can visit.' Containerise, deploy to a hosted platform, connect a domain, and expose a Nepal-serving endpoint. The day-one deployment playbook for AI projects.
The service runs on your laptop. Close the lid, and the service is gone. To become a real thing, it must run on a computer that is always on, has power and internet, and is reachable at a URL. This section is the smallest honest path from “works locally” to “runs at nepse-mitra.example.np” — the day-one deployment playbook for AI projects in Nepal.
The three moving parts
Every deployment has three parts:
- The build. Your code, its dependencies, and its runtime, packaged into something reproducible — usually a Docker container.
- The host. A machine (physical or cloud) that runs the container 24/7. In 2026, this is almost always a managed platform (Fly.io, Railway, Render, DigitalOcean App Platform) or a cloud provider (AWS, GCP).
- The address. A URL that points to the host. For a real product, a custom domain (
your-app.npor a subdomain).
We’ll walk through each in turn.
Step 1 — Containerise
A Docker container is a small, reproducible bundle of your app: code, Python version, dependencies, config. Any machine with Docker installed can run it identically.
A minimal Dockerfile for the service from Section 1.2:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY service.py .
EXPOSE 8000
CMD ["uvicorn", "service:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
And requirements.txt:
fastapi==0.115.0
uvicorn[standard]==0.30.0
anthropic==0.40.0
python-dotenv==1.0.0
slowapi==0.1.9
pydantic==2.9.0
Pin your versions. This is not a preference — this is how you keep “works on my laptop” and “works on production” the same.
Build the image:
docker build -t nepse-mitra:v0.1 .
Run it locally:
docker run -p 8000:8000 --env-file .env nepse-mitra:v0.1
Curl the same endpoints as before. Same behavior. The difference: it now runs identically on any machine.
Step 2 — Pick a host
Where you deploy matters. Options, in rough order of complexity:
Managed platforms — recommended for day 1.
- Fly.io — Docker-native, generous free tier, deploys to nearby regions (Singapore/Mumbai serve Nepal well). Commands:
flyctl deploy. Ideal for small AI services. - Railway — very smooth developer experience,
git pushto deploy. Similar pricing. - Render — mature platform, less Docker-native but very simple.
- Google Cloud Run — pay-per-request; scales to zero when idle. Great for low-traffic services.
IaaS (Infrastructure as a Service) — for later.
- DigitalOcean droplets or AWS EC2 — you manage the machine, install Docker, set up nginx, handle updates. More control, more work.
Nepal-hosted options.
- Nepali cloud providers exist (WorldLink, Vianet enterprise) but their Docker/serverless offerings are limited as of 2026. For latency reasons, Singapore or Mumbai is close enough to Nepal (round-trip ~80-100 ms).
For a first Nepal-facing AI service, Fly.io in Singapore is usually the right call. Latency is good, the free tier is real, and deployment is one command.
Step 3 — Deploy
With Fly.io as an example:
# One-time setup
brew install flyctl # or: curl -L https://fly.io/install.sh | sh
flyctl auth login
flyctl launch # creates fly.toml interactively
The flyctl launch command reads your Dockerfile, asks a few questions, and writes a fly.toml. Choose region: sin (Singapore) or bom (Mumbai) for Nepal-serving traffic.
Add your API keys as secrets:
flyctl secrets set ANTHROPIC_API_KEY=sk-ant-...
flyctl secrets set OPENAI_API_KEY=sk-...
Then:
flyctl deploy
Two minutes later, the platform outputs something like:
Deployed successfully.
Visit: https://nepse-mitra.fly.dev
Curl the URL:
curl https://nepse-mitra.fly.dev/summarise \
-H "Content-Type: application/json" \
-d '{"text": "...", "max_sentences": 2}'
It works. Your service is live.
Step 4 — A real domain
nepse-mitra.fly.dev is a demo URL. For a real product, you want your own domain (nepse-mitra.np, or a subdomain like api.nepse-mitra.np).
The two-step process:
-
Register the domain. For a
.npdomain, register through Mercantile or another accredited Nepali registrar (Rs 1,500/year for individual TLDs like$10/year)..com.np; higher for premium namespaces). For an international.com, use Namecheap or Cloudflare ( -
Point the domain at the host. In your DNS provider’s dashboard, add an
Arecord (orCNAME) pointing your domain to the platform. Fly.io provides exact instructions inflyctl certs create nepse-mitra.np. Wait 15 minutes for DNS to propagate.
Fly.io (like all modern platforms) will provision an SSL certificate automatically via Let’s Encrypt. You get HTTPS for free.
Done. https://nepse-mitra.np returns your summariser API.
Step 5 — Verify from Nepal
Latency matters. From a Kathmandu connection, curl your endpoint:
time curl -s https://nepse-mitra.np/hello
Expect ~150-300 ms round trip if you’re on Singapore or Mumbai. Anything above 500 ms suggests the request is being routed the long way around; check region settings on your host.
For the model call itself, add another ~800-1500 ms (Anthropic/OpenAI response time). Total end-to-end from Nepal for a summariser call: 1-2 seconds. Acceptable for most UI flows.
If you serve a product where sub-second responses matter (interactive chat), consider streaming responses (covered in Course 04 Section 1.2) so the user sees output start immediately.
What you now have
A deployed AI system with all the day-one essentials:
- Reproducible build (Docker).
- Always-on host (managed platform).
- Real URL (custom domain).
- HTTPS by default (Let’s Encrypt).
- Nepal-acceptable latency (regional host).
- Secrets stored securely (platform secrets).
- Restart on crash (platform-managed).
This is a shipped service. It is small — one endpoint, one model, one worker pool — but it is real. External users can reach it. It runs when you close your laptop. It restarts if it crashes. It bills against your usage.
Everything from here builds on top of this shape.
Deploy discipline
Three habits worth building from day one:
-
Deploy on every meaningful change. Not once a month. Small, frequent deploys keep the pipeline healthy and let you catch problems while they’re small. Every platform above supports
flyctl deploy/git pushdeploys in seconds. -
Use a staging environment. For anything user-facing, run two versions:
nepse-mitra.np(production) andstaging.nepse-mitra.np(where you test the next version). Never deploy directly to production without a test on staging first. -
Version your deploys. Tag each deploy with a version (
v0.1,v0.2.1) or a git SHA. Your platform likely does this automatically. When something breaks, you can roll back to a known-good version in one command.
What comes next
You have a service. It runs. It has a URL. But it happily calls the LLM on every request without checking cost. Chapter 2 is where the wallet story begins: the true cost of every call, budget caps, quotas, and caching — so your beautiful deployed service does not turn into an surprise Rs 50,000 monthly bill on the first day of viral traffic.