Skip to content

AlinaSHforwork/git-deploy-healer

Repository files navigation

PyPaaS – Git Deploy Healer

CI/CD License: MIT Test Coverage Python 3.12+

PyPaaS is a lightweight, developer‑friendly Platform‑as‑a‑Service engine that automates deployments from Git repositories. It builds Docker images, deploys containers, updates Nginx routing, and includes a self‑healing daemon to restart unhealthy apps. Inspired by Heroku and Kubernetes, PyPaaS brings Git‑Ops workflows, observability, and developer experience — without the complexity.

Perfect for:

  • 🚀 Local development PaaS environments
  • 🏠 Self‑hosted mini‑cloud deployments
  • 📚 DevOps learning and experimentation
  • 🔧 Deployment automation demonstrations
  • 👥 Small team collaboration on shared infrastructure

📌 Current Status: Local-only deployment. AWS cloud deployment support is planned for future releases.


Features

  • Automated Git Deployments – Webhook‑driven builds and deploys from GitHub/GitLab
  • Zero‑Downtime Routing – Nginx reverse proxy with atomic config swaps
  • Self‑Healing Engine – Background daemon detects and restarts unhealthy containers
  • Observability – Prometheus metrics for deployments, restarts, and active apps
  • Interactive Dashboard – Web UI for app management and monitoring
  • RESTful API – Full-featured API with OpenAPI/Swagger documentation
  • Security First – API key authentication, HMAC webhook verification, rate limiting
  • Extensible Configuration.env‑based setup with sensible defaults
  • Comprehensive Testing – 80%+ code coverage with unit and integration tests
  • CI/CD Ready – GitHub Actions pipeline with linting, testing, and security scans

Architecture

PyPaaS runs as a FastAPI service (default port 8080) backed by PostgreSQL and Nginx.

┌─────────────────────────────────────────────────────────────────┐
│                     Git Webhook Event                           │
│                    (GitHub/GitLab Push)                         │
└────────────────────────┬────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────────┐
│              FastAPI Server (:8080)                             │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ • Webhook Handler (HMAC verification)                    │   │
│  │ • API Endpoints (Deploy, Status, Logs)                   │   │
│  │ • Dashboard UI                                           │   │
│  │ • Prometheus Metrics                                     │   │
│  └──────────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────────┐
│           Background Deployment Pipeline                        │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ 1. Git Manager: Clone/Update Repository                  │   │
│  │ 2. Container Engine: Build Docker Image                  │   │
│  │ 3. Deploy: Run Container with Port Mapping               │   │
│  │ 4. Proxy Manager: Update Nginx Configuration             │   │
│  └──────────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────────┐
│              Running Containers                                 │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ • App 1 (Port 8001)                                      │   │
│  │ • App 2 (Port 8002)                                      │   │
│  │ • App N (Port 800N)                                      │   │
│  └──────────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────────┐
│              Nginx Reverse Proxy (:80)                          │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ Routes traffic to running containers                     │   │
│  │ http://localhost/app1 → Container 1                      │   │
│  │ http://localhost/app2 → Container 2                      │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              Healer Daemon (Background)                         │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ • Periodic Health Checks (every 30s)                     │   │
│  │ • Detect Unhealthy Containers                            │   │
│  │ • Automatic Restart/Recovery                             │   │
│  │ • Metrics Export                                         │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Tech Stack

Component Technology
Backend Python 3.12, FastAPI, Uvicorn
Database PostgreSQL 15 (Dockerized)
Container Runtime Docker Engine, Docker SDK
Reverse Proxy Nginx
Observability Prometheus, Loguru
Version Control GitPython
Testing Pytest, pytest-asyncio, pytest-cov
Code Quality Black, isort, flake8, mypy, bandit
Containerization Docker, Docker Compose

Prerequisites


Quick Start (5 minutes)

1. Clone the Repository

git clone https://github.com/AlinaSHforwork/git-deploy-healer.git
cd git-deploy-healer

2. Create Environment File

cp .env.example .env

Edit .env with your configuration:

# .env
DEPLOYMENT_MODE=local
APP_PORT=8080

# Database
POSTGRES_USER=pypaas_user
POSTGRES_PASSWORD=secure_password_here
POSTGRES_DB=pypaas
POSTGRES_HOST=db
POSTGRES_PORT=5432
DATABASE_URL=postgresql://pypaas_user:secure_password_here@db:5432/pypaas

# Security (Generate with: python -c "import secrets; print(secrets.token_urlsafe(32))")
API_KEY=your-secret-api-key-here
GITHUB_WEBHOOK_SECRET=your-webhook-secret-here

# Logging
LOG_LEVEL=INFO

# Self-Healing
ENABLE_HEALER=true
HEALER_INTERVAL=30

3. Start the Stack

docker-compose up --build

This will start:

4. Access the Dashboard

Open your browser and navigate to:

5. Access Monitoring Stack

The monitoring stack (Prometheus + Grafana) starts automatically with the main stack:


Deploying Your First App

Option A: Using the API

curl -X POST "http://localhost:8080/api/deploy" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-secret-api-key-here" \
  -d '{
    "repo_url": "https://github.com/your-username/your-app.git",
    "app_name": "my-app",
    "branch": "main"
  }'

Option B: Using the Dashboard

  1. Navigate to http://localhost:8080/dashboard
  2. Click "Deploy New App"
  3. Enter repository URL, app name, and branch
  4. Click "Deploy"

Option C: Using the CLI

python main.py my-app /path/to/dockerfile/directory

Configuration Guide

Environment Variables

Variable Default Description
DEPLOYMENT_MODE local Deployment environment (local only)
APP_PORT 8080 FastAPI server port
DATABASE_URL - PostgreSQL connection string
API_KEY - API authentication key
GITHUB_WEBHOOK_SECRET - GitHub webhook secret
LOG_LEVEL INFO Logging level (DEBUG, INFO, WARNING, ERROR)
ENABLE_HEALER true Enable self-healing daemon
HEALER_INTERVAL 30 Health check interval (seconds)
WEBHOOK_RATE_LIMIT 10 Webhook rate limit (requests/minute)
HEALTH_CHECK_TIMEOUT 30 Container health check timeout (seconds)

See .env.example for complete configuration options.


Testing

Run All Tests

# Inside Docker
docker-compose exec app pytest tests/ -v

# Locally (with venv)
pip install -r requirements.txt
pytest tests/ -v

Run Specific Test Suites

# Unit tests only
pytest tests/unit/ -v

# Integration tests (requires RUN_INTEGRATION=1)
RUN_INTEGRATION=1 pytest tests/integration/ -v

# With coverage report
pytest tests/ --cov=core --cov=api --cov-report=html

Test Coverage

Current coverage: 80%+

View detailed coverage report:

open htmlcov/index.html

API Reference

Authentication

All API requests require the X-API-Key header:

curl -H "X-API-Key: your-secret-api-key-here" http://localhost:8080/api/...

Endpoints

Deploy Application

POST /api/deploy
Content-Type: application/json
X-API-Key: your-secret-api-key-here

{
  "repo_url": "https://github.com/user/repo.git",
  "app_name": "my-app",
  "branch": "main"
}

Response:

{
  "status": "success",
  "app_name": "my-app",
  "container_id": "abc123...",
  "port": 8001,
  "url": "http://localhost:8001"
}

Get Application Status

GET /api/apps/{app_name}
X-API-Key: your-secret-api-key-here

List All Applications

GET /api/apps
X-API-Key: your-secret-api-key-here

Get Application Logs

GET /api/apps/{app_name}/logs
X-API-Key: your-secret-api-key-here

Health Check

GET /health

For complete API documentation, visit: http://localhost:8080/docs


Monitoring & Observability

PyPaaS includes a built-in monitoring stack with Prometheus and Grafana that starts automatically with the main docker-compose.

Monitoring Architecture

┌──────────────────────────────────────────────────────────────┐
│                    PyPaaS App (:8080)                        │
│  ┌────────────────────────────────────────────────────────┐  │
│  │ • Prometheus Metrics Endpoint (/metrics)               │  │
│  │ • Deployment Counter                                   │  │
│  │ • Active Containers Gauge                              │  │
│  │ • Container Restart Counter                            │  │
│  └────────────────────────────────────────────────────────┘  │
└────────────────┬─────────────────────────────────────────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│         Prometheus (:9090)                                   │
│  ┌────────────────────────────────────────────────────────┐  │
│  │ • Scrapes metrics every 5 seconds                      │  │
│  │ • Stores time-series data                              │  │
│  │ • Evaluates alert rules                                │  │
│  │ • Provides query API                                   │  │
│  └────────────────────────────────────────────────────────┘  │
└────────────────┬─────────────────────────────────────────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│         Grafana (:3000)                                      │
│  ┌────────────────────────────────────────────────────────┐  │
│  │ • Auto-provisioned Prometheus datasource               │  │
│  │ • PyPaaS Overview Dashboard                            │  │
│  │ • Alert visualization                                  │  │
│  │ • Custom dashboard creation                            │  │
│  └────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────┘

Accessing Monitoring

Once the stack is running:

  1. Prometheus UIhttp://localhost:9090

    • Query metrics: up{job="pypaas-app"}
    • View scrape targets: Status → Targets
    • Check alert rules: Alerts
  2. Grafana Dashboardhttp://localhost:3000

    • Login: admin / admin
    • Pre-configured PyPaaS Overview dashboard
    • Create custom dashboards

Available Metrics

Metric Type Description
up{job="pypaas-app"} Gauge App availability (1=up, 0=down)
deployment_counter_total Counter Total deployments
active_containers_gauge Gauge Currently running containers
container_restarts_total Counter Total container restarts
http_requests_total Counter HTTP requests by status

Alert Rules

PyPaaS includes three pre-configured alert rules:

1. AppDown (Critical)

  • Condition: App metrics endpoint unreachable for >1 minute
  • Action: Immediate notification
  • Query: up{job="pypaas-app"} == 0

2. HighErrorRate (Warning)

  • Condition: Error rate >5% for >5 minutes
  • Action: Warning notification
  • Query: rate(http_requests_total{status=~"5.."}[5m]) > 0.05

3. ContainerRestartingFrequently (Warning)

  • Condition: Restart rate >0.1/min for >5 minutes
  • Action: Warning notification
  • Query: rate(container_restarts_total[15m]) > 0.1

Customizing Monitoring

Add Custom Metrics

In api/server.py:

from prometheus_client import Counter, Gauge

# Define custom metric
custom_counter = Counter('custom_metric_total', 'Description')

# Use in your code
custom_counter.inc()

Modify Alert Rules

Edit monitoring/alerts.yml:

groups:
  - name: custom-alerts
    interval: 30s
    rules:
      - alert: CustomAlert
        expr: your_metric > threshold
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Alert summary"
          description: "Alert description"

Reload Prometheus:

curl -X POST http://localhost:9090/-/reload

Create Custom Dashboards

  1. Open Grafana: http://localhost:3000
  2. Click +Dashboard
  3. Add panels with PromQL queries
  4. Save dashboard

Example queries:

# App uptime percentage
(1 - (rate(up{job="pypaas-app"}[5m]))) * 100

# Deployment rate
rate(deployment_counter_total[5m])

# Container count over time
active_containers_gauge

Monitoring Configuration Files

monitoring/
├── prometheus.yml              # Prometheus config (scrape targets, rules)
├── alerts.yml                  # Alert rules
├── grafana-datasources.yml     # Auto-provision Prometheus datasource
├── grafana-dashboards.yml      # Auto-provision dashboard loader
└── pypaas-dashboard.json       # Pre-built PyPaaS dashboard

Troubleshooting Monitoring

Prometheus not scraping metrics

# Check Prometheus targets
curl http://localhost:9090/api/v1/targets

# Verify app is exposing metrics
curl http://localhost:8080/metrics

# Check Prometheus logs
docker-compose logs prometheus

Grafana datasource not connecting

# Verify Prometheus is running
docker-compose ps prometheus

# Check Grafana logs
docker-compose logs grafana

# Manually add datasource:
# 1. Grafana → Configuration → Data Sources
# 2. Add Prometheus: http://prometheus:9090

Alerts not firing

# Check alert rules are loaded
curl http://localhost:9090/api/v1/rules

# Verify metric exists
curl 'http://localhost:9090/api/v1/query?query=up{job="pypaas-app"}'

# Check alert evaluation
docker-compose logs prometheus | grep -i alert

Webhook Integration (GitHub)

Setup GitHub Webhook

  1. Go to your repository settings
  2. Navigate to WebhooksAdd webhook
  3. Configure:
    • Payload URL: http://your-domain:8080/webhook
    • Content type: application/json
    • Secret: Use the value from GITHUB_WEBHOOK_SECRET in .env
    • Events: Select "Push events"
  4. Click Add webhook

Webhook Payload

When you push to your repository, GitHub will send:

{
  "ref": "refs/heads/main",
  "repository": {
    "url": "https://github.com/user/repo.git",
    "name": "repo"
  },
  "pusher": {
    "name": "username"
  }
}

PyPaaS will automatically:

  1. Verify the HMAC signature
  2. Extract repository URL and branch
  3. Trigger deployment
  4. Update Nginx routing

Troubleshooting

Database Connection Error

Error: psycopg2.OperationalError: could not connect to server

Solution:

# Check if db container is running
docker-compose ps

# Restart database
docker-compose restart db

# Verify DATABASE_URL in .env matches container config

Docker Build Fails

Error: docker.errors.BuildError: ...

Solution:

# Check if target repository has valid Dockerfile
# Verify repository is accessible
# Check Docker daemon is running
docker ps

# View build logs
docker-compose logs app

Webhook Returns 403/401

Error: Unauthorized or Forbidden

Solution:

# Verify API_KEY in .env
# Verify X-API-Key header in request
# Check GITHUB_WEBHOOK_SECRET matches GitHub webhook configuration

Nginx Configuration Error

Error: nginx: [emerg] ...

Solution:

# Check Nginx logs
docker-compose logs app | grep nginx

# Verify Nginx config syntax
docker-compose exec app nginx -t

# Restart Nginx
docker-compose exec app nginx -s reload

Port Already in Use

Error: bind: address already in use

Solution:

# Change APP_PORT in .env
APP_PORT=8081

# Or kill process using the port
lsof -i :8080
kill -9 <PID>

Development Guide

Local Development Setup

# Create virtual environment
python3.12 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Install pre-commit hooks
pre-commit install

# Run tests
pytest tests/ -v

# Start development server
uvicorn api.server:app --reload --host 0.0.0.0 --port 8080

Code Quality

# Format code
black .
isort .

# Lint
flake8 .

# Type checking
mypy core/ api/

# Security scan
bandit -r core/ api/

# All checks
pre-commit run --all-files

Project Structure

git-deploy-healer/
├── api/                      # FastAPI application
│   ├── auth.py              # Authentication & rate limiting
│   ├── server.py            # Main server & endpoints
│   ├── routes/
│   │   ├── webhook.py       # GitHub webhook handler
│   │   └── management.py    # App management endpoints
│   └── schemas.py           # Pydantic models
├── core/                     # Core business logic
│   ├── engine.py            # Docker container management
│   ├── git_manager.py       # Git operations
│   ├── healer.py            # Self-healing daemon
|   ├── proxy_manager.py     # Nginx configuration
│   ├── network.py           # Port management
│   ├── models.py            # SQLAlchemy ORM models
│   ├── security.py          # Security validation
│   └── secrets_manager.py   # Secret management
├── tests/                    # Test suite
│   ├── unit/                # Unit tests (88 tests)
│   ├── integration/         # Integration tests (34 tests)
│   └── conftest.py          # Pytest configuration
├── templates/               # HTML templates
│   ├── dashboard.html       # Web dashboard
│   └── app.conf.j2          # Nginx config template
├── config/                  # Configuration files
│   └── local.yaml           # Local environment config
├── docker-compose.yml       # Docker Compose setup
├── Dockerfile               # Container image
├── requirements.txt         # Python dependencies
├── main.py                  # CLI entry point
└── README.md               # This file

Security Considerations

⚠️ Important Security Notes

  1. Docker Socket Access

    • PyPaaS requires access to /var/run/docker.sock to manage containers
    • This grants elevated privileges – only run on trusted systems
    • Consider using rootless Docker for additional security
  2. API Key Management

    • Generate strong API keys: python -c "import secrets; print(secrets.token_urlsafe(32))"
    • Never commit .env files to version control
    • Rotate keys regularly in production
  3. Webhook Verification

    • All webhooks are verified using HMAC-SHA256
    • Ensure GITHUB_WEBHOOK_SECRET is strong and kept secret
  4. Database Security

    • Use strong PostgreSQL passwords
    • Consider using environment-specific credentials
    • Enable SSL for database connections in production
  5. Rate Limiting

    • API endpoints are rate-limited to prevent abuse
    • Webhook endpoints have per-IP rate limiting
    • Configure limits via environment variables

Performance Tips

Optimize Deployment Speed

  1. Use smaller base images

    FROM python:3.12-slim  # Instead of python:3.12
  2. Leverage Docker layer caching

    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
  3. Minimize image size

    RUN pip install --no-cache-dir -r requirements.txt

Monitor Performance

# View metrics
curl http://localhost:8080/metrics

# Check container resource usage
docker stats

# View application logs
docker-compose logs -f app

Known Limitations

  • ⚠️ Single-instance only – No horizontal scaling support yet
  • ⚠️ Local deployments only – AWS/cloud deployment planned for future
  • ⚠️ Sequential deployments – Builds run one at a time
  • ⚠️ No persistent volumes – Container data is lost on restart
  • ⚠️ Limited to 1000 apps – Port range 8000-9000

Roadmap

Planned Features

  • Horizontal scaling with Redis
  • AWS ECS/Fargate support
  • Blue-green deployments
  • Canary releases
  • Multi-tenancy support
  • Plugin system for extensibility

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please ensure:

  • Tests pass: pytest tests/ -v
  • Code is formatted: black . && isort .
  • No linting errors: flake8 .
  • Type hints are correct: mypy core/ api/

License

MIT License – see LICENSE file for details.


Acknowledgments

  • Inspired by Heroku, Kubernetes, and Dokku
  • Built with FastAPI, Docker, and PostgreSQL
  • Community contributions and feedback

Made with ❤️ by Alina Shvyryd

About

A Self-Healing PaaS Engine

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors