# Report Abuse Source: https://docs.vapor.build/abuse Help us keep Laravel Vapor safe by reporting any abuse, security concerns, or violations. Please email us at [security@laravel.com](mailto:security@laravel.com) # Sentry Source: https://docs.vapor.build/integrations/sentry Integrate Sentry error monitoring with Laravel Vapor. ## Overview [Sentry](https://sentry.io) provides error monitoring and tracing for Laravel applications. Vapor has partnered with Sentry to allow you to create new Sentry organizations without leaving Vapor. After creating your Sentry organization, you may easily add Sentry error monitoring to any of your Vapor projects. ## Connect with Sentry Before you can use Sentry with Vapor, you must connect your Vapor account to a Sentry account. To do this, visit the [Sentry panel](https://vapor.laravel.com/app/team/settings/sentry-organization) in the team settings dashboard. Connect with Sentry Team Settings form Clicking "Connect with Sentry" will create a new, Vapor-linked Sentry organization with the email address shown under "Sentry Account Email". You will receive an email from Sentry confirming your new organization. It is not possible to use an existing Sentry organization with the Vapor integration. Vapor created Sentry projects will be added to the new organization. ## Creating Sentry Projects Vapor allows you to create new Sentry projects directly from the Vapor dashboard. To create a new Sentry project, visit the project's Sentry dashboard. Sentry Panel Clicking "Save" will create a new project within the team owner's connected Sentry organization. Once the project is created, you will be provided with a DSN key that you may use to configure your Laravel application. Vapor does not automatically install Sentry into your Laravel application. You should install the [Sentry SDK for Laravel](https://github.com/getsentry/sentry-laravel) via Composer and define the `SENTRY_LARAVEL_DSN` environment variable. # Introduction Source: https://docs.vapor.build/introduction Manage your Laravel infrastructure on Vapor and fall in love with the scalability and simplicity of serverless. [Laravel Cloud](https://cloud.laravel.com) builds on the ideas behind Vapor while removing much of the operational complexity. [This migration guide](https://cloud.laravel.com/migration-vapor-cloud) explains why teams are migrating from Vapor to Cloud and what changes when moving an application.
Create your Vapor account today Watch the free Vapor series on Laracasts ## What Is Vapor? Laravel Vapor is an auto-scaling, serverless deployment platform for Laravel, powered by AWS Lambda. Manage your Laravel infrastructure on Vapor and fall in love with the scalability and simplicity of serverless. Vapor abstracts the complexity of managing Laravel applications on AWS Lambda, as well as interfacing those applications with SQS queues, databases, Redis clusters, networks, CloudFront CDN, and more. Some highlights of Vapor's features include: * Auto-scaling web / queue infrastructure fine tuned for Laravel * Zero-downtime deployments and rollbacks * Environment variable / secret management * Database management, including point-in-time restores and scaling * Redis Cache management, including cluster scaling * Database and cache tunnels, allowing for easy local inspection * Automatic uploading of assets to Cloudfront CDN during deployment * Unique, Vapor assigned vanity URLs for each environment, allowing immediate inspection * Custom application domains * DNS management * Certificate management and renewal * Application, database, and cache metrics * CI friendly **In short, you can think of Vapor as** [Laravel Forge](https://forge.laravel.com) **for serverless technology.** ## Requirements Vapor requires that your application be compatible with PHP 7.3+ and Laravel 6.0+. ## Account Creation Before integrating Vapor into your application, you should create a Vapor account. If you are just collaborating with others on their projects, you are not required to have a Vapor subscription. To create and manage your own projects, you will need a Vapor subscription. ## Installing The Vapor CLI You will deploy your Laravel Vapor applications using the [Vapor CLI](https://github.com/laravel/vapor-cli). This CLI may be installed globally or on a per-project basis using Composer: ```bash theme={null} composer require laravel/vapor-cli --update-with-dependencies composer global require laravel/vapor-cli --update-with-dependencies ``` When the CLI is installed per project, you will likely need to execute it via the `vendor/bin` directory of your project, which is where Composer installs executables. For example, to view all of the available Vapor CLI commands, you may use the `list` command: ```bash theme={null} php vendor/bin/vapor list ``` To save keystrokes when interacting with per-project installations of the Vapor CLI, you may add a shell alias to your operating system that aliases the `vapor` command to `php vendor/bin/vapor`. To learn more about a command and its arguments, execute the `help` command with the name of the command you wish to explore: ```bash theme={null} php vendor/bin/vapor help deploy ``` ### Logging In After you have installed the Vapor CLI, you should authenticate with your Vapor account using the `login` command: ```bash theme={null} vapor login ``` ## Installing The Vapor Core The `laravel/vapor-core` [package](https://github.com/laravel/vapor-core) must be installed as a dependency of every Laravel application that is deployed using Vapor. This package contains various Vapor runtime files and a service provider to allow your application to run on Vapor. You may install the Vapor Core into your project using Composer: ```bash theme={null} composer require laravel/vapor-core --update-with-dependencies ``` ## Sandbox Accounts After creating a Vapor account, your account will be on our free "sandbox" plan, which allows you to experience the power of Vapor without the upfront commitment of subscribing to a paid plan. A sandbox account allows you to provision services such as networks, databases, and caches. You may add a single project which, once deployed, will be accessible via an [AWS Lambda function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html). Sandbox projects may not utilize API Gateway versions, load balancers, firewalls, or custom domains. To utilize these features, you will need to choose a subscription plan. ## Teams When you create your Vapor account, a "Personal" team is automatically created for you. You can rename this team in your team settings. All projects, databases, caches, and other Vapor resources belong to a team. You are free to create as many teams as you wish via the Vapor UI or the `team` CLI command. There is no additional charge for creating teams, and they serve as a great way to organize your projects by client or topic. ### Current Team & Switching Teams When managing Vapor resources via the CLI, you will need to be aware of your currently active team. You may view your current team using the `team:current` command: ```bash theme={null} vapor team:current ``` To change your active team, you may use the `team:switch` command: ```bash theme={null} vapor team:switch ``` ### Collaborators You can invite more people to your team via the "Team Settings" menu in the Vapor UI, or using the `team:add` CLI command. When you add a new collaborator to your team via the Vapor UI, you may select the permissions to assign to that person. For example, you can prevent a given team member from deleting databases or caches. You may remove collaborators from your team using the Vapor UI or `team:remove` CLI command. ## Linking With AWS In order to deploy projects or create other resources using Vapor, you will need to link an active AWS account on your team's settings management page. ### Creating An IAM Role To create a new IAM role, navigate to the IAM service on your AWS dashboard. Once you are in the IAM dashboard, you may select "Roles" from the left-side navigation panel and click the "Create Role" button. The process for creating the role is outlined in these steps: 1. Choose "AWS account" as the trusted entity type, and select "Another AWS account". 2. Enter the "Vapor Account ID" from the Vapor dashboard. 3. Under "Options", enable the "Require external ID" checkbox, enter the "Team External ID" shown in the Vapor dashboard, and then click "Next". 4. In the "Permissions policies" section, either grant full administrator access by selecting the `AdministratorAccess` policy or create a custom policy with the [specific permissions](/introduction#permissions) required by Vapor. After selecting a policy, click "Next". 5. In the "Name, review, and create" section, provide a name and description for the role. 6. Complete the process by creating the role. 7. Copy the role ARN displayed in the AWS dashboard and add it to your AWS credentials in Vapor. #### Permissions Since Vapor manages many types of resources across more than a dozen AWS services, it may be convenient to create a role with the `AdministratorAccess` policy. If desired, you may create a separate AWS account to house this role and contain all of your Vapor resources. On the permissions management screen, you may grant full administrator access to the IAM role by selecting the "AdministratorAccess" policy. Or, you would prefer to not provide administrator access to Vapor, you may instead create a custom permission policy with the specific permissions needed by Vapor. It is necessary to create two policies due to the policy size limit set by AWS. To do so, select "Create policy" from the "Permissions policies" panel. Choose the JSON option and provide the first permission definition below. Then, follow the same process to create another policy using the second definition listed below. Once the policies have been defined, you may attach them to your new IAM role: ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Sid": "VaporPolicy", "Effect": "Allow", "Action": [ "acm:AddTagsToCertificate", "acm:DeleteCertificate", "acm:DescribeCertificate", "acm:ImportCertificate", "acm:RequestCertificate", "apigateway:DELETE", "apigateway:GET", "apigateway:PATCH", "apigateway:POST", "apigateway:PUT", "apigateway:SetWebACL", "budgets:ModifyBudget", "budgets:ViewBudget", "cloudformation:CreateStack", "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:UpdateStack", "cloudfront:CreateOriginAccessControl", "cloudfront:CreateDistribution", "cloudfront:DeleteDistribution", "cloudfront:GetDistribution", "cloudfront:GetDistributionConfig", "cloudfront:UpdateDistribution", "cloudwatch:DeleteAlarms", "cloudwatch:GetMetricStatistics", "cloudwatch:PutMetricAlarm", "dynamodb:CreateTable", "dynamodb:DescribeTable", "dynamodb:DescribeTimeToLive", "dynamodb:TagResource", "dynamodb:UpdateTimeToLive", "ec2:AllocateAddress", "ec2:AssociateAddress", "ec2:AssociateRouteTable", "ec2:AttachInternetGateway", "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateInternetGateway", "ec2:CreateNatGateway", "ec2:CreateRoute", "ec2:CreateRouteTable", "ec2:CreateSubnet", "ec2:CreateTags", "ec2:CreateVpc", "ec2:CreateVpcEndpoint", "ec2:DeleteInternetGateway", "ec2:DeleteKeyPair", "ec2:DeleteNatGateway", "ec2:DeleteRoute", "ec2:DeleteRouteTable", "ec2:DeleteSubnet", "ec2:DeleteVolume", "ec2:DeleteVpc", "ec2:DeleteVpcEndpoints", "ec2:DescribeAddresses", "ec2:DescribeAvailabilityZones", "ec2:DescribeImages", "ec2:DescribeInstanceAttribute", "ec2:DescribeInstances", "ec2:DescribeInternetGateways", "ec2:DescribeKeyPairs", "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", "ec2:DescribeRegions", "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroupRules", "ec2:DescribeSecurityGroups", "ec2:DescribeSnapshots", "ec2:DescribeSubnets", "ec2:DescribeTransitGatewayRouteTables", "ec2:DescribeTransitGatewayVpcAttachments", "ec2:DescribeTransitGateways", "ec2:DescribeVolumes", "ec2:DescribeVpcEndpoints", "ec2:DescribeVpcs", "ec2:DetachInternetGateway", "ec2:DisassociateRouteTable", "ec2:ImportKeyPair", "ec2:ModifySubnetAttribute", "ec2:ModifyVpcAttribute", "ec2:ReleaseAddress", "ec2:RevokeSecurityGroupEgress", "ec2:RevokeSecurityGroupIngress", "ec2:RunInstances", "ec2:TerminateInstances", "ecr:BatchCheckLayerAvailability", "ecr:BatchDeleteImage", "ecr:BatchGetImage", "ecr:CompleteLayerUpload", "ecr:CreateRepository", "ecr:DeleteRepository", "ecr:GetAuthorizationToken", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:InitiateLayerUpload", "ecr:PutImage", "ecr:SetRepositoryPolicy", "ecr:UploadLayerPart", "elasticache:AddTagsToResource", "elasticache:CreateCacheSubnetGroup", "elasticache:CreateReplicationGroup", "elasticache:CreateServerlessCache", "elasticache:DeleteCacheSubnetGroup", "elasticache:DeleteReplicationGroup", "elasticache:DeleteServerlessCache", "elasticache:DescribeCacheSubnetGroups", "elasticache:DescribeReplicationGroups", "elasticache:DescribeServerlessCaches", "elasticache:ListTagsForResource", "elasticache:ModifyReplicationGroupShardConfiguration", "elasticache:ModifyServerlessCache", "elasticloadbalancing:AddListenerCertificates", "elasticloadbalancing:AddTags", "elasticloadbalancing:CreateListener", "elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateRule", "elasticloadbalancing:CreateTargetGroup", "elasticloadbalancing:DeleteLoadBalancer", "elasticloadbalancing:DescribeListenerCertificates", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeRules", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:ModifyListener", "elasticloadbalancing:ModifyRule", "elasticloadbalancing:ModifyTargetGroupAttributes", "elasticloadbalancing:RegisterTargets", "elasticloadbalancing:SetWebAcl", "events:DeleteRule", "events:DescribeRule", "events:ListTargetsByRule", "events:PutRule", "events:PutTargets", "events:RemoveTargets", "iam:CreateRole", "iam:CreateServiceLinkedRole", "iam:GetRole", "iam:GetUser", "iam:PassRole", "iam:PutRolePolicy", "iam:UpdateAssumeRolePolicy", "kms:CreateGrant", "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", "kms:GenerateDataKey", "lambda:AddPermission", "lambda:CreateAlias", "lambda:CreateEventSourceMapping", "lambda:CreateFunction", "lambda:CreateFunctionUrlConfig", "lambda:DeleteFunction", "lambda:DeleteFunctionConcurrency", "lambda:DeleteProvisionedConcurrencyConfig", "lambda:GetAccountSettings", "lambda:GetAlias", "lambda:GetFunction", "lambda:GetFunctionUrlConfig", "lambda:GetLayerVersion", "lambda:GetPolicy", "lambda:InvokeFunction", "lambda:InvokeFunctionUrl", "lambda:ListEventSourceMappings", "lambda:ListVersionsByFunction", "lambda:PublishVersion", "lambda:PutFunctionConcurrency", "lambda:PutFunctionEventInvokeConfig", "lambda:PutProvisionedConcurrencyConfig", "lambda:TagResource", "lambda:UpdateAlias", "lambda:UpdateEventSourceMapping", "lambda:UpdateFunctionCode", "lambda:UpdateFunctionConfiguration", "logs:FilterLogEvents", "rds:AddTagsToResource", "rds:CreateDBCluster", "rds:CreateDBInstance", "rds:CreateDBProxy", "rds:CreateDBSubnetGroup", "rds:DeleteDBCluster", "rds:DeleteDBInstance", "rds:DeleteDBProxy", "rds:DeleteDBSubnetGroup", "rds:DescribeDBClusters", "rds:DescribeDBEngineVersions", "rds:DescribeDBInstances", "rds:DescribeDBProxies", "rds:DescribeDBSubnetGroups", "rds:ListTagsForResource", "rds:ModifyDBCluster", "rds:ModifyDBInstance", "rds:RegisterDBProxyTargets", "rds:RestoreDBInstanceToPointInTime", "route53:ChangeResourceRecordSets", "route53:CreateHostedZone", "route53:GetHostedZone", "route53:ListHostedZonesByName", "route53:ListResourceRecordSets", "s3:CreateBucket", "s3:DeleteBucket", "s3:DeleteBucketPolicy", "s3:DeleteObject", "s3:GetBucketCORS", "s3:GetBucketLocation", "s3:GetBucketTagging", "s3:GetBucketVersioning", "s3:GetObject", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:PutBucketCORS", "s3:PutBucketOwnershipControls", "s3:PutBucketPublicAccessBlock", "s3:PutLifecycleConfiguration", "s3:PutObject", "s3:PutObjectAcl", "s3:PutBucketPolicy", "secretsmanager:CreateSecret", "secretsmanager:DeleteSecret", "secretsmanager:GetSecretValue", "secretsmanager:TagResource", "servicequotas:GetServiceQuota", "ses:VerifyDomainDkim", "ses:VerifyDomainIdentity", "sns:ConfirmSubscription", "sns:CreateTopic", "sns:GetTopicAttributes", "sns:ListSubscriptionsByTopic", "sns:SetTopicAttributes", "sns:Subscribe", "sns:TagResource" ], "Resource": "*" } ] } ``` ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Sid": "VaporPolicy", "Effect": "Allow", "Action": [ "sqs:CreateQueue", "sqs:DeleteQueue", "sqs:GetQueueAttributes", "sqs:GetQueueUrl", "sqs:SetQueueAttributes", "ssm:DeleteParameter", "ssm:DeleteParameters", "ssm:PutParameter", "ssm:UpdateServiceSetting", "wafv2:AssociateWebACL", "wafv2:CreateWebACL", "wafv2:DeleteWebACL", "wafv2:GetWebACL", "wafv2:ListResourcesForWebACL", "wafv2:TagResource", "wafv2:UpdateWebACL" ], "Resource": "*" } ] } ``` It's probable this list of permissions will change as we add new features to Vapor, which may result in unexpected errors if your policy is not kept up to date. #### Defining Your AWS Budget When linking your AWS account to Vapor, it is important to stay informed about your AWS costs. This can be done directly in the AWS Console using the AWS Budgets service. In addition, you can use Vapor's managed budgets to define your monthly AWS budget in USD, while also configuring multiple alarms directly on the "Team Settings > AWS Accounts" screen of the Vapor UI. At this time, up to five alarms can be configured: * Actual cost > 85% * Actual cost > 100% * Actual cost > 200% * Actual cost > 500% * Forecasted cost > 100% Each alarm can be triggered once per monthly billing period. When an alarm is triggered, the team owner will receive an email, allowing them to act quickly and avoid unexpected charges. #### AWS Service Limits AWS Service Limits can be increased through the following options: 1. Open the Service Quotas console. 2. In the navigation pane, choose AWS services. 3. Select a service. 4. Select a quota. 5. Follow the directions to request a quota increase. 1. Use the [request-service-quota-increase](https://docs.aws.amazon.com/cli/latest/reference/service-quotas/request-service-quota-increase.html) AWS CLI command. * If a service is not yet available in Service Quotas, use the AWS Support Center Console to create a [service quota increase case](https://support.console.aws.amazon.com/support/home#/case/create?issueType=service-limit-increase). * If the service is available in Service Quotas, AWS recommends that you use the [Service Quotas console](https://console.aws.amazon.com/servicequotas/home) instead of creating a support case. For additional information, refer to the following AWS documentation: * [Requesting a quota increase](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html) in the *Service Quotas User Guide*. * [AWS Service Quotas reference](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html). ## Notification Methods ### Slack In order to receive notifications via Slack, you will need to [create a Slack App](https://api.slack.com/apps) and select the workspace to which the Slack App should be installed. Once the Slack App has been created, visit the **Incoming Webhooks** settings pane of your App under the "Features" sidebar. Then, activate the Incoming Webhooks feature using the activation switch. Once activated, you can create a new Incoming Webhook using the **Add New Webhook to Workspace** button. Finally, you should copy the Webhook URL provided by Slack and insert into your team's [Notifications Settings](https://vapor.laravel.com/app/team/settings/notification-methods). ## Legal and Compliance Our [Terms of Service](https://vapor.laravel.com/terms) and [Privacy Policy](https://vapor.laravel.com/privacy) provide details on the terms, conditions, and privacy practices for using Laravel Vapor. # Troubleshooting Source: https://docs.vapor.build/kb/troubleshooting Common questions and issues when using Laravel Vapor. ## Performance Issues While you can achieve blazing-fast load times in your Laravel applications powered by Vapor, you may face performance issues if you misconfigure your infrastructure. In this section, we'll cover the Vapor **most common infrastructure performance tips** that may speed your Laravel applications powered by Vapor. Before we dive in, please keep in mind: 1. **Optimize your application first**: by making your application faster you may not require any infrastructure changes at all. Identify application performance bottlenecks and try to solve them using simple techniques such as caching, queuing, or database query optimizations. 2. **Infrastructure changes may have an impact on your AWS bill**: Of course, allocating more (or different) resources for your Vapor environment may cause your AWS bill to increase. Therefore, you may need to study how the pricing of that changes will affect your AWS bill: **[aws.amazon.com/pricing](https://aws.amazon.com/pricing/)**. #### Increasing the `memory` option Vapor - via AWS Lambda - allocates CPU power to your Lambda function in proportion to the amount of memory configured for the environment. Therefore, increasing the memory may lead to better performance as the Lambda function will have more CPU power to process your requests and queued jobs. You may increase the configured memory for the HTTP Lambda function, Queue Lambda function, or CLI Lambda function using the [`memory`](/projects/environments#memory), [`queue-memory`](/resources/queues#queue-memory), or `cli-memory` options, respectively, in your environment's `vapor.yml` configuration. #### Increasing the `warm` option If you are facing post-deployment performance issues at scale, that may indicate that your environment does not "pre-warm" enough containers in advance. Therefore, some requests incur a penalty of a few seconds while AWS loads a serverless container to process the request. To mitigate this issue - commonly known as "cold-starts" - Vapor allows you to define a [`warm`](/projects/environments#prewarming) configuration value for an environment in your `vapor.yml` file. The `warm` value represents how many serverless containers Vapor will "pre-warm" so they can be ready to serve requests. #### Using "fixed-size" databases Serverless databases are auto-scaling databases that do not have a fixed amount of RAM or disk space. Yet, the "auto-scaling" mechanism offered by AWS can have cold start times of up to a few seconds every time your environment needs more database resources. To mitigate this issue, consider using "fixed-size" databases where resources are prepared in advance. You may [create "fixed-size" databases](/resources/databases#fixed-size-databases) using the Vapor UI or using the `database` CLI command. #### Using database proxies Even though your serverless Laravel applications powered by Vapor can handle extreme amounts of web traffic, traditional relational databases such as MySQL can become overwhelmed and crash due to connection limit restrictions. To mitigate this issue, Vapor allows the usage of an **[RDS proxy](https://aws.amazon.com/rds/proxy/)** to efficiently manage your database connections and allow many more connections than would typically be possible. The database proxy [can be added](/resources/databases#database-proxies) via the Vapor UI or the `database:proxy` CLI command. #### Scale existing "fixed-size" resources If you are facing performance issues at scale, that may indicate that existing resources - such as "fixed-size" databases or "fixed-size" caches - may not be able to keep up with the number of tasks managed by your application. To mitigate this issue, consider scale existing "fixed-size" resources, if any. For example, you may [scale "fixed-size" databases](/resources/databases#scaling-databases) via the Vapor UI's database detail screen or the `database:scale` CLI command. #### Consider Redis over DynamoDB If your application heavily relies on caching - which is already a great way to massively speed up your application - using a Redis cache instead of DynamoDB can speed up cache IO. You may [create caches](/resources/caches#introduction) using the Vapor UI or using the `cache` CLI command. #### Consider API Gateway v2 instead of API Gateway v1 By migrating from API Gateway v1 to API Gateway v2, you can expect 50% less latency in the requests to your application. However, API Gateway v2 is regional, meaning that customers from a region very distant from your project may be negatively affected by this change. Also, some features, like Vapor's managed Firewall, may not be available. If you would like to [use API Gateway 2.0](/projects/environments#gateway-versions), you may specify `gateway-version: 2` in your environment's `vapor.yml` configuration. #### Contact AWS Support Laravel Vapor provisions and configures your projects on the AWS infrastructure. However, for performance insights regarding your infrastructure, we recommend you to reach out to [AWS Support](https://console.aws.amazon.com/support/home?#/case/create?issueType=technical) as they can deeply examine the internal logs of your infrastructure. ## 502 Bad Gateway Or "Internal Server Error" Typically, a 502 Bad Gateway or an "Internal Server Error" is thrown when the Lambda function fails to handle the request internally. Most of the time this is because the request has timed out or because the payload / response is exceeding the size allowed by AWS. You can see if a request has timed out by searching for "Task timed out" messages in your environment logs. Here are some common solutions to "time out" issues: 1. Change the [`timeout`](/projects/environments#timeout) value on your `vapor.yml` file and deploy your application again. 2. Try to identify the code that may be causing this "time out" issue. This may be related resources configured incorrectly, or a task may take longer than expected — in this case, please consider using [queues](/resources/queues) for heavy tasks. 3. Alternatively, you can reach [AWS Support](https://console.aws.amazon.com/support/home?#/case/create?issueType=technical) - as they can deeply examine the internal logs of your infrastructure. If you don't see any "Task timed out" messages in your environment logs, this indicates the error is likely because the payload / response is exceeding the size allowed by AWS. Please consult AWS's [API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html) and [Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-limits.html) quotas. ## Sandbox URL Returns 400 "message: null" Square brackets used in the query string of a Lambda function URL must be URL encoded. Failure to do so results in a 400 status code error being returned by the application. This is due to an AWS limitation in the mapping between the URL and Lambda functions. It is most common to encounter this issue when attempting to send arrays of data as part of the URL: ``` https://xyz.lambda-url.us-east-1.on.aws?items[]=1 ❌ https://xyz.lambda-url.us-east-1.on.aws?items%5B%5D=1 ✅ ``` ## Account Termination To permanently delete your Vapor account, follow these steps: 1. **Verify Resource Removal**: Ensure all resources, such as projects, environments, and related AWS resources, are deleted. 2. **Unlink AWS Account**: In your team settings, make sure your AWS account is unlinked from Vapor to prevent future deployments or resource creation. 3. **Revoke IAM Roles**: Remove any IAM roles or permissions created for Vapor in your AWS console. 4. **Cancel Subscription**: Check your billing settings on the Vapor dashboard to ensure any active subscriptions are canceled. 5. **Final Confirmation**: Once the steps above are complete, contact [vapor@laravel.com](mailto:vapor@laravel.com) to finalize the account deletion. # Deployments Source: https://docs.vapor.build/projects/deployments Learn how to deploy your Laravel applications to Laravel Vapor. ## Introduction Of course, one of the primary features of Laravel Vapor is atomic, zero-downtime deployments. Unlike many other features of Vapor, deployments are **only initiated via the Vapor CLI**. During deployment, Vapor will run the `build` steps of your `vapor.yml` file on the local machine that the deployment is running on. This might be your personal machine or a continuous integration platform. ## Initiating Deployments To initiate a deployment, execute the `deploy` CLI command from the root of your application: ```bash theme={null} vapor deploy production ``` By default, when you run `vapor deploy production`, Vapor will look for a `vapor.yml` manifest file. However, you can specify a custom manifest using the `--manifest` option: ```bash theme={null} vapor deploy production --manifest vapor-eu-west-1.yml ``` AWS Lambda has strict limitations on the size of applications running within the environment. If your application exceeds this limit, you may take advantage of Vapor's [Docker based deployments](/projects/environments#building-custom-docker-images). Docker based deployments allow you to package and deploy applications up to 10GB in size. ## Build Hooks You may define build hooks for an environment using the `build` key within your `vapor.yml` file. These commands are executed on the local machine that the deployment is running on and may be used to prepare your application for deployment. During deployment, your application is built within a temporary `.vapor` directory that is created by the CLI and all of your `build` commands will run within that temporary directory: ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: memory: 1024 database: vapor-app cache: vapor-cache build: - 'composer install --no-dev' - 'php artisan event:cache' deploy: - 'php artisan migrate --force' ``` ## Deploy Hooks You may define deployment hooks for an environment using the `deploy` key within your `vapor.yml` file. These commands are executed against the deployed environment **before it is activated for general availability**. If any of these commands fail, the deployment will not be activated. ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: memory: 1024 database: vapor-app cache: vapor-cache build: - 'composer install --no-dev' - 'php artisan event:cache' deploy: - 'php artisan migrate --force' ``` ### Reviewing Output / Logs When a deployment hook fails, you may review the output / logs via the Vapor UI's deployment detail screen. Also, if you are deploying your application using the `vapor deploy` command, the CLI output will contain the failing hook output. Of course, you may review the output at any time using the `hook:output` command: ```bash theme={null} vapor hook:output {DEPLOYMENT_HOOK_ID} ``` You can review the logs associated with the failing hook using the `hook:log` command: ```bash theme={null} vapor hook:log {DEPLOYMENT_HOOK_ID} ``` [Native Vapor runtimes](/projects/environments#runtime) do not support [squashed migrations](https://laravel.com/docs/migrations#squashing-migrations). If you wish to utilize this feature of Laravel, you may take advantage of Vapor's [Docker based deployments](/projects/environments#docker-runtimes) ## Assets During deployment, Vapor will automatically extract all of the assets in your Laravel project's `public` directory and upload them to S3. In addition, Vapor will create a AWS CloudFront (CDN) distribution to distribute these assets efficiently around the world. Because all of your assets will be served via S3 / CloudFront, you should always generate URLs to these assets using Laravel's `asset` helper. Vapor injects an `ASSET_URL` environment variable which Laravel's `asset` helper will use when constructing your URLs: ```php theme={null} ``` On subsequent deployments, only the assets that have changed will be uploaded to S3, while unchanged assets will be copied over from the previous deployment. ### Custom Asset Domains If you would like to use your own domain to serve your assets, you may do so by attaching a custom asset domain to your project. First, you should [ensure a DNS zone exists](/projects/domains.html#adding-domains) for the domain and that a [certificate is issued](/projects/domains.html#requesting-ssl-certificates) for the domain in the `us-east-1` region. Next, set the `asset-domain` option of your `vapor.yml` file to your chosen domain: ```yml theme={null} id: 3 name: vapor-app asset-domain: assets.laravel.rocks environments: production: ... ``` During a subsequent deployment of any environment associated with your project, Vapor will add the custom domain as an alias to your CloudFront distribution. Vapor will also inject the relevant environment variables for the [asset helper](/projects/deployments#assets) and Vite asset compilation process to ensure your assets are served from your custom asset domain. ### Referencing Assets From JavaScript If you are referencing your project's public assets in your JavaScript code, you may generate URLs to these assets using Vapor's NPM package. This package includes a `Vapor.asset` helper that will behave like Laravel's `asset` helper but on the client. To get started, install the `laravel-vapor` NPM package: ```bash theme={null} npm install --save-dev laravel-vapor ``` Next, within your application's `app.js` file, initialize the global Vapor JavaScript object: ```js theme={null} // Vite import Vapor from 'laravel-vapor' window.Vapor = Vapor // Mix window.Vapor = require('laravel-vapor'); ``` Finally, you may call the `Vapor.asset` helper in your JavaScript code: ```js theme={null} $('#container').prepend($('', { src: Vapor.asset('avatar.png') })) ``` Or, if you are using Vue, you may find it convenient to add the following mixin to your Vue application: ``` Vue.mixin({ methods: { asset: window.Vapor.asset }, }); // Within your Vue components... ``` If you are using Laravel Vite with your project, you only need to utilize the `asset` helper when you are referencing assets you don't want bundled, such as those that already live in your public directory. If you want to use the `asset` helper with your Vite project, you will also need to specify the base URL for assets in your application's entry point, for example in your `resources/js/app.js`, like so: `Vapor.withBaseAssetUrl(import.meta.env.VITE_VAPOR_ASSET_URL)` ### Asset Compilation If you are compiling your application's assets in one of the build steps listed in your `vapor.yml` configuration file, you may need your build script to be able to access your environment variables. An excellent example of this requirement is instantiating a frontend SDK such as Pusher. Build steps are executed in the environment where a deployment is initiated - typically, this will be your local machine or your CI pipeline. As such, you must ensure the required environment variables are available in that environment. To assist with this, Vapor will attempt to load variables first from `.env.[environment]` (e.g. `.env.staging`). If that file does not exist, Vapor will attempt to load variables from the `.env` file. You should ensure one of these file contains all of the environment variables needed by that environment's build script. When using CI platforms, you may not have access to the environment files as these are typically omitted from version control. In this scenario, your CI provider will typically provide a mechanism for injecting variables into the build pipeline. For instance, with GitHub Actions, your GitHub Action configuration might look like the following: ```yml theme={null} - name: Deploy Environment run: vapor deploy production env: VITE_PUSHER_APP_KEY: ${{ secrets.VITE_PUSHER_APP_KEY }} ``` When using Vite and running `npm run build`, Vite will always use the `.env.production` file if it is present, even if you are deploying a different environment. If you maintain multiple environment files in your deployment environment, you should set the Vite build mode explicitly: ```shell theme={null} npm run build -- --mode staging ``` ### Code Splitting / Dynamic Imports With Mix If you are taking advantage of JavaScript dynamic imports and code splitting in your project via Laravel Mix, you will need to let Webpack know where the child chunks will be loaded from for each deployment. To accomplish this, you can take advantage of the `ASSET_URL` variable that Laravel Vapor injects into your environment during your build step: ```javascript theme={null} const mix = require("laravel-mix"); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel application. By default, we are compiling the Sass | file for the application as well as bundling up all the JS files. | */ mix .js("resources/js/app.js", "public/js") .sass("resources/sass/app.scss", "public/css"); if (mix.inProduction()) { const ASSET_URL = process.env.ASSET_URL + "/"; mix.webpackConfig(webpack => { return { plugins: [ new webpack.DefinePlugin({ "process.env.ASSET_PATH": JSON.stringify(ASSET_URL) }) ], output: { publicPath: ASSET_URL } }; }); } ``` ### Hot Module Replacement With Mix If you are using code splitting and "hot module replacement" with Laravel Mix during local development, you will need to use the `mix` helper locally and the `asset` helper when deploying to Vapor: ```php theme={null} @if (app()->environment('local')) @else @endif ``` ### URLs Within CSS Sometimes, your CSS may need to reference asset URLs, such as a `background-image` property that references an image via URL. Obviously, you are not able to use the PHP `asset` helper within your CSS. For this reason, Vapor will automatically prepend the correct asset base URL to all relative URLs in your CSS during the build process. After your build steps have executed, Vapor performs this action against any CSS files in your application's `public` directory (including directories nested under `public`). ### Root Domain Assets Some applications, such as PWAs, may need to serve certain assets from the root domain. If your application has this need, you can define an array of assets that should be served from your application's root domain via the `serve_assets` configuration option within your `vapor` configuration file: ```php theme={null} /* |-------------------------------------------------------------------------- | Servable Assets |-------------------------------------------------------------------------- | | Here you can configure list of public assets that should be servable | from your application's domain instead of only being servable via | the public S3 "asset" bucket or the AWS CloudFront CDN network. | */ 'serve_assets' => [ 'serviceWorker.js', ], ``` If your application doesn't contain a `vapor` configuration file, you can publish it using the `vendor:publish` Artisan command: ``` php artisan vendor:publish --tag=vapor-config ``` Due to the serverless nature of applications powered by Vapor, assets served from the root domain are not cacheable at the client-side and they are served using Laravel routes. Therefore, you should only serve assets that absolutely must be served from the root domain as there is a slight performance penalty for doing so. ### Dot Files As Assets Typically, "dot" files are not uploaded to the AWS CloudFront CDN by Vapor. However, if you need the public directory's dot files to be uploaded as assets, you should set the `dot-files-as-assets` key to `true` in your `vapor.yml` file: ```yml theme={null} id: 1 name: app-test dot-files-as-assets: true ``` You may also choose to serve asset dot files from the application's root domain: ```php theme={null} 'serve_assets' => [ 'serviceWorker.js', '.well-known/assetlinks.json', ], ``` ### Root Domain robots.txt By default, Vapor will redirect requests to your application's `robots.txt` file to the S3 asset bucket or CloudFront's asset URL. If you would like the `robots.txt` file to be served directly from your application, you may set the `redirect_robots_txt` configuration value to `false` within your application's `config/vapor.php` configuration file: ```php theme={null} 'redirect_robots_txt' => false, ``` If your application doesn't contain a `vapor` configuration file, you can publish it using the `vendor:publish` Artisan command: ``` php artisan vendor:publish --tag=vapor-config ``` ## Redeploying Sometimes you may need to simply redeploy a given environment without rebuilding it. For example, you may wish to do this after updating an environment variable. To accomplish this, you may use the Vapor UI or the `redeploy` CLI command: ```bash theme={null} vapor redeploy production ``` ## Rollbacks To rollback to a previous deployment, you may select the deployment in the Vapor UI and click the "Rollback To" button, or you may use the `rollback` CLI command. The `rollback` command's "--select" option will allow you to select which deployment to rollback to from a list of recent deployments. If the `rollback` command is executed without this option, it will simply rollback to the most previous successful deployment: ```bash theme={null} vapor rollback production vapor rollback production --select ``` When rolling back to a previous deployment, Vapor will use the environment's variables and secrets as they existed at the time the deployment you're rolling back to was originally deployed. ## Deploying From CI So far, we have discussed deploying Vapor projects from your local command line. However, you may also deploy them from a CI platform of your choice. Since the Vapor CLI client is part of your Composer dependencies, you may simply execute the `vapor deploy` command in your CI platform's deployment pipeline. In order to authenticate with Vapor from your CI platform, you will need to add a `VAPOR_API_TOKEN` environment variable to your CI build environment. You may generate an API token in your [Vapor API settings dashboard](https://vapor.laravel.com/app/account/api-tokens). ### Git Commit Information Some CI platforms expose the Git commit information as environment variables during your build. You may pass this information to the `vapor deploy` command. For example, if using CodeShip: ```sh theme={null} vapor deploy production --commit="${CI_COMMIT_ID}" --message="${CI_MESSAGE}" ``` The commit hash will be injected into your application's environment variables as `VAPOR_COMMIT_HASH`. ### Example With GitHub Actions If your application uses [GitHub Actions](https://github.com/features/actions) as its CI platform, the following guidelines will assist you in configuring Vapor deployments so that your application is automatically deployed when someone pushes a commit to the `master` branch: 1. First, add the `VAPOR_API_TOKEN` environment variable to your "GitHub > Project Settings > Secrets" settings so that GitHub can authenticate with Vapor while running actions. 2. Next, create a `deploy.yml` file within the `your-project/.github/workflows` directory. The file should have the following contents: ```yml theme={null} name: Deploy on: push: branches: [ master ] jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: 8.5 tools: composer:v2 coverage: none - name: Require Vapor CLI run: composer global require laravel/vapor-cli - name: Install Project Dependencies run: composer install --no-interaction --prefer-dist --optimize-autoloader - name: Deploy Environment run: vapor deploy production --commit="${{ github.sha }}" --message="${{ github.event.head_commit.message }}" env: VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }} ``` 3. Finally, you can edit the `deploy.yml` file to fit your application's deployment needs, as it may require a different PHP version or a library like `npm`. Once you are done, commit and push the `deploy.yml` file to `master` so GitHub Actions can run the first deployment job. #### Docker Arm Runtime Since GitHub actions run on the `x86_64` architecture, they are unable to natively compile `arm64` based images. In order to compile the `docker-arm` runtime, the `arm64` platform can be emulated using QEMU. To get started, add the following to your `deploy.yml`, directly after the "Checkout Code" step: ```yml theme={null} - name: Setup QEMU uses: docker/setup-qemu-action@v2 with: platforms: arm64 ``` When building a `docker-arm` image via GitHub Actions or other CI environments that emulate the `arm64` architecture using QEMU, you should disable Docker's build provenance attestations by setting `provenance=false`. Without this option, the build may produce a manifest list instead of a single image, which can cause deployment failures. You may specify Docker build options via the `docker-build-options` configuration option within your application's `vapor.yml` file. The `docker-build-options` option accepts an array of strings, where each string corresponds to a flag passed to the `docker build` command: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: runtime: docker-arm docker-build-options: - provenance=false build: - 'composer install --no-dev' ``` ### Example With Chipper CI If your application uses [Chipper CI](https://chipperci.com/) as its CI platform, the following guidelines will assist you in configuring Vapor deployments so that your application is automatically deployed when someone pushes a commit to the `master` branch: 1. First, add the `VAPOR_API_TOKEN` environment variable to your "Chipper CI > Project Settings > Project Environment Variables" settings so that Chipper CI can authenticate with Vapor while running your build pipeline. 2. Then, on the "Build Pipeline" dashboard, add a step with the name `Deploy` and the following content: ```bash theme={null} if [[ $CI_COMMIT_BRANCH == 'master' ]]; then composer install --no-interaction --prefer-dist --optimize-autoloader composer global require laravel/vapor-cli vapor deploy fi ``` 3. Next, commit and push any change to the `master` branch so that Chipper CI will deploy your application. If you plan to use Docker based runtimes to run your Vapor application, you must purchase a Chipper CI paid plan and enable Docker in each project that contains a Docker based Vapor application. # Development Source: https://docs.vapor.build/projects/development Learn how to develop applications for Laravel Vapor. ## Binary Responses To return binary responses, such as PDF downloads, from your Vapor application, your HTTP response should include the `X-Vapor-Base64-Encode` header: ```php theme={null} return $response->withHeaders([ 'X-Vapor-Base64-Encode' => 'True', ]); ``` Lambda limits responses to 6MB. If you need to serve a larger file, consider returning a signed, temporary S3 URL that your user may use to download the file directly from S3. ## Configuring OpenSSL To use certain OpenSSL functions such as [openssl\_pkey\_new](https://www.php.net/manual/en/function.openssl-pkey-new.php), you must create an `openssl.cnf` configuration file and instruct Vapor to load it via the `OPENSSL_CONF` environment variable. For example, this environment variable will instruct Vapor to load an `openssl.cnf` file from the root of your project: ```ini theme={null} OPENSSL_CONF="/var/task/openssl.cnf" ``` An example `openssl.cnf` file is available below: ```ini theme={null} dir = certificates [ ca ] default_ca = CA_default [ CA_default ] serial = $dir/serial database = $dir/index.txt new_certs_dir = $dir/newcerts certificate = $dir/cacert.pem private_key = $dir/private/cakey.pem default_days = 36500 default_md = sha256 preserve = no email_in_dn = no nameopt = default_ca certopt = default_ca policy = policy_match [ policy_match ] commonName = supplied countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional emailAddress = optional [ req ] default_bits = 2048 default_keyfile = priv.pem default_md = sha256 distinguished_name = req_distinguished_name req_extensions = v3_req encyrpt_key = no [ req_distinguished_name ] [ v3_ca ] basicConstraints = CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always [ v3_req ] basicConstraints = CA:FALSE subjectKeyIdentifier = hash ``` ## "After Response" Jobs In typical Laravel applications, you may dispatch jobs that will be executed after the HTTP response is sent to the browser: ```php theme={null} Route::get('/', function () { dispatch(function () { Mail::to('taylor@example.com')->send(new WelcomeMessage); })->afterResponse(); return view('home'); }); ``` However, we recommend that you always dispatch jobs to your queue workers when using Vapor. Vapor is not able to execute a job after sending a response to the browser; therefore, attempting to do so will cause your application to appear slower to the end user. ## Inertia SSR Currently, Inertia server-side rendering (SSR) is not available on Vapor environments due to constraints of AWS Lambda. For applications requiring [Inertia with SSR capabilities](https://inertiajs.com/server-side-rendering), we recommend: * **[Laravel Cloud](https://cloud.laravel.com/docs/compute#inertia-ssr)** - Our fully-managed Laravel application platform. * **[Laravel Forge](https://forge.laravel.com/docs/sites/laravel#inertia-server-side-rendering-ssr)** - Our VPS server management platform. # Domains Source: https://docs.vapor.build/projects/domains Learn how to manage domains in Laravel Vapor. ## Introduction When using Vapor, each environment is provided a unique vanity domain that you can use to access the environment after it is deployed. However, it's important to keep in mind that vanity domains are intended for development purposes only and Vapor automatically adds "no-index" headers to responses from these URLs to prevent them from being indexed by search engines. In addition, these vanity domains will continue to function even when an application is in maintenance mode, allowing you to test your environment before disabling maintenance mode and restoring general access. While vanity domains are useful during the development process, it's not recommended to use them for a production environment or share them with the public. Instead, it's a best practice to use your own custom domain. ## Adding Domains You may add a domain that you own to Vapor through Vapor's domain screen or by using the `domain` CLI command. When adding a domain to Vapor, always add the root domain, even if you plan to serve your application from a subdomain: ```bash theme={null} vapor domain example.com ``` Of course, you can review the details of your Vapor domains from the Vapor UI or using the `domain:list` CLI command: ```bash theme={null} vapor domain:list ``` ## Managing DNS Records When you add a domain to Vapor, you will be provided with nameservers that you should provide to your domain registrar's nameserver configuration screen. This will designate Vapor as the entity managing the DNS records for the domain. This also allows Vapor to automatically add and remove DNS records to the domain as needed. **If you prefer to manage your DNS records on your own**, requesting a certificate or attaching the domain to an environment will require you to **manually create DNS records** via your domain registrar. ### Custom DNS Records If you have chosen to allow Vapor to manage your DNS records, you can add, update, or DNS records at any time as needed. Vapor provides two ways for you to manage your DNS records: through the Vapor UI's domain detail screen or via the Vapor CLI. To create a DNS record using the Vapor CLI, you can use the `record` command: ```bash theme={null} vapor record example.com A www 192.168.1.1 vapor record example.com A @ 192.168.1.1 vapor record example.com CNAME foo another-example.com vapor record example.com MX foo "10 example.com,20 example2.com" ``` The `record` command functions as an "UPSERT" operation. If an existing record exists with the given type and name, its value will be updated to the given value. If no record exists with the given type or name, the record will be created. To delete a record using the Vapor CLI, you can use the `record:delete` command: ```bash theme={null} vapor record:delete example.com A www ``` ## Requesting SSL Certificates Before attaching a domain to an existing Vapor environment, you must have a valid SSL certificate. Vapor offers free, automatically renewing SSL certificates for your Vapor environment through AWS Certificate Manager. Typically, users choose the "us-east-1" region for their certificate, which is the required certificate region for all environments using API Gateway 1.0. However, environments using API Gateway 2.0 or Application Load Balancers require a certificate in the same region as the project. You can create a certificate through the Vapor UI's domain screen or by using the `cert` CLI command: ```bash theme={null} vapor cert example.com ``` At this point, no further action is required and your certificate will be validated and issued within minutes. If you self-manage your domain's DNS records, Vapor will not be able to automatically update them. In this case, you can obtain the domain's certificate CNAME record from the Vapor UI's domain detail screen or by running the vapor `record:list example.com` command. Then, you can update your DNS records at the external domain registrar accordingly. Please note that some DNS providers will automatically append the domain name to the CNAME name. In these instances, you can remove the domain name from the CNAME name. You can view the validation status of your certificates on the Vapor UI or by using the `cert:list` CLI command: ```bash theme={null} vapor cert:list example.com ``` If you want to delete an old certificate that is not attached to an environment, you can do so through the Vapor UI's domain detail screen or by using the `cert:delete` CLI command. After running the command, Vapor will prompt you to select the specific certificate you want to delete for the given domain: ```bash theme={null} vapor cert:delete example.com ``` ## Attaching Domains To Environments Once your domain has a valid SSL certificate, you can attach your domain to your environment using the `domain` configuration option in your application's `vapor.yml` file. When attaching a domain to an environment, you don't need to include the "www" subdomain: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: domain: example.com build: - 'composer install --no-dev' ``` During deployment, Vapor will automatically configure the environment to handle requests on this domain. However, due to the nature of AWS CloudFront, custom domains often take 30-45 minutes to become fully active. So, do not worry if your custom domain is not immediately accessible after deployment. If you self-manage your domain's DNS records, Vapor will not be able to automatically update them. In this case, you can obtain the domain's environment CNAME records from the Vapor UI's domain detail screen or by running the vapor `record:list example.com` command. Then, you can update your DNS records at the external domain registrar accordingly. ### Multiple Domains Vapor allows you to attach multiple domains to a single project. Before doing so, ensure you have a valid certificate for each of the domains. Then, update your application's `vapor.yml` file to include each domain: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: domain: - example1.com - example2.com build: - 'composer install --no-dev' ``` ### Wildcard Subdomains You may indicate that a domain should support wildcard subdomains as long as you have a valid certificate for the primary domain. To attach a wildcard domain to an environment, specify `*` as the subdomain: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: domain: '*.example.com' build: - 'composer install --no-dev' ``` ### Multi-level Subdomains Vapor provides support for multi-level subdomains - for example `v1.api.example.com`. To make use of this functionality, a certificate must be requested which explicitly includes the full multi-level subdomain. The certificate can be requested from the Vapor CLI: ```shell theme={null} vapor cert v1.api.example.com ``` It's also possible to obtain a certificate for a multi-level subdomain from the [Vapor domains dashboard](https://vapor.laravel.com/app/domains) by setting the multi-level subdomain as either the "Domain Name" or any of the "Alternative Names" in the "Advanced Settings" when requesting a certificate. When the certificate has been issued, you may access your application from your multi-level subdomain by including it in the `domain` section of your `vapor.yml` configuration file and carrying out a full deployment from the Vapor CLI: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: domain: 'v1.api.example.com' build: - 'composer install --no-dev' ``` Wildcard certificates provided by AWS Certificate Manager can only protect single-level subdomains. As such, it is not possible to access your application via a multi-level subdomain when using only wildcard subdomains. The multi-level subdomain must be explicitly added to your `vapor.yml` file. ## Removing Vanity Domains If you no longer want a vanity domain to be attached to your environment, you may remove it using the `vanity-domain:delete ` commmand: ```shell theme={null} vapor vanity-domain:delete production ``` # Environments Source: https://docs.vapor.build/projects/environments Learn how to manage environments in Laravel Vapor. ## Introduction As you may have noticed, projects do not contain much information or resources themselves. All of your deployments and invoked commands are stored within environments. Each project may have as many environments as needed. Typically, you will have an environment for "production", and a "staging" environment for testing your application. However, don't be afraid to create more environments for testing new features without interrupting your main staging environment. ## Creating Environments Environments may be created using the `env` Vapor CLI command: ```bash theme={null} vapor env my-environment ``` This command will add a new environment entry to your project's `vapor.yml` file that you may deploy when ready: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: build: - 'composer install --no-dev' my-environment: build: - 'composer install --no-dev' ``` In addition to our native runtimes, Vapor supports Docker image deployments. If you would like an environment to use a Docker image runtime instead of the default Vapor runtime, use the `--docker` option when creating your environment: ```bash theme={null} vapor env my-environment --docker ``` This command will create a `my-environment.Dockerfile` file in your application's root directory. ## Opening Environments Environments may be opened in your default browser using the Vapor CLI's `open` command: ```bash theme={null} vapor open my-environment ``` ## Default Environment When executing a Vapor CLI command, Vapor CLI uses the `staging` environment by default: ```bash theme={null} vapor open // Opens the `staging` environment in your default browser... vapor open production // Opens the `production` environment in your default browser... ``` However, within your application's `vapor.yml` file, you may define a `default-environment` option to change the default environment for your project: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app default-environment: production environments: production: build: - 'composer install --no-dev' my-environment: build: - 'composer install --no-dev' ``` ## Environment Variables Each environment contains a set of environment variables that provide crucial information to your application during execution, just like the variables present in your application's local `.env` file. ### Vapor's Default Environment Variables Vapor automatically injects a variety of environment variables based on your environment's configured cache, database, etc. As an example, by adding a `cache` or `database` key to your `vapor.yml` file, Vapor will inject the necessary `CACHE_*` and `DB_*` environment variables. Here is the full list of environment variables injected by Vapor on your environment: | `.env` Value | `env()` Value | | ----------------------- | ---------------------------------------------------------- | | `APP_ENV` | Environment name | | `APP_DEBUG` | False | | `APP_LOG_LEVEL` | Debug | | `APP_URL` | Vanity domain, or custom domain if exists | | `ASSET_URL` | CloudFront | | `AWS_BUCKET` | Storage resource if exists | | `BROADCAST_DRIVER` | Pusher | | `CACHE_DRIVER` | DynamoDB, or cache (Redis) resource if exists | | `DB_*` | Database (MySQL, Postgresql, etc) resource if exists | | `DYNAMODB_CACHE_TABLE` | `vapor_cache` | | `FILESYSTEM_DISK` | S3 | | `FILESYSTEM_DRIVER` | S3 | | `FILESYSTEM_CLOUD` | S3 | | `LOG_CHANNEL` | Stderr | | `MAIL_DRIVER` | LOG, but SES for environments with the name `production` | | `MAIL_MAILER` | LOG, but SES for environments with the name `production` | | `MAIL_FROM_ADDRESS` | `hello@example.com` or `hello@custom-domain.com` if exists | | `MAIL_FROM_NAME` | `your_project_name` | | `MIX_URL` | CloudFront | | `QUEUE_CONNECTION` | SQS | | `SCHEDULE_CACHE_DRIVER` | DynamoDB | | `SESSION_DRIVER` | Cookie | You will not see these environment variables when you manage your environment via Vapor CLI or Vapor UI, and any variables you manually define will override Vapor's automatically injected variables. ### Updating Environment Variables You may update an environment's variables via the Vapor UI or using the `env:pull` and `env:push` CLI commands. The `env:pull` command may be used to pull down an environment file for a given environment: ```bash theme={null} vapor env:pull production ``` Once this command has been executed, a `.env.{environment}` file will be placed in your application's root directory. To update the environment's variables, simply open and edit this file. When you are done editing the variables, use the `env:push` command to push the variables back to Vapor: ```bash theme={null} vapor env:push production ``` If you are using the DotEnv library's [variable nesting](https://github.com/vlucas/phpdotenv#nesting-variables) feature to reference default environment variables that Vapor is injecting, you should replace these references with literal values instead. Since Vapor's injected environment variables do not belong to the environment file, they can not be referenced using the nesting feature. After updating an environment's variables, the new variables will not be utilized until the application is deployed again. In addition, when rolling back to a previous deployment, Vapor will use the variables as they existed at the time the deployment you're rolling back to was originally deployed. Due to AWS Lambda limitations, your environment variables may only be 4kb in total. To accommodate Vapor's own injection of environment variables, users are limited to 2,000 characters of environment variables. You should use encrypted environment files in place of or in addition to environment variables if you exceed this limit. ### Reserved Environment Variables The following environment variables are reserved and may not be added to your environment: * `_HANDLER` * `AWS_ACCESS_KEY_ID` * `AWS_DEFAULT_REGION` * `AWS_EXECUTION_ENV` * `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` * `AWS_LAMBDA_FUNCTION_NAME` * `AWS_LAMBDA_FUNCTION_VERSION` * `AWS_LAMBDA_LOG_GROUP_NAME` * `AWS_LAMBDA_LOG_STREAM_NAME` * `AWS_LAMBDA_RUNTIME_API` * `AWS_REGION` * `AWS_SECRET_ACCESS_KEY` * `AWS_SESSION_TOKEN` * `LAMBDA_RUNTIME_DIR` * `LAMBDA_TASK_ROOT` * `TZ` In addition, environment variables should not contain `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, or `AWS_SESSION_TOKEN` in their names. For example: `MY_SERVICE_AWS_SECRET_ACCESS_KEY`. ## Encrypted Environment Files Vapor provides built-in support for Laravel's [encrypted environment files](https://laravel.com/docs/configuration#encrypting-environment-files). If Vapor discovers an encrypted environment file while booting your application, it will automatically attempt to decrypt it and inject the resulting variables into the runtime. To leverage this feature, you must first ensure an encrypted environment file is present at the root of your application during deployment. For example, deploying the `production` environment requires a file called `.env.production.encrypted` to be present at the root of your application. Additionally, you should ensure the decryption key is available in the runtime by defining it as the `LARAVEL_ENV_ENCRYPTION_KEY` environment variable via the Vapor UI or [CLI](#environment-variables). Utilizing encrypted environment files requires your application to be running Laravel >= v9.37 and Vapor Core >= v2.26. ### Passport Keys You may easily add your project's Passport keys to your encrypted environment file using the `env:passport` CLI command: ```bash theme={null} vapor env:passport production ``` The `env:passport` command will append the contents of your local Passport keys to your `.env.production` file. When the command completes, you should re-encrypt the environment file using Laravel's `env:encrypt` command and redeploy your project in order for the changes to take effect. ## Maintenance Mode When deploying a Laravel application using a traditional VPS like those managed by [Laravel Forge](https://forge.laravel.com), you may have used the `php artisan down` command to place your application in "maintenance mode". To place a Vapor environment in maintenance mode, you may use the Vapor UI or the `down` CLI command: ```bash theme={null} vapor down production ``` To remove an environment from maintenance mode, you may use the `up` command: ```bash theme={null} vapor up production ``` When an environment is in maintenance mode, the environment's custom domain will display a maintenance mode splash screen; however, you may still access the environment via its "vanity URL" ### Customizing The Maintenance Mode Screen You may customize the maintenance mode splash screen for your application by placing a `503.html` file in your application's root directory. In addition, you may also place a `503.json` file in your application's root directory for requests asking for JSON responses. ### Bypassing Maintenance Mode You may find it useful to be able to access your site on its custom domain rather than the vanity domain while in maintenance mode. To accomplish this, you may provide a secret when invoking the `down` command: ```bash theme={null} vapor down --secret="example-secret" ``` You may then access your application using the secret key as the URL path: ``` https://example.com/example-secret ``` ### Queue Processing During Maintenance Mode When an environment is placed in maintenance mode, queue workers will stop processing jobs. Unlike traditional Laravel deployments where you can use `php artisan queue:work --force` to continue processing jobs during maintenance, Vapor does not currently support forcing queue processing during maintenance mode. This means: * All queued jobs will remain in the queue unprocessed while maintenance mode is active. * Queue workers will automatically resume processing jobs once maintenance mode is disabled. * There is no way to selectively process critical jobs during maintenance. ## Commands Commands allow you to execute an arbitrary Artisan command against an environment. You may issue a command via the Vapor UI or using the `command` CLI command. The `command` command will prompt you for the Artisan command you would like to run: ```bash theme={null} vapor command production vapor command production --command="php artisan inspire" ``` By default, your command will timeout after one minute. You can configure the timeout of your CLI commands using the `cli-timeout` option within your `vapor.yml` file. This option allows you to specify the maximum number of seconds a CLI command should be allowed to run: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: cli-timeout: 20 build: - 'composer install --no-dev' ``` Sometimes you may need to run the previous command again. To accomplish this, you may use the Vapor UI or the `command:again` CLI command: ```bash theme={null} # Run the previous command again... vapor command:again # Run a specific command again using the command's ID... vapor command:again 50 ``` ## Memory Vapor (via AWS Lambda) allocates CPU power to your Lambda function in proportion to the amount of memory configured for the application. You may increase or decrease the configured memory using the `memory` option in your environment's `vapor.yml` configuration: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: memory: 1024 build: - 'composer install --no-dev' ``` When configuring the memory for your Lambda function, you may define a value between 128 MB and 10,240 MB in 64-MB increments. Available values: 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 4096, 5120, 6144, 7168, 8192, 9216, and 10240 ## Concurrency By default, Vapor will allow your application to process web requests at max concurrency, which is typically 1,000 requests executing at the same time at any given moment across all of your AWS Lambda functions in a given region. If you would like to reduce the maximum web concurrency, you may define the `concurrency` option in the environment's `vapor.yml` configuration. Additionally, if you need more than 1,000 concurrent requests, you can submit a limit increase request in the AWS Support Center console. While maximum performance is certainly appealing, in some situations it may make sense to set this value to the maximum concurrency you reasonably expect for your particular application. Otherwise, a DDoS attack against your application could result in larger than expected AWS costs: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: concurrency: 50 build: - 'composer install --no-dev' ``` ## Prewarming By default, when an environment is deployed, the first request it receives may encounter "cold starts". These requests typically incur a penalty of a few seconds while AWS loads a serverless container to serve the request. Once a request has been served by that container, it is typically kept warm to serve further requests with no delay. To mitigate "cold starts" after a fresh deployment, Vapor allows you to define a `warm` configuration value for an environment in your `vapor.yml` file. The `warm` value represents how many serverless containers Vapor will "pre-warm" by making concurrent requests to the newly deployed application **before it is activated for public accessibility**. Vapor will continue to pre-warm this many containers every 5 minutes while the application is deployed so the specified number of containers are always ready to serve requests: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: warm: 10 build: - 'composer install --no-dev' ``` ## Firewall You may instruct Vapor to automatically configure a firewall that provides basic protection against denial-of-service attacks targeting your environment, as well as protection against pervasive bot traffic that can consume your environment's resources. Before getting started, keep in mind that Vapor's managed firewall inspects requests using the IP address from the web request origin. Therefore, this feature should only be used if the requests are not already being reversed proxied through a service such as Cloudflare. **If you are already using a reverse proxy, you should not use this feature**. You may use Vapor's managed firewall by defining the `firewall` configuration option within your application's `vapor.yml` file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: build: - 'composer install --no-dev' firewall: rate-limit: 1000 bot-control: - CategorySearchEngine - CategorySocialMedia - CategoryScrapingFramework ``` ### `rate-limit` When using the `rate-limit` option, Vapor's managed firewall tracks the rate of requests for each originating IP address and blocks IPs with request rates over the given `rate-limit` value. In the example above, if the request count for an IP address exceeds 1,000 requests in any 5-minute time span then the firewall will temporarily block requests from that IP address with the `403 Forbidden` HTTP status code. ### `bot-control` When using the `bot-control` option, Vapor's managed firewall blocks requests from pervasive bots, such as scrapers or search engines. You may customize the "category" of requests the `bot-control` should block by providing an `array` of categories within your application's `vapor.yml` file: ```yaml vapor.yml theme={null} firewall: bot-control: - CategoryAdvertising - CategoryArchiver - SignalNonBrowserUserAgent ``` Here is the list of available categories you may use: | Category | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | CategoryAdvertising | Blocks requests from bots that are used for advertising purposes. | | CategoryArchiver | Blocks requests from bots that are used for archiving purposes. | | CategoryContentFetcher | Blocks requests from bots that are fetching content on behalf of an end-user. | | CategoryHttpLibrary | Blocks requests from HTTP libraries that are often used by bots. | | CategoryLinkChecker | Blocks requests from bots that check for broken links. | | CategoryMiscellaneous | Blocks requests from miscellaneous bots. | | CategoryMonitoring | Blocks requests from bots that are used for monitoring purposes. | | CategoryScrapingFramework | Blocks requests from web scraping frameworks. | | CategorySecurity | Blocks requests from security-related bots. | | CategorySeo | Blocks requests from bots that are used for search engine optimization. | | CategorySocialMedia | Blocks requests from bots that are used by social media platforms to provide content summaries. Verified social media bots are not blocked. | | CategorySearchEngine | Blocks requests from search engine bots. Verified search engines are not blocked. | | SignalAutomatedBrowser | Blocks requests with indications of an automated web browser. | | SignalKnownBotDataCenter | Blocks requests from data centers that are typically used by bots. | | SignalNonBrowserUserAgent | Blocks requests with user-agent strings that don't seem to be from a web browser. | *** Due to AWS limitations, Vapor's managed firewall does not support API Gateway v2. Behind the scenes, Vapor's managed firewall uses **[Amazon WAF](https://aws.amazon.com/waf/)**, creating a Web ACL with one rate-based rule per Vapor environment. Feel free to check out the AWS WAF documentation for more information about WAF and its pricing. ## Timeout By default, Vapor will limit web request execution time to 10 seconds. If you would like to change the timeout value, you may add a `timeout` value (in seconds) to the environment's configuration. API Gateway has a maximum timeout of 30 seconds. Should you require a longer request duration, you may utilize a [load balancer](/resources/networks#load-balancers). Note that AWS does not allow Lambda executions to process for more than 15 minutes: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: timeout: 20 build: - 'composer install --no-dev' ``` Remember, you can use the "Logs" panel of the [Vapor dashboard](https://vapor.laravel.com/app) to search for timeout occurrences. ## Scheduler Vapor automatically configures Laravel's task scheduler and instructs it to use the DynamoDB cache driver to avoid overlapping tasks, so no other configuration is required to begin leveraging Laravel's scheduled task feature. Due to the serverless nature of Vapor, you should avoid using the `runInBackground` method when scheduling jobs. Doing so may prevent other tasks from running in the event the Lambda container shuts down before the current task completes. If you would like to disable the scheduler, you may set an environment's `scheduler` option to `false`: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: scheduler: false build: - 'composer install --no-dev' ``` Due to Vapor limitations, log messages from scheduled tasks will not appear in AWS CloudWatch or Vapor UI. As a workaround, you should dispatch a queued job from your scheduled tasks and write log messages from your queued job. ### Sub-Minute Scheduled Tasks Due to AWS limitations, there is no guarantee the scheduler will be invoked at the very beginning of any given minute. Therefore, you may find that, by default, sub-minute tasks scheduled early in the `schedule:run` process do not run as expected and those which run later in the schedule may not start at the expected time. For example, when scheduling a command using `everyThirtySeconds` and assuming the scheduler is invoked by AWS at 12:00:10, you should expect your command to run at 12:00:10 and 12:00:40. To work around these limitations for sub-minute tasks, you may enable Vapor's own scheduler engine by adding `scheduler: sub-minute` to your application's `vapor.yml` file: ```yml theme={null} id: 2 name: vapor-laravel-app environments: production: scheduler: sub-minute cli-timeout: 120 ``` When Vapor's sub-minute scheduler is enabled, Vapor runs its own scheduler command which waits until the beginning of every minute before calling `schedule:run`. Therefore, when enabling this option, you should also ensure your `cli-timeout` is >= 120 to allow enough time to both invoke Laravel's scheduler and allow it to complete all sub-minute tasks. You should also ensure `cli-concurrency` is >= 2 to allow for the possibility of overlapping invocations of Vapor's scheduler. In addition, the `runInBackground` option is not supported on Vapor; therefore, you may find some of your tasks are blocked from running if the previous task runs longer than expected. ## Mail Laravel provides a clean, simple email API. And, by default, Vapor will automatically configure your environment to use **[Amazon SES](https://aws.amazon.com/ses/)** as the default mail driver by injecting the proper Laravel environment variables during deployment. Of course, you may change the default mail driver by defining a different value for the `MAIL_MAILER` environment variable. If you plan to use Amazon SES as your application's mail service, you should first ensure the `MAIL_MAILER` environment variable is set and it contains the value `ses`. Next, you should [attach a domain](#custom-domains) to your environment. Once attached and deployed, Vapor will automatically update the domain's DNS records so Amazon SES can validate the domain and configure DKIM. These DNS records are necessary to protect your reputation as a sender. If you self-manage your domain's DNS records, Vapor will not be able to update the domain's DNS records automatically. Therefore, you should run the `vapor record:list domain-name.com` command to view the records that Vapor indicates are required for your domain and update your DNS records accordingly. By default, Vapor configures the "From Address" and "From Name" Laravel configuration settings with `hello@your-domain.com` and `Your Project Name`, respectively. Of course, you're free to modify these values by defining new values for the `MAIL_FROM_ADDRESS` and `MAIL_FROM_NAME` environment variables. Finally, if you haven't used Amazon SES before, your SES account will be in "sandbox" mode. Sandbox mode only allows you to send emails to manually verified domains. To move out of SES sandbox mode, follow these instructions: **[https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html)**. ## Metrics A variety of environment performance metrics may be found in the Vapor UI or using the `metrics` CLI command: ```bash theme={null} vapor metrics production vapor metrics production 5m vapor metrics production 30m vapor metrics production 1h vapor metrics production 8h vapor metrics production 1d vapor metrics production 3d vapor metrics production 7d vapor metrics production 1M ``` ### Alarms You may configure alarms for all environment metrics using the Vapor UI. These alarms will notify you via the notification method of your choice when an alarm's configured threshold is broken and when an alarm recovers. ## Runtime The `runtime` configuration option allows you to specify the runtime a given environment runs on. ### Native Runtimes The currently supported native runtimes are `php-8.5:al2`, `php-8.5:al2-arm`, `php-8.5:al2023`, `php-8.5:al2023-arm`, `php-8.4:al2`, `php-8.4:al2-arm`, `php-8.4:al2023`, `php-8.4:al2023-arm`, `php-8.3:al2`, `php-8.3:al2-arm`, `php-8.3:al2023`, `php-8.3:al2023-arm`, `php-8.2:al2`, and `php-8.2:al2-arm`. Runtimes without the `-arm` suffix run on x86 architecture whereas those suffixed with `-arm` run on Arm architecture. Arm provides performance benefits and cost savings compared to its x86 equivalent: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: runtime: 'php-8.5:al2023' build: - 'composer install --no-dev' ``` Using [Amazon Linux 2023](https://aws.amazon.com/linux/amazon-linux-2023/) (`php-8.5:al2023`, `php-8.5:al2023-arm`, `php-8.4:al2023`, `php-8.4:al2023-arm`, `php-8.3:al2023`, `php-8.3:al2023-arm`) is **highly recommended**, as Amazon Linux 2 will no longer be maintained as of June 30, 2026. The following limitations apply to Vapor native runtimes: * The application size, including the runtime itself, must not exceed 250MB. * Additional PHP extensions or libraries (such as `imagick`) can not be installed. #### Customizing Core `php.ini` Directives To customize core `php.ini` directives on our native runtimes, create a `php.ini` file in the `php/conf.d` directory of your project with the desired directives. For example, to change the `upload_max_filesize`, add the following line to your application's `php.ini` file: ```ini theme={null} upload_max_filesize = 4M ``` After deploying, the new directive will take effect in your Vapor environment. ### Docker Runtimes Docker based runtimes allow you to package and deploy applications up to 10GB in size and allow you to install additional PHP extensions or libraries by updating the environment's corresponding `.Dockerfile`. For every new Docker based environment, Vapor creates a `.Dockerfile` file within your application that uses one of Vapor's base images as a starting point for building your image. All of Vapor's Docker images are based on Alpine Linux: ```docker theme={null} FROM laravelphp/vapor:php85 COPY . /var/task ``` Vapor's Docker runtimes also support Arm architecture, which provides increased performance and cost savings. If you want to take advantage of Arm architecture, you should update your base image as follows: ```docker theme={null} FROM laravelphp/vapor:php85-arm COPY . /var/task ``` If you would like to use a Docker image instead of the Vapor native runtimes, you should set your `vapor.yml` configuration file's `runtime` option to `docker` (for x86 architecture) or `docker-arm` (for Arm architecture): ```yaml vapor.yml theme={null} # x86 id: 2 name: vapor-laravel-app environments: production: runtime: docker build: - 'composer install --no-dev' # Arm id: 2 name: vapor-laravel-app environments: production: runtime: docker-arm docker-build-options: - provenance=false build: - 'composer install --no-dev' ``` To avoid errors when compiling an image for the `docker-arm` runtime, it is essential to ensure that the environment where the image is built is compatible with `arm64` based architecture. To avoid such issues, it may be necessary to emulate the `arm64` architecture using a tool such as QEMU. The [Docker documentation](https://docs.docker.com/build/building/multi-platform/#building-multi-platform-images) provides further guidance on this topic. If you would like to rename the Dockerfile or use a shared Dockerfile across multiple environments, you may define a `dockerfile` option within your `vapor.yml` file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: runtime: docker dockerfile: vapor.Dockerfile build: - 'composer install --no-dev' ``` When migrating an existing environment to a Docker runtime, please keep in mind that you won't be able to revert that environment to the default Vapor Lambda runtime later. For that reason, you may want to create an environment for testing the Docker runtime first. Vapor will build, tag, and publish your environment's image during your deployments; therefore, you should ensure that you have installed [Docker](https://docs.docker.com/get-docker/) on your local machine. Vapor's base Docker images are: * `laravelphp/vapor:php85` * `laravelphp/vapor:php85-arm` * `laravelphp/vapor:php84` * `laravelphp/vapor:php84-arm` * `laravelphp/vapor:php83` * `laravelphp/vapor:php83-arm` * `laravelphp/vapor:php82` * `laravelphp/vapor:php82-arm` * `laravelphp/vapor:php81` * `laravelphp/vapor:php80` * `laravelphp/vapor:php74` Of course, you are free to modify your environment's `Dockerfile` to install additional dependencies or PHP extensions. Here are a few examples: ```docker theme={null} FROM laravelphp/vapor:php85 # Add the `ffmpeg` library... RUN apk --update add ffmpeg # Add the `mysql` client... RUN apk --update add mysql-client # Add the `gmp` PHP extension... RUN apk --update add gmp gmp-dev RUN docker-php-ext-install gmp # Place application in Lambda application directory... COPY . /var/task ``` #### Customizing Core `php.ini` Directives To customize core `php.ini` directives on our Docker runtimes, create a `php.ini` file in the **root** directory of your project with the desired directives. For example, to change the `upload_max_filesize` directive, add the following line to your `php.ini` file: ```ini theme={null} upload_max_filesize = 4M ``` Next, in your Dockerfile, include a new `COPY` command that copies the local `php.ini` file into the Docker image: ```docker theme={null} FROM laravelphp/vapor:php85 COPY ./php.ini /usr/local/etc/php/conf.d/overrides.ini COPY . /var/task ``` After deploying, the new directive will take effect in your Vapor environment. #### Docker Build Arguments When using Docker, is common to use `ARG` instructions in `.Dockerfile` files to define build-time variables: ```docker theme={null} ARG VERSION=php85 FROM laravelphp/vapor:${VERSION} COPY . /var/task ``` You may set Docker build arguments via the `docker-build-args` configuration option within your application's `vapor.yml` file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: runtime: docker docker-build-args: VERSION: php85 build: - 'composer install --no-dev' ``` Alternatively, you may provide one or multiple `--build-arg` options to the `deploy` Vapor CLI command to specify the values of the build arguments: ```bash theme={null} vapor deploy --build-arg VERSION=php74 --build-arg KEY=value ``` ## Octane By default, when Lambda receives HTTP requests, Vapor sends those requests synchronously to PHP-FPM using the FastCGI Protocol. This means every incoming request spawns a PHP-FPM worker and boots your application. This approach ensures Vapor behaves exactly like a traditional web server. If you wish to reduce the overhead involved in using PHP-FPM, you may opt-in to **Laravel [Octane](https://laravel.com/docs/octane)** support on Vapor. Octane can increase your application's performance by booting your application once, keeping it in memory, and then feeding that same application instance requests as they are received. To get started, [install Laravel Octane](https://laravel.com/docs/octane#installation) in your project. After installing Octane, don't forget to review important [Octane documentation](https://laravel.com/docs/octane) topics such as [dependency injection](https://laravel.com/docs/octane#dependency-injection-and-octane) and [managing memory leaks](https://laravel.com/docs/octane#managing-memory-leaks). Finally, you may instruct Vapor to use Octane by setting the `octane` configuration option within your application's `vapor.yml` file: ```yaml vapor.yml theme={null} id: 1 name: my-application environments: staging: memory: 1024 runtime: 'php-8.5:al2023' octane: true ``` In addition, if your project uses a database, you may use the `octane-database-session-persist` and `octane-database-session-ttl` options to instruct Octane that database connections should be reused between requests: ```yaml vapor.yml theme={null} database: my-database octane: true octane-database-session-persist: true octane-database-session-ttl: 10 ``` * The `octane-database-session-persist` option indicates that database connections should persist between requests. The main purpose of this option is to reduce the overhead involved on creating a database connection on each request. * The `octane-database-session-ttl` option allows specifying the time (in seconds) the Lambda container should stay connected to the database when the Lambda container is not being used. This option is only available for MySQL fixed size databases. **We recommended that you specify an `octane-database-session-ttl` value**; otherwise, the Lambda container will stay connected to your database until the Lambda container gets destroyed. This may take several minutes and may result in your database becoming overwhelmed with active connections. Vapor does not use standard Octane runtimes like Swoole, RoadRunner, or FrankenPHP. Instead, it runs on the AWS Lambda runtime environment. Because of this architectural difference, features that depend on Swoole or other specific runtimes may not be available or might behave differently than expected in Vapor deployments. ## Gateway Versions By default, Vapor routes HTTP traffic to your serverless applications using AWS API Gateway v1 (REST APIs). Your application may run on either API Gateway v1 (REST APIs) or API Gateway v2 (HTTP APIs). By default, applications deploy using API Gateway v1 as it provides a fuller feature set such as Vapor's managed Firewall, and more. However, API Gateway v2 offers a cost reduction per million requests to your application (\$1.00 per million vs. \$3.50 per million). If you would like to use API Gateway v2, you may specify the `gateway-version` configuration option for a given environment in your `vapor.yml` file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: gateway-version: 2 build: - 'composer install --no-dev' ``` ### HTTP to HTTPS Redirection With API Gateway v2 If you choose to use API Gateway v2 and would like to support HTTP to HTTPS redirection, we currently suggest using [Cloudflare](https://cloudflare.com) as an external DNS provider for your Vapor application. Cloudflare not only provides DNS, but serves as a reverse proxy to your application and features an option for automatic HTTP to HTTPS redirection. After a Vapor deployment is completed, Vapor will provide you with CNAME records for the domain(s) associated with your environment. These records will point the domain to your Lambda application. You should manually add these values as CNAME records within the Cloudflare DNS dashboard. In addition, when using Cloudflare, you should set your Cloudflare SSL / TLS mode to "Full". The "Always Use HTTPS" configuration option may be found under the SSL / TLS menu's "Edge Certificates" tab. ## Custom VPCs If you want to place your Lambda functions within a VPC that is not managed by Vapor, you may specify the `subnets` and `security-groups` configuration options for a given environment in your `vapor.yml` file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: subnets: - subnet-08aczain4man8bba7 - subnet-08acr4nd0mbba7 security-groups: - sg-0cr4and0m45b7e0 ``` ## Deleting Environments Environments may be deleted via the Vapor UI or using the `env:delete` CLI command: ```bash theme={null} vapor env:delete testing ``` # The Basics Source: https://docs.vapor.build/projects/the-basics Get started with Laravel Vapor. ## Creating Projects Vapor projects are created via the Vapor UI or the `vapor init` CLI command. We recommend using the Vapor UI if you wish to start a fresh Laravel project on Vapor. This option's fully integrated with GitHub, and once you connect your GitHub account, Vapor automatically creates a new GitHub repository (with a fresh installation of Laravel), makes the first deployment, and sets up automatic deployments on code pushes. Or, if you need to deploy an existing project to Laravel Vapor, you may use the `vapor init` CLI command. This command should be executed within the root directory of the Laravel project you wish to deploy. The `init` command will prompt you to select the AWS account that the project should be associated with, as well as the AWS region that it should be deployed to. ```bash theme={null} vapor init ``` The `init` command will generate a `vapor.yml` file within the root of your project. This is the primary configuration file for your Vapor project and contains things like build steps, deployment hooks, linked databases / caches, and other project settings. Each time you deploy, Vapor reads this configuration file and deploys your project appropriately. When creating a project in a region that you have not created previous projects in, Vapor will automatically begin building a "network" (AWS VPC) in that region. This network may take several minutes to finish provisioning. You can review its status in the "Networks" tab of the Vapor UI. ### Projects & Teams Before creating a project via the Vapor CLI, ensure your current team is the team you intend to create the project for. You may view your current team using the `team:current` command. You may switch your active team using the `team:switch` command. ```bash theme={null} vapor team:switch ``` You may view your current team's project list via the Vapor UI or the `vapor project:list` CLI command: ```bash theme={null} vapor project:list ``` ## Project Settings ### GitHub Repository Within Vapor's "Project Settings" screen, you may provide the GitHub repository information for a project. Providing this information simply allows Vapor to provide links to GitHub for each deployment's commit hash. You are not required to provide repository information for Vapor to function. ## Deleting Projects You may delete a project using the Vapor UI or the `project:delete` CLI command. The `project:delete` command should be run from the root directory of your project. This command will delete the project in Vapor as well as the AWS Lambda function and AWS API Gateway definition. Any custom resources defined for the project, such as S3 buckets, will not be deleted by Vapor in case they are being used by other projects. If you wish to delete them, you may do so manually from the AWS management console. # Caches Source: https://docs.vapor.build/resources/caches Using caches with Laravel Vapor. ## Introduction Vapor allows you to easily create and manage scalable Redis clusters directly from the Vapor UI or using the Vapor CLI. AWS requires all cache clusters to be private, meaning Vapor will place any application that uses them in a network with a [NAT Gateway](./networks#nat-gateways). If you are primarily using a cache for Laravel's task scheduler and atomic locks, you may find that using a [DynamoDB cache](#dynamodb-caches) is a cost-efficient alternative to using Redis clusters. In addition, DynamoDB caches do not require Vapor to attach a NAT Gateway to your application's network. If no Redis cache is attached to the environment, the DynamoDB cache will automatically be set as the default cache driver. ## Creating Caches You may create caches using the Vapor UI or using the `cache` CLI command. When using the CLI command, the command will prompt you for more details about the cache such as its desired performance class: ```bash theme={null} vapor cache my-application-cache ``` ## Using Caches To attach a cache to an environment, add a `cache` key to the environment's configuration in your `vapor.yml` file. The value of this key should be the name of the cache. **When the environment is deployed, Vapor will automatically inject the necessary Laravel environment variables for connecting to the cache, allowing your application to start using it immediately:** ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: cache: my-application-cache build: - 'composer install --no-dev' deploy: - 'php artisan migrate --force' ``` ### Connecting To Caches Locally To connect to your cache cluster from your local machine, you can use a Vapor [jumpbox](./networks#jumpboxes) in combination with the `cache:tunnel` CLI command. Jumpboxes are small, SSH-accessible servers placed within your private network. After creating a jumpbox in your cache's network, you can use the `cache:tunnel` command: ```bash theme={null} vapor cache:tunnel my-application-cache ``` This command will make your Redis cache cluster available on `localhost:6378`, allowing you to access it with the Redis management tool of your choice, such as [Medis](http://getmedis.com). ## Scaling Caches You may scale caches via the Vapor UI's cache detail screen or the `cache:scale` CLI command. When scaling a cache, you will be prompted to specify the number of "nodes" you wish to scale up or down to. When scaling a cache via the CLI, you should specify your desired number of nodes when executing the `cache:scale` command. Think of each node as a cache server with the performance specs you specified when the cache was created. Cache keys will automatically be sharded across all of your available nodes. Scaling a cache should not typically cause downtime: ```bash theme={null} vapor cache:scale my-application-cache 5 ``` ## Metrics A variety of cache performance metrics are available via the Vapor UI's cache detail screen or using the `cache:metrics` CLI command: ```bash theme={null} vapor cache:metrics my-application-cache vapor cache:metrics my-application-cache 5m vapor cache:metrics my-application-cache 30m vapor cache:metrics my-application-cache 1h vapor cache:metrics my-application-cache 8h vapor cache:metrics my-application-cache 1d vapor cache:metrics my-application-cache 3d vapor cache:metrics my-application-cache 7d vapor cache:metrics my-application-cache 1M ``` ## DynamoDB Caches When you create a project, Vapor will ensure that an auto-scaling DynamoDB cache table is created in that project's region. Then, during deployment, Vapor will automatically populate the environment variables required to interact with this cache using Laravel's built-in `dynamodb` cache driver. All you need to do is start using it within your Laravel application! If no Redis cache is attached to the environment, the DynamoDB cache will automatically be set as the default cache driver. These caches, while not as performant as Redis clusters, provide a very low-cost alternative for applications with light caching requirements. Vapor automatically configures Laravel's task scheduler to use the DynamoDB cache driver to avoid overlapping tasks. ## Deleting Caches Caches may be deleted via the Vapor UI or using the `cache:delete` CLI command: ```bash theme={null} vapor cache:delete my-application-cache ``` # Databases Source: https://docs.vapor.build/resources/databases Managing databases within Laravel Vapor. ## Introduction Vapor allows you to easily create and manage RDS and Aurora Serverless databases directly from the Vapor UI or using the Vapor CLI. **Database backups are automatically performed and you may restore a database to any point in time (down to the second) within the backup retention window.** ## Creating Databases You may create databases using the Vapor UI or using the `database` CLI command. When using the CLI command, the command will prompt you for more details about the database such as its desired performance class and maximum storage space. ```bash theme={null} vapor database my-application-db ``` ### The Default Database Vapor will automatically create a "vapor" database within each database instance that you create. You are free to create additional databases using the database management tool of your choice. ### Database Types When creating Vapor databases, you may choose from two different types of databases: fixed size and auto-scaling serverless databases. #### Fixed Size Databases Fixed sized databases are RDS MySQL 5.7 / RDS MySQL 8 / Postgres 17 databases that have a fixed amount of RAM and disk space. These databases may be scaled up or down after creation, but not without incurring downtime. In addition, these databases may be publicly accessible (with a long, random password automatically assigned by Vapor) or private. Private databases may not typically be accessed from the public Internet. To access them from your local machine, you will need to create a Vapor jumpbox. Vapor will place any application that uses a private database in a network with a [NAT Gateway](/resources/networks#nat-gateways). Later, if you no longer plan to use the database and are using no other private resources from your application, you may remove the NAT Gateway from your network via the network's management screen. #### Serverless Databases Serverless databases are auto-scaling Aurora MySQL 5.7 / MySQL 8.0 / Postgres 11 / Postgres 16 databases which do not have a fixed amount of RAM or disk space. Instead, these databases automatically scale based on the needs of your application. At their smallest scale, they are allocated 1GB of RAM. AWS requires all serverless databases to be private, meaning Vapor will place any application that uses them in a network with a [NAT Gateway](/resources/networks#nat-gateways). If you no longer plan to use a serverless database and are using no other private resources from your application, you may remove the NAT Gateway from your network via the network's management screen. ### Quick Development Databases To quickly create a publicly accessible database of the smallest performance class, you may use the `--dev` flag when creating your database. These small, affordable databases are perfect for testing or staging environments: ```bash theme={null} vapor database my-test-database --dev ``` ## Using Databases To attach a database to an environment, add a `database` key to the environment's configuration in your `vapor.yml` file and deploy your application. The value of this key should be the name of the database. **When the environment is deployed, Vapor will automatically inject the necessary Laravel environment variables for connecting to the database, allowing your application to start using it immediately:** ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: database: my-application-db build: - 'composer install --no-dev' deploy: - 'php artisan migrate --force' ``` ### Connecting To Private Databases Locally If you would like to connect to your private database from your local machine, you can either use a Vapor [jumpbox](/resources/networks#jumpboxes) in combination with a GUI database management tool or the `database:shell` CLI command. Jumpboxes are very small, SSH accessible servers that are placed within your private network. #### Jumpboxes + GUI Tool Once a jumpbox has been created, you may configure your database management tool to connect to your database through the jumpbox SSH connection: Database GUI Connection Settings #### Shell Command After provisioning a jumpbox, you may use the `database:shell` command to quickly access a command line database shell that lets you interact with your database: ```bash theme={null} vapor database:shell my-application-db ``` ## Existing Databases If you wish to use an RDS database that was not created by Vapor, you have two options: 1. Exporting and importing the contents of your existing database into a new database created by Vapor. We recommend this approach as it allows you to use your existing data within a database and network managed by Vapor. 2. Connecting your existing database to a Vapor environment. If your existing database is publicly accessible, make sure your Vapor project is created in the same region as the database. If the existing database is private, you will need to connect your Vapor environment to the VPC your existing database belongs to. You can find instructions on how to do this in our documentation about connecting to [Custom VPCs](/projects/environments#custom-vpcs). After connecting your existing database, you will need to configure the appropriate environment variables: ``` DB_HOST= DB_PORT= DB_DATABASE= DB_USERNAME= DB_PASSWORD= ``` When working with an AWS RDS MySQL Fixed Size databases, an additional environment variable specifying the SSL certificate authority is required: ``` MYSQL_ATTR_SSL_CA=/var/task/rds-combined-ca-bundle.pem ``` If your database is hosted by [PlanetScale](https://planetscale.com/), the SSL certificate authority is as follows: ``` MYSQL_ATTR_SSL_CA=/opt/lib/curl/cert.pem ``` ## Database Users When a database is created, Vapor creates a "vapor" master user. You may create additional database users, which will automatically be assigned a secure, random password, using the Vapor UI or the `database:user` CLI command: ```bash theme={null} vapor database:user my-application-db user-2 ``` You may instruct an environment to connect to a database as a given user using the `database-user` configuration option within your `vapor.yml` file: ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: database: my-application-db database-user: user-2 build: - 'composer install --no-dev' deploy: - 'php artisan migrate --force' ``` You may use the `database:password` CLI command to rotate the password of a database. Alternatively, you may leverage users to "rotate" the password of a database without downtime by creating a new user, updating the environment to use that user, deploying the environment, and then deleting the old database user. ## Scaling Databases You may scale fixed size databases via the Vapor UI's database detail screen or the `database:scale` CLI command. When scaling a fixed size database, the database will be unavailable, and the amount of time it takes to scale the database could vary based on the size of the database. Therefore, you should place your application in maintenance mode before beginning the scaling operation: ```bash theme={null} vapor database:scale my-application-db ``` ## Restoring Databases Vapor database backups are performed automatically and you may restore databases to any point in time within the database backup retention period, which is three days by default. You can change the database backup retention period at any time via the Vapor UI's database details screen. Database restoration may be initiated via the Vapor UI or the `database:restore` CLI command: ```bash theme={null} vapor database:restore current-database-name new-database-name ``` When restoring a database, a new database is created with the same configuration as the previous database. Then, the previous database's contents are restored to the new database as they existed at the exact point in time you choose. To attach the restored database to an environment, update the value of the `database` key in your `vapor.yml` file and deploy the environment. Once you are satisfied with the database restoration, you may delete the old database. ## Upgrading Databases You may upgrade a Vapor managed MySQL database via the Vapor UI or the `database:upgrade` CLI command. When upgrading a database, a new database is created with the same configuration and credentials as the original database: ```bash theme={null} vapor database:upgrade current-database-name new-database-name ``` Keep in mind that major version upgrades can contain database changes that are not backward-compatible with existing applications. For that reason, we recommend that you thoroughly test the new upgraded database version before attaching it to a production environment. The original database will not be affected by this operation at any point. Upgrading a database can take several hours for large databases. Therefore, if you plan to attach the new database to a production environment, you may want to place any affected environments in maintenance mode first. Once the newly upgraded database is available, you may start using it by attaching it to an environment. Of course, once you are satisfied with the database upgrade, you may delete the original database. ## Metrics A variety of database performance metrics are available via the Vapor UI's database detail screen or using the `database:metrics` CLI command: ```bash theme={null} vapor database:metrics my-application-db vapor database:metrics my-application-db 5m vapor database:metrics my-application-db 30m vapor database:metrics my-application-db 1h vapor database:metrics my-application-db 8h vapor database:metrics my-application-db 1d vapor database:metrics my-application-db 3d vapor database:metrics my-application-db 7d vapor database:metrics my-application-db 1M ``` ### Alarms You may configure alarms for all database metrics using the Vapor UI. These alarms will notify you via the notification method of your choice when an alarm's configured threshold is broken and when an alarm recovers. ## Deleting Databases Databases may be deleted via the Vapor UI or using the `database:delete` CLI command. Once a database has been deleted, it can not be recovered, so take extra caution before deleting a database: ```bash theme={null} vapor database:delete my-application-db ``` When deleting a database via the UI, you can choose to **preserve the resource on AWS**. Enabling this option only removes the database record in Laravel Vapor; the AWS resource remains intact. # Logs Source: https://docs.vapor.build/resources/logs Viewing and managing logs within Laravel Vapor. ## Introduction As you may know, Laravel provides support for a variety of logging services. By default, when using Vapor, your application will use the AWS CloudWatch service when logging messages. ## Viewing Logs The Vapor dashboard provides the most convenient way to view and search your application's logs. By utilizing Vapor's powerful search and filter tools, you can easily access and analyze all of your application's logs that are stored on AWS CloudWatch. Vapor allows you to search for specific logs or exceptions, and apply filters based on function type, log level, and the log's time period. Once you locate the relevant log entry, you can click it to view additional information associated with the entry, such as its context or exception details. Alternatively, you may view logs directly in AWS CloudWatch. To do so, navigate to the AWS console's "Lambda" dashboard. Then, locate the Lambda for your project (vapor--). Then, you may click the "View logs in CloudWatch" link within the Lambda's "Monitoring" tab. Remember, even if you configure a different logging service for your application logs, the AWS CloudWatch service and Vapor UI will display your infrastructure logs as well. Infrastructure logs may include logs regarding AWS Lambda timeouts, etc. # Migrate to Cloud Source: https://docs.vapor.build/resources/migrate-to-cloud Learn how to migrate your application from Laravel Vapor to Laravel Cloud While Vapor and Cloud serve similar use cases, Laravel Cloud provides a simpler operational model and a more predictable runtime environment. Migrating allows you to keep the same Laravel application while reducing infrastructure complexity. ## How to migrate If you’re running applications on Laravel Vapor, the migration process focuses on mapping your existing configuration and deployment workflows to Laravel Cloud equivalents. The [Vapor to Cloud migration guide](https://cloud.laravel.com/migration-vapor-cloud) explains why teams migrate and how to move an existing application. # Networks Source: https://docs.vapor.build/resources/networks Managing networks within Laravel Vapor. ## Introduction Networks house your databases, caches, jumpboxes, and occasionally applications within AWS. In general, although they are displayed in the Vapor UI for you to review, you are not required to interact with networks directly when using Vapor. When you create a project in a region that does not contain any previous Vapor projects, Vapor automatically begins provisioning a network for you. ### Attaching A Network To An Environment Typically, you do not need to manually add a `network` directive to your `vapor.yml` file; however, sometimes you may want to manually specify that a Vapor environment should be placed within a given network. This may be the case when you are accessing private AWS resources, such as ElasticSearch, that are not created through Vapor. To place an environment within a network, add the `network` directive to your `vapor.yml` configuration file: ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: network: my-network build: - 'composer install --no-dev' ``` ## Custom IP Range By default, Vapor provisions new networks with an IP address range which is more than sufficient for most projects. However, if you need more control over how your network is configured - such as when you plan to configure your Vapor environment to communicate with pre-existing resources on AWS - you may set your own custom IP range. When creating the network within the Vapor UI, select "Configure Custom IP Range" to show the Custom IP Range interface. You must enter an IP range in valid CIDR notation for the overall VPC, along with the public and private subnets. The total number of ranges required for private subnets varies between two and four depending on the number of availability zones for the selected region. IP ranges provided for public and private subnets must fall in the range provided for the overall VPC without overlapping each other. ## Jumpboxes Some Vapor resources, such as private databases or cache clusters, may not be accessed from the public Internet. Instead, they can only be accessed by a machine within their network. This can make it cumbersome to inspect and manipulate these resources during development. To mitigate this inconvenience, Vapor allows you to create jumpboxes. Jumpboxes are very small, SSH accessible servers that are placed within your private network. You may create a jumpbox via the Vapor UI's network detail screen or using the `jump` CLI command: ```bash theme={null} vapor jump my-jumpbox ``` Once the jumpbox has been created, Vapor will provide you with the private SSH key needed to access the jumpbox. You should connect to the jumpbox via SSH as the `ec2-user` user and the private SSH key. For practical examples of using jumpboxes to make your serverless life easier, check out the [database](./databases#using-databases) and [cache](./caches#using-caches) documentation. ## NAT Gateways ### What Are They? If your application interacts with a private database or a cache cluster, your network will require a NAT Gateway. It sounds complicated, but don't worry, Vapor takes care of the heavy lifting. In summary, when a serverless application needs to interact with one of these resources, AWS requires us to place that application within that region's network. By default, this network has no access to the outside Internet, meaning any outgoing API calls from your application will fail. Not good. ### Managing NAT Gateways Anytime you deploy an application that lists a private database or cache cluster as an attached resource within its `vapor.yml` file, Vapor will automatically ensure that the network associated with that database / cache contains a NAT Gateway. If it doesn't, Vapor will automatically begin provisioning one. Unfortunately, AWS bills for NAT Gateways by the hour, resulting in a monthly fee of about \$32 / month. To totally avoid using NAT Gateways, you can use publicly accessible RDS databases (Vapor automatically assigns a long, random password) and a [DynamoDB cache table](./caches#dynamodb-caches), which Vapor automatically creates for each of your projects. You may also manually add or remove NAT Gateways from your networks using the Vapor UI or using the `network:nat` and `network:delete-nat` CLI commands. ## Load Balancers By default, Vapor routes HTTP traffic to your serverless applications using AWS API Gateway. When using this service, AWS only bills you based on the amount of requests your application receives. However, at very high scale, API Gateway can become more expensive than your Lambda functions themselves. As an alternative to API Gateway, you may route traffic to your application using an Application Load Balancer, which provides large cost savings at scale. For example, if an application receives about 1 billion requests per month, using an Application Load Balancer will save about \$3,000 on the application's monthly Amazon bill when compared to an API Gateway REST API and about \$1,000 when compared to an API Gateway HTTP API. ### Creating Load Balancers You may create load balancers using the Vapor UI or using the `balancer` CLI command. When using the CLI command: ```bash theme={null} vapor balancer my-balancer ``` ### Using Load Balancers To attach a load balancer to an environment, add a `balancer` key to the environment's configuration in your `vapor.yml` file and deploy your application. The value of this key should be the name of the load balancer. ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: balancer: my-balancer build: - 'composer install --no-dev' ``` By default, Vapor creates all SSL certificates in the `us-east-1` region, regardless of the region of your project. When your application is using API Gateway, AWS will automatically replicate your certificate to all regions behind the scenes. However, when using an Application Load Balancer to route traffic to your application, you will need to create a certificate in the region that the project is actually deployed to. ### Deleting Load Balancers Load balancers may be deleted via the Vapor UI or using the `balancer:delete` CLI command: ```bash theme={null} vapor balancer:delete my-balancer ``` # Queues Source: https://docs.vapor.build/resources/queues Using queues with Laravel Vapor. ## Introduction Laravel's queues are one of the framework's most powerful features. With Vapor, you can continue writing and dispatching queued jobs exactly as you would in a traditional server-hosted Laravel application. The only difference is that Vapor will automatically scale your queue processing throughput on-demand within seconds: ```php theme={null} use App\Jobs\ProcessPodcast; ProcessPodcast::dispatch($podcast); ``` When using Vapor, your application will use the AWS SQS service, which is already a first-party queue driver within Laravel. Vapor will automatically configure your deployed application to use this queue driver by injecting the proper Laravel environment variables. You do not need to perform any additional configuration. Currently, serverless applications on AWS may only process a single request (web or queue) for a maximum of 15 minutes. If your queued jobs take longer than 15 minutes, you will need to either chunk your job's work into smaller pieces or consider another deployment solution for your application. In addition, a queued job may not have a "delay" greater than 15 minutes. ## Custom Queue Names By default, Vapor will create an SQS queue that has the same name as your project and inject the proper environment variables to make this queue the default queue. If you would like to specify your own custom queue names that Vapor should create instead, you may define a `queues` option in your environment's `vapor.yml` configuration. The first queue in the list of queues will be considered your "default" queue and will automatically be set as the `SQS_QUEUE` environment variable: ```yaml vapor.yml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queues: - emails - invoices ``` ### Queue Names Should Be Unique When using custom queue names, it is important to ensure the names are unique between projects and environments. For instance, you can add suffix values such as `-staging` and `-production` to the queue names specified in your application's `vapor.yml` file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queues: - emails-production - invoices-production staging: queues: - emails-staging - invoices-staging ``` Because it is cumbersome to include these suffixes when dispatching jobs to specific queues in Laravel, Laravel's `sqs` queue configuration includes a `suffix` option that references the `SQS_SUFFIX` environment variable by default. When this option and variable are defined, you may provide the queue name without its suffix when dispatching jobs and Laravel will automatically append the suffix to the queue name when interacting with SQS: ```php theme={null} // Environment should include... // SQS_SUFFIX="-production" // Configuration... 'sqs' => [ 'driver' => 'sqs', // ... 'queue' => env('SQS_QUEUE', 'invoices'), 'suffix' => env('SQS_SUFFIX'), // ... ], // Dispatching... SendInvoice::dispatch($invoice)->onQueue('invoices'); ``` ### Disabling The Queue If your application does not use queues, you may set the environment's `queues` option to `false`: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queues: false build: - 'composer install --no-dev' ``` ## FIFO Queues AWS SQS FIFO (First-In-First-Out) queues guarantee that messages are processed exactly once and in the exact order they are sent. To use FIFO queues with Vapor, you must first create the FIFO queue directly in the AWS Console. FIFO queue names must end with the `.fifo` suffix, such as `notifications-production.fifo`. Once you have created the FIFO queue in AWS, you may add it to your environment's `vapor.yml` configuration file: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queues: - notifications-production.fifo ``` ## Queue Concurrency By default, Vapor will allow your queue to process jobs at max concurrency, which is typically 1,000 concurrent jobs executing at the same time. If you would like to reduce the maximum queue concurrency, you may define the `queue-concurrency` option in the environment's `vapor.yml` configuration: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queue-concurrency: 50 build: - 'composer install --no-dev' ``` When using multiple custom queues, the `queue-concurrency` option defines the total maximum concurrency of all queues. For example, if you were to define two custom queues and a `queue-concurrency` of 100 the total maximum concurrency will still be 100. For the queue Lambda, Vapor defaults to the value of the `cli-concurrency` option if no value was set for `queue-concurrency`. Before you set a limit on `cli-concurrency`, make sure you provide a value for `queue-concurrency` that's suitable specifically for your queue processing requirements. ### Individual Queue Concurrency In addition to setting the overall queue concurrency, you may also set the maximum concurrency of each queue. Doing so can be helpful if you wish to prevent certain queues from consuming all available resources: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queues: - emails: 10 - invoices: 10 ``` In the example above, the concurrency of the `emails` and `invoices` queue is 10, meaning if the queue Lambda function is processing ten jobs concurrently, it will not pick up any more jobs from the queue until jobs are finished and capacity becomes available. This behavior differs from when the total invocations reach the queue function's overall capacity, where throttling occurs instead. You may also set the maximum concurrency on some queues but not others. In the example below, the `emails` queue is not allowed more than ten concurrent invocations, whereas it's possible to invoke the `invoices` queue until the overall capacity is reached: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queues: - emails: 10 - invoices ``` It is not possible to set the maximum concurrency of an individual queue higher than the value of the overall currency set by either the `queue-concurrency` option or the general AWS account concurrency limit. In addition, the concurrency value must be an integer between 2 and 1,000. ## Queue Visibility Timeout By default, if your queued job is not deleted or released within one minute of beginning to process, SQS will retry the job. To configure this "visibility timeout", you may define the `queue-timeout` option in the environment's `vapor.yml` configuration. For example, we may set this timeout to five minutes: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queue-timeout: 300 build: - 'composer install --no-dev' ``` ## Queue Memory You may use the `queue-memory` option in your environment's `vapor.yml` configuration to define the memory that should be available to your queue worker Lambda function: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queue-memory: 1024 build: - 'composer install --no-dev' ``` ## Queue Database Connections By default, database connections do not persist between queued jobs, ensuring that the database does not get overwhelmed with active connections. However, if your database can handle a large number of connections and you want to reduce the overhead involved in creating a database connection on each job, you may define the `queue-database-session-persist` option in your environment's `vapor.yml` configuration file to instruct Vapor to reuse the same database connection across jobs: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: queue-database-session-persist: true build: - 'composer install --no-dev' ``` ## Monitoring Jobs You may monitor your queued jobs directly from the Vapor dashboard by navigating to the "Queues" tab of any environment. Here, you can see how your queues perform and also details regarding the number of jobs processed, in flight, and failed jobs over time. You may refine the results by selecting a specific queue and period. If you have had job failures during the selected period, you may examine them further by clicking on the "View Failed Jobs" link. Doing so will present you with a list of failed jobs along with a snapshot of the failure. You may filter the results further by selecting the specific queue and period or providing a search term. Clicking on an entry presents the full payload and stack trace. From here, you may also retry or delete the job. In order to view details of failed jobs in the Vapor dashboard, your application must be running Vapor Core >= v2.29.0. ## Failed Jobs Vapor automatically keeps track of failed job attempts using your environment's configured cache driver. This allows Vapor to ensure the correct number of failed attempts is accessible by your application, even if a queued job does not complete due to exceeding the maximum execution time enforced by Lambda (15 minutes) or fails due to an unhandled exception causing the entire container processing your job to fail. Applications processing a large volume of queued jobs may notice an increase in AWS charges when using the DynamoDB cache driver. In these situations, we recommend utilizing a Redis cache. ## Queues and Maintenance Mode Queue processing is automatically paused when an environment is in [maintenance mode](/projects/environments#queue-processing-during-maintenance-mode). Jobs will remain in the queue and resume processing once maintenance mode is disabled. Unlike traditional Laravel deployments, Vapor does not support forcing queue processing during maintenance mode using the `--force` flag. ## Laravel Horizon on Vapor Laravel Vapor does not currently support [Laravel Horizon](https://laravel.com/docs/horizon) due to the serverless architecture of AWS Lambda. The long-running processes required by Horizon are incompatible with Vapor's execution environment. ### Alternative Solutions For applications that require Laravel Horizon's powerful queue monitoring and management capabilities, we recommend exploring these alternative Laravel hosting platforms which support Horizon: * **[Laravel Cloud](https://cloud.laravel.com/docs/queues#custom-background-processes)** - Our fully-managed Laravel application platform. * **[Laravel Forge](https://forge.laravel.com/docs/sites/queues#laravel-horizon)** - Our VPS server management platform. # Storage Source: https://docs.vapor.build/resources/storage Storing files in a serverless environment. ## Introduction When running an application in a serverless environment, you may not store files permanently on the local filesystem, since you can never be sure that the same serverless "container" will be used on a subsequent request. All files should be stored in a cloud storage system, such as AWS S3, or in a shared file system through AWS EFS. ## Attaching Storage To ensure that an application environment has a place to store file uploads, you may add a `storage` key to the environment's `vapor.yml` configuration. This value should be a valid S3 bucket name. During deployment, Vapor will ensure that this bucket exists. If the bucket does not exist, Vapor will create and configure it. Remember, bucket names must be unique across all of AWS: ```yaml vapor.yml theme={null} id: 3 name: vapor-app environments: production: storage: my-bucket-name memory: 1024 build: - 'composer install --no-dev' deploy: - 'php artisan migrate --force' ``` ## Mounting A Persistent File System To mount a file system on your Lambda, you need to [attach a network to your environment](./networks#attaching-a-network-to-an-environment) and then create a new elastic file system (EFS) using the AWS console. In the EFS dashboard, you should click the "Create file system" button and choose the VPC created by your Vapor network. Once the file system is created, click on its name to access the configuration screen and then click on "Access Points". Create an access point and specify `1001` for the user and group of both the "POSIX user" and "Root directory creation permissions" settings. For the "Root directory path" configuration option, you should assign a unique name such as `/{project_name}_{environment_name}`. After creating the disk, you should navigate to the AWS Lambda dashboard. Once in the Lambda dashboard, locate each of the three Lambda functions (the primary function, the "cli" function, and the "queue" function) for your project environment and attach the file system you just created. You may attach the file system by viewing the Lambda function's detail page and clicking the "Add file system" button. You should mount the file system to `/mnt/local`. Once mounted, you can store and retrieve files to the `/mnt/local` disk path. This path will be shared and accessible by all three of the Lambda functions. ## File Uploads Due to AWS Lambda limitations, file uploads made directly to your application backend can only be up to roughly 4.5MB in size. This is a hard limit imposed by AWS, and updating the `php.ini` configuration file or any other configuration will not raise this limit. Therefore, to ensure your application's users won't receive an `HTTP 413 Payload Too Large` response, you may validate the file upload size using JavaScript before initiating the file upload to your application's backend. If your application needs to receive file uploads larger than AWS allows, those files must be streamed directly to S3 from your application's frontend (Browser). To assist you, we've written an NPM package that makes it easy to perform file uploads directly from your application's frontend. ### Installing The Vapor NPM Package To get started, install the `laravel-vapor` NPM package: ```bash theme={null} npm install --save-dev laravel-vapor ``` Next, within your application's `app.js` file, initialize the global Vapor JavaScript object: ```js theme={null} // Vite import Vapor from 'laravel-vapor' window.Vapor = Vapor // Mix window.Vapor = require('laravel-vapor'); ``` ### Authorization Before initiating an upload directly to S3, Vapor's internal signed storage URL generator will perform an authorization check against the currently authenticated user. If you do not already have one, you should create a `UserPolicy` for your application using the following command: ```bash theme={null} php artisan make:policy UserPolicy --model=User ``` Next, you should add an `uploadFiles` method to this policy. This method should return `true` if the given authenticated user is allowed to upload files. Otherwise, you should return `false`: ```php theme={null} /** * Determine whether the user can upload files. * * @param \App\User $user * @return mixed */ public function uploadFiles(User $user) { return true; } ``` ### Streaming Files To S3 You may use the `Vapor.store` method within your frontend code to upload a file directly to the S3 bucket attached to your environment. The following example demonstrates this functionality using Vue: ```html HTML theme={null} ``` ```js JavaScript theme={null} Vapor.store(this.$refs.file.files[0], { progress: progress => { this.uploadProgress = Math.round(progress * 100); } }).then(response => { axios.post('/api/profile-photo', { uuid: response.uuid, key: response.key, bucket: response.bucket, name: this.$refs.file.files[0].name, content_type: this.$refs.file.files[0].type, }) }); ``` All uploaded files will be placed in a `tmp` directory within the bucket. **This directory is automatically configured to purge any files older than 24 hours.** This feature serves to conveniently clean up file uploads that are initiated but not completed, such as a user that begins updating their profile photo but does not save the change. The `tmp` directory is private by default. To override this for a given file you may add a `visibility` property to the options provided to the `Vapor.store` method. The `visibility` property should be assigned one of [S3's predefined permission grants](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl): ```js theme={null} Vapor.store(this.$refs.file.files[0], { visibility: 'public-read' }).then(response => { // ... }); ``` ### Acknowledge File Uploads & Permanent Storage All uploaded files will be stored using a UUID as their filename. The `response` provided to the `store` method's `then` callback will contain the UUID of the file, the file's full S3 key, and the file's bucket. You may then POST this information to your application's backend to permanently store the file by moving it out of the bucket's `tmp` directory. In addition, you may wish to store additional information about the file, such as its original name and content type, in your application's database: ```php theme={null} use Illuminate\Support\Facades\Storage; Storage::copy( $request->input('key'), str_replace('tmp/', '', $request->input('key')) ); ``` #### Local Development When developing locally, `Vapor.store` will upload to the bucket specified by the `AWS_BUCKET` environment variable. In addition, your bucket may require CORS configuration to allow uploads from localhost: ```json theme={null} [ { "AllowedHeaders":[ "*" ], "AllowedMethods":[ "GET", "PUT" ], "AllowedOrigins":[ "*" ], "ExposeHeaders":[] } ] ``` ## Temporary Storage Your application may store temporary files within the `/tmp` directory. By default, this directory has a fixed size of 512 MB, and the information on it is preserved for the lifetime of each request, CLI command, or queue job. You may increase or decrease the configured temporary storage size using the `tmp-storage`, `cli-tmp-storage`, and `queue-tmp-storage` options in your environment's `vapor.yml` configuration. These configuration options accept values between 512 MB and 10,240 MB: ```yaml vapor.yml theme={null} id: 2 name: vapor-laravel-app environments: production: tmp-storage: 1024 cli-tmp-storage: 512 queue-tmp-storage: 10240 build: - 'composer install --no-dev' ```