[{"data":1,"prerenderedAt":198},["ShallowReactive",2],{"seo-verification":3,"blog-hosting-appwrite-on-a-vps-ma-en":6,"promo-bar-likely":197},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-hosting-appwrite-on-a-vps-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":139,"ctaBody":140,"ctaButton":141,"ctaUrl":142,"relatedPosts":143},61,"hosting-appwrite-on-a-vps",{"fr":12,"en":10,"ar":13,"es":14},"heberger-appwrite-vps","استضافة-appwrite-على-خادم-vps","alojar-appwrite-en-un-vps","Hosting Appwrite on a VPS: complete self-hosted guide","Deploy Appwrite on your VPS with Docker: full stack, Traefik SSL, backups, hardening, and Supabase comparison.",10,1,false,"2026-04-20T00:00:00+00:00","2026-09-19T02:00:43+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},6,"Databases","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fheberger-appwrite-vps-poster.svg",{"categorySlug":34,"appSlug":35},"databases","appwrite","Appwrite is an open source backend-as-a-service designed for web and mobile developers: document database, authentication, file storage, serverless functions, and messaging. Self-hosting it on a VPS gives you a complete self-hosted backend, with multi-platform SDKs and no usage-based billing. This guide covers installation, Traefik configuration, production hardening, and backups — from A to Z.",[38,42,54,57,60,82,85,88,132,136],{"type":39,"title":40,"body":41},"h2","Why self-host Appwrite on a VPS","Appwrite brings together in a single platform everything an application needs on the server side: authentication with more than 30 OAuth methods, a document database with granular permissions, file storage with image transformation, serverless functions in several languages, and messaging. Its cloud version bills per usage and per resources; by self-hosting on a VPS, you deploy the whole thing via Docker and drive it from an elegant web console, with no cap.\n\nIt's particularly suited to Flutter, React Native, or web developers who want a ready-to-use backend with official SDKs, while keeping the data and logic on their own infrastructure. You control the functions, the API keys, and the permissions, and you scale at your own pace — without being subject to the quotas or price increases of a public cloud.",{"type":43,"title":44,"items":45},"ul","The concrete benefits of a self-hosted Appwrite",[46,47,48,49,50,51,52,53],"All-in-one backend: Auth, Databases, Storage, Functions, and Messaging in a single console.","Official SDKs for Flutter, React Native, Web, Android, iOS, Node, Python, and more.","More than 30 built-in OAuth providers (Google, GitHub, Apple...) with no code.","Self-hosted serverless functions: run your business logic without an external service.","Granular permissions at the document and collection level, managed from the console.","No billing per execution and no user quota: a fixed VPS plan.","Data hosted on your own infrastructure: simplified GDPR compliance, no third-party cloud dependency.","Built-in Realtime: subscribe to changes in documents, files, and session state via WebSocket.",{"type":39,"title":55,"body":56},"Internal architecture: what Docker actually launches","Before installing, it helps to know what Appwrite orchestrates. The official installer generates a `docker-compose.yml` with at least twenty services:\n\n- **appwrite** — the main API server (PHP, exposed on port 80\u002F443 via Traefik).\n- **appwrite-console** — the web administration console (React, served at the same domain on `\u002F`).\n- **appwrite-realtime** — the WebSocket service for real-time subscriptions.\n- **appwrite-worker-*** — a series of workers for asynchronous tasks: sending e-mails, outbound webhooks, temporary file cleanup, etc.\n- **appwrite-executor** — the serverless Functions execution runtime (Docker-in-Docker).\n- **mariadb** — the internal relational database (users, projects, permission rules).\n- **redis** — the cache and task queue (worker jobs, sessions, rate-limiting).\n- **traefik** — the built-in reverse proxy that handles HTTPS routing and Let's Encrypt certificates.\n\nFor a development VPS, only the `core` node is strictly necessary: API, Console, MariaDB, Redis, and Traefik. The workers and executor are indispensable in production if you use Functions, webhooks, or e-mail sending. **Count on at least 4 GB of RAM for this full stack**: MariaDB and the background workers share the available memory, and each Function invocation starts its own ephemeral container.",{"type":39,"title":58,"body":59},"Hardware and software prerequisites","For a development or test instance, 2 vCPU and 4 GB of RAM with 40 GB of SSD are enough. For production with active serverless functions and several client apps, aim for 4 vCPU, 8 GB of RAM, and 80 GB of SSD — each Function invocation starts its own ephemeral container, which puts pressure on disk and CPU.\n\nOn the software side: Ubuntu 22.04 or 24.04 LTS, Docker CE and Docker Compose v2 (Appwrite manages its own Traefik for routing and SSL), and a domain name pointing to the VPS IP — for example `api.myapp.com`. Ports 80 and 443 must be free and open in `ufw` for Traefik to obtain the Let's Encrypt certificates via the ACME challenge.\n\n**A note on storage.** Functions generate intermediate Docker images that accumulate on the SSD. Without regular pruning, an instance running for several months can saturate its disk. Plan a weekly `docker system prune --volumes -f` cron task, and monitor free space with `df -h`.",{"type":61,"title":62,"steps":63},"steps","Deploying self-hosted Appwrite with Docker",[64,67,70,73,76,79],{"title":65,"body":66},"Prepare the VPS and open the ports","Install Docker CE and Docker Compose v2, then open the required ports:\n\n```bash\nufw allow 80\u002Ftcp\nufw allow 443\u002Ftcp\nufw enable\n```\n\nPoint your domain (e.g., `api.myapp.com`) to the VPS IP via an A record. Wait for DNS propagation before running the installer — Traefik needs the domain to resolve correctly in order to pass the ACME challenge.",{"title":68,"body":69},"Run the official interactive installer","Run the installer with one command:\n\n```bash\ndocker run -it --rm \\\n  --volume \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock \\\n  --volume \"$(pwd)\"\u002Fappwrite:\u002Fusr\u002Fsrc\u002Fcode\u002Fappwrite:rw \\\n  --entrypoint=\"install\" \\\n  appwrite\u002Fappwrite\n```\n\nThe wizard asks for the main domain, HTTP port (80), HTTPS port (443), an e-mail for Let's Encrypt, and a few options. It generates a `docker-compose.yml` and a `.env` file with randomly generated secrets. **Do not change these secrets by hand** — modify them only via the environment variables in `.env`.",{"title":71,"body":72},"Verify the domain and SSL configuration","After startup (`docker compose up -d`), wait 30 to 60 seconds for Traefik to issue the certificate. Check:\n\n```bash\ncurl -I https:\u002F\u002Fapi.myapp.com\u002Fv1\u002Fhealth\n```\n\nThe response should be `HTTP\u002F2 200` with a `content-type: application\u002Fjson`. If Traefik does not yet have a certificate, you'll get a TLS error — this is normal during the first few seconds. If it persists, check that ports 80\u002F443 are not filtered by an upstream firewall and that the domain resolves to the correct IP (`dig api.myapp.com`).",{"title":74,"body":75},"Create the administrator account and the first project","Open `https:\u002F\u002Fapi.myapp.com` in your browser. Appwrite invites you to create the root administrator account on first access — this account is the only one with access to platform settings. From the console, create a project, add a platform (Web, Flutter, Apple…) by declaring the allowed hostname, and retrieve the project ID. This information feeds the client-side SDK initialization:\n\n```bash\nnpm install appwrite\n```\n\n```bash\nimport { Client } from 'appwrite';\nconst client = new Client()\n  .setEndpoint('https:\u002F\u002Fapi.myapp.com\u002Fv1')\n  .setProject('\u003Cyour-project-id>');\n```",{"title":77,"body":78},"Harden the production configuration","Open the `.env` file generated by the installer and adjust the following variables:\n\n- `_APP_OPTIONS_ABUSE=enabled` — activates built-in per-IP rate-limiting.\n- `_APP_OPTIONS_FORCE_HTTPS=enabled` — redirects all HTTP requests to HTTPS.\n- `_APP_SMTP_HOST` \u002F `_APP_SMTP_PORT` \u002F `_APP_SMTP_SECURE` \u002F `_APP_SMTP_USERNAME` \u002F `_APP_SMTP_PASSWORD` — configure your SMTP relay for verification and password-reset e-mails.\n- `_APP_CONSOLE_WHITELIST_ROOT=disabled` if you want to allow open registration to the console (not recommended in prod); leave it on `enabled` and fill in `_APP_CONSOLE_WHITELIST_EMAILS` with the authorized addresses.\n\nRestart the services after modification: `docker compose up -d`.",{"title":80,"body":81},"Configure automated backups","Two Docker volumes hold all of Appwrite's persistent data:\n\n- `appwrite-mariadb` — the database (users, projects, documents, rules).\n- `appwrite-uploads` — files uploaded by client apps.\n\nSchedule a daily dump:\n\n```bash\ndocker exec appwrite-mariadb mysqldump \\\n  -u appwrite -p\"$MARIADB_ROOT_PASSWORD\" appwrite \\\n  > \u002Fbackups\u002Fappwrite-$(date +%Y%m%d).sql\n```\n\nAlso archive the `appwrite-uploads` volume (a `tar` of the data or a volume snapshot depending on your infrastructure). **Also back up `_APP_OPENSSL_KEY_V1`** — Appwrite uses it to encrypt files and some sensitive data. Without this key, a database restore makes the encrypted content permanently unreadable.",{"type":39,"title":83,"body":84},"Networking and Traefik: what happens behind the scenes","Traefik is Appwrite's only network entry point: it listens on ports 80 and 443, manages Let's Encrypt certificates, and routes requests to the correct internal service. This integration is transparent — you don't write any Traefik configuration, it's generated by the installer.\n\nA few important points if you add an upstream reverse proxy (nginx, Cloudflare Tunnel…):\n\n- **Do not double the TLS.** If your upstream proxy already terminates SSL and forwards in HTTP to Appwrite, disable the ACME challenge by setting `_APP_OPTIONS_FORCE_HTTPS=disabled` and leaving `_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=` empty to prevent Traefik from trying to obtain a certificate it cannot validate.\n- **Forward the real IP.** Add `X-Forwarded-For` and `X-Real-IP` in your upstream proxy, and enable header trust in Traefik (already configured by default in the Appwrite installer).\n- **Console ports.** The web console and the API are served under the same domain: do not route port 9501 (internal Realtime) publicly — it is managed internally by Traefik.\n\nIf you place Appwrite behind Cloudflare in proxied mode, set the zone's SSL mode to **Full (strict)** — in Flexible mode, nginx redirects HTTP→HTTPS, which creates an infinite redirect loop between Cloudflare and Traefik.",{"type":39,"title":86,"body":87},"Troubleshooting common issues","**The console shows \"Could not connect to the Appwrite API\".**\nCheck that the `_APP_DOMAIN` and `_APP_DOMAIN_TARGET` variables in `.env` exactly match the domain you are using. A misconfigured subdomain (with or without `www`) prevents Traefik from routing correctly. Run `docker compose up -d` after any `.env` modification.\n\n**Verification e-mails are not arriving.**\nAppwrite has no built-in SMTP relay — you must configure `_APP_SMTP_*` with an external service (Mailgun, Resend, your own server). Without SMTP configured, e-mails are queued and ignored. Check the logs of the `appwrite-worker-mails` worker: `docker compose logs appwrite-worker-mails --tail 50`.\n\n**Serverless Functions time out.**\nEach Function starts its own Docker container. On a VPS with 2 GB of RAM, the cold start often exceeds 10 seconds, which triggers the default timeout. Increase `_APP_FUNCTIONS_TIMEOUT` in `.env` and plan for at least 4 GB of RAM for production use. Also monitor disk space — runtime images stay on the SSD after execution.\n\n**The SSL certificate is not being generated.**\nTraefik needs ports 80 and 443 to respond from the outside in order to pass the ACME challenge. If an upstream firewall (your VPS provider's security rules) blocks these ports, the challenge fails silently. Test from an external machine: `curl -I http:\u002F\u002Fapi.myapp.com` should respond (even with a 302), not time out.\n\n**MariaDB starts but the console shows database errors.**\nIf you have manually modified `.env` between restarts, check that `_APP_DB_HOST`, `_APP_DB_USER`, and `_APP_DB_PASS` match the values in the MariaDB container. A partial restart (a single service) without `docker compose down` can leave orphaned containers with old variables in memory.",{"type":89,"title":90,"headers":91,"rows":95},"comparison","Appwrite vs Supabase: which one to self-host?",[92,93,94],"Criterion","Appwrite","Supabase",[96,100,104,108,112,116,120,124,128],[97,98,99],"Database","MariaDB, document model","Native PostgreSQL, full SQL",[101,102,103],"Approach","SDK- and mobile-app-oriented","SQL- and relational-app-oriented",[105,106,107],"Serverless functions","Native, multi-language built-in","Edge Functions (Deno)",[109,110,111],"Installation","Official interactive installer","Compose to configure manually",[113,114,115],"SSL \u002F routing","Built-in Traefik, automatic","External reverse proxy to add",[117,118,119],"Vector \u002F AI search","Not native","Native via pgvector",[121,122,123],"Realtime","Built-in WebSocket, multi-resource","Postgres CDC via Realtime",[125,126,127],"Ideal for","Flutter, React Native, mobile-first","Advanced SQL, RAG, relational",[129,130,131],"Administration console","Rich, guided console","Studio focused on SQL tables",{"type":133,"title":134,"body":135},"tip","Updates and ongoing maintenance","To update Appwrite, re-run the installer with the new version or modify the image tag in `docker-compose.yml` and run `docker compose pull && docker compose up -d`. Appwrite applies schema migrations automatically when the API container starts — no manual command is needed.\n\nAlso schedule a weekly purge of orphaned Docker images to avoid SSD saturation:\n\n```bash\ndocker system prune --volumes -f\n```\n\nBack up `_APP_OPENSSL_KEY_V1` in a separate vault (secrets manager, encrypted file outside the VPS). Without this key, a database restore makes encrypted files and some sensitive data permanently unreadable — it is the only point of no return in an Appwrite installation.",{"type":133,"title":137,"body":138},"This template ships the core — Functions come later","The official Appwrite installer generates 25+ containers, including background workers and an execution runtime for serverless Functions and Sites. To keep the VPS footprint small, this template ships only the self-consistent core — the API server, MariaDB, Redis and Traefik — which fully powers Auth, Databases, Storage, Realtime and the Console. Serverless Functions, outbound webhooks and background e-mail need the extra worker and executor containers and are not enabled here. When your project needs them, grow to Appwrite's full official docker-compose stack and plan for 4 GB+ of RAM. For backups, snapshot the `appwrite-mariadb` (data) and `appwrite-uploads` (files) Docker volumes on a schedule.","Self-host your Appwrite backend","The ServOrbit Cloud VPS with a ready-to-use Docker template and SSD storage hosts the entire Appwrite stack, serverless functions included, over HTTPS.","Deploy my Cloud VPS","\u002Fvps-cloud",[144,162,180],{"id":145,"slug":146,"slugs":147,"title":151,"excerpt":152,"readTime":153,"views":18,"isPinned":19,"noindex":19,"publishedAt":154,"updatedAt":155,"category":156,"categories":157,"featuredImage":30,"bgImage":31,"posterImage":159,"relatedSolution":160},56,"postgresql-on-a-vps-a-reliable-and-controlled-database",{"fr":148,"en":146,"ar":149,"es":150},"heberger-postgresql-vps","postgresql-على-خادم-vps-قاعدة-بيانات-موثوقة-ومتحكم-بها","alojar-postgresql-en-un-vps","PostgreSQL on a VPS: reliable, controlled database","Host PostgreSQL on a VPS: production config, pgBackRest backups, streaming HA, RDS\u002FSupabase\u002FNeon comparison and OOM troubleshooting.",9,"2026-04-25T00:00:00+00:00","2026-10-21T15:21:37+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[158],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-postgresql-vps-poster.svg",{"categorySlug":34,"appSlug":161},"postgresql-stack",{"id":163,"slug":164,"slugs":165,"title":169,"excerpt":170,"readTime":153,"views":171,"isPinned":19,"noindex":19,"publishedAt":172,"updatedAt":173,"category":174,"categories":175,"featuredImage":30,"bgImage":31,"posterImage":177,"relatedSolution":178},57,"hosting-mysql-on-a-vps",{"fr":166,"en":164,"ar":167,"es":168},"heberger-mysql-vps","استضافة-mysql-على-خادم-vps","alojar-mysql-en-un-vps","Hosting MySQL on a VPS: complete guide","Install MySQL 8.4 LTS on a VPS: prerequisites, security hardening, InnoDB performance, secure remote access, automated backups, and troubleshooting.",0,"2026-04-24T00:00:00+00:00","2026-11-09T20:55:18+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[176],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-mysql-vps-poster.svg",{"categorySlug":34,"appSlug":179},"mysql-stack",{"id":181,"slug":182,"slugs":183,"title":187,"excerpt":188,"readTime":17,"views":171,"isPinned":19,"noindex":19,"publishedAt":189,"updatedAt":190,"category":191,"categories":192,"featuredImage":30,"bgImage":31,"posterImage":194,"relatedSolution":195},58,"hosting-redis-on-a-vps",{"fr":184,"en":182,"ar":185,"es":186},"heberger-redis-vps","استضافة-redis-على-خادم-vps","alojar-redis-en-un-vps","Hosting Redis on a VPS: the complete guide","Deploy Redis on your Cloud VPS: RAM\u002FCPU requirements, security (ACL, TLS), RDB\u002FAOF persistence, troubleshooting, and high availability.","2026-04-23T00:00:00+00:00","2026-09-08T21:59:59+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[193],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-redis-vps-poster.svg",{"categorySlug":34,"appSlug":196},"redis-stack",true,1794270415544]