{"id":16547766,"url":"https://github.com/brunojppb/turbo-cache-server","last_synced_at":"2026-01-19T17:03:02.830Z","repository":{"id":214958170,"uuid":"737640035","full_name":"brunojppb/turbo-cache-server","owner":"brunojppb","description":"Blazingly fast Turborepo remote cache server written in Rust as a Github Action and Docker for ARM64 and AMD64 Linux","archived":false,"fork":false,"pushed_at":"2026-01-12T04:28:18.000Z","size":168116,"stargazers_count":132,"open_issues_count":1,"forks_count":15,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-12T13:51:07.789Z","etag":null,"topics":["action","actions","github","gitlab","javascript","monorepo","rust","turborepo","typescript"],"latest_commit_sha":null,"homepage":"https://turbo.bpaulino.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brunojppb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-31T21:48:21.000Z","updated_at":"2026-01-12T04:28:21.000Z","dependencies_parsed_at":"2024-02-11T15:30:40.216Z","dependency_job_id":"8e9d6906-d27b-4ce0-aabe-d0e756f2ccb3","html_url":"https://github.com/brunojppb/turbo-cache-server","commit_stats":null,"previous_names":["brunojppb/decay","brunojppb/turbo-cache-server"],"tags_count":46,"template":false,"template_full_name":null,"purl":"pkg:github/brunojppb/turbo-cache-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brunojppb%2Fturbo-cache-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brunojppb%2Fturbo-cache-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brunojppb%2Fturbo-cache-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brunojppb%2Fturbo-cache-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brunojppb","download_url":"https://codeload.github.com/brunojppb/turbo-cache-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brunojppb%2Fturbo-cache-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28577043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T16:29:19.148Z","status":"ssl_error","status_checked_at":"2026-01-19T16:29:17.772Z","response_time":67,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["action","actions","github","gitlab","javascript","monorepo","rust","turborepo","typescript"],"created_at":"2024-10-11T19:23:03.192Z","updated_at":"2026-01-19T17:03:02.817Z","avatar_url":"https://github.com/brunojppb.png","language":"Rust","funding_links":[],"categories":["Remote Cache Servers"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cbr\u003e\u003cimg src=\"./icon.png\" width=\"128\" height=\"128\" alt=\"Turbo engine\" /\u003e\u003c/p\u003e\n\u003ch2 align=\"center\"\u003eTurbo Cache Server\u003c/h2\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://turbo.build/repo\"\u003eTurborepo\u003c/a\u003e remote cache server, \u003ca href=\"https://turbo.build/repo/docs/core-concepts/remote-caching#self-hosting\"\u003eAPI-compliant\u003c/a\u003e as a GitHub Action or Docker with S3-compatible storage support.\n\u003c/p\u003e\n\n## Used by folks at\n\n\u003cdiv\u003e\n  \u003cimg src=\"used_by.png\"/\u003e\n\u003c/div\u003e\n\n### How can I use this in my monorepo?\n\nMake sure that you have an S3-compatible storage available. We currently tested\nwith:\n\n- [Amazon S3](https://aws.amazon.com/s3/)\n- [Cloudflare R2](https://www.cloudflare.com/en-gb/developer-platform/r2/)\n- [Minio Object Storage](https://min.io/)\n\nYou can use the Turbo Cache Server as a **GitHub Action**. Here is how:\n\n1.  In your workflow files, add the following global environment variables:\n\n    ```yml\n    env:\n      TURBO_API: \"http://127.0.0.1:8585\"\n      TURBO_TEAM: \"NAME_OF_YOUR_REPO_HERE\"\n      # The value of TURBO_TOKEN will be checked by the cache server\n      TURBO_TOKEN: \"secret-turbo-token\"\n    ```\n\n1.  In the same workflow file, after checking out your code,\n    start the Turbo Cache Server in the background:\n\n    ````yml\n        - name: Checkout repository\n          uses: actions/checkout@v4\n\n        - name: Turborepo Cache Server\n          # ALWAYS use a pinned version of the action\n          # As we don't ship the latest versions of the binary on the main branch\n          # PLEASE see the latest versions here:\n          # https://github.com/brunojppb/turbo-cache-server/releases\n          uses: brunojppb/turbo-cache-server@2.0.2\n          env:\n            PORT: \"8585\"\n            S3_BUCKET_NAME: your-bucket-name-here\n            # Region defaults to \"eu-central-1\"\n            S3_REGION: \"eu-central-1\"\n            # Optional: If you need to provide specific auth keys, separate from default AWS credentials\n            S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}\n            S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}\n            # Optional: If not using AWS, provide endpoint like `https://minio` for your instance.\n            S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}\n            # Optional: If your S3-compatible store does not support requests\n            # like https://bucket.hostname.domain/. Setting `S3_USE_PATH_STYLE`\n            # to true configures the S3 client to make requests like\n            # https://hostname.domain/bucket instead.\n            # Defaults to \"false\"\n            S3_USE_PATH_STYLE: false\n            # Optional: Enable server-side encryption for stored artifacts.\n            # Valid values: AES256, aws:kms, aws:kms:dsse, aws:fsx\n            S3_SERVER_SIDE_ENCRYPTION: \"AES256\"\n            # Max payload size for each cache object sent by Turborepo\n            # Defaults to 100 MB\n            # Requests larger than that, will get \"HTTP 413: Entity Too Large\" errors\n            MAX_PAYLOAD_SIZE_IN_MB: \"100\"\n\n        # Now you can run your turborepo tasks and rely on the cache server\n        # available in the background to provide previously built artifacts (cache hits)\n        # and let Turborepo upload new artifacts when there is a cache miss.\n        - name: Run tasks\n          run: turbo run test build typecheck\n        ```\n    ````\n\nAnd that is all you need to use our remote cache server for Turborepo. As a\nreference, take a look at\n[this example workflow file](https://github.com/brunojppb/turbo-decay/blob/main/.github/workflows/ci.yml)\nfor inspiration.\n\n\u003e [!NOTE]\n\u003e These environment variables are required by Turborepo so it can call\n\u003e the Turbo Cache Server with the right HTTP body, headers and query strings.\n\u003e These environment variables are necessary so the Turborepo binary can identify\n\u003e the Remote Cache feature is enabled and can use them across all steps. You can\n\u003e [read more about this here](https://turbo.build/repo/docs/ci#setup) on the\n\u003e Turborepo official docs.\n\n## Gitlab support\n\nFor folks using Gitlab or any other CI environment that supports Docker,\nyou can run the Turbo Cache Server as a docker container:\n\n```shell\ndocker run \\\n  -e S3_ACCESS_KEY=KEY \\\n  -e S3_SECRET_KEY=SECRET \\\n  -e S3_BUCKET_NAME=my_cache_bucket \\\n  -e S3_ENDPOINT=https://s3_endpoint_here \\\n  -e S3_REGION=eu \\\n  -e S3_SERVER_SIDE_ENCRYPTION=AES256 \\\n  -e TURBO_TOKEN=secret-turbo-token \\\n  -p \"8000:8000\" \\\n  ghcr.io/brunojppb/turbo-cache-server\n```\n\n## Deploying to Kubernetes\n\nTurbo Cache Server is a cloud-native, stateless application that runs seamlessly in Kubernetes environments. This makes it ideal for horizontally scaled deployments across multiple pods.\n\n### Prerequisites\n\n- A Kubernetes cluster (v1.20 or higher recommended)\n- `kubectl` configured to access your cluster\n- An S3-compatible storage bucket configured\n- S3 credentials stored as Kubernetes secrets\n\n### Minimal Deployment Configuration\n\nBelow is a minimal setup to deploy Turbo Cache Server to your Kubernetes cluster:\n\n#### 1. Create a Secret for S3 Credentials\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: turbo-cache-s3-credentials\n  namespace: default\ntype: Opaque\nstringData:\n  S3_ACCESS_KEY: \"your-access-key-here\"\n  S3_SECRET_KEY: \"your-secret-key-here\"\n  TURBO_TOKEN: \"secret-turbo-token\"\n```\n\nApply the secret:\n\n```shell\nkubectl apply -f turbo-cache-secret.yaml\n```\n\n#### 2. Create a Deployment\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: turbo-cache-server\n  namespace: default\nspec:\n  replicas: 2 # Scale horizontally as needed\n  selector:\n    matchLabels:\n      app: turbo-cache-server\n  template:\n    metadata:\n      labels:\n        app: turbo-cache-server\n    spec:\n      containers:\n        - name: turbo-cache-server\n          image: ghcr.io/brunojppb/turbo-cache-server:latest\n          ports:\n            - containerPort: 8000\n              name: http\n          env:\n            - name: PORT\n              value: \"8000\"\n            - name: S3_BUCKET_NAME\n              value: \"your-bucket-name-here\"\n            - name: S3_REGION\n              value: \"eu-central-1\"\n            - name: S3_ACCESS_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: turbo-cache-s3-credentials\n                  key: S3_ACCESS_KEY\n            - name: S3_SECRET_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: turbo-cache-s3-credentials\n                  key: S3_SECRET_KEY\n            - name: TURBO_TOKEN\n              valueFrom:\n                secretKeyRef:\n                  name: turbo-cache-s3-credentials\n                  key: TURBO_TOKEN\n            - name: S3_ENDPOINT\n              value: \"https://your-s3-endpoint.com\"\n            - name: S3_SERVER_SIDE_ENCRYPTION\n              value: \"AES256\"\n            - name: MAX_PAYLOAD_SIZE_IN_MB\n              value: \"100\"\n          resources:\n            requests:\n              memory: \"128Mi\"\n              cpu: \"100m\"\n            limits:\n              memory: \"256Mi\"\n              cpu: \"500m\"\n          livenessProbe:\n            httpGet:\n              path: /management/health\n              port: 8000\n            initialDelaySeconds: 10\n            periodSeconds: 10\n          readinessProbe:\n            httpGet:\n              path: /management/health\n              port: 8000\n            initialDelaySeconds: 5\n            periodSeconds: 5\n```\n\nApply the deployment:\n\n```shell\nkubectl apply -f turbo-cache-deployment.yaml\n```\n\n#### 3. Create a Service\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: turbo-cache-server\n  namespace: default\nspec:\n  selector:\n    app: turbo-cache-server\n  ports:\n    - protocol: TCP\n      port: 8000\n      targetPort: 8000\n  type: ClusterIP\n```\n\nApply the service:\n\n```shell\nkubectl apply -f turbo-cache-service.yaml\n```\n\n#### 4. (Optional) Create an Ingress\n\nIf you need to expose the service externally:\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: turbo-cache-ingress\n  namespace: default\n  annotations:\n    # Configure based on your ingress controller\n    # nginx.ingress.kubernetes.io/rewrite-target: /\nspec:\n  rules:\n    - host: turbo.yourdomain.com\n      http:\n        paths:\n          - path: /\n            pathType: Prefix\n            backend:\n              service:\n                name: turbo-cache-server\n                port:\n                  number: 8000\n```\n\nApply the ingress:\n\n```shell\nkubectl apply -f turbo-cache-ingress.yaml\n```\n\n### Configuring Turborepo\n\nOnce deployed, configure your Turborepo clients to use the Kubernetes service:\n\n```shell\nexport TURBO_API=\"http://turbo-cache-server.default.svc.cluster.local:8000\"\nexport TURBO_TEAM=\"your-team-name\"\nexport TURBO_TOKEN=\"secret-turbo-token\"\n```\n\nFor external access through ingress:\n\n```shell\nexport TURBO_API=\"https://turbo.yourdomain.com\"\nexport TURBO_TEAM=\"your-team-name\"\nexport TURBO_TOKEN=\"secret-turbo-token\"\n```\n\n## Managing Cache Storage with Lifecycle Rules\n\nAs your cache grows over time, you may want to automatically expire old cache entries to control storage usage and costs. Since Turbo Cache Server uses S3-compatible storage, you can configure bucket lifecycle rules to automatically delete objects after a specified period.\n\n\u003e [!NOTE]\n\u003e Lifecycle rules are configured at the S3 bucket level, not within the Turbo Cache Server itself. This allows you to manage storage independently of the cache server configuration.\n\n### Setting up Object Expiration\n\nObject expiration is based on the last modified time of objects in your bucket. You can configure expiration in two ways:\n\n- **Days**: Objects will be deleted after a specified number of days (most common for a long running cache-server)\n- **Date**: Objects will be deleted on a specific date\n\n### AWS S3 and S3-Compatible Providers\n\nFor AWS S3, Cloudflare R2, Minio, and other S3-compatible providers, you can use the AWS CLI to configure lifecycle rules.\n\n#### Expire objects after 30 days\n\nCreate a JSON file named `lifecycle.json` with the following content:\n\n```json\n{\n  \"Rules\": [\n    {\n      \"Status\": \"Enabled\",\n      \"Expiration\": {\n        \"Days\": 30\n      }\n    }\n  ]\n}\n```\n\nThen apply the lifecycle configuration to your bucket:\n\n```shell\naws s3api put-bucket-lifecycle-configuration \\\n  --bucket your-bucket-name \\\n  --lifecycle-configuration file://lifecycle.json\n```\n\n#### Expire objects on a specific date\n\nYou can also set a specific expiration date:\n\n```json\n{\n  \"Rules\": [\n    {\n      \"Status\": \"Enabled\",\n      \"Expiration\": {\n        \"Date\": \"2025-12-31T00:00:00Z\"\n      }\n    }\n  ]\n}\n```\n\n### Provider-Specific Notes\n\n- **AWS S3**: Full lifecycle management support. See the [AWS S3 Lifecycle documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html) for advanced options like transitioning to different storage classes.\n- **Cloudflare R2**: Supports S3-compatible lifecycle API. Use the same AWS CLI commands with your R2 endpoint.\n- **Tigris**: Supports object expiration via lifecycle rules. See the [Tigris object expiration documentation](https://www.tigrisdata.com/docs/buckets/objects-expiration/) for details.\n- **Minio**: Supports S3-compatible lifecycle configuration. Use the AWS CLI with your Minio endpoint.\n\n### Important Considerations\n\n- **Lifecycle rules apply to all objects** in the bucket. If you're using the bucket for other purposes, consider using a dedicated bucket for cache storage or add filters to your lifecycle rules.\n- **Expiration is asynchronous**: There may be a delay between the expiration date and when objects are actually removed.\n- **Versioning**: If your bucket has versioning enabled, expiration rules apply only to current object versions. You may need separate rules for noncurrent versions.\n\n## OpenTelemetry Support\n\nTurbo Cache Server includes built-in support for [OpenTelemetry](https://opentelemetry.io/), providing distributed tracing and metrics collection out of the box. This enables you to monitor your cache server's performance and troubleshoot issues using industry-standard observability tools.\n\n### Features\n\n- **Distributed Tracing**: Track request flows through your cache server with detailed span data\n- **Metrics Collection**: Monitor performance metrics like request rates, latencies, and cache hit/miss ratios\n- **OTLP Export**: Supports both gRPC and HTTP protocols for exporting telemetry data\n- **Industry Standard**: Compatible with any OpenTelemetry-compliant backend\n\n### Service Identification\n\nAll traces and metrics are tagged with the service name **`decay`** (the internal Rust crate name). You'll see this identifier in your observability platform when filtering or querying telemetry data.\n\n### Supported Platforms\n\nThe OpenTelemetry integration works with all major observability SaaS platforms and open-source tools:\n\n- **Commercial Platforms**: [Datadog](https://www.datadoghq.com/), [New Relic](https://newrelic.com/), [Honeycomb](https://www.honeycomb.io/), [Lightstep](https://lightstep.com/), [Dynatrace](https://www.dynatrace.com/)\n- **Open Source**: [Jaeger](https://www.jaegertracing.io/), [Prometheus](https://prometheus.io/), [Grafana Tempo](https://grafana.com/oss/tempo/), [Zipkin](https://zipkin.io/)\n\n### Configuration\n\nTo enable OpenTelemetry export, set the following environment variables:\n\n```shell\n# OTLP endpoint (gRPC by default)\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"http://localhost:4317\"\n\n# Or use HTTP protocol\nexport OTEL_EXPORTER_OTLP_PROTOCOL=\"http/protobuf\"\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"http://localhost:4318\"\n```\n\nFor platform-specific configurations:\n\n#### Datadog\n\n```shell\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"https://api.datadoghq.com\"\nexport OTEL_EXPORTER_OTLP_HEADERS=\"dd-api-key=\u003cyour-api-key\u003e\"\n```\n\n#### Honeycomb\n\n```shell\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"https://api.honeycomb.io\"\nexport OTEL_EXPORTER_OTLP_HEADERS=\"x-honeycomb-team=\u003cyour-api-key\u003e\"\n```\n\n### Local Development\n\nFor local testing, you can use the provided Docker Compose setup that includes Jaeger and Prometheus:\n\n```shell\ndocker-compose -f docker-compose.otel.yml up\n```\n\nThis starts:\n- **Jaeger UI**: http://localhost:16686 (trace visualization)\n- **Prometheus**: http://localhost:9090 (metrics storage and queries)\n- **OpenTelemetry Collector**: Receives and routes telemetry data\n\nThen run your cache server with:\n\n```shell\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"http://localhost:4317\"\ncargo run\n```\n\nVisit Jaeger to see distributed traces and Prometheus to query metrics from your local cache server.\n\n## How does that work?\n\nTurbo Cache Server is a tiny web server written in\n[Rust](https://www.rust-lang.org/) that uses any S3-compatible bucket as its\nstorage layer for the artifacts generated by Turborepo.\n\n### What happens when there is a cache hit?\n\nHere is a diagram showing how the Turbo Cache Server works within our actions\nduring a cache hit:\n\n```mermaid\nsequenceDiagram\n    actor A as Developer\n    participant B as GitHub\n    participant C as GitHub Actions\n    participant D as Turbo Cache Server\n    participant E as S3 bucket\n    A-\u003e\u003e+B: Push new commit to GH.\u003cbr\u003eTrigger PR Checks.\n    B-\u003e\u003e+C: Trigger CI pipeline\n    C-\u003e\u003e+D: turborepo cache server via\u003cbr/\u003e\"use: turbo-cache-server@0.0.2\" action\n    Note right of C: Starts a server instance\u003cbr/\u003e in the background.\n    D--\u003e\u003e-C: Turbo cache server ready\n    C-\u003e\u003e+D: Turborepo executes task\u003cbr/\u003e(e.g. test, build)\n    Note right of C: Cache check on the Turbo cache server\u003cbr/\u003efor task hash \"1wa2dr3\"\n    D-\u003e\u003e+E: Get object with name \"1wa2dr3\"\n    E--\u003e\u003e-D: object \"1wa2dr3\" exists\n    D--\u003e\u003e-C: Cache hit for task \"1wa2dr3\"\n    Note right of C: Replay logs and artifacts\u003cbr/\u003efor task\n    C-\u003e\u003e+D: Post-action: Shutdown Turbo Cache Server\n    D--\u003e\u003e-C: Turbo Cache server terminates safely\n    C--\u003e\u003e-B: CI pipline complete\n    B--\u003e\u003e-A: PR Checks done\n```\n\n### What happens when there is a cache miss?\n\nWhen a cache isn't yet available, the Turbo Cache Server will handle new uploads\nand store the artifacts in S3 as you can see in the following diagram:\n\n```mermaid\nsequenceDiagram\n    actor A as Developer\n    participant B as GitHub\n    participant C as GitHub Actions\n    participant D as Turbo Cache Server\n    participant E as S3 bucket\n    A-\u003e\u003e+B: Push new commit to GH.\u003cbr\u003eTrigger PR Checks.\n    B-\u003e\u003e+C: Trigger CI pipeline\n    C-\u003e\u003e+D: turborepo cache server via\u003cbr/\u003e\"use: turbo-cache-server@0.0.2\" action\n    Note right of C: Starts a server instance\u003cbr/\u003e in the background.\n    D--\u003e\u003e-C: Turborepo cache server ready\n    C-\u003e\u003e+D: Turborepo executes build task\n    Note right of C: Cache check on the server\u003cbr/\u003efor task hash \"1wa2dr3\"\n    D-\u003e\u003e+E: Get object with name \"1wa2dr3\"\n    E--\u003e\u003e-D: object \"1wa2dr3\" DOES NOT exist\n    D--\u003e\u003e-C: Cache miss for task \"1wa2dr3\"\n    Note right of C: Turborepo executes task normaly\n    C--\u003e\u003eC: Turborepo executes build task\n    C-\u003e\u003e+D: Turborepo uploads cache artifact\u003cbr/\u003ewith hash \"1wa2dr3\"\n    D-\u003e\u003e+E: Put object with name \"1wa2dr3\"\n    E-\u003e\u003e-D: Object stored\n    D--\u003e\u003e-C: Cache upload complete\n    C-\u003e\u003e+D: Post-action: Turbo Cache Server shutdown\n    D--\u003e\u003e-C: Turbo Cache server terminates safely\n    C--\u003e\u003e-B: CI pipline complete\n    B--\u003e\u003e-A: PR Checks done\n```\n\n## Development\n\nTurbo Cache Server requires [Rust](https://www.rust-lang.org/) 1.75 or above. To\nsetup your environment, use the rustup script as recommended by the\n[Rust docs](https://www.rust-lang.org/learn/get-started):\n\n```shell\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n```\n\nNow run the following command to run the web server locally:\n\n```shell\ncargo run\n```\n\n### Setting up your environment\n\nDuring local development, you might want to try the Turbo Dev Server locally\nagainst a JS monorepo. As it depends on a S3-compatible service for storing\nTurborepo artifacts, we recommend using [Minio](https://min.io/) with Docker\nwith the following command:\n\n```shell\ndocker run \\\n  -d \\\n  -p 9000:9000 \\\n  -p 9001:9001 \\\n  --user $(id -u):$(id -g) \\\n  --name minio1 \\\n  -e \"MINIO_ROOT_USER=minio\" \\\n  -e \"MINIO_ROOT_PASSWORD=minio12345\" \\\n  -v ./s3_data:/data \\\n  quay.io/minio/minio server /data --console-address \":9001\"\n```\n\n#### Setting up environment variables\n\nCopy the `.env.example` file, rename it to `.env` and add the environment\nvariables required. As we use Minio locally, just go to the\n[Web UI](http://localhost:9001) of Minio, create a bucket and generate\ncredentials and copy it to the `.env` file.\n\n### Tests\n\nTo execute the test suite, run:\n\n```shell\ncargo test\n```\n\nWhile running our end-to-end tests, you might run into the following error:\n\n```log\nthread 'actix-server worker 9' panicked at /src/index.crates.io-6f17d22bba15001f/actix-server-2.4.0/src/worker.rs:404:34:\ncalled `Result::unwrap()` on an `Err` value: Os { code: 24, kind: Uncategorized, message: \"Too many open files\" }\nthread 'artifacts::list_team_artifacts_test' panicked at tests/e2e/artifacts.rs:81:29:\nFailed to request /v8/artifacts\n```\n\nThis is likely due the the maximum number of open file descriptors defined for\nyour user. Just run the following command to fix it:\n\n```shell\nulimit -n 1024\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrunojppb%2Fturbo-cache-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrunojppb%2Fturbo-cache-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrunojppb%2Fturbo-cache-server/lists"}