Plog is a full-stack blogging application featuring a robust backend API built with Go and a frontend built with React (FE is generated by AI).
Plog provides a RESTful API for managing blog posts and user authentication. The backend is written in Go, leveraging modern practices and libraries. It is designed to be containerized using Docker and deployed onto AWS infrastructure.
- User registration and JWT-based authentication
- CRUD (Create, Read, Update, Delete) operations for blog posts
- Pagination for listing posts
- Association of posts with their authors
- Database migrations management
- API documentation via Swagger
- Backend:
- Language: Go (v1.24+)
- Framework: Gin-Gonic (
github.com/gin-gonic/gin) - ORM/Query Builder: sqlc (
github.com/sqlc-dev/sqlc) for type-safe SQL query generation - Migrations: golang-migrate (
github.com/golang-migrate/migrate) - Authentication: JWT (
github.com/golang-jwt/jwt/v5)
- Database:
- PostgreSQL
- Containerization:
- Docker, Docker Compose (for local dev)
- AWS Services:
- EC2: Application hosting
- RDS: Managed PostgreSQL database
- ECR: Docker container registry (Public)
- Secrets Manager: Secure storage for credentials and secrets
- IAM: Permissions management for AWS services
- CI/CD:
- GitHub Actions
- Go 1.24+
- Docker & Docker Compose
- Make (Optional, for using Makefile commands)
- AWS Account (If deploying to AWS)
- AWS CLI (Optional, for manual AWS setup/interaction)
migrateCLI (Install via instructions here)
-
Clone the repository:
git clone https://github.com/lshigami/Plog.git cd lshigami-plog -
Create
.envfile: Create a file named.envin the project root with the following content (adjust values as needed):DATABASE_URL=postgres://admin:secret@localhost:5432/personal_blog_db?sslmode=disable JWT_SECRET=a_very_secret_key_should_be_longer_and_random_for_dev SERVER_PORT=8080 ACCESS_TOKEN_DURATION=15m
Note:
docker-compose.yamlalso setsDATABASE_URLfor theapiservice, overriding the.envfile value for the container if both are present and docker-compose reads the env file. -
Using Docker Compose (Recommended): This starts the PostgreSQL database and the Go API service together.
docker-compose up --build
The API will be available at
http://localhost:8080. Theentrypoint.shscript within theapiservice's container will automatically wait for Postgres and run migrations. -
Using Makefile (Alternative): If you have PostgreSQL running separately and
migrateCLI installed locally:- Start your local PostgreSQL server ensuring the DB
personal_blog_dbexists with useradminand passwordsecret - Update
DB_URLin theMakefileif your local connection details differ - Run migrations:
make migrate_up - Run the server:
make server(This runsgo run cmd/server/main.go)
- Start your local PostgreSQL server ensuring the DB
(This is a manual deployment guide)
-
AWS Prerequisites:
- An RDS PostgreSQL instance running and accessible
- An ECR Public repository (
public.ecr.aws/r8o3t2l0/go/plog) where the image has been pushed (e.g., by the GitHub Action) - A secret created in AWS Secrets Manager (e.g.,
goPloginap-southeast-1) containing keys likeDATABASE_URL(pointing to RDS),JWT_SECRET,SERVER_PORT,ACCESS_TOKEN_DURATION - An IAM Role for EC2 with Secrets Manager ReadWrite permission for the specific secret
-
Launch EC2 Instance:
- Choose an AMI (e.g., Amazon Linux 2023)
- Select an instance type (e.g.,
t2.micro) - Assign the IAM Role created above
- Configure a Security Group:
- Allow inbound SSH (Port 22) from your IP only
- Allow inbound TCP (Port 8080) from
Anywhere (0.0.0.0/0)or your specific IP/Load Balancer - Ensure outbound traffic to your RDS instance on port 5432 is allowed (often allowed by default, but verify)
- Use a key pair you have access to
-
Connect to EC2 via SSH:
ssh -i /path/to/your/key.pem ec2-user@YOUR_EC2_PUBLIC_IP
-
Install Tools on EC2:
sudo dnf update -y sudo dnf install docker jq -y sudo systemctl start docker sudo systemctl enable docker sudo usermod -a -G docker ec2-user # Log out and log back in for group changes to take effect, or use 'newgrp docker'
-
Deploy the Application:
# (Log back in if you logged out) mkdir ~/plog-app && cd ~/plog-app # Fetch secrets and create .env file (Ensure EC2 Role has permissions) aws secretsmanager get-secret-value --secret-id goPlog --region ap-southeast-1 --query 'SecretString' --output text | jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' > .env # Verify .env content, especially DATABASE_URL pointing to RDS cat .env # Pull the latest image (or specific tag) export IMAGE_TAG=latest # Or your specific commit SHA tag export ECR_PUBLIC_REPO=public.ecr.aws/r8o3t2l0/go/plog docker pull $ECR_PUBLIC_REPO:$IMAGE_TAG # Run the container docker run -d --name plog-container \ --restart unless-stopped \ -p 8080:8080 \ --env-file .env \ $ECR_PUBLIC_REPO:$IMAGE_TAG
-
Verify:
- Check logs:
docker logs plog-container - Check status:
docker ps - Access the API:
curl http://localhost:8080/health(from within EC2) orhttp://YOUR_EC2_PUBLIC_IP:8080/health(from your browser)
- Check logs:
The main API endpoints include:
POST /register: Register a new userPOST /login: Login a user, returns JWTGET /posts: List posts with pagination (limit,offsetquery params)POST /posts: Create a new post (Requires Authentication)GET /posts/{id}: Get a specific post by IDPUT /posts/{id}: Update a specific post (Requires Authentication, user must own post)GET /health: Health check endpoint
This project uses GitHub Actions for basic CI/CD:
test.yml: Triggered on push/pull_request tomain. Checks out code, sets up Go, builds the project, and runs unit tests (go test -v ./...)deploy.yml: Triggered on push tomain- Checks out the code
- Configures AWS credentials using an IAM Role assumed via OIDC
- Logs into AWS ECR Public
- Builds the multi-stage Docker image
- Tags the image with the Git commit SHA
- Pushes the tagged image to the specified ECR Public repository (
public.ecr.aws/r8o3t2l0/go/plog)
Note: The deploy.yml workflow only pushes the image. It does not automatically deploy the new image to the EC2 instance. Manual steps or further automation (e.g., AWS CodeDeploy, SSM Run Command) are required to update the running container on EC2.



