A multi-cloud infrastructure management platform. Provision VMs on AWS and Azure, manage Kubernetes clusters, deploy containerized services, and run isolated Jupyter notebooks — all through a single REST API.
Built with FastAPI, PostgreSQL, Docker, and Kubernetes. Managed with uv.
- Python 3.11+
- uv
- Docker
- PostgreSQL 16+
1. Clone and enter the app directory
git clone https://github.com/Swastik19Nit/cloudlab.git
cd cloudlab/src/app2. Copy and configure environment variables
cp ../../sample.env .env
# Edit .env with your values (see Environment Variables below)3. Create the Docker network
docker network create <DOCKER_NETWORK>
# Replace <DOCKER_NETWORK> with the value set in your .env4. Install dependencies
uv sync5. Apply database migrations
uv run alembic upgrade head6. Start the development server
uv run fastapi devThe API will be available at http://localhost:8000.
Interactive docs at http://localhost:8000/docs.
Spin up PostgreSQL locally:
docker compose up -dThis starts PostgreSQL 16 on port 5432 with a persistent volume.
All configuration is loaded from a .env file in src/app/. Required variables:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string — postgresql+asyncpg://user:pass@host:port/aicloudlab |
SESSION_SECRET_KEY |
Secret key for session middleware |
ALLOWED_ORIGINS |
Comma-separated list of allowed CORS origins |
DOMAIN_NAME |
Base domain for service/notebook URLs (e.g. localdev.me) |
| Variable | Description |
|---|---|
FUSIONAUTH_URL |
FusionAuth server URL |
FUSIONAUTH_APPLICATION_ID |
FusionAuth application ID |
FUSIONAUTH_API_KEY |
FusionAuth API key |
| Variable | Description |
|---|---|
HF_CLIENT_ID / HF_CLIENT_SECRET |
Hugging Face OAuth app credentials |
GH_CLIENT_ID / GH_CLIENT_SECRET |
GitHub OAuth app credentials |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
Google OAuth app credentials |
| Variable | Description |
|---|---|
AWS_REGION |
AWS region (e.g. ap-south-1) |
AWS_ACCESS_KEY |
AWS access key ID |
AWS_SECRET_KEY |
AWS secret access key |
| Variable | Description |
|---|---|
DOCKER_NETWORK |
Docker network name for notebook containers |
DOCKER_ACCOUNT |
Docker Hub account name |
CADDY_FORWARD_AUTH_HOST |
Caddy forward auth endpoint |
| Variable | Description |
|---|---|
RAZORPAY_CLIENT_ID / RAZORPAY_CLIENT_SECRET |
Razorpay API credentials |
RAZORPAY_WEBHOOK_SECRET |
Razorpay webhook validation secret |
| Variable | Description |
|---|---|
E2E_API_KEY |
E2E cloud API key |
E2E_JWT_TOKEN |
E2E cloud JWT token |
E2E_PROJECT_ID |
E2E cloud project ID |
Migrations are managed with Alembic.
Apply all pending migrations
uv run alembic upgrade headGenerate a new migration (after adding or modifying a model)
# First, import the new model in src/app/migrations/env.py
uv run alembic revision --autogenerate -m "describe your change"Downgrade one step
uv run alembic downgrade -1Note
Always import new models in src/app/migrations/env.py before generating a migration, otherwise the change will not be detected.
This project uses Ruff for linting and formatting.
Install pre-commit hooks (run once after cloning)
uv run pre-commit installRun linter and formatter manually
uv run pre-commit run --all-filesFormat only
uv run ruff format src/appcloudlab/
├── src/app/
│ ├── main.py # FastAPI application, middleware, router registration
│ ├── core/
│ │ ├── config.py # Singleton config loader (.env + environment)
│ │ ├── database.py # Async SQLAlchemy engine and session factory
│ │ └── auth.py # JWT authentication guard (FusionAuth JWKS, RS256)
│ ├── models/ # SQLAlchemy ORM models (18 models)
│ ├── routers/ # FastAPI route handlers (18 routers)
│ ├── cloud/
│ │ ├── aws.py # AWS EC2, VPC, security groups, pricing
│ │ ├── azure.py # Azure VMs, virtual networks, resource groups
│ │ └── e2e.py # E2E cloud provider integration
│ ├── utils/
│ │ ├── kubernetes.py # Kubernetes API client — namespaces, deployments, ingress
│ │ ├── docker.py # Docker SDK — notebook container lifecycle
│ │ ├── crypto.py # SSH key generation, HMAC request signing
│ │ ├── razorpay.py # Razorpay payment helpers
│ │ └── ses.py # AWS SES email sending
│ ├── migrations/ # Alembic migration versions (29 versions)
│ └── pyproject.toml
├── docker_images/
│ └── dockerfile # Jupyter notebook base image (jupyter + git + git-lfs)
├── docker-compose.yml # PostgreSQL 16 for local development
└── sample.env # Environment variable template
The API is versioned at the router level. All endpoints require a Bearer JWT token issued by FusionAuth except authentication routes.
| Prefix | Description |
|---|---|
/ |
Login, signup, user management |
/cloud |
Cloud account management, VM provisioning (AWS / Azure) |
/cluster |
Kubernetes cluster creation and management |
/service |
Service deployment to Kubernetes clusters (v1) |
/service/v2 |
Service deployment directly to nodes (v2) |
/project |
Project management |
/hf |
Hugging Face OAuth and account linking |
/gh |
GitHub OAuth and account linking |
/google |
Google OAuth and account linking |
/cloud_connect |
Cloud connection helpers |
Full interactive docs available at /docs when the server is running.
Two deployment strategies are supported:
v1 — Kubernetes native
Deploys a Deployment, Service, and Ingress resource on a configured cluster. Uses Kong as the ingress controller.
v2 — Direct node
Posts directly to the node manager daemon running at http://<node-ip>:8000. Requests are signed with HMAC using the node's private key. Supports private Docker registry credentials.
Authentication is delegated to FusionAuth. JWTs are validated using RS256 against the JWKS endpoint at {FUSIONAUTH_URL}/.well-known/jwks.json.
Tokens are accepted via:
Authorization: Bearer <token>header- Session cookie
Image tags:
- Branch push →
app-{branch-name} - Release →
app-{version},app-latest
MIT
