This guide walks you through deploying the Prebid Sales Agent to Fly.io, a platform that runs Docker containers on servers close to your users. Fly.io is a good option for teams that want a managed platform without the complexity of Kubernetes.
| Requirement | Notes |
|---|---|
| Fly.io account | Sign up at fly.io |
flyctl CLI |
Install instructions |
| Authenticated CLI | Run fly auth login |
Create a new Fly app in your preferred region:
fly apps create sales-agent --org personal
Replace personal with your Fly.io organization name if applicable. Run fly regions list to see available regions.
The Sales Agent requires PostgreSQL. Fly.io offers two options:
Fly’s fully managed Postgres service includes automatic backups, failover, and monitoring:
fly postgres create --name sales-agent-db --region ord --vm-size shared-cpu-1x --volume-size 10
Attach the database to your app:
fly postgres attach sales-agent-db --app sales-agent
This automatically sets the DATABASE_URL secret on your app.
| Resource | Estimated Cost |
|---|---|
| Managed Postgres (shared-cpu-1x, 10GB) | ~$38/month |
| Automatic daily backups | Included |
For lower cost, use Fly’s self-managed Postgres option. This runs Postgres as a regular Fly app without managed backups or failover:
fly postgres create --name sales-agent-db --region ord --vm-size shared-cpu-1x --volume-size 1 --initial-cluster-size 1
Attach to your app:
fly postgres attach sales-agent-db --app sales-agent
| Resource | Estimated Cost |
|---|---|
| Self-managed Postgres (shared-cpu-1x, 1GB) | ~$5-7/month |
| Backups | Manual (your responsibility) |
With self-managed Postgres, you are responsible for backups. Set up pg_dump on a schedule or use Fly’s volume snapshots.
Configure the required secrets for your deployment:
# Generate and set the encryption key
fly secrets set ENCRYPTION_KEY="$(openssl rand -base64 32)" --app sales-agent
# Enable test mode for initial setup (remove later)
fly secrets set ADCP_AUTH_TEST_MODE="true" --app sales-agent
Record the ENCRYPTION_KEY value securely before proceeding. If lost, all encrypted data (API keys, adapter credentials) becomes unrecoverable. Run fly secrets list --app sales-agent to verify the secret is set, but note that Fly does not display secret values after creation.
Deploy using the published container image:
fly deploy --image docker.io/prebid/salesagent:latest --app sales-agent
If you need to customize the build, clone the repository and deploy from source:
git clone https://github.com/prebid/salesagent.git
cd salesagent
fly deploy --app sales-agent
The repository includes a Dockerfile that Fly uses automatically.
Once the deployment completes, open the Admin UI:
fly open /admin --app sales-agent
Or navigate to https://sales-agent.fly.dev/admin in your browser.
On first launch with no tenants configured, the Sales Agent enters Setup Mode. This provides a guided workflow:
test123 (since ADCP_AUTH_TEST_MODE=true)When ADCP_AUTH_TEST_MODE=true, the following credentials are available:
| Credential | Value | Purpose |
|---|---|---|
| Admin UI password | test123 |
Access the admin dashboard |
| MCP auth token | test-token |
Authenticate MCP tool calls |
| A2A bearer token | test-token |
Authenticate A2A requests |
Disable test mode before production use. Run fly secrets unset ADCP_AUTH_TEST_MODE --app sales-agent and configure SSO instead.
For production authentication, configure an SSO provider:
https://sales-agent.fly.dev/auth/oidc/callback
fly secrets unset ADCP_AUTH_TEST_MODE --app sales-agent
Database migrations run automatically on each application startup. No manual intervention is needed for routine deployments.
To run migrations manually (e.g., for troubleshooting), open an SSH console:
fly ssh console --app sales-agent
Inside the console:
python -m alembic upgrade head
# Stream live logs
fly logs --app sales-agent
# View recent logs
fly logs --app sales-agent --no-tail
# View app status and running instances
fly status --app sales-agent
# Check the health endpoint
curl https://sales-agent.fly.dev/health
# Open an interactive shell
fly ssh console --app sales-agent
# Run a one-off command
fly ssh console --app sales-agent -C "python -m scripts.diagnostics"
Add more instances to handle increased traffic:
# Scale to 2 instances
fly scale count 2 --app sales-agent
Increase resources per instance:
# Scale to 1 dedicated CPU and 1GB memory
fly scale vm shared-cpu-2x --memory 1024 --app sales-agent
| VM Size | CPU | Memory | Estimated Cost |
|---|---|---|---|
shared-cpu-1x |
Shared 1x | 256MB | ~$5/month |
shared-cpu-2x |
Shared 2x | 512MB | ~$10/month |
performance-1x |
Dedicated 1x | 2GB | ~$30/month |
To serve the Sales Agent on your own domain:
# Add a certificate for your domain
fly certs create ads.yourpublisher.com --app sales-agent
Then create a CNAME record in your DNS provider:
ads.yourpublisher.com. IN CNAME sales-agent.fly.dev.
Fly.io automatically provisions and renews the TLS certificate.
| Component | Managed Postgres | Self-Managed Postgres |
|---|---|---|
| App (shared-cpu-1x) | ~$5/month | ~$5/month |
| Postgres | ~$38/month | ~$5-7/month |
| Bandwidth (typical) | ~$2-5/month | ~$2-5/month |
| Total | ~$45-50/month | ~$12-17/month |
fly logs --app sales-agent
| Symptom | Cause | Fix |
|---|---|---|
ENCRYPTION_KEY not set |
Missing secret | Run fly secrets set ENCRYPTION_KEY="$(openssl rand -base64 32)" --app sales-agent |
connection refused on database |
Postgres not attached | Run fly postgres attach sales-agent-db --app sales-agent |
| OOM killed | Insufficient memory | Scale up: fly scale vm shared-cpu-1x --memory 512 --app sales-agent |
| Health check failures | App still starting | Wait 30-60 seconds; check logs for migration progress |
If the app cannot reach the database:
# Verify the database is running
fly status --app sales-agent-db
# Check the DATABASE_URL secret is set
fly secrets list --app sales-agent
If the database was recreated, you may need to re-attach it:
fly postgres attach sales-agent-db --app sales-agent
If a deployment hangs during health checks:
# Check what's happening
fly logs --app sales-agent
# Cancel and retry
fly deploy --image docker.io/prebid/salesagent:latest --app sales-agent --strategy immediate