{"id":23897718,"url":"https://github.com/tkwonn/portfolio","last_synced_at":"2026-06-03T16:30:58.863Z","repository":{"id":240466844,"uuid":"801796737","full_name":"tkwonn/portfolio","owner":"tkwonn","description":"Backend Project #2","archived":false,"fork":false,"pushed_at":"2025-06-20T18:04:37.000Z","size":16805,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-14T16:25:36.151Z","etag":null,"topics":["static-website","vm","web-server"],"latest_commit_sha":null,"homepage":"https://taesokkwon.com","language":"TypeScript","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/tkwonn.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-16T23:51:54.000Z","updated_at":"2025-06-20T18:04:41.000Z","dependencies_parsed_at":"2024-05-19T05:28:45.670Z","dependency_job_id":"6c74679b-83a3-4bde-b51c-d2afc682e223","html_url":"https://github.com/tkwonn/portfolio","commit_stats":null,"previous_names":["tkwonn/portfolio"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tkwonn/portfolio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkwonn%2Fportfolio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkwonn%2Fportfolio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkwonn%2Fportfolio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkwonn%2Fportfolio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tkwonn","download_url":"https://codeload.github.com/tkwonn/portfolio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkwonn%2Fportfolio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33874679,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["static-website","vm","web-server"],"created_at":"2025-01-04T17:17:25.975Z","updated_at":"2026-06-03T16:30:58.842Z","avatar_url":"https://github.com/tkwonn.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Portfolio Website\n\n[![GitHub last commit](https://img.shields.io/github/last-commit/tkwonn/portfolio?color=chocolate)](https://github.com/tkwonn/portfolio/commits/)\n[![deploy to EC2](https://github.com/tkwonn/portfolio/actions/workflows/deploy.yml/badge.svg)](https://github.com/tkwonn/portfolio/actions/workflows/deploy.yml)\n\n## Table of Contents\n\n- [About](#-about)\n- [Built with](#️-built-with)\n- [Architecture](#️-architecture)\n- [Server Configuration](#️-server-configuration)\n- [CI/CD](#-cicd)\n\n## 💡 About\n\nThis is a personal portfolio project designed to showcase my personal background, skills, and projects.\n\n**URL:** [taesokkwon.com](https://taesokkwon.com)\n\n## 🏗️ Built with\n\n| **Category** | **Technology**                    |\n| ------------ | --------------------------------- |\n| VM           | Amazon EC2                        |\n| Web server   | Nginx                             |\n| Frontend     | TypeScript, Next.js, Tailwind CSS |\n| CI/CD        | GitHub Actions                    |\n\nThis site is fully static by using Next.js's Static Export and does not require Node.js.\n\n## 🏛️ Architecture\n\nThis website is hosted on a single AWS EC2 instance and uses Nginx as a reverse proxy to manage multiple services under different domains.\n\n| **Server name**                                                                               | **Backend Service**                             | **GitHub Repository**                                                       |\n| --------------------------------------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------- |\n| \u003ca href=\"https://taesokkwon.com\" target=\"_blank\"\u003etaesokkwon.com\u003c/a\u003e                           | Static site served by Nginx                     | -                                                                           |\n| \u003ca href=\"https://plantuml.taesokkwon.com\" target=\"_blank\"\u003eplantuml.taesokkwon.com\u003c/a\u003e         | PHP application served by PHP-FPM (via FastCGI) | \u003ca href=\"https://github.com/tkwonn/plantuml\" target=\"_blank\"\u003eREADME\u003c/a\u003e     |\n| \u003ca href=\"https://text-snippet.taesokkwon.com\" target=\"_blank\"\u003etext-snippet.taesokkwon.com\u003c/a\u003e | PHP application served by PHP-FPM (via FastCGI) | \u003ca href=\"https://github.com/tkwonn/text-snippet\" target=\"_blank\"\u003eREADME\u003c/a\u003e |\n\n![System Architecture](docs/architecture.svg)\n\n## ⚙️ Server Configuration\n\n#### SSL/TLS Setup\n\n- All services are secured with SSL/TLS certificates managed through LetsEncrypt (automatic certificate renewal via Certbot's systemd timer)\n\n#### Security Headers\n\n| **Header**                | **Description**                                                         |\n| ------------------------- | ----------------------------------------------------------------------- |\n| Strict-Transport-Security | Enforces secure (HTTPS) connections to the server                       |\n| X-Content-Type-Options    | Prevents MIME-type sniffing, ensuring the declared content type is used |\n\n#### Cache Control Settings\n\nThe Cache-Control headers are configured by content type:\n\n```nginx\nmap $sent_http_content_type $cache_control {\n    \"text/html\"                     \"public, no-cache, must-revalidate\";\n    \"~image/\"                       \"public, max-age=31536000, immutable\";\n    \"~/_next/static/\"               \"public, max-age=31536000, immutable\";\n    default                         \"public, no-cache\";\n}\n```\n\n- HTML: No caching, always serves fresh content.\n- Images and static files: Cached for one year and marked as immutable.\n\nSince Next.js generates unique filenames for each build, any changes automatically generate new filenames, ensuring updates are reflected despite the immutable setting (cache-busting).\n\nAdditionally, the following compression settings reduce transfer sizes:\n\n```nginx\ngzip on;\ngzip_types text/plain text/css application/javascript application/json image/svg+xml;\n```\n\n## 🚀 CI/CD\n\nThis project uses GitHub Actions to automate testing and deployment workflows with the following configurations.\n\n#### Continuous Integration\n\n- Utilizes npm cache and Next.js cache to speed up builds\n- Code quality checks using Prettier and ESLint\n\n#### Continuous Deployment\n\n- Temporary Security Group Modifications: Dynamically updates the EC2 instance’s security group to allow SSH access from the GitHub Actions runner.\n- SSH Deployment: Deploys updates via an SSH connection that remotely executes commands (such as pulling the latest code, installing dependencies, building the project, and reloading Nginx) on the production server.\n- Post-Deployment Cleanup: Revokes the temporary SSH access immediately after deployment to maintain security.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkwonn%2Fportfolio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftkwonn%2Fportfolio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkwonn%2Fportfolio/lists"}