# Glance Dashboard for Orsi
# Namespace: glance-system
# Domain: orsi.dooplex.hu
# Version: v0.8.4
#
# Features:
# - Custom background image (purple theme matching Homepage)
# - 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 Orsi"
# 2. Create Provider: Proxy Provider with external host https://orsi.dooplex.hu
# 3. Create Outpost: glance-outpost
# 4. Update auth-url annotation with actual outpost service name
---
apiVersion: v1
kind: Namespace
metadata:
name: glance-system
labels:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: glance-config
namespace: glance-system
labels:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
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/assets
document:
head: |
branding:
logo-url: https://web.dooplex.hu/static/dooplex_logo_orsi_3.png
favicon-url: https://web.dooplex.hu/static/dooplex_favicon_orsi.png
app-name: "Orsi's Home"
app-icon-url: https://web.dooplex.hu/static/dooplex_favicon_orsi.png
app-background-color: "#2d1f3d"
hide-footer: true
theme:
disable-picker: true
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:
# Quick Links - Frequently used
- type: bookmarks
title: Frequently used
groups:
- title: ""
links:
- title: Youtube
url: https://youtube.com
icon: si:youtube
- title: Facebook
url: https://facebook.com
icon: si:facebook
- title: Spotify
url: https://spotify.com
icon: si:spotify
- title: Gmail
url: https://gmail.com
icon: si:gmail
- title: Google Drive
url: https://drive.google.com
icon: si:googledrive
- title: Google Calendar
url: https://calendar.google.com
icon: si:googlecalendar
- title: Yahoo Mail
url: https://mail.yahoo.com
icon: https://web.dooplex.hu/static/white-icons/yahoo.png
# 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: https://web.dooplex.hu/static/white-icons/tandoor.png
- 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: https://web.dooplex.hu/static/white-icons/privatebin.png
- title: Pastes (OpenGist)
url: https://paste.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/opengist.png
- title: Zipline
url: https://zipline.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/zipline.png
# ---------- CENTER COLUMN ----------
- size: full
widgets:
- type: split-column
max-columns: 3
widgets:
# Weather Widget (Időkép)
- type: custom-api
title: "Időkép — Budapest VII."
url: "http://idokep-scraper.glance-system.svc.cluster.local:8000/api?v=2"
cache: 30s
template: |
{{ $loc := .JSON.String "location.name" }}
{{ if eq $loc "" }}{{ $loc = .JSON.String "place" }}{{ end }}
{{ $curTemp := .JSON.Float "current.temp_c" }}
{{ $curIcon := .JSON.String "current.icon_url" }}
{{ $daily := .JSON.Array "daily" }}
{{ $hourly := .JSON.Array "hourly" }}
{{ if $curIcon }}

{{ end }}
{{ printf "%.0f" $curTemp }}°C
{{ if gt (len $hourly) 0 }}
{{ range $i, $h := $hourly }}
{{ $h.String "time" }}
{{ if $h.String "icon_url" }}

{{ end }}
{{ printf "%.0f" ($h.Float "temp_c") }}°
{{ end }}
{{ end }}
{{ if gt (len $daily) 0 }}
{{ range $daily }}
{{ .String "dow" }}
{{ .String "daynum" }}
{{ if .String "icon_url" }}

{{ end }}
{{ printf "%.0f" (.Float "tmin_c") }}°
{{/* We construct the style manually to bypass Go security sanitization */}}
{{ printf "%.0f" (.Float "tmax_c") }}°
{{ end }}
{{ end }}
# Calendar Widget
# - type: calendar
# first-day-of-week: monday
# To-Do List
- type: to-do
title: Tasks
- type: custom-api
title: Meal for the Day
cache: 5m
url: http://glance-helper.glance-system.svc.cluster.local:8000/tandoor/daily
parameters:
count: 3
cooldown: 14
options:
tandoor_url: https://tandoor.dooplex.hu
template: |
{{ $tandoor := .Options.StringOr "tandoor_url" "https://tandoor.dooplex.hu" }}
{{ $items := .JSON.Array "items" }}
{{ $count := len $items }}
{{ $last := sub $count 1 }}
{{ if lt $count 1 }}
No recipes.
{{ else }}
{{ range $i, $_ := $items }}
{{ end }}
{{ range $r := $items }}{{ $img := $r.String "image" }}{{ $url := $r.String "url" }}{{ $cook := $r.String "cook_url" }}{{ $cooked := $r.Int "cooked_count" }}
{{ end }}
{{ if gt $count 1 }}
{{ range $i, $_ := $items }}{{ if gt $i 0 }}
{{ end }}{{ if lt $i $last }}
{{ end }}{{ end }}
{{ range $i, $_ := $items }}{{ end }}
{{ end }}
{{ end }}
- type: split-column
max-columns: 2
widgets:
# Google Calendar iframe
- type: iframe
source: https://calendar.google.com/calendar/embed?src=b2884faf3db792ac082a6206057552c79080716efd5f966e169a41fc500e1c1c%40group.calendar.google.com&ctz=Europe%2FBudapest
height: 500
title: Calendar
# Reddit
- type: group
title: Reddit
widgets:
- type: reddit
subreddit: psychology
show-thumbnails: true
- type: reddit
subreddit: psychologystudents
show-thumbnails: true
- type: reddit
subreddit: psychologytalk
show-thumbnails: true
- type: reddit
subreddit: psychologists
show-thumbnails: true
- type: reddit
subreddit: psychologyresearch
show-thumbnails: true
- type: reddit
subreddit: academicpsychology
show-thumbnails: true
- type: reddit
subreddit: social_psychology
show-thumbnails: true
# ---------- RIGHT COLUMN ----------
- size: small
widgets:
# Calendar Events Widget (Órák & Családi)
- type: custom-api
title: Events Calendar
cache: 5m
url: http://glance-helper.glance-system.svc.cluster.local:8000/calendar/events
parameters:
count: 10
days: 14
template: |
{{ $events := .JSON.Array "events" }}
{{ $count := len $events }}
{{ $showCount := 5 }}
{{ $hasMore := gt $count $showCount }}
- 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
- url: http://www.socialpsychology.org/headlines.rss
title: socialpsychology.org
limit: 3
- url: https://youarenotsosmart.com/feed/
title: youarenotsosmart.com
limit: 3
# ==================== TEACHING/LEARNING PAGE ====================
- name: Teaching & Learning
slug: teaching
width: wide
columns:
- size: small
widgets:
- type: iframe
css-class: iframe-no-tint
source: https://glance-helper.dooplex.hu/notes?key=oplQqnLnJK2vErRVYJpvVUcSDBOSbCHZSbsYY2bwSifgTMfT&user=orsi&accent=e292ff&bgcolor=2d1f3d
height: 250
title: Quick Notes
- type: bookmarks
title: Links for Teaching
groups:
- links:
- title: Plex
url: https://plex.dooplex.hu
icon: si:plex
- type: bookmarks
title: Links for Learning
groups:
- links:
- title: Plex
url: https://plex.dooplex.hu
icon: si:plex
# ---------- CENTER COLUMN ----------
- size: full
widgets:
# Outline Notes iframe
- type: iframe
source: https://outline.dooplex.hu/collection/tanulok-HUBgG382kV/recent
height: 800
title: Recent Notes
# Cal.com Booking iframe
- type: iframe
source: https://booking.dooplex.hu/bookings/upcoming
height: 500
title: Upcoming Bookings
# ==================== 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: https://web.dooplex.hu/static/white-icons/radarr.png
- title: RadarrKids
url: https://radarrkids.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/radarrkids.png
- title: Prowlarr (Indexers)
url: https://prowlarr.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/prowlarr.png
- title: Seerr (Requests)
url: https://seerr.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/seerr.png
- 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: psychology
show-thumbnails: true
- type: reddit
subreddit: psychologystudents
show-thumbnails: true
- type: reddit
subreddit: psychologytalk
show-thumbnails: true
- type: reddit
subreddit: psychologists
show-thumbnails: true
- type: reddit
subreddit: psychologyresearch
show-thumbnails: true
- type: reddit
subreddit: academicpsychology
show-thumbnails: true
- type: reddit
subreddit: social_psychology
show-thumbnails: true
- size: small
widgets:
- type: bookmarks
title: Other Apps
groups:
- links:
- title: AdventureLog
url: https://adventures.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/adventurelog.png
- title: Wanderer
url: https://wanderer.dooplex.hu
icon: sh:wanderer
- title: Plant-it
url: https://plantit.dooplex.hu
icon: si:leaflet
- title: Workout (wger)
url: https://workout.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/wger.png
- title: Fileshare
url: https://fileshare.dooplex.hu
icon: si:files
- title: Privatebin
url: https://privatebin.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/privatebin.png
- title: Pastes (OpenGist)
url: https://paste.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/opengist.png
- title: Zipline
url: https://zipline.dooplex.hu
icon: https://web.dooplex.hu/static/white-icons/zipline.png
# ==================== FILES PAGE ====================
- name: Files
slug: files
width: wide
columns:
- size: full
widgets:
# Filebrowser iframe
- type: iframe
css-class: iframe-no-tint
source: https://orsi-files.dooplex.hu/files/
height: 1200
title: My Files
# ==================== 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 Orsi's Glance Dashboard
Purple theme with background image matching Homepage
OPTIMIZED: Duplicates removed, styles consolidated
============================================================================= */
/* =============================================================================
1. BACKGROUND & BASE TRANSPARENCY
============================================================================= */
html, body { height: 100%; }
html {
background: url("https://web.dooplex.hu/static/wallpaper-orsi.jpg") center / cover no-repeat fixed !important;
}
/* Make all Glance containers transparent to show wallpaper */
body,
.page,
#page-content,
.page-content,
.content-bounds,
.body-content,
.page-columns,
.page-column {
background: transparent !important;
}
/* Readability veil overlay */
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; }
/* =============================================================================
2. HEADER & NAVIGATION
============================================================================= */
.header-container,
.header,
.page-header,
.nav,
.navigation {
background: transparent !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
box-shadow: none !important;
border: 0 !important;
}
.header {
min-height: 150px !important;
display: flex !important;
align-items: flex-end !important;
gap: 18px !important;
padding: 16px 18px !important;
}
/* Logo sizing */
.logo img {
max-height: 170px !important;
height: auto !important;
width: auto !important;
object-fit: contain !important;
}
/* Nav alignment and styling (consolidated) */
.header.flex > .nav.flex {
height: 100% !important;
align-items: flex-end !important;
padding-bottom: 14px !important;
}
.header.flex > .nav.flex > .nav-item {
display: flex !important;
align-items: flex-end !important;
height: 100% !important;
padding: 0 14px 18px 14px !important;
font-size: 20px !important;
line-height: 1 !important;
}
/* Current tab underline */
.header .nav .nav-item-current::after,
.header .nav .nav-item[aria-current="page"]::after {
bottom: -6px !important;
}
/* =============================================================================
3. WIDGETS - BASE STYLING
============================================================================= */
.widget {
background: rgba(45, 31, 61, 0.55) !important;
border: 1px solid rgba(226, 146, 255, 0.3) !important;
border-radius: 10px !important;
backdrop-filter: blur(6px) !important;
-webkit-backdrop-filter: blur(6px) !important;
}
.widget-content {
background: transparent !important;
}
/* Widget headers */
.widget-header {
display: flex !important;
align-items: center !important;
border-bottom-color: rgba(226, 146, 255, 0.25) !important;
}
.widget-header,
.widget-title {
color: #e292ff !important;
font-weight: 600 !important;
}
.widget-header .widget-title {
display: flex !important;
align-items: center !important;
line-height: 1.2 !important;
}
/* =============================================================================
4. SPLIT-COLUMN WIDGET
============================================================================= */
/* Container keeps glassy effect */
.widget.widget-type-split-column {
background: rgba(45, 31, 61, 0.55) !important;
border: 1px solid rgba(226, 146, 255, 0.15) !important;
backdrop-filter: blur(6px) !important;
-webkit-backdrop-filter: blur(6px) !important;
}
/* Content area - NO TOP PADDING to align headers with other widgets */
.widget.widget-type-split-column > .widget-content {
padding: 0 3px 8px 3px !important;
}
/* Inner widgets should be transparent */
.widget-type-split-column .masonry-column .widget,
.widget-type-split-column .widget-content .widget {
background: transparent !important;
border: none !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
box-shadow: none !important;
}
/* Masonry layout */
.widget-type-split-column .masonry-column {
background: transparent !important;
overflow: visible !important;
}
.widget-type-split-column .masonry {
gap: 16px !important;
}
/* Inner widget headers - compact styling */
.widget-type-split-column .widget .widget-header {
display: flex !important;
align-items: center !important;
justify-content: flex-start !important;
min-height: unset !important;
height: auto !important;
padding: 0 0 8px 0 !important;
margin: 0 !important;
}
.widget-type-split-column .widget .widget-header .widget-title {
font-size: 0.9rem !important;
line-height: 1 !important;
padding: 0 !important;
margin: 0 !important;
}
/* =============================================================================
5. IFRAME WIDGETS
============================================================================= */
.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;
}
/* Header above overlay */
.widget.widget-type-iframe > .widget-header {
position: relative;
z-index: 3;
}
/* Purple overlay - positioned below header */
.widget.widget-type-iframe::after {
content: "";
position: absolute;
top: 45px;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
pointer-events: none;
border-radius: 0 0 12px 12px;
background: rgba(226, 146, 255, 0.16);
}
/* Frameless iframes - overlay covers everything */
.widget.widget-type-iframe.widget-content-frameless::after {
top: 0;
border-radius: 12px;
}
/* No-tint iframes (disable filter and overlay) */
.widget.iframe-no-tint iframe {
filter: none !important;
background: transparent !important;
}
.widget.iframe-no-tint::after {
content: none !important;
display: none !important;
}
/* =============================================================================
6. LINKS & INTERACTIVE ELEMENTS
============================================================================= */
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;
}
/* 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;
}
/* =============================================================================
7. EXPAND/COLLAPSE BUTTONS
============================================================================= */
.expand-toggle-button,
.expand-toggle-button.container-expanded {
background: transparent !important;
box-shadow: none !important;
border: 0 !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
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;
}
.expand-toggle-button:hover {
color: rgba(255,255,255,0.95) !important;
}
.expand-toggle-button::before,
.expand-toggle-button::after,
.expand-toggle-button-icon::before,
.expand-toggle-button-icon::after {
background: transparent !important;
box-shadow: none !important;
}
/* =============================================================================
8. 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);
}
/* =============================================================================
9. IDŐKÉP WEATHER WIDGET
============================================================================= */
.idokep { display: flex; flex-direction: column; gap: 10px; }
.idokep-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.idokep-top-left { display: flex; align-items: center; gap: 10px; }
.idokep-icon { width: 42px; height: 42px; opacity: 0.95; }
.idokep-temp { font-size: 42px; font-weight: 700; letter-spacing: 0.5px; line-height: 1; }
.idokep-top-right { text-align: right; }
.idokep-loc { opacity: 0.85; font-weight: 600; }
.idokep-src { opacity: 0.6; font-size: 12px; margin-top: 2px; }
.idokep-src a { opacity: 0.9; }
.idokep-hourly { display: flex; gap: 6px; padding-top: 4px; }
.idokep-hour { width: 48px; display: flex; flex-direction: column; align-items: center; gap: 6px; opacity: 0.9; }
.idokep-hour-time { font-size: 12px; opacity: 0.65; }
.idokep-hour-icon { width: 26px; height: 26px; }
.idokep-hour-temp { font-weight: 700; }
.idokep-muted { opacity: 0.6; font-size: 12px; padding: 4px 0; }
.idokep-daily { display: flex; flex-direction: column; gap: 8px; margin-top: 2px; }
.idokep-row {
display: grid;
grid-template-columns: 44px 26px 36px 1fr 36px;
gap: 10px;
align-items: center;
}
.idokep-dow {
display: grid;
grid-template-columns: 22px 1fr;
column-gap: 6px;
align-items: center;
opacity: 0.8;
font-weight: 700;
}
.idokep-daynum {
text-align: right;
opacity: 0.75;
font-variant-numeric: tabular-nums;
}
.idokep-dayicon img { width: 22px; height: 22px; opacity: 0.95; }
.idokep-min, .idokep-max { text-align: right; font-weight: 700; opacity: 0.8; }
/* Temperature bar */
.idokep-bar {
position: relative;
height: 10px;
}
.idokep-bar-track {
position: absolute;
inset: 0;
border-radius: 999px;
background: rgba(255,255,255,0.10);
}
.idokep-bar-fill {
position: absolute;
top: 0;
bottom: 0;
border-radius: 999px;
overflow: hidden;
box-shadow: 0 0 0 1px rgba(0,0,0,0.08) inset;
left: var(--l, 0%);
width: var(--w, 0%);
}
.idokep-bar-gradient {
position: absolute;
top: 0;
bottom: 0;
width: var(--gw, 100%);
margin-left: var(--ml, 0%);
background: linear-gradient(90deg,
#ffffff var(--s-wht),
#60a5fa var(--s-blu),
#a78bfa var(--s-pur),
#fb7185 var(--s-pnk),
#ef4444 var(--s-red)
);
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: glance-orsi
namespace: glance-system
labels:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
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-orsi
app.kubernetes.io/instance: glance-orsi
template:
metadata:
labels:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
app.kubernetes.io/version: "v0.8.4"
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
initContainers:
- name: build-bookmarks-index
image: mikefarah/yq:4.50.1
securityContext:
runAsUser: 1000
runAsGroup: 1000
allowPrivilegeEscalation: false
command: ["/bin/sh", "-c"]
args:
- |
set -eux
which yq
yq --version
mkdir -p /app/assets
yq eval -o=json '
[ .pages[] as $p
| $p.columns[]? as $c
| $c.widgets[]? as $w
| select($w.type == "bookmarks")
| $w.groups[]? as $g
| $g.links[]?
| select(.url != null and .url != "")
| {
"title": (.title // .url),
"url": .url,
"page": ($p.name // ""),
"widget": ($w.title // ""),
"group": ($g.title // "")
}
] | unique_by(.url)
' /config/glance.yml > /app/assets/bookmarks.json
echo "Bookmarks indexed: $(yq eval -r 'length' /app/assets/bookmarks.json)"
volumeMounts:
- name: config
mountPath: /config
readOnly: true
- name: assets
mountPath: /app/assets
containers:
- name: glance
image: glanceapp/glance:v0.8.4
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: "Europe/Budapest"
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: assets
mountPath: /app/assets
- name: config
mountPath: /app/config/glance.yml
subPath: glance.yml
- name: config
mountPath: /app/assets/custom.css
subPath: custom.css
volumes:
- name: config
configMap:
name: glance-config
- name: assets
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: glance-orsi
namespace: glance-system
labels:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
spec:
type: ClusterIP
ports:
- name: http
port: 8080
targetPort: http
protocol: TCP
selector:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
---
# 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-orsi
namespace: glance-system
labels:
app.kubernetes.io/name: glance-orsi
app.kubernetes.io/instance: glance-orsi
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
external-dns.alpha.kubernetes.io/hostname: orsi.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-home-outpost' with your actual outpost name after creating in Authentik
nginx.ingress.kubernetes.io/auth-url: http://ak-outpost-glance-orsi-outpost.auth-system.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx
nginx.ingress.kubernetes.io/auth-signin: https://orsi.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;
nginx.ingress.kubernetes.io/configuration-snippet: |
set $geo_allowed 0;
if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; }
if ($remote_addr ~ "^10\.") { set $geo_allowed 1; }
if ($geoip2_country_code = "HU") { set $geo_allowed 1; }
if ($geo_allowed = 0) {
return 403 "Access restricted to Hungary";
}
spec:
ingressClassName: nginx-internal
rules:
- host: orsi.dooplex.hu
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: glance-orsi
port:
number: 8080
tls:
- hosts:
- orsi.dooplex.hu
secretName: glance-orsi-tls
---