Building & Deploying AI Apps: Infrastructure Guide (VPS, Security, Monitoring, Costs)

Published: December 27, 2025

I build AI & automation tools and manage VPS, DNS, security, databases, auth, infra - the full chain. Working setups below - for data scientists, analysts, and small businesses deploying their own tools.

30+ live AI & Automation apps. Open source, publicly available on this site tigzig.com

Fourth in my 2025 learnings series on building and deploying AI apps. full cycle of AI apps from build to live deployment.


STRATEGIC CHOICES

Skipped AWS and Azure

Too expensive, too complicated for my needs. These are aircraft carriers. My requirements fit a Toyota.

I work with small businesses. Don't need 'Enterprise Level' or 'At Scale' yet. When that changes, I'll move. Until then, simpler providers work fine.

I keep small AWS/Azure instances running for client testing and compatibility checks. But my production apps run elsewhere.

Hetzner as primary VPS

Chose Hetzner for clean UI, solid performance, straightforward pricing, simple setup.

Server that I use to host tigzig.com backend - CAX21 (ARM-based)

Currently hosting:


SECURITY : SERVER & FRONTEND

Defended a bot attack with Fail2ban

A few months after setup, got hit with a bot attack - rotating proxies, thousands of SSH login attempts. Server load spiked, had to restart.

I already had Fail2ban running but with loose parameters. Tightened the config:

Current Fail2ban settings:

Results after tightening:

Attack stopped. No issues since.

Layered firewall with UFW

Hetzner has built-in firewall. I added UFW (Uncomplicated Firewall) on the server following the video guide, but in hindsight Hetzner firewall alone is sufficient - this was redundant.

UFW config:

SSH hardening

Password auth completely disabled. Root login via SSH keys only.

SSH config:

No password = no brute force risk.

Automatic security updates enabled

unattended-upgrades package installed and active. Security patches apply automatically. One less thing to monitor.

Three baseline security rules for every backend

  1. CORS: configured per use case (sometimes loose, sometimes strict - depends on app)
  2. Rate limiting: SlowAPI middleware, default limits on all endpoints
  3. API keys: for non-browser access (programmatic clients)

Browser access = CORS check. Non-browser = API key required.


Frontend Security: API Keys

Environment variables in React get bundled into client build - visible to anyone. Not secure for API keys or backend endpoints.

Solution: Server-side execution

1. Vercel API Routes (for quick tasks <5 min)
Serverless functions run server-side. Frontend calls your route, which holds sensitive variables and makes external API calls. Keys stay hidden. 5-minute execution limit on free tier.

2. Polling (what I use for long tasks)
Route initiates job, returns ID. Frontend polls status every 10-15 seconds via separate route. Backend processes however long needed - no timeout. Requires job queue and status endpoints.

3. Full server-side rendering (client case)
One client: PHP with server-side rendering. All processing happens server-side. Browser sees rendered HTML only. No React, no exposure issues.

4. Self-hosted options (haven't tried)
Next.js SSR on Vercel still hits 5-minute limit. Self-hosted Next.js on Coolify - no timeout, continuous Node server. FastAPI on Coolify works similarly.


Authentication: Auth0 currently, exploring Clerk

Some apps need user auth. Using Auth0 now - works but can get complicated with callback URLs and React frontend integration. Exploring Clerk as alternative but haven't tested yet.


DEPLOYMENT & HOSTING

Coolify = self-hosted Render

Point to GitHub repo, Coolify deploys each backend in its own Docker container. Seamless.

Each FastAPI backend gets isolated container, auto-restarts on crash, logs accessible via UI.

Flowise via docker custom image

Deployed Flowise via a custom docker image built for ARM64 architecture of my Hetzner server, as the official Flowise image was for AMD64 (x86). Manually triggered via Github Actions.

n8n via docker compose

n8n via a docker compose - UI worked fine through the reverse proxy, but webhooks weren't reachable from outside - external services couldn't callback to my n8n instance. The fix required a few changes to the compose file:

Vercel for frontends

40+ UIs on Vercel free tier. Fast, reliable, zero config deployments. No reason to self-host static frontends when Vercel does it better.

This guide walked me through the entire security hardening process: https://www.youtube.com/watch?v=taJlPG82Ucw

I could have used an AI coder with CLI access now, but when I set this up, this video + ChatGPT got me through it step-by-step.


DNS, DOMAIN & CLOUDFLARE

Keep domain registrar separate from DNS

Domains registered on: Namecheap or GoDaddy
DNS management: Cloudflare

Reason: If Cloudflare has issues, I can quickly point DNS elsewhere. If registrar has issues, DNS still works.

Migrated 100+ DNS records to Cloudflare

Migration was seamless. Cloudflare lets you import/export DNS record files. Moved everything in one shot.

DNS management is straightforward

Set routing rules, configure caching, manage SSL - all in one dashboard. Clean UI.

I'm using a fraction of what Cloudflare can do, but what I use works well.

Cloudflare proxy: 100-second timeout limit

Free tier has 100-second timeout for proxied requests.

Problem: Some of my backends run 5-10 minutes (heavy data processing, large file uploads).

Solution: Remove those endpoints from Cloudflare proxy, point directly to server. Manage security at FastAPI level (CORS, rate limits, API keys).

Most backends are proxied. Long-running ones are direct.

Free tier SSL: one subdomain level only

Cloudflare free tier handles SSL for:

But NOT for:

Multi-level subdomains require paid tier for SSL certificates. Plan accordingly.

Caching rules for static content

Set up custom cache rules for:

After deploying new blog posts, I run a cache purge + warm script. Purges old cache, warms new content. Users see updates immediately instead of waiting for TTL expiry.

Cloudflare caching for large files

Some apps serve 1GB+ datasets. Hosting on Hetzner gives decent speed. Hosting via Cloudflare cache gives better speed. Files still live on my server, but Cloudflare edge caching improves delivery.


MONITORING

Built a custom app for monitoring all my FastAPI backends.

Frontend: React dashboard

Built simple React dashboard to view:

Deployed on Vercel. Pulls from Neon database.

Created PyPI package for API logging

Built custom FastAPI middleware: tigzig-api-monitor

Published to PyPI: https://pypi.org/project/tigzig-api-monitor/

Why a package? I was copying the same logging code across 30+ backends. Package = import once, use everywhere.

What the package collects

IP hashing = no PII stored

IPs are hashed before storage. Can't reverse-engineer original IP. Privacy by design.

Geolocation tracking: done separately using GeoLite2 free database. Not very accurate, but works for basic country-level tracking.

Non-blocking async logging

Logging happens asynchronously. API requests don't wait for log writes. If logging fails, API still works.

Database: PostgreSQL on Neon

All API logs go to PostgreSQL on Neon.com.

Neon free tier: 40-50 projects, 500MB each. Perfect for log storage across multiple apps. Currently on paid tier temporarily for higher limits, but free tier worked fine for months.

Web analytics: PostHog

Migrated from StatCounter to PostHog.

StatCounter fine for low traffic. With increasing visitors, needed better dashboards and event tracking.

PostHog setup: cloud version, free tier. Easy to configure, customizable dashboards.

Brevo for automated emails

Email not a major requirement for my apps. Occasionally need notification emails (user action triggers alert to me).

Using Brevo free tier. Works fine for low-volume transactional emails. Not using for campaigns or marketing - just automated notifications.


SELF-BUILT TOOLS

Blog automation: markdown to HTML pipeline

Used to host blog on managed service. Migrated out. Now self-hosted with custom pipeline.

Process:

  1. Write in markdown
  2. Run script - script converts markdown → styled HTML
  3. Purge + warm Cloudflare cache

Default to custom tools now

Earlier, I'd use a microservice or SaaS tool for file conversion, scraping, monitoring. Now I just build it. FastAPI backend + React frontend + deploy via Coolify. Easier to maintain, no vendor dependencies, full control.

Examples:

Total build time with AI coders: few hours to a day for simpler tools. More for complex ones. Maintenance: minimal.


BACKUP STRATEGY

Hetzner 7-day backups enabled

Automatic snapshots, 7-day retention. Costs extra but worth it.

Backups exist. Haven't needed them yet. Should test restoration process - haven't done it.

No comprehensive backup strategy

Don't have mirror site or off-site backups. Everything critical is in Git repos.

This is a gap. Should improve. Haven't prioritized it yet.


COSTS

Hetzner VPS: €7.69/month

Includes 7-day backups. Hosting 30+ backends, n8n, Coolify. Still 30% capacity left.

AWS: ~$5/month for shut-off instances

I maintain an EC2 instance and MySQL RDS for client testing. Both stay shut off unless needed (few times a month).

Still get charged ~$5/month for baseline costs - IP allocation, DNS, other AWS oddities. Small price to keep testing environment ready.

Vercel: Free tier

40+ React frontends. No cost.

Neon PostgreSQL: Free tier (currently paid)

Was on free tier for months. Temporarily on paid for higher limits. Will likely drop back to free.

Cloudflare: Free tier

DNS, caching, basic security. No cost.

PostHog: Free tier

Web analytics. No cost.

Brevo: Free tier

Email notifications. No cost.

Claude Code Max: $100/month - biggest cost, worth every penny

This is like having a team of developers. Cloud engineering, Python, FastAPI, React - covered.

With CLI and API access, it now manages GitHub workflows, server operations, deployment scripts. I barely touch the command line manually anymore.

Worth it? Absolutely. $20 keeps servers running. $100 gives me a full dev team. The multiplier is massive.


KEY TAKEAWAYS

Start simple, scale when needed

Don't jump to AWS/Azure until you actually need their scale. Smaller providers work fine for most use cases.

Security is not optional

Fail2ban, SSH hardening, automatic updates. Set these up early. Defending attacks after the fact is painful.

Self-host what you can, use SaaS where it's better

VPS + deployments = Hetzner + Coolify
Frontends = Vercel
Databases = Neon
DNS/CDN = Cloudflare

Pick the right tool for each layer.

Build custom tools when you need control

Blog automation, API monitoring, file processing - built custom. Took hours with AI coders, now fully under my control.

Test your backups

I haven't. Should. Don't be me.


RESOURCES

Hetzner + Coolify setup guide:
https://www.youtube.com/watch?v=taJlPG82Ucw

Live apps (30+ micro-apps): Open Source - Hit 'Docs' for source codes tigzig.com