From a30fe604141ab0137e79355bbd40bd36c0738108 Mon Sep 17 00:00:00 2001 From: Ivan Liashkevich Date: Tue, 10 Feb 2026 01:02:56 +0200 Subject: [PATCH] Add local development environment with switchable backend Set up local dev workflow: SSH tunnel to dev DB, Next.js API proxy via rewrites, Docker or native backend on port 5000. Update and restructure project documentation. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 3 + CLAUDE.md | 58 ++- README.md | 129 +++---- SERVER.md | 333 ++++-------------- backend/src/GBSite.Api/Program.cs | 1 + .../GBSite.Api/Properties/launchSettings.json | 2 +- deploy/docker-compose.local.yml | 9 + frontend/.env.example | 3 + frontend/next.config.ts | 10 + scripts/local-backend-docker.ps1 | 4 + scripts/local-backend-dotnet.ps1 | 6 + scripts/local-frontend.ps1 | 6 + scripts/local-tunnel.ps1 | 4 + 13 files changed, 216 insertions(+), 352 deletions(-) create mode 100644 deploy/docker-compose.local.yml create mode 100644 scripts/local-backend-docker.ps1 create mode 100644 scripts/local-backend-dotnet.ps1 create mode 100644 scripts/local-frontend.ps1 create mode 100644 scripts/local-tunnel.ps1 diff --git a/.gitignore b/.gitignore index b57a966..fbfb1eb 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,9 @@ backend/.idea/ *.swp *.swo +# Local development +backend/src/*/appsettings.Local.json + # OS Thumbs.db .DS_Store diff --git a/CLAUDE.md b/CLAUDE.md index 9c99142..de442c4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,7 +28,13 @@ GBSite/ │ └── Dockerfile # Multi-stage: dotnet sdk → aspnet runtime ├── deploy/ │ ├── docker-compose.prod.yml -│ └── docker-compose.dev.yml +│ ├── docker-compose.dev.yml +│ └── docker-compose.local.yml # Local backend (Docker mode) +├── scripts/ +│ ├── local-tunnel.ps1 # SSH tunnel to dev DB +│ ├── local-backend-docker.ps1 # Start Docker backend +│ ├── local-backend-dotnet.ps1 # Start native backend +│ └── local-frontend.ps1 # Start frontend dev server ├── .woodpecker/ │ └── deploy.yml # CI/CD pipeline └── CLAUDE.md # This file @@ -40,8 +46,9 @@ GBSite/ |-----|-------------|---------|-----| | **Prod** | https://new.goodbrick.com.ua | https://new.goodbrick.com.ua/api/* | prod_db | | **Dev** | https://dev.goodbrick.com.ua | https://dev.goodbrick.com.ua/api/* | dev_db | +| **Local** | http://localhost:3000 | http://localhost:5000/api/* | dev_db (via SSH tunnel) | -## Docker Containers +## Docker Containers (Server) | Container | Internal Port | Host Port | Network | |-----------|--------------|-----------|---------| @@ -58,7 +65,48 @@ Path-based routing — один домен для фронта и API: Backend получает запросы с prefix `/api/` (Caddy использует `handle`, не `handle_path`). -## Development +## Local Development + +### Quick Start (3 терминала) + +**Terminal 1 — SSH Tunnel (всегда нужен):** +```powershell +.\scripts\local-tunnel.ps1 +``` + +**Terminal 2 — Backend (выбрать один):** +```powershell +# Работа с фронтом — бэкенд в Docker: +.\scripts\local-backend-docker.ps1 + +# Работа с бэком — dotnet run с hot-reload: +.\scripts\local-backend-dotnet.ps1 +``` + +**Terminal 3 — Frontend:** +```powershell +.\scripts\local-frontend.ps1 +``` + +### Как это работает + +- **SSH Tunnel:** `localhost:5433` → сервер `31.131.18.254:5432` (dev_db) +- **Backend:** слушает на `localhost:5000`, подключается к БД через туннель +- **Frontend:** `npm run dev` на `:3000`, Next.js rewrites проксируют `/api/*` → `localhost:5000` +- **Переключение режимов:** Ctrl+C в терминале с бэком, запустить другой скрипт. Фронт перезапускать не нужно. + +### Конфигурация + +- `backend/src/GBSite.Api/appsettings.Local.json` — connection string к dev_db (gitignored) +- `frontend/.env.local` — `LOCAL_API_URL` и `INTERNAL_API_URL` для локального проксирования +- `deploy/docker-compose.local.yml` — Docker backend с `host.docker.internal:5433` + +### URLs +- Frontend: http://localhost:3000 +- Backend API: http://localhost:5000/api/health +- DB: localhost:5433 (через SSH tunnel к dev_db) + +## Development (manual) ### Frontend ```bash @@ -91,7 +139,7 @@ cd backend && dotnet build - `src/components/` — React components (create when needed) - shadcn/ui components via `npx shadcn@latest add ` - Server-side calls to backend use `INTERNAL_API_URL` env var -- Client-side calls use relative paths (`/api/...`) — Caddy proxies them +- Client-side calls use relative paths (`/api/...`) — Caddy proxies them on server, Next.js rewrites locally ## Git & CI/CD @@ -118,6 +166,7 @@ Host=postgres;Port=5432;Database={db};Username={user};Password={pass} ``` Configured via env var `ConnectionStrings__Default` in docker-compose files. +Locally via `appsettings.Local.json` with SSH tunnel (`localhost:5433`). ## Key Rules @@ -125,3 +174,4 @@ Configured via env var `ConnectionStrings__Default` in docker-compose files. - Frontend standalone output (`output: "standalone"` in next.config.ts) — required for Docker - Backend listens on port 5000 (`ASPNETCORE_URLS=http://+:5000`) - All containers must be in `app-network` (external Docker network) +- `appsettings.Local.json` is gitignored — local dev overrides only diff --git a/README.md b/README.md index 4a6a48f..8a21169 100644 --- a/README.md +++ b/README.md @@ -1,94 +1,59 @@ # GoodBrick Project -Корпоративная инфраструктура для компании GoodBrick на базе self-hosted сервисов. +Сайт производителя фасадной плитки GoodBrick — каталог продукции, корпоративная информация. -## 🚀 Deployed Services +## Services -| Service | URL | Status | Purpose | -|---------|-----|--------|---------| -| **Gitea** | https://git.goodbrick.com.ua | ✅ Running | Git сервер | -| **Uptime Kuma** | https://status.goodbrick.com.ua | ✅ Running | Мониторинг | -| **Woodpecker CI** | https://ci.goodbrick.com.ua | ✅ Running | CI/CD | -| **Production App** | https://new.goodbrick.com.ua | 🔨 TODO | Продакшн приложение | -| **Development App** | https://dev.goodbrick.com.ua | 🔨 TODO | Dev окружение | +| Service | URL | Purpose | +|---------|-----|---------| +| **Production** | https://new.goodbrick.com.ua | Продакшн приложение | +| **Development** | https://dev.goodbrick.com.ua | Dev окружение | +| **Gitea** | https://git.goodbrick.com.ua | Git сервер | +| **Woodpecker CI** | https://ci.goodbrick.com.ua | CI/CD | +| **Uptime Kuma** | https://status.goodbrick.com.ua | Мониторинг | -## 📚 Documentation +## Stack -- **[SERVER.md](./SERVER.md)** - Полная документация по серверу, сервисам, Docker, базам данных и troubleshooting +- **Frontend:** Next.js 16 + shadcn/ui + Tailwind CSS 4 +- **Backend:** .NET 9 Web API + Npgsql +- **Database:** PostgreSQL 16 +- **Proxy:** Caddy 2 (auto-SSL) +- **CI/CD:** Woodpecker CI -## 🖥️ Server Info +## Local Development + +See [CLAUDE.md](./CLAUDE.md#local-development) for full local dev setup. + +```powershell +# Terminal 1: SSH tunnel to dev database +.\scripts\local-tunnel.ps1 + +# Terminal 2: Backend (choose one) +.\scripts\local-backend-dotnet.ps1 # native, with hot-reload +.\scripts\local-backend-docker.ps1 # Docker container + +# Terminal 3: Frontend +.\scripts\local-frontend.ps1 +``` + +## Documentation + +- **[CLAUDE.md](./CLAUDE.md)** — Project conventions, structure, local dev setup +- **[SERVER.md](./SERVER.md)** — Server infrastructure, services, troubleshooting + +## Git Workflow + +- `main` branch → auto-deploy to production +- `dev` branch → auto-deploy to dev environment +- Commit style: conventional, English + +## Server - **Host:** 31.131.18.254 -- **SSH:** `ssh deploy@31.131.18.254` (key-based auth) -- **OS:** Linux +- **SSH:** `ssh deploy@31.131.18.254` (key-based) - **Docker Network:** `app-network` -## 🗄️ Databases +## Next Steps -PostgreSQL 16 с отдельными базами для каждого сервиса: -- `gitea_db` - Gitea -- `prod_db` - Production app -- `dev_db` - Development app - -Все credentials в `/srv/postgres/CREDENTIALS.txt` на сервере. - -## 🔧 Stack - -- **Reverse Proxy:** Caddy 2 (автоматический SSL) -- **Database:** PostgreSQL 16 -- **Git:** Gitea -- **CI/CD:** Woodpecker CI -- **Monitoring:** Uptime Kuma -- **Container:** Docker + Docker Compose - -## 📝 Quick Commands - -### SSH в сервер -```bash -ssh deploy@31.131.18.254 -``` - -### Просмотр всех контейнеров -```bash -ssh deploy@31.131.18.254 'docker ps' -``` - -### Просмотр логов -```bash -ssh deploy@31.131.18.254 'docker logs --tail 50' -``` - -### Рестарт сервиса -```bash -ssh deploy@31.131.18.254 'cd /srv/ && docker compose restart' -``` - -## 🏗️ Project Structure - -``` -C:\Work\goodbrick\GBSite\ -├── README.md ← Этот файл -├── SERVER.md ← Полная документация сервера -└── [project files] ← Файлы проектов -``` - -## 🔐 Security - -- SSH: Только key-based аутентификация -- PostgreSQL: Изолированные пользователи для каждого приложения -- Docker: Все сервисы в изолированной сети `app-network` -- SSL: Автоматические сертификаты через Let's Encrypt - -## 🎯 Next Steps - -1. Deploy production app на `new.goodbrick.com.ua` -2. Deploy development app на `dev.goodbrick.com.ua` -3. Настроить CI/CD пайплайны в Woodpecker -4. Настроить email для Gitea -5. Настроить автобэкапы баз данных - ---- - -**Документация актуальна на:** 2026-02-09 -**Разработчик:** Ivan -**AI Assistant:** Claude Sonnet 4.5 +- [ ] Настроить email для Gitea +- [ ] Настроить автобэкапы баз данных diff --git a/SERVER.md b/SERVER.md index 6721e96..465b686 100644 --- a/SERVER.md +++ b/SERVER.md @@ -3,7 +3,7 @@ ## SSH Access - **Host:** 31.131.18.254 - **User:** deploy -- **Auth:** SSH key (already configured, no password needed) +- **Auth:** SSH key (no password) - **Command:** `ssh deploy@31.131.18.254` ## Server Structure @@ -12,12 +12,14 @@ ``` /srv/ -├── apps/ # Empty, ready for applications -├── gitea/ # Git server -├── postgres/ # PostgreSQL database -├── proxy/ # Caddy reverse proxy -├── uptime-kuma/ # Status monitoring -└── woodpecker/ # CI/CD server +├── apps/ +│ ├── gb-site/ # Production app (main branch) +│ └── gb-site-dev/ # Development app (dev branch, git worktree) +├── gitea/ # Git server +├── postgres/ # PostgreSQL database +├── proxy/ # Caddy reverse proxy +├── uptime-kuma/ # Status monitoring +└── woodpecker/ # CI/CD server ``` ## Docker Network @@ -27,12 +29,13 @@ ## Live Services -### Production URLs -- **Gitea:** https://git.goodbrick.com.ua -- **Uptime Kuma:** https://status.goodbrick.com.ua -- **Woodpecker CI:** https://ci.goodbrick.com.ua ✅ Working! -- **Production App:** https://new.goodbrick.com.ua (TODO) -- **Development App:** https://dev.goodbrick.com.ua (TODO) +| Service | URL | +|---------|-----| +| **Production App** | https://new.goodbrick.com.ua | +| **Development App** | https://dev.goodbrick.com.ua | +| **Gitea** | https://git.goodbrick.com.ua | +| **Woodpecker CI** | https://ci.goodbrick.com.ua | +| **Uptime Kuma** | https://status.goodbrick.com.ua | All domains point to `31.131.18.254` via A records. @@ -49,6 +52,7 @@ All domains point to `31.131.18.254` via A records. - **SSL:** Automatic via Let's Encrypt #### Caddyfile Routes + ```caddyfile git.goodbrick.com.ua { reverse_proxy gitea:3000 @@ -65,17 +69,25 @@ ci.goodbrick.com.ua { } new.goodbrick.com.ua { - reverse_proxy new:3000 + handle /api/* { + reverse_proxy gb-prod-backend:5000 + } + handle { + reverse_proxy gb-prod-frontend:3000 + } } dev.goodbrick.com.ua { - reverse_proxy dev:3000 + handle /api/* { + reverse_proxy gb-dev-backend:5000 + } + handle { + reverse_proxy gb-dev-frontend:3000 + } } ``` -**Important Notes:** -- Use container names (not `127.0.0.1` or `localhost`) -- `flush_interval -1` required for Woodpecker's Server-Sent Events +**Important:** `handle` (not `handle_path`) preserves the `/api/` prefix in the request. **Restart:** ```bash @@ -88,7 +100,7 @@ ssh deploy@31.131.18.254 'cd /srv/proxy && docker compose restart' - **Location:** `/srv/postgres` - **Container:** `postgres` - **Image:** `postgres:16` -- **Port:** 127.0.0.1:5432 (localhost only) +- **Port:** 127.0.0.1:5432 (localhost only, not exposed to internet) - **Data:** `/srv/postgres/data` - **Credentials:** `/srv/postgres/CREDENTIALS.txt` (chmod 600) @@ -102,34 +114,13 @@ Database: app #### Application Databases -**Gitea:** -``` -User: gitea_user -Password: gitea_pass_zYWT5JWu3iAbbW7m -Database: gitea_db -Connection String: postgres://gitea_user:gitea_pass_zYWT5JWu3iAbbW7m@postgres:5432/gitea_db -``` +| App | User | Password | Database | +|-----|------|----------|----------| +| Gitea | gitea_user | gitea_pass_zYWT5JWu3iAbbW7m | gitea_db | +| Production | prod_user | prod_pass_kL9mN2pQ7xR8sT4v | prod_db | +| Development | dev_user | dev_pass_vB6nM3qP8yW2rT9k | dev_db | -**Production App:** -``` -User: prod_user -Password: prod_pass_kL9mN2pQ7xR8sT4v -Database: prod_db -Connection String: postgres://prod_user:prod_pass_kL9mN2pQ7xR8sT4v@postgres:5432/prod_db -``` - -**Development App:** -``` -User: dev_user -Password: dev_pass_vB6nM3qP8yW2rT9k -Database: dev_db -Connection String: postgres://dev_user:dev_pass_vB6nM3qP8yW2rT9k@postgres:5432/dev_db -``` - -**Important:** -- Each app has its own isolated database and user -- Users cannot access other databases -- PostgreSQL only accessible via Docker network +Each app has isolated DB and user. Users cannot access other databases. **Restart:** ```bash @@ -143,34 +134,13 @@ ssh deploy@31.131.18.254 'cd /srv/postgres && docker compose restart' - **Container:** `gitea` - **Image:** `gitea/gitea:latest` - **URL:** https://git.goodbrick.com.ua -- **Admin:** admin (set during installation) -- **Ports:** - - 127.0.0.1:3002:3000 (HTTP) - - 127.0.0.1:2222:22 (SSH) -- **Database:** gitea_db (PostgreSQL) -- **Data:** `/srv/gitea/data` +- **Ports:** 127.0.0.1:3002:3000 (HTTP), 127.0.0.1:2222:22 (SSH) +- **Database:** gitea_db #### OAuth Application for Woodpecker - **Client ID:** 157422cf-7391-4fb0-8f2d-27083676dda6 - **Redirect URI:** https://ci.goodbrick.com.ua/authorize -**Config:** -```yaml -environment: - - GITEA__server__DOMAIN=git.goodbrick.com.ua - - GITEA__server__ROOT_URL=https://git.goodbrick.com.ua/ - - GITEA__webhook__ALLOWED_HOST_LIST=* # Allows webhooks to Woodpecker - - GITEA__database__DB_TYPE=postgres - - GITEA__database__HOST=postgres:5432 - - GITEA__database__NAME=gitea_db - - GITEA__database__USER=gitea_user -``` - -**Restart:** -```bash -ssh deploy@31.131.18.254 'cd /srv/gitea && docker compose restart' -``` - --- ### 4. Uptime Kuma (Monitoring) @@ -179,244 +149,77 @@ ssh deploy@31.131.18.254 'cd /srv/gitea && docker compose restart' - **Image:** `louislam/uptime-kuma:2` - **URL:** https://status.goodbrick.com.ua - **Port:** 127.0.0.1:3001:3001 -- **Data:** `/srv/uptime-kuma/data` - -**Restart:** -```bash -ssh deploy@31.131.18.254 'cd /srv/uptime-kuma && docker compose restart' -``` --- -### 5. Woodpecker CI ✅ +### 5. Woodpecker CI - **Location:** `/srv/woodpecker` - **Containers:** `woodpecker-server`, `woodpecker-agent` -- **Image:** `woodpeckerci/woodpecker-server:latest` (v2.8.3), `woodpeckerci/woodpecker-agent:latest` +- **Image:** `woodpeckerci/woodpecker-server:latest` (v2.8.3+) - **URL:** https://ci.goodbrick.com.ua - **Port:** 127.0.0.1:8000:8000 -- **Data:** `/srv/woodpecker/data` -**Config:** -```yaml -environment: - # Server - - WOODPECKER_OPEN=true - - WOODPECKER_HOST=https://ci.goodbrick.com.ua - - WOODPECKER_GITEA=true - - WOODPECKER_GITEA_URL=https://git.goodbrick.com.ua - - WOODPECKER_GITEA_CLIENT=157422cf-7391-4fb0-8f2d-27083676dda6 - - WOODPECKER_GITEA_SECRET=gto_2r3udrnmvtebt37v35bzl375eq5bumxqu2dpwwdfflbumnp5fy7q - - WOODPECKER_AGENT_SECRET=supersecrettoken123 - - WOODPECKER_ADMIN=admin - - # Agent - - WOODPECKER_SERVER=woodpecker-server:9000 - - WOODPECKER_AGENT_SECRET=supersecrettoken123 -``` - -**Status:** ✅ Working! Login with Gitea account. - -**Important Notes:** -- Uses OAuth authentication via Gitea +**Notes:** +- OAuth authentication via Gitea - Agent connects to server on port 9000 (gRPC) -- Agent has access to Docker socket for running builds -- Version 2.8.3 fixes JavaScript security issues (v2.7.2 had SES errors) - -**Restart:** -```bash -ssh deploy@31.131.18.254 'cd /srv/woodpecker && docker compose restart' -``` +- Agent has Docker socket access for builds +- v2.8.3+ required (older versions have SES JS errors) --- ## Common Commands -### View all containers ```bash +# View all containers ssh deploy@31.131.18.254 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"' -``` -### View container logs -```bash +# View container logs ssh deploy@31.131.18.254 'docker logs --tail 50' -ssh deploy@31.131.18.254 'docker logs -f' # Follow logs -``` +ssh deploy@31.131.18.254 'docker logs -f' -### Restart a service -```bash +# Restart a service ssh deploy@31.131.18.254 'cd /srv/ && docker compose restart' -``` -### Restart all services -```bash -ssh deploy@31.131.18.254 'cd /srv/postgres && docker compose restart && \ - cd /srv/gitea && docker compose restart && \ - cd /srv/uptime-kuma && docker compose restart && \ - cd /srv/woodpecker && docker compose restart && \ - cd /srv/proxy && docker compose restart' -``` - -### Access PostgreSQL CLI -```bash +# Access PostgreSQL CLI ssh deploy@31.131.18.254 'docker exec -it postgres psql -U app -d app' -``` -### Check Docker network -```bash +# Check Docker network ssh deploy@31.131.18.254 'docker network inspect app-network' -ssh deploy@31.131.18.254 'docker ps --format "{{.Names}}\t{{.Networks}}"' -``` - -### Test container connectivity -```bash -ssh deploy@31.131.18.254 'docker exec ping -c 2 ' ``` --- ## Troubleshooting -### Issue: Container can't reach another container +### Container can't reach another container **Symptoms:** "connection refused", "no such host" - -**Check:** ```bash -# Verify all containers are in app-network +# Check all containers are in app-network ssh deploy@31.131.18.254 'docker ps --format "{{.Names}}\t{{.Networks}}"' +# Fix: ensure docker-compose has networks: app-network: external: true ``` -**Solution:** -1. Ensure all docker-compose.yml files have: -```yaml -networks: - app-network: - external: true -``` -2. Restart the affected service +### Caddy "502 Bad Gateway" +1. Target service is down → `docker ps | grep ` +2. Not in app-network → check networks +3. Wrong port/name in Caddyfile → check config ---- - -### Issue: "dial tcp: lookup on 127.0.0.11:53: no such host" -**Cause:** Container not in app-network - -**Solution:** -```bash -ssh deploy@31.131.18.254 'cd /srv/ && docker compose down && docker compose up -d' -``` - ---- - -### Issue: Caddy shows "502 Bad Gateway" -**Causes:** -1. Target service is down -2. Target service not in app-network -3. Wrong port/container name in Caddyfile - -**Check:** -```bash -# Check if target is running -ssh deploy@31.131.18.254 'docker ps | grep ' - -# Check Caddy logs -ssh deploy@31.131.18.254 'docker logs caddy --tail 50' - -# Test direct connection -ssh deploy@31.131.18.254 'docker exec caddy wget -O- http://:' -``` - ---- - -### Issue: Woodpecker shows blank page or JavaScript errors -**Symptoms:** "SES Removing unpermitted intrinsics", SyntaxError - -**Solution:** -1. Update to latest version (2.8.3+) -2. Ensure Caddy has `flush_interval -1` for SSE support +### Woodpecker blank page / JS errors +1. Update to v2.8.3+ +2. Ensure `flush_interval -1` in Caddy 3. Clear browser cache (Ctrl+Shift+R) ---- - -### Issue: SSL certificate not working -**Cause:** Usually DNS propagation or Let's Encrypt rate limits - -**Check:** -```bash -# Check Caddy logs -ssh deploy@31.131.18.254 'docker logs caddy | grep -i certificate' - -# Check if domain resolves -nslookup -``` - -**Solution:** Wait for DNS propagation (up to 24h) or check DNS A records. +### SSL certificate issues +Usually DNS propagation delay. Check `docker logs caddy | grep certificate` and `nslookup `. --- -## Security Notes +## TODO -1. **PostgreSQL:** - - Not exposed to internet (127.0.0.1 only) - - Separate users for each application - - Credentials stored in `/srv/postgres/CREDENTIALS.txt` (chmod 600) - -2. **SSH:** - - Key-based authentication only - - User `deploy` has Docker permissions - -3. **Docker Network:** - - All containers isolated in `app-network` - - No direct internet access except through Caddy - -4. **Secrets:** - - Never commit credentials to git - - Store sensitive data in environment variables - - Use `.env` files (gitignored) +- [ ] Настроить email для Gitea +- [ ] Настроить автобэкапы PostgreSQL +- [ ] Настроить алерты в Uptime Kuma --- -## Next Steps / TODO - -- [ ] Deploy production app to `new.goodbrick.com.ua` (port 3100) -- [ ] Deploy development app to `dev.goodbrick.com.ua` (port 3200) -- [ ] Set up email for Gitea (optional) -- [ ] Configure Woodpecker pipelines for repositories -- [ ] Set up automatic backups for PostgreSQL databases -- [ ] Configure monitoring alerts in Uptime Kuma - ---- - -## File Locations Summary - -``` -Server (31.131.18.254): -├── /srv/ -│ ├── apps/ -│ ├── gitea/ -│ │ ├── docker-compose.yml -│ │ └── data/ -│ ├── postgres/ -│ │ ├── docker-compose.yml -│ │ ├── data/ -│ │ └── CREDENTIALS.txt ← All DB credentials -│ ├── proxy/ -│ │ ├── docker-compose.yml -│ │ ├── Caddyfile ← All routes -│ │ ├── data/ -│ │ └── config/ -│ ├── uptime-kuma/ -│ │ ├── docker-compose.yml -│ │ └── data/ -│ └── woodpecker/ -│ ├── docker-compose.yml -│ └── data/ - -Local: -└── C:\Work\goodbrick\GBSite\ - ├── SERVER.md ← This file - └── README.md ← Project overview -``` - ---- - -**Last Updated:** 2026-02-09 -**Maintained by:** Claude AI Assistant +**Last Updated:** 2026-02-10 diff --git a/backend/src/GBSite.Api/Program.cs b/backend/src/GBSite.Api/Program.cs index c381f9b..31ce2d3 100644 --- a/backend/src/GBSite.Api/Program.cs +++ b/backend/src/GBSite.Api/Program.cs @@ -1,4 +1,5 @@ var builder = WebApplication.CreateBuilder(args); +builder.Configuration.AddJsonFile("appsettings.Local.json", optional: true, reloadOnChange: true); builder.Services.AddControllers(); builder.Services.AddOpenApi(); diff --git a/backend/src/GBSite.Api/Properties/launchSettings.json b/backend/src/GBSite.Api/Properties/launchSettings.json index 0126323..596fb6c 100644 --- a/backend/src/GBSite.Api/Properties/launchSettings.json +++ b/backend/src/GBSite.Api/Properties/launchSettings.json @@ -5,7 +5,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, - "applicationUrl": "http://localhost:5224", + "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/deploy/docker-compose.local.yml b/deploy/docker-compose.local.yml new file mode 100644 index 0000000..5e46709 --- /dev/null +++ b/deploy/docker-compose.local.yml @@ -0,0 +1,9 @@ +services: + gb-local-backend: + build: ../backend + container_name: gb-local-backend + ports: + - "127.0.0.1:5000:5000" + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ConnectionStrings__Default=Host=host.docker.internal;Port=5433;Database=dev_db;Username=dev_user;Password=dev_pass_vB6nM3qP8yW2rT9k diff --git a/frontend/.env.example b/frontend/.env.example index 6b1a72f..16d99ca 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,2 +1,5 @@ # URL бэкенда для server-side запросов (внутри Docker network) INTERNAL_API_URL=http://gb-prod-backend:5000 + +# URL бэкенда для проксирования /api/* в локальной разработке (не задавать на сервере!) +# LOCAL_API_URL=http://localhost:5000 diff --git a/frontend/next.config.ts b/frontend/next.config.ts index 68a6c64..a38131f 100644 --- a/frontend/next.config.ts +++ b/frontend/next.config.ts @@ -2,6 +2,16 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: "standalone", + async rewrites() { + const apiUrl = process.env.LOCAL_API_URL; + if (!apiUrl) return []; + return [ + { + source: "/api/:path*", + destination: `${apiUrl}/api/:path*`, + }, + ]; + }, }; export default nextConfig; diff --git a/scripts/local-backend-docker.ps1 b/scripts/local-backend-docker.ps1 new file mode 100644 index 0000000..7bcbabe --- /dev/null +++ b/scripts/local-backend-docker.ps1 @@ -0,0 +1,4 @@ +Write-Host "Starting Docker backend on http://localhost:5000" -ForegroundColor Cyan +Write-Host "Requires: SSH tunnel running (scripts/local-tunnel.ps1)" +Write-Host "" +docker compose -f "$PSScriptRoot\..\deploy\docker-compose.local.yml" up --build diff --git a/scripts/local-backend-dotnet.ps1 b/scripts/local-backend-dotnet.ps1 new file mode 100644 index 0000000..da6ef67 --- /dev/null +++ b/scripts/local-backend-dotnet.ps1 @@ -0,0 +1,6 @@ +Write-Host "Starting backend (dotnet run) on http://localhost:5000" -ForegroundColor Cyan +Write-Host "Requires: SSH tunnel running (scripts/local-tunnel.ps1)" +Write-Host "" +Push-Location "$PSScriptRoot\..\backend" +dotnet run --project src/GBSite.Api +Pop-Location diff --git a/scripts/local-frontend.ps1 b/scripts/local-frontend.ps1 new file mode 100644 index 0000000..58061f8 --- /dev/null +++ b/scripts/local-frontend.ps1 @@ -0,0 +1,6 @@ +Write-Host "Starting frontend on http://localhost:3000" -ForegroundColor Cyan +Write-Host "API proxy -> http://localhost:5000" +Write-Host "" +Push-Location "$PSScriptRoot\..\frontend" +npm run dev +Pop-Location diff --git a/scripts/local-tunnel.ps1 b/scripts/local-tunnel.ps1 new file mode 100644 index 0000000..f4b8548 --- /dev/null +++ b/scripts/local-tunnel.ps1 @@ -0,0 +1,4 @@ +Write-Host "SSH Tunnel: localhost:5433 -> server:5432 (dev_db)" -ForegroundColor Cyan +Write-Host "Press Ctrl+C to stop" +Write-Host "" +ssh -N -L 5433:127.0.0.1:5432 -o ServerAliveInterval=60 deploy@31.131.18.254