Files
homelab-manifests/glance-system/glance-kisfenyo.yaml
T
2026-01-11 13:02:37 +01:00

1018 lines
41 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Glance Dashboard for Kisfenyo
# Namespace: glance-system
# Domain: kisfenyo.dooplex.hu
# Version: v0.8.4
#
# Features:
# - Custom background image
# - Custom logo
# - Weather widget (Budapest)
# - YouTube subscriptions
# - RSS feeds
# - To-do list
# - iFrames for Cal.com, Google Calendar, Outline
# - Bookmarks/Links to all apps
# - Calendar widget
#
# Authentik Integration:
# 1. Create Application: "Glance Home"
# 2. Create Provider: Proxy Provider with external host https://kisfenyo.dooplex.hu
# 3. Create Outpost: glance-outpost
# 4. Update auth-url annotation with actual outpost service name
---
apiVersion: v1
kind: ConfigMap
metadata:
name: glance-config-kisfenyo
namespace: glance-system
labels:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
data:
glance.yml: |
# Glance Configuration
# Documentation: https://github.com/glanceapp/glance/blob/main/docs/configuration.md
server:
host: 0.0.0.0
port: 8080
assets-path: /app/config/assets
branding:
logo-url: https://web.dooplex.hu/static/DooPlex_logo_3.png
favicon-url: https://web.dooplex.hu/static/DooPlex_favicon_2.png
app-name: "Kisfenyo's Home"
app-icon-url: https://web.dooplex.hu/static/DooPlex_favicon_2.png
app-background-color: "#132b66"
hide-footer: true
theme:
background-color: 280 30 15
primary-color: 280 60 70
positive-color: 120 50 50
negative-color: 0 70 60
contrast-multiplier: 1.2
text-saturation-multiplier: 0.8
custom-css-file: /assets/custom.css
pages:
# ==================== HOME PAGE ====================
- name: Home
slug: home
width: wide
columns:
# ---------- LEFT COLUMN ----------
- size: small
widgets:
# Glance Custom API Widget - System Stats from Prometheus
# Add this widget to your glance.yml configuration under a column's widgets section
#
# Prometheus URL: http://prometheus.mon-system.svc.cluster.local:9090
#
# This widget displays:
# - Hostname & Uptime
# - CPU usage % and Temperature
# - Memory usage %
# - Disk usage for all mount points with progress bars
# - Fan speeds
#
# Note: Make sure your Glance version is v0.8.0+ for all template functions
- type: custom-api
title: DooPlex Server
cache: 30s
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_uname_info
subrequests:
uptime_days:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: floor((time() - node_boot_time_seconds) / 86400)
uptime_hours:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: floor((time() - node_boot_time_seconds) % 86400 / 3600)
cpu:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
memory:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
cpu_temp:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_hwmon_temp_celsius{instance="dooplex",chip="platform_coretemp_0",sensor="temp1"}
fans:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: fan_speed_rpm{instance="dooplex"}
disk_root:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})
disk_root_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / 1073741824
disk_root_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/"} / 1073741824
disk_ssd2:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/ssd_2"} / node_filesystem_size_bytes{mountpoint="/mnt/ssd_2"})
disk_ssd2_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/mnt/ssd_2"} - node_filesystem_avail_bytes{mountpoint="/mnt/ssd_2"}) / 1073741824
disk_ssd2_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/mnt/ssd_2"} / 1073741824
disk_hdd1:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/1_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/1_hdd"})
disk_hdd1_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/mnt/1_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/1_hdd"}) / 1099511627776
disk_hdd1_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/mnt/1_hdd"} / 1099511627776
disk_hdd2:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/2_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/2_hdd"})
disk_hdd2_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/mnt/2_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/2_hdd"}) / 1099511627776
disk_hdd2_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/mnt/2_hdd"} / 1099511627776
disk_hdd3:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/3_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/3_hdd"})
disk_hdd3_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/mnt/3_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/3_hdd"}) / 1099511627776
disk_hdd3_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/mnt/3_hdd"} / 1099511627776
disk_hdd4:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/4_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/4_hdd"})
disk_hdd4_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/mnt/4_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/4_hdd"}) / 1099511627776
disk_hdd4_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/mnt/4_hdd"} / 1099511627776
disk_hdd5:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/5_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/5_hdd"})
disk_hdd5_used:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: (node_filesystem_size_bytes{mountpoint="/mnt/5_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/5_hdd"}) / 1099511627776
disk_hdd5_total:
url: ${PROMETHEUS_URL}/api/v1/query
parameters:
query: node_filesystem_size_bytes{mountpoint="/mnt/5_hdd"} / 1099511627776
template: |
<style>
.sys-stats { font-size: 0.9em; }
.top-row { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; justify-content: space-around; }
.top-item { text-align: center; padding: 8px 12px; background: rgba(255,255,255,0.05); border-radius: 8px; min-width: 70px; }
.top-label { font-size: 0.7em; opacity: 0.6; text-transform: uppercase; letter-spacing: 0.5px; }
.top-value { font-size: 1.1em; font-weight: 600; margin-top: 2px; }
.section-title { font-size: 0.75em; opacity: 0.6; text-transform: uppercase; letter-spacing: 0.5px; margin: 12px 0 8px 0; }
.disk-row { display: flex; align-items: center; padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.08); }
.disk-row:last-child { border-bottom: none; }
.disk-name { font-weight: 500; min-width: 55px; font-size: 0.9em; }
.disk-bar { flex: 1; height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; margin: 0 12px; overflow: hidden; }
.disk-fill { height: 100%; border-radius: 3px; }
.fill-ok { background: linear-gradient(90deg, #4ade80, #22c55e); }
.fill-warn { background: linear-gradient(90deg, #fbbf24, #f59e0b); }
.fill-crit { background: linear-gradient(90deg, #f87171, #ef4444); }
.disk-info { font-size: 0.8em; opacity: 0.8; text-align: right; min-width: 150px; }
</style>
{{ $hostname := .JSON.String "data.result.0.metric.nodename" }}
{{ $uptimeDays := (.Subrequest "uptime_days").JSON.Float "data.result.0.value.1" }}
{{ $uptimeHours := (.Subrequest "uptime_hours").JSON.Float "data.result.0.value.1" }} {{ $cpu := (.Subrequest "cpu").JSON.Float "data.result.0.value.1" }}
{{ $mem := (.Subrequest "memory").JSON.Float "data.result.0.value.1" }}
{{ $temp := (.Subrequest "cpu_temp").JSON.Float "data.result.0.value.1" }}
{{ $fans := (.Subrequest "fans").JSON.Array "data.result" }}
<div class="sys-stats">
<div class="top-row">
<div class="top-item">
<div class="top-label">Host</div>
<div class="top-value">{{ $hostname }}</div>
</div>
<div class="top-item">
<div class="top-label">Uptime</div>
<div class="top-value">{{ printf "%.0f" $uptimeDays }}d {{ printf "%.0f" $uptimeHours }}h</div>
</div>
<div class="top-item">
<div class="top-label">CPU</div>
<div class="top-value">{{ printf "%.1f" $cpu }}%</div>
</div>
<div class="top-item">
<div class="top-label">Memory</div>
<div class="top-value">{{ printf "%.1f" $mem }}%</div>
</div>
<div class="top-item">
<div class="top-label">Temp</div>
<div class="top-value">{{ printf "%.0f" $temp }}°C</div>
</div>
<div class="top-item">
<div class="top-label">Fans</div>
<div class="top-value">{{ range $i, $fan := $fans }}{{ if $i }}/{{ end }}{{ $fan.Int "value.1" }}{{ end }}</div>
</div>
</div>
<div class="section-title">Storage</div>
{{ $rootPct := (.Subrequest "disk_root").JSON.Float "data.result.0.value.1" }}
{{ $rootUsed := (.Subrequest "disk_root_used").JSON.Float "data.result.0.value.1" }}
{{ $rootTotal := (.Subrequest "disk_root_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">Root</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $rootPct 70.0 }}fill-ok{{ else if lt $rootPct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $rootPct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.0f" $rootUsed }} / {{ printf "%.0f" $rootTotal }} GB ({{ printf "%.0f" $rootPct }}%)</span>
</div>
{{ $ssd2Pct := (.Subrequest "disk_ssd2").JSON.Float "data.result.0.value.1" }}
{{ $ssd2Used := (.Subrequest "disk_ssd2_used").JSON.Float "data.result.0.value.1" }}
{{ $ssd2Total := (.Subrequest "disk_ssd2_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">SSD2</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $ssd2Pct 70.0 }}fill-ok{{ else if lt $ssd2Pct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $ssd2Pct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.0f" $ssd2Used }} / {{ printf "%.0f" $ssd2Total }} GB ({{ printf "%.0f" $ssd2Pct }}%)</span>
</div>
{{ $hdd1Pct := (.Subrequest "disk_hdd1").JSON.Float "data.result.0.value.1" }}
{{ $hdd1Used := (.Subrequest "disk_hdd1_used").JSON.Float "data.result.0.value.1" }}
{{ $hdd1Total := (.Subrequest "disk_hdd1_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">HDD1</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $hdd1Pct 70.0 }}fill-ok{{ else if lt $hdd1Pct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $hdd1Pct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.1f" $hdd1Used }} / {{ printf "%.1f" $hdd1Total }} TB ({{ printf "%.0f" $hdd1Pct }}%)</span>
</div>
{{ $hdd2Pct := (.Subrequest "disk_hdd2").JSON.Float "data.result.0.value.1" }}
{{ $hdd2Used := (.Subrequest "disk_hdd2_used").JSON.Float "data.result.0.value.1" }}
{{ $hdd2Total := (.Subrequest "disk_hdd2_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">HDD2</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $hdd2Pct 70.0 }}fill-ok{{ else if lt $hdd2Pct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $hdd2Pct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.1f" $hdd2Used }} / {{ printf "%.1f" $hdd2Total }} TB ({{ printf "%.0f" $hdd2Pct }}%)</span>
</div>
{{ $hdd3Pct := (.Subrequest "disk_hdd3").JSON.Float "data.result.0.value.1" }}
{{ $hdd3Used := (.Subrequest "disk_hdd3_used").JSON.Float "data.result.0.value.1" }}
{{ $hdd3Total := (.Subrequest "disk_hdd3_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">HDD3</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $hdd3Pct 70.0 }}fill-ok{{ else if lt $hdd3Pct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $hdd3Pct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.1f" $hdd3Used }} / {{ printf "%.1f" $hdd3Total }} TB ({{ printf "%.0f" $hdd3Pct }}%)</span>
</div>
{{ $hdd4Pct := (.Subrequest "disk_hdd4").JSON.Float "data.result.0.value.1" }}
{{ $hdd4Used := (.Subrequest "disk_hdd4_used").JSON.Float "data.result.0.value.1" }}
{{ $hdd4Total := (.Subrequest "disk_hdd4_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">HDD4</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $hdd4Pct 70.0 }}fill-ok{{ else if lt $hdd4Pct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $hdd4Pct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.1f" $hdd4Used }} / {{ printf "%.1f" $hdd4Total }} TB ({{ printf "%.0f" $hdd4Pct }}%)</span>
</div>
{{ $hdd5Pct := (.Subrequest "disk_hdd5").JSON.Float "data.result.0.value.1" }}
{{ $hdd5Used := (.Subrequest "disk_hdd5_used").JSON.Float "data.result.0.value.1" }}
{{ $hdd5Total := (.Subrequest "disk_hdd5_total").JSON.Float "data.result.0.value.1" }}
<div class="disk-row">
<span class="disk-name">HDD5</span>
<div class="disk-bar">
<div class="disk-fill {{ if lt $hdd5Pct 70.0 }}fill-ok{{ else if lt $hdd5Pct 85.0 }}fill-warn{{ else }}fill-crit{{ end }}" style="width: {{ printf "%.0f" $hdd5Pct }}%"></div>
</div>
<span class="disk-info">{{ printf "%.1f" $hdd5Used }} / {{ printf "%.1f" $hdd5Total }} TB ({{ printf "%.0f" $hdd5Pct }}%)</span>
</div>
</div>
# Weather Widget
- type: weather
location: Budapest, Hungary
units: metric
hour-format: 24h
# Calendar Widget
- type: calendar
first-day-of-week: monday
# To-Do List
- type: to-do
title: Tasks
# Quick Links - Productivity
- type: bookmarks
title: Productivity
groups:
- title: ""
links:
- title: Nextcloud
url: https://nextcloud.dooplex.hu
icon: si:nextcloud
- title: Outline
url: https://outline.dooplex.hu
icon: si:outline
- title: Paperless
url: https://paperless.dooplex.hu
icon: si:paperlessngx
- title: Vaultwarden
url: https://vaultwarden.dooplex.hu
icon: si:bitwarden
- title: Actual Budget
url: https://actualbudget.dooplex.hu
icon: si:actualbudget
- title: Tandoor
url: https://tandoor.dooplex.hu
icon: sh:tandoor-recipes
- title: Bookstack
url: https://bookstack.dooplex.hu
icon: si:bookstack
# Quick Links - File Sharing
- type: bookmarks
title: File Sharing
groups:
- title: ""
links:
- title: Fileshare
url: https://fileshare.dooplex.hu
icon: si:files
- title: Privatebin
url: https://privatebin.dooplex.hu
icon: sh:privatebin
- title: Pastes (OpenGist)
url: https://paste.dooplex.hu
icon: sh:opengist
- title: Zipline
url: https://zipline.dooplex.hu
icon: sh:zipline
# ---------- CENTER COLUMN ----------
- size: full
widgets:
# Outline Notes iframe
- type: iframe
source: https://outline.dooplex.hu/collection/notes-VVby8kTDMn/recent
height: 500
title: Recent Notes
# ---------- RIGHT COLUMN ----------
- size: small
widgets:
# RSS Feeds - Add your favorite feeds here
- type: rss
title: News & Feeds
limit: 15
collapse-after: 8
feeds:
- url: https://telex.hu/rss
title: telex.hu
limit: 3
- url: https://444.hu/feed
title: 444.hu
limit: 3
- url: https://444.hu/feed
title: 444.hu
limit: 3
- url: https://hvg.hu/rss
title: hvg.hu
limit: 3
# ==================== MEDIA PAGE ====================
- name: Media
slug: media
width: wide
columns:
- size: small
widgets:
- type: bookmarks
title: Entertainment
groups:
- links:
- title: Plex
url: https://plex.dooplex.hu
icon: si:plex
- title: Immich (Photos)
url: https://photos.dooplex.hu
icon: si:immich
- title: AudioBookshelf
url: https://audiobookshelf.dooplex.hu
icon: si:audiobookshelf
- title: Calibre-Web (eBooks)
url: https://books.dooplex.hu
icon: si:calibreweb
- title: Arcade (Retro Games)
url: https://arcade.dooplex.hu
icon: si:retroarch
- type: bookmarks
title: Media Management
groups:
- links:
- title: Sonarr (TV Shows)
url: https://sonarr.dooplex.hu
icon: si:sonarr
- title: Radarr (Movies)
url: https://radarr.dooplex.hu
icon: si:radarr
- title: RadarrKids
url: https://radarrkids.dooplex.hu
icon: si:radarr
- title: Prowlarr (Indexers)
url: https://prowlarr.dooplex.hu
icon: sh:prowlarr
- title: Seerr (Requests)
url: https://seerr.dooplex.hu
icon: sh:overseerr
- size: full
widgets:
# YouTube Videos
- type: videos
title: YouTube
channels:
- UCir93b_ftqInEaDpsWYbo_g #Practical Psychology - @practicalpsychologytips
- UCEwsbtepqts935wXykReKxg #CounsellingTutor - @Counsellingtutor1
- UCUdettijNYvLAm4AixZv4RA #SciShow Psych - @SciShowPsych
- UClHVl2N3jPEbkNJVx-ItQIQ #HealthyGamerGG - @HealthyGamerGG
- UCAvfZQ3r24F-V1JYqn2pfXg #The Psychology Podcast - @ThePsychologyPodcast
- UC6Unpcb3T4QijIBs8hPfeyA #Psych Explained - @PsychExplained
- UCl8TEoIOnMq_5ntJOYMq-Zg #DrJulie - @DrJulie
limit: 12
collapse-after: 6
# Reddit
- type: group
title: Reddit
widgets:
- type: reddit
subreddit: hungary
show-thumbnails: true
- type: reddit
subreddit: selfhosted
show-thumbnails: true
- type: reddit
subreddit: homeserver
show-thumbnails: true
- type: reddit
subreddit: homelab
show-thumbnails: true
- type: reddit
subreddit: kubernetes
show-thumbnails: true
- type: reddit
subreddit: linux
show-thumbnails: true
- type: reddit
subreddit: sysadmin
show-thumbnails: true
- type: reddit
subreddit: technology
show-thumbnails: true
- type: reddit
subreddit: futurology
show-thumbnails: true
- size: small
widgets:
- type: bookmarks
title: Other Apps
groups:
- links:
- title: AdventureLog
url: https://adventures.dooplex.hu
icon: sh:adventurelog
- title: Wanderer
url: https://wanderer.dooplex.hu
icon: sh:wanderer
- title: Plant-it
url: https://plantit.dooplex.hu
icon: sh:plant-it
- title: Workout (wger)
url: https://workout.dooplex.hu
icon: sh:wger
- title: Fileshare
url: https://fileshare.dooplex.hu
icon: si:files
- title: Privatebin
url: https://privatebin.dooplex.hu
icon: sh:privatebin
- title: Pastes (OpenGist)
url: https://paste.dooplex.hu
icon: sh:opengist
- title: Zipline
url: https://zipline.dooplex.hu
icon: sh:zipline
# ==================== NECTCLOUD PAGE ====================
- name: NextCloud
slug: nextcloud
width: wide
columns:
- size: full
widgets:
# Nextcloud iframe
- type: iframe
css-class: iframe-no-tint
source: https://nextcloud.dooplex.hu/apps/files/files
height: 1200
title: NextCloud
custom.css: |
/* Custom CSS for Kisfenyo's Glance Dashboard */
/* Dark Blue theme */
/* ===== Wallpaper visible ===== */
html, body { height: 100%; }
html {
background: url("https://web.dooplex.hu/static/wallpaper-2.jpg") center / cover no-repeat fixed !important;
}
/* Glance containers that tend to paint over the wallpaper */
body,
.page,
#page-content,
.page-content,
.content-bounds,
.page-columns,
.page-column {
background: transparent !important;
}
/* Optional readability veil (Homepage-like) */
body::before {
content: "";
position: fixed;
inset: 0;
background: rgba(20, 10, 30, 0.25);
pointer-events: none;
z-index: 0;
}
body > * { position: relative; z-index: 1; }
/* ===== Glassy widgets like Homepage ===== */
.widget {
background: rgba(45, 31, 61, 0.55) !important;
border: 1px solid rgba(255,255,255,0.08) !important;
border-radius: 10px !important;
backdrop-filter: blur(6px) !important;
-webkit-backdrop-filter: blur(6px) !important;
}
/* ===== Header + bigger logo ===== */
.header-container {
background: rgba(45, 31, 61, 0.55) !important;
backdrop-filter: blur(10px) !important;
-webkit-backdrop-filter: blur(10px) !important;
border-bottom: 1px solid rgba(255,255,255,0.08) !important;
}
.header {
min-height: 150px !important;
align-items: flex-end !important;
padding: 16px 18px !important;
}
/* This matches your DOM: <div class="logo"> <img ...> */
.logo img {
max-height: 170px !important;
height: auto !important;
width: auto !important;
object-fit: contain !important;
}
/* ===== iFrame purple tint + visible overlay ===== */
.widget.widget-type-iframe {
position: relative !important;
overflow: hidden !important;
border-radius: 12px !important;
}
.widget.widget-type-iframe iframe {
border-radius: 12px !important;
width: 100% !important;
border: 0 !important;
filter: sepia(0.25) saturate(3) hue-rotate(250deg) brightness(1.02) !important;
position: relative !important;
z-index: 1 !important;
}
/* Overlay ON TOP of iframe (you cant style inside cross-origin iframes) */
.widget.widget-type-iframe::after {
content: "";
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
border-radius: 12px;
background: rgba(226, 146, 255, 0.16);
}
/* Widget content area */
.widget-content {
background-color: transparent !important;
}
/* Header fully transparent */
.header-container,
.header,
.page-header,
.nav,
.navigation {
background-color: transparent !important;
background: transparent !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
box-shadow: none !important;
border: 0 !important;
}
/* --- Header: align tabs to bottom + larger font --- */
.header {
display: flex !important;
align-items: flex-end !important; /* bottom-align children */
gap: 18px !important;
}
/* Push the nav to the bottom edge */
.header .nav {
align-self: flex-end !important;
padding-bottom: 10px !important; /* tweak this value if you want it lower/higher */
}
/* Bigger, cleaner tab text */
.header .nav .nav-item {
font-size: 18px !important; /* increase */
line-height: 1.1 !important;
padding: 10px 14px !important; /* makes it feel less “floaty” */
letter-spacing: 0.2px !important;
}
/* Optional: make current tab underline sit nicely at the bottom */
.header .nav .nav-item-current::after,
.header .nav .nav-item[aria-current="page"]::after {
bottom: -6px !important;
}
.content-bounds,
.body-content,
.page,
#page-content {
background: transparent !important;
}
/* Column containers */
.page-column, .page-columns {
background-color: transparent !important;
}
/* Links styling - purple accent */
a {
color: #e292ff !important;
}
a:hover {
color: #f0b8ff !important;
}
/* Bookmark items */
.bookmark-link {
background-color: rgba(60, 40, 80, 0.6) !important;
border-radius: 8px !important;
transition: background-color 0.2s ease !important;
}
.bookmark-link:hover {
background-color: rgba(80, 50, 110, 0.8) !important;
}
.widget-type-calendar,
.widget-type-weather,
.widget-type-to-do {
background-color: rgba(45, 31, 61, 0.55) !important;
}
/* RSS feed items */
.rss-item, .feed-item {
background-color: rgba(60, 40, 80, 0.5) !important;
border-radius: 6px !important;
margin-bottom: 4px !important;
}
/* Video thumbnails */
.video-item, .videos-item {
background-color: rgba(60, 40, 80, 0.5) !important;
border-radius: 8px !important;
}
/* Widget titles */
.widget-header, .widget-title {
color: #e292ff !important;
font-weight: 600 !important;
}
/* Scrollbar styling */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(45, 31, 61, 0.5);
}
::-webkit-scrollbar-thumb {
background: rgba(226, 146, 255, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(226, 146, 255, 0.7);
}
/* Fix "Show more" bar background in RSS widget */
.widget-type-rss .expand-toggle-button {
background: transparent !important;
box-shadow: none !important;
border: 0 !important;
}
/* Glance often draws that ugly bar via a pseudo-element */
.widget-type-rss .expand-toggle-button::before,
.widget-type-rss .expand-toggle-button::after,
.widget-type-rss .expand-toggle-button-icon::before,
.widget-type-rss .expand-toggle-button-icon::after {
background: transparent !important;
box-shadow: none !important;
border: 0 !important;
}
/* Optional: make it feel "intentional" instead of floating */
.widget-type-rss .expand-toggle-button {
margin-top: 8px !important;
padding: 10px 12px !important;
border-top: 1px solid rgba(255,255,255,0.08) !important;
color: rgba(255,255,255,0.75) !important;
}
.widget-type-rss .expand-toggle-button:hover {
color: rgba(255,255,255,0.95) !important;
}
/* --- Force header nav to sit at the bottom (override utility classes) --- */
.header.flex {
align-items: flex-end !important;
}
/* Make the nav fill the header height and align its items to the bottom */
.header.flex > .nav.flex {
height: 100% !important;
align-items: flex-end !important;
padding-bottom: 14px !important; /* increase/decrease to taste */
}
/* Bigger tab text */
.header.flex > .nav.flex > .nav-item {
font-size: 20px !important;
line-height: 1.1 !important;
padding: 10px 14px !important;
}
/* Tabs: bottom-align text inside full-height .nav-item */
.header.flex > .nav.flex > .nav-item {
display: flex !important;
align-items: flex-end !important;
/* keep them full-height, but move the text down */
height: 100% !important;
padding: 0 14px 18px 14px !important; /* bottom padding controls “how low” */
/* kill Glance's vertical centering */
line-height: 1 !important;
font-size: 20px !important;
}
/* Expand buttons: force transparent everywhere (RSS, Reddit, etc) */
.expand-toggle-button,
.expand-toggle-button.container-expanded {
background: transparent !important;
background-color: transparent !important;
box-shadow: none !important;
border: 0 !important;
}
/* Some themes draw the bar via pseudo elements */
.expand-toggle-button::before,
.expand-toggle-button::after,
.expand-toggle-button-icon::before,
.expand-toggle-button-icon::after {
background: transparent !important;
background-color: transparent !important;
box-shadow: none !important;
}
/* If the purple comes from a wrapper around the button, kill that too */
.widget-content > button.expand-toggle-button,
.widget-content > .expand-toggle-button,
.widget-content .expand-toggle-button {
background: transparent !important;
background-color: transparent !important;
}
/* If its "sticking" to bottom and picking up background from parent */
.expand-toggle-button.container-expanded {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
.widget.iframe-no-tint iframe {
filter: none !important;
}
.widget.iframe-no-tint::after {
content: none !important;
display: none !important;
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: glance-kisfenyo
namespace: glance-system
labels:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
app.kubernetes.io/version: "v0.8.4"
annotations:
reloader.stakater.com/auto: "true"
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
template:
metadata:
labels:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
app.kubernetes.io/version: "v0.8.4"
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: glance
image: glanceapp/glance:v0.8.4
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: "Europe/Budapest"
- name: PROMETHEUS_URL
value: "http://prometheus.mon-system.svc.cluster.local:9090"
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
volumeMounts:
- name: config
mountPath: /app/config/glance.yml
subPath: glance.yml
- name: config
mountPath: /app/config/assets/custom.css
subPath: custom.css
volumes:
- name: config
configMap:
name: glance-config-kisfenyo
---
apiVersion: v1
kind: Service
metadata:
name: glance-kisfenyo
namespace: glance-system
labels:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
spec:
type: ClusterIP
ports:
- name: http
port: 8080
targetPort: http
protocol: TCP
selector:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
---
# Ingress WITH Authentik proxy authentication
# Update the auth-url annotation with your actual outpost service name after creating in Authentik
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: glance-kisfenyo
namespace: glance-system
labels:
app.kubernetes.io/name: glance-kisfenyo
app.kubernetes.io/instance: glance-kisfenyo
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
external-dns.alpha.kubernetes.io/hostname: kisfenyo.dooplex.hu
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
nginx.ingress.kubernetes.io/proxy-busy-buffers-size: "32k"
# Authentik Forward Auth annotations
# TODO: Update 'glance-outpost' with your actual outpost name after creating in Authentik
nginx.ingress.kubernetes.io/auth-url: http://ak-outpost-glance-outpost.auth-system.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx
nginx.ingress.kubernetes.io/auth-signin: https://kisfenyo.dooplex.hu/outpost.goauthentik.io/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-response-headers: Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email
nginx.ingress.kubernetes.io/auth-snippet: |
proxy_set_header X-Forwarded-Host $http_host;
spec:
ingressClassName: nginx-internal
rules:
- host: kisfenyo.dooplex.hu
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: glance-kisfenyo
port:
number: 8080
tls:
- hosts:
- kisfenyo.dooplex.hu
secretName: glance-kisfenyo-tls
---