Appwrite is an open-source backend-as-a-service: authentication (email, OAuth, phone, magic links), databases with permissions, file storage with image transformations, serverless functions, realtime subscriptions and messaging, exposed through SDKs for web, Flutter, iOS, Android and server languages. Self-hosting it gives you a Firebase-like platform on your own VPS.
Comparing options? See Supabase self-hosted and PocketBase.
Requirements
- 2 vCPU and 4 GB RAM minimum. Appwrite runs many containers (API, workers, MariaDB, Redis, Traefik, executor and others).
- 20+ GB disk, plus storage for user files.
- Docker and the Docker Compose plugin. See install Docker.
- A domain, e.g.
appwrite.example.com, pointing at the server, with ports 80/443 free (Appwrite’s bundled Traefik handles TLS), or a reverse proxy setup.
Install
The official installer generates docker-compose.yml and .env:
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.6.1
(Use the current version.) It asks for:
- HTTP/HTTPS ports;
- the hostname (
appwrite.example.com); - a DNS A/CNAME target, for function and site domains;
- a secret API key (
_APP_OPENSSL_KEY_V1): keep it safe, since it encrypts stored data.
Then it starts the stack. Open https://appwrite.example.com, and create the console account.
Important .env settings
In appwrite/.env (then docker compose up -d to apply):
_APP_DOMAIN=appwrite.example.com
_APP_DOMAIN_TARGET=appwrite.example.com
_APP_ENV=production
_APP_CONSOLE_WHITELIST_EMAILS[email protected] # restrict who can sign up to the console
_APP_SMTP_HOST=smtp.example.com
_APP_SMTP_PORT=587
_APP_SMTP_SECURE=tls
_APP_SMTP_USERNAME=…
_APP_SMTP_PASSWORD=…
_APP_SYSTEM_EMAIL_ADDRESS[email protected]
_APP_STORAGE_LIMIT=30000000 # max file size in bytes
Restrict console signups (whitelist emails or IPs). Otherwise anyone can create a console account on your server. SMTP is needed for verification, password recovery and magic links. See transactional email services.
Using Appwrite
- Create a project in the console.
- Add platforms: web (your site’s hostname), Flutter, Apple and Android apps. Appwrite only accepts client requests from registered platforms.
- Enable auth methods (email/password, OAuth providers like GitHub and Google, magic URL), with password policies and session limits.
- Create databases and collections with attributes, indexes and permissions (role-based: any, users, a team, a specific user).
- Create storage buckets, with size and type limits and permissions.
- Write functions (Node, Python, PHP, Dart, Bun, Go…) triggered by HTTP, events or schedules.
Web SDK example:
import { Client, Account, Databases } from 'appwrite';
const client = new Client().setEndpoint('https://appwrite.example.com/v1').setProject('PROJECT_ID');
const account = new Account(client);
await account.createEmailPasswordSession('[email protected]', 'password');
Server SDKs use API keys with limited scopes. Never ship them in client code. See secrets management.
Behind your own reverse proxy
If the server already runs Nginx on 80/443, change Appwrite’s Traefik ports in the installer (e.g. 8080/8443) and proxy to them, keeping WebSocket upgrade headers for realtime. Or run Appwrite on a dedicated VPS, which is simpler with its many containers. See Nginx WebSocket proxy.
Backups
Appwrite’s data lives in Docker volumes: MariaDB (all project data), uploads (storage), functions, and certificates. A consistent backup:
cd appwrite
docker compose exec -T mariadb sh -c 'exec mysqldump --all-databases --single-transaction -uroot -p"$MYSQL_ROOT_PASSWORD"' > /backups/appwrite-db-$(date +%F).sql
docker run --rm -v appwrite_appwrite-uploads:/data -v /backups:/b alpine tar czf /b/appwrite-uploads-$(date +%F).tgz -C /data .
Also keep .env (with _APP_OPENSSL_KEY_V1) safe. Without it, encrypted data can’t be read. See backup strategy.
Upgrades
Upgrades use the same installer with the new version tag, followed by a migration:
docker run -it --rm --volume /var/run/docker.sock:/var/run/docker.sock --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw --entrypoint="upgrade" appwrite/appwrite:<new-version>
cd appwrite && docker compose exec appwrite migrate
Upgrade one minor version at a time, after a backup. See updating self-hosted apps.
Quick reference
| Item | Value |
|---|---|
| Console | https://appwrite.example.com |
| API endpoint | /v1 |
| Config | appwrite/.env |
| Restrict console | _APP_CONSOLE_WHITELIST_EMAILS |
| Encryption key | _APP_OPENSSL_KEY_V1 (back it up) |
| Upgrade | installer --entrypoint="upgrade", then migrate |
Related: Docker security and API security.