Instalación de Appwrite Backend-as-a-Service

Appwrite es un backend-as-a-service (BaaS) de código abierto que proporciona autenticación, base de datos, almacenamiento, funciones serverless y mensajería en tiempo real con una sola instalación Docker. Diseñado como alternativa self-hosted a Firebase, Appwrite ofrece SDKs para más de 10 plataformas y un panel de administración completo, siendo ideal para acelerar el desarrollo de aplicaciones móviles y web. Esta guía cubre la instalación y configuración completa en Linux.

Requisitos Previos

  • Ubuntu 20.04/22.04 o Debian 11/12
  • Mínimo 1 vCPU y 2 GB RAM (recomendado 4 GB)
  • 15 GB de espacio en disco
  • Docker y Docker Compose instalados
  • Acceso a los puertos 80 y 443
# Instalar Docker si no está disponible
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker

# Verificar Docker
docker --version
docker compose version

Instalación con Docker

Appwrite proporciona un script de instalación que configura automáticamente Docker Compose:

# Instalar Appwrite con el script oficial interactivo
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.5.7

# Durante la instalación, el asistente preguntará:
# - Puerto HTTP (defecto: 80)
# - Puerto HTTPS (defecto: 443)
# - Hostname del servidor (ej: appwrite.tudominio.com)
# - Si habilitar SSL automático con Let's Encrypt
# - Email para certificados SSL

Instalación manual con Docker Compose

Para mayor control, usa Docker Compose directamente:

# Descargar el docker-compose oficial
curl -o docker-compose.yml https://appwrite.io/install/compose
curl -o .env https://appwrite.io/install/env

# Editar la configuración
nano .env

Variables clave en .env:

# .env de Appwrite - Variables principales

# Dominio del servidor
_APP_ENV=production
_APP_DOMAIN=appwrite.tudominio.com
_APP_DOMAIN_TARGET=appwrite.tudominio.com
_APP_DOMAIN_FUNCTIONS=functions.tudominio.com

# Credenciales de la base de datos interna
_APP_DB_HOST=mariadb
_APP_DB_PORT=3306
_APP_DB_SCHEMA=appwrite
_APP_DB_USER=appwrite
_APP_DB_PASS=tu-password-mariadb-seguro

# Secreto principal (mínimo 32 caracteres)
_APP_OPENSSL_KEY_V1=tu-clave-openssl-de-32-caracteres-min

# Redis (caché y colas)
_APP_REDIS_HOST=redis
_APP_REDIS_PORT=6379
_APP_REDIS_USER=
_APP_REDIS_PASS=

# Consola de administración
_APP_CONSOLE_WHITELIST_ROOT=enabled
[email protected]

# SMTP para emails transaccionales
_APP_SMTP_HOST=smtp.tudominio.com
_APP_SMTP_PORT=587
_APP_SMTP_SECURE=tls
[email protected]
_APP_SMTP_PASSWORD=tu-password-smtp

# Storage
_APP_STORAGE_LIMIT=30000000  # 30 MB por archivo
_APP_STORAGE_ANTIVIRUS=disabled  # Habilitar si tienes ClamAV

# Funciones
_APP_FUNCTIONS_SIZE_LIMIT=30000000
_APP_FUNCTIONS_TIMEOUT=900
_APP_FUNCTIONS_BUILD_TIMEOUT=900
# Iniciar Appwrite
docker compose up -d

# Ver los logs durante el inicio (puede tardar 2-3 minutos)
docker compose logs -f appwrite

# Verificar que todos los contenedores están corriendo
docker compose ps

Configuración del Servidor

Accede a https://appwrite.tudominio.com para el panel de administración:

  1. Crear cuenta de administrador: La primera cuenta tiene acceso total
  2. Crear un proyecto: Cada app tiene su propio proyecto con credenciales únicas
  3. Obtener Project ID y API Key: Necesarios para el SDK en tu aplicación
# Verificar que Appwrite responde
curl https://appwrite.tudominio.com/v1/health
# Respuesta esperada: {"status":"pass","version":"1.5.7"}

# Ver la versión instalada
docker exec appwrite appwrite --version

Configurar con la CLI de Appwrite

# Instalar la CLI de Appwrite
npm install -g appwrite-cli

# Autenticarse con el servidor
appwrite login

# Crear un proyecto desde CLI
appwrite projects create \
    --projectId mi-proyecto \
    --name "Mi Aplicación"

# Listar proyectos
appwrite projects list

Autenticación de Usuarios

Appwrite soporta múltiples métodos de autenticación configurables desde el panel:

Email y contraseña

# Habilitar método en: Project > Auth > Email/Password > Enable

# Crear usuario de prueba con la CLI
appwrite users create \
    --userId unique() \
    --email [email protected] \
    --password Password123! \
    --name "Usuario de Prueba"

# Listar usuarios
appwrite users list

Proveedores OAuth

# Configurar en: Project > Auth > OAuth2 Providers

# Ejemplo de configuración de Google:
# Client ID: obtenido en Google Cloud Console
# Client Secret: obtenido en Google Cloud Console
# URI de redirección: https://appwrite.tudominio.com/v1/account/sessions/oauth2/callback/google/TU_PROJECT_ID

# Providers disponibles:
# Google, GitHub, Apple, Facebook, Discord, Twitter, Spotify,
# LinkedIn, Microsoft, Dropbox, Twitch, GitLab, Amazon, y más

Autenticación por teléfono

# Requiere configurar un proveedor SMS en .env
_APP_SMS_PROVIDER=sms-vonage
_APP_SMS_FROM=+34600000000

# Credenciales de Vonage/Twilio
_APP_SMS_FROM=+14155552671
VONAGE_API_KEY=tu-api-key
VONAGE_API_SECRET=tu-api-secret

Base de Datos y Colecciones

Appwrite usa su propia capa de base de datos sobre MariaDB con soporte para reglas de permisos granulares:

# Crear una base de datos
appwrite databases create \
    --databaseId mi-base-de-datos \
    --name "Base de datos principal"

# Crear una colección (tabla)
appwrite databases createCollection \
    --databaseId mi-base-de-datos \
    --collectionId articulos \
    --name "Artículos" \
    --permissions 'read("users")' 'create("users")'

# Agregar atributos a la colección
appwrite databases createStringAttribute \
    --databaseId mi-base-de-datos \
    --collectionId articulos \
    --key titulo \
    --size 255 \
    --required true

appwrite databases createStringAttribute \
    --databaseId mi-base-de-datos \
    --collectionId articulos \
    --key contenido \
    --size 65535 \
    --required false

appwrite databases createIntegerAttribute \
    --databaseId mi-base-de-datos \
    --collectionId articulos \
    --key vistas \
    --required false \
    --default 0

# Crear un índice para búsqueda
appwrite databases createIndex \
    --databaseId mi-base-de-datos \
    --collectionId articulos \
    --key titulo_idx \
    --type fulltext \
    --attributes titulo

Consultas con el SDK de JavaScript

// Instalar el SDK: npm install appwrite

const { Client, Databases, Query } = require('appwrite');

const client = new Client()
    .setEndpoint('https://appwrite.tudominio.com/v1')
    .setProject('TU_PROJECT_ID');

const databases = new Databases(client);

// Listar documentos con filtros
const response = await databases.listDocuments(
    'mi-base-de-datos',
    'articulos',
    [
        Query.equal('autor', 'juan'),
        Query.orderDesc('$createdAt'),
        Query.limit(10)
    ]
);

Almacenamiento de Archivos

# Crear un bucket de almacenamiento
appwrite storage createBucket \
    --bucketId imagenes \
    --name "Imágenes de usuarios" \
    --permissions 'read("any")' 'create("users")' \
    --fileSecurity true \
    --enabled true \
    --maximumFileSize 5242880 \
    --allowedFileExtensions jpg jpeg png gif webp

# Subir un archivo
appwrite storage createFile \
    --bucketId imagenes \
    --fileId unique() \
    --file foto.jpg

# Generar URL de vista previa de imagen (con transformación)
# https://appwrite.tudominio.com/v1/storage/buckets/imagenes/files/FILE_ID/preview
# ?width=400&height=300&gravity=center&quality=80
// Subir archivo desde JavaScript
const { Storage, ID } = require('appwrite');
const storage = new Storage(client);

const file = await storage.createFile(
    'imagenes',
    ID.unique(),
    document.getElementById('fileInput').files[0]
);

// Obtener URL pública del archivo
const url = storage.getFileView('imagenes', file.$id);

Funciones Serverless

Appwrite Functions permite ejecutar código en respuesta a eventos o webhooks:

# Crear una función
appwrite functions create \
    --functionId procesar-imagen \
    --name "Procesar imágenes" \
    --runtime node-18.0 \
    --execute 'users' \
    --events 'databases.*.collections.*.documents.*.create'

# Crear el código de la función
mkdir -p funciones/procesar-imagen
cat > funciones/procesar-imagen/index.js << 'EOF'
module.exports = async ({ req, res, log, error }) => {
    const { databaseId, collectionId, documentId } = JSON.parse(req.body);
    
    log(`Procesando documento: ${documentId}`);
    
    return res.json({
        ok: true,
        mensaje: `Documento ${documentId} procesado`
    });
};
EOF

# Subir el código de la función
appwrite functions createDeployment \
    --functionId procesar-imagen \
    --entrypoint index.js \
    --code funciones/procesar-imagen/ \
    --activate true

Variables de entorno en funciones

# Configurar variables para una función específica
appwrite functions createVariable \
    --functionId procesar-imagen \
    --key API_KEY \
    --value tu-api-key-externa

appwrite functions createVariable \
    --functionId procesar-imagen \
    --key DATABASE_URL \
    --value postgresql://...

Solución de Problemas

El panel no carga o da error 502

# Verificar el estado de los contenedores
docker compose ps

# Ver logs del proxy (Traefik)
docker compose logs traefik --tail=50

# Ver logs del servicio principal
docker compose logs appwrite --tail=50

# Reiniciar servicios problemáticos
docker compose restart appwrite appwrite-worker-webhooks

Error de certificado SSL

# Verificar que el dominio resuelve correctamente
dig +short appwrite.tudominio.com

# Ver logs de Let's Encrypt
docker compose logs traefik | grep -i "acme\|cert\|error"

# Si hay problemas, verificar que los puertos 80 y 443 están abiertos
curl -I http://appwrite.tudominio.com/.well-known/acme-challenge/test

Las funciones no se ejecutan

# Verificar que el runtime está instalado
docker compose logs appwrite-executor --tail=50

# Ver ejecuciones fallidas
appwrite functions listExecutions --functionId mi-funcion

# Ver los logs de una ejecución específica
appwrite functions getExecution \
    --functionId mi-funcion \
    --executionId EXECUTION_ID

Error de permisos en colecciones

# Verificar los permisos de la colección en el panel:
# Project > Databases > Colección > Settings > Permissions

# Los permisos siguen el formato: action("role")
# - read("any") - cualquiera puede leer
# - read("users") - solo usuarios autenticados
# - read("user:USER_ID") - solo ese usuario específico
# - read("team:TEAM_ID/owner") - solo owners del equipo

Conclusión

Appwrite proporciona una solución BaaS completa y self-hosted que elimina la necesidad de escribir código de backend para las funcionalidades más comunes: autenticación, almacenamiento, base de datos con permisos y funciones serverless. Su amplio soporte de SDKs para web, móvil y desktop, combinado con la facilidad de instalación con Docker, lo convierte en una opción excelente para equipos que quieren acelerar el desarrollo sin depender de servicios cloud externos o sus costes variables.