diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 50bde36072..0000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,10 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Security Contact - about: Please report security vulnerabilities to security@tiangolo.com - - name: Question or Problem - about: Ask a question or ask about a problem in GitHub Discussions. - url: https://github.com/fastapi/full-stack-fastapi-template/discussions/categories/questions - - name: Feature Request - about: To suggest an idea or ask about a feature, please start with a question saying what you would like to achieve. There might be a way to do it already. - url: https://github.com/fastapi/full-stack-fastapi-template/discussions/categories/questions diff --git a/.github/ISSUE_TEMPLATE/privileged.yml b/.github/ISSUE_TEMPLATE/privileged.yml deleted file mode 100644 index 6438848c83..0000000000 --- a/.github/ISSUE_TEMPLATE/privileged.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Privileged -description: You are @tiangolo or he asked you directly to create an issue here. If not, check the other options. 👇 -body: - - type: markdown - attributes: - value: | - Thanks for your interest in this project! 🚀 - - If you are not @tiangolo or he didn't ask you directly to create an issue here, please start the conversation in a [Question in GitHub Discussions](https://github.com/tiangolo/full-stack-fastapi-template/discussions/categories/questions) instead. - - type: checkboxes - id: privileged - attributes: - label: Privileged issue - description: Confirm that you are allowed to create an issue here. - options: - - label: I'm @tiangolo or he asked me directly to create an issue here. - required: true - - type: textarea - id: content - attributes: - label: Issue Content - description: Add the content of the issue here. diff --git a/.github/workflows/README.MD b/.github/workflows/README.MD new file mode 100644 index 0000000000..7e97cdf01d --- /dev/null +++ b/.github/workflows/README.MD @@ -0,0 +1,9 @@ +![CI](https://github.com/AlfreMu/devops-portfolio-fastapi/actions/workflows/ci.yml/badge.svg) + +# Workflows (portfolio) + +Workflows del portfolio: +- ci.yml: se ejecuta en Pull Requests +- cd.yml: deploy automático al mergear a main + +Se construyen de forma incremental. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..180c63b5a4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + pull_request: + branches: [ "main" ] + push: + branches: [ "main" ] + +jobs: + docker-build: + runs-on: ubuntu-latest + permissions: + contents: read + strategy: + fail-fast: false + matrix: + service: + - name: backend + context: ./backend + - name: frontend + context: ./frontend + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build ${{ matrix.service.name }} + uses: docker/build-push-action@v6 + with: + context: ${{ matrix.service.context }} + push: false + tags: devops-portfolio/${{ matrix.service.name }}:ci + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/add-to-project.yml b/.github/workflows_upstream/add-to-project.yml similarity index 100% rename from .github/workflows/add-to-project.yml rename to .github/workflows_upstream/add-to-project.yml diff --git a/.github/workflows/deploy-production.yml b/.github/workflows_upstream/deploy-production.yml similarity index 100% rename from .github/workflows/deploy-production.yml rename to .github/workflows_upstream/deploy-production.yml diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows_upstream/deploy-staging.yml similarity index 100% rename from .github/workflows/deploy-staging.yml rename to .github/workflows_upstream/deploy-staging.yml diff --git a/.github/workflows/detect-conflicts.yml b/.github/workflows_upstream/detect-conflicts.yml similarity index 100% rename from .github/workflows/detect-conflicts.yml rename to .github/workflows_upstream/detect-conflicts.yml diff --git a/.github/workflows/generate-client.yml b/.github/workflows_upstream/generate-client.yml similarity index 100% rename from .github/workflows/generate-client.yml rename to .github/workflows_upstream/generate-client.yml diff --git a/.github/workflows/issue-manager.yml b/.github/workflows_upstream/issue-manager.yml similarity index 100% rename from .github/workflows/issue-manager.yml rename to .github/workflows_upstream/issue-manager.yml diff --git a/.github/workflows/labeler.yml b/.github/workflows_upstream/labeler.yml similarity index 100% rename from .github/workflows/labeler.yml rename to .github/workflows_upstream/labeler.yml diff --git a/.github/workflows/latest-changes.yml b/.github/workflows_upstream/latest-changes.yml similarity index 100% rename from .github/workflows/latest-changes.yml rename to .github/workflows_upstream/latest-changes.yml diff --git a/.github/workflows/playwright.yml b/.github/workflows_upstream/playwright.yml similarity index 100% rename from .github/workflows/playwright.yml rename to .github/workflows_upstream/playwright.yml diff --git a/.github/workflows/pre-commit.yml b/.github/workflows_upstream/pre-commit.yml similarity index 100% rename from .github/workflows/pre-commit.yml rename to .github/workflows_upstream/pre-commit.yml diff --git a/.github/workflows/smokeshow.yml b/.github/workflows_upstream/smokeshow.yml similarity index 100% rename from .github/workflows/smokeshow.yml rename to .github/workflows_upstream/smokeshow.yml diff --git a/.github/workflows/test-backend.yml b/.github/workflows_upstream/test-backend.yml similarity index 100% rename from .github/workflows/test-backend.yml rename to .github/workflows_upstream/test-backend.yml diff --git a/.github/workflows/test-docker-compose.yml b/.github/workflows_upstream/test-docker-compose.yml similarity index 100% rename from .github/workflows/test-docker-compose.yml rename to .github/workflows_upstream/test-docker-compose.yml diff --git a/README.md b/README.md index a9049b4779..443498629c 100644 --- a/README.md +++ b/README.md @@ -1,233 +1,50 @@ -# Full Stack FastAPI Template +# DevOps Portfolio — FastAPI Template (Docker + Kubernetes + CI/CD + AWS) -Test Docker Compose -Test Backend -Coverage +![CI](https://github.com/AlfreMu/devops-portfolio-fastapi/actions/workflows/ci.yml/badge.svg) -## Technology Stack and Features +Este repositorio es un **portfolio personal DevOps/Cloud**. El objetivo es demostrar prácticas modernas de: +- Docker +- Kubernetes (kind en local / k3s en AWS EC2 — **sin EKS**) +- CI/CD con GitHub Actions +- Deploy automático al mergear Pull Requests -- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API. - - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) for the Python SQL database interactions (ORM). - - 🔍 [Pydantic](https://docs.pydantic.dev), used by FastAPI, for the data validation and settings management. - - 💾 [PostgreSQL](https://www.postgresql.org) as the SQL database. -- 🚀 [React](https://react.dev) for the frontend. - - 💃 Using TypeScript, hooks, [Vite](https://vitejs.dev), and other parts of a modern frontend stack. - - 🎨 [Tailwind CSS](https://tailwindcss.com) and [shadcn/ui](https://ui.shadcn.com) for the frontend components. - - 🤖 An automatically generated frontend client. - - 🧪 [Playwright](https://playwright.dev) for End-to-End testing. - - 🦇 Dark mode support. -- 🐋 [Docker Compose](https://www.docker.com) for development and production. -- 🔒 Secure password hashing by default. -- 🔑 JWT (JSON Web Token) authentication. -- 📫 Email based password recovery. -- 📬 [Mailcatcher](https://mailcatcher.me) for local email testing during development. -- ✅ Tests with [Pytest](https://pytest.org). -- 📞 [Traefik](https://traefik.io) as a reverse proxy / load balancer. -- 🚢 Deployment instructions using Docker Compose, including how to set up a frontend Traefik proxy to handle automatic HTTPS certificates. -- 🏭 CI (continuous integration) and CD (continuous deployment) based on GitHub Actions. +> La aplicación se utiliza como base open-source. El foco principal es infraestructura, automatización y despliegue. -### Dashboard Login +## Qué vas a encontrar acá +- `docs/`: arquitectura, decisiones técnicas y guías de ejecución +- `k8s/portfolio/`: manifiestos Kubernetes creados como parte del portfolio +- `.github/workflows/`: pipelines del portfolio (CI y CD) -[![API docs](img/login.png)](https://github.com/fastapi/full-stack-fastapi-template) +## Arquitectura (resumen) +- **Local (Docker):** ejecución reproducible con Docker/Compose +- **Local (Kubernetes):** cluster kind + manifests del portfolio +- **AWS:** instancia EC2 corriendo k3s + Nginx Ingress Controller +- **CI/CD:** GitHub Actions: + - CI en Pull Requests + - CD al mergear a `main` -### Dashboard - Admin +## Cómo ejecutarlo +- Local con Docker: ver `docs/runbooks/local-docker.md` +- Kubernetes local (kind): ver `docs/runbooks/kind.md` +- AWS (EC2 + k3s): ver `docs/runbooks/aws-k3s.md` -[![API docs](img/dashboard.png)](https://github.com/fastapi/full-stack-fastapi-template) +## Skills DevOps demostradas +- Containerización y buenas prácticas Docker +- Deploy y troubleshooting en Kubernetes +- Automatización CI/CD con GitHub Actions +- Deploy automático a infraestructura en AWS (sin EKS) +- Documentación técnica orientada a entrevistas -### Dashboard - Items +## Roadmap +- [X] Phase 1: Docker baseline +- [X] Phase 2: Kubernetes local (kind) +- [ ] Phase 3: CI/CD +- [ ] Phase 4: AWS EC2 + k3s deploy -[![API docs](img/dashboard-items.png)](https://github.com/fastapi/full-stack-fastapi-template) +--- -### Dashboard - Dark Mode + -[![API docs](img/dashboard-dark.png)](https://github.com/fastapi/full-stack-fastapi-template) +📌 Autor: AlfreMu -### Interactive API Documentation -[![API docs](img/docs.png)](https://github.com/fastapi/full-stack-fastapi-template) - -## How To Use It - -You can **just fork or clone** this repository and use it as is. - -✨ It just works. ✨ - -### How to Use a Private Repository - -If you want to have a private repository, GitHub won't allow you to simply fork it as it doesn't allow changing the visibility of forks. - -But you can do the following: - -- Create a new GitHub repo, for example `my-full-stack`. -- Clone this repository manually, set the name with the name of the project you want to use, for example `my-full-stack`: - -```bash -git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack -``` - -- Enter into the new directory: - -```bash -cd my-full-stack -``` - -- Set the new origin to your new repository, copy it from the GitHub interface, for example: - -```bash -git remote set-url origin git@github.com:octocat/my-full-stack.git -``` - -- Add this repo as another "remote" to allow you to get updates later: - -```bash -git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git -``` - -- Push the code to your new repository: - -```bash -git push -u origin master -``` - -### Update From the Original Template - -After cloning the repository, and after doing changes, you might want to get the latest changes from this original template. - -- Make sure you added the original repository as a remote, you can check it with: - -```bash -git remote -v - -origin git@github.com:octocat/my-full-stack.git (fetch) -origin git@github.com:octocat/my-full-stack.git (push) -upstream git@github.com:fastapi/full-stack-fastapi-template.git (fetch) -upstream git@github.com:fastapi/full-stack-fastapi-template.git (push) -``` - -- Pull the latest changes without merging: - -```bash -git pull --no-commit upstream master -``` - -This will download the latest changes from this template without committing them, that way you can check everything is right before committing. - -- If there are conflicts, solve them in your editor. - -- Once you are done, commit the changes: - -```bash -git merge --continue -``` - -### Configure - -You can then update configs in the `.env` files to customize your configurations. - -Before deploying it, make sure you change at least the values for: - -- `SECRET_KEY` -- `FIRST_SUPERUSER_PASSWORD` -- `POSTGRES_PASSWORD` - -You can (and should) pass these as environment variables from secrets. - -Read the [deployment.md](./deployment.md) docs for more details. - -### Generate Secret Keys - -Some environment variables in the `.env` file have a default value of `changethis`. - -You have to change them with a secret key, to generate secret keys you can run the following command: - -```bash -python -c "import secrets; print(secrets.token_urlsafe(32))" -``` - -Copy the content and use that as password / secret key. And run that again to generate another secure key. - -## How To Use It - Alternative With Copier - -This repository also supports generating a new project using [Copier](https://copier.readthedocs.io). - -It will copy all the files, ask you configuration questions, and update the `.env` files with your answers. - -### Install Copier - -You can install Copier with: - -```bash -pip install copier -``` - -Or better, if you have [`pipx`](https://pipx.pypa.io/), you can run it with: - -```bash -pipx install copier -``` - -**Note**: If you have `pipx`, installing copier is optional, you could run it directly. - -### Generate a Project With Copier - -Decide a name for your new project's directory, you will use it below. For example, `my-awesome-project`. - -Go to the directory that will be the parent of your project, and run the command with your project's name: - -```bash -copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust -``` - -If you have `pipx` and you didn't install `copier`, you can run it directly: - -```bash -pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust -``` - -**Note** the `--trust` option is necessary to be able to execute a [post-creation script](https://github.com/fastapi/full-stack-fastapi-template/blob/master/.copier/update_dotenv.py) that updates your `.env` files. - -### Input Variables - -Copier will ask you for some data, you might want to have at hand before generating the project. - -But don't worry, you can just update any of that in the `.env` files afterwards. - -The input variables, with their default values (some auto generated) are: - -- `project_name`: (default: `"FastAPI Project"`) The name of the project, shown to API users (in .env). -- `stack_name`: (default: `"fastapi-project"`) The name of the stack used for Docker Compose labels and project name (no spaces, no periods) (in .env). -- `secret_key`: (default: `"changethis"`) The secret key for the project, used for security, stored in .env, you can generate one with the method above. -- `first_superuser`: (default: `"admin@example.com"`) The email of the first superuser (in .env). -- `first_superuser_password`: (default: `"changethis"`) The password of the first superuser (in .env). -- `smtp_host`: (default: "") The SMTP server host to send emails, you can set it later in .env. -- `smtp_user`: (default: "") The SMTP server user to send emails, you can set it later in .env. -- `smtp_password`: (default: "") The SMTP server password to send emails, you can set it later in .env. -- `emails_from_email`: (default: `"info@example.com"`) The email account to send emails from, you can set it later in .env. -- `postgres_password`: (default: `"changethis"`) The password for the PostgreSQL database, stored in .env, you can generate one with the method above. -- `sentry_dsn`: (default: "") The DSN for Sentry, if you are using it, you can set it later in .env. - -## Backend Development - -Backend docs: [backend/README.md](./backend/README.md). - -## Frontend Development - -Frontend docs: [frontend/README.md](./frontend/README.md). - -## Deployment - -Deployment docs: [deployment.md](./deployment.md). - -## Development - -General development docs: [development.md](./development.md). - -This includes using Docker Compose, custom local domains, `.env` configurations, etc. - -## Release Notes - -Check the file [release-notes.md](./release-notes.md). - -## License - -The Full Stack FastAPI Template is licensed under the terms of the MIT license. diff --git a/docker-compose.portfolio.yml b/docker-compose.portfolio.yml new file mode 100644 index 0000000000..e030357e34 --- /dev/null +++ b/docker-compose.portfolio.yml @@ -0,0 +1,49 @@ +services: + db: + image: postgres:17 + restart: unless-stopped + environment: + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changethis} + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_DB: ${POSTGRES_DB:-app} + volumes: + - db-data:/var/lib/postgresql/data + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + interval: 10s + timeout: 5s + retries: 5 + + backend: + build: + context: ./backend + restart: unless-stopped + env_file: + - .env + depends_on: + db: + condition: service_healthy + ports: + - "8000:8000" + + frontend: + build: + context: ./frontend + restart: unless-stopped + depends_on: + - backend + ports: + - "5173:80" + + adminer: + image: adminer + restart: unless-stopped + depends_on: + - db + ports: + - "8080:8080" + +volumes: + db-data: diff --git a/docs/arquitectura.md b/docs/arquitectura.md new file mode 100644 index 0000000000..10f5335409 --- /dev/null +++ b/docs/arquitectura.md @@ -0,0 +1,10 @@ +# Arquitectura (Portfolio DevOps) + +Este repositorio se utiliza como portfolio profesional DevOps/Cloud. + +Objetivo del proyecto: +- Flujo local con Docker (reproducible) +- Flujo local con Kubernetes (kind) +- CI/CD con GitHub Actions +- Deploy automático al hacer merge a main hacia AWS (EC2 + k3s, sin EKS) + diff --git a/docs/decisiones.md b/docs/decisiones.md new file mode 100644 index 0000000000..cb8288d849 --- /dev/null +++ b/docs/decisiones.md @@ -0,0 +1,14 @@ +# Decisiones técnicas + +## 0001 - App base: template open-source (código secundario) +Se utiliza una aplicación open-source existente como base. + +**El foco del repositorio es la infraestructura, automatización y despliegue (prácticas DevOps).** + +## 0002 - Kubernetes: kind en local, k3s en AWS EC2 (sin EKS) +Se eligen alternativas livianas para mantener el alcance terminable y ejecutable, evitando complejidad innecesaria. + +## 0003 - CI/CD con GitHub Actions +Se utiliza GitHub Actions para: +- CI en Pull Requests (checks de calidad) +- CD al mergear a main (deploy automático) diff --git a/docs/docstream/README-fastapi-template.md b/docs/docstream/README-fastapi-template.md new file mode 100644 index 0000000000..a9049b4779 --- /dev/null +++ b/docs/docstream/README-fastapi-template.md @@ -0,0 +1,233 @@ +# Full Stack FastAPI Template + +Test Docker Compose +Test Backend +Coverage + +## Technology Stack and Features + +- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) for the Python SQL database interactions (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), used by FastAPI, for the data validation and settings management. + - 💾 [PostgreSQL](https://www.postgresql.org) as the SQL database. +- 🚀 [React](https://react.dev) for the frontend. + - 💃 Using TypeScript, hooks, [Vite](https://vitejs.dev), and other parts of a modern frontend stack. + - 🎨 [Tailwind CSS](https://tailwindcss.com) and [shadcn/ui](https://ui.shadcn.com) for the frontend components. + - 🤖 An automatically generated frontend client. + - 🧪 [Playwright](https://playwright.dev) for End-to-End testing. + - 🦇 Dark mode support. +- 🐋 [Docker Compose](https://www.docker.com) for development and production. +- 🔒 Secure password hashing by default. +- 🔑 JWT (JSON Web Token) authentication. +- 📫 Email based password recovery. +- 📬 [Mailcatcher](https://mailcatcher.me) for local email testing during development. +- ✅ Tests with [Pytest](https://pytest.org). +- 📞 [Traefik](https://traefik.io) as a reverse proxy / load balancer. +- 🚢 Deployment instructions using Docker Compose, including how to set up a frontend Traefik proxy to handle automatic HTTPS certificates. +- 🏭 CI (continuous integration) and CD (continuous deployment) based on GitHub Actions. + +### Dashboard Login + +[![API docs](img/login.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### Dashboard - Admin + +[![API docs](img/dashboard.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### Dashboard - Items + +[![API docs](img/dashboard-items.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### Dashboard - Dark Mode + +[![API docs](img/dashboard-dark.png)](https://github.com/fastapi/full-stack-fastapi-template) + +### Interactive API Documentation + +[![API docs](img/docs.png)](https://github.com/fastapi/full-stack-fastapi-template) + +## How To Use It + +You can **just fork or clone** this repository and use it as is. + +✨ It just works. ✨ + +### How to Use a Private Repository + +If you want to have a private repository, GitHub won't allow you to simply fork it as it doesn't allow changing the visibility of forks. + +But you can do the following: + +- Create a new GitHub repo, for example `my-full-stack`. +- Clone this repository manually, set the name with the name of the project you want to use, for example `my-full-stack`: + +```bash +git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack +``` + +- Enter into the new directory: + +```bash +cd my-full-stack +``` + +- Set the new origin to your new repository, copy it from the GitHub interface, for example: + +```bash +git remote set-url origin git@github.com:octocat/my-full-stack.git +``` + +- Add this repo as another "remote" to allow you to get updates later: + +```bash +git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git +``` + +- Push the code to your new repository: + +```bash +git push -u origin master +``` + +### Update From the Original Template + +After cloning the repository, and after doing changes, you might want to get the latest changes from this original template. + +- Make sure you added the original repository as a remote, you can check it with: + +```bash +git remote -v + +origin git@github.com:octocat/my-full-stack.git (fetch) +origin git@github.com:octocat/my-full-stack.git (push) +upstream git@github.com:fastapi/full-stack-fastapi-template.git (fetch) +upstream git@github.com:fastapi/full-stack-fastapi-template.git (push) +``` + +- Pull the latest changes without merging: + +```bash +git pull --no-commit upstream master +``` + +This will download the latest changes from this template without committing them, that way you can check everything is right before committing. + +- If there are conflicts, solve them in your editor. + +- Once you are done, commit the changes: + +```bash +git merge --continue +``` + +### Configure + +You can then update configs in the `.env` files to customize your configurations. + +Before deploying it, make sure you change at least the values for: + +- `SECRET_KEY` +- `FIRST_SUPERUSER_PASSWORD` +- `POSTGRES_PASSWORD` + +You can (and should) pass these as environment variables from secrets. + +Read the [deployment.md](./deployment.md) docs for more details. + +### Generate Secret Keys + +Some environment variables in the `.env` file have a default value of `changethis`. + +You have to change them with a secret key, to generate secret keys you can run the following command: + +```bash +python -c "import secrets; print(secrets.token_urlsafe(32))" +``` + +Copy the content and use that as password / secret key. And run that again to generate another secure key. + +## How To Use It - Alternative With Copier + +This repository also supports generating a new project using [Copier](https://copier.readthedocs.io). + +It will copy all the files, ask you configuration questions, and update the `.env` files with your answers. + +### Install Copier + +You can install Copier with: + +```bash +pip install copier +``` + +Or better, if you have [`pipx`](https://pipx.pypa.io/), you can run it with: + +```bash +pipx install copier +``` + +**Note**: If you have `pipx`, installing copier is optional, you could run it directly. + +### Generate a Project With Copier + +Decide a name for your new project's directory, you will use it below. For example, `my-awesome-project`. + +Go to the directory that will be the parent of your project, and run the command with your project's name: + +```bash +copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust +``` + +If you have `pipx` and you didn't install `copier`, you can run it directly: + +```bash +pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust +``` + +**Note** the `--trust` option is necessary to be able to execute a [post-creation script](https://github.com/fastapi/full-stack-fastapi-template/blob/master/.copier/update_dotenv.py) that updates your `.env` files. + +### Input Variables + +Copier will ask you for some data, you might want to have at hand before generating the project. + +But don't worry, you can just update any of that in the `.env` files afterwards. + +The input variables, with their default values (some auto generated) are: + +- `project_name`: (default: `"FastAPI Project"`) The name of the project, shown to API users (in .env). +- `stack_name`: (default: `"fastapi-project"`) The name of the stack used for Docker Compose labels and project name (no spaces, no periods) (in .env). +- `secret_key`: (default: `"changethis"`) The secret key for the project, used for security, stored in .env, you can generate one with the method above. +- `first_superuser`: (default: `"admin@example.com"`) The email of the first superuser (in .env). +- `first_superuser_password`: (default: `"changethis"`) The password of the first superuser (in .env). +- `smtp_host`: (default: "") The SMTP server host to send emails, you can set it later in .env. +- `smtp_user`: (default: "") The SMTP server user to send emails, you can set it later in .env. +- `smtp_password`: (default: "") The SMTP server password to send emails, you can set it later in .env. +- `emails_from_email`: (default: `"info@example.com"`) The email account to send emails from, you can set it later in .env. +- `postgres_password`: (default: `"changethis"`) The password for the PostgreSQL database, stored in .env, you can generate one with the method above. +- `sentry_dsn`: (default: "") The DSN for Sentry, if you are using it, you can set it later in .env. + +## Backend Development + +Backend docs: [backend/README.md](./backend/README.md). + +## Frontend Development + +Frontend docs: [frontend/README.md](./frontend/README.md). + +## Deployment + +Deployment docs: [deployment.md](./deployment.md). + +## Development + +General development docs: [development.md](./development.md). + +This includes using Docker Compose, custom local domains, `.env` configurations, etc. + +## Release Notes + +Check the file [release-notes.md](./release-notes.md). + +## License + +The Full Stack FastAPI Template is licensed under the terms of the MIT license. diff --git a/docs/runbooks/aws-k3s.md b/docs/runbooks/aws-k3s.md new file mode 100644 index 0000000000..7eab1cd14e --- /dev/null +++ b/docs/runbooks/aws-k3s.md @@ -0,0 +1,5 @@ +# Runbook — AWS (EC2 + k3s) + +> Pendiente: se completará en Phase 4 (AWS deploy). + +Objetivo: desplegar automáticamente al mergear a main hacia un cluster k3s corriendo en EC2. diff --git a/docs/runbooks/kind.md b/docs/runbooks/kind.md new file mode 100644 index 0000000000..86f455c300 --- /dev/null +++ b/docs/runbooks/kind.md @@ -0,0 +1,5 @@ +# Runbook — Kubernetes local (kind) + +> Pendiente: se completará en Phase 2 (Kubernetes local). + +Objetivo: levantar el stack en un cluster kind y acceder vía Ingress. diff --git a/docs/runbooks/local-docker.md b/docs/runbooks/local-docker.md new file mode 100644 index 0000000000..68acd4d242 --- /dev/null +++ b/docs/runbooks/local-docker.md @@ -0,0 +1,5 @@ +# Runbook — Local (Docker) + +> Pendiente: se completará en Phase 1 (Docker baseline). + +Objetivo: levantar el stack localmente con Docker/Compose de forma reproducible. diff --git a/k8s/portfolio/README.md b/k8s/portfolio/README.md new file mode 100644 index 0000000000..36044ba5cd --- /dev/null +++ b/k8s/portfolio/README.md @@ -0,0 +1,8 @@ +# Manifiestos Kubernetes (portfolio) + +En esta carpeta van a vivir los manifiestos Kubernetes creados como parte del portfolio. + +Principios: +- Separar el “trabajo propio” del contenido upstream del template +- Mantenerlo incremental por fases +- Minimizar complejidad: primero kind (local), luego k3s (AWS) diff --git a/k8s/portfolio/backend/deployment.yaml b/k8s/portfolio/backend/deployment.yaml new file mode 100644 index 0000000000..e490d1ad3f --- /dev/null +++ b/k8s/portfolio/backend/deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend + labels: + app: backend +spec: + replicas: 1 + selector: + matchLabels: + app: backend + template: + metadata: + labels: + app: backend + spec: + containers: + - name: backend + image: devops-portfolio-fastapi-backend:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8000 + env: + - name: PORT + value: "8000" + envFrom: + - configMapRef: + name: backend-config + - secretRef: + name: backend-secret diff --git a/k8s/portfolio/backend/env/configmap.yaml b/k8s/portfolio/backend/env/configmap.yaml new file mode 100644 index 0000000000..70254adaeb --- /dev/null +++ b/k8s/portfolio/backend/env/configmap.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: backend-config +data: + PROJECT_NAME: "DevOps Portfolio FastAPI" + POSTGRES_SERVER: "postgres" + POSTGRES_PORT: "5432" + POSTGRES_DB: "app" + POSTGRES_USER: "postgres" + BACKEND_CORS_ORIGINS: '["http://localhost:5173","http://localhost:18000"]' diff --git a/k8s/portfolio/backend/env/secret.yaml b/k8s/portfolio/backend/env/secret.yaml new file mode 100644 index 0000000000..074bd4664d --- /dev/null +++ b/k8s/portfolio/backend/env/secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: backend-secret +type: Opaque +stringData: + POSTGRES_PASSWORD: "postgres" + FIRST_SUPERUSER: "admin@example.com" + FIRST_SUPERUSER_PASSWORD: "admin123" diff --git a/k8s/portfolio/backend/service.yaml b/k8s/portfolio/backend/service.yaml new file mode 100644 index 0000000000..b54c3595d4 --- /dev/null +++ b/k8s/portfolio/backend/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: backend +spec: + type: NodePort + selector: + app: backend + ports: + - port: 8000 + targetPort: 8000 + nodePort: 30080 diff --git a/k8s/portfolio/postgres/deployment.yaml b/k8s/portfolio/postgres/deployment.yaml new file mode 100644 index 0000000000..1c71439f30 --- /dev/null +++ b/k8s/portfolio/postgres/deployment.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + labels: + app: postgres +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:17 + ports: + - containerPort: 5432 + envFrom: + - secretRef: + name: postgres-secret + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: postgres-pvc diff --git a/k8s/portfolio/postgres/pvc.yaml b/k8s/portfolio/postgres/pvc.yaml new file mode 100644 index 0000000000..23afd37855 --- /dev/null +++ b/k8s/portfolio/postgres/pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/k8s/portfolio/postgres/secret.yaml b/k8s/portfolio/postgres/secret.yaml new file mode 100644 index 0000000000..fd11573938 --- /dev/null +++ b/k8s/portfolio/postgres/secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: postgres-secret +type: Opaque +stringData: + POSTGRES_DB: app + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres diff --git a/k8s/portfolio/postgres/service.yaml b/k8s/portfolio/postgres/service.yaml new file mode 100644 index 0000000000..e78c91e198 --- /dev/null +++ b/k8s/portfolio/postgres/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + type: ClusterIP + selector: + app: postgres + ports: + - port: 5432 + targetPort: 5432 diff --git a/kind-config.yaml b/kind-config.yaml new file mode 100644 index 0000000000..f64b87e8e2 --- /dev/null +++ b/kind-config.yaml @@ -0,0 +1,4 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: + - role: control-plane