How to Configure Media Storage, Archival, and Retrieval in Grok

Grok stores generated images and videos in a three-layer media subsystem that combines YAML-based storage drivers, database-backed metadata with automatic cleanup workers, and public HTTP endpoints for retrieval.

The chenyme/grok2api repository implements a complete media management pipeline that allows operators to configure storage limits, enforce automatic archival policies, and serve assets through a public API. To configure media storage archival and retrieval in Grok, administrators modify the media section of the configuration file and tune runtime parameters through the admin settings interface.

Media Configuration and Storage Drivers

YAML Configuration Structure

All storage parameters reside under the top-level media: key in config.example.yaml (lines 80-87). Currently, only the local driver is supported, which writes raw image and video files to a specified directory.

media:
  driver: local                     # only "local" is supported now

  local:
    path: "./data/media"           # directory where raw files are written

Runtime Limits and Admin UI

The admin interface (accessed at /settings) exposes additional runtime constraints managed by frontend/src/features/settings/settings-model.ts. These values are persisted in the media_config database table and exposed via the /api/admin/v1/settings endpoint:

  • maxImageBytes – Maximum size of a single image file (default: 32 MiB)
  • maxTotalBytes – Total storage quota for all media assets (default: 1 GiB)
  • cleanupThresholdPercent – Storage usage percentage that triggers automatic deletion of oldest assets (default: 80%)
  • cleanupInterval – Frequency of background cleanup checks (default: 1m)
  • publicApiBaseURL – Base URL used to generate public-facing asset links (auto-derived from server address if not set)

The Archival and Cleanup Workflow

Size Accounting and Triggers

Every time an image or video is saved, the service updates a bytes-used counter stored in the database. The checkCapacity function in backend/internal/application/media/service.go enforces the maxImageBytes limit on individual uploads and tracks aggregate usage against maxTotalBytes.

When used storage exceeds maxTotalBytes * cleanupThresholdPercent/100, the service triggers automatic archival.

The Cleanup Worker

The cleanupWorker goroutine, scheduled by the Start method in backend/internal/application/media/service.go, periodically executes runCleanup from backend/internal/application/media/cleanup.go based on the configured cleanupInterval.

The worker performs the following steps:

  1. Queries the media_asset table ordered by creation time (oldest first)
  2. Deletes physical files from the media.local.path directory
  3. Removes database records until usage falls below the threshold
  4. Invalidates existing public URLs (subsequent requests return 404 with error code mediaAssetNotFound)

Media Retrieval via Public API

Assets are served through read-only endpoints registered in backend/internal/transport/http/media/handler.go (lines 28-31). These handlers delegate to service.GetImage and service.GetVideo, which verify file existence on disk and stream content with proper Content-Type headers.

Endpoint Method Description
GET /v1/media/images/:assetId Public Returns the raw image file or b64_json payload
GET /v1/media/videos/:assetId Public Streams the video file or returns a temporary URL

When an asset is missing—either because it was deleted by the cleanup worker or manually removed—the API returns a 404 Not Found status.

Upload Flow and Size Enforcement

Admin clients ingest media through authenticated endpoints implemented in backend/internal/transport/http/media/ingest.go. These handlers enforce the maxImageBytes limit before storage:

Endpoint Purpose
POST /api/admin/v1/media/inputs/upload Direct multipart upload via uploadInputImage
POST /api/admin/v1/media/inputs/import Import from external URL via importInputImageFromURL

Both functions return a MediaInputDTO containing the generated asset ID and its public URL. You can force an immediate cleanup run via the admin endpoint POST /api/admin/v1/media/cleanup.

Summary

  • Configuration happens in config.example.yaml under the media: key, with runtime limits adjustable through the /settings UI and stored in the media_config table.
  • Archival is handled automatically by a background worker in backend/internal/application/media/cleanup.go that deletes oldest assets when usage exceeds cleanupThresholdPercent.
  • Retrieval occurs through public endpoints at /v1/media/images/:assetId and /v1/media/videos/:assetId, returning 404 for cleaned assets.
  • Uploads are processed by backend/internal/transport/http/media/ingest.go, which enforces maxImageBytes and stores metadata in media_asset.

Frequently Asked Questions

What storage drivers does Grok support for media?

Currently, only the local driver is implemented. According to config.example.yaml, you must specify driver: local and provide a filesystem path via media.local.path. The architecture in backend/internal/application/media/service.go supports future driver extensions, but no cloud or object storage backends are available in the current codebase.

How does Grok handle storage quota exceeded scenarios?

When the aggregate size of stored assets exceeds maxTotalBytes * cleanupThresholdPercent/100, the cleanupWorker goroutine automatically deletes the oldest assets from the media_asset table and removes corresponding files from media.local.path. This process runs every cleanupInterval (default one minute) to ensure total storage remains bounded.

Can I manually trigger media cleanup?

Yes. Administrators can force an immediate cleanup run by sending a POST request to /api/admin/v1/media/cleanup. This bypasses the normal interval and executes the same runCleanup logic found in backend/internal/application/media/cleanup.go, deleting assets until usage falls below the threshold.

What happens to public URLs when media is deleted?

Public URLs become invalid immediately upon deletion. When a client requests GET /v1/media/images/:assetId or GET /v1/media/videos/:assetId, the handler in backend/internal/transport/http/media/handler.go checks the media_asset table and filesystem. If the asset is missing, the API returns 404 Not Found with the error code mediaAssetNotFound.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →