feat(k8s/homepage): add homepage stack
This commit is contained in:
111
kubernetes/app/homepage/configmap.yaml
Normal file
111
kubernetes/app/homepage/configmap.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: homepage-config
|
||||
namespace: homepage
|
||||
data:
|
||||
settings.yaml: |
|
||||
---
|
||||
title: Home
|
||||
theme: light
|
||||
color: slate
|
||||
headerStyle: clean
|
||||
layout:
|
||||
# Define your layout sections here
|
||||
|
||||
services.yaml: |
|
||||
---
|
||||
- Media:
|
||||
- Jellyfin:
|
||||
icon: jellyfin.png
|
||||
href: https://${JELLYFIN_HOST}
|
||||
description: Media system
|
||||
widget:
|
||||
type: jellyfin
|
||||
url: https://${JELLYFIN_HOST}
|
||||
key: "{{HOMEPAGE_VAR_JELLYFIN_API_KEY}}"
|
||||
enableBlocks: true
|
||||
enableUser: true
|
||||
enableMediaControl: false
|
||||
showEpisodeNumber: true
|
||||
expandOneStreamToTwoRows: false
|
||||
- Sonarr:
|
||||
icon: sonarr.png
|
||||
href: https://${SONARR_HOST}
|
||||
description: Series management
|
||||
widget:
|
||||
type: sonarr
|
||||
url: https://${SONARR_HOST}
|
||||
username: "{{HOMEPAGE_VAR_SONARR_USERNAME}}"
|
||||
password: "{{HOMEPAGE_VAR_SONARR_PASSWORD}}"
|
||||
key: "{{HOMEPAGE_VAR_SONARR_API_KEY}}"
|
||||
- Radarr:
|
||||
icon: radarr.png
|
||||
href: https://${RADARR_HOST}
|
||||
description: Movie management
|
||||
widget:
|
||||
type: radarr
|
||||
url: https://${RADARR_HOST}
|
||||
username: "{{HOMEPAGE_VAR_RADARR_USERNAME}}"
|
||||
password: "{{HOMEPAGE_VAR_RADARR_PASSWORD}}"
|
||||
key: "{{HOMEPAGE_VAR_RADARR_API_KEY}}"
|
||||
- qBittorrent:
|
||||
icon: qbittorrent.png
|
||||
href: https://${QBITTORRENT_HOST}
|
||||
description: Torrent download
|
||||
|
||||
- Services:
|
||||
- Home Assistant:
|
||||
icon: home-assistant.png
|
||||
href: "{{HOMEPAGE_VAR_HOMEASSISTANT_URL}}"
|
||||
ping: "{{HOMEPAGE_VAR_HOMEASSISTANT_URL}}"
|
||||
description: Home Automation server
|
||||
widget:
|
||||
type: homeassistant
|
||||
url: "{{HOMEPAGE_VAR_HOMEASSISTANT_URL}}"
|
||||
key: "{{HOMEPAGE_VAR_HOMEASSISTANT_API_KEY}}"
|
||||
custom:
|
||||
- state: sensor.system_monitor_processor_temperature
|
||||
label: CPU
|
||||
- state: sensor.system_monitor_processor_use
|
||||
label: CPU
|
||||
- state: sensor.system_monitor_memory_usage
|
||||
label: MEM
|
||||
- state: sensor.system_monitor_swap_usage
|
||||
label: SWAP
|
||||
- Immich:
|
||||
icon: immich.png
|
||||
href: https://${IMMICH_HOST}
|
||||
description: Photo gallery
|
||||
widget:
|
||||
type: immich
|
||||
url: https://${IMMICH_HOST}
|
||||
key: "{{HOMEPAGE_VAR_IMMICH_API_KEY}}"
|
||||
version: 2
|
||||
- Paperless-ngx:
|
||||
icon: paperless-ngx.png
|
||||
href: https://${PAPERLESS_HOST}/
|
||||
description: Documents storage
|
||||
- Grocy:
|
||||
icon: grocy.png
|
||||
href: https://${GROCY_HOST}/
|
||||
description: Chores and inventory tracker
|
||||
|
||||
widgets.yaml: |
|
||||
---
|
||||
- resources:
|
||||
cpu: true
|
||||
memory: true
|
||||
disk: /
|
||||
- datetime:
|
||||
text_size: xl
|
||||
format:
|
||||
timeStyle: short
|
||||
|
||||
bookmarks.yaml: |
|
||||
---
|
||||
# Define your bookmarks here
|
||||
|
||||
kubernetes.yaml: |
|
||||
---
|
||||
mode: cluster
|
||||
75
kubernetes/app/homepage/deployment.yaml
Normal file
75
kubernetes/app/homepage/deployment.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
labels:
|
||||
app: homepage
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: homepage
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: homepage
|
||||
spec:
|
||||
serviceAccountName: homepage
|
||||
securityContext:
|
||||
# runAsNonRoot omitted — homepage image starts as root; non-root requires PUID/PGID entrypoint setup
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: homepage
|
||||
image: ghcr.io/gethomepage/homepage:v1.10.1
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: http
|
||||
protocol: TCP
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: homepage-credentials
|
||||
env:
|
||||
- name: HOMEPAGE_ALLOWED_HOSTS
|
||||
value: "${HOMEPAGE_HOST}"
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /app/config/settings.yaml
|
||||
subPath: settings.yaml
|
||||
- name: config
|
||||
mountPath: /app/config/services.yaml
|
||||
subPath: services.yaml
|
||||
- name: config
|
||||
mountPath: /app/config/widgets.yaml
|
||||
subPath: widgets.yaml
|
||||
- name: config
|
||||
mountPath: /app/config/bookmarks.yaml
|
||||
subPath: bookmarks.yaml
|
||||
- name: config
|
||||
mountPath: /app/config/kubernetes.yaml
|
||||
subPath: kubernetes.yaml
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
port: 3000
|
||||
path: /
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 3000
|
||||
path: /
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: homepage-config
|
||||
24
kubernetes/app/homepage/ingress.yaml
Normal file
24
kubernetes/app/homepage/ingress.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
traefik.ingress.kubernetes.io/router.middlewares: authelia-chain-authelia-authelia-auth@kubernetescrd
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- ${HOMEPAGE_HOST}
|
||||
secretName: homepage-tls
|
||||
rules:
|
||||
- host: ${HOMEPAGE_HOST}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: homepage
|
||||
port:
|
||||
number: 3000
|
||||
4
kubernetes/app/homepage/namespace.yaml
Normal file
4
kubernetes/app/homepage/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: homepage
|
||||
26
kubernetes/app/homepage/networkpolicy.yaml
Normal file
26
kubernetes/app/homepage/networkpolicy.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny-ingress
|
||||
namespace: homepage
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-ingress-controller
|
||||
namespace: homepage
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: homepage
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: traefik
|
||||
36
kubernetes/app/homepage/secret.sops.yaml
Normal file
36
kubernetes/app/homepage/secret.sops.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: homepage-credentials
|
||||
namespace: homepage
|
||||
stringData:
|
||||
#ENC[AES256_GCM,data:kRiN5JB/ca3N,iv:0sNhC4i6zxUf/0VMKt98ynvRqvwn87vRyNcq6RJTIHs=,tag:s/8/EvIBUaWXIg17r+Iaig==,type:comment]
|
||||
HOMEPAGE_VAR_JELLYFIN_API_KEY: ENC[AES256_GCM,data:G0l+DMIr56w00qk/66v5SVl/hJnpvfwj6LU5wr73ExM=,iv:smVHXj9rGTxULO+iRcnYsu6pQCU0Uu8DJwwWXQyMzRI=,tag:zg3ggPUA9jBCbBmuIuys2g==,type:str]
|
||||
#ENC[AES256_GCM,data:+2tpnodG4A==,iv:Jbi23B2V815IC2DHgdZ3JByGP8Pbq8Si4OzAdZg2tfE=,tag:FOKsVAq7MGMy5QbZdzv6Eg==,type:comment]
|
||||
HOMEPAGE_VAR_SONARR_USERNAME: ENC[AES256_GCM,data:ZqKdBJH1gpQ=,iv:bPjBYxyBr25k58X5gFmQDsFcwRHnHsyJaD1toqFC9hM=,tag:CaxY829WQ4LTzQOG48Or/w==,type:str]
|
||||
HOMEPAGE_VAR_SONARR_PASSWORD: ENC[AES256_GCM,data:tCFmcRaKylbP33O5VX3jRcsw5To8fPdZXpqmJ7aW5RI+EXr4SgPJCD5hcMY7g2qqGXL6ZUyAe4GPj+cyNkpj1g==,iv:LKeAbrS04u+Ip3IuTGfEc6Ee0SVLkLAcM5BCMP8JQuk=,tag:sQPSG5+SMI2buxG1WxYL3A==,type:str]
|
||||
HOMEPAGE_VAR_SONARR_API_KEY: ENC[AES256_GCM,data:h1nmDPRl9APUaMBL7SMxJbudG/BAwxhNxmN8ux76ri4=,iv:ssekkf4tPCgmuUBHPugpuYxaCrXAbXjC1kkFZe/y+DI=,tag:l9f4iy1TCd/KyyTrHFeIwA==,type:str]
|
||||
#ENC[AES256_GCM,data:T0sPU34UTw==,iv:x7slQXYqmrlc8LbXy3WK3435oKt8MPxg63F1Le9Q9Gc=,tag:OQJZgrSbVvQJYxIoADYiUQ==,type:comment]
|
||||
HOMEPAGE_VAR_RADARR_USERNAME: ENC[AES256_GCM,data:0JO3+tYe73g=,iv:rwc8mN7BspHqQaK4jOamxxfmfCIz+LIOcXP6+ttf+EM=,tag:8xbi9cOv04ydi48/omcAxw==,type:str]
|
||||
HOMEPAGE_VAR_RADARR_PASSWORD: ENC[AES256_GCM,data:GAQDMYTcmdjsDAKhc+lVMWgqiw/7QI4O4mRczrZTwBNleLIT1ypq2YL6iTSE8VNoMVhayEHWFfhlnW19jfE7Mw==,iv:mV+BFgvu0g56sexTVF39xOXZt0g2WXU6Bvfv5rMSjOo=,tag:ONo3c8WoRP1nkjKuZWbCsA==,type:str]
|
||||
HOMEPAGE_VAR_RADARR_API_KEY: ENC[AES256_GCM,data:pSop8tQFKlqjubts1dYLmAuJykHgiKfN5AE3TiJ+/FA=,iv:vjkgcKV0fazgKAzwPVCnLnky8vi+C/5oX+kjYZooo1g=,tag:UxL6DV8Soac2kQtiKdjByA==,type:str]
|
||||
#ENC[AES256_GCM,data:veoFUhGcVc9wxkHhEC+2,iv:NzvpUsCaUUplDgNTQYnZHnp9wp3eYDr3nSHS+KH1O+g=,tag:I4QnzFgNIsnTUqYa/pisqA==,type:comment]
|
||||
HOMEPAGE_VAR_HOMEASSISTANT_URL: ENC[AES256_GCM,data:/wqyadZAZDLX9wvZBgb1JVWGR4Nx3LLZqasuun70yXLNnhDRfcriSLM+,iv:PE/vo49SP4ietb5MA3QQYNwUGGs9ssZ3HB5OKgCsEcA=,tag:EXutc1HIXAC7lHqHo8lPnw==,type:str]
|
||||
HOMEPAGE_VAR_HOMEASSISTANT_API_KEY: ENC[AES256_GCM,data:UmYMhbs8uTCpnQavv07fSeEQi48sgaHKhZGUoMMOPY57EKw1TLoLl4Ew2xk7ISM2yzLIJ8ltYkjx3c6XGBhQcrmwibWLr0SqQbF8TTmzG3jNYnmYGmw+ocB+KsVn4dwH22XXBUcPPto9ca8/heCldWvinEb6hEy+/TzQH/J5+j9P91XmYlMkD6a17C4CxEorr5wQ/7mrF3o9YkXOmVl3iOTcLPLWGUBJ7GwerR5TObClwEXvp2di,iv:ueOKaNGs1Afmb51aQorO/NuNrvBF+0kn5t6sPMG5npU=,tag:HZSPBWqrJ3oIueFQieqTNw==,type:str]
|
||||
#ENC[AES256_GCM,data:SdvlWse6XQ==,iv:qt3dXpJnCdtZRCvhw1WN8Ns5oeqXXJnCZGU/u+IqYs0=,tag:XRQ4NGgrQ1EQ6kgYDKBugg==,type:comment]
|
||||
HOMEPAGE_VAR_IMMICH_API_KEY: ENC[AES256_GCM,data:U4Va0z9GmVwNUGtcpkopSdi7+tyT7Ar18TBq50014xuJc4btqbpf,iv:59VQPnPURUShRiWj3Ykgxkq0nwc9Ho8NPdP6ZEXbgJw=,tag:2Mb0rh+2zYuJuszOYcPysA==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjcFBqR2NVM2hIdW5sVDRt
|
||||
MzB0TkFBMEFQYWM0UGhtZUdWYnd5VzhVemdnCm9TK3REanBiNmhyYTZCcVFSbG42
|
||||
R1d4Z29NUk1nUE5QbWNxNTMwbmliM2cKLS0tIGQ4NTNWQWpTeEovdmwwRmhBd1RR
|
||||
SGRjZnczTEJuOTZCdk14VEV4M1M3alEKfPm69NHpOdZrWli/DhtAej8nSETSSsYW
|
||||
SK8sg1oX9oA12J12FpI1XzFppYaKu8GrGv+r4SgbLN5FbXVoyGJ8ZQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-03-12T10:07:22Z"
|
||||
mac: ENC[AES256_GCM,data:v742LFJuZoS1h8EuCVotY6iG1qxHxC3hiREbyqpllH0QXTf0k/tQ5FImqsM20N2Qc5aEXtS0dpfuTTgB3hZtHOaiBX4Kuzqewvc2gc1yQNrT/r3e2/iB8RNON+0erOwkqVECyPbgKsG/Y5p368rRgDQMbBwl8wjYrc3mLm2T9Yw=,iv:oI1PtCsJHRE6PjSrtG7vLtQQ+Ym5yBCGyqdLljlO0og=,tag:qPLi2beb2zsAkV5iP14Qiw==,type:str]
|
||||
encrypted_regex: ^(data|stringData|email)$
|
||||
version: 3.12.1
|
||||
12
kubernetes/app/homepage/service.yaml
Normal file
12
kubernetes/app/homepage/service.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
spec:
|
||||
selector:
|
||||
app: homepage
|
||||
ports:
|
||||
- port: 3000
|
||||
targetPort: 3000
|
||||
name: http
|
||||
39
kubernetes/app/homepage/serviceaccount.yaml
Normal file
39
kubernetes/app/homepage/serviceaccount.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: homepage
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces", "pods", "nodes"]
|
||||
verbs: ["get", "list"]
|
||||
- apiGroups: ["networking.k8s.io"]
|
||||
resources: ["ingresses"]
|
||||
verbs: ["get", "list"]
|
||||
- apiGroups: ["traefik.io"]
|
||||
resources: ["ingressroutes"]
|
||||
verbs: ["get", "list"]
|
||||
- apiGroups: ["metrics.k8s.io"]
|
||||
resources: ["nodes", "pods"]
|
||||
verbs: ["get", "list"]
|
||||
- apiGroups: ["apiextensions.k8s.io"]
|
||||
resources: ["customresourcedefinitions"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: homepage
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: homepage
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
Reference in New Issue
Block a user