Step 1: EC2 and PHP
Use Ubuntu 24.04 LTS for the simplest reference deployment. Install Nginx, PHP-FPM, PHP MySQL/cURL/XML/mbstring extensions, unzip and a MySQL client. Verify PHP is at least 8.2. AL2023 can also be used, but select a supported PHP 8.2+ package family available in your pinned repository and adapt the FPM service/socket. Do not assume its unversioned PHP default meets the application requirement.
sudo apt update
sudo apt install -y nginx php-fpm php-cli php-mysql php-curl php-xml php-mbstring unzip mysql-client
php -v
php -mStep 2: private bucket and role
Create the private bucket as taught in the S3 chapter. Copy project/config/iam-policy.json, replace its bucket placeholder and create a policy. Create an EC2-trusted role, attach that policy and assign its instance profile to the web instance. The DeleteObject permission is used to compensate if a database insert fails after an upload. Versioning may retain previous objects/delete markers, so reconciliation still matters. Do not add S3FullAccess. The sample explicitly uses SSE-S3 for uploads; adapt both code and permissions if your bucket requires SSE-KMS.
Step 3: RDS and SQL
Create private RDS MySQL, its subnet group and security group. Download the RDS CA bundle and verify its source. Connect from EC2 using hostname verification, then apply schema.sql as a setup administrator.
mysql -h DB_ENDPOINT -u ADMIN -p --ssl-mode=VERIFY_IDENTITY \
--ssl-ca=/etc/ssl/certs/rds-global-bundle.pem < schema.sqlCreate an application account with a generated password in an administrative SQL session. Use the correct host scope for your network; the example below permits matching network connections but relies on the private SG boundary and authentication.
CREATE USER 'reels_app'@'%' IDENTIFIED BY 'REPLACE_WITH_A_GENERATED_PASSWORD' REQUIRE SSL;
GRANT SELECT, INSERT, UPDATE ON reels.posts TO 'reels_app'@'%';
SHOW GRANTS FOR 'reels_app'@'%';Never paste a real password into shared notes. MySQL client history can retain SQL statements; use an approved secret/bootstrap process for real deployments.
Step 4: prove access
Verify the instance role with aws sts get-caller-identity. Test a permitted S3 key and a forbidden prefix. Connect as reels_app and verify SELECT works while CREATE TABLE is denied. Query SHOW SESSION STATUS LIKE 'Ssl_cipher' and confirm TLS is negotiated.
Ravindra’s Tip
पहले तीन छोटे tests करो: EC2 से database connect, role से S3 access, और Nginx से page load। ये तीनों ठीक हों, तभी पूरा application जोड़ो—debugging आसान होगी।
Official references
Interview and revision check
Why does S3 access succeeding not prove RDS will work?
S3 uses AWS API authorization; RDS also requires private connectivity, TLS and database credentials/privileges.
Ravindra Bagale · Cloud & DevOps Academy · Handbook and project downloads