Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔭 Porthole

A self-updating app portal for Kubernetes. Porthole watches the Ingress resources in your cluster and turns every app that opts in (via a label) into a tile on a central website — name, description, icon and link included.

Built for teams that constantly deploy tools and prototypes and want a single place to share them: deploy your app with an Ingress, add one label and a few annotations, and it shows up on the portal within seconds. Delete the Ingress and it disappears again. No portal config files, no redeploys.

┌──────────────┐   watch Ingresses    ┌─────────────────────────┐
│   Porthole   │ ◄──────────────────  │  Kubernetes API server  │
│  (web + API) │  label selector:     └─────────────────────────┘
└──────┬───────┘  porthole/enabled=true
       │ serves
       ▼
  https://apps.example.com  →  tiles linking to every opted-in app

Adding an app to the portal

Your Deployment/Service stay completely ordinary. On the Ingress, add:

metadata:
  labels:
    porthole/enabled: "true"            # opt in
  annotations:
    porthole.io/name: "My Prototype"     # display name   (default: ingress name)
    porthole.io/description: "One-line pitch shown on the card"
    porthole.io/group: "Prototypes"      # section on the page (default: "Apps")
    porthole.io/icon: "🧪"               # emoji or image URL (default: 🚀)

Optional annotations:

Annotation Purpose
porthole.io/url Override the link (otherwise derived from the Ingress host/path; https when TLS is configured)
porthole.io/weight Sort order within a group, higher first (default 0)

A full copy-paste example lives in deploy/examples/whoami/.

Deploying Porthole

  1. Build and push the image:

    docker build -t <your-registry>/porthole:latest .
    docker push <your-registry>/porthole:latest
  2. Point the manifests at your environment: in deploy/base/deployment.yaml set the image, and in deploy/base/ingress.yaml set the host (and ingressClassName/TLS as needed).

  3. Apply:

    kubectl apply -k deploy/base

The manifests create a porthole namespace, a ServiceAccount with a read-only ClusterRole for Ingresses (get/list/watch — nothing else), the Deployment, a Service and the portal's own Ingress.

Extending the deployment

The manifests are plain Kustomize. To adapt them per environment, create an overlay instead of editing the base:

deploy/
  base/                  # what's in this repo
  overlays/
    prod/
      kustomization.yaml # resources: [../../base] + patches for host, image, replicas …

New apps never require touching this repo — they self-register through their own Ingress labels/annotations.

Configuration

Env var Default Purpose
PORTHOLE_TITLE Porthole Page title
PORTHOLE_LABEL_SELECTOR porthole/enabled=true Which Ingresses to show
PORTHOLE_ANNOTATION_PREFIX porthole.io Annotation prefix to read
PORTHOLE_NAMESPACES (all) Comma-separated namespace allowlist
PORTHOLE_DEMO false Serve built-in sample data (no cluster needed)

API

  • GET /api/apps — JSON list of all discovered apps
  • GET /healthz — liveness/readiness (reports watcher state)

Local development

python -m venv .venv && . .venv/bin/activate
pip install -r app/requirements.txt

# without a cluster (sample data):
PORTHOLE_DEMO=true uvicorn app.main:app --reload --port 8080

# against a real cluster (uses your kubeconfig):
uvicorn app.main:app --reload --port 8080

Then open http://localhost:8080.

Tests:

pip install pytest
pytest

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages