Introduction to ForgePod
ForgePod is your self-hosted Platform-as-a-Service powered by Podman — deploy containerized applications to your own infrastructure with a single API call. Multi-node cluster architecture with automatic load balancing, built-in monitoring, and zero Docker dependency.
Prerequisites
Prerequisites
- Ubuntu 24.04 LTS
- Root or sudo access
- At least 1 GB RAM + 10 GB disk per node
Control Plane
git clone <repo> forgepod && cd forgepod
sudo ./scripts/forgepod-cp-install.shThis installs:
- PostgreSQL + Redis
- Podman v5 (via APT pinning from Plucky/25.04)
- Buildah
- Traefik (latest binary)
- Python venv with FastAPI + dependencies
- Systemd services:
forgepod-api,forgepod-traefik
Verify Installation
systemctl status forgepod-api
systemctl status forgepod-traefik
curl http://localhost:9000/health
curl http://localhost:9000/docs # Swagger UIWorker Node
git clone <repo> forgepod && cd forgepod
sudo ./scripts/forgepod-worker-install.sh \
http://CONTROL_PLANE_IP:9000This installs:
- Podman v5 (APT pinning)
- Buildah
- Python venv with Flask + psutil
- Systemd services:
forgepod-podman-api,forgepod-worker
Verify Worker
systemctl status forgepod-worker
systemctl status forgepod-podman-api
# On control plane:
curl http://CONTROL_PLANE_IP:9000/nodesTroubleshooting
| Issue | Solution |
|---|---|
forgepod-api fails to start | Check PostgreSQL: systemctl status postgresql |
Worker not in /nodes | Check CONTROL_PLANE_URL env, verify connectivity |
| Podman v5 not installed | Run apt-cache policy podman to verify pinning |
| Traefik unreachable | Check ufw status, ensure port 80 is open |
Quick Start
Get ForgePod running with two commands:
git clone <repo> forgepod && cd forgepod
sudo ./scripts/forgepod-cp-install.shThen deploy your first app:
curl -X POST http://localhost:9000/deploy \
-H "Content-Type: application/json" \
-d '{"name": "demo", "image": "nginx", "replicas": 2}'Your app is now available at http://demo.apps.example.com
API Reference
Base URL: http://CONTROL_PLANE_IP:9000 · Interactive Swagger UI at /docs
| Method | Endpoint | Description |
|---|---|---|
| GET | /health | Liveness probe — returns {"status": "ok"} |
| GET | /readyz | Readiness probe — verifies database connection |
| POST | /deploy | Deploy a new app or update existing |
| POST | /scale | Scale app to desired replica count |
| GET | /apps | List all deployed applications |
| GET | /apps/{name}/logs | Stream aggregated logs |
| POST | /stop/{name} | Stop all containers, remove route |
| GET | /nodes | List worker nodes with status |
| POST | /internal/node/register | Register worker (internal) |
| POST | /internal/node/heartbeat/{hostname} | Heartbeat ping every 30s |
Deploy Example
Request
curl -X POST http://CP_IP:9000/deploy \
-H "Content-Type: application/json" \
-d '{
"name": "myapp",
"image": "nginx",
"container_port": 80,
"replicas": 2
}'Response
{
"status": "deployed",
"url": "http://myapp.apps.local",
"replicas_requested": 2,
"replicas_running": 2
}Scale Example
Request
curl -X POST http://CP_IP:9000/scale \
-H "Content-Type: application/json" \
-d '{"name": "myapp", "replicas": 4}'Response
{
"status": "scaled",
"app": "myapp",
"replicas": 4
}CLI Reference
Use forgepodctl to manage your cluster from the terminal:
python3 cli/forgepodctl.py deploy demo nginx --replicas 2 # Deploy
python3 cli/forgepodctl.py apps # List apps
python3 cli/forgepodctl.py nodes # List nodes
python3 cli/forgepodctl.py logs demo # View logs
python3 cli/forgepodctl.py stop demo # Stop appDNS & Cloudflare Setup
Point these DNS records to your Control Plane server's public IP:
| Type | Name | Content | Proxy |
|---|---|---|---|
A | api | SERVER_IP | Proxied ☁️ |
A | *.apps | SERVER_IP | Proxied ☁️ |
The wildcard *.apps.example.com allows Traefik to dynamically route traffic to each deployed app.
SSL/TLS Mode
Full (Strict) — encrypts traffic end-to-end between visitors ↔ Cloudflare ↔ server.
Environment Variable
# /etc/systemd/system/forgepod-api.service:
Environment="BASE_DOMAIN=apps.example.com"
sudo systemctl daemon-reload
sudo systemctl restart forgepod-apiLocal Development Setup (Mac)
Test the entire ForgePod flow on Mac without Ubuntu, using Podman (lighter than Docker Desktop).
1. Install Podman
make podman-setup
# Or manually:
brew install podman
podman machine init \
--cpus 2 --memory 2048
podman machine start2. Install Deps
make setup3. Run Services
# Terminal 1
make dev-infra
# Terminal 2
make dev-api
# Terminal 3
make dev-workerCheat Sheet
| Command | Function |
|---|---|
make podman-setup | Install Podman (one-time) |
make setup | Install Python deps (one-time) |
make dev-infra | Start PostgreSQL + Redis |
make dev-api | Start API server (port 9000) |
make dev-worker | Start mock worker (port 9001) |
make test | Run smoke tests |
make dev-stop | Stop all services |
make quality | Run all quality checks |
Uninstall
Works on both control plane and worker nodes:
sudo ./scripts/forgepod-uninstall.sh