404.html
· 8.3 KiB · HTML
原始檔案
<!--
404 Custom Error Page
Author: Emanuele Gori <emanuelegori.uno>
Version: 1.0.0
Created: 2025-03-22
License: GPL-2.0-or-later
Description: Custom 404 page for NGINX Proxy Manager.
Served for unconfigured or unknown hosts.
Hostname and path populated dynamically via JS.
No external dependencies.
-->
<!DOCTYPE html>
<html lang="it">
<head>
<meta name="author" content="Emanuele Gori">
<meta name="description" content="Pagina di errore 404 personalizzata per NGINX Proxy Manager">
<meta name="version" content="1.0.0">
<meta name="robots" content="noindex, nofollow">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow">
<title>404 - Risorsa non trovata</title>
<style>
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--bg: #0d0f12;
--surface: #141720;
--border: #1f2435;
--border-hi: #2d3350;
--text: #c8cdd8;
--text-dim: #5a6075;
--text-mute: #3a3f52;
--accent: #4a7fbd;
--accent-lo: #1a2d45;
--error: #bd4a4a;
--error-lo: #2d1a1a;
--green: #4abd7a;
--mono: "Courier New", "Lucida Console", monospace;
}
html, body {
height: 100%;
}
body {
background-color: var(--bg);
color: var(--text);
font-family: var(--mono);
font-size: 14px;
line-height: 1.6;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 2rem 1rem;
}
.terminal {
width: 100%;
max-width: 680px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 6px;
overflow: hidden;
}
.terminal-bar {
background: var(--border);
padding: 0.55rem 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid var(--border-hi);
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--border-hi);
flex-shrink: 0;
}
.bar-label {
flex: 1;
text-align: center;
font-size: 11px;
color: var(--text-dim);
letter-spacing: 0.05em;
}
.terminal-body {
padding: 1.75rem 2rem;
}
.prompt-line {
display: flex;
align-items: baseline;
gap: 0.5rem;
margin-bottom: 1.5rem;
}
.prompt-sign {
color: var(--green);
font-size: 13px;
flex-shrink: 0;
}
.prompt-cmd {
color: var(--text-dim);
font-size: 13px;
word-break: break-all;
}
.error-block {
border-left: 2px solid var(--error);
background: var(--error-lo);
padding: 1rem 1.25rem;
margin-bottom: 1.5rem;
border-radius: 0 4px 4px 0;
}
.error-code {
font-size: 11px;
color: var(--error);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.error-title {
font-size: 22px;
font-weight: bold;
color: #e0e4ef;
letter-spacing: -0.01em;
margin-bottom: 0.25rem;
}
.error-sub {
font-size: 12px;
color: var(--text-dim);
}
.output-block {
margin-bottom: 1.5rem;
}
.output-line {
display: flex;
gap: 1rem;
padding: 0.2rem 0;
font-size: 13px;
border-bottom: 1px solid var(--border);
}
.output-line:last-child {
border-bottom: none;
}
.output-key {
color: var(--text-dim);
min-width: 120px;
flex-shrink: 0;
}
.output-val {
color: var(--text);
}
.output-val.highlight {
color: var(--accent);
}
.output-val.warn {
color: #bd8a4a;
}
.divider {
border: none;
border-top: 1px solid var(--border);
margin: 1.5rem 0;
}
.note-block {
background: var(--accent-lo);
border: 1px solid #1e3050;
border-radius: 4px;
padding: 0.85rem 1.1rem;
margin-bottom: 1.5rem;
}
.note-block p {
font-size: 12px;
color: var(--text-dim);
line-height: 1.7;
}
.note-block p + p {
margin-top: 0.4rem;
}
.note-block strong {
color: var(--text);
font-weight: normal;
}
.action-line {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 13px;
}
.action-line .prompt-sign {
color: var(--green);
}
.home-link {
color: var(--accent);
text-decoration: none;
border-bottom: 1px solid var(--accent-lo);
transition: border-color 0.15s;
}
.home-link:hover {
border-color: var(--accent);
}
.cursor {
display: inline-block;
width: 8px;
height: 14px;
background: var(--text-dim);
vertical-align: middle;
margin-left: 2px;
animation: blink 1.1s step-start infinite;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.footer-note {
margin-top: 1.5rem;
font-size: 11px;
color: var(--text-mute);
text-align: center;
letter-spacing: 0.03em;
}
@media (max-width: 500px) {
.terminal-body { padding: 1.25rem 1rem; }
.output-key { min-width: 90px; }
.error-title { font-size: 18px; }
}
</style>
</head>
<body>
<div class="terminal" role="main">
<div class="terminal-bar" aria-hidden="true">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
<span class="bar-label" id="bar-host">http-error-handler</span>
</div>
<div class="terminal-body">
<div class="prompt-line">
<span class="prompt-sign">$</span>
<span class="prompt-cmd" id="prompt-path">GET <span id="req-url">...</span> HTTP/1.1</span>
</div>
<div class="error-block">
<div class="error-code">HTTP 404 — Not Found</div>
<div class="error-title">Risorsa non trovata</div>
<div class="error-sub">The requested resource could not be located on this server.</div>
</div>
<div class="output-block">
<div class="output-line">
<span class="output-key">host</span>
<span class="output-val highlight" id="out-host">-</span>
</div>
<div class="output-line">
<span class="output-key">path</span>
<span class="output-val" id="out-path">-</span>
</div>
<div class="output-line">
<span class="output-key">status</span>
<span class="output-val warn">404 Not Found</span>
</div>
<div class="output-line">
<span class="output-key">indexing</span>
<span class="output-val">noindex, nofollow</span>
</div>
</div>
<hr class="divider">
<div class="note-block" role="note">
<p>
<strong>La risorsa richiesta non esiste</strong> oppure l'host non e' configurato su questo server.
Se hai seguito un link esterno, potrebbe essere obsoleto o errato.
</p>
<p>
The requested resource does not exist or the host is not configured on this server.
If you followed an external link, it may be outdated or incorrect.
</p>
</div>
<div class="action-line">
<span class="prompt-sign">$</span>
<span>cd <a href="/" class="home-link" aria-label="Visita la home del sito">home</a></span>
<span class="cursor" aria-hidden="true"></span>
</div>
</div>
</div>
<p class="footer-note" aria-hidden="true">
nginx proxy manager — custom error page
</p>
<script>
(function () {
var host = window.location.hostname || '';
var path = window.location.pathname || '/';
var fullUrl = host + path;
var elHost = document.getElementById('out-host');
var elPath = document.getElementById('out-path');
var elReqUrl = document.getElementById('req-url');
var elBarHost = document.getElementById('bar-host');
if (host) {
elHost.textContent = host;
elBarHost.textContent = host;
elReqUrl.textContent = fullUrl;
}
elPath.textContent = path;
})();
</script>
</body>
</html>
| 1 | <!-- |
| 2 | 404 Custom Error Page |
| 3 | Author: Emanuele Gori <emanuelegori.uno> |
| 4 | Version: 1.0.0 |
| 5 | Created: 2025-03-22 |
| 6 | License: GPL-2.0-or-later |
| 7 | Description: Custom 404 page for NGINX Proxy Manager. |
| 8 | Served for unconfigured or unknown hosts. |
| 9 | Hostname and path populated dynamically via JS. |
| 10 | No external dependencies. |
| 11 | --> |
| 12 | <!DOCTYPE html> |
| 13 | <html lang="it"> |
| 14 | <head> |
| 15 | <meta name="author" content="Emanuele Gori"> |
| 16 | <meta name="description" content="Pagina di errore 404 personalizzata per NGINX Proxy Manager"> |
| 17 | <meta name="version" content="1.0.0"> |
| 18 | <meta name="robots" content="noindex, nofollow"> |
| 19 | <meta charset="UTF-8"> |
| 20 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 21 | <meta name="robots" content="noindex, nofollow"> |
| 22 | <title>404 - Risorsa non trovata</title> |
| 23 | <style> |
| 24 | *, *::before, *::after { |
| 25 | box-sizing: border-box; |
| 26 | margin: 0; |
| 27 | padding: 0; |
| 28 | } |
| 29 | |
| 30 | :root { |
| 31 | --bg: #0d0f12; |
| 32 | --surface: #141720; |
| 33 | --border: #1f2435; |
| 34 | --border-hi: #2d3350; |
| 35 | --text: #c8cdd8; |
| 36 | --text-dim: #5a6075; |
| 37 | --text-mute: #3a3f52; |
| 38 | --accent: #4a7fbd; |
| 39 | --accent-lo: #1a2d45; |
| 40 | --error: #bd4a4a; |
| 41 | --error-lo: #2d1a1a; |
| 42 | --green: #4abd7a; |
| 43 | --mono: "Courier New", "Lucida Console", monospace; |
| 44 | } |
| 45 | |
| 46 | html, body { |
| 47 | height: 100%; |
| 48 | } |
| 49 | |
| 50 | body { |
| 51 | background-color: var(--bg); |
| 52 | color: var(--text); |
| 53 | font-family: var(--mono); |
| 54 | font-size: 14px; |
| 55 | line-height: 1.6; |
| 56 | display: flex; |
| 57 | flex-direction: column; |
| 58 | align-items: center; |
| 59 | justify-content: center; |
| 60 | min-height: 100vh; |
| 61 | padding: 2rem 1rem; |
| 62 | } |
| 63 | |
| 64 | .terminal { |
| 65 | width: 100%; |
| 66 | max-width: 680px; |
| 67 | background: var(--surface); |
| 68 | border: 1px solid var(--border); |
| 69 | border-radius: 6px; |
| 70 | overflow: hidden; |
| 71 | } |
| 72 | |
| 73 | .terminal-bar { |
| 74 | background: var(--border); |
| 75 | padding: 0.55rem 1rem; |
| 76 | display: flex; |
| 77 | align-items: center; |
| 78 | gap: 0.5rem; |
| 79 | border-bottom: 1px solid var(--border-hi); |
| 80 | } |
| 81 | |
| 82 | .dot { |
| 83 | width: 10px; |
| 84 | height: 10px; |
| 85 | border-radius: 50%; |
| 86 | background: var(--border-hi); |
| 87 | flex-shrink: 0; |
| 88 | } |
| 89 | |
| 90 | .bar-label { |
| 91 | flex: 1; |
| 92 | text-align: center; |
| 93 | font-size: 11px; |
| 94 | color: var(--text-dim); |
| 95 | letter-spacing: 0.05em; |
| 96 | } |
| 97 | |
| 98 | .terminal-body { |
| 99 | padding: 1.75rem 2rem; |
| 100 | } |
| 101 | |
| 102 | .prompt-line { |
| 103 | display: flex; |
| 104 | align-items: baseline; |
| 105 | gap: 0.5rem; |
| 106 | margin-bottom: 1.5rem; |
| 107 | } |
| 108 | |
| 109 | .prompt-sign { |
| 110 | color: var(--green); |
| 111 | font-size: 13px; |
| 112 | flex-shrink: 0; |
| 113 | } |
| 114 | |
| 115 | .prompt-cmd { |
| 116 | color: var(--text-dim); |
| 117 | font-size: 13px; |
| 118 | word-break: break-all; |
| 119 | } |
| 120 | |
| 121 | .error-block { |
| 122 | border-left: 2px solid var(--error); |
| 123 | background: var(--error-lo); |
| 124 | padding: 1rem 1.25rem; |
| 125 | margin-bottom: 1.5rem; |
| 126 | border-radius: 0 4px 4px 0; |
| 127 | } |
| 128 | |
| 129 | .error-code { |
| 130 | font-size: 11px; |
| 131 | color: var(--error); |
| 132 | letter-spacing: 0.1em; |
| 133 | text-transform: uppercase; |
| 134 | margin-bottom: 0.5rem; |
| 135 | } |
| 136 | |
| 137 | .error-title { |
| 138 | font-size: 22px; |
| 139 | font-weight: bold; |
| 140 | color: #e0e4ef; |
| 141 | letter-spacing: -0.01em; |
| 142 | margin-bottom: 0.25rem; |
| 143 | } |
| 144 | |
| 145 | .error-sub { |
| 146 | font-size: 12px; |
| 147 | color: var(--text-dim); |
| 148 | } |
| 149 | |
| 150 | .output-block { |
| 151 | margin-bottom: 1.5rem; |
| 152 | } |
| 153 | |
| 154 | .output-line { |
| 155 | display: flex; |
| 156 | gap: 1rem; |
| 157 | padding: 0.2rem 0; |
| 158 | font-size: 13px; |
| 159 | border-bottom: 1px solid var(--border); |
| 160 | } |
| 161 | |
| 162 | .output-line:last-child { |
| 163 | border-bottom: none; |
| 164 | } |
| 165 | |
| 166 | .output-key { |
| 167 | color: var(--text-dim); |
| 168 | min-width: 120px; |
| 169 | flex-shrink: 0; |
| 170 | } |
| 171 | |
| 172 | .output-val { |
| 173 | color: var(--text); |
| 174 | } |
| 175 | |
| 176 | .output-val.highlight { |
| 177 | color: var(--accent); |
| 178 | } |
| 179 | |
| 180 | .output-val.warn { |
| 181 | color: #bd8a4a; |
| 182 | } |
| 183 | |
| 184 | .divider { |
| 185 | border: none; |
| 186 | border-top: 1px solid var(--border); |
| 187 | margin: 1.5rem 0; |
| 188 | } |
| 189 | |
| 190 | .note-block { |
| 191 | background: var(--accent-lo); |
| 192 | border: 1px solid #1e3050; |
| 193 | border-radius: 4px; |
| 194 | padding: 0.85rem 1.1rem; |
| 195 | margin-bottom: 1.5rem; |
| 196 | } |
| 197 | |
| 198 | .note-block p { |
| 199 | font-size: 12px; |
| 200 | color: var(--text-dim); |
| 201 | line-height: 1.7; |
| 202 | } |
| 203 | |
| 204 | .note-block p + p { |
| 205 | margin-top: 0.4rem; |
| 206 | } |
| 207 | |
| 208 | .note-block strong { |
| 209 | color: var(--text); |
| 210 | font-weight: normal; |
| 211 | } |
| 212 | |
| 213 | .action-line { |
| 214 | display: flex; |
| 215 | align-items: center; |
| 216 | gap: 0.5rem; |
| 217 | font-size: 13px; |
| 218 | } |
| 219 | |
| 220 | .action-line .prompt-sign { |
| 221 | color: var(--green); |
| 222 | } |
| 223 | |
| 224 | .home-link { |
| 225 | color: var(--accent); |
| 226 | text-decoration: none; |
| 227 | border-bottom: 1px solid var(--accent-lo); |
| 228 | transition: border-color 0.15s; |
| 229 | } |
| 230 | |
| 231 | .home-link:hover { |
| 232 | border-color: var(--accent); |
| 233 | } |
| 234 | |
| 235 | .cursor { |
| 236 | display: inline-block; |
| 237 | width: 8px; |
| 238 | height: 14px; |
| 239 | background: var(--text-dim); |
| 240 | vertical-align: middle; |
| 241 | margin-left: 2px; |
| 242 | animation: blink 1.1s step-start infinite; |
| 243 | } |
| 244 | |
| 245 | @keyframes blink { |
| 246 | 0%, 100% { opacity: 1; } |
| 247 | 50% { opacity: 0; } |
| 248 | } |
| 249 | |
| 250 | .footer-note { |
| 251 | margin-top: 1.5rem; |
| 252 | font-size: 11px; |
| 253 | color: var(--text-mute); |
| 254 | text-align: center; |
| 255 | letter-spacing: 0.03em; |
| 256 | } |
| 257 | |
| 258 | @media (max-width: 500px) { |
| 259 | .terminal-body { padding: 1.25rem 1rem; } |
| 260 | .output-key { min-width: 90px; } |
| 261 | .error-title { font-size: 18px; } |
| 262 | } |
| 263 | </style> |
| 264 | </head> |
| 265 | <body> |
| 266 | |
| 267 | <div class="terminal" role="main"> |
| 268 | |
| 269 | <div class="terminal-bar" aria-hidden="true"> |
| 270 | <span class="dot"></span> |
| 271 | <span class="dot"></span> |
| 272 | <span class="dot"></span> |
| 273 | <span class="bar-label" id="bar-host">http-error-handler</span> |
| 274 | </div> |
| 275 | |
| 276 | <div class="terminal-body"> |
| 277 | |
| 278 | <div class="prompt-line"> |
| 279 | <span class="prompt-sign">$</span> |
| 280 | <span class="prompt-cmd" id="prompt-path">GET <span id="req-url">...</span> HTTP/1.1</span> |
| 281 | </div> |
| 282 | |
| 283 | <div class="error-block"> |
| 284 | <div class="error-code">HTTP 404 — Not Found</div> |
| 285 | <div class="error-title">Risorsa non trovata</div> |
| 286 | <div class="error-sub">The requested resource could not be located on this server.</div> |
| 287 | </div> |
| 288 | |
| 289 | <div class="output-block"> |
| 290 | <div class="output-line"> |
| 291 | <span class="output-key">host</span> |
| 292 | <span class="output-val highlight" id="out-host">-</span> |
| 293 | </div> |
| 294 | <div class="output-line"> |
| 295 | <span class="output-key">path</span> |
| 296 | <span class="output-val" id="out-path">-</span> |
| 297 | </div> |
| 298 | <div class="output-line"> |
| 299 | <span class="output-key">status</span> |
| 300 | <span class="output-val warn">404 Not Found</span> |
| 301 | </div> |
| 302 | <div class="output-line"> |
| 303 | <span class="output-key">indexing</span> |
| 304 | <span class="output-val">noindex, nofollow</span> |
| 305 | </div> |
| 306 | </div> |
| 307 | |
| 308 | <hr class="divider"> |
| 309 | |
| 310 | <div class="note-block" role="note"> |
| 311 | <p> |
| 312 | <strong>La risorsa richiesta non esiste</strong> oppure l'host non e' configurato su questo server. |
| 313 | Se hai seguito un link esterno, potrebbe essere obsoleto o errato. |
| 314 | </p> |
| 315 | <p> |
| 316 | The requested resource does not exist or the host is not configured on this server. |
| 317 | If you followed an external link, it may be outdated or incorrect. |
| 318 | </p> |
| 319 | </div> |
| 320 | |
| 321 | <div class="action-line"> |
| 322 | <span class="prompt-sign">$</span> |
| 323 | <span>cd <a href="/" class="home-link" aria-label="Visita la home del sito">home</a></span> |
| 324 | <span class="cursor" aria-hidden="true"></span> |
| 325 | </div> |
| 326 | |
| 327 | </div> |
| 328 | |
| 329 | </div> |
| 330 | |
| 331 | <p class="footer-note" aria-hidden="true"> |
| 332 | nginx proxy manager — custom error page |
| 333 | </p> |
| 334 | |
| 335 | <script> |
| 336 | (function () { |
| 337 | var host = window.location.hostname || ''; |
| 338 | var path = window.location.pathname || '/'; |
| 339 | var fullUrl = host + path; |
| 340 | |
| 341 | var elHost = document.getElementById('out-host'); |
| 342 | var elPath = document.getElementById('out-path'); |
| 343 | var elReqUrl = document.getElementById('req-url'); |
| 344 | var elBarHost = document.getElementById('bar-host'); |
| 345 | |
| 346 | if (host) { |
| 347 | elHost.textContent = host; |
| 348 | elBarHost.textContent = host; |
| 349 | elReqUrl.textContent = fullUrl; |
| 350 | } |
| 351 | |
| 352 | elPath.textContent = path; |
| 353 | })(); |
| 354 | </script> |
| 355 | |
| 356 | </body> |
| 357 | </html> |