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
| Superficie | Comportamiento |
|---|---|
| Campos de archivo/imagen de Console | El navegador carga directamente al almacenamiento mediante URLs prefirmadas |
REST /api/v1/storage/* | Endpoints de carga/descarga programáticos |
Campos file / image de objetos | Se 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-presignerimport { 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:
| Origen | Variable de entorno |
|---|---|
| Entorno estándar | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION |
| Token de sesión | AWS_SESSION_TOKEN |
| Configuración compartida | ~/.aws/credentials, AWS_PROFILE |
| Rol de IAM | Automá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/GETdesde 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=truetras 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étodo | Ruta | Propósito |
|---|---|---|
| POST | /api/v1/storage/upload/presigned | Obtener una URL de carga prefirmada |
| POST | /api/v1/storage/upload/complete | Confirmar una carga finalizada |
| POST | /api/v1/storage/upload/chunked | Iniciar una carga por fragmentos |
| PUT | /api/v1/storage/upload/chunked/:uploadId/chunk/:i | Cargar un fragmento |
| POST | /api/v1/storage/upload/chunked/:uploadId/complete | Finalizar la carga por fragmentos |
| GET | /api/v1/storage/upload/chunked/:uploadId/progress | Consultar el progreso |
| GET | /api/v1/storage/files/:fileId/url | Obtener 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
| Recurso | Predeterminado | Ajustable |
|---|---|---|
| TTL de URL prefirmada | 1 hora | Opción del plugin presignedTtl |
| TTL de sesión de carga por fragmentos | 24 horas | Opción del plugin sessionTtl |
| Carga máxima de una sola parte | Impuesta por el backend (S3 = 5 GB) | — |
| Carga máxima por fragmentos | Impuesta por el backend (S3 = 5 TB) | — |
A dónde ir después
- Configuración del sistema — configuración en vivo y el servicio de settings que utilizan los cambios de almacenamiento
- Preparación para producción — lista de verificación que incluye la durabilidad y la copia de seguridad del almacenamiento de objetos
@objectstack/service-storageen GitHub — código fuente y referencia completa de opciones