Gitea theme: capital theta (circle+H) logo + homepage senza badge

- Logo/favicon ridisegnati come theta maiuscola: cerchio (anello)
  con 'H' centrata, clearance verificata (non tocca l'anello); ring
  ispessito per la favicon; centratura ottica verificata.
- Rimosso il badge 'Self-hosted Git' dal hero della homepage (era
  esteticamente di troppo) - CSS e markup.
- Aggiornati generate_theta.py, README, home.tmpl; caricati sul VPS in
  staging (md5 locali == remoti); tarball ricostruito.
- Salvataggio iniziale dell'intero admin pack in git.
This commit is contained in:
2026-09-01 16:54:15 +02:00
commit f5c763be7b
23 changed files with 1430 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
# Gitea theme pack — git.zomas.net
Homepage moderna + favicon/logo personalizzati per l'istanza Gitea.
## Contenuto
```
custom/
templates/home.tmpl # homepage pubblica ridisegnata
public/assets/img/logo.svg # logo (navbar + hero)
public/assets/img/logo.png
public/assets/img/favicon.svg # icona tab browser (SVG)
public/assets/img/favicon.png # favicon fallback (PNG)
public/assets/img/apple-touch-icon.png
install_gitea_theme.sh # installer — da eseguire come ROOT sul VPS
rollback_gitea_theme.sh # ripristino stato iniziale — da eseguire come ROOT
gitea_theme.sh # script UNICO: install o rollback (consigliato)
generate_theta.py # rigenera logo/favicon con theta greca (opzionale, serve PIL)
```
La homepage pubblica (la landing page che si vede su git.zomas.net
senza login) è ora un hero con gradiente, titolo, tagline e 4
feature card. Usa solo CSS inline + variabili tematiche di Gitea, quindi
rispetta automaticamente tema chiaro/scuro.
Il logo è una THETA MAIUSCOLA (Θ): un cerchio (anello) con una "H"
centrata. La H non tocca i bordi dell'anello (clearance verificata),
in bianco su quadrato arrotondato con gradiente viola→azzurro.
Niente badge "Self-hosted Git" sopra il logo (era esteticamente di
troppo) — il hero parte direttamente dal logo.
## Requisiti / limitazione
Installare questi file richiede **accesso root** (o appartenenza al
gruppo `gitea`) sul VPS: la cartella `/var/lib/gitea/custom` non è
scrivibile dall'utente SSH `deb_zomas_connection`. L'installer va quindi
lanciato da chi ha root.
I file sono già stati caricati sul VPS in staging (dall'utente
`deb_zomas_connection`) in `/var/tmp/gitea-theme/` — pronto per essere
installato da root.
## Applicazione (root sul VPS) — script UNICO
I file sono già sul VPS. Da root, uno script solo gestisce tutto:
```bash
cd /var/tmp/gitea-theme/gitea-theme-pack
bash gitea_theme.sh install # applica homepage moderna + favicon
bash gitea_theme.sh rollback # torna allo stato iniziale (se non piace)
```
Lo script `gitea_theme.sh` è l'unico che serve:
- `install` salva il backup delle eventuali personalizzazioni in
`/var/lib/gitea/custom/.backup-*`, copia i file, imposta i permessi
`gitea:gitea`, scrive lo stato in `$CUSTOM_DIR/.gitea-theme-state`,
riavvia Gitea e verifica gli asset.
- `rollback` rimuove homepage+favicon custom, ripristina la precedente
personalizzazione dal backup (se esiste), riavvia Gitea.
(Permangono anche `install_gitea_theme.sh` e `rollback_gitea_theme.sh`
come equivalenti separati, per chi preferisce un comando per azione.)
3. Sul browser apri https://git.zomas.net premendo **Ctrl+Shift+R**
(hard reload) per bypassare la cache.
## Ripristino
Se la modifica non piace, da root sul VPS:
```bash
cd /var/tmp/gitea-theme/gitea-theme-pack
bash gitea_theme.sh rollback
```
Lo script rimuove homepage + favicon custom, ripristina l'eventuale
personalizzazione precedente dal backup (se esiste), riavvia Gitea e
verifica. In alternativa il ripristino manuale è:
```bash
rm -rf /var/lib/gitea/custom/templates/home.tmpl /var/lib/gitea/custom/public/assets/img
systemctl restart gitea
```
La vecchia homepage è comunque salvata anche su questo PC in
`/home/zomas/vps-admin/homepage-backup/homepage_original_20260901-152245.html`.
## Note
- Gitea 1.27.3. Homepage di riferimento: stock `templates/home.tmpl`.
- Le icone octicon usate (`git-branch`, `shield-check`, `telescope`,
`sign-in`, `repo`, `code`, `rocket`) e le chiavi locale
(`dashboard`, `explore_title`, `sign_in`, `home_title`) sono verificate
esistenti nel sorgente Gitea 1.27.3.
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
<defs><linearGradient id="zg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#7c3aed"/><stop offset="1" stop-color="#0ea5e9"/></linearGradient></defs>
<rect x="2.56" y="2.56" width="58.88" height="58.88" rx="14.08" fill="url(#zg)"/>
<path fill-rule="evenodd" fill="#fff" d="M 5.76 32.00 A 26.24 26.24 0 1 0 58.24 32.00 A 26.24 26.24 0 1 0 5.76 32.00 ZM 8.96 32.00 A 23.04 23.04 0 1 0 55.04 32.00 A 23.04 23.04 0 1 0 8.96 32.00 Z"/>
<rect x="21.12" y="15.36" width="3.20" height="33.28" fill="#fff"/>
<rect x="39.68" y="15.36" width="3.20" height="33.28" fill="#fff"/>
<rect x="21.12" y="30.66" width="21.76" height="2.69" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
<defs><linearGradient id="zg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#7c3aed"/><stop offset="1" stop-color="#0ea5e9"/></linearGradient></defs>
<rect x="2.56" y="2.56" width="58.88" height="58.88" rx="14.08" fill="url(#zg)"/>
<path fill-rule="evenodd" fill="#fff" d="M 5.76 32.00 A 26.24 26.24 0 1 0 58.24 32.00 A 26.24 26.24 0 1 0 5.76 32.00 ZM 8.96 32.00 A 23.04 23.04 0 1 0 55.04 32.00 A 23.04 23.04 0 1 0 8.96 32.00 Z"/>
<rect x="21.12" y="15.36" width="3.20" height="33.28" fill="#fff"/>
<rect x="39.68" y="15.36" width="3.20" height="33.28" fill="#fff"/>
<rect x="21.12" y="30.66" width="21.76" height="2.69" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 749 B

+143
View File
@@ -0,0 +1,143 @@
{{template "base/head" .}}
<style>
.zm-hero {
position: relative;
overflow: hidden;
padding: 3.5rem 1.5rem 4rem;
text-align: center;
}
.zm-hero::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(60rem 30rem at 20% 0%, rgba(124, 58, 237, 0.18), transparent 60%),
radial-gradient(50rem 26rem at 85% 10%, rgba(14, 165, 233, 0.18), transparent 60%);
pointer-events: none;
}
.zm-hero-logo {
margin: 1.5rem auto 1rem;
width: 120px;
height: 120px;
filter: drop-shadow(0 12px 24px rgba(80, 70, 229, 0.25));
}
.zm-hero h1 {
font-size: clamp(2rem, 5vw, 3.4rem);
font-weight: 800;
line-height: 1.1;
margin: 0 0 0.6rem;
letter-spacing: -0.02em;
}
.zm-hero p.lead {
max-width: 46rem;
margin: 0 auto 2rem;
font-size: 1.15rem;
line-height: 1.6;
opacity: 0.85;
}
.zm-ctas {
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
justify-content: center;
}
.zm-ctas .ui.button {
padding: 0.7rem 1.4rem;
font-weight: 600;
border-radius: 0.55rem;
}
.zm-features {
max-width: 66rem;
margin: 2.5rem auto 1rem;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
gap: 1rem;
padding: 0 1.5rem;
}
.zm-feature {
border-radius: 0.9rem;
padding: 1.3rem 1.3rem 1.4rem;
background: var(--color-box-header, #f0f0f0);
border: 1px solid var(--color-secondary, rgba(0, 0, 0, 0.1));
text-align: left;
transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.zm-feature:hover {
transform: translateY(-3px);
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
}
.zm-feature .zm-ico {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.4rem;
height: 2.4rem;
border-radius: 0.6rem;
margin-bottom: 0.8rem;
color: #fff;
background: linear-gradient(135deg, #7c3aed, #0ea5e9);
}
.zm-feature h3 {
margin: 0 0 0.35rem;
font-size: 1.05rem;
}
.zm-feature p {
margin: 0;
font-size: 0.92rem;
line-height: 1.55;
opacity: 0.82;
}
@media (prefers-color-scheme: dark) {
.zm-feature { background: var(--color-box-header, #1a1a1a); }
}
</style>
<div role="main" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home_title"}}{{end}}" class="page-content home">
<div class="zm-hero">
<img class="zm-hero-logo" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{AppName}}" width="120" height="120">
<h1>{{AppName}}</h1>
<p class="lead">
Il tuo spazio Git personale, veloce e affidabile.
Gestisci repository, collabora e tieni tutto sotto controllo, con un unico account.
</p>
<div class="zm-ctas">
{{if .IsSigned}}
<a class="ui primary button" href="{{AppSubUrl}}/">
{{svg "octicon-rocket" 16}}&nbsp;{{ctx.Locale.Tr "dashboard"}}
</a>
<a class="ui secondary button" href="{{AppSubUrl}}/explore/repos">
{{svg "octicon-telescope" 16}}&nbsp;{{ctx.Locale.Tr "explore_title"}}
</a>
{{else}}
<a class="ui primary button" href="{{AppSubUrl}}/user/login">
{{svg "octicon-sign-in" 16}}&nbsp;{{ctx.Locale.Tr "sign_in"}}
</a>
<a class="ui secondary button" href="{{AppSubUrl}}/explore/repos">
{{svg "octicon-telescope" 16}}&nbsp;{{ctx.Locale.Tr "explore_title"}}
</a>
{{end}}
</div>
</div>
<div class="zm-features">
<div class="zm-feature">
<div class="zm-ico">{{svg "octicon-rocket" 22}}</div>
<h3>Veloce e leggero</h3>
<p>Prestazioni elevate anche su risorse ridotte. Il tuo codice, sempre a portata di mano.</p>
</div>
<div class="zm-feature">
<div class="zm-ico">{{svg "octicon-shield-check" 22}}</div>
<h3>Sicuro e privato</h3>
<p>Accessi protetti e controllo completo sui tuoi repository, dalla creazione alla condivisione.</p>
</div>
<div class="zm-feature">
<div class="zm-ico">{{svg "octicon-git-branch" 22}}</div>
<h3>Versioning semplice</h3>
<p>Branches, pull request e collaborazione fluida, progettati per chi scrive codice ogni giorno.</p>
</div>
<div class="zm-feature">
<div class="zm-ico">{{svg "octicon-code" 22}}</div>
<h3>Open source</h3>
<p>Costruito con tecnologie aperte e libere. Nessun blocco, tutta la flessibilità di cui hai bisogno.</p>
</div>
</div>
</div>
{{template "base/footer" .}}
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
# Logo/favicon Gitea: THETA MAIUSCOLA = cerchio (anello) con una "H" al centro.
# La H non tocca l'anello (clearance sicura). Niente coda.
# Emette sia gli SVG (logo/favicon) che i PNG (logo/favicon/apple-touch-icon)
# partendo dalla STESSA geometria, così SVG e PNG combaciano.
import os
from PIL import Image, ImageDraw
OUT = "custom/public/assets/img"
# --- geometria normalizzata (frazioni del lato quadrato) ---
INSET = 0.04 # bordo del riquadro arrotondato
RAD = 0.22 # raggio angoli del riquadro
CX, CY = 0.5, 0.5 # centro (simmetrico, nessuna coda)
RO = 0.41 # raggio esterno anello
RING = 0.05 # spessore anello -> raggio interno RI = RO - RING
# H centrale
HH = 0.26 # mezza altezza della H (stelo da CY-HH a CY+HH)
SPAC = 0.145 # distanza orizzontale dal centro agli steli
STEM = 0.05 # spessore steli
CROSS = 0.042 # spessore barra orizzontale
C1, C2 = (124, 58, 237), (14, 165, 233) # viola -> azzurro
RI = RO - RING
def lerp(a, b, t):
return int(a + (b - a) * t)
def grad_color(t):
return (lerp(C1[0], C2[0], t), lerp(C1[1], C2[1], t), lerp(C1[2], C2[2], t))
def theta_geo(size):
cx, cy = CX * size, CY * size
ro, ri = RO * size, RI * size
stem = STEM * size
cross = CROSS * size
# steli: centro x = cx ± SPAC
left_x0 = (CX - SPAC - STEM / 2) * size
left_x1 = (CX - SPAC + STEM / 2) * size
right_x0 = (CX + SPAC - STEM / 2) * size
right_x1 = (CX + SPAC + STEM / 2) * size
st_y0, st_y1 = (CY - HH) * size, (CY + HH) * size
# barra: attraversa tutta la larghezza della H, centrata su CY
cb_y0, cb_y1 = CY * size - cross / 2, CY * size + cross / 2
return dict(cx=cx, cy=cy, ro=ro, ri=ri,
left_x0=left_x0, left_x1=left_x1,
right_x0=right_x0, right_x1=right_x1,
st_y0=st_y0, st_y1=st_y1,
cb_x0=left_x0, cb_x1=right_x1, cb_y0=cb_y0, cb_y1=cb_y1,
stem=stem, cross=cross)
def circle_path(r, cx, cy, size):
lx, rx = cx - r, cx + r
return (f"M {lx:.2f} {cy:.2f} A {r:.2f} {r:.2f} 0 1 0 {rx:.2f} {cy:.2f} "
f"A {r:.2f} {r:.2f} 0 1 0 {lx:.2f} {cy:.2f} Z")
def svg_theta(size):
g = theta_geo(size)
inset, rad = INSET * size, RAD * size
w = size
def e(x):
return f"{x:.2f}"
outer = circle_path(g["ro"], g["cx"], g["cy"], size)
inner = circle_path(g["ri"], g["cx"], g["cy"], size)
lines = []
lines.append(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {size} {size}" width="{size}" height="{size}">')
lines.append(' <defs><linearGradient id="zg" x1="0" y1="0" x2="0" y2="1">'
'<stop offset="0" stop-color="#7c3aed"/><stop offset="1" stop-color="#0ea5e9"/></linearGradient></defs>')
lines.append(f' <rect x="{e(inset)}" y="{e(inset)}" width="{e(w-2*inset)}" height="{e(w-2*inset)}" rx="{e(rad)}" fill="url(#zg)"/>')
# anello (theta maiuscola = cerchio)
lines.append(f' <path fill-rule="evenodd" fill="#fff" d="{outer}{inner}"/>')
# H centrale (steli + barra)
lines.append(f' <rect x="{e(g["left_x0"])}" y="{e(g["st_y0"])}" width="{e(g["left_x1"]-g["left_x0"])}" height="{e(g["st_y1"]-g["st_y0"])}" fill="#fff"/>')
lines.append(f' <rect x="{e(g["right_x0"])}" y="{e(g["st_y0"])}" width="{e(g["right_x1"]-g["right_x0"])}" height="{e(g["st_y1"]-g["st_y0"])}" fill="#fff"/>')
lines.append(f' <rect x="{e(g["cb_x0"])}" y="{e(g["cb_y0"])}" width="{e(g["cb_x1"]-g["cb_x0"])}" height="{e(g["cb_y1"]-g["cb_y0"])}" fill="#fff"/>')
lines.append('</svg>')
return "\n".join(lines) + "\n"
def draw_theta_png(size, apple=False):
g = theta_geo(size)
img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
inset, rad = INSET * size, RAD * size
# sfondo: riquadro arrotondato con gradiente verticale
sq = Image.new("L", (size, size), 0)
ImageDraw.Draw(sq).rounded_rectangle(
[inset, inset, size - inset, size - inset], radius=rad, fill=255)
grad = Image.new("RGBA", (size, size), (0, 0, 0, 0))
gd = ImageDraw.Draw(grad)
for i in range(size * 2):
t = i / (size * 2 - 1)
gd.line([(i, 0), (i, size)], fill=grad_color(t))
grad.putalpha(sq)
img.alpha_composite(grad)
# theta+H come maschera bianca
mask = Image.new("L", (size, size), 0)
md = ImageDraw.Draw(mask)
md.ellipse([g["cx"] - g["ro"], g["cy"] - g["ro"],
g["cx"] + g["ro"], g["cy"] + g["ro"]], fill=255)
md.ellipse([g["cx"] - g["ri"], g["cy"] - g["ri"],
g["cx"] + g["ri"], g["cy"] + g["ri"]], fill=0)
md.rectangle([g["left_x0"], g["st_y0"], g["left_x1"], g["st_y1"]], fill=255)
md.rectangle([g["right_x0"], g["st_y0"], g["right_x1"], g["st_y1"]], fill=255)
md.rectangle([g["cb_x0"], g["cb_y0"], g["cb_x1"], g["cb_y1"]], fill=255)
white = Image.new("RGBA", (size, size), (255, 255, 255, 255))
white.putalpha(mask)
img.alpha_composite(white)
if apple:
base = Image.new("RGBA", img.size, (255, 255, 255, 255))
base.alpha_composite(img)
return base.convert("RGB")
return img
def make_assets():
os.makedirs(OUT, exist_ok=True)
open(f"{OUT}/logo.svg", "w").write(svg_theta(64))
open(f"{OUT}/favicon.svg", "w").write(svg_theta(64))
draw_theta_png(220).save(f"{OUT}/logo.png")
draw_theta_png(64).save(f"{OUT}/favicon.png")
draw_theta_png(180, apple=True).save(f"{OUT}/apple-touch-icon.png")
print("theta (capital: circle + H) assets written to", OUT)
if __name__ == "__main__":
make_assets()
+133
View File
@@ -0,0 +1,133 @@
#!/bin/bash
# Gitea theme manager — installa o ripristina homepage + favicon custom.
# DA ESEGUIRE COME ROOT SUL VPS (o con sudo).
#
# Uso:
# bash gitea_theme.sh install # applica la homepage moderna + favicon
# bash gitea_theme.sh rollback # torna allo stato iniziale
# bash gitea_theme.sh # come "install"
set -euo pipefail
CUSTOM_DIR="${CUSTOM_DIR:-/var/lib/gitea/custom}"
SRC_DIR="$(cd "$(dirname "$0")" && pwd)/custom"
STATE_FILE="$CUSTOM_DIR/.gitea-theme-state"
MODE="${1:-install}"
case "$MODE" in
install|rollback) : ;;
*) echo "Uso: $0 [install|rollback]"; exit 2 ;;
esac
if [ "$(id -u)" != "0" ]; then
echo "ERRORE: devi eseguire questo script come root (o sudo)."
exit 1
fi
# ---------------------------------------------------------------- verifica
echo "==> Modalità: $MODE"
echo "==> Custom dir: $CUSTOM_DIR"
# ---------------------------------------------------------------- install
install_theme() {
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_DIR="${CUSTOM_DIR}/.backup-${STAMP}"
if [ ! -d "$SRC_DIR" ]; then
echo "ERRORE: cartella sorgente '$SRC_DIR' non trovata (script in cartella sbagliata?)."
exit 1
fi
# 1) Backup delle eventuali personalizzazioni esistenti
HAD_PREV=no
if [ -e "$CUSTOM_DIR/templates/home.tmpl" ] || [ -e "$CUSTOM_DIR/public/assets/img" ]; then
HAD_PREV=yes
mkdir -p "$BACKUP_DIR"
for p in templates/home.tmpl public/assets/img; do
if [ -e "$CUSTOM_DIR/$p" ]; then
mkdir -p "$BACKUP_DIR/$(dirname "$p")"
cp -a "$CUSTOM_DIR/$p" "$BACKUP_DIR/$p"
echo "==> Backup salvato: $BACKUP_DIR/$p"
fi
done
else
echo "==> Nessuna personalizzazione precedente, niente da salvare."
fi
# 2) Copia dei nuovi file
mkdir -p "$CUSTOM_DIR/templates" "$CUSTOM_DIR/public/assets/img"
cp "$SRC_DIR/templates/home.tmpl" "$CUSTOM_DIR/templates/home.tmpl"
cp "$SRC_DIR/public/assets/img/"* "$CUSTOM_DIR/public/assets/img/"
echo "==> File copiati:"
ls -l "$CUSTOM_DIR/templates/home.tmpl"
ls -l "$CUSTOM_DIR/public/assets/img/"
# 3) Permessi corretti (il processo gitea gira come utente gitea)
chown -R gitea:gitea "$CUSTOM_DIR"
echo "==> Permessi impostati (gitea:gitea)."
# 4) Stato per il rollback
{
echo "installed_at=$STAMP"
echo "backup_dir=$BACKUP_DIR"
echo "had_custom=$HAD_PREV"
} > "$STATE_FILE"
echo "==> Stato rollback salvato in $STATE_FILE"
}
# ---------------------------------------------------------------- rollback
rollback_theme() {
# 1) Leggi lo stato di installazione (se esiste)
BACKUP_DIR=""
HAD_PREV=no
if [ -f "$STATE_FILE" ]; then
source "$STATE_FILE" 2>/dev/null || true
echo "==> Stato trovato: installato $installed_at, backup=${backup_dir:-nessuno}, precedente=$had_custom"
fi
# 2) Rimuovi i file del tema
rm -f "$CUSTOM_DIR/templates/home.tmpl"
rm -rf "$CUSTOM_DIR/public/assets/img"
echo "==> File del tema rimossi (home.tmpl e assets/img)."
# 3) Ripristina l'eventuale personalizzazione precedente dal backup
if [ "$HAD_PREV" = "yes" ] && [ -n "${BACKUP_DIR:-}" ] && [ -d "$BACKUP_DIR" ]; then
echo "==> Ripristino personalizzazione precedente da $BACKUP_DIR"
if [ -f "$BACKUP_DIR/templates/home.tmpl" ]; then
mkdir -p "$CUSTOM_DIR/templates"
cp -a "$BACKUP_DIR/templates/home.tmpl" "$CUSTOM_DIR/templates/home.tmpl"
fi
if [ -d "$BACKUP_DIR/public/assets/img" ]; then
mkdir -p "$CUSTOM_DIR/public/assets/img"
cp -a "$BACKUP_DIR/public/assets/img/." "$CUSTOM_DIR/public/assets/img/"
fi
fi
# 4) Rimuovi lo stato e le cartelle eventualmente vuote
rm -f "$STATE_FILE"
rmdir "$CUSTOM_DIR/public/assets/img" "$CUSTOM_DIR/public/assets" "$CUSTOM_DIR/public" 2>/dev/null || true
rmdir "$CUSTOM_DIR/templates" 2>/dev/null || true
echo "==> Stato rollback pulito."
# 5) Permessi
chown -R gitea:gitea "$CUSTOM_DIR" 2>/dev/null || true
}
# ---------------------------------------------------------------- esegui
if [ "$MODE" = "install" ]; then
install_theme
else
rollback_theme
fi
# ---------------------------------------------------------------- restart+verify
systemctl restart gitea
sleep 6
echo "==> Stato servizio: $(systemctl is-active gitea)"
if [ "$MODE" = "install" ]; then
echo "==> Verifica asset (favicon/logo):"
curl -sk -o /dev/null -w " /assets/img/favicon.svg -> %{http_code}\n" https://127.0.0.1/assets/img/favicon.svg 2>/dev/null || true
curl -sk -o /dev/null -w " /assets/img/logo.svg -> %{http_code}\n" https://127.0.0.1/assets/img/logo.svg 2>/dev/null || true
fi
echo ""
echo "FATTO ($MODE). Ricarica https://git.zomas.net (Ctrl+Shift+R per bypassare la cache)."
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
# Installa homepage moderna + favicon personalizzate per Gitea.
# DA ESEGUIRE COME ROOT SUL VPS (o con sudo).
# Uso: bash install_gitea_theme.sh
set -euo pipefail
CUSTOM_DIR="${CUSTOM_DIR:-/var/lib/gitea/custom}"
SRC_DIR="$(cd "$(dirname "$0")" && pwd)/custom"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_DIR="${CUSTOM_DIR}/.backup-${STAMP}"
if [ "$(id -u)" != "0" ]; then
echo "ERRORE: devi eseguire questo script come root (o sudo)."
exit 1
fi
if [ ! -d "$SRC_DIR" ]; then
echo "ERRORE: cartella sorgente '$SRC_DIR' non trovata (script in cartella sbagliata?)."
exit 1
fi
echo "==> Target custom dir: $CUSTOM_DIR"
# 1) Backup delle eventuali personalizzazioni esistenti
HAD_PREV=no
if [ -e "$CUSTOM_DIR/templates/home.tmpl" ] || [ -e "$CUSTOM_DIR/public/assets/img" ]; then
HAD_PREV=yes
mkdir -p "$BACKUP_DIR"
for p in templates/home.tmpl public/assets/img; do
if [ -e "$CUSTOM_DIR/$p" ]; then
mkdir -p "$BACKUP_DIR/$(dirname "$p")"
cp -a "$CUSTOM_DIR/$p" "$BACKUP_DIR/$p"
echo "==> Backup salvato: $BACKUP_DIR/$p"
fi
done
else
echo "==> Nessuna personalizzazione precedente, niente da salvare."
fi
# 2) Copia dei nuovi file
mkdir -p "$CUSTOM_DIR/templates" "$CUSTOM_DIR/public/assets/img"
cp "$SRC_DIR/templates/home.tmpl" "$CUSTOM_DIR/templates/home.tmpl"
cp "$SRC_DIR/public/assets/img/"* "$CUSTOM_DIR/public/assets/img/"
echo "==> File copiati:"
ls -l "$CUSTOM_DIR/templates/home.tmpl"
ls -l "$CUSTOM_DIR/public/assets/img/"
# 3) Permessi corretti (il processo gitea gira come utente gitea)
chown -R gitea:gitea "$CUSTOM_DIR"
echo "==> Permessi impostati (gitea:gitea)."
# 3b) Stato per il rollback
STATE_FILE="$CUSTOM_DIR/.gitea-theme-state"
{
echo "installed_at=$STAMP"
echo "backup_dir=$BACKUP_DIR"
echo "had_custom=$HAD_PREV"
} > "$STATE_FILE"
echo "==> Stato rollback salvato in $STATE_FILE"
# 4) Riavvio di Gitea
systemctl restart gitea
sleep 6
# 5) Verifica
echo "==> Stato servizio:"
systemctl is-active gitea
echo "==> Verifica favicon (HTTP code):"
curl -sk -o /dev/null -w " /assets/img/favicon.svg -> %{http_code}\n" https://127.0.0.1/assets/img/favicon.svg \
|| echo " (curl locale non disponibile, verificare via browser)"
echo "==> Verifica logo:"
curl -sk -o /dev/null -w " /assets/img/logo.svg -> %{http_code}\n" https://127.0.0.1/assets/img/logo.svg \
|| true
echo ""
echo "FATTO. Ricarica https://git.zomas.net (con Ctrl+Shift+R per bypassare la cache del browser)."
echo "Per ripristinare la versione originale:"
echo " rm -rf $CUSTOM_DIR/templates/home.tmpl $CUSTOM_DIR/public/assets/img"
echo " systemctl restart gitea"
echo "Backup delle vecchie file (se esistenti): $BACKUP_DIR"
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
# Rimuove la homepage personalizzata e la favicon di Gitea, tornando allo
# stato originale (Gitea stock) o a una eventuale personalizzazione precedente.
# DA ESEGUIRE COME ROOT SUL VPS (o con sudo).
# Uso: bash rollback_gitea_theme.sh
set -euo pipefail
CUSTOM_DIR="${CUSTOM_DIR:-/var/lib/gitea/custom}"
STATE_FILE="$CUSTOM_DIR/.gitea-theme-state"
if [ "$(id -u)" != "0" ]; then
echo "ERRORE: devi eseguire questo script come root (o sudo)."
exit 1
fi
echo "==> Ripristino stato iniziale di Gitea (custom) in $CUSTOM_DIR"
# 1) Leggi lo stato di installazione (se esiste)
BACKUP_DIR=""
HAD_PREV=no
if [ -f "$STATE_FILE" ]; then
source "$STATE_FILE" 2>/dev/null || true
echo "==> Stato trovato: installato $installed_at, backup=${backup_dir:-nessuno}, precedente=$had_custom"
fi
# 2) Rimuovi i file del tema
rm -f "$CUSTOM_DIR/templates/home.tmpl"
rm -rf "$CUSTOM_DIR/public/assets/img"
echo "==> File del tema rimossi (home.tmpl e assets/img)."
# 3) Ripristina una eventuale personalizzazione precedente dal backup
RESTORED=no
if [ "$HAD_PREV" = "yes" ] && [ -n "${BACKUP_DIR:-}" ] && [ -d "$BACKUP_DIR" ]; then
echo "==> Ripristino personalizzazione precedente da $BACKUP_DIR"
if [ -f "$BACKUP_DIR/templates/home.tmpl" ]; then
mkdir -p "$CUSTOM_DIR/templates"
cp -a "$BACKUP_DIR/templates/home.tmpl" "$CUSTOM_DIR/templates/home.tmpl"
RESTORED=yes
fi
if [ -d "$BACKUP_DIR/public/assets/img" ]; then
mkdir -p "$CUSTOM_DIR/public/assets/img"
cp -a "$BACKUP_DIR/public/assets/img/." "$CUSTOM_DIR/public/assets/img/"
fi
fi
# 4) Rimuovi lo stato e le cartelle eventualmente vuote
rm -f "$STATE_FILE"
rmdir "$CUSTOM_DIR/public/assets/img" "$CUSTOM_DIR/public/assets" "$CUSTOM_DIR/public" 2>/dev/null || true
rmdir "$CUSTOM_DIR/templates" 2>/dev/null || true
echo "==> Stato rollback pulito."
# 5) Permessi e riavvio
chown -R gitea:gitea "$CUSTOM_DIR" 2>/dev/null || true
systemctl restart gitea
sleep 6
# 6) Verifica
echo "==> Stato servizio: $(systemctl is-active gitea)"
curl -sk -o /dev/null -w " /assets/img/favicon.svg -> %{http_code} (200=stock Gitea, 404=custom rimosso)\n" https://127.0.0.1/assets/img/favicon.svg 2>/dev/null || true
echo ""
echo "FATTO. Ricarica https://git.zomas.net (Ctrl+Shift+R per bypassare la cache)."