hooks
This commit is contained in:
40
CLAUDE.md
Normal file
40
CLAUDE.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Agent Instructions
|
||||||
|
|
||||||
|
## Project Context
|
||||||
|
|
||||||
|
This is the server-stack repository for deploying tessavb.com, jamesvanboxtel.com, and git.jamesvanboxtel.com. It runs on a GCP e2-micro VM (Debian 12) at 35.230.59.34.
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- **Caddy** (lucaslorentz/caddy-docker-proxy) - reverse proxy with auto-SSL via Docker labels
|
||||||
|
- **Gitea** - self-hosted git at git.jamesvanboxtel.com
|
||||||
|
- **Node/Express apps** - each site runs on port 8080 internally
|
||||||
|
- **Docker Compose** - orchestrates everything (use `docker-compose` not `docker compose` on the server, the v2 plugin isn't installed)
|
||||||
|
- **SQLite** - database files go in `apps/<name>/data/`
|
||||||
|
|
||||||
|
## Key Conventions
|
||||||
|
|
||||||
|
- Caddy routing is configured via Docker labels on each service (e.g., `caddy: tessavb.com`, `caddy.reverse_proxy: "{{upstreams 8080}}"`)
|
||||||
|
- The Docker network is named `server-stack_server-network` (docker-compose prefixes the project name)
|
||||||
|
- The `CADDY_INGRESS_NETWORKS` env var must match this exact network name
|
||||||
|
- Data directories (`caddy_data/`, `gitea_data/`, `apps/*/data/`) are gitignored and must never be deleted on the server
|
||||||
|
- Each app has its own Dockerfile, package.json, and server.js in `apps/<name>/`
|
||||||
|
|
||||||
|
## Adding a New Site
|
||||||
|
|
||||||
|
1. Create `apps/<name>/` with Dockerfile, package.json, server.js
|
||||||
|
2. Add a service block to docker-compose.yml with appropriate `caddy` labels
|
||||||
|
3. Add DNS A record pointing the domain to 35.230.59.34
|
||||||
|
4. Push and rebuild: `docker-compose up -d --build`
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
Currently manual: push to Gitea, SSH in, `git pull && docker-compose up -d --build`.
|
||||||
|
Auto-deploy via webhook is planned but not yet configured.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
No test suite yet. Verify changes by:
|
||||||
|
1. Building locally: `docker-compose build <service-name>`
|
||||||
|
2. Checking the site loads after deploying
|
||||||
|
3. Checking logs: `docker logs <container-name>`
|
||||||
87
README.md
Normal file
87
README.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Server Stack
|
||||||
|
|
||||||
|
Production infrastructure for **tessavb.com**, **jamesvanboxtel.com**, and developer services.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
Runs on a GCP `e2-micro` (Debian 12, Always Free Tier) at `35.230.59.34`.
|
||||||
|
|
||||||
|
| Service | Container | Domain | Port |
|
||||||
|
|---------|-----------|--------|------|
|
||||||
|
| Reverse Proxy / SSL | `caddy` | — | 80, 443 |
|
||||||
|
| Git Hosting | `gitea` | git.jamesvanboxtel.com | 3000 (internal) |
|
||||||
|
| Tessa's Site | `tessavb-app` | tessavb.com | 8080 (internal) |
|
||||||
|
| James's Site | `jamesvanboxtel-app` | jamesvanboxtel.com | 8080 (internal) |
|
||||||
|
|
||||||
|
**Caddy** auto-provisions Let's Encrypt SSL certificates and routes traffic to containers via Docker labels. **Gitea** provides private git hosting. Both apps are Node/Express placeholder sites.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
server-stack/
|
||||||
|
docker-compose.yml # All service definitions
|
||||||
|
deploy.sh # Auto-deploy script (git pull + rebuild)
|
||||||
|
hooks.json # Webhook daemon config
|
||||||
|
.gitignore # Excludes data dirs from git
|
||||||
|
apps/
|
||||||
|
tessavb/ # tessavb.com source code
|
||||||
|
Dockerfile
|
||||||
|
server.js
|
||||||
|
package.json
|
||||||
|
data/ # SQLite/persistent data (gitignored)
|
||||||
|
jamesvanboxtel/ # jamesvanboxtel.com source code
|
||||||
|
Dockerfile
|
||||||
|
server.js
|
||||||
|
package.json
|
||||||
|
data/ # SQLite/persistent data (gitignored)
|
||||||
|
caddy_data/ # Caddy SSL certs + config (gitignored)
|
||||||
|
gitea_data/ # Gitea database + repos (gitignored)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual Deploy
|
||||||
|
|
||||||
|
From your Mac:
|
||||||
|
```bash
|
||||||
|
cd /Users/jamesvanboxtel/Programming/websites/server-stack
|
||||||
|
git add -A && git commit -m "description" && git push
|
||||||
|
```
|
||||||
|
|
||||||
|
On the server (SSH):
|
||||||
|
```bash
|
||||||
|
cd ~/server-stack && git pull origin main && docker-compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auto Deploy (Not Yet Configured)
|
||||||
|
|
||||||
|
Once the webhook daemon is set up, pushing to Gitea will automatically trigger `deploy.sh`, which pulls and rebuilds containers. See TASKS.md for setup steps.
|
||||||
|
|
||||||
|
## Useful Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View running containers
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# View logs for a service
|
||||||
|
docker logs caddy
|
||||||
|
docker logs gitea
|
||||||
|
docker logs tessavb-app
|
||||||
|
|
||||||
|
# Restart everything
|
||||||
|
docker-compose down && docker-compose up -d
|
||||||
|
|
||||||
|
# Rebuild a single app after code changes
|
||||||
|
docker-compose up -d --build tessavb-app
|
||||||
|
```
|
||||||
|
|
||||||
|
## DNS Records
|
||||||
|
|
||||||
|
**jamesvanboxtel.com** (Namecheap):
|
||||||
|
- `@` A `35.230.59.34`
|
||||||
|
- `git` A `35.230.59.34`
|
||||||
|
|
||||||
|
**tessavb.com** (Namecheap):
|
||||||
|
- `@` A `35.230.59.34`
|
||||||
|
|
||||||
|
## GCP Firewall
|
||||||
|
|
||||||
|
Ingress rule `allow-http` permits TCP ports 80, 443 from `0.0.0.0/0`.
|
||||||
15
TASKS.md
Normal file
15
TASKS.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Tasks
|
||||||
|
|
||||||
|
## Auto-Deploy Webhook Setup
|
||||||
|
- [ ] Fix `hooks.json` paths (currently hardcoded to `/home/james/`, should be `/home/jamesvanboxtel/`)
|
||||||
|
- [ ] Fix `deploy.sh` to use `docker-compose` instead of `docker compose` (v2 plugin not installed on server)
|
||||||
|
- [ ] Start the webhook daemon on the server: `webhook -hooks ~/server-stack/hooks.json -verbose &`
|
||||||
|
- [ ] Add GCP firewall rule to allow TCP port 9000 ingress
|
||||||
|
- [ ] Create a Gitea webhook on the server-stack repo pointing to `http://35.230.59.34:9000/hooks/redeploy-apps`
|
||||||
|
- [ ] Make the webhook daemon start on boot (systemd service)
|
||||||
|
- [ ] Add a webhook secret so only Gitea can trigger deploys
|
||||||
|
|
||||||
|
## Infrastructure
|
||||||
|
- [ ] Set up `gcloud` CLI on Mac for SSH access without browser console
|
||||||
|
- [ ] Add www subdomain redirects (www.tessavb.com -> tessavb.com, etc.)
|
||||||
|
- [ ] Add backup strategy for gitea_data and app data directories
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd /home/$USER/server-stack
|
cd /home/$USER/server-stack
|
||||||
git pull origin main
|
git pull origin main
|
||||||
docker compose up -d --build
|
docker-compose up -d --build
|
||||||
|
|||||||
14
hooks.json
14
hooks.json
@@ -1,7 +1,17 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "redeploy-apps",
|
"id": "redeploy-apps",
|
||||||
"execute-command": "/home/james/server-stack/deploy.sh",
|
"execute-command": "{{getenv \"HOME\"}}/server-stack/deploy.sh",
|
||||||
"command-working-directory": "/home/james/server-stack"
|
"command-working-directory": "{{getenv \"HOME\"}}/server-stack",
|
||||||
|
"trigger-rule": {
|
||||||
|
"match": {
|
||||||
|
"type": "payload-hmac-sha256",
|
||||||
|
"secret": "{{getenv \"WEBHOOK_SECRET\"}}",
|
||||||
|
"parameter": {
|
||||||
|
"source": "header",
|
||||||
|
"name": "X-Gitea-Signature"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
14
webhook.service
Normal file
14
webhook.service
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Webhook auto-deploy daemon
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=jamesvanboxtel
|
||||||
|
EnvironmentFile=/home/jamesvanboxtel/.webhook-env
|
||||||
|
ExecStart=/usr/bin/webhook -hooks /home/jamesvanboxtel/server-stack/hooks.json -verbose
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Reference in New Issue
Block a user