Files
syncrow-web/infrastructure/web-stack.ts
Ammar Qaffaf 99b13ee062 Adds CDK deployment instructions and updates region
Enhances the README with CDK deployment commands.
2025-07-07 09:38:09 +03:00

110 lines
3.7 KiB
TypeScript

import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
import * as acm from 'aws-cdk-lib/aws-certificatemanager';
import * as route53 from 'aws-cdk-lib/aws-route53';
import * as targets from 'aws-cdk-lib/aws-route53-targets';
import { Construct } from 'constructs';
export interface WebStackProps extends cdk.StackProps {
certificateArn?: string;
}
export class WebStack extends cdk.Stack {
public readonly distributionUrl: string;
public readonly bucketName: string;
constructor(scope: Construct, id: string, props?: WebStackProps) {
super(scope, id, props);
const bucketName = `syncrow-web-${this.account}-${this.region}`;
const webBucket = new s3.Bucket(this, 'SyncrowWebBucket', {
bucketName,
websiteIndexDocument: 'index.html',
websiteErrorDocument: 'index.html',
publicReadAccess: true,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
// Use existing wildcard certificate in us-east-1 (required for CloudFront)
const webCertificate = props?.certificateArn
? acm.Certificate.fromCertificateArn(this, 'WildcardCertificate', props.certificateArn)
: acm.Certificate.fromCertificateArn(this, 'WildcardCertificate',
'arn:aws:acm:us-east-1:482311766496:certificate/b3ea57be-9bf0-4c66-8b01-9672ef1e8530');
// Get the hosted zone
const hostedZone = route53.HostedZone.fromLookup(this, 'SyncrowZone', {
domainName: 'syncrow.me',
});
const distribution = new cloudfront.Distribution(this, 'SyncrowWebDistribution', {
defaultBehavior: {
origin: new origins.S3Origin(webBucket),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
domainNames: ['app.syncrow.me'],
certificate: webCertificate,
defaultRootObject: 'index.html',
errorResponses: [
{
httpStatus: 404,
responseHttpStatus: 200,
responsePagePath: '/index.html',
},
{
httpStatus: 403,
responseHttpStatus: 200,
responsePagePath: '/index.html',
},
],
});
// Create Route 53 record for app.syncrow.me
new route53.ARecord(this, 'WebAliasRecord', {
zone: hostedZone,
recordName: 'app',
target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
});
new s3deploy.BucketDeployment(this, 'SyncrowWebDeployment', {
sources: [s3deploy.Source.asset('./build/web')],
destinationBucket: webBucket,
distribution,
distributionPaths: ['/*'],
});
this.distributionUrl = 'https://app.syncrow.me';
this.bucketName = bucketName;
new cdk.CfnOutput(this, 'WebsiteUrl', {
value: this.distributionUrl,
description: 'Web Application URL',
exportName: `${this.stackName}-WebsiteUrl`,
});
new cdk.CfnOutput(this, 'CloudFrontUrl', {
value: `https://${distribution.distributionDomainName}`,
description: 'CloudFront Distribution URL',
exportName: `${this.stackName}-CloudFrontUrl`,
});
new cdk.CfnOutput(this, 'BucketName', {
value: this.bucketName,
description: 'S3 Bucket Name',
exportName: `${this.stackName}-BucketName`,
});
new cdk.CfnOutput(this, 'WildcardCertificateArn', {
value: webCertificate.certificateArn,
description: 'Wildcard SSL Certificate ARN (us-east-1)',
exportName: `${this.stackName}-WildcardCertificateArn`,
});
}
}