{"id":26925378,"url":"https://github.com/libops/ppb","last_synced_at":"2026-04-01T17:28:25.497Z","repository":{"id":284425861,"uuid":"951839112","full_name":"libops/ppb","owner":"libops","description":"A reverse proxy that automatically powers on Google Compute instances when traffic arrives","archived":false,"fork":false,"pushed_at":"2025-12-14T18:40:03.000Z","size":44,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-17T05:36:14.375Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/libops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-20T10:22:01.000Z","updated_at":"2025-12-14T18:39:58.000Z","dependencies_parsed_at":"2025-03-25T20:47:43.253Z","dependency_job_id":"3c114caf-0a1c-4878-a626-79153131481f","html_url":"https://github.com/libops/ppb","commit_stats":null,"previous_names":["libops/ppb"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/libops/ppb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libops%2Fppb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libops%2Fppb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libops%2Fppb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libops%2Fppb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/libops","download_url":"https://codeload.github.com/libops/ppb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libops%2Fppb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28336316,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-02T02:36:46.186Z","updated_at":"2026-01-12T06:28:13.723Z","avatar_url":"https://github.com/libops.png","language":"Go","readme":"# proxy power button (ppb)\n\nA reverse proxy that automatically powers on Google Compute Engine instances when traffic arrives.\n\nThis service is designed to run on **Google Cloud Run as an ingress layer** in front of your full application stack running on Google Compute Engine. When traffic hits your Cloud Run endpoint, PPB automatically powers on the target GCE VM (if needed) and proxies the request through. This architecture allows you to run complete application stacks on cost-effective VMs while only paying for Cloud Run when traffic actually arrives.\n\n## Architecture\n\n```\nInternet → Cloud Run (PPB) → Google Compute Engine (Full App Stack + lightsout)\n```\n\n- **Cloud Run**: Runs PPB as serverless ingress, scales to zero when no traffic\n- **GCE VM**: Runs your complete application (web server, database, etc.), can power off when idle\n- **PPB**: Powers on the VM when requests arrive, proxies traffic through with IP authorization\n- **lightsout**: Monitors activity and automatically shuts down VMs during idle periods (optional companion service)\n\n### Complete On-Demand Infrastructure\n\nPPB works seamlessly with [lightsout](https://github.com/libops/lightsout) to create a complete on-demand infrastructure solution:\n\n- **PPB handles startup**: Automatically powers on GCE instances when traffic arrives\n- **lightsout handles shutdown**: Monitors activity and automatically suspends instances during idle periods\n- **Cost optimization**: Only pay for compute resources when actively serving traffic\n\nDeploy lightsout alongside your application on the GCE instance to complete the automation cycle.\n\n## Cloud Run Behavior\n\nPPB runs as a reverse proxy with intelligent rate limiting:\n\n1. **Request handling**: Each authorized request attempts to power on the target machine if needed\n2. **Rate limiting**: Power-on attempts are rate limited with a configurable cooldown period (default 30s)\n3. **API protection**: Prevents hammering Google Cloud APIs during high traffic periods\n4. **IP Security**: Only requests from allowed IP ranges can trigger machine power-on attempts\n\nThis approach balances responsiveness with API efficiency - machines get powered on when traffic arrives, but multiple requests don't spam the Google Cloud APIs.\n\n## Use Case Examples\n\n- **Full Stack Applications**: Run complete LAMP/MEAN/Django stacks on GCE VMs with PPB as Cloud Run ingress\n- **Development Environments**: Keep expensive GPU/high-memory dev instances off until developers access them\n- **Legacy Applications**: Modernize access to monolithic applications that need full VM environments\n- **Cost Optimization**: Run databases, processing servers, or complete application environments that can idle\n- **Multi-service Backends**: Power on VMs running docker-compose stacks, Kubernetes clusters, or complex service meshes\n\n## Config\n\nCurrently, only backend services running on Google Compute Engine are supported.\n\n```yaml\ntype: google_compute_engine\nport: 80\nscheme: http\nallowedIps:\n  - 127.0.0.1/32\n  - 10.0.0.0/8\n  - 172.16.0.0/12\n  - 192.168.0.0/16\nipForwardedHeader: X-Forwarded-For # header to check for real client IP\nipDepth: 0 # depth in X-Forwarded-For chain\npowerOnCooldown: 30 # seconds between power-on attempts (default: 30)\n# metadata about the machine that will be turned on\nmachineMetadata:\n  project_id: foo\n  zone: us-central1-a\n  name: my-compute-instance-name\n  usePrivateIp: false # true for VPC-native setups\n# Optional proxy timeout configuration (defaults shown)\nproxyTimeouts:\n  dialTimeout: 120           # Connection dial timeout in seconds\n  keepAlive: 120            # TCP keep-alive timeout in seconds\n  idleConnTimeout: 90       # Idle connection timeout in seconds\n  tlsHandshakeTimeout: 10   # TLS handshake timeout in seconds\n  expectContinueTimeout: 1  # Expect: 100-continue timeout in seconds\n  maxIdleConns: 100        # Maximum idle connections\n\n```\n\n### Configuration Reference\n\n| Field                                   | Type     | Required | Default | Description                                                  |\n|-----------------------------------------|----------|----------|---------|--------------------------------------------------------------|\n| `type`                                  | string   | ✅       | -       | Backend type, currently only `google_compute_engine`         |\n| `port`                                  | int      | ✅       | -       | Port on target machine to proxy to                           |\n| `scheme`                                | string   | ✅       | -       | Protocol scheme (`http` or `https`)                          |\n| `allowedIps`                            | []string | ✅       | -       | CIDR ranges of IPs allowed to access the proxy               |\n| `ipForwardedHeader`                     | string   | ❌       | `\"\"`    | Header to check for real client IP (e.g., `X-Forwarded-For`) |\n| `ipDepth`                               | int      | ❌       | `0`     | Depth in forwarded header chain (0 = rightmost IP)           |\n| `powerOnCooldown`                       | int      | ❌       | `30`    | Seconds between power-on attempts (rate limiting)            |\n| `proxyTimeouts.dialTimeout`             | int      | ❌       | `120`   | Connection dial timeout in seconds                           |\n| `proxyTimeouts.keepAlive`               | int      | ❌       | `120`   | TCP keep-alive timeout in seconds                            |\n| `proxyTimeouts.idleConnTimeout`         | int      | ❌       | `90`    | Idle connection timeout in seconds                           |\n| `proxyTimeouts.tlsHandshakeTimeout`     | int      | ❌       | `10`    | TLS handshake timeout in seconds                             |\n| `proxyTimeouts.expectContinueTimeout`   | int      | ❌       | `1`     | Expect: 100-continue timeout in seconds                      |\n| `proxyTimeouts.maxIdleConns`            | int      | ❌       | `100`   | Maximum number of idle connections                           |\n| `machineMetadata.project_id`            | string   | ✅       | -       | Google Cloud project ID                                      |\n| `machineMetadata.zone`                  | string   | ✅       | -       | GCE zone (e.g., `us-central1-a`)                             |\n| `machineMetadata.name`                  | string   | ✅       | -       | GCE instance name                                            |\n| `machineMetadata.usePrivateIp`          | bool     | ❌       | `false` | Use private IP for VPC-native setups                         |\n\nDeploy this service on **Google Cloud Run** as the public endpoint for your application. Configure the `machineMetadata` to point to your GCE VM running the actual application stack. Only requests from allowed IPs will power on the VM and be proxied through. Set to `0.0.0.0/0` to allow any request to power on the machine.\n\n### Environment Variables\n\nPPB also supports these environment variables for runtime configuration:\n\n| Variable                         | Description                                  | Default                  |\n|----------------------------------|----------------------------------------------|--------------------------|\n| `PPB_YAML`                       | YAML configuration content (takes priority)  | -                        |\n| `PPB_CONFIG_PATH`                | Path to YAML configuration file              | /app/ppb.yaml            |\n| `LOG_LEVEL`                      | Log level (`DEBUG`, `INFO`, `WARN`, `ERROR`) | `INFO`                   |\n| `GOOGLE_APPLICATION_CREDENTIALS` | Path to service account JSON file            | Uses default credentials |\n\n## IAM Permissions\n\nThe Google Service Account (GSA) used by Cloud Run needs a custom IAM role with minimal permissions to control the target compute instance.\n\n### Custom Role Definition\n\nCreate a custom role with only the required permissions:\n\n```hcl\nresource \"google_project_iam_custom_role\" \"compute-start\" {\n  project = var.project\n\n  role_id     = \"startVM\"\n  title       = \"Start Compute Instance\"\n  description = \"Minimal permissions for PPB to control compute instances\"\n  permissions = [\n    \"compute.instances.start\",\n    \"compute.instances.resume\",\n    \"compute.instances.get\"\n  ]\n}\n```\n\n### Assign Role to Service Account\n\n```hcl\nresource \"google_project_iam_member\" \"ppb_service_account\" {\n  project = var.project\n  role    = google_project_iam_custom_role.compute-start.name\n  member  = \"serviceAccount:${var.service_account_email}\"\n}\n```\n\n### CLI Alternative\n\n```bash\ngcloud iam roles create startVM \\\n    --project=PROJECT_ID \\\n    --title=\"Start Compute Instance\" \\\n    --description=\"Minimal permissions for PPB to control compute instances\" \\\n    --permissions=\"compute.instances.start,compute.instances.resume,compute.instances.get\"\n\ngcloud projects add-iam-policy-binding PROJECT_ID \\\n    --member=\"serviceAccount:SERVICE_ACCOUNT_EMAIL\" \\\n    --role=\"projects/PROJECT_ID/roles/startVM\"\n```\n\n## Usage\n\n### Local development\n\n```bash\ndocker build -t us-docker.pkg.dev/your/gar/ppb:development .\ndocker run \\\n  -p 8080:8080 \\\n  -v $GOOGLE_APPLICATION_CREDENTIALS:/app/svc.json:ro \\\n  -v ./ppb.yaml:/app/ppb.yaml:ro \\\n  --env PPB_CONFIG_PATH=/app/ppb.yaml \\\n  --env GOOGLE_APPLICATION_CREDENTIALS=/app/svc.json \\\n  --env PRIVATE_IP=false \\\n  --env LOG_LEVEL=DEBUG \\\n  us-docker.pkg.dev/your/gar/ppb:development\n```\n\nPPB will act as a local ingress proxy to your GCE VM. Visit http://localhost:8080 and PPB will power on your target VM (if needed) then proxy your requests through to the application running on the VM.\n\n### Google Cloud Run Deployment\n\nDeploy PPB to Cloud Run and configure it as your application's public endpoint:\n\n```bash\ngcloud run deploy ppb \\\n  --image=us-docker.pkg.dev/your/gar/ppb:latest \\\n  --set-env-vars=\"PPB_CONFIG_PATH=/app/ppb.yaml\" \\\n  --service-account=your-ppb-service-account@project.iam.gserviceaccount.com \\\n  --allow-unauthenticated \\\n  --port=8080 \\\n  --region=us-central1\n```\n\nYour users will access `https://ppb-xxx-uc.a.run.app` which automatically powers on your GCE VM and proxies traffic through.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibops%2Fppb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibops%2Fppb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibops%2Fppb/lists"}