AWS Marketplace AMI
Deploy SpatialFlow to your own AWS account using our pre-built Amazon Machine Image (AMI) from the AWS Marketplace.
Overview
The SpatialFlow AMI provides a complete, production-ready deployment in a single EC2 instance:
- Pre-configured Stack: Django API, React frontend, PostgreSQL/PostGIS, Valkey (Redis-compatible)
- Quick Launch: CloudFormation template for automated deployment
- Flexible Architecture: Optional RDS PostgreSQL and ElastiCache for high availability
- Enterprise Ready: TLS support, SSO authentication, CloudWatch integration
Architecture Options
All-in-One (Default)
Perfect for development, testing, or small deployments:
┌─────────────────────────────────────────────┐
│ EC2 Instance │
│ ┌─────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Nginx │ │ Django │ │ Celery │ │
│ │ │ │ API │ │ Workers │ │
│ └─────────┘ └──────────┘ └──────────────┘ │
│ ┌─────────────────┐ ┌──────────────────┐ │
│ │ PostgreSQL │ │ Valkey │ │
│ │ + PostGIS │ │ (Cache/Queue) │ │
│ └─────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────┘
High Availability (Recommended for Production)
For production workloads, use external managed services:
┌─────────────────────────────────────────────┐
│ EC2 Instance │
│ ┌─────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Nginx │ │ Django │ │ Celery │ │
│ │ │ │ API │ │ Workers │ │
│ └─────────┘ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────┘
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Amazon RDS │ │ ElastiCache │
│ PostgreSQL │ │ (Valkey/Redis)│
└────────────────┘ └────────────────┘
Quick Start
Prerequisites
- AWS account with permissions to create EC2, RDS, ElastiCache resources
- VPC with at least 2 subnets in different Availability Zones
- SSH key pair for instance access
Deploy with CloudFormation
-
Subscribe to the AMI on AWS Marketplace
-
Launch CloudFormation Stack:
- Go to AWS CloudFormation Console
- Click "Create stack" → "With new resources"
- Upload the SpatialFlow QuickStart template
- Fill in parameters:
| Parameter | Description | Default |
|---|---|---|
InstanceType | EC2 instance size | t3.medium |
KeyName | SSH key pair for access | (required) |
VpcId | Your VPC ID | (required) |
SubnetId1 | Primary subnet (public recommended) | (required) |
SubnetId2 | Secondary subnet (different AZ, required for RDS/ElastiCache) | (required) |
AllowedCIDR | CIDR block for HTTP/HTTPS access (e.g., 0.0.0.0/0 for public, or your corporate CIDR) | (required - no default) |
SSHAllowedCIDR | CIDR block for SSH access (leave empty to disable SSH, use SSM Session Manager instead) | (empty - SSH disabled) |
AmiIdOverride | Optional AMI ID override (leave empty to use latest AMI via SSM parameter) | (empty - uses SSM) |
AdminEmail | Email for admin account | (required) |
SenderEmailDomain | Verified SES domain or email for outbound emails | (optional) |
Environment | Environment name for logging | production |
UseExternalDB | Use RDS PostgreSQL instead of local | false |
DBInstanceClass | RDS instance class (if UseExternalDB=true) | db.t3.micro |
DBAllocatedStorage | RDS storage in GB | 20 |
UseExternalCache | Use ElastiCache instead of local Valkey | false |
CacheNodeType | ElastiCache node type (if UseExternalCache=true) | cache.t3.micro |
-
Wait for deployment (~10-15 minutes)
-
Access your instance:
- Application URL: Check CloudFormation Outputs for
ApplicationURL - SSH (if
SSHAllowedCIDRis configured):ssh -i your-key.pem ec2-user@<public-ip> - SSM Session Manager (recommended):
aws ssm start-session --target <instance-id>
- Application URL: Check CloudFormation Outputs for
First Boot Process
On first launch, SpatialFlow automatically:
- Generates secure passwords for PostgreSQL and Valkey
- Runs database migrations
- Creates an admin user with the provided email
- Writes credentials to
~/SPATIALFLOW_CREDENTIALS.txt - Starts all services
Retrieve your admin credentials:
ssh -i your-key.pem ec2-user@<public-ip>
cat ~/SPATIALFLOW_CREDENTIALS.txt
Configuring HTTPS
HTTPS is required for production deployments. The AMI includes a helper script:
Using Let's Encrypt (Recommended)
sudo spatialflow-enable-tls --domain your-domain.com --email admin@your-domain.com
This will:
- Obtain a certificate from Let's Encrypt
- Configure Nginx for HTTPS
- Set up automatic certificate renewal
Using Custom Certificate
sudo spatialflow-enable-tls --custom \
--cert /path/to/fullchain.pem \
--key /path/to/privkey.pem
Enabling SSO Authentication
SpatialFlow supports Single Sign-On with Google, Microsoft, and GitHub.
OAuth providers require HTTPS for callback URLs. Configure TLS before enabling SSO.
Provider Setup
Google OAuth
- Go to Google Cloud Console
- Create OAuth 2.0 Client ID (Web application)
- Add redirect URI:
https://your-domain.com/api/v1/auth/oauth/google/callback - Copy Client ID and Client Secret
Microsoft OAuth
- Go to Azure Portal
- Create App Registration
- Add redirect URI:
https://your-domain.com/api/v1/auth/oauth/microsoft/callback - Create client secret
GitHub OAuth
- Go to GitHub Developer Settings
- Create OAuth App
- Set callback URL:
https://your-domain.com/api/v1/auth/oauth/github/callback
Configuration
Add credentials to the environment file:
sudo nano /etc/spatialflow/.env
# Add your OAuth credentials (only providers you want to enable)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
MICROSOFT_CLIENT_ID=your-microsoft-client-id
MICROSOFT_CLIENT_SECRET=your-microsoft-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
# Set to your domain
OAUTH_REDIRECT_BASE_URL=https://your-domain.com
Restart services:
sudo systemctl restart spatialflow-api spatialflow-celery spatialflow-celerybeat
Service Management
SpatialFlow uses systemd for service management:
# View service status
sudo systemctl status spatialflow-api
sudo systemctl status spatialflow-celery
sudo systemctl status spatialflow-celerybeat
# View logs
sudo journalctl -u spatialflow-api -f
sudo journalctl -u spatialflow-celery -f
# Restart services after configuration changes
sudo systemctl restart spatialflow-api spatialflow-celery spatialflow-celerybeat
Configuration Reference
All configuration is managed through /etc/spatialflow/.env:
Core Settings
| Variable | Default | Description |
|---|---|---|
SECRET_KEY | Auto-generated | Django secret key |
DEBUG | False | Debug mode (never enable in production) |
ALLOWED_HOSTS | * | Comma-separated allowed hostnames |
LOG_LEVEL | INFO | Logging level |
Database Settings
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | Local PostgreSQL | Database connection URL |
EXTERNAL_DB | 0 | Set to 1 for RDS |
Cache Settings
| Variable | Default | Description |
|---|---|---|
REDIS_URL | Local Valkey | Redis/Valkey connection URL |
EXTERNAL_VALKEY | 0 | Set to 1 for ElastiCache |
REDIS_SSL | 0 | Set to 1 for TLS connections |
SSO Settings
| Variable | Description |
|---|---|
GOOGLE_CLIENT_ID | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Google OAuth client secret |
MICROSOFT_CLIENT_ID | Microsoft/Azure AD client ID |
MICROSOFT_CLIENT_SECRET | Microsoft/Azure AD client secret |
GITHUB_CLIENT_ID | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET | GitHub OAuth app client secret |
OAUTH_REDIRECT_BASE_URL | Base URL for OAuth callbacks |
Backup and Recovery
Local PostgreSQL Backup (All-in-One Setup)
If using the default local PostgreSQL:
# Create backup
sudo -u postgres pg_dump spatialflow > spatialflow_backup_$(date +%Y%m%d).sql
# Restore from backup
sudo -u postgres psql spatialflow < spatialflow_backup_20250101.sql
RDS Backup (High Availability Setup)
If using external RDS (UseExternalDB=true), RDS handles automated backups. You can also create manual snapshots:
# Create RDS snapshot via AWS CLI
aws rds create-db-snapshot \
--db-instance-identifier your-stack-name-db \
--db-snapshot-identifier spatialflow-manual-$(date +%Y%m%d) \
--region us-east-1
# Or manually export using pg_dump with RDS credentials
# DATABASE_URL contains embedded credentials, so pg_dump can use it directly
source /etc/spatialflow/.env
pg_dump "$DATABASE_URL" > spatialflow_backup_$(date +%Y%m%d).sql
RDS automatically creates daily snapshots with configurable retention (default: 7 days). Access these via the AWS Console under RDS → Snapshots.
Backup to S3 (Local PostgreSQL)
For local PostgreSQL deployments, automate backups to S3. This requires an IAM role attached to the EC2 instance with S3 write permissions.
# Create and upload encrypted backup (replace with your values)
sudo -u postgres pg_dump spatialflow | gzip | \
aws s3 cp - s3://your-backup-bucket/spatialflow_$(date +%Y%m%d).sql.gz \
--region us-east-1 \
--sse AES256
# Set up daily cron job (2 AM daily)
# Replace YOUR_BUCKET and YOUR_REGION with your actual values
# Note: The cron runs as postgres user; ensure aws-cli is installed and in PATH
cat <<'EOF' | sudo tee /etc/cron.d/spatialflow-backup
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
0 2 * * * postgres pg_dump spatialflow | gzip | aws s3 cp - s3://YOUR_BUCKET/spatialflow_$(date +\%Y\%m\%d).sql.gz --region YOUR_REGION --sse AES256
EOF
# Then edit the file to set your bucket and region
sudo nano /etc/cron.d/spatialflow-backup
Enable S3 bucket versioning and configure a lifecycle policy to expire old backups. Use a bucket policy to enforce encryption (aws:SecureTransport) and restrict access to the EC2 instance role.
Configuration Backup
Also back up your configuration:
sudo cp /etc/spatialflow/.env /path/to/backup/.env.backup
Upgrading
To upgrade to a new AMI version:
- Create a backup of your database and configuration
- Launch a new instance from the updated AMI
- Restore your data to the new instance
- Update DNS/Elastic IP to point to the new instance
- Terminate the old instance after verification
# Check current version
cat /opt/spatialflow/VERSION
# Back up before upgrading
sudo -u postgres pg_dump spatialflow > pre_upgrade_backup.sql
sudo cp /etc/spatialflow/.env /home/ec2-user/.env.backup
For zero-downtime upgrades, run the new instance in parallel and switch traffic using an Elastic IP or load balancer.
Security Best Practices
- Restrict SSH access - Limit security group SSH rule to your IP
- Enable HTTPS - Configure TLS before production use
- Use IAM roles - Attach IAM role instead of access keys
- Delete credentials file - Remove
~/SPATIALFLOW_CREDENTIALS.txtafter noting values - Configure ALLOWED_HOSTS - Set specific domains, not
* - Enable CloudWatch - Monitor logs and set up alarms
Health Checks
Configure load balancer health checks:
| Endpoint | Response | Use Case |
|---|---|---|
/health | 200 OK | Full application health |
/nginx-health | 200 OK | Nginx only (faster) |
Troubleshooting
Common Issues
"DisallowedHost" errors:
sudo nano /etc/spatialflow/.env
# Set ALLOWED_HOSTS to your domain
ALLOWED_HOSTS=your-domain.com,*.your-domain.com
Services not starting:
# Check service status
sudo systemctl status spatialflow-api
# View detailed logs
sudo journalctl -u spatialflow-api --no-pager -n 100
Database connection issues:
# Test connection
sudo -u spatialflow /opt/spatialflow/.venv/bin/python \
/opt/spatialflow/api/manage.py dbshell
SSO buttons not appearing:
- Verify credentials are set in
.env - Credentials must be at least 20 characters
- Restart services after configuration changes
Getting Help
- View first-boot logs:
sudo journalctl -u spatialflow-first-boot - Application logs:
sudo journalctl -u spatialflow-api -f - Email: support@spatialflow.io
Cost Optimization
Recommended Instance Types
| Use Case | Instance Type | vCPU | Memory |
|---|---|---|---|
| Development | t3.small | 2 | 2 GB |
| Small Production | t3.medium | 2 | 4 GB |
| Medium Production | t3.large | 2 | 8 GB |
| Large Production | m5.xlarge | 4 | 16 GB |
Cost-Saving Tips
- Use Reserved Instances for predictable workloads
- Enable RDS/ElastiCache only when needed for HA
- Right-size instances based on actual usage
- Use Savings Plans for long-term commitments