Deploying with BYOC Using the Edgenivo CLI
Bring Your Own Cloud is available on Enterprise plans and is set up through your Edgenivo account team. Contact your account team to request access.
Create a Bring Your Own Cloud (BYOC) deployment from your machine or CI with the Edgenivo CLI. You initialize a deployment, build it, generate its AWS resource descriptor, provision the functions in your AWS account, and then tell Edgenivo to complete the deployment.
- An AWS account connected to your Edgenivo team with the Active status.
- The ARN of a Lambda execution role in that account.
- macOS or Linux with Node.js 20 or later.
vercel deploy describedoesn't run on Windows. - Edgenivo CLI 63.1.2 or later. Install the latest version with
npm i -g vercel@latest. - The AWS CLI v2 and
jq. - AWS credentials for an identity with the provisioning permissions.
- A Edgenivo project with its build settings and environment variables configured for the target environment.
The Edgenivo CLI generates the AWS resources to create, but doesn't create them. You need a provisioning tool that reads descriptor.json and creates the Lambda layers and functions in your account. Choose one of these options:
- Generate a script with the BYOC agent skill: Install the BYOC skill in your application repository, then ask your coding agent to create a provisioning script.
- Use your own tooling: Build provisioning into your existing infrastructure tooling, such as Terraform or the AWS SDK, following the BYOC provisioning reference.
To use the BYOC skill, install it from your application's directory:
npx skills add vercel-labs/vercel-byocThen ask your coding agent to create a project script, replacing the execution role ARN with your own:
Using the BYOC skill, create `pnpm byoc:provision <deployment-id>` using the execution role arn:aws:iam::<AWS_ACCOUNT_ID>:role/byoc-lambda-execution.The rest of this guide runs that script as pnpm byoc:provision. If you use your own tooling, run your tool at the provisioning step instead.
Run every command from your application's directory, and use the same deployment ID from initialization through completion.
Set the values for your team, project, target environment, and AWS account. Use
previeworproductionfor the target, and keep the same value throughout:Terminalteam_id="<TEAM_ID>" project_name="my-app" target="preview" aws_account_id="<AWS_ACCOUNT_ID>"Authenticate the Edgenivo CLI with
vercel login, and make sure your AWS credentials point to the intended account:Terminalaws sts get-caller-identityCheck: The
Accountvalue in the output matchesaws_account_id.Link your application to the Edgenivo project, then pull the project settings for the target environment:
Terminalvercel link --yes --team "$team_id" --project "$project_name" vercel pull --yes --environment "$target" --scope "$team_id"Check:
.vercel/project.jsoncontains the intended team and project.Create a deployment on Edgenivo and save its ID.
vercel deploy inituploads no files. The deployment waits for you to provision its functions:Terminalmkdir -p .vercel/byoc vercel deploy init --yes --target "$target" --scope "$team_id" --json > .vercel/byoc/init.json deployment_id=$(jq -er '.deployment.id // .id' .vercel/byoc/init.json) jq -r '.deployment.target // .target' .vercel/byoc/init.jsonThe deployment ID is at
.idwhen you run the command in a terminal, and at.deployment.idwhen the CLI runs non-interactively, such as in CI or from a coding agent. Thejqexpression above handles both.Check: The printed target is
productionfor a production deployment, ornullfor a preview deployment. A new project's first deployment is assigned to production even when you requestpreview. If the target is wrong, mark the deployment as failed and initialize another.Build the application with the environment variables of the deployment you initialized:
Terminalvercel build --id "$deployment_id" --target "$target" --yesResult: The build output is written to
.vercel/output.Package the functions and generate the descriptor for your AWS account:
Terminalvercel deploy describe --id "$deployment_id" --aws-account-id "$aws_account_id"vercel deploy describeuses the team in.vercel/project.json, and fails if--scopeorVERCEL_ORG_IDnames a different team. It doesn't create any AWS resources.Result: The command writes these files under
.vercel/<deployment-id>/:Path Contents descriptor.jsonThe Lambda functions and layers to create in your AWS account zips/One ZIP file per function layers/One ZIP file per runtime layer build/The original build output, moved from .vercel/outputIt also replaces
.vercel/outputwith a version that contains no function code, plus aprovision.jsonfile that maps routes to Lambda functions.vercel deploy continueuploads this version.The function ZIP files contain your application code and environment variable values. Keep the
.verceldirectory private and keep the workspace until the deployment completes. For field-level details, see the BYOC provisioning reference.Run your provisioning tool with the credentials of your provisioning identity. This example selects a local AWS CLI profile with
AWS_PROFILE:TerminalAWS_PROFILE="byoc-provisioner" pnpm byoc:provision "$deployment_id"Your provisioning tool must create every layer and function in the descriptor, in each function's AWS region, and wait until each function reaches the
Activestate. The invocation role must allowlambda:InvokeFunctionon every function you create.Check: Every function in
descriptor.jsonexists in AWS with theActivestate. To list the functions and regions the descriptor expects, run:Terminaljq -r '.functions[] | "\(.region) \(.configuration.FunctionName)"' ".vercel/$deployment_id/descriptor.json"Tell Edgenivo the functions are ready.
vercel deploy continueuploads the code-free output andprovision.json, then waits for the deployment to finish:Terminalvercel deploy continue --id "$deployment_id" --scope "$team_id" vercel inspect "$deployment_id" --scope "$team_id" --waitCheck:
vercel inspectreports theREADYstatus.Request a dynamic route through the exact deployment. Replace
/api/hellowith a route in your application that runs a function:Terminalvercel curl "/api/hello" --deployment "$deployment_id" --scope "$team_id" -- --fail-with-body --silent --show-errorA static or cached response doesn't prove that BYOC is working. Confirm that the function ran in your account by checking its Amazon CloudWatch logs, using a function name and region from the descriptor:
Terminalaws logs tail "/aws/lambda/your_function_name" --region us-east-1 --since 10mCheck: The route returns the expected response, and the function's CloudWatch log group shows the invocation. If your functions run in multiple regions, confirm each region's functions exist and record which region handled your test requests.
You can change how your provisioning tool creates functions, for example to attach functions to a VPC or add Lambda layers. Keep the generated function names, handlers, runtimes, memory, timeouts, environment variables, and tags exactly as they appear in the descriptor. Edgenivo invokes each function by its generated name, so renaming a function causes requests to it to fail. For the full list of values to preserve, see Values to keep as generated.
If you attach functions to a VPC, route the subnets through a NAT gateway or equivalent egress so functions keep outbound internet access, and check your security group rules and DNS resolution.
For function packages larger than 50 MB, upload the ZIP files to a private Amazon S3 bucket in the same region as the function, and create the function from the bucket. See Function package size.
| Symptom | Cause | Fix |
|---|---|---|
Deployment dpl_... was not found, or manual provisioning is not enabled for this team. | BYOC isn't enabled for the team, or the deployment ID belongs to a different team | Confirm the deployment ID and linked team. Ask your Edgenivo account team to confirm BYOC is enabled. |
vercel deploy describe reports a scope or project mismatch | --scope, VERCEL_ORG_ID, or VERCEL_PROJECT_ID doesn't match .vercel/project.json | Remove the conflicting value or relink the project. |
vercel deploy describe rejects the build as unsupported | The build includes functions using the Edge runtime or the container runtime, or Services | Move those functions to the Node.js or Python runtime, and remove Services from the project. See BYOC limitations. |
No prebuilt output found in ".vercel/output" | vercel deploy continue ran from a different directory, or before vercel deploy describe | Run every command from the application's directory, in order. |
Provisioning exceeded the maximum allowed time. | More than 15 minutes passed between vercel deploy init and vercel deploy continue | Start a new deployment. See Failures and retries. |
The deployment is READY, but dynamic routes fail | The invocation role can't invoke the functions, or the account credentials are Expired | Check the invocation role's permissions policy and the account status in Connect AWS Account. |
- Deploy from GitHub Actions to start BYOC deployments from Git pushes
- Operate BYOC deployments, including retries and cleanup
- Review the BYOC provisioning reference
Was this helpful?