Hasura Storage

repository·main·Indexed 42 days ago

https://github.com/nhost/hasura-storage

A middleware service that connects Hasura and S3-compatible storage to manage file uploads and retrievals. It leverages Hasura's GraphQL API to enforce permissions and manage file metadata, and includes optional ClamAV antivirus integration for scanning uploaded files.

Tokens
2.5K
Snippets
9
Records
14
Agent score
53%

What's inside Hasura Storage

  1. How Hasura Storage works for uploading and retrieving files

    main

    Hasura Storage acts as a middleware between your users, Hasura, and an S3-compatible storage service. It leverages Hasura's GraphQL API to enforce permissions and manage file metadata.

    Upload Workflow

    1. Permission Check: The service asks Hasura if the user has permission to upload.
    2. S3 Upload: If permitted, the file is uploaded to the S3-compatible service.
    3. Metadata Storage: Upon successful S3 upload, the file's metadata is stored in Hasura via GraphQL.
    4. Response: The user receives the file metadata.

    Retrieval Workflow

    1. Permission Check: The service asks Hasura if the user has permission to access the specific file.
    2. S3 Fetch: If permitted, the service requests the file from S3.
    3. Response: The file is streamed back to the user.
  2. Test changes locally using Makefile or Nix

    main

    To verify your changes, follow these steps:

    1. Start prerequisites: Run make dev-env-up-short to start the necessary containers.
    2. Apply changes: Modify your code.
    3. Build and run:
      • Use the Makefile: make dev-env-up-hasura (this builds and deploys in a Docker container).
      • Or, if your local environment is configured (via Nix or manual C dependencies), run go run main.go serve or nix run . -- serve.
    4. Run tests: Execute make integration-tests to run the test suite.
    5. Cleanup: Stop the environment with make dev-env-down.
    make dev-env-up-short
    make dev-env-up-hasura
    make integration-tests
    make dev-env-down
  3. Self-host Hasura Storage

    main

    To self-host Hasura Storage, you must satisfy the following requirements:

    1. Hasura: A running Hasura instance connected to a supported database (e.g., PostgreSQL).
    2. S3-Compatible Storage: An S3-compatible service such as AWS S3 or MinIO.

    For a complete setup guide, refer to the docker-compose example in the /build/dev/docker/ directory of the repository. When using Docker, ensure you use a valid production image (e.g., nhost/hasura-storage:0.1.5) instead of the dev tag.

  4. Set up the development environment with Nix

    main

    The project uses Nix to provide a consistent development environment. If you have Nix installed, you can initialize the environment by running nix develop. This ensures your local environment matches the one used in CI.

    Note that hasura-storage relies on the C library libvips for performance. If you are not using Nix, you must manually install libvips-dev and the necessary compilation tools such as gcc and pkg-config.

    nix develop
  5. Configure ClamAV antivirus integration

    main

    Hasura Storage can integrate with ClamAV to scan uploaded files for viruses. This requires an external clamd service running and accessible via a TCP socket.

    Workflow with Antivirus:

    • When a file is uploaded, the service first checks the file with clamd.
    • If a virus is found: The S3 upload is aborted, and details are inserted into the virus table in Hasura.
    • If the file is clean: The upload to S3 proceeds and the metadata is updated in Hasura.

    To enable this, use the --clamav-server flag with the TCP address of your clamd service.

    --clamav-server <tcp-address>
  6. Apply Migrations on Startup

    main

    You can automate the setup of your database and Hasura metadata by using the following flags during the serve command:

    1. Postgres Migrations: Use --postgres-migrations and provide the connection string via --postgres-migrations-source.
    2. Hasura Metadata: Use --hasura-metadata and provide the Hasura endpoint via --hasura-endpoint and the admin secret via --hasura-graphql-admin-secret.
    # Example applying both Postgres and Hasura migrations
    ./hasura-storage serve \
      --postgres-migrations \
      --postgres-migrations-source postgres://user:pass@localhost:5432/mydb \
      --hasura-metadata \
      --hasura-endpoint http://localhost:8080 \
      --hasura-graphql-admin-secret mysecret
  7. Configure S3 Content Storage

    main

    The service uses S3 for content storage. You must provide the --s3-bucket and --s3-endpoint. If you provide both --s3-access-key and --s3-secret-key, the service will use static credentials. Otherwise, it will attempt to use the default AWS credential provider chain. You can also specify a --s3-root-folder to nest all created buckets under a specific path in your S3 bucket.

    # Example using static credentials and a custom endpoint
    ./hasura-storage serve \
      --s3-endpoint https://minio:9000 \
      --s3-access-key minioadmin \
      --s3-secret-key minioadmin \
      --s3-bucket my-storage-bucket \
      --s3-region us-east-1
  8. Configure CORS settings

    main

    To control Cross-Origin Resource Sharing (CORS), use the following flags:

    • --cors-allow-origins: A list of allowed origins (defaults to *).
    • --cors-allow-credentials: A boolean to allow credentials (defaults to false).

    Note that the service automatically exposes several headers including Content-Length, Content-Type, Cache-Control, ETag, Last-Modified, and X-Error.

  9. Configure hasura-storage via environment variables

    main
    The CLI uses viper to manage configuration, which means you can configure the service using environment variables. The CLI automatically replaces hyphens (-) with underscores (_) in environment variable keys to match standard naming conventions.
  10. Access the Hasura Storage OpenAPI definition

    main
    The service provides an OpenAPI specification for its controller. You can find the local definition in the repository or view it online via the Swagger editor to understand the available endpoints and request/response schemas.
  11. Reference: `serve` command flags

    main

    The following flags are available for the serve command to configure the service behavior, storage backends, and migrations.

    --public-url string
      # public URL of the service (default: http://localhost:8000)
    
    --api-root-prefix string
      # API root prefix (default: /v1)
    
    --bind string
      # bind the service to this address (default: :8000)
    
    --hasura-endpoint string
      # Use this endpoint when connecting using graphql as metadata storage
    
    --s3-endpoint string
      # S3 Endpoint
    
    --s3-access-key string
      # S3 Access key
    
    --s3-secret-key string
      # S3 Secret key
    
    --s3-region string
      # S3 region (default: no-region)
    
    --s3-bucket string
      # S3 bucket
    
    --s3-root-folder string
      # All buckets will be created inside this root
    
    --s3-disable-http
      # Disable HTTPS for S3
    
    --postgres-migrations
      # Apply Postgres migrations
    
    --postgres-migrations-source string
      # postgres connection, i.e. postgres://user@pass:localhost:5432/mydb
    
    --hasura-db-name string
      # Hasura database name (default: default)
    
    --hasura-metadata
      # Apply Hasura's metadata
    
    --hasura-graphql-admin-secret string
      # Hasura GraphQL admin secret
    
    --fastly-service string
      # Enable Fastly middleware and enable automated purges
    
    --fastly-key string
      # Fastly CDN Key to authenticate purges
    
    --cors-allow-origins []string
      # CORS allow origins (default: [*])
    
    --cors-allow-credentials bool
      # CORS allow credentials
    
    --clamav-server string
      # If set, use ClamAV to scan files. Example: tcp://clamavd:3310