Panduan ini dibuat berdasarkan kasus real deployment MeshCentral di EasyPanel dengan Docker/Swarm dan reverse proxy bawaan EasyPanel/Traefik.
Target akhir:
- MeshCentral bisa diakses via domain sendiri, contoh:
https://mesh.darsya.my.id - Agent bisa install normal dari command dashboard MeshCentral
- Tidak muncul error:
Agent bad web cert hashinvalid origin in HTTP request
EasyPanel biasanya menjalankan app di belakang reverse proxy/TLS offload.
Artinya:
Browser / Mesh Agent
|
| HTTPS cert publik dari EasyPanel / Cloudflare / Let's Encrypt
v
EasyPanel Reverse Proxy
|
| koneksi internal ke container MeshCentral
v
MeshCentral container
MeshCentral sangat sensitif terhadap hash sertifikat web. Agent yang di-download dari dashboard membawa informasi hash cert server. Kalau agent melihat cert publik dari proxy, tapi MeshCentral mengira cert internal/self-signed yang dipakai, maka agent akan ditolak.
Gejalanya di log:
Agent bad web cert hash (Agent:xxxx != Server:yyyy or zzzz), holding connection
Agent reported web cert hash: xxxxxxxxxx...
Solusinya: MeshCentral harus diberi tahu URL publik yang dipakai agent lewat config certUrl.
Gunakan image resmi:
ghcr.io/ylianst/meshcentral:latest-slim
Recommended volume persistent:
/opt/meshcentral/meshcentral-data
/opt/meshcentral/meshcentral-files
/opt/meshcentral/meshcentral-backups
/opt/meshcentral/meshcentral-web
Minimal yang wajib dipersistent-kan adalah:
/opt/meshcentral/meshcentral-data
Karena folder ini berisi:
config.json- database lokal
- sertifikat MeshCentral
- signing cert agent
Kalau volume ini hilang, agent lama bisa rusak koneksinya.
Contoh env untuk domain mesh.example.com:
HOSTNAME=mesh.example.com
PORT=443
ALLOW_NEW_ACCOUNTS=true
TZ=Asia/Jakarta
REVERSE_PROXY=10.0.1.0/24
REVERSE_PROXY_TLS_PORT=443Catatan:
HOSTNAMEharus sama dengan domain publik final.ALLOW_NEW_ACCOUNTS=truehanya untuk setup awal. Setelah admin dibuat, sebaiknya ubah kefalse.REVERSE_PROXYbawaan EasyPanel bisa berbeda range IP-nya. Pada kasus saya, proxy masuk dari network10.11.x.x, jadi perlu ditambahkan juga di config MeshCentral.
Di EasyPanel:
- Buka app MeshCentral.
- Tambahkan domain, contoh:
mesh.example.com
- Arahkan DNS domain ke server EasyPanel.
- Pastikan HTTPS/SSL aktif di EasyPanel.
Kalau pakai Cloudflare:
- DNS boleh proxied/orange cloud jika halaman web berjalan normal.
- Untuk debugging, bisa pakai DNS only sementara.
- Pastikan SSL mode Cloudflare tidak membuat loop/error. Umumnya
FullatauFull (strict)jika origin cert valid.
Tes dari server:
curl -I https://mesh.example.com/Harus dapat HTTP/2 200 atau minimal response dari MeshCentral, bukan 502.
Masuk ke container:
docker ps | grep meshcentralContoh nama container:
prod_darsya-mesh.1.xxxxx
Buka config:
docker exec -it <nama-container> sh
vi /opt/meshcentral/meshcentral-data/config.jsonAtau edit dari host jika volume bisa diakses.
Contoh config final yang disarankan:
{
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
"settings": {
"plugins": {
"enabled": false
},
"cert": "mesh.example.com",
"port": 443,
"redirPort": 80,
"AgentPong": 300,
"tlsOffload": "10.0.1.0/24,10.11.0.0/16",
"trustedProxy": "10.0.1.0/24,10.11.0.0/16",
"SelfUpdate": false,
"AllowFraming": false,
"WebRTC": false
},
"domains": {
"": {
"minify": false,
"NewAccounts": true,
"localSessionRecording": true,
"allowedOrigin": false,
"certUrl": "https://mesh.example.com/"
}
}
}Ganti semua mesh.example.com dengan domain kamu.
Poin paling penting:
"cert": "mesh.example.com""certUrl": "https://mesh.example.com/""tlsOffload": "10.0.1.0/24,10.11.0.0/16""trustedProxy": "10.0.1.0/24,10.11.0.0/16"Kenapa 10.11.0.0/16? Pada kasus EasyPanel saya, request agent masuk ke MeshCentral dari IP internal 10.11.x.x. Jika log kamu menunjukkan IP internal lain, sesuaikan range-nya.
Contoh log:
holding connection (10.11.0.4:59646)
Maka masukkan 10.11.0.0/16.
Bagian ini penting karena nilai tlsOffload dan trustedProxy harus mencakup IP internal reverse proxy yang benar. Kalau salah, MeshCentral bisa salah membaca header proxy dan agent/websocket bisa bermasalah.
Ada beberapa cara untuk mengetahuinya.
Ini cara paling mudah kalau agent sudah pernah mencoba connect.
Jalankan:
docker logs <nama-container> 2>&1 | grep -i "Agent bad web cert hash"Contoh output:
Agent bad web cert hash (Agent:a3b321a97d != Server:9974a5ee65 or 8c50ad4960), holding connection (10.11.0.4:59646).
Perhatikan bagian akhir:
(10.11.0.4:59646)
Itu adalah IP yang terlihat oleh MeshCentral saat koneksi agent masuk. Dalam contoh ini IP-nya 10.11.0.4, jadi range yang aman untuk dimasukkan adalah:
"tlsOffload": "10.11.0.0/16",
"trustedProxy": "10.11.0.0/16"Kalau sebelumnya sudah ada range lain, gabungkan dengan koma:
"tlsOffload": "10.0.1.0/24,10.11.0.0/16",
"trustedProxy": "10.0.1.0/24,10.11.0.0/16"Jalankan:
docker inspect <nama-container> --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{$v.IPAddress}}{{"\n"}}{{end}}'Contoh output:
easypanel 10.11.218.144
easypanel-prod 10.0.1.233
Dari sini terlihat container terhubung ke network 10.11.x.x dan 10.0.1.x. Maka config yang masuk akal:
"tlsOffload": "10.0.1.0/24,10.11.0.0/16",
"trustedProxy": "10.0.1.0/24,10.11.0.0/16"Catatan: IP container MeshCentral bukan selalu IP proxy, tapi network range-nya biasanya sama dengan network tempat proxy EasyPanel berkomunikasi. Untuk memastikan, tetap lebih akurat memakai Cara 1 dari log koneksi masuk.
Kalau EasyPanel deploy sebagai Docker Swarm service:
docker service inspect <nama-service> --prettyCari bagian:
Networks:
Lalu inspect network tersebut:
docker network inspect <nama-network> | grep -A 5 -i subnetContoh output:
"Subnet": "10.11.0.0/16"Masukkan subnet itu ke tlsOffload dan trustedProxy.
docker network lsLalu inspect network yang namanya mirip easypanel atau network app kamu:
docker network inspect <nama-network>Cari bagian IPAM/Subnet:
"IPAM": {
"Config": [
{
"Subnet": "10.11.0.0/16"
}
]
}Kalau IP yang muncul adalah:
10.11.0.4
Pakai:
10.11.0.0/16
Kalau IP yang muncul adalah:
10.0.1.233
Pakai:
10.0.1.0/24
Kalau ragu, masukkan dua-duanya seperti ini:
"tlsOffload": "10.0.1.0/24,10.11.0.0/16",
"trustedProxy": "10.0.1.0/24,10.11.0.0/16"Jangan isi terlalu luas seperti 0.0.0.0/0, karena itu berarti mempercayai forwarded headers dari semua sumber.
Jika EasyPanel pakai Docker Swarm:
docker service update --force <nama-service>Contoh:
docker service update --force prod_darsya-meshJika container biasa:
docker restart <nama-container>Lihat log:
docker logs -f <nama-container>Log yang diharapkan:
Loaded web certificate from "https://mesh.example.com/", host: "mesh.example.com"
SHA384 cert hash: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MeshCentral HTTP server running on port 443.
Kalau sudah muncul Loaded web certificate from ..., berarti certUrl sudah bekerja.
Buka:
https://mesh.example.com
Buat account admin pertama.
Setelah itu, untuk keamanan, ubah:
"NewAccounts": falseatau env:
ALLOW_NEW_ACCOUNTS=falseLalu restart lagi.
Penting: setelah config domain dan cert sudah benar, generate/copy ulang command install dari dashboard MeshCentral.
Jangan pakai command lama dari domain lama.
Langkah:
- Login ke
https://mesh.example.com - Buat device group.
- Klik
Add Agent. - Pilih OS client.
- Copy command install terbaru.
- Jalankan di client.
Kalau sebelumnya agent sudah pernah install dari domain lama, uninstall dulu agent lama lalu install ulang.
Dari host/server:
printf '' | openssl s_client -connect mesh.example.com:443 -servername mesh.example.com 2>/dev/null \
| openssl x509 -noout -fingerprint -sha384Contoh output:
sha384 Fingerprint=30:63:05:8B:85:24:96:BD:...
MeshCentral log harus menampilkan hash yang sama setelah certUrl loaded.
Contoh:
Agent bad web cert hash (Agent:a3b321a97d != Server:9974a5ee65 or 8c50ad4960)
Agent reported web cert hash:a3b321a97d...
Penyebab:
- MeshCentral belum tahu sertifikat publik reverse proxy.
certUrlbelum ada atau salah.- Agent masih install dari command/domain lama.
Fix:
- Pastikan config punya:
"certUrl": "https://mesh.example.com/"- Restart MeshCentral.
- Pastikan log menampilkan:
Loaded web certificate from "https://mesh.example.com/"
- Copy ulang command agent dari dashboard.
- Reinstall agent.
Penyebab umum:
- Domain yang diakses browser berbeda dengan
settings.certdi MeshCentral. - Baru pindah domain tapi config masih domain lama.
- Reverse proxy mengirim header Host/Origin berbeda.
Fix:
Pastikan:
"cert": "mesh.example.com"Dan:
"certUrl": "https://mesh.example.com/"Lalu restart.
Jika masih error, pastikan domain di EasyPanel benar-benar forward ke app yang sama dan header Host tidak diubah ke domain internal.
Ini normal. Agent lama kemungkinan membawa hash/URL dari domain lama.
Fix:
- Login dashboard via domain baru.
- Copy ulang command install agent.
- Uninstall agent lama di client.
- Install agent baru.
Cek:
docker logs <nama-container>Pastikan MeshCentral benar-benar running:
MeshCentral HTTP server running on port 443.
Jika MeshCentral masih generate certificate/sign agent, tunggu beberapa menit.
Cek juga apakah domain di EasyPanel mengarah ke port container yang benar.
Kalau container punya Node.js, bisa edit otomatis seperti ini:
docker exec <nama-container> sh -lc '
CFG=/opt/meshcentral/meshcentral-data/config.json
cp "$CFG" "$CFG.bak.$(date +%Y%m%d-%H%M%S)"
node - <<"NODE"
const fs = require("fs");
const cfg = "/opt/meshcentral/meshcentral-data/config.json";
const domain = "mesh.example.com";
const data = JSON.parse(fs.readFileSync(cfg, "utf8"));
data.settings = data.settings || {};
data.settings.cert = domain;
data.settings.tlsOffload = "10.0.1.0/24,10.11.0.0/16";
data.settings.trustedProxy = "10.0.1.0/24,10.11.0.0/16";
data.domains = data.domains || {};
data.domains[""] = data.domains[""] || {};
data.domains[""].certUrl = `https://${domain}/`;
fs.writeFileSync(cfg, JSON.stringify(data, null, 2) + "\n");
NODE
'Lalu restart:
docker service update --force <nama-service>atau:
docker restart <nama-container>- Domain publik sudah resolve ke EasyPanel.
- HTTPS domain sudah aktif.
-
settings.certsama dengan domain publik. -
domains[""].certUrlmengarah ke URL publik HTTPS. -
tlsOffloaddantrustedProxymencakup IP/range reverse proxy EasyPanel. - Log menampilkan
Loaded web certificate from .... - Dashboard dibuka via domain final.
- Command install agent dicopy ulang setelah config benar.
- Agent lama dari domain lama di-uninstall/reinstall.
{
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
"settings": {
"cert": "mesh.example.com",
"port": 443,
"redirPort": 80,
"tlsOffload": "10.0.1.0/24,10.11.0.0/16",
"trustedProxy": "10.0.1.0/24,10.11.0.0/16"
},
"domains": {
"": {
"NewAccounts": false,
"certUrl": "https://mesh.example.com/"
}
}
}Selesai.