replace all service favicons and logos with throwback branding
All checks were successful
ci/woodpecker/push/infra-ci Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

Pixel-art "H" favicon (navy/red/cream) injected via Traefik rewrite
for themed services and via new inject-favicon middleware for
woodpecker, notebooks, and zotero. Volume mounts override native
favicon/logo files in Gitea, Grafana, and Marimo containers.
Dashboard gets direct favicon link in HTML.
This commit is contained in:
kert
2026-02-28 18:38:41 -05:00
parent 245ef1c3b6
commit 2163000b7f
11 changed files with 42 additions and 6 deletions

View File

@@ -117,6 +117,9 @@ services:
- gitea_config:/etc/gitea - gitea_config:/etc/gitea
- ./gitea/custom:/var/lib/gitea/custom:ro - ./gitea/custom:/var/lib/gitea/custom:ro
- ./css/gitea.css:/var/lib/gitea/custom/public/assets/css/theme-throwback.css:ro - ./css/gitea.css:/var/lib/gitea/custom/public/assets/css/theme-throwback.css:ro
- ./css/favicon.svg:/var/lib/gitea/custom/public/assets/img/favicon.svg:ro
- ./css/favicon.png:/var/lib/gitea/custom/public/assets/img/favicon.png:ro
- ./css/logo.svg:/var/lib/gitea/custom/public/assets/img/logo.svg:ro
ports: ports:
- "2222:2222" - "2222:2222"
depends_on: depends_on:
@@ -187,6 +190,11 @@ services:
- ./notebooks/.marimo-config:/home/kert/.config/marimo:ro - ./notebooks/.marimo-config:/home/kert/.config/marimo:ro
- ./css/marimo.css:/home/kert/.config/marimo/retro-arcade.css:ro - ./css/marimo.css:/home/kert/.config/marimo/retro-arcade.css:ro
- ./notebooks/home-page-DUMF8ZY4.js:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/assets/home-page-DUMF8ZY4.js:ro - ./notebooks/home-page-DUMF8ZY4.js:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/assets/home-page-DUMF8ZY4.js:ro
- ./css/favicon.svg:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/favicon.ico:ro
- ./css/fav32.png:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/favicon-32x32.png:ro
- ./css/fav16.png:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/favicon-16x16.png:ro
- ./css/logo.png:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/logo.png:ro
- ./css/apple-touch-icon.png:/home/kert/workspace/.venv/lib/python3.13/site-packages/marimo/_static/apple-touch-icon.png:ro
- ./data:/home/kert/data - ./data:/home/kert/data
- ./zotero/data:/home/kert/zotero:ro - ./zotero/data:/home/kert/zotero:ro
- ./src:/home/kert/src:ro - ./src:/home/kert/src:ro
@@ -335,6 +343,7 @@ services:
- ./nginx/index.html:/usr/share/nginx/html/index.html:ro - ./nginx/index.html:/usr/share/nginx/html/index.html:ro
- ./css/dashboard.css:/usr/share/nginx/html/dashboard.css:ro - ./css/dashboard.css:/usr/share/nginx/html/dashboard.css:ro
- ./css/inject.css:/usr/share/nginx/html/throwback.css:ro - ./css/inject.css:/usr/share/nginx/html/throwback.css:ro
- ./css/favicon.svg:/usr/share/nginx/html/favicon.svg:ro
security_opt: security_opt:
- no-new-privileges:true - no-new-privileges:true
restart: unless-stopped restart: unless-stopped
@@ -443,6 +452,9 @@ services:
- ./grafana/provisioning:/etc/grafana/provisioning:ro - ./grafana/provisioning:/etc/grafana/provisioning:ro
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro - ./grafana/dashboards:/var/lib/grafana/dashboards:ro
- grafana_data:/var/lib/grafana - grafana_data:/var/lib/grafana
- ./css/favicon.svg:/usr/share/grafana/public/img/grafana_icon.svg:ro
- ./css/fav32.png:/usr/share/grafana/public/img/fav32.png:ro
- ./css/apple-touch-icon.png:/usr/share/grafana/public/img/apple-touch-icon.png:ro
depends_on: depends_on:
- loki - loki
- jaeger - jaeger

BIN
css/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

BIN
css/fav16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

BIN
css/fav32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

BIN
css/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

8
css/favicon.svg Normal file
View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" shape-rendering="crispEdges">
<rect width="16" height="16" fill="#0a1628"/>
<rect y="14" width="16" height="2" fill="#cc2244"/>
<!-- H letterform: pixel-art style -->
<rect x="3" y="2" width="3" height="10" fill="#e8e0d4"/>
<rect x="10" y="2" width="3" height="10" fill="#e8e0d4"/>
<rect x="6" y="5" width="4" height="3" fill="#e8e0d4"/>
</svg>

After

Width:  |  Height:  |  Size: 417 B

BIN
css/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 921 B

8
css/logo.svg Normal file
View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" shape-rendering="crispEdges">
<rect width="32" height="32" rx="4" fill="#0a1628"/>
<rect y="28" width="32" height="4" rx="0" fill="#cc2244"/>
<!-- H letterform: pixel-art style, scaled 2x -->
<rect x="6" y="4" width="6" height="20" fill="#e8e0d4"/>
<rect x="20" y="4" width="6" height="20" fill="#e8e0d4"/>
<rect x="12" y="10" width="8" height="6" fill="#e8e0d4"/>
</svg>

After

Width:  |  Height:  |  Size: 444 B

View File

@@ -4,6 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HOMELAB COMMAND CENTER</title> <title>HOMELAB COMMAND CENTER</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="stylesheet" href="/dashboard.css"> <link rel="stylesheet" href="/dashboard.css">
</head> </head>
<body> <body>

View File

@@ -13,8 +13,8 @@ http {
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;
# CORS for CSS files (loaded cross-origin by themed services) # CORS for theme assets (loaded cross-origin by themed services)
location ~* \.css$ { location ~* \.(css|svg|png|ico)$ {
add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS"; add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Cache-Control "public, max-age=3600"; add_header Cache-Control "public, max-age=3600";

View File

@@ -16,9 +16,9 @@
{{- $reef := dict {{- $reef := dict
"dashboard" (dict "port" "80" "theme" false "extra_hosts" (list $domain) "mw" "secure-headers") "dashboard" (dict "port" "80" "theme" false "extra_hosts" (list $domain) "mw" "secure-headers")
"gitea" (dict "port" "3000" "theme" false "mw" "secure-headers,rate-limit") "gitea" (dict "port" "3000" "theme" false "mw" "secure-headers,rate-limit")
"woodpecker-server" (dict "port" "8000" "theme" false "subdomain" "ci" "mw" "local-only,secure-headers,rate-limit") "woodpecker-server" (dict "port" "8000" "theme" false "subdomain" "ci" "mw" "inject-favicon,local-only,secure-headers,rate-limit")
"notebooks" (dict "port" "2718" "theme" false "mw" "local-only,secure-headers") "notebooks" (dict "port" "2718" "theme" false "mw" "inject-favicon,local-only,secure-headers")
"zotero" (dict "port" "8080" "theme" false "mw" "secure-headers") "zotero" (dict "port" "8080" "theme" false "mw" "inject-favicon,secure-headers")
"nessie" (dict "port" "19120" "theme" false "mw" "local-only,infra-headers") "nessie" (dict "port" "19120" "theme" false "mw" "local-only,infra-headers")
"trino" (dict "port" "8080" "theme" true "mw" "local-only,infra-headers") "trino" (dict "port" "8080" "theme" true "mw" "local-only,infra-headers")
"polaris" (dict "port" "8181" "theme" false "mw" "local-only,infra-headers") "polaris" (dict "port" "8181" "theme" false "mw" "local-only,infra-headers")
@@ -67,7 +67,14 @@ http:
lastModified: true lastModified: true
rewrites: rewrites:
- regex: "</head>" - regex: "</head>"
replacement: '<link rel="stylesheet" type="text/css" href="http://{{ $domain }}/throwback.css"></head>' replacement: '<link rel="icon" type="image/svg+xml" href="http://{{ $domain }}/favicon.svg"><link rel="stylesheet" type="text/css" href="http://{{ $domain }}/throwback.css"></head>'
inject-favicon:
plugin:
rewrite-body:
lastModified: true
rewrites:
- regex: "</head>"
replacement: '<link rel="icon" type="image/svg+xml" href="http://{{ $domain }}/favicon.svg"></head>'
{{/* ── Generated routers ─────────────────────────────────────── */}} {{/* ── Generated routers ─────────────────────────────────────── */}}
routers: routers: