Add local development environment with switchable backend
All checks were successful
ci/woodpecker/push/deploy Pipeline was successful

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 <noreply@anthropic.com>
This commit is contained in:
2026-02-10 01:02:56 +02:00
parent 2dadc5362d
commit a30fe60414
13 changed files with 216 additions and 352 deletions

333
SERVER.md
View File

@@ -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 <container_name> --tail 50'
ssh deploy@31.131.18.254 'docker logs <container_name> -f' # Follow logs
```
ssh deploy@31.131.18.254 'docker logs <container_name> -f'
### Restart a service
```bash
# Restart a service
ssh deploy@31.131.18.254 'cd /srv/<service> && 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 <container1> ping -c 2 <container2>'
```
---
## 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 <service>`
2. Not in app-network → check networks
3. Wrong port/name in Caddyfile → check config
---
### Issue: "dial tcp: lookup <service> 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/<service> && 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 <service>'
# 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://<container>:<port>'
```
---
### 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 <domain>
```
**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 <domain>`.
---
## 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