homepage
This commit is contained in:
@@ -57,7 +57,7 @@ This repository contains the complete GitOps configuration for our Kubernetes cl
|
|||||||
|
|
||||||
### What's Inside
|
### What's Inside
|
||||||
|
|
||||||
- **Infrastructure Applications**: Traefik, Cert-Manager, Kyverno, Prometheus, Grafana, Loki, Tempo, Sealed Secrets
|
- **Infrastructure Applications**: Traefik, Cert-Manager, Kyverno, Prometheus, Grafana, Loki, Tempo, Sealed Secrets, Homepage (platform dashboard)
|
||||||
- **Business Applications**: MCP10X, MusicMan, Dot-AI Stack, ArgoCD MCP
|
- **Business Applications**: MCP10X, MusicMan, Dot-AI Stack, ArgoCD MCP
|
||||||
- **Policies**: Kyverno security policies for secret management, namespace controls, pod verification
|
- **Policies**: Kyverno security policies for secret management, namespace controls, pod verification
|
||||||
- **Monitoring**: Full observability stack with metrics, logs, traces, and alerting
|
- **Monitoring**: Full observability stack with metrics, logs, traces, and alerting
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ Bootstrap()
|
|||||||
Gitea()
|
Gitea()
|
||||||
{
|
{
|
||||||
echo "Installing secret..."
|
echo "Installing secret..."
|
||||||
kubectl apply -f "secrets/"
|
|
||||||
kubectl apply -f "private/${CLUSTER}/gitea-repo-main.yaml"
|
kubectl apply -f "private/${CLUSTER}/gitea-repo-main.yaml"
|
||||||
kubectl apply -f "private/${CLUSTER}/main.key"
|
kubectl apply -f "private/${CLUSTER}/main.key"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -725,6 +725,59 @@ TLS terminates at Traefik; ArgoCD runs in insecure mode behind the proxy.
|
|||||||
|
|
||||||
## Infrastructure Components
|
## Infrastructure Components
|
||||||
|
|
||||||
|
### Homepage (Platform Dashboard)
|
||||||
|
|
||||||
|
**Chart**: `jameswynn/homepage`
|
||||||
|
**Namespace**: `homepage`
|
||||||
|
**URL**: `https://start.forteapps.net`
|
||||||
|
|
||||||
|
Platform dashboard that auto-discovers deployed apps via Kubernetes service annotations.
|
||||||
|
|
||||||
|
**Discovery mechanism**: Services annotated with `gethomepage.dev/enabled: "true"` appear in the dashboard. Apps not deployed = annotations absent = not shown. Fully dynamic per environment.
|
||||||
|
|
||||||
|
**Annotated services**:
|
||||||
|
| Service | Namespace | Group | Widget |
|
||||||
|
|---------|-----------|-------|--------|
|
||||||
|
| `gitea-http` | `gitea` | DevOps | `gitea` |
|
||||||
|
| `argocd-server` | `argocd` | DevOps | `argocd` |
|
||||||
|
| `keycloak` | `keycloak` | Identity | none |
|
||||||
|
| `grafana` | `monitoring` | Monitoring | `grafana` |
|
||||||
|
| `karpor-server` | `karpor` | DevOps | none |
|
||||||
|
|
||||||
|
**Adding a new app**: Annotate the app's Service in its Helm values:
|
||||||
|
```yaml
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
gethomepage.dev/enabled: "true"
|
||||||
|
gethomepage.dev/name: "My App"
|
||||||
|
gethomepage.dev/description: "What it does"
|
||||||
|
gethomepage.dev/group: "GroupName"
|
||||||
|
gethomepage.dev/icon: "icon-name" # https://github.com/walkxcode/dashboard-icons
|
||||||
|
gethomepage.dev/href: "https://myapp.forteapps.net"
|
||||||
|
# Optional live widget:
|
||||||
|
gethomepage.dev/widget.type: "myapp"
|
||||||
|
gethomepage.dev/widget.url: "https://myapp.forteapps.net"
|
||||||
|
# gethomepage.dev/widget.key: "{{HOMEPAGE_VAR_MYAPP_TOKEN}}"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Widget API credentials**: Inject via env vars into the Homepage pod:
|
||||||
|
```yaml
|
||||||
|
# In homepage-values.yaml per environment
|
||||||
|
env:
|
||||||
|
- name: HOMEPAGE_VAR_GRAFANA_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: homepage-widget-credentials
|
||||||
|
key: grafana-token
|
||||||
|
```
|
||||||
|
Then reference as `gethomepage.dev/widget.key: "{{HOMEPAGE_VAR_GRAFANA_TOKEN}}"`.
|
||||||
|
|
||||||
|
**Values files**:
|
||||||
|
- `infra/values/base/homepage-values.yaml` — RBAC, kubernetes mode, layout
|
||||||
|
- `infra/values/{env}/homepage-values.yaml` — hostname per environment
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Traefik
|
### Traefik
|
||||||
|
|
||||||
**Chart**: `traefik/traefik`
|
**Chart**: `traefik/traefik`
|
||||||
|
|||||||
21
infra/base/homepage/homepage-extra-rbac.yaml
Normal file
21
infra/base/homepage/homepage-extra-rbac.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: homepage-services-reader
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["services"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: homepage-services-reader
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: homepage-services-reader
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: homepage
|
||||||
|
namespace: homepage
|
||||||
16
infra/base/homepage/homepage-widget-credentials-sealed.yaml
Normal file
16
infra/base/homepage/homepage-widget-credentials-sealed.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
apiVersion: bitnami.com/v1alpha1
|
||||||
|
kind: SealedSecret
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: homepage-widget-credentials
|
||||||
|
namespace: homepage
|
||||||
|
spec:
|
||||||
|
encryptedData:
|
||||||
|
HOMEPAGE_VAR_GITEA_TOKEN: AgAVN1C931EQpn+sodr3CpjlhORfJVTW8aUr+pGZQb+65Pb8QLGeVGVa7Jv60gDJUX3r+93/jMrEbCOeDL6I4qCz/V35wMCxFZLnXIdkmto0W4MKt6cK8To1/OP7EhQJOGBlSuOFsrwoy+HDtvLIqmyF0nrxhTusm9/NHrw+gCVwSTPhiAX1MCuSOSRWpbXvyNphW8j7aqUaV6ixDt424Fe4alEIShYELcS3EX/VPgsf2p2bhvBRCQOh3LEprkuxSFMuPfCBk06TPTbIN4saNVm0Ke0zW/pxkVNSiIxEnKjOmpPJtacsfWN7du+nQbx276G2qvWrf+iawJVq0Z/SLikA/NUFBL6EjSRfgE3cSOri8sbxsd0AycsFGyp98EM29wE+WOQl52M/lwl02EmCivqkICSO7Jp9pM1ScbmRMa5vcnupsGbVDxhRKLqxhAskt/BXDkRzvHN31gH3YmelES3JuqNMHV0urFxmX2oOX9Pxbtv63csc+zhy1Ui5aoex7TPnLdk7kYLSAE2MSrzT6wHvVhBC5kNnDYVrLehvJrT+eNh0MOLx2wkuJmIOxRAGUyNi5DfDnP6qnvj2aefEymLuOXAIUXH8DbeBtrjsd74HX2hhIfBlPkXvhJR3ks7i5RXjK2/YYHkgJ+nJoW80S9N7ciaRy103g74TNJZt6QzzL5Vb80qZ6yQOD4G081KmTLDmhHjJVIIv9M3nLh2s0IeBV3/Z5qHZmtjN7sSaKAn4MIr5FaH9quhx
|
||||||
|
HOMEPAGE_VAR_GRAFANA_TOKEN: AgBloBlOlP+R/4VizE1CGpj0wyiwU14BemAnuUpld7OvOGc67dwfDPyponkQXjAZg3UU2cZ70A51WUAuVlAr+25Ktlf/FW2OBqj+1BJOCqMMyu+kv026yjX2aB8dKGzlTxgF8aji+j1mC8vP3vvmgI4Zf2HQAH7uFwLfeo8+QnV5EyhcExSS0xDne+VtOP9jNXbPRayry0DdyRVtaeKAiZacO+45oAJWszWOwmoMTg9FZQkLjER6Q0tyI6NnoNObsFCnh56chZTdzBOYtmPnwld1bP2FjoJDqn8AfRwbPTIj7t0eFP7WLUO7GQKpxVl+pFwJLb5xCOw2+HNtp1BhNCu7icuc0P88IlvwzkbN0lXJbYigVOzyjEo8f/al1DXPM4WaB/Nqmr7Mtt8KTRh2WMVTgiX5jsu25D0rGDvY9gqfBBqswkRhCLsG0v0EN32zXj1/52KYdmB7pk/+2lMwSaGMS11MOenHeU1Z95fGxm9f3EGF0E8xlFr4FowgsNwr+tJQqpM0bT/4mZnaQbGWtKPFizMtsfQFm+rHFcNCrGaOuecslmiIJs8lTm18KlrncsGfxNS64tVXk+LvydU0rwybvpg2rQjEWtAl1IQsaaiz96OAlYxxK1MGxN7KE6F8R4kfnWTZ5Fs1KMmd/DOIVBXyCbqXxk8pbekmaIeNSfv92JNZ0QNJWsBa2vgQ24WI2pb4XiR0BvtLpt3BVlZUcSK92SzUblWmYWVMwHYCJkEeEUV1PhYEmyiN+V/Kq5Qb
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: homepage-widget-credentials
|
||||||
|
namespace: homepage
|
||||||
43
infra/base/homepage/homepage.yaml
Normal file
43
infra/base/homepage/homepage.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: homepage
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "3"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: homepage
|
||||||
|
app.kubernetes.io/part-of: platform
|
||||||
|
app.kubernetes.io/managed-by: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
|
||||||
|
sources:
|
||||||
|
- repoURL: https://jameswynn.github.io/helm-charts
|
||||||
|
chart: homepage
|
||||||
|
targetRevision: "2.1.0"
|
||||||
|
helm:
|
||||||
|
releaseName: homepage
|
||||||
|
valueFiles:
|
||||||
|
- $values/infra/values/base/homepage-values.yaml
|
||||||
|
- $values/infra/values/upc-dev/homepage-values.yaml
|
||||||
|
|
||||||
|
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
|
||||||
|
targetRevision: HEAD
|
||||||
|
ref: values
|
||||||
|
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: homepage
|
||||||
|
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
allowEmpty: false
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- Validate=true
|
||||||
|
- ServerSideApply=true
|
||||||
6
infra/base/homepage/kustomization.yaml
Normal file
6
infra/base/homepage/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- homepage.yaml
|
||||||
|
- homepage-widget-credentials-sealed.yaml
|
||||||
|
- homepage-extra-rbac.yaml
|
||||||
@@ -21,3 +21,4 @@ resources:
|
|||||||
- grafana-dashboards
|
- grafana-dashboards
|
||||||
- karpor
|
- karpor
|
||||||
- databunker
|
- databunker
|
||||||
|
- homepage
|
||||||
|
|||||||
@@ -13,9 +13,19 @@ resources:
|
|||||||
- ../../base/prometheus
|
- ../../base/prometheus
|
||||||
- ../../base/sealedsecrets
|
- ../../base/sealedsecrets
|
||||||
- ../../base/tempo
|
- ../../base/tempo
|
||||||
|
- ../../base/homepage
|
||||||
- ../../base/traefik-application
|
- ../../base/traefik-application
|
||||||
|
|
||||||
patches:
|
patches:
|
||||||
|
# Homepage: swap upc-dev → aks-dev
|
||||||
|
- target:
|
||||||
|
kind: Application
|
||||||
|
name: homepage
|
||||||
|
patch: |
|
||||||
|
- op: replace
|
||||||
|
path: /spec/sources/0/helm/valueFiles/1
|
||||||
|
value: $values/infra/values/aks-dev/homepage-values.yaml
|
||||||
|
|
||||||
# Traefik: swap upc-dev → aks-dev
|
# Traefik: swap upc-dev → aks-dev
|
||||||
- target:
|
- target:
|
||||||
kind: Application
|
kind: Application
|
||||||
|
|||||||
15
infra/values/aks-dev/homepage-values.yaml
Normal file
15
infra/values/aks-dev/homepage-values.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
ingress:
|
||||||
|
main:
|
||||||
|
enabled: true
|
||||||
|
ingressClassName: traefik
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
hosts:
|
||||||
|
- host: start.forteapps.net
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: homepage-tls
|
||||||
|
hosts:
|
||||||
|
- start.forteapps.net
|
||||||
@@ -35,6 +35,12 @@ server:
|
|||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
annotations:
|
annotations:
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
gethomepage.dev/enabled: "true"
|
||||||
|
gethomepage.dev/name: "ArgoCD"
|
||||||
|
gethomepage.dev/description: "GitOps continuous delivery"
|
||||||
|
gethomepage.dev/group: "DevOps"
|
||||||
|
gethomepage.dev/icon: "argo-cd"
|
||||||
|
gethomepage.dev/href: "https://argocd.forteapps.net"
|
||||||
tls: true
|
tls: true
|
||||||
extraArgs:
|
extraArgs:
|
||||||
- --insecure
|
- --insecure
|
||||||
|
|||||||
@@ -114,6 +114,15 @@ ingress:
|
|||||||
className: traefik
|
className: traefik
|
||||||
annotations:
|
annotations:
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
gethomepage.dev/enabled: "true"
|
||||||
|
gethomepage.dev/name: "Gitea"
|
||||||
|
gethomepage.dev/description: "Git hosting & CI/CD"
|
||||||
|
gethomepage.dev/group: "DevOps"
|
||||||
|
gethomepage.dev/icon: "gitea"
|
||||||
|
gethomepage.dev/href: "https://git.forteapps.net"
|
||||||
|
gethomepage.dev/widget.type: "gitea"
|
||||||
|
gethomepage.dev/widget.url: "https://git.forteapps.net"
|
||||||
|
gethomepage.dev/widget.key: "{{HOMEPAGE_VAR_GITEA_TOKEN}}"
|
||||||
hosts:
|
hosts:
|
||||||
- host: git.forteapps.net
|
- host: git.forteapps.net
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@@ -3,11 +3,21 @@ ingress:
|
|||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
annotations:
|
annotations:
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
gethomepage.dev/enabled: "true"
|
||||||
|
gethomepage.dev/name: "Grafana"
|
||||||
|
gethomepage.dev/description: "Metrics & observability dashboards"
|
||||||
|
gethomepage.dev/group: "Monitoring"
|
||||||
|
gethomepage.dev/icon: "grafana"
|
||||||
|
gethomepage.dev/href: "https://grafana.forteapps.net"
|
||||||
tls:
|
tls:
|
||||||
- secretName: grafana-tls
|
- secretName: grafana-tls
|
||||||
hosts:
|
hosts:
|
||||||
- grafana.forteapps.net
|
- grafana.forteapps.net
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 1Gi
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 50m
|
cpu: 50m
|
||||||
|
|||||||
73
infra/values/base/homepage-values.yaml
Normal file
73
infra/values/base/homepage-values.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Homepage Helm Values
|
||||||
|
# Chart: jameswynn/homepage — https://gethomepage.dev
|
||||||
|
# Discovery: K8s service annotations (gethomepage.dev/*)
|
||||||
|
# Each deployed app annotates its own Service — apps not deployed = not visible.
|
||||||
|
|
||||||
|
# RBAC ClusterRole — required for cluster-wide service annotation scanning
|
||||||
|
enableRbac: true
|
||||||
|
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
name: homepage
|
||||||
|
|
||||||
|
config:
|
||||||
|
# Scan all namespaces for services with gethomepage.dev/enabled: "true"
|
||||||
|
kubernetes:
|
||||||
|
mode: cluster
|
||||||
|
traefik: true
|
||||||
|
|
||||||
|
settings:
|
||||||
|
title: "Forte Platform"
|
||||||
|
headerStyle: clean
|
||||||
|
layout:
|
||||||
|
Apps:
|
||||||
|
style: row
|
||||||
|
columns: 3
|
||||||
|
Identity:
|
||||||
|
style: row
|
||||||
|
columns: 2
|
||||||
|
DevOps:
|
||||||
|
style: row
|
||||||
|
columns: 2
|
||||||
|
Monitoring:
|
||||||
|
style: row
|
||||||
|
columns: 1
|
||||||
|
|
||||||
|
# Top-of-page cluster overview widget
|
||||||
|
widgets:
|
||||||
|
- kubernetes:
|
||||||
|
cluster:
|
||||||
|
show: true
|
||||||
|
cpu: true
|
||||||
|
memory: true
|
||||||
|
showLabel: true
|
||||||
|
label: "Cluster"
|
||||||
|
nodes:
|
||||||
|
show: true
|
||||||
|
cpu: true
|
||||||
|
memory: true
|
||||||
|
showLabel: true
|
||||||
|
# In-cluster entries come from K8s service annotations.
|
||||||
|
# External (out-of-cluster) services are listed here statically.
|
||||||
|
bookmarks: []
|
||||||
|
services:
|
||||||
|
- Apps:
|
||||||
|
- Forte Feedback:
|
||||||
|
href: https://feedback.forteapps.net
|
||||||
|
description: Fortes internal feedback app
|
||||||
|
icon: forte
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
env:
|
||||||
|
- name: HOMEPAGE_ALLOWED_HOSTS
|
||||||
|
value: start.forteapps.net
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: homepage-widget-credentials
|
||||||
@@ -18,6 +18,12 @@ ingress:
|
|||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
annotations:
|
annotations:
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
gethomepage.dev/enabled: "true"
|
||||||
|
gethomepage.dev/name: "Keycloak"
|
||||||
|
gethomepage.dev/description: "Identity & access management"
|
||||||
|
gethomepage.dev/group: "Identity"
|
||||||
|
gethomepage.dev/icon: "keycloak"
|
||||||
|
gethomepage.dev/href: "https://id.forteapps.net"
|
||||||
|
|
||||||
metrics:
|
metrics:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
ingress:
|
ingress:
|
||||||
enabled: true
|
enabled: true
|
||||||
host: databunker.forteapps.net
|
host: databunker.forteapps.net
|
||||||
|
annotations:
|
||||||
|
gethomepage.dev/enabled: "true"
|
||||||
|
gethomepage.dev/name: "Databunker"
|
||||||
|
gethomepage.dev/description: "Secure Database for PII and PCI Records"
|
||||||
|
gethomepage.dev/group: "Identity"
|
||||||
|
gethomepage.dev/icon: "adminer"
|
||||||
|
gethomepage.dev/href: "https://databunker.forteapps.net"
|
||||||
|
|||||||
15
infra/values/upc-dev/homepage-values.yaml
Normal file
15
infra/values/upc-dev/homepage-values.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
ingress:
|
||||||
|
main:
|
||||||
|
enabled: true
|
||||||
|
ingressClassName: traefik
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
hosts:
|
||||||
|
- host: start.forteapps.net
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: homepage-tls
|
||||||
|
hosts:
|
||||||
|
- start.forteapps.net
|
||||||
Submodule shared-prompts updated: c5bc55b3d7...b79858d73c
Reference in New Issue
Block a user