case study
Storage
In this section, I configured AWS storage and recovery capabilities for the production environment. I deployed encrypted EBS storage, created snapshots for backup and recovery, and built a custom AMI of the production web server.
I then launched a new EC2 instance from the AMI and successfully ran the Threat Intelligence Application, validating that the configured workload could be reproduced and restored from the image.
-projectzero-prod-vpc has been created with subnets configured.
-projectzero-prod-jumpbox EC2 instance exists and is accessible.
-projectzero-prod-websvr EC2 instance exists (or any EC2 instance for testing).
-My-Desktop-Key-Pair key pair exists.
-AWS CLI configured with appropriate credentials.
#EBS & Snapshots
This section covers the implementation of persistent and recoverable storage for the production web server. I configured an encrypted EBS volume, attached and mounted it to the EC2 instance, made the mount persistent across reboots, and created an EBS snapshot to provide a point-in-time backup for recovery.
##Create and Configure EBS Volume
In this section, I configured Amazon Elastic Block Store (EBS) to provide persistent storage for the production web server. The volume is encrypted at rest and can be independently attached, detached, backed up, and restored using EBS snapshots, providing a foundation for secure storage and recovery within the AWS environment.
1.Availability Zone
The volume was placed in the same Availability Zone as projectzero-prod-websvr to allow it to be attached to the EC2 instance.
2.Configure Volume Settings
I created a dedicated EBS volume to provide persistent storage for the production web server, configuring the volume with the following settings:
-Volume type: gp3 (General Purpose SSD)
-Size: 10 GiB
-IOPS: Default (3000 for gp3)
-Throughput: Default (125 MiB/s for gp3)
3.Enable Encryption at Rest
-KMS key: Default AWS managed key (aws/ebs)
-Encryption at rest is a security best practice. For production, consider using customer managed KMS keys.
-Note: I recorded the Volume ID for use during the attachment and snapshot configuration steps.
##Attach EBS Volume to EC2 Instance
After creating the encrypted EBS volume, I attached it to the production web server. Because EBS volumes are Availability Zone specific, the volume and EC2 instance must reside in the same Availability Zone before they can be attached.
1.Attach Volume via Console
From EC2 → Elastic Block Store → Volumes, I selected the newly created projectzero-volume and chose Actions → Attach volume.
2.Select the Production Web Server
I selected projectzero-prod-websvr as the target EC2 instance and assigned /dev/sdf as the requested Linux device name. AWS may expose the device internally using an NVMe device name on Nitro-based EC2 instances.
3.Verify the Attached Volume via SSH
I connected to projectzero-prod-websvr through the jumpbox and used lsblk to inspect the available block devices. The newly attached 10 GiB EBS volume appeared as nvme1n1, confirming that the volume was successfully attached and recognized by the operating system.
##Format and Mount the EBS Volume
After attaching the EBS volume to projectzero-prod-websvr, I prepared it for use by creating an ext4 filesystem, mounting it to a dedicated directory, and validating read/write access. This makes the newly provisioned block storage accessible to the operating system and ready to store application data.
1.Identify the Device
I used lsblk to identify the newly attached EBS volume. The 10 GiB volume was presented to the instance as nvme1n1 and did not yet contain a filesystem or mount point.
2.Create a File System
I formatted the new EBS volume with the ext4 filesystem so it could be used for persistent Linux storage.
sudo mkfs -t ext4 /dev/nvme1n1
3.Create a Mount Point
I created a dedicated directory that will serve as the mount point for the EBS volume.
sudo mkdir /mnt/projectzero-data
4.Mount the EBS Volume
I mounted the formatted EBS volume to /mnt/projectzero-data, making the storage accessible through the production web server's filesystem.
sudo mount /dev/nvme1n1 /mnt/projectzero-data
5.Verify the Mount
I used df -h to confirm that the EBS volume was successfully mounted. The output shows the 10 GiB nvme1n1 device mounted at /mnt/projectzero-data.
6.Test the Volume
Finally, I created a test file on the mounted volume and read its contents back to verify that the filesystem was writable and functioning correctly.
echo "EBS Volume Test - $(date)" | sudo tee /mnt/projectzero-data/test.txt
cat /mnt/projectzero-data/test.txt
7.Make Mount Persistent
To ensure the EBS volume remains available after the EC2 instance is rebooted, I configured a persistent mount using /etc/fstab. I used the filesystem UUID rather than the NVMe device name to provide a stable reference for the volume across reboots.
First, I retrieved the UUID of the EBS filesystem:
sudo blkid /dev/nvme1n1
Then I edited /etc/fstab:
sudo nano /etc/fstab
and added the EBS volume:
UUID=bba4eff6-1bcf-43c0-82f4-e364a5ddfcd3 /mnt/projectzero-data ext4 defaults,nofail 0 2
Using nofail allows the EC2 instance to continue booting even if the EBS volume is temporarily unavailable.
Finally, I validated the configuration:
sudo mount -a
The command completed without errors, validating the /etc/fstab entry and confirming that the EBS volume is configured for persistent mounting.
##Create EBS Snapshot
After configuring and validating the EBS volume, I created a point-in-time snapshot to demonstrate backup and recovery capabilities. EBS snapshots provide a reusable backup of volume data that can later be used to restore or create replacement volumes.
1.Create Snapshot
From EC2 → Elastic Block Store → Volumes, I selected projectzero-volume and chose Actions → Create snapshot.
I configured the snapshot with a descriptive name and description so the recovery point could be easily identified.
2.Verify Snapshot Completion
Snapshot creation occurs asynchronously. I monitored the snapshot until its status changed to Completed and progress reached 100%, confirming that the backup was successfully created.
#Lab Cleanup
After completing the EBS storage and snapshot validation, I removed the temporary resources to maintain a clean environment and avoid unnecessary AWS costs.
-Removed the EBS entry from /etc/fstab and unmounted the volume.
-Detached and deleted the temporary EBS volume.
-Deleted the test snapshot after validation.
#Create Web Server AMI
In this section, I created a custom Amazon Machine Image (AMI) from the configured projectzero-prod-websvr EC2 instance. The AMI captures the server configuration and provides a reusable baseline that can be used to deploy additional instances without rebuilding the web server from scratch.
1.Create AMI from the Web Server
I selected the existing projectzero-prod-websvr instance and created an image from its current configuration using:
Actions → Image and templates → Create image
I configured the image with a descriptive name and included the instance storage configuration as part of the AMI.
2.Verify AMI Creation
After the image creation process completed, I verified that the custom AMI was available and recorded its AMI ID for use when launching a new instance.
#Launch Instance from AMI in Public Subnet
To validate that the custom AMI could be reused successfully, I launched a new EC2 instance from the image. Unlike the original web server, which resides in the private web subnet, this instance was deployed into the public subnet to provide direct network access for testing.
1.Select the Custom AMI
I selected the previously created projectzero-prod-websvr-ami as the machine image for the new EC2 instance.
2.Configure Instance Type and Key Pair
I configured the new instance with the same t3.small instance type as the original web server and selected my existing SSH key pair for administrative access.
-Instance type: t3.small
-Key pair: My-Desktop-Key-Pair
3.Configure Network Settings
I deployed the instance into the existing projectzero-prod-vpc, but selected the Public Subnet instead of the private web subnet. I also enabled automatic public IPv4 assignment so the instance could be accessed directly for validation.
-VPC: projectzero-prod-vpc
-Subnet: Public Subnet
-Auto-assign public IP: Enabled
-Security group: projectzero-prod-websvr-sg
4.Launch the AMI-Based Web Server
I launched a new EC2 instance from the custom AMI using the public subnet configuration. For validation, I updated the security group to permit access to the application on TCP port 4321.
-Name: projectzero-prod-websvr
-AMI: projectzero-prod-websvr-ami
-Instance type: t3.small
-Key pair: My-Desktop-Key-Pair
-VPC: projectzero-prod-vpc
-Subnet: Public Subnet
-Auto-assign public IP: Enabled
-Security group: projectzero-prod-websvr-SG
5.Validate the AMI Deployment
After the new instance launched, I connected to it and confirmed that the threat-intel-app application files were already present. This verified that the custom AMI successfully preserved the configured web server environment.
1.Start the Threat Intelligence Application
I allowed TCP port 4321 through the host firewall and started the application with the Astro development server, binding it to all network interfaces so it could accept external connections.
sudo ufw allow 4321/tcp
npm run dev -- --host
The application successfully started and listened on 0.0.0.0:4321.
6.Verify External Application Access
Finally, I accessed the Threat Intelligence Application using the new EC2 instance's public IPv4 address on port 4321. The application loaded successfully in the browser, validating the AMI deployment from end to end.
#Why This Matters
EBS volumes provide persistent storage, while snapshots enable backup and recovery. Custom AMIs allow configured EC2 workloads to be quickly reproduced without rebuilding them from scratch. Together, these capabilities support data protection, disaster recovery, and consistent workload deployment in AWS.





















