When you move from managed platforms (Vercel, Supabase, paid APIs) to your own VPS, you trade convenience for cost control. You now do the DevOps, but your monthly bill drops to essentially zero (just the VPS you already have).
1. The Free/Self-Hosted Stack
| Layer | Managed Stack (Before) | Your VPS Stack (Free) | Why the Change |
| Frontend | Next.js on Vercel | Next.js (static export) or React + Vite served by Nginx | Vercel is paid/convenient; Nginx on your VPS is free and faster for static content |
| Reverse Proxy / SSL | Vercel handles it | Nginx + Let's Encrypt (Certbot) | Industry standard, completely free |
| CDN / WAF | Vercel Edge | Cloudflare Free Plan | Genuine free tier with global caching + DDoS protection |
| Backend API | Next.js API Routes | Fastify (Node.js) or FastAPI (Python) in Docker | Lightweight, runs anywhere, easier to debug on VPS |
| Database | Supabase / Neon | PostgreSQL (self-hosted in Docker) | Full control, no row limits |
| Cache | Upstash Redis | Redis (self-hosted in Docker) | Zero cost, unlimited |
| Search | Algolia / paid Meilisearch Cloud | Meilisearch (self-hosted in Docker) | Open-source, runs perfectly in Docker, no per-search fees |
| Process Manager | Vercel auto-scaling | PM2 (for Node) or systemd | Keeps your API alive if it crashes |
| Containers | Serverless functions | Docker Compose | Orchestrates Postgres + Redis + Meilisearch + API on one machine |
| Text Translation | Google Cloud Translation ($$$) | LibreTranslate (self-hosted) + Azure Translator free tier as backup | LibreTranslate is open-source NMT; Azure gives 2M chars/month free |
| Speech-to-Text | Whisper API ($$$) | Browser Web Speech API (client-side, free) + self-hosted faster-whisper (CPU) | Browser API costs nothing; self-hosted Whisper is slow on CPU but works |
| Text-to-Speech | Google TTS / ElevenLabs ($$$) | Browser SpeechSynthesis (free) or Coqui TTS (self-hosted) | Browser voices are instant and free |
| Monitoring | Vercel Analytics / Sentry | Uptime Kuma + Nginx access logs | Free, self-hosted status pages |
2. What Stays the Same
- Next.js still works, but you will likely use
output: 'export' to generate static HTML/JS and let Nginx serve it. This is much faster than running a Node.js server for content pages.
- PostgreSQL + Redis + Meilisearch architecture remains identical — you just run them in Docker instead of paying for managed instances.
- Content strategy (atomic notes, editorial workflow, i18n routing) is unchanged.
- Cloudflare sits in front of your VPS to cache pages globally and absorb traffic spikes.
3. What Changes Radically: Translation
This is the hardest part to do for free. Neural translation and speech recognition are compute-heavy.
Text Translation (Free Options)
| Option | Cost | Quality | Best For |
| LibreTranslate (self-hosted Docker) | $0 | Fair-Good for major languages | Common phrases, menu items, basic communication |
| Argos Translate (LibreTranslate backend) | $0 | Fair | Same as above |
| Azure Translator | 2M characters/month free | Excellent | Safety-critical notes, customs, legal info |
| DeepL Free API | 500k chars/month | Excellent | European/Japanese/Chinese (but missing Malay, Indonesian, Urdu) |
My recommendation:
- Run LibreTranslate on your VPS for instant chat/phrase translation (unlimited, no rate limits).
- Use Azure Translator free tier for pre-translating your curated country notes (2M chars/month is enough for steady content updates).
- For Arabic↔Japanese/Korean/Urdu, LibreTranslate is usable but not perfect. Have a disclaimer: "Community-powered translation — verify critical info."
Speech Translation (Free Options)
| Option | Cost | Latency | Quality |
| Browser Web Speech API | $0 | Instant | Inconsistent across devices; good for English/Arabic/Japanese, poor for Urdu/Indonesian |
| Self-hosted faster-whisper (CPU) | $0 | Slow (2-5x real-time on VPS CPU) | Excellent accuracy |
| Azure Speech STT free tier | 5 audio hours/month | Fast | Production-grade |
My recommendation for a free app:
- Phase 1: Use the Browser Web Speech API entirely. It runs on the user's phone, costs you nothing, and requires zero backend infrastructure. Add a big microphone button.
- Phase 2: If quality complaints arise, proxy audio to your VPS running faster-whisper (small model) as a fallback. Warn users it takes 2-3 seconds.
4. Docker Compose for Your VPS
This single file runs your entire backend on one VPS:
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: tourism
POSTGRES_PASSWORD: your_secure_password
POSTGRES_DB: tourism_db
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432" # Only local access
redis:
image: redis:7-alpine
restart: always
volumes:
- redisdata:/data
ports:
- "127.0.0.1:6379:6379"
meilisearch:
image: getmeili/meilisearch:v1.9
restart: always
environment:
MEILI_MASTER_KEY: your_meili_key
volumes:
- meilisearch:/meili_data
ports:
- "127.0.0.1:7700:7700"
libretranslate:
image: libretranslate/libretranslate:latest
restart: always
environment:
LT_UPDATE_MODELS: "true"
volumes:
- libretranslate:/home/libretranslate/.local
ports:
- "127.0.0.1:5000:5000"
api:
build: ./api # Your Fastify/FastAPI backend
restart: always
environment:
DATABASE_URL: postgres://tourism:your_secure_password@postgres:5432/tourism_db
REDIS_URL: redis://redis:6379
MEILI_URL: http://meilisearch:7700
TRANSLATE_URL: http://libretranslate:5000
depends_on:
- postgres
- redis
- meilisearch
- libretranslate
ports:
- "127.0.0.1:3001:3001"
volumes:
pgdata:
redisdata:
meilisearch:
libretranslate:
Nginx config (/etc/nginx/sites-available/tourism)
server {
listen 80;
server_name yourdomain.com;
# Let's Encrypt SSL (certbot handles this)
# Cache static assets for 1 year
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
root /var/www/tourism/dist;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Serve frontend static export
location / {
root /var/www/tourism/dist;
try_files $uri $uri/ /index.html;
# Cache HTML at Cloudflare edge, not here
add_header Cache-Control "public, max-age=0, must-revalidate";
}
# Proxy API requests
location /api/ {
proxy_pass http://127.0.0.1:3001/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
5. Handling High Traffic on a Single VPS
A $5–$20/month VPS (2–4 vCPU, 4–8GB RAM) can handle surprising traffic if you are disciplined:
| Technique | How |
| Cloudflare caching | Cache country pages at edge for 1 hour. Your VPS sees almost zero requests. |
| Nginx static serving | Pre-built HTML/JS files served directly by Nginx (not Node.js). |
| Redis query cache | Cache the top 100 searches per country. Tourists ask the same questions. |
| Meilisearch | Offloads search from PostgreSQL. Sub-50ms response time. |
| PgBouncer | Add a connection pooler so PostgreSQL doesn't choke during spikes. |
| Rate limiting | Nginx limit_req or Cloudflare rules to prevent abuse. |
| Gzip/Brotli | Nginx compresses responses. |
Realistic capacity: With Cloudflare caching static pages, a single 4GB VPS can serve 50,000–100,000 page views/day easily. The bottleneck becomes translation API calls (if not cached in Redis).
6. The Honest Trade-offs of "Free"
| Feature | Paid Stack | Your Free VPS Stack |
| Monthly cost | ~$200+ | ~$0 (VPS only) |
| DevOps work | Minimal | Moderate (backups, updates, SSL renewal) |
| Translation quality | Excellent (Google/Azure) | Fair-Good (LibreTranslate) |
| Speech translation speed | <1 second | 2–5 seconds (self-hosted CPU) or browser-dependent |
| Uptime responsibility | Vercel/Supabase | You (3 AM server crashes) |
| Scaling | Click button | Manual (bigger VPS or add servers) |
7. Recommended Build Order (Free VPS Path)
- Week 1: Docker Compose (Postgres + Redis + Meilisearch) + Nginx + static React/Vite frontend
- Week 2: Content schema + seed 10 countries from Wikivoyage (with attribution)
- Week 3: Meilisearch indexing + language routing + RTL support
- Week 4: LibreTranslate container + text translation widget
- Week 5: Browser Web Speech API integration (microphone button)
- Week 6: Cloudflare caching + PgBouncer + rate limiting
- Week 7: Load testing + monitoring (Uptime Kuma)
Bottom Line
No, it is not the same stack — but it is the same architecture. You swap managed services for self-hosted Docker containers and accept lower translation quality (or strict free-tier API limits) in exchange for zero recurring platform costs.
If your VPS has at least 4GB RAM, this is absolutely viable for a free tourism app. If it is a 1GB VPS, drop Meilisearch and use PostgreSQL full-text search instead to save memory.
Do you want the full docker-compose.yml with a pre-configured LibreTranslate image, or a deployment script that automates Nginx + SSL + Docker on your VPS?
١. المقدمة: هل يبقى نفس المكدس التقني؟
الإجابة المختصرة: لا. المفاهيم المعمارية تبقى كما هي، لكن الأدوات يجب أن تتغير. عند الانتقال من المنصات المُدارة (مثل Vercel وSupabase) إلى خادم VPS خاص بك، فأنت تتنازل عن الراحة مقابل التحكم الكامل في التكاليف. الفاتورة الشهرية تنخفض إلى صفر تقريبًا (ما عدا تكلفة الـVPS التي تمتلكه بالفعل).
٢. المكدس التقني المجاني بالكامل على VPS
| الطبقة | المكدس المُدارة (المدفوع) | مكدس الـVPS المجاني | سبب التغيير |
| الواجهة الأمامية | Next.js على Vercel | Next.js (تصدير ثابت) أو React + Vite يخدمه Nginx | Vercel مدفوع/سهل؛ Nginx على VPS مجاني وأسرع للمحتوى الثابت |
| البوابة العكسية / SSL | يديره Vercel | Nginx + Let's Encrypt (Certbot) | معيار الصناعة، مجاني بالكامل |
| شبكة توصيل المحتوى (CDN) | Vercel Edge | خطة Cloudflare المجانية | طبقة مجانية حقيقية مع تخزين مؤقت عالمي + حماية من هجمات DDoS |
| واجهة برمجة التطبيقات (API) | مسارات Next.js API | Fastify (Node.js) أو FastAPI (Python) داخل Docker | خفيف الوزن، يعمل في أي مكان، أسهل في التصحيح على VPS |
| قاعدة البيانات | Supabase / Neon | PostgreSQL (مستضاف ذاتيًا داخل Docker) | تحكم كامل، بدون حدود للصفوف |
| ذاكرة التخزين المؤقت | Upstash Redis | Redis (مستضاف ذاتيًا داخل Docker) | تكلفة صفر، بدون قيود |
| محرك البحث | Algolia / Meilisearch المدفوع | Meilisearch (مستضاف ذاتيًا داخل Docker) | مفتوح المصدر، يعمل بكفاءة في Docker، بدون رسوم لكل عملية بحث |
| مدير العمليات | التوسع التلقائي في Vercel | PM2 (لـNode) أو systemd | يبقي واجهة البرمجة نشطة إذا تعطلت |
| الحاويات | دوال Serverless | Docker Compose | يدير PostgreSQL + Redis + Meilisearch + API على آلة واحدة |
| ترجمة النصوص | Google Cloud Translation (مدفوع) | LibreTranslate (مستضاف ذاتيًا) + الطبقة المجانية من Azure Translator كاحتياط | LibreTranslate مفتوح المصدر؛ Azure يعطي ٢ مليون حرف شهريًا مجانًا |
| التحويل من كلام إلى نص (STT) | Whisper API (مدفوع) | Web Speech API في المتصفح (جانب العميل، مجاني) + faster-whisper مستضاف ذاتيًا (CPU) | واجهة المتصفح لا تكلف شيئًا؛ Whisper الذاتي بطيء على المعالج لكنه يعمل |
| التحويل من نص إلى كلام (TTS) | Google TTS / ElevenLabs (مدفوع) | SpeechSynthesis في المتصفح (مجاني) أو Coqui TTS (مستضاف ذاتيًا) | أصوات المتصفح فورية ومجانية |
| المراقبة | Vercel Analytics / Sentry | Uptime Kuma + سجلات وصول Nginx | مجاني، صفحات حالة مستضافة ذاتيًا |
٣. ما الذي يبقى كما هو؟
- Next.js لا يزال يعمل، لكنك ستستخدم على الأرجح
output: 'export' لتوليد ملفات HTML/JS ثابتة وترك Nginx يخدمها. هذا أسرع بكثير من تشغيل خادم Node.js لصفحات المحتوى.
- البنية المعمارية لـPostgreSQL + Redis + Meilisearch تبقى متطابقة — الفرق الوحيد أنك تشغّلها في Docker بدلًا من دفع ثمن النسخ المُدارة.
- استراتيجية المحتوى (الملاحظات الذرية، سير العمل التحريري، توجيه اللغات) لا يتغير.
- Cloudflare يجلس أمام VPS لتخزين الصفحات عالميًا وامتصاص الذروات المرورية.
٤. ما الذي يتغير جذريًا: الترجمة
هذا هو الجزء الأصعب في المشروع المجاني. الترجمة العصبية والتعرف على الكلام يتطلبان قوة حوسبة هائلة.
| الخيار | التكلفة | الجودة | الأفضل لـ |
| LibreTranslate (Docker مستضاف ذاتيًا) | ٠ دولار | جيدة-مقبولة للغات الرئيسية | العبارات الشائعة، عناصر القائمة، التواصل الأساسي |
| Argos Translate (الخلفية التي يعمل عليها LibreTranslate) | ٠ دولار | مقبولة | نفس ما سبق |
| Azure Translator | ٢ مليون حرف شهريًا مجانًا | ممتازة | الملاحظات الحرجة، العادات، المعلومات القانونية |
| DeepL Free API | ٥٠٠ ألف حرف شهريًا | ممتازة | اللغات الأوروبية/اليابانية/الصينية (لكنه يفتقد الملايو والإندونيسية والأردو) |
توصيتي: شغّل LibreTranslate على VPS للترجمة الفورية في الدردشة (غير محدود). استخدم الطبقة المجانية من Azure Translator لترجمة ملاحظات البلدان المُحكَّمة مسبقًا (٢ مليون حرف شهريًا). للعربية ↔ اليابانية/الكورية/الأردو ضع إخلاء: «ترجمة مجتمعية — راجع المعلومات الحرجة.»
| الخيار | التكلفة | السرعة | الجودة |
| Web Speech API في المتصفح | ٠ دولار | فورية | متفاوتة بين الأجهزة؛ جيدة للإنجليزية/العربية/اليابانية، ضعيفة للأردو/الإندونيسية |
| faster-whisper مستضاف ذاتيًا (CPU) | ٠ دولار | بطيئة (٢-٥ أضعاف الزمن الحقيقي على معالج VPS) | دقة ممتازة |
| Azure Speech STT المجاني | ٥ ساعات صوتية شهريًا | سريعة | جودة إنتاجية |
توصيتي لتطبيق مجاني: المرحلة الأولى Web Speech API بالكامل على هاتف المستخدم + زر ميكروفون كبير. المرحلة الثانية: إن وُجدت شكاوى جودة، وجّه الصوت إلى faster-whisper (النموذج الصغير) وحذّر أن ذلك يستغرق ٢–٣ ثوانٍ.
٥. شرح ملف Docker Compose لخادمك الخاص
الفكرة العامة: ملف يُخبر Docker أن يشغّل خمس خدمات متصلة:
- PostgreSQL: صورة Alpine خفيفة. مستخدم
tourism وقاعدة tourism_db. Volume حتى لا تُفقد البيانات. المنفذ ٥٤٣٢ محلي فقط.
- Redis: كاش لنتائج البحث والجلسات والترجمات المتكررة. المنفذ ٦٣٧٩ محلي.
- Meilisearch: محرك بحث مفتوح المصدر + Master Key. المنفذ ٧٧٠٠ محلي.
- LibreTranslate: ترجمة عصبية، تنزّل النماذج عند أول تشغيل. المنفذ ٥٠٠٠ محلي.
- API: Fastify أو FastAPI يتصل بالخدمات الأربع. المنفذ ٣٠٠١ محلي.
الفائدة: docker-compose up يشغّلها معًا على شبكة Docker الداخلية. الكود كما في النسخة الإنجليزية أعلاه (نفس الملف حرفيًا).
٦. شرح إعداد Nginx كبوابة عكسية
- الملفات الثابتة: Nginx يبحث في
/var/www/tourism/dist. الأصول (صور، خطوط، JS) تُكاش في المتصفح سنة.
- طلبات API: أي مسار يبدأ بـ
/api/ يُمرَّر إلى المنفذ ٣٠٠١ مع رؤوس Host وX-Real-IP.
- SSL: Certbot / Let's Encrypt شهادة مجانية تُجدَّد كل ٩٠ يومًا.
٧. الزيارات العالية على VPS واحد
خادم بـ ٥–٢٠ دولار شهريًا (٢–٤ أنوية، ٤–٨ جيجابايت رام) يكفي إن التزمت: كاش Cloudflare لصفحات البلدان ساعة، Nginx للثابت لا Node، Redis لأعلى ١٠٠ بحث لكل بلد، Meilisearch أقل من ٥٠ مللي ثانية، PgBouncer، تحديد معدل، Gzip/Brotli.
القدرة الواقعية: VPS بـ٤ جيجابايت مع كاش Cloudflare يخدم ٥٠٬٠٠٠ إلى ١٠٠٬٠٠٠ مشاهدة/يوم. الاختناق يصبح استدعاءات الترجمة إن لم تُكاش في Redis.
٨. المقايضات الصادقة
التكلفة ~٢٠٠+ دولار مقابل ~٠ (VPS فقط). DevOps قليلة مقابل متوسطة. جودة ترجمة ممتازة مقابل جيدة-مقبولة. سرعة كلام أقل من ثانية مقابل ٢–٥ ثوانٍ. التشغيل على Vercel/Supabase مقابل أنت (تعطل الثالثة فجرًا). توسع بزر مقابل يدوي.
٩. ترتيب البناء (٧ أسابيع)
- الأسبوع الأول: Docker Compose (PostgreSQL + Redis + Meilisearch) + Nginx + واجهة React/Vite ثابتة
- الأسبوع الثاني: مخطط قاعدة البيانات + إدخال ١٠ بلدان من Wikivoyage (مع الإسناد)
- الأسبوع الثالث: فهرسة Meilisearch + توجيه اللغات + دعم RTL
- الأسبوع الرابع: حاوية LibreTranslate + أداة ترجمة النصوص
- الأسبوع الخامس: دمج Web Speech API (زر الميكروفون)
- الأسبوع السادس: تخزين Cloudflare + PgBouncer + تحديد المعدل
- الأسبوع السابع: اختبار الحمل + المراقبة (Uptime Kuma)
١٠. الخلاصة
لا، ليس نفس المكدس التقني — لكنها نفس البنية المعمارية. تستبدل الخدمات المُدارة بحاويات Docker، وتقبل جودة ترجمة أقل (أو حدود الطبقات المجانية) مقابل تكاليف منصة صفر.
إن كان الـ VPS ٤ جيجابايت رام على الأقل فالمسار قابل للتطبيق. إن كان ١ جيجابايت فقط، أزل Meilisearch واستخدم البحث النصي الكامل في PostgreSQL.