# 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 ```caddyfile 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.1` or `localhost`) - `flush_interval -1` required for Woodpecker's Server-Sent Events **Restart:** ```bash 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:** ```bash 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:** ```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) - **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:** ```bash 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:** ```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 - 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' ``` --- ## Common Commands ### View all containers ```bash ssh deploy@31.131.18.254 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"' ``` ### View container logs ```bash ssh deploy@31.131.18.254 'docker logs --tail 50' ssh deploy@31.131.18.254 'docker logs -f' # Follow logs ``` ### Restart a service ```bash 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 ssh deploy@31.131.18.254 'docker exec -it postgres psql -U app -d app' ``` ### Check Docker network ```bash 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 **Symptoms:** "connection refused", "no such host" **Check:** ```bash # Verify all containers are in app-network ssh deploy@31.131.18.254 'docker ps --format "{{.Names}}\t{{.Networks}}"' ``` **Solution:** 1. Ensure all docker-compose.yml files have: ```yaml networks: app-network: external: true ``` 2. Restart the affected service --- ### 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 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. --- ## Security Notes 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) --- ## 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