ObjectOS
Configurar

Almacenamiento

Dónde coloca ObjectOS los archivos — disco local, S3, R2, MinIO, Spaces.

Almacenamiento

Los archivos de ObjectOS (adjuntos, cargas, documentos generados) fluyen a través del servicio de almacenamiento — una abstracción conectable con dos adaptadores: sistema de archivos local (predeterminado) y compatible con S3 (producción).

El servicio lo proporciona @objectstack/service-storage y está habilitado de forma predeterminada en los arranques standalone y de proyecto.

Cómo interactúan los usuarios con él

SuperficieComportamiento
Campos de archivo/imagen de ConsoleEl navegador carga directamente al almacenamiento mediante URLs prefirmadas
REST /api/v1/storage/*Endpoints de carga/descarga programáticos
Campos file / image de objetosSe renderizan como widgets de carga; los metadatos persisten en sys_file

Los archivos se rastrean en el objeto de sistema sys_file — nunca como rutas sin procesar en tus registros. Eso desacopla tu modelo de datos del backend de almacenamiento.

Sistema de archivos local (predeterminado)

Ideal para: desarrollo, despliegues de un solo nodo, demostraciones.

// objectstack.config.ts (or wherever you assemble plugins)
import { StorageServicePlugin } from '@objectstack/service-storage';

new StorageServicePlugin({
  adapter: 'local',
  local: {
    rootDir: './uploads',
    baseUrl: 'http://localhost:3000',  // for presigned URLs
    signingSecret: process.env.OS_STORAGE_SIGNING_SECRET, // optional; auto-generated if omitted
  },
  presignedTtl: 3600,   // seconds — TTL for presigned URLs
  sessionTtl: 86400,    // seconds — TTL for chunked upload sessions
});

En modo standalone (os start sin proyecto), el runtime configura el almacenamiento local automáticamente en .objectstack/data/uploads/. Anula el directorio raíz con la variable de entorno OS_STORAGE_ROOT.

La idoneidad para producción depende de la forma del despliegue:

  • ✅ Aplicaciones de escritorio, herramientas internas de un solo nodo, dispositivos edge / on-prem — el almacenamiento local funciona bien, siempre que el directorio uploads/ esté incluido en tu copia de seguridad del sistema de archivos (o resida en una carpeta de sincronización controlada por el usuario en aplicaciones de escritorio).
  • ❌ Multinodo, multi-AZ, o cualquier cosa que requiera durabilidad entre regiones — usa almacenamiento compatible con S3.

Compatible con S3 (producción)

Ideal para: producción, multinodo, durabilidad + gestión del ciclo de vida.

pnpm add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
import { StorageServicePlugin } from '@objectstack/service-storage';

new StorageServicePlugin({
  adapter: 's3',
  s3: {
    bucket: 'my-bucket',
    region: 'us-east-1',
    // omit credentials to use the AWS SDK's default chain
    // (env, ~/.aws, IAM role)
  },
});

El AWS SDK lee las credenciales de su cadena habitual:

OrigenVariable de entorno
Entorno estándarAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
Token de sesiónAWS_SESSION_TOKEN
Configuración compartida~/.aws/credentials, AWS_PROFILE
Rol de IAMAutomático en EC2 / ECS / EKS / Lambda — sin configuración

Cloudflare R2

new StorageServicePlugin({
  adapter: 's3',
  s3: {
    bucket: 'my-bucket',
    region: 'auto',
    endpoint: 'https://<account-id>.r2.cloudflarestorage.com',
    forcePathStyle: false,
  },
});

Credenciales: ID de clave de acceso de R2 + secreto, pasados mediante las variables de entorno estándar AWS_* o tu gestor de secretos.

MinIO (autoalojado)

new StorageServicePlugin({
  adapter: 's3',
  s3: {
    bucket: 'my-bucket',
    region: 'us-east-1',
    endpoint: 'http://minio.internal:9000',
    forcePathStyle: true,
  },
});

DigitalOcean Spaces

new StorageServicePlugin({
  adapter: 's3',
  s3: {
    bucket: 'my-bucket',
    region: 'nyc3',
    endpoint: 'https://nyc3.digitaloceanspaces.com',
    forcePathStyle: false,
  },
});

Política de bucket de S3

El almacenamiento usa URLs prefirmadas PUT/GET. Política de bucket recomendada:

  • Bloquea todo el acceso público.
  • CORS: permite PUT/GET desde tus nombres de host de ObjectOS.
  • Ciclo de vida: caduca las cargas multiparte incompletas tras 1–7 días; caduca los objetos etiquetados con temp=true tras 24 horas.
  • Versionado + Object Lock: opcional, recomendado para despliegues de cumplimiento normativo.

Superficie REST

@objectstack/client llama a estos — normalmente no los invocas directamente:

MétodoRutaPropósito
POST/api/v1/storage/upload/presignedObtener una URL de carga prefirmada
POST/api/v1/storage/upload/completeConfirmar una carga finalizada
POST/api/v1/storage/upload/chunkedIniciar una carga por fragmentos
PUT/api/v1/storage/upload/chunked/:uploadId/chunk/:iCargar un fragmento
POST/api/v1/storage/upload/chunked/:uploadId/completeFinalizar la carga por fragmentos
GET/api/v1/storage/upload/chunked/:uploadId/progressConsultar el progreso
GET/api/v1/storage/files/:fileId/urlObtener una URL de descarga prefirmada

La autorización por archivo la gestiona el evaluador de permisos del plugin de seguridad contra el objeto sys_file — no necesitas ACLs separadas en la capa de almacenamiento.

Configuración en vivo

Cuando el servicio de settings está habilitado (lo está de forma predeterminada), un administrador puede cambiar el adaptador de almacenamiento en Console → Configuration → Storage sin reiniciar:

  • elige adaptador, bucket, región, endpoint;
  • pega las credenciales (cifradas en reposo en sys_setting);
  • haz clic en Test connection antes de guardar.

El cambio se aplica en la siguiente petición — sin necesidad de reiniciar.

Dimensionamiento

RecursoPredeterminadoAjustable
TTL de URL prefirmada1 horaOpción del plugin presignedTtl
TTL de sesión de carga por fragmentos24 horasOpción del plugin sessionTtl
Carga máxima de una sola parteImpuesta por el backend (S3 = 5 GB)
Carga máxima por fragmentosImpuesta por el backend (S3 = 5 TB)

A dónde ir después

On this page