An open-source, self-hosted AWS Instance Scheduler designed to run inside a single Docker container using Docker Compose. CloudNap helps you automatically schedule the shutdown and startup of AWS resources (EC2 and RDS) to optimize operations and cloud resource runtime.
Managing AWS EC2 and RDS instances on a budget shouldn't require complex architectures or expensive third-party subscriptions. Here is how CloudNap compares to common AWS Cost Optimization practices:
| Feature | CloudNap π΄ | AWS Instance Scheduler | SaaS Platforms | Manual Scripts |
|---|---|---|---|---|
| Deployment | Single Docker Container | Heavy CloudFormation / Lambda | Third-party Connection | Cron on server / Local |
| Pricing | Free & Open Source | Pay-per-use (DynamoDB/Lambda) | Monthly Subscription | Free |
| Live Cost Tracking | Yes (AWS Pricing API) | No | Yes | No |
| UI Dashboard | Yes (Premium Dark/Light) | No | Yes | No |
| TTL Lease Expiry | Yes | No | Yes (Premium plans) | No |
| GreenOps Impact | Built-in tracking | No | Yes | No |
- Development & QA Sandboxes: Instantly shut down non-production servers overnight and on weekends to avoid idle bill runups.
- Startups & SMBs: Implement cloud cost-saving policies in 10 minutes without security approvals or platform subscription fees.
- Temporary Lease Allocations: Allocate cloud resources to contractors or sprints with a hard lease expiry time (TTL) to automatically prevent orphaned servers.
- GreenOps & Carbon reduction: Quantify active server sleeping hours to track resource footprint reduction.
- Auto-Discovery: Automatically scan and list EC2 and RDS instances across selected AWS regions.
- Date-Based Sleep Windows (Sleep Duration): Define date and time ranges (Turn OFF date to Turn ON date) where the resource must be stopped (sleeping). Outside of these ranges, the resource automatically runs.
- Recurring Sleep Schedules (Daily & Weekly): Define repeating daily or weekly sleep schedules (e.g. Turn OFF daily at 22:00 and Turn ON at 08:00 UTC, or select specific active days of the week).
- Searchable Audit Trail: Interactive logs table displaying user actions (creating/deleting schedules, applying overrides) and system operations (
SYSTEM_START/SYSTEM_STOP). Logs are tagged by resource and support text search. - High-Contrast Light Theme: Sleek UI styled using the custom brand colors matching the
logs.applinker.iocolor scheme (Teal Blue#0c586c, Slate Gray#5f6e79, Soft Gray borders, and Light Blue-Grey background#f0f4f8). - Resource Details Routing & Chronological View: Clicking a resource card routes you to a dedicated detail page where all sleep schedules are displayed, sorted chronologically.
- Manual Controls & Holds: Start or stop instances manually directly from the details view with a single click. The scheduler locks the state and pauses automated schedules until "Resume Schedule" is clicked.
- Operational Overview Dashboard: Monitor your infrastructure at a glance with metrics showing Managed Resources, Scheduled Resources, Manual Holds, and Sleeping instances.
- Pure UTC Engine: The calendar picker, time text fields, and scheduling backend run entirely on UTC. No local browser timezone conversions are applied.
- Conflict & Overlap Prevention: The backend validates sleep windows on creation, rejecting overlapping date/time ranges.
- State-Based Self-Healing: Scheduler ticks are range-based (every minute) rather than event-triggered, ensuring instances heal to their target state even after container restarts or host downtime.
- Mock Mode for Testing: Run locally without any AWS credentials or active AWS resources by enabling
MOCK_AWS=true. - Slack & Telegram Integrations: Real-time notifications dispatched to Slack incoming webhooks and Telegram Bot APIs on scheduling creations, override adjustments, and automated system state corrections. Features a dedicated sidebar Settings panel supporting active toggles, optional Slack channel overrides, and instant connection test message buttons.
- Resource Lease Expiry (TTL): Assign temporary leases to developers or teams by specifying a precise UTC lease expiration date and time. Once expired, the scheduler automatically stops the resource, locks it in a stopped state, and broadcasts alert notifications to Slack/Telegram.
- Cost Savings Dashboard & Analytics: Live cost management dashboard tracking accumulated dollar savings and real-time hourly savings rate. Features an interactive information popup explaining the underlying math and formulas.
- Free AWS Pricing API Integration: Automatically queries the official, free-of-charge AWS Price List Service API (
pricing) to fetch exact hourly costs for active EC2 and RDS sizes based on region, with local in-memory caching and offline fallback cost tables. - Dark & Light Themes: Premium Dark mode styled with a high-end Dark Slate-Blue and Glowing Teal aesthetic, toggled from the bottom of the sidebar with persistent preference saving.
- Backend: Python (FastAPI) +
boto3(AWS SDK) +APScheduler. - Database: SQLite (SQLAlchemy) for persistent resource mappings, sleep schedules, action logs, and manual overrides.
- Frontend: React (Vite) + Tailwind CSS + High-Contrast Light Theme, served statically by FastAPI.
- Containerization: Docker & Docker Compose.
graph TD
User([Platform User]) -->|React UI| FE[Vite Frontend]
FE -->|REST API / Bearer Auth| BE[FastAPI Backend]
BE -->|Read/Write Config & Schedules| DB[(SQLite Database)]
BE -->|"APScheduler Ticks (Every 1m)"| SE[Self-Healing Engine]
SE -->|Boto3 / pricing Client| AWS[AWS API - EC2 & RDS]
SE -.->|Alerts| Slack[Slack Webhook]
SE -.->|Alerts| Telegram[Telegram Bot API]
cloudnap/
βββ backend/
β βββ app/
β β βββ __init__.py
β β βββ main.py # FastAPI entrypoint & static file mounting
β β βββ config.py # Settings & environment variables
β β βββ db.py # SQLite database & self-healing migrations
β β βββ models.py # Database models (Resource, ResourceSchedule, ResourceOverride, ActionLog)
β β βββ schemas.py # Pydantic validation schemas
β β βββ aws.py # Boto3 logic & Mock AWS implementation
β β βββ scheduler.py # Background state-based check job (every minute)
β β βββ routes/
β β βββ auth.py # Basic/Local password authentication
β β βββ instances.py # Endpoints for resource management, active windows, and audit logs
β βββ requirements.txt # Python dependencies
β βββ Dockerfile # Multi-stage build (React build + Python backend)
βββ frontend/
β βββ src/ # React UI code (Components, Dashboards, api client)
β βββ package.json # Node dependencies
β βββ tailwind.config.js # Custom Tailwind theme (Glassmorphism)
β βββ vite.config.js # Vite configuration
βββ docker-compose.yml # Production-ready compose configuration
βββ LICENSE # MIT License
βββ README.md # Documentation (this file)
The easiest way to run CloudNap locally or in production is using Docker Compose:
-
Clone the repository:
git clone https://github.com/your-username/cloudnap.git cd cloudnap -
Configure environment variables: Create a
.envfile in thebackend/directory:MOCK_AWS=true APP_PASSWORD=secret123 DATABASE_URL=sqlite:///./data/cloudnap.db
Note: Set
MOCK_AWS=falseand configure standard AWS environment variables (AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_DEFAULT_REGION) to connect to actual AWS resources. -
Launch the stack:
Using Docker Compose:
docker compose up --build -d
Using Docker Swarm (
docker stack deploy):# Build the image first (since Swarm stack deploy doesn't support the 'build' key) docker build -t cloudnap:latest -f backend/Dockerfile . # Deploy the stack docker stack deploy -c docker-stack.yml cloudnap
-
Access the web panel: Open http://localhost:8080 and authenticate using your password (
secret123). -
Health Checks: If deploying behind an AWS Application Load Balancer (ALB), configure your Target Group health check with:
- Path:
/api/auth/status - Port:
8080(public JSON status endpoint, returns200 OK)
- Path:
You can execute the automated test suite inside the running Docker container:
docker compose exec cloudnap pip install pytest
docker compose exec cloudnap python -m pytest backend/tests -vOr run them locally on your host machine:
cd backend
python3 -m pytest tests -vWe love contributions! You can easily develop and test CloudNap locally without having an AWS account by utilizing the Mock AWS Mode.
For detailed instructions on running backend hot-reloading, frontend dev servers, and code standards, please read our Contributing Guide.
If deploying to AWS (with MOCK_AWS=false), the IAM role running the container requires the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:DescribeRegions",
"rds:DescribeDBInstances",
"rds:StartDBInstance",
"rds:StopDBInstance",
"rds:StartDBCluster",
"rds:StopDBCluster",
"pricing:GetProducts"
],
"Resource": "*"
}
]
}CloudNap is designed to scale across multiple AWS Accounts from a single dashboard. You can add external accounts under the AWS Accounts tab using two methods:
This method allows CloudNap to securely manage resources in target accounts without storing long-lived access keys.
To set this up:
- In the target account, create an IAM Role (e.g.
CloudNapCrossAccountRole) with the Required AWS IAM Permissions. - Configure the role's Trust Relationship to trust the main account where CloudNap is running:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::MAIN_ACCOUNT_ID:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "YOUR_OPTIONAL_EXTERNAL_ID"
}
}
}
]
}- Add the role's ARN and external ID (if set) in CloudNap's dashboard.
Alternatively, you can connect accounts by providing standard AWS Access Keys. All credentials are AES-256 Fernet encrypted at rest in your SQLite database using either the ENCRYPTION_KEY environment variable or a stable key derived from your APP_PASSWORD fallback.