{"id":28919314,"url":"https://github.com/jemjal/linkshrink-microservices","last_synced_at":"2026-04-13T03:03:14.035Z","repository":{"id":299780458,"uuid":"1002486278","full_name":"JemJal/linkshrink-microservices","owner":"JemJal","description":"A complete microservices-powered URL shortener (FastAPI, Nginx) with automated CI/CD deployment to AWS using Terraform and GitHub Actions.","archived":false,"fork":false,"pushed_at":"2025-06-18T08:58:53.000Z","size":102,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-18T09:24:27.694Z","etag":null,"topics":["aws","cicd","docker","ecs","fastapi","github-actions","infrastructure-as-code","microservices","nginx","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JemJal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-15T15:23:10.000Z","updated_at":"2025-06-18T08:43:20.000Z","dependencies_parsed_at":"2025-06-18T09:37:06.201Z","dependency_job_id":null,"html_url":"https://github.com/JemJal/linkshrink-microservices","commit_stats":null,"previous_names":["jemjal/linkshrink-microservices"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/JemJal/linkshrink-microservices","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JemJal%2Flinkshrink-microservices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JemJal%2Flinkshrink-microservices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JemJal%2Flinkshrink-microservices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JemJal%2Flinkshrink-microservices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JemJal","download_url":"https://codeload.github.com/JemJal/linkshrink-microservices/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JemJal%2Flinkshrink-microservices/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261229093,"owners_count":23127555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","cicd","docker","ecs","fastapi","github-actions","infrastructure-as-code","microservices","nginx","terraform"],"created_at":"2025-06-22T03:06:00.631Z","updated_at":"2026-04-13T03:03:13.942Z","avatar_url":"https://github.com/JemJal.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LinkShrink Microservices\n\nA fully-featured URL shortening application built on a modern microservices architecture. It provides user authentication, authenticated link creation and management, high-performance redirects, and asynchronous click analytics. The entire system is designed for automated, production-ready deployment to AWS using Terraform and GitHub Actions.\n\nThis repository serves as a complete, real-world blueprint for deploying a complex, multi-service application to the cloud.\n\n## Table of Contents\n\n1.  [Project Overview](#project-overview)\n2.  [System Architecture](#system-architecture)\n3.  [File \u0026 Directory Structure](#file--directory-structure)\n4.  [Getting Started: Local Development](#getting-started-local-development)\n5.  [Cloud Deployment: The Automated CI/CD Pipeline](#cloud-deployment-the-automated-cicd-pipeline)\n    -   [One-Time Setup (Prerequisites)](#one-time-setup-prerequisites)\n    -   [Automated Deployment](#automated-deployment)\n6.  [Running Terraform Commands Locally](#running-terraform-commands-locally)\n7.  [Destroying the Cloud Infrastructure](#destroying-the-cloud-infrastructure)\n8.  [Key Design Decisions \u0026 Concepts](#key-design-decisions--concepts)\n9.  [Release History](#release-history)\n\n## Project Overview\n\nThis project demonstrates a real-world software development lifecycle, from local containerized development to a fully automated cloud deployment.\n\n**Core Features:**\n-   **Secure HTTPS:** All traffic is encrypted using an SSL certificate from AWS Certificate Manager.\n-   **Custom Domain:** The application is served from a custom domain/subdomain managed by Amazon Route 53.\n-   **User-Facing GUI:** A reactive frontend built with Vue.js for user registration, login, and link management.\n-   **Authenticated API:** Users must be logged in to create or view their links.\n-   **Custom Aliases:** Users can now specify their own custom short codes for links.\n-   **High-Performance Redirects:** A dedicated redirect service using a Redis cache for sub-millisecond lookups.\n-   **Asynchronous Analytics:** Link clicks are processed in the background via a message queue (RabbitMQ) without slowing down user redirects.\n-   **Infrastructure as Code (IaC):** The entire AWS infrastructure is defined idempotently and managed by Terraform.\n-   **Automated CI/CD:** A multi-stage GitHub Actions workflow automatically builds, tests (implicitly), and deploys the entire application on every push to the `main` branch.\n\n## System Architecture\n\nThe system is composed of five distinct microservices and a suite of managed AWS services, all orchestrated by an Application Load Balancer. All public traffic is served over HTTPS.\n\n```mermaid\ngraph TD\n    subgraph \"User's Browser\"\n        A[\"Vue.js GUI (HTTPS)\"]\n    end\n\n    subgraph \"AWS Cloud\"\n        subgraph \"Application Load Balancer\"\n            B(\"HTTPS Listener on Port 443\")\n        end\n\n        subgraph \"ECS Services on Fargate\"\n            C[\"Vue.js GUI (linkshrink-vue-gui)\"]\n            D[\"User Service\"]\n            E[\"Link Service\"]\n            F[\"Redirect Service\"]\n            G[\"Analytics Service\"]\n        end\n\n        subgraph \"Data Stores\"\n            H[\"User DB - Postgres\"]\n            I[\"Link DB - Postgres\"]\n            J[\"Redirect Cache - Redis\"]\n            K[\"Message Queue - RabbitMQ\"]\n        end\n    end\n\n    A -- \"Secure Requests\" --\u003e B\n\n    B -- \"API: /users or /token\" --\u003e D\n    B -- \"API: /links\" --\u003e E\n    B -- \"Redirects: /r/:shortcode\" --\u003e F\n    B -- \"Default Route for GUI\" --\u003e C\n\n    D -- \"Reads/Writes\" --\u003e H\n    E -- \"Reads/Writes\" --\u003e I\n    E -- \"Writes to Cache\" --\u003e J\n    F -- \"Internal API Call (Cache Miss)\" --\u003e B\n    F -- \"Cache Hit\" --\u003e J\n    F -- \"Publishes Click Event\" --\u003e K\n    G -- \"Consumes Events\" --\u003e K\n```\n\n## File \u0026 Directory Structure\n\n-   **Core Application Services:** Source code for each microservice (`user-service/`, `link-service/`, etc.) and the new Vue.js frontend (`linkshrink-vue-gui/`).\n-   **Local Development \u0026 Tooling:** The file used for orchestrating all services locally (`docker-compose.yml`).\n-   **Cloud Infrastructure \u0026 CI/CD (AWS):** Files defining the production environment and its automation (`.github/`, `terraform/`).\n-   **Project-Wide Configuration:** General project files (`.gitignore`, `.dockerignore`, `README.md`).\n\n## Getting Started: Local Development\n\nRunning the entire application on your local machine is the recommended way to develop new features. The setup uses Docker Compose to orchestrate all services, including the Vue.js development server with hot-reloading.\n\n**Prerequisites:**\n-   Docker \u0026 Docker Compose\n\n**Steps:**\n1.  Clone this repository.\n2.  From the project's root directory, run:\n    ```bash\n    docker-compose up --build\n    ```\n3.  Open your web browser and navigate to `http://localhost:8080`. You will see the Vue.js application.\n\n## Cloud Deployment: The Automated CI/CD Pipeline\n\nThis project is configured for fully automated deployment to AWS. The process requires a one-time setup of cloud resources and secrets, after which every `git push` to the `main` branch will trigger a safe, multi-stage deployment.\n\n### One-Time Setup (Prerequisites)\n\n1.  **AWS Account:** You need an active AWS account.\n2.  **Custom Domain \u0026 DNS Delegation:**\n    -   Own a custom domain name (e.g., `c3mcal.com`).\n    -   In Amazon Route 53, create a public **Hosted Zone** for a subdomain you will use for AWS projects (e.g., `aws.c3mcal.com`).\n    -   In your domain registrar's settings (e.g., Cloudflare, GoDaddy), add `NS` records to delegate control of that subdomain to the four Name Servers provided by your new Route 53 Hosted Zone.\n3.  **SSL Certificate:**\n    -   In AWS Certificate Manager (ACM), request a public certificate for your application's domain (e.g., `linkshrink.aws.c3mcal.com`) and a wildcard (e.g., `*.aws.c3mcal.com`).\n    -   Use **DNS validation**. Since Route 53 now controls your DNS, you can use the \"Create records in Route 53\" button for instant, automatic validation.\n    -   Once the certificate is \"Issued\", copy its **ARN**.\n4.  **Terraform Backend:** Manually create an S3 bucket and a DynamoDB table in AWS to store Terraform's state securely, as defined in `terraform/backend.tf`.\n5.  **GitHub Repository Secrets:** In your repository's **Settings \u003e Secrets and variables \u003e Actions**, create the following secrets. The workflow uses these to authenticate and configure the deployment.\n\n| Secret Name                   | Description                                                |\n| ----------------------------- | ---------------------------------------------------------- |\n| `AWS_ACCESS_KEY_ID`           | Your IAM user's Access Key ID.                             |\n| `AWS_SECRET_ACCESS_KEY`       | Your IAM user's Secret Access Key.                         |\n| `TF_VAR_DB_PASSWORD`          | A strong password for the `user-db`.                       |\n| `TF_VAR_LINK_DB_PASSWORD`     | A strong password for the `link-db`.                       |\n| `TF_VAR_JWT_SECRET_KEY`       | A long, random string for signing JWTs.                    |\n| `TF_VAR_MQ_PASSWORD`          | A strong password for the RabbitMQ user.                   |\n| `TF_VAR_PARENT_ZONE_NAME`     | The name of your delegated Route 53 Hosted Zone (e.g., `aws.c3mcal.com`). |\n| `TF_VAR_DOMAIN_NAME`          | The full domain for this specific application (e.g., `linkshrink.aws.c3mcal.com`). |\n| `TF_VAR_ACM_CERTIFICATE_ARN`  | The full ARN of your issued ACM certificate.               |\n\n*Note: The `TF_VAR_` prefix is important, as it allows Terraform to automatically recognize these as input variables.*\n\n### Automated Deployment\n\nWith the one-time setup complete, the process is fully automated.\n\n1.  **Develop on a branch:** Create a new branch for your changes (`git checkout -b fix/new-feature`).\n2.  **Open a Pull Request:** When ready, push your branch and open a Pull Request against `main`. The CI workflow will run a `terraform plan` to show you a safe preview of the infrastructure changes.\n3.  **Merge to `main`:** After reviewing the plan, merge the PR. Merging to `main` automatically triggers the full deployment workflow.\n\nMonitor the progress in the \"Actions\" tab of your repository. Upon completion, your application will be live at your custom domain.\n\n## Running Terraform Commands Locally\n\nTo run `terraform` commands from your own computer, you must provide your secrets locally.\n\n1.  Navigate to the `/terraform` directory.\n2.  Copy the example variables file: `cp terraform.tfvars.example terraform.tfvars`\n3.  Open `terraform.tfvars` and replace the placeholders with your actual secrets. This file is ignored by Git and must not be committed.\n4.  You can now run commands like `terraform plan` or `terraform apply` locally.\n\n## Destroying the Cloud Infrastructure\n\nTo avoid ongoing AWS costs, you can tear down the entire infrastructure with a single command from the `/terraform` directory:\n\n```bash\nterraform destroy\n```\n\n## Key Design Decisions \u0026 Concepts\n\n-   **Three-Phase Deployment:** The CI/CD pipeline is explicitly split into three jobs (Create Repos, Build Images, Deploy Services) to correctly handle infrastructure dependencies.\n-   **Immutable Image Tags:** ECR repositories are configured to be immutable, ensuring deployment integrity and preventing accidental changes.\n-   **Git Commit as Source of Truth:** The Git commit hash is used as the Docker image tag, creating a direct, auditable link between code and what's running in production.\n\n## Release History\n\n-   **v2.0.0-beta.1 - The Vue.js Frontend (Current)**\n    -   Overhauled the entire frontend with a modern Vue.js single-page application (`linkshrink-vue-gui`).\n    -   Introduced the ability for users to create links with custom short codes (aliases).\n    -   Replaced the static Nginx-based local UI with a full-featured Vue development server for a better developer experience.\n    -   Updated the CI/CD pipeline to seamlessly build and deploy the new Vue.js frontend alongside the backend services.\n    -   Resolved complex Terraform state-locking and resource dependency issues during the migration, hardening the deployment process for future updates.\n\n-   **v1.1.0 - The Secure Cloud Update**\n    -   Added full HTTPS encryption for all traffic using AWS Certificate Manager.\n    -   Configured the application to run on a custom subdomain (`linkshrink.aws.c3mcal.com`).\n    -   Implemented automated DNS record creation via Terraform and Route 53.\n    -   Hardened the CI/CD pipeline to be fully parameterized and reusable.\n    -   Fixed a bug where the `analytics-service` would fail to start.\n    -   Fixed a bug where the `redirect-service` could not handle the `/r/` path.\n    -   Fixed a bug where the `link-service` generated incorrect `localhost` URLs.\n\n-   **v1.0.0 - Initial Stable Release**\n    -   First stable, fully functional release of the LinkShrink application.\n    -   Established the core 5-service microservices architecture.\n    -   Launched the initial automated deployment pipeline to AWS with a functional frontend.\n\n# A line to force a new deployment...","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjemjal%2Flinkshrink-microservices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjemjal%2Flinkshrink-microservices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjemjal%2Flinkshrink-microservices/lists"}