init
This commit is contained in:
commit
50f5234488
85
README.md
Normal file
85
README.md
Normal file
@ -0,0 +1,85 @@
|
||||
# Homepage K3s Configuration
|
||||
|
||||
A complete Kubernetes configuration for deploying [Homepage](https://gethomepage.dev/) dashboard on K3s clusters.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Deploy Homepage to your K3s cluster:
|
||||
|
||||
```bash
|
||||
kubectl apply -k k8s/
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The configuration includes:
|
||||
|
||||
- **Namespace**: `homepage` namespace with service account
|
||||
- **RBAC**: ClusterRole with permissions to read cluster resources
|
||||
- **ConfigMap**: Pre-configured with widgets for K3s monitoring
|
||||
- **Deployment**: Secure deployment with resource limits and health checks
|
||||
- **Service**: ClusterIP service on port 3000
|
||||
- **Ingress**: Traefik-compatible ingress with TLS support
|
||||
|
||||
## Access
|
||||
|
||||
After deployment, Homepage will be available at:
|
||||
- HTTP: `http://sortifal.fr`
|
||||
- HTTPS: `https://sortifal.fr` (with cert-manager)
|
||||
|
||||
Ensure your DNS points `sortifal.fr` to your K3s ingress IP.
|
||||
|
||||
## Customization
|
||||
|
||||
### Update Configuration
|
||||
|
||||
Edit the ConfigMap in `k8s/configmap.yaml` to customize:
|
||||
- **services.yaml**: Your applications and services
|
||||
- **bookmarks.yaml**: Quick links and bookmarks
|
||||
- **widgets.yaml**: Dashboard widgets (cluster info, resources, etc.)
|
||||
- **settings.yaml**: Theme, layout, and provider settings
|
||||
|
||||
Apply changes:
|
||||
```bash
|
||||
kubectl apply -k k8s/
|
||||
kubectl rollout restart deployment/homepage -n homepage
|
||||
```
|
||||
|
||||
### Change Domain
|
||||
|
||||
Update `sortifal.fr` in `k8s/ingress.yaml` and the `HOMEPAGE_ALLOWED_HOSTS` environment variable in `k8s/deployment.yaml`.
|
||||
|
||||
### Resource Limits
|
||||
|
||||
Adjust CPU/memory limits in `k8s/deployment.yaml` based on your needs.
|
||||
|
||||
## Monitoring
|
||||
|
||||
Homepage includes widgets for monitoring your K3s cluster:
|
||||
- Cluster CPU and memory usage
|
||||
- Node status and resources
|
||||
- Pod information across namespaces
|
||||
- System resources
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Check deployment status:
|
||||
```bash
|
||||
kubectl get pods -n homepage
|
||||
kubectl logs -n homepage deployment/homepage
|
||||
```
|
||||
|
||||
Verify RBAC permissions:
|
||||
```bash
|
||||
kubectl auth can-i get nodes --as=system:serviceaccount:homepage:homepage
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
The configuration follows security best practices:
|
||||
- Non-root container execution
|
||||
- Read-only root filesystem where possible
|
||||
- Minimal RBAC permissions
|
||||
- Resource limits
|
||||
- Security contexts
|
||||
- Dropped capabilities
|
||||
100
k8s/configmap.yaml
Normal file
100
k8s/configmap.yaml
Normal file
@ -0,0 +1,100 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: homepage-config
|
||||
namespace: homepage
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
data:
|
||||
kubernetes.yaml: |
|
||||
mode: cluster
|
||||
settings.yaml: |
|
||||
providers:
|
||||
openweathermap: openweathermapapikey
|
||||
weatherapi: weatherapiapikey
|
||||
title: Dashboard
|
||||
favicon: https://github.com/walkxcode/dashboard-icons/blob/main/png/homepage.png
|
||||
theme: dark
|
||||
color: slate
|
||||
headerStyle: clean
|
||||
layout:
|
||||
My First Group:
|
||||
style: row
|
||||
columns: 3
|
||||
My Second Group:
|
||||
style: column
|
||||
custom.css: ""
|
||||
custom.js: ""
|
||||
bookmarks.yaml: |
|
||||
- Developer:
|
||||
- Github:
|
||||
- abbr: GH
|
||||
href: https://github.com/
|
||||
- Docker Hub:
|
||||
- abbr: DH
|
||||
href: https://hub.docker.com/
|
||||
- Social:
|
||||
- Reddit:
|
||||
- abbr: RE
|
||||
href: https://www.reddit.com/
|
||||
services.yaml: |
|
||||
- Infrastructure:
|
||||
- Traefik:
|
||||
href: http://traefik.local
|
||||
description: Reverse Proxy & Load Balancer
|
||||
icon: traefik.png
|
||||
server: my-k3s
|
||||
container: traefik
|
||||
- Longhorn:
|
||||
href: http://longhorn.local
|
||||
description: Distributed Storage
|
||||
icon: longhorn.png
|
||||
|
||||
- Monitoring:
|
||||
- Grafana:
|
||||
href: http://grafana.local
|
||||
description: Analytics & Monitoring
|
||||
icon: grafana.png
|
||||
- Prometheus:
|
||||
href: http://prometheus.local
|
||||
description: Metrics Collection
|
||||
icon: prometheus.png
|
||||
|
||||
- Applications:
|
||||
- Nextcloud:
|
||||
href: http://nextcloud.local
|
||||
description: File Sharing & Collaboration
|
||||
icon: nextcloud.png
|
||||
- Jellyfin:
|
||||
href: http://jellyfin.local
|
||||
description: Media Server
|
||||
icon: jellyfin.png
|
||||
widgets.yaml: |
|
||||
- kubernetes:
|
||||
cluster:
|
||||
show: true
|
||||
cpu: true
|
||||
memory: true
|
||||
showLabel: true
|
||||
label: "K3s Cluster"
|
||||
nodes:
|
||||
show: true
|
||||
cpu: true
|
||||
memory: true
|
||||
showLabel: true
|
||||
- resources:
|
||||
backend: resources
|
||||
expanded: true
|
||||
cpu: true
|
||||
memory: true
|
||||
- datetime:
|
||||
text_size: xl
|
||||
format:
|
||||
timeStyle: short
|
||||
dateStyle: short
|
||||
hourCycle: h23
|
||||
- search:
|
||||
provider: duckduckgo
|
||||
target: _blank
|
||||
showSearchSuggestions: true
|
||||
docker.yaml: ""
|
||||
110
k8s/deployment.yaml
Normal file
110
k8s/deployment.yaml
Normal file
@ -0,0 +1,110 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
spec:
|
||||
revisionHistoryLimit: 3
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
maxSurge: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: homepage
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
spec:
|
||||
serviceAccountName: homepage
|
||||
automountServiceAccountToken: true
|
||||
dnsPolicy: ClusterFirst
|
||||
enableServiceLinks: true
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: homepage
|
||||
image: "ghcr.io/gethomepage/homepage:latest"
|
||||
imagePullPolicy: Always
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
env:
|
||||
- name: HOMEPAGE_ALLOWED_HOSTS
|
||||
value: "sortifal.fr,localhost"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3000
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
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/services.yaml
|
||||
name: homepage-config
|
||||
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
|
||||
volumes:
|
||||
- name: homepage-config
|
||||
configMap:
|
||||
name: homepage-config
|
||||
- name: logs
|
||||
emptyDir: {}
|
||||
33
k8s/ingress.yaml
Normal file
33
k8s/ingress.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "traefik"
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||
traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
gethomepage.dev/description: "Homepage Dashboard"
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/group: "Dashboard"
|
||||
gethomepage.dev/icon: "homepage.png"
|
||||
gethomepage.dev/name: "Homepage"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- sortifal.fr
|
||||
secretName: homepage-tls
|
||||
rules:
|
||||
- host: "sortifal.fr"
|
||||
http:
|
||||
paths:
|
||||
- path: "/"
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: homepage
|
||||
port:
|
||||
number: 3000
|
||||
24
k8s/kustomization.yaml
Normal file
24
k8s/kustomization.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: homepage
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- configmap.yaml
|
||||
- rbac.yaml
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
- ingress.yaml
|
||||
|
||||
commonLabels:
|
||||
app: homepage
|
||||
version: v1.0.0
|
||||
|
||||
images:
|
||||
- name: ghcr.io/gethomepage/homepage
|
||||
newTag: latest
|
||||
|
||||
replicas:
|
||||
- name: homepage
|
||||
count: 1
|
||||
14
k8s/namespace.yaml
Normal file
14
k8s/namespace.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: homepage
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
72
k8s/rbac.yaml
Normal file
72
k8s/rbac.yaml
Normal file
@ -0,0 +1,72 @@
|
||||
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.containo.us
|
||||
- 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
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- deployments
|
||||
- replicasets
|
||||
- statefulsets
|
||||
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: homepage
|
||||
16
k8s/service.yaml
Normal file
16
k8s/service.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: homepage
|
||||
namespace: homepage
|
||||
labels:
|
||||
app.kubernetes.io/name: homepage
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 3000
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app.kubernetes.io/name: homepage
|
||||
Loading…
x
Reference in New Issue
Block a user