Homepage
Prerequisites#
This guide assumes you have the following prerequisites in place:
Homepage#
A modern, fully static, fast, secure fully proxied, highly customizable application dashboard with integrations for over 100 services and translations into multiple languages. Easily configured via YAML files or through docker label discovery.
Installation#
- Create the following directory structure for Homepage:
homepage/ ├── secret.yml ├── clusterole.yml ├── cm.yml ├── ingress.yml ├── pvc.yml ├── svc-account.yml ├── svc-account-token.yml ├── svc.yml └── homepage.yml - This secret will contain all api-keys and passwords for the services you want to integrate with Homepage. You can use the following template for your
secret-tmp.yml:apiVersion: v1 kind: Secret metadata: name: homepage-secrets namespace: monitoring type: Opaque data: BAZARR_API_KEY: <base64-encoded-api-key> SONARR_API_KEY: <base64-encoded-password> # Add more services as needed- Encrypt the secret using Sealed Secrets like so:
kubeseal -o yaml < secret-tmp.yml > secret.yml && \ rm secret-tmp.yml
- Encrypt the secret using Sealed Secrets like so:
- The
clusterole.ymlfile will define the necessary permissions for Homepage to access the Kubernetes API. You can use the following template:--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: homepage labels: app.kubernetes.io/name: homepage rules: - apiGroups: - "" resources: - namespaces - pods - nodes verbs: - get - list - apiGroups: - extensions - networking.k8s.io resources: - ingresses verbs: - get - list - apiGroups: - traefik.io resources: - ingressroutes verbs: - get - list - apiGroups: - gateway.networking.k8s.io resources: - httproutes - gateways verbs: - get - list - apiGroups: - metrics.k8s.io resources: - nodes - pods verbs: - get - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: homepage labels: app.kubernetes.io/name: homepage roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: homepage subjects: - kind: ServiceAccount name: homepage namespace: monitoring - The
cm.ymlfile will contain the configuration for Homepage, including the services you want to integrate. This is an example configuration:--- apiVersion: v1 kind: ConfigMap metadata: name: homepage namespace: monitoring labels: app.kubernetes.io/name: homepage data: docker.yaml: | "" bookmarks.yaml: | "" custom.css: | "" custom.js: | "" kubernetes.yaml: | mode: cluster widgets.yaml: | - kubernetes: cluster: show: true cpu: true memory: true showLabel: true label: "k3s-cluster" nodes: show: true - longhorn: expanded: true total: true labels: true nodes: false settings.yaml: | providers: longhorn: url: http://longhorn-frontend.longhorn-system.svc.cluster.local:80 services.yaml: | - Apps: - Sonarr: href: https://sonarr.example.com description: series icon: sonarr.png namespace: arr-stack podSelector: app=sonarr app: sonarr widget: type: sonarr url: http://sonarr-service.arr-stack.svc.cluster.local:8989 key: "${SONARR_API_KEY}" - Bazarr: href: https://bazarr.example.com description: subtitles icon: bazarr.png namespace: arr-stack podSelector: app=bazarr app: bazarr widget: type: bazarr url: http://bazarr-service.arr-stack.svc.cluster.local:6767 key: "${BAZARR_API_KEY}" - Add the following to
ingress.yml:--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: homepage-ingress namespace: monitoring annotations: cert-manager.io/cluster-issuer: letsencrypt-cloudflare traefik.ingress.kubernetes.io/router.middlewares: tools-authelia@kubernetescrd traefik.ingress.kubernetes.io/router.entrypoints: websecure spec: ingressClassName: traefik tls: - hosts: - home.example.com secretName: homepage-tls rules: - host: home.example.com http: paths: - path: / pathType: Prefix backend: service: name: homepage-service port: number: 3000 - The
pvc.ymlfile will define the persistent volume claim for Homepage images.--- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: homepage-longhorn namespace: monitoring spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 100Mi storageClassName: longhorn - The
svc-account.ymlfile will create a service account for Homepage:--- apiVersion: v1 kind: ServiceAccount metadata: name: homepage namespace: monitoring labels: app.kubernetes.io/name: homepage secrets: - name: homepage - The
svc-account-token.ymlfile will create a secret for the service account token:--- apiVersion: v1 kind: Secret type: kubernetes.io/service-account-token metadata: name: homepage namespace: monitoring labels: app.kubernetes.io/name: homepage annotations: kubernetes.io/service-account.name: homepage - Create a
svc.ymlfile to define the service for Homepage:--- apiVersion: v1 kind: Service metadata: name: homepage-service namespace: monitoring spec: selector: app.kubernetes.io/name: homepage ports: - port: 3000 targetPort: 3000 - Finally, the
homepage.ymlfile will define the deployment for Homepage. This deployment will substitute the api-keys from the secret into the configmap.--- apiVersion: apps/v1 kind: Deployment metadata: name: homepage namespace: monitoring labels: app.kubernetes.io/name: homepage spec: revisionHistoryLimit: 3 replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/name: homepage template: metadata: labels: app.kubernetes.io/name: homepage spec: serviceAccountName: homepage automountServiceAccountToken: true enableServiceLinks: true initContainers: - name: substitute-config image: alpine envFrom: - secretRef: name: homepage-secrets command: - "sh" - "-c" - apk add gettext && envsubst < /mnt/init/services.yaml > /mnt/services.yaml volumeMounts: - name: homepage-config mountPath: /mnt/init/services.yaml subPath: services.yaml - name: tmp mountPath: /mnt subPath: services.yaml containers: - name: homepage image: "ghcr.io/gethomepage/homepage:v1.10.1" imagePullPolicy: IfNotPresent env: - name: HOMEPAGE_ALLOWED_HOSTS value: "home.example.com" ports: - name: http containerPort: 3000 protocol: TCP volumeMounts: - mountPath: /app/config/custom.js name: homepage-config subPath: custom.js - mountPath: /app/config/custom.css name: homepage-config subPath: custom.css - mountPath: /app/config/bookmarks.yaml name: homepage-config subPath: bookmarks.yaml - mountPath: /app/config/docker.yaml name: homepage-config subPath: docker.yaml - mountPath: /app/config/kubernetes.yaml name: homepage-config subPath: kubernetes.yaml - mountPath: /app/config name: tmp subPath: services.yaml - mountPath: /app/config/settings.yaml name: homepage-config subPath: settings.yaml - mountPath: /app/config/widgets.yaml name: homepage-config subPath: widgets.yaml - mountPath: /app/config/logs name: logs - mountPath: /app/public/images name: images volumes: - name: homepage-config configMap: name: homepage - name: images persistentVolumeClaim: claimName: homepage-longhorn - name: logs emptyDir: {} - name: tmp emptyDir: {} - Commit and push all the files to your repository. Flux will automatically deploy Homepage to your cluster.