gadget/site/README.md
2026-05-14 03:05:24 -04:00

208 lines
5.1 KiB
Markdown

# Gadget Code Landing Site
Static React/Vite landing page for Gadget Code, served at [https://g4dge7.com](https://g4dge7.com).
---
## Production Environment
### Host Configuration
| Setting | Value |
|---------|-------|
| **Provider** | DigitalOcean Droplet |
| **Hostname** | `gadget-site` |
| **Domain** | `g4dge7.com` |
| **Git Subdomain** | `git.g4dge7.com` |
| **OS** | Ubuntu 24.04.3 LTS |
| **Web Server** | Nginx 1.24.0 |
| **SSL** | Let's Encrypt (Certbot) |
### Service Architecture
```
g4dge7.com → Nginx → /var/www/g4dge7.com (static site)
git.g4dge7.com → Nginx → Gitea (port 3000)
```
### Directory Structure
| Path | Purpose |
|------|---------|
| `/var/www/g4dge7.com` | Production static site files |
| `/var/www/certbot` | Let's Encrypt ACME challenge files |
| `/etc/nginx/sites-available/g4dge7.com` | Nginx config for main site |
| `/etc/nginx/sites-available/git.g4dge7.com` | Nginx config for Gitea |
| `/etc/letsencrypt/live/g4dge7.com/` | SSL certificates for main domain |
| `/etc/letsencrypt/live/git.g4dge7.com/` | SSL certificates for git subdomain |
### Nginx Configuration Summary
**g4dge7.com** (`/etc/nginx/sites-available/g4dge7.com`):
- Listens on ports 80 and 443
- HTTP redirects to HTTPS (301)
- Serves static files from `/var/www/g4dge7.com`
- SPA fallback: all routes serve `index.html`
- Gzip compression enabled
- Security headers: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy
- Static assets cached for 1 year
**git.g4dge7.com** (`/etc/nginx/sites-available/git.g4dge7.com`):
- Listens on ports 80 and 443
- HTTP redirects to HTTPS (301)
- Proxies to Gitea at `http://127.0.0.1:3000`
- WebSocket support enabled for real-time features
---
## Development
### Prerequisites
- Node.js 18+
- pnpm (recommended) or npm
### Setup
```bash
cd site
pnpm install
```
### Commands
```bash
pnpm dev # Start Vite dev server
pnpm build # Type check and build for production
pnpm preview # Preview production build locally
pnpm typecheck # Run TypeScript type checking only
```
### Build Output
Production builds are output to `site/dist/`:
- `index.html` - Entry point
- `assets/` - Bundled JS, CSS, and other assets
- `*.png` - Static images (favicon, icons, etc.)
---
## Deployment to Production
### Full Deployment Process
```bash
# 1. Build the site
cd /home/rob/workspaces/core-001/gadget/site
pnpm build
# 2. Sync to production server
rsync -avz --delete dist/ g4dge7.com:/var/www/g4dge7.com/
# 3. Set correct ownership (if needed)
ssh g4dge7.com "chown -R www-data:www-data /var/www/g4dge7.com"
# 4. Reload Nginx (usually not needed, but safe to run)
ssh g4dge7.com "nginx -t && systemctl reload nginx"
```
### Quick Deploy (One-Liner)
```bash
pnpm build && rsync -avz --delete dist/ g4dge7.com:/var/www/g4dge7.com/ && ssh g4dge7.com "chown -R www-data:www-data /var/www/g4dge7.com"
```
### Deployment Checklist
- [ ] Build completes without errors
- [ ] rsync completes without errors
- [ ] Site loads at https://g4dge7.com
- [ ] No console errors in browser dev tools
- [ ] Git server still accessible at https://git.g4dge7.com
---
## SSL Certificate Management
### Renewal
Certbot is configured for automatic renewal via systemd timer. Manual renewal:
```bash
ssh g4dge7.com "certbot renew --dry-run" # Test renewal
ssh g4dge7.com "certbot renew" # Actual renewal
```
### Certificate Locations
| Domain | Certificate | Private Key |
|--------|-------------|-------------|
| g4dge7.com | `/etc/letsencrypt/live/g4dge7.com/fullchain.pem` | `/etc/letsencrypt/live/g4dge7.com/privkey.pem` |
| git.g4dge7.com | `/etc/letsencrypt/live/git.g4dge7.com/fullchain.pem` | `/etc/letsencrypt/live/git.g4dge7.com/privkey.pem` |
---
## Troubleshooting
### Site not loading
```bash
# Check Nginx status
ssh g4dge7.com "systemctl status nginx"
# Check Nginx config
ssh g4dge7.com "nginx -t"
# Check if files exist
ssh g4dge7.com "ls -la /var/www/g4dge7.com/"
# Check Nginx error logs
ssh g4dge7.com "tail -50 /var/log/nginx/error.log"
```
### SSL certificate issues
```bash
# Check certificate expiry
ssh g4dge7.com "certbot certificates"
# Force renewal
ssh g4dge7.com "certbot renew --force-renewal"
```
### Gitea not accessible
```bash
# Check Gitea status
ssh g4dge7.com "systemctl status gitea"
# Check if port 3000 is listening
ssh g4dge7.com "ss -tlnp | grep 3000"
# Check Gitea logs
ssh g4dge7.com "journalctl -u gitea --no-pager -n 50"
```
### SSH access issues
Use the direct IP for SSH (Cloudflare doesn't proxy SSH):
```bash
ssh root@157.230.50.250
```
---
## Security Notes
- **IP-only Git access**: Git SSH access requires the droplet IP (`157.230.50.250`), not the domain. This is intentional—Cloudflare doesn't proxy SSH, and this limits access to trusted parties.
- **No shell access for git user**: The `git` system user can only execute Gitea commands via authorized_keys restrictions.
- **Security headers**: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, and Referrer-Policy are all configured.
- **HTTPS only**: Both domains redirect HTTP to HTTPS automatically.
---
## Contact
For issues or questions about this deployment, contact the system administrator.