đź’ˇ What I Built
I created a fast, automated deployment pipeline for a static website using:
AWS EC2 to host the site,
Pulumi to provision infrastructure as code,
GitHub Actions for CI/CD,
And Astro as the static site framework (can easily be swapped for others like Hugo or Jekyll).
The entire process—from infrastructure provisioning to code deployment—is triggered on every push to the main branch. It’s a clean, serverless-free solution leveraging IaaS for simplicity and control.
đź”— Live Demo Link
👉 http://
(Replace this with your EC2 public IP or domain)
📦 Project Repo
🧰 GitHub Repository: github.com/yourusername/fast-static-deploy
(Be sure to include a README with steps, architecture, and how to replicate the deployment!)
✍️ My Journey
This project started as a way to explore how fast and repeatable static site deployments could be using IaaS rather than managed services like Netlify or Vercel.
Key Milestones:
Static Site Creation – I used Astro for its quick setup and zero-JS static rendering.
Pulumi Setup – Defined an EC2 instance, security group, and userData script to install and configure Nginx.
GitHub Actions – Integrated Pulumi into the CI/CD pipeline and added an SCP step to upload the built static files to the EC2 instance.
Secrets Management – Stored Pulumi token, AWS keys, and EC2 SSH key securely in GitHub Secrets.
Challenges I Faced:
EC2 AMI choice and default user (ec2-user for Amazon Linux).
Setting up Pulumi authentication properly in GitHub Actions.
SCP to EC2: Ensuring the SSH key had proper permissions and that Nginx was serving the right folder.
What I Learned:
Pulumi’s type-safe infrastructure-as-code approach is intuitive and powerful.
GitHub Actions make CI/CD effortless with great community actions (e.g., scp-action).
Full control over infrastructure helps you understand deployment deeply—great for learning and production-ready work.
⚙️ Using Pulumi
Pulumi was the backbone of this project’s infrastructure. Here's how I used it:
Provisioned EC2 Instance with Nginx and configured it via userData.
Created Security Group to allow HTTP traffic.
Defined Outputs for public IP, which was picked up in the GitHub Action.
Here’s a simplified Pulumi (TypeScript) snippet I used:
ts
const server = new aws.ec2.Instance("web-server", {
ami: "ami-0c02fb55956c7d316",
instanceType: "t2.micro",
securityGroups: [group.name],
userData:
,
#!/bin/bash
sudo yum install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
});
GitHub Actions + Pulumi:
I used the Pulumi GitHub Action to run pulumi up on every push to main. After that, I added an SCP step to deploy the static files:
yaml
- name: Deploy files to EC2 uses: appleboy/scp-action@master with: host: ${{ secrets.EC2_HOST }} username: ec2-user key: ${{ secrets.EC2_SSH_KEY }} source: "dist/" target: "/usr/share/nginx/html" Pulumi made the whole provisioning process more robust and transparent. Everything is in code. I could destroy or recreate the infrastructure in minutes.
🎉 Thanks Pulumi & DEV for this awesome challenge!
Top comments (0)