From “Permission Denied” to Production: My AWS & Terraform Journey

Source: Dev.to | Dec 30, 2025 (UTC)

Provisioning infrastructure and deploying applications manually is a recipe for inconsistency. Today, I took on the challenge of automating a server setup using Terraform to host a Spring Boot Java application. It wasn’t a straight path. I ran into regional payment blocks, architecture mismatches and SSH “ghosts” but here is exactly how I solved them.

The Pivot From DigitalOcean to AWS:

I was following a course where the instructor used DigitalOcean to deploy the Java app. I tried to follow along, but I hit a brick wall, DigitalOcean kept rejecting my cards because I am in Nigeria.
I felt bad for a few days, but then I remembered my #30ofAWSTerraform challenge. AWS is known for its complexity, but it’s also the industry leader. I decided to stop feeling bad and start building. If the course used a DigitalOcean “Firewall,” I knew I could translate that into an AWS Security Group. I decided to test my knowledge and gain real experience.

1. Provisioning Infrastructure with Terraform:

My goal was to use Infrastructure as Code (IaC) to create an EC2 instance. I used the aws_instance and aws_key_pair resources to define my server.

The Challenge: SSH Key Management
Initially, passing the public key as a raw string variable led to formatting errors.

The Solution:
I used the Terraform file() function to read my public key directly from my local disk. This ensured that the exact bytes on my Windows machine matched what AWS received.

resource "aws_key_pair" "my_ssh_key" { key_name = "zacks-key" public_key = file("C:/Users/Public/id_aws.pub") }

Enter fullscreen mode

Exit fullscreen mode

2. The Battle of AMI IDs and Usernames:

Even after the server was “running,” I couldn’t get in. I kept seeing InvalidAMIID.NotFound or Permission denied (publickey).

The Lessons Learned:

3. Deploying the Application (The JAR File):

Once the server was accessible, I needed to move my Java artifact from my local build/libs folder to the cloud.

The Tool: SCP (Secure Copy)
I used the following command to securely upload the JAR:
scp -i C:\Users\Public\id_aws "C:\Users\...\java-app-1.0-SNAPSHOT.jar" ubuntu@<IP>:/home/ubuntu/

Translating Firewall to Security Group:
When my instructor added a firewall on DigitalOcean, I knew exactly what to do in AWS. I updated my Security Group in Terraform to open Port 8080, allowing traffic to reach my Spring Boot application.

4. Linux User Management & Security

For security best practices, I created a personal user: zacks.

The Steps taken:

  1. Creation: sudo adduser zacks.
  2. Permissions: I gave the user administrative power using sudo usermod -aG sudo zacks.
  3. The Final SSH Boss: I mistakenly named my key file Authentication_keys. Linux ignores this, It must be named authorized_keys. Furthermore, I had to use chown to ensure the user zacks actually owned the file and chmod 600 to make it private.

sudo mv /home/zacks/.ssh/Authentication_keys /home/zacks/.ssh/authorized_keys sudo chown -R zacks:zacks /home/zacks/.ssh sudo chmod 600 /home/zacks/.ssh/authorized_keys

Enter fullscreen mode

Exit fullscreen mode

Conclusion

Today was a masterclass in troubleshooting. I learned that DevOps isn’t just about writing code; it’s about being adaptable. When one cloud door closed, I used Terraform to open a better one on AWS.

Infrastructure is live, the JAR is running, and the “Whitelabel Error Page” never looked so beautiful!

For further actions, you may consider blocking this person and/or reporting abuse

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Читайте також