- Frontend: Next.js 16 + shadcn/ui + Tailwind CSS 4 - Backend: .NET 9 Web API with Npgsql health check - Docker Compose for prod and dev environments - Woodpecker CI pipeline for auto-deploy - Health check endpoints for E2E testing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 KiB
10 KiB
GoodBrick Server Infrastructure
SSH Access
- Host: 31.131.18.254
- User: deploy
- Auth: SSH key (already configured, no password needed)
- Command:
ssh deploy@31.131.18.254
Server Structure
Base Directory: /srv
/srv/
├── apps/ # Empty, ready for applications
├── gitea/ # Git server
├── postgres/ # PostgreSQL database
├── proxy/ # Caddy reverse proxy
├── uptime-kuma/ # Status monitoring
└── woodpecker/ # CI/CD server
Docker Network
- Network name:
app-network(external, shared) - All services connected to this network
- Containers communicate by name (e.g.,
postgres,gitea,caddy)
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)
All domains point to 31.131.18.254 via A records.
Service Details
1. Caddy (Reverse Proxy)
- Location:
/srv/proxy - Container:
caddy - Image:
caddy:2 - Ports: 80, 443 (public)
- Config:
/srv/proxy/Caddyfile - SSL: Automatic via Let's Encrypt
Caddyfile Routes
git.goodbrick.com.ua {
reverse_proxy gitea:3000
}
status.goodbrick.com.ua {
reverse_proxy uptime-kuma:3001
}
ci.goodbrick.com.ua {
reverse_proxy woodpecker-server:8000 {
flush_interval -1 # For SSE support
}
}
new.goodbrick.com.ua {
reverse_proxy new:3000
}
dev.goodbrick.com.ua {
reverse_proxy dev:3000
}
Important Notes:
- Use container names (not
127.0.0.1orlocalhost) flush_interval -1required for Woodpecker's Server-Sent Events
Restart:
ssh deploy@31.131.18.254 'cd /srv/proxy && docker compose restart'
2. PostgreSQL
- Location:
/srv/postgres - Container:
postgres - Image:
postgres:16 - Port: 127.0.0.1:5432 (localhost only)
- Data:
/srv/postgres/data - Credentials:
/srv/postgres/CREDENTIALS.txt(chmod 600)
Master Admin
Host: postgres:5432 (from containers) or 127.0.0.1:5432 (from host)
User: app
Password: zYWT5JWu3iAbbW7mOyd1
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
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
Restart:
ssh deploy@31.131.18.254 'cd /srv/postgres && docker compose restart'
3. Gitea (Git Server)
- Location:
/srv/gitea - 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
OAuth Application for Woodpecker
- Client ID: 157422cf-7391-4fb0-8f2d-27083676dda6
- Redirect URI: https://ci.goodbrick.com.ua/authorize
Config:
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:
ssh deploy@31.131.18.254 'cd /srv/gitea && docker compose restart'
4. Uptime Kuma (Monitoring)
- Location:
/srv/uptime-kuma - Container:
uptime-kuma - Image:
louislam/uptime-kuma:2 - URL: https://status.goodbrick.com.ua
- Port: 127.0.0.1:3001:3001
- Data:
/srv/uptime-kuma/data
Restart:
ssh deploy@31.131.18.254 'cd /srv/uptime-kuma && docker compose restart'
5. Woodpecker CI ✅
- Location:
/srv/woodpecker - Containers:
woodpecker-server,woodpecker-agent - Image:
woodpeckerci/woodpecker-server:latest(v2.8.3),woodpeckerci/woodpecker-agent:latest - URL: https://ci.goodbrick.com.ua
- Port: 127.0.0.1:8000:8000
- Data:
/srv/woodpecker/data
Config:
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
- 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:
ssh deploy@31.131.18.254 'cd /srv/woodpecker && docker compose restart'
Common Commands
View all containers
ssh deploy@31.131.18.254 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'
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
Restart a service
ssh deploy@31.131.18.254 'cd /srv/<service> && docker compose restart'
Restart all services
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
ssh deploy@31.131.18.254 'docker exec -it postgres psql -U app -d app'
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
ssh deploy@31.131.18.254 'docker exec <container1> ping -c 2 <container2>'
Troubleshooting
Issue: Container can't reach another container
Symptoms: "connection refused", "no such host"
Check:
# Verify all containers are in app-network
ssh deploy@31.131.18.254 'docker ps --format "{{.Names}}\t{{.Networks}}"'
Solution:
- Ensure all docker-compose.yml files have:
networks:
app-network:
external: true
- Restart the affected service
Issue: "dial tcp: lookup on 127.0.0.11:53: no such host"
Cause: Container not in app-network
Solution:
ssh deploy@31.131.18.254 'cd /srv/<service> && docker compose down && docker compose up -d'
Issue: Caddy shows "502 Bad Gateway"
Causes:
- Target service is down
- Target service not in app-network
- Wrong port/container name in Caddyfile
Check:
# 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:
- Update to latest version (2.8.3+)
- Ensure Caddy has
flush_interval -1for SSE support - Clear browser cache (Ctrl+Shift+R)
Issue: SSL certificate not working
Cause: Usually DNS propagation or Let's Encrypt rate limits
Check:
# 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.
Security Notes
-
PostgreSQL:
- Not exposed to internet (127.0.0.1 only)
- Separate users for each application
- Credentials stored in
/srv/postgres/CREDENTIALS.txt(chmod 600)
-
SSH:
- Key-based authentication only
- User
deployhas Docker permissions
-
Docker Network:
- All containers isolated in
app-network - No direct internet access except through Caddy
- All containers isolated in
-
Secrets:
- Never commit credentials to git
- Store sensitive data in environment variables
- Use
.envfiles (gitignored)
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