Files
open-isp/views/admin/update.ejs
oxpoe 8a312485a7
All checks were successful
CI / test (push) Successful in 2m21s
feat(update): kotak panduan restart self-hosted & cloud
- PM2, manual pkill, quadlet/systemd, compose
- cloud: otomatis saat update berikutnya / hubungi admin server
- versi 0.5.16
2026-11-05 17:57:03 +07:00

120 lines
7.6 KiB
Plaintext

<!DOCTYPE html>
<html lang="<%= lang || 'id' %>">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= title %> | <%= company %></title>
<link rel="stylesheet" href="/vendor/bootstrap-icons/bootstrap-icons.min.css">
<link rel="stylesheet" href="/css/admin.css">
</head>
<body>
<%- include('partials/sidebar', { activePage: activePage || 'update', company }) %>
<div class="mw">
<div class="topbar">
<div class="tb-title"><button class="hb-menu" onclick="toggleSidebar()"><i class="bi bi-list"></i></button><i class="bi bi-cloud-arrow-down"></i> <%= t('admin.update.title', 'Update Gitea') %></div>
<div class="tb-right">
<span class="adm-badge"><i class="bi bi-person-fill"></i> <%= t('admin.role.admin', 'Admin') %></span>
<a href="/admin/logout" class="btn btn-g btn-sm"><i class="bi bi-box-arrow-left"></i> <%= t('common.logout', 'Logout') %></a>
</div>
</div>
<div class="page">
<% if (msg) { %>
<div class="alert alert-<%= msg.type==='success'?'s':'d' %>" data-flash="1">
<i class="bi bi-<%= msg.type==='success'?'check-circle':'exclamation-circle' %>"></i> <%= msg.text %>
</div>
<% } %>
<div class="card mb16">
<div class="card-hd"><h6><i class="bi bi-git"></i> <%= t('admin.update.status_title', 'Status Versi') %></h6></div>
<div class="card-bd">
<% if (info && info.error) { %>
<div class="alert alert-d"><i class="bi bi-exclamation-circle"></i> <%= info.error %></div>
<% } %>
<% if (info && info.container) { %>
<div class="alert" style="background:rgba(59,130,246,.08);border:1px solid rgba(59,130,246,.3);border-radius:10px;padding:12px 14px;font-size:13px;line-height:1.55">
<b><i class="bi bi-box-seam"></i> <%= t('admin.update.container_title', 'Instalasi Container (tanpa .git)') %></b><br>
<%= t('admin.update.container_msg', 'Pembaruan TIDAK lewat git. Bangun ulang image dari repo terbaru lalu ganti container:') %>
<div style="margin-top:8px;font-family:monospace;font-size:12px;background:rgba(0,0,0,.25);padding:8px 10px;border-radius:8px">
docker compose build &amp;&amp; docker compose up -d<br>
# atau: build image baru, lalu ganti tag/container
</div>
<%= t('admin.update.container_safe', 'Data (settings.json, database, uploads) tetap aman bila disimpan di volume/mount.') %>
</div>
<% } %>
<div class="form-row" style="align-items:flex-start">
<div class="fg">
<label class="fl"><%= t('admin.update.server_version', 'Versi Server (version.txt)') %></label>
<div class="fc" style="display:flex;align-items:center;gap:8px">
<i class="bi bi-hdd-network"></i>
<span style="font-weight:800"><%= info?.localVersion || '-' %></span>
</div>
</div>
<div class="fg">
<label class="fl"><%= t('admin.update.gitea_version_prefix', 'Versi Gitea (') %><%= info?.repo || 'origin' %>/<%= info?.branch || '-' %><%= t('admin.update.gitea_version_suffix', ')') %></label>
<div class="fc" style="display:flex;align-items:center;gap:8px">
<i class="bi bi-git"></i>
<span style="font-weight:800"><%= info?.remoteVersion || '-' %></span>
<% if (info?.needsUpdate) { %>
<span class="badge badge-d" style="margin-left:8px"><i class="bi bi-arrow-up-circle"></i> <%= t('admin.update.has_update', 'Ada update') %></span>
<% } else { %>
<span class="badge badge-s" style="margin-left:8px"><i class="bi bi-check2-circle"></i> <%= t('admin.update.latest', 'Terbaru') %></span>
<% } %>
</div>
</div>
</div>
<% if (!(info && info.container)) { %>
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-top:12px">
<form method="GET" action="/admin/update">
<button type="submit" class="btn btn-g"><i class="bi bi-arrow-repeat"></i> <%= t('admin.update.check', 'Cek Versi') %></button>
</form>
<form method="POST" action="/admin/update/run" onsubmit="return confirmUpdate()">
<button type="submit" class="btn btn-s" <%= (info && info.error) ? 'disabled' : '' %>><i class="bi bi-cloud-arrow-down"></i> <%= t('admin.update.run', 'Update Sekarang') %></button>
</form>
</div>
<div style="margin-top:12px;color:var(--muted);font-size:12px;line-height:1.5">
<%= t('admin.update.keep_files', 'File yang tidak ditimpa saat update: settings.json dan folder database. Setelah update selesai, restart aplikasi agar versi baru aktif.') %>
</div>
<% } %>
</div>
</div>
<div class="card mb16">
<div class="card-hd"><h6><i class="bi bi-arrow-repeat"></i> <%= t('admin.update.restart_title', 'Cara Restart Aplikasi') %></h6></div>
<div class="card-bd" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;font-size:12px">
<div style="border:1px solid var(--border);border-radius:12px;padding:12px 14px;background:rgba(255,255,255,.02);line-height:1.75">
<div style="font-weight:800;margin-bottom:8px"><i class="bi bi-server"></i> <%= t('admin.update.restart_selfhosted', 'Self-hosted') %></div>
<div><b>PM2</b><br><code>pm2 restart all</code> <span style="color:var(--muted)">(atau <code>pm2 restart open-isp</code>)</span></div>
<div style="margin-top:8px"><b>Manual (tanpa PM2)</b><br><code>pkill -f "node app-customer.js"</code><br><code>nohup node app-customer.js &gt; logs/run.log 2&gt;&amp;1 &amp;</code></div>
<div style="margin-top:8px"><b>Quadlet / systemd</b><br><code>systemctl --user restart open-isp</code> <span style="color:var(--muted)">(user)</span><br><code>sudo systemctl restart open-isp</code> <span style="color:var(--muted)">(system)</span></div>
<div style="margin-top:8px"><b>Docker / Podman Compose</b><br><code>docker compose restart</code><br><code>podman compose restart</code> <span style="color:var(--muted)">(atau <code>up -d</code> bila env berubah)</span></div>
<div style="margin-top:8px;color:var(--muted)">Jalankan dari folder aplikasi, lalu muat ulang halaman ini.</div>
</div>
<div style="border:1px solid var(--border);border-radius:12px;padding:12px 14px;background:rgba(59,130,246,.06);line-height:1.75">
<div style="font-weight:800;margin-bottom:8px"><i class="bi bi-cloud"></i> <%= t('admin.update.restart_cloud', 'Cloud / managed') %></div>
<div><i class="bi bi-check2-circle" style="color:var(--success)"></i> Restart dilakukan <b>otomatis pada update berikutnya</b>.</div>
<div style="margin-top:8px"><i class="bi bi-headset"></i> Butuh restart sekarang? <b>Hubungi admin server</b> — jangan jalankan perintah restart sendiri.</div>
<div style="margin-top:8px;color:var(--muted)">Cocok untuk instance yang dikelola penyedia/hosting bersama.</div>
</div>
</div>
</div>
<% if (log) { %>
<div class="card mb16">
<div class="card-hd"><h6><i class="bi bi-terminal"></i> <%= t('admin.update.log_title', 'Log Update') %></h6></div>
<div class="card-bd">
<pre style="white-space:pre-wrap;word-break:break-word;margin:0;background:rgba(0,0,0,0.08);padding:12px;border-radius:12px"><%= log %></pre>
</div>
</div>
<% } %>
</div>
</div>
<script>
function confirmUpdate() {
return confirm("<%= t('admin.update.confirm', 'Jalankan update dari Gitea sekarang? Pastikan koneksi internet aman dan aplikasi akan direstart setelah selesai.') %>");
}
</script>
</body>
</html>