feat: harden gateway with policy engine, secure tools, and governance docs
This commit is contained in:
@@ -1,126 +1,46 @@
|
||||
# Deployment
|
||||
|
||||
## Local / Development
|
||||
## Secure Defaults
|
||||
|
||||
- Default bind: `MCP_HOST=127.0.0.1`.
|
||||
- Binding `0.0.0.0` requires explicit `ALLOW_INSECURE_BIND=true`.
|
||||
- Write mode disabled by default.
|
||||
- Policy file path configurable via `POLICY_FILE_PATH`.
|
||||
|
||||
## Local Development
|
||||
|
||||
```bash
|
||||
make install-dev
|
||||
source venv/bin/activate # Linux/macOS
|
||||
# venv\Scripts\activate # Windows
|
||||
|
||||
cp .env.example .env
|
||||
# Edit .env
|
||||
make generate-key # Add key to .env
|
||||
make generate-key
|
||||
make run
|
||||
```
|
||||
|
||||
The server listens on `http://0.0.0.0:8080` by default.
|
||||
|
||||
---
|
||||
|
||||
## Docker
|
||||
|
||||
### Build
|
||||
- Use `docker/Dockerfile` (non-root runtime).
|
||||
- Use compose profiles:
|
||||
- `prod`: hardened runtime profile.
|
||||
- `dev`: local development profile (localhost-only port bind).
|
||||
|
||||
Run examples:
|
||||
|
||||
```bash
|
||||
make docker-build
|
||||
# or: docker build -f docker/Dockerfile -t aegis-gitea-mcp .
|
||||
docker compose --profile prod up -d
|
||||
docker compose --profile dev up -d
|
||||
```
|
||||
|
||||
### Configure
|
||||
## Environment Validation
|
||||
|
||||
Create a `.env` file (copy from `.env.example`) with your settings before starting the container.
|
||||
Startup validates:
|
||||
- Required Gitea settings.
|
||||
- API keys (when auth enabled).
|
||||
- Insecure bind opt-in.
|
||||
- Write whitelist when write mode enabled.
|
||||
|
||||
### Run
|
||||
## Production Recommendations
|
||||
|
||||
```bash
|
||||
make docker-up
|
||||
# or: docker-compose up -d
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
make docker-logs
|
||||
# or: docker-compose logs -f
|
||||
```
|
||||
|
||||
### Stop
|
||||
|
||||
```bash
|
||||
make docker-down
|
||||
# or: docker-compose down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## docker-compose.yml Overview
|
||||
|
||||
The included `docker-compose.yml` provides:
|
||||
|
||||
- **Health check:** polls `GET /health` every 30 seconds
|
||||
- **Audit log volume:** mounts a named volume at `/var/log/aegis-mcp` so logs survive container restarts
|
||||
- **Resource limits:** 1 CPU, 512 MB memory
|
||||
- **Security:** non-root user, `no-new-privileges`
|
||||
- **Traefik labels:** commented out — uncomment and set `MCP_DOMAIN` to enable automatic HTTPS via Traefik
|
||||
|
||||
### Enabling Traefik
|
||||
|
||||
1. Set `MCP_DOMAIN=mcp.yourdomain.com` in `.env`.
|
||||
2. Uncomment the Traefik labels in `docker-compose.yml`.
|
||||
3. Make sure Traefik is running with a `web` and `websecure` entrypoint and Let's Encrypt configured.
|
||||
|
||||
---
|
||||
|
||||
## Dockerfile Details
|
||||
|
||||
The image uses a multi-stage build:
|
||||
|
||||
| Stage | Base image | Purpose |
|
||||
|---|---|---|
|
||||
| `builder` | `python:3.11-slim` | Install dependencies |
|
||||
| `final` | `python:3.11-slim` | Minimal runtime image |
|
||||
|
||||
The final image:
|
||||
- Runs as user `aegis` (UID 1000, GID 1000)
|
||||
- Exposes port `8080`
|
||||
- Entry point: `python -m aegis_gitea_mcp.server`
|
||||
|
||||
---
|
||||
|
||||
## Production Checklist
|
||||
|
||||
- [ ] `AUTH_ENABLED=true` and `MCP_API_KEYS` set to a strong key
|
||||
- [ ] `GITEA_TOKEN` belongs to a dedicated bot user with minimal permissions
|
||||
- [ ] TLS terminated at the reverse proxy (Traefik, nginx, Caddy, etc.)
|
||||
- [ ] `AUDIT_LOG_PATH` points to a persistent volume
|
||||
- [ ] Log rotation configured for the audit log file
|
||||
- [ ] API key rotation scheduled (every 90 days recommended)
|
||||
- [ ] `MAX_AUTH_FAILURES` and `AUTH_FAILURE_WINDOW` tuned for your threat model
|
||||
- [ ] Resource limits configured in Docker/Kubernetes
|
||||
|
||||
---
|
||||
|
||||
## Kubernetes (Basic)
|
||||
|
||||
A minimal Kubernetes deployment is not included, but the server is stateless and the Docker image is suitable for use in Kubernetes. Key considerations:
|
||||
|
||||
- Store `.env` values as a `Secret` and expose them as environment variables.
|
||||
- Mount an `emptyDir` or PersistentVolumeClaim at the audit log path.
|
||||
- Use a `readinessProbe` and `livenessProbe` on `GET /health`.
|
||||
- Set `resources.requests` and `resources.limits` for CPU and memory.
|
||||
|
||||
---
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
git pull
|
||||
make docker-build
|
||||
make docker-up
|
||||
```
|
||||
|
||||
If you added a new key via `make generate-key` during the update, restart the container to pick up the new `.env`:
|
||||
|
||||
```bash
|
||||
docker-compose restart aegis-mcp
|
||||
```
|
||||
- Run behind TLS-terminating reverse proxy.
|
||||
- Restrict network exposure.
|
||||
- Persist and rotate audit logs.
|
||||
- Enable external monitoring for `/metrics`.
|
||||
|
||||
Reference in New Issue
Block a user