Skip to content

Commit f1595e0

Browse files
authored
Merge pull request #120 from manavgup/feature/docs-deploy-fly-io
Updated docs and fly.toml file to deploy to fly.io
2 parents bd756c8 + 1af12c0 commit f1595e0

File tree

3 files changed

+267
-0
lines changed

3 files changed

+267
-0
lines changed

docs/docs/deployment/.pages

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ nav:
1212
- ibm-code-engine.md
1313
- aws.md
1414
- azure.md
15+
- fly-io.md

docs/docs/deployment/fly-io.md

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# ⚙️ Fly.io Deployment Guide for MCP Gateway
2+
3+
This guide covers the complete deployment workflow for the **MCP Gateway** on Fly.io, including common troubleshooting steps.
4+
5+
---
6+
7+
## Overview
8+
9+
Fly.io is a global app platform for running containers close to your users, with built-in TLS, persistent volumes, and managed Postgres support. It offers a generous free tier and automatic HTTPS with fly.dev subdomains.
10+
11+
---
12+
13+
## 1 · Prerequisites
14+
15+
| Requirement | Details |
16+
| -------------------- | ------------------------------------------------------------------ |
17+
| Fly.io account | [Sign up](https://fly.io) |
18+
| Fly CLI | Install via Homebrew: `brew install flyctl` or see Fly docs |
19+
| Docker **or** Podman | For local image builds (optional) |
20+
| Containerfile | The included Containerfile with psycopg2-binary support |
21+
22+
---
23+
24+
## 2 · Quick Start (Recommended)
25+
26+
### 2.1 Initialize Fly project
27+
```bash
28+
fly launch --name your-app-name --no-deploy
29+
```
30+
This creates a new Fly app without deploying immediately.
31+
32+
### 2.2 Create and attach Fly Postgres
33+
```bash
34+
# Create postgres (choose Development configuration for testing)
35+
fly postgres create --name your-app-db --region yyz
36+
37+
# Note the connection details from the output, you'll need the password
38+
```
39+
40+
### 2.3 Set secrets
41+
```bash
42+
# Set authentication secrets
43+
fly secrets set JWT_SECRET_KEY=$(openssl rand -hex 32)
44+
fly secrets set BASIC_AUTH_USER=admin BASIC_AUTH_PASSWORD=your-secure-password
45+
46+
# Set database URL (CRITICAL: use postgresql:// not postgres://)
47+
fly secrets set DATABASE_URL="postgresql://postgres:[email protected]:5432/postgres"
48+
```
49+
50+
**⚠️ Important:** Always use `postgresql://` scheme, not `postgres://`. The latter causes SQLAlchemy dialect loading errors.
51+
52+
### 2.4 Deploy the app
53+
```bash
54+
fly deploy
55+
```
56+
57+
---
58+
59+
## 3 · Containerfile Requirements
60+
61+
Ensure your Containerfile explicitly installs PostgreSQL dependencies:
62+
63+
```dockerfile
64+
# Create virtual environment, upgrade pip and install dependencies
65+
RUN python3 -m venv /app/.venv && \
66+
/app/.venv/bin/python3 -m pip install --upgrade pip setuptools pdm uv && \
67+
/app/.venv/bin/python3 -m pip install psycopg2-binary && \
68+
/app/.venv/bin/python3 -m uv pip install ".[redis]"
69+
```
70+
71+
The explicit `psycopg2-binary` installation is required because uv may not properly install optional dependencies.
72+
73+
---
74+
75+
## 4 · fly.toml Configuration
76+
77+
Your `fly.toml` should look like this:
78+
79+
```toml
80+
app = "your-app-name"
81+
primary_region = "yyz"
82+
83+
[build]
84+
dockerfile = "Containerfile"
85+
86+
[env]
87+
HOST = "0.0.0.0"
88+
PORT = "4444"
89+
90+
[http_service]
91+
internal_port = 4444
92+
force_https = true
93+
auto_stop_machines = "stop"
94+
auto_start_machines = true
95+
min_machines_running = 0
96+
processes = ["app"]
97+
98+
[[vm]]
99+
memory = "1gb"
100+
cpu_kind = "shared"
101+
cpus = 1
102+
```
103+
104+
**Note:** Don't put secrets like `DATABASE_URL` in `fly.toml` - use `fly secrets set` instead.
105+
106+
---
107+
108+
## 5 · Testing Your Deployment
109+
110+
### 5.1 Check app status
111+
```bash
112+
fly status
113+
fly logs
114+
```
115+
116+
### 5.2 Test endpoints
117+
```bash
118+
# Health check (no auth required)
119+
curl https://your-app-name.fly.dev/health
120+
121+
# Protected endpoints (require auth)
122+
curl -u admin:your-password https://your-app-name.fly.dev/docs
123+
curl -u admin:your-password https://your-app-name.fly.dev/tools
124+
```
125+
126+
### 5.3 Expected responses
127+
- Health: `{"status":"healthy"}`
128+
- Protected endpoints without auth: `{"detail":"Not authenticated"}`
129+
- Protected endpoints with auth: JSON response with data
130+
131+
---
132+
133+
## 6 · Troubleshooting
134+
135+
### Common Issue 1: SQLAlchemy postgres dialect error
136+
```
137+
sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres
138+
```
139+
140+
**Solutions:**
141+
1. Ensure `psycopg2-binary` is explicitly installed in Containerfile
142+
2. Use `postgresql://` not `postgres://` in DATABASE_URL
143+
3. Rebuild with `fly deploy --no-cache`
144+
145+
### Common Issue 2: Database connection refused
146+
**Solutions:**
147+
1. Verify DATABASE_URL format: `postgresql://postgres:[email protected]:5432/postgres`
148+
2. Check postgres app is running: `fly status -a your-app-db`
149+
3. Verify password matches postgres creation output
150+
151+
### Common Issue 3: Machines not updating
152+
**Solutions:**
153+
```bash
154+
# Force machine updates
155+
fly machine list
156+
fly machine update MACHINE_ID --image your-new-image
157+
158+
# Or restart all machines
159+
fly scale count 0
160+
fly scale count 1
161+
```
162+
163+
---
164+
165+
## 7 · Production Considerations
166+
167+
### Security
168+
- Change default `BASIC_AUTH_PASSWORD` to a strong password
169+
- Consider using JWT tokens for API access
170+
- Enable Fly's private networking for database connections
171+
172+
### Scaling
173+
```bash
174+
# Scale to multiple machines for HA
175+
fly scale count 2
176+
177+
# Scale machine resources
178+
fly scale memory 2gb
179+
```
180+
181+
### Monitoring
182+
```bash
183+
# View real-time logs
184+
fly logs -f
185+
186+
# Check machine metrics
187+
fly machine status MACHINE_ID
188+
```
189+
190+
---
191+
192+
## 8 · Clean Deployment Script
193+
194+
For a completely fresh deployment:
195+
196+
```bash
197+
#!/bin/bash
198+
set -e
199+
200+
APP_NAME="your-app-name"
201+
DB_NAME="${APP_NAME}-db"
202+
REGION="yyz"
203+
PASSWORD=$(openssl rand -base64 32)
204+
205+
echo "🚀 Deploying MCP Gateway to Fly.io..."
206+
207+
# Create app
208+
fly launch --name $APP_NAME --no-deploy --region $REGION
209+
210+
# Create postgres
211+
fly postgres create --name $DB_NAME --region $REGION
212+
213+
# Set secrets
214+
fly secrets set JWT_SECRET_KEY=$(openssl rand -hex 32)
215+
fly secrets set BASIC_AUTH_USER=admin
216+
fly secrets set BASIC_AUTH_PASSWORD=$PASSWORD
217+
218+
# Get postgres password and set DATABASE_URL
219+
echo "⚠️ Set your DATABASE_URL manually with the postgres password:"
220+
echo "fly secrets set DATABASE_URL=\"postgresql://postgres:YOUR_PG_PASSWORD@${DB_NAME}.flycast:5432/postgres\""
221+
222+
# Deploy
223+
echo "🏗️ Ready to deploy. Run: fly deploy"
224+
```
225+
226+
---
227+
228+
## 9 · Additional Resources
229+
230+
- [Fly.io Documentation](https://fly.io/docs)
231+
- [Fly Postgres Guide](https://fly.io/docs/postgres/)
232+
- [Fly Secrets Management](https://fly.io/docs/reference/secrets/)
233+
234+
**Success indicators:**
235+
-`fly status` shows machines as "started"
236+
-`/health` endpoint returns `{"status":"healthy"}`
237+
- ✅ Protected endpoints require authentication
238+
- ✅ No SQLAlchemy errors in logs

fly.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# fly.toml app configuration file generated for mcpgateway on 2025-06-17T14:12:40-04:00
2+
#
3+
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
4+
#
5+
6+
app = 'mcpgateway'
7+
primary_region = 'yyz'
8+
9+
[build]
10+
dockerfile = 'Containerfile'
11+
12+
[env]
13+
HOST = '0.0.0.0'
14+
PORT = '4444'
15+
REDIS_URL = 'redis://redis:6379/0'
16+
17+
[http_service]
18+
internal_port = 4444
19+
force_https = true
20+
auto_stop_machines = 'stop'
21+
auto_start_machines = true
22+
min_machines_running = 0
23+
processes = ['app']
24+
25+
[[vm]]
26+
memory = '1gb'
27+
cpu_kind = 'shared'
28+
cpus = 1

0 commit comments

Comments
 (0)