A first AWS CodeDeploy deployment to EC2 comes down to four things lining up: a revision that contains an appspec.yml file at its root, a deployment group that selects the right instances, a CodeDeploy agent that is running on each instance with the permissions it needs, and a check of the lifecycle events once the deployment runs. This walkthrough follows that EC2/On-Premises path in the order a beginner needs it. The application, operating system, commands and errors from Chandra’s own run are not reproduced here, so the steps below describe the official workflow rather than a record of a tested setup.
The four pieces you are configuring
CodeDeploy uses a small vocabulary, and most first-deployment confusion comes from mixing up these terms.
- Application. The container that holds your deployment configuration and revisions. It does not pick machines by itself.
- Revision. The bundle of application files, scripts and AppSpec instructions you want to put on a server.
- Deployment group. The set of target instances and the deployment type for that set. This is where instance selection happens.
- Agent. Software on each target instance that downloads the revision, unpacks it, copies files as the AppSpec directs, and runs the scripts it lists.
Step 1: Prepare the revision
The revision is what you upload. For EC2/On-Premises, it is uploaded to Amazon S3 or GitHub, and the agent on each target retrieves it from there. Keep the bucket in the same AWS Region as your deployment. AWS lists cross-Region S3 placement among the causes of revision-download failures, so this is the first thing to check if a deployment cannot fetch its bundle.
Lay out the bundle so the AppSpec file sits at the top level, not inside a subfolder created by your archiving tool:
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
my-app-revision/
├── appspec.yml
├── index.html
├── app/
│ └── server.js
└── scripts/
├── stop_server.sh
├── install_dependencies.sh
└── start_server.sh
A common beginner mistake is zipping the parent folder, which produces my-app-revision/appspec.yml inside the archive instead of appspec.yml at the root. Compress the contents of the folder, not the folder itself.
Step 2: Write the AppSpec file
For EC2/On-Premises, the AppSpec file must be YAML, must be named appspec.yml, and must sit at the root of the revision directory. Each revision can contain only one AppSpec file. AWS recommends validating the YAML and checking its placement before you upload, because a file in the wrong place or with broken indentation is one of the most common reasons a deployment never starts usefully. The official reference is Add an application specification file to a revision for CodeDeploy, and the full field list is in the AppSpec file reference.
The following is a generic example for a Linux instance, written to show the structure rather than any particular project:
Rank #2
version: 0.0
os: linux
files:
- source: /
destination: /var/www/my-app
hooks:
ApplicationStop:
- location: scripts/stop_server.sh
timeout: 60
runas: root
AfterInstall:
- location: scripts/install_dependencies.sh
timeout: 300
runas: root
ApplicationStart:
- location: scripts/start_server.sh
timeout: 60
runas: root
What each part does
- version is the AppSpec format version. For EC2/On-Premises it is
0.0. - os tells CodeDeploy which operating system the file targets. Use the value that matches your instances.
- files maps revision content to destinations. A
sourceof/copies the whole revision to thedestinationpath. You can instead map individual files or folders if only part of the bundle should land on the server. - hooks names the scripts to run at each lifecycle event. Each
locationis a path relative to the revision root.timeoutis the number of seconds the agent allows the script to run, andrunassets the user that executes it.
The agent runs the listed hook scripts in sequence. A script that finishes successfully returns exit code 0, and its status is written to the CodeDeploy agent log. Any other exit code fails the lifecycle event. Check the YAML indentation first, because a single misaligned line changes the meaning of the whole file.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsLifecycle events you will see
For an in-place deployment to EC2, the agent works through a fixed sequence of events. The scripts you listed attach to some of them:
- ApplicationStop stops the old version.
- DownloadBundle is handled by the agent itself; it fetches the revision.
- BeforeInstall runs preparation scripts.
- Install copies files to their destinations, as the
filessection directs. - AfterInstall runs setup such as dependency installation.
- ApplicationStart starts the new version.
- ValidateService checks that the new version works.
Blue/green deployments add traffic-related events, including BeforeBlockTraffic and AfterBlockTraffic, which are covered in the EC2/On-Premises deployment steps.
Rank #3
Step 3: Choose the deployment type
The deployment type decides which instances receive the revision and whether traffic moves between them.
| Question | In-place | Blue/green |
|---|---|---|
| Which instances receive the revision? | The existing instances in the deployment group | Replacement instances, which the deployment installs the revision on |
| How is traffic handled? | Traffic is not moved between separate environments as part of the deployment | Traffic can be routed to the replacement environment through a load balancer, when you configure it |
| Is a separate environment needed for validation? | No | Yes, the replacement environment is where the new version is validated before traffic moves |
| Best fit for a first deployment | A single application on a small, known set of instances, where you want the fewest moving parts | Situations where you need a replacement environment to test before any users reach it |
For a first deployment, in-place is the simpler choice, because it needs no load balancer and no second set of instances. Blue/green becomes worth the extra setup when you need to validate on new machines before traffic reaches them. Neither option gives zero downtime or easy rollback by default; those behaviours depend on how you configure the deployment and the load balancer.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Step 4: Configure the deployment group
The deployment group decides which instances are in scope. A group can target:
- Amazon EC2 instances selected by tag. Only instances that carry the tag key and value you specify are included. This limits the deployment to exactly the machines you tagged.
- EC2 Auto Scaling group members. Every instance in the named Auto Scaling group is in scope, including instances the group adds later.
- Both. The group includes tagged instances and Auto Scaling members together.
For a first run, a tag on one or two test instances is the most controllable selector. A mistyped tag value means no instances match, so confirm the instance list before you start the deployment.
Step 5: Confirm the instances are ready
Each target instance needs two things before a deployment can succeed:
- The CodeDeploy agent installed and running. A stopped agent is one of the causes AWS lists for failed deployments. Check the agent’s status on the instance before every deployment, not just the first one. The CodeDeploy agent documentation covers installation and operation.
- An IAM instance profile that allows the needed AWS access. Missing instance-profile credentials or insufficient permissions cause agent communication failures and S3 revision-download failures. The instance also needs network access to AWS endpoints, and a blocked path produces the same kind of failure.
Agent version matters too. AWS’s agent release history lists version 2.1.0, released September 7, 2026. That release adds native support for the RESTART deployment mode and makes the agent reject an AppSpec path that resolves outside the application revision directory. Check the current version and the operating systems supported in your Region before installing or upgrading, because support can change between releases.
Recommended Free Tools
Best Value
Step 6: Deploy and verify the lifecycle events
Once the revision is in S3 or GitHub, the group is set, and the agent is running, create the deployment from the CodeDeploy console by choosing the application, the deployment group, and the revision location. When it starts, open the deployment’s details page. It lists each instance and each lifecycle event with its status.
- Watch the events in order. A deployment is only successful when every event completes, not when the first one does.
- Open any failed event and read its status and the script output for the instance it failed on.
- Confirm the application behaves as expected on the target instance, for example by loading the page or endpoint your
ValidateServicescript checks. - Read the agent log on the instance for the exit code and any error text if a script’s output is not enough.
When a deployment fails: a debugging order
AWS recommends starting from the failed lifecycle event and working outward, rather than changing several settings at once. Changing many things together makes it impossible to tell which change fixed the problem. Check these in order:
- The failed event. Identify the event and instance from the deployment details.
- The agent. Confirm it is installed, updated and running on that instance.
- Permissions. Confirm the instance is tagged as your group expects and the instance profile grants the access the agent needs.
- Revision access. Confirm the bundle is in the expected S3 bucket or GitHub location, in the same Region, and readable from the instance.
- AppSpec and scripts. Confirm the YAML is valid,
appspec.ymlis at the root, file paths resolve, and each hook script exists at the path you listed. - Resources. Check that the instance has enough memory and disk space for the copy and the scripts.
Monitoring helps at every step. AWS recommends centralising deployment logs in CloudWatch Logs, so you can compare the agent output across instances without logging into each one.
One detail catches people out. The ApplicationStop, BeforeBlockTraffic and AfterBlockTraffic scripts can be taken from the AppSpec file of the previous successful deployment, while the other scripts come from the current revision. If one of those early events fails, review the previously deployed revision as well as the one you just uploaded. The EC2/On-Premises troubleshooting guide and the general troubleshooting page list further causes and fixes.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Before your next deployment
- The revision is zipped from the folder’s contents, with
appspec.ymlat the root and only one AppSpec file in the bundle. - The YAML validates, and every hook path points to a script that exists in the revision.
- The deployment group’s tag or Auto Scaling group selects exactly the instances you intend.
- The agent is running on each target, and its instance profile allows access to the revision bucket.
- The bucket is in the same Region as the deployment group.
- You know which lifecycle event to check first if the deployment fails.
Keep the first deployment small, on one or two instances, so that a failure is easy to read and easy to repeat.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




