Skip to main content
Version: 4.1

3.5.0

The Rust migration release. The two panels and the CLI keep every URL, template, configuration path and output they had in 3.4.0; what changed is who answers. Two new binaries, hitechcloud-rustpanel and hitechcloud-rustadmin, are required from this version, most of hitechcloudcli now runs in hitechcloud-rustcli (149 scripts removed), and the health monitor sentinel is a Rust program.

Everything in this release was ported one route or one command at a time and compared with the old implementation on a live server - same bytes on the wire, same files on disk - before the old code was retired. The bugs that comparison turned up are listed under Fixed on the way.

Built from HiTechCloud-Panel #68–#114, hitechcloudcli #16–#52, hitechcloudadmin #6–#24 and sentinel #1.

How the panels moved (#74, #86, #100–#102, admin #6, #12, #14, #19, #20)​

  • Each Go panel starts its Rust twin and supervises it (restarted with a growing pause when it exits, stopped with the panel). The twin listens on a root-only unix socket - /run/hitechcloud/rustpanel.sock for the user panel, /run/hitechcloud/rustadmin.sock for the admin - and prints the routes it answers (hitechcloud-rustpanel routes, hitechcloud-rustadmin routes).
  • The Go server stays the front door: TLS, the session, the CSRF token, the licence, the feature gates and, on the admin, the role checks all run in Go. Only after RequireLogin / RequireAPI / RequireAdmin (and, for the admin's JWT API, the innermost API wrapper) has let a request through is it proxied to the twin with the caller's identity in X-HiTech-* headers; a client's own copies of those headers are dropped. Every admin route the twin lists declares the gate it needs (session, session-admin, api-token, api-owner-or-admin:<param>, api-admin, api-superadmin, +enterprise), Go re-checks that gate before forwarding, and a test in the admin repository fails on any route declaring a weaker gate than the Go wrapper it hands over from.
  • HTML pages are rendered by the twin from the same templates the Go panel embeds (internal/web/templates, internal/webtemplates): the twin carries a Go text/template-compatible engine with html/template's contextual escaping, the gotext .po catalogues, and receives the locale, the CSRF token and the pending flash messages from Go for page routes. A Go test renders each ported page through both engines from the same fixture and requires the same bytes; the same holds for every JSON reply (struct field order, whole floats, null for a nil slice, < escaping).
  • Form POSTs reach the twin with their body (Go buffers up to 8 MiB after the CSRF check and replays it; larger bodies and /api/ multipart uploads stream through), flash messages travel both ways as base64 JSON so non-ASCII text survives, a twin route ending in / matches that path only and not its subtree, and a twin handler may hand a request back to Go (X-Hitech-Pass). WebSocket upgrades, chunked streams and multipart uploads are proxied unchanged (proven on the web terminal, service journals and file uploads).
  • Nothing depends on the twin at run time: with RUSTPANEL=off or RUSTADMIN=off in the panel's environment file (/etc/hitechcloud/hitechcloud/conf/panel.env, /etc/hitechcloud/hitechadmin/config/admin.env), or while a twin is down, every route is served by Go exactly as in 3.4.0. A twin that fails before writing a byte is answered by the Go handler for that request. Routes whose Rust half covers the native stack only are not offered on a Docker-stack server.

User panel - hitechcloud-rustpanel, 271 routes​

  • JSON and read-only API (#75–#78, #80, #82, #84): /json/system/hosting/*, /json/services, /json/mysql-size, /json/directory-size, and the read routes of /api/* - account, hosting, server info, domains, DNS, emails, FTP and FTP connections, cron jobs, stats, send limits, inodes, disk usage, backups, site tools, DNSSEC and health checks, dashboard widgets, autoinstaller, port forwards, IP blocker, dynamic DNS, fix permissions, plugins.
  • Pages (#86, #88, #89, #91, #93–#95, #98, #104): server information, usage and usage history, IP blocker, fix permissions, site tools, hotlink, the inode and disk-usage explorers, FTP and its sub-pages, cron jobs, SSH keys, mailboxes with new/aliases/delete/catch-all/connect-devices, account, domains, DNS zone list, trash, backups, PHP default, per-domain PHP, PHP info and the extensions picker, sites, multiweb, git deploy, dynamic DNS, monitoring, dashboard, services, every MySQL GET page, the WordPress toolkit, the runtime installers (Node.js, Python, Ruby, Java, PHP), VPN, process manager and network diagnostics.
  • Writes (#100, #105, #109, #111, #112): SSH keys, FTP accounts, IP blocker and hotlink POSTs; domains (new, delete, suspend, unsuspend, docroot, redirect), DNS records and zones, site tools (protect, error pages, MIME types, HTTP/3); the MySQL module (delete database, users, passwords, assign, remove, optimize/repair, wizard, remote access and its access list); capitalize, vhosts, sites detach/remove/delete, dynamic DNS, fix permissions, cron jobs save/edit/delete, PHP default, dashboard markers; and the JWT write routes POST/DELETE /api/account/favorites, PUT /api/account/language, DELETE /api/account/sessions/{token}, /api/ftp create/delete/patch, /api/ssh-keys, /api/crons incl. raw, /api/ip-blocker, /api/fix-permissions, /api/dynamic-dns.
  • Streams (#101): service journals (page widget and API as NDJSON) and the web terminal over WebSocket.
  • File manager (#106): the pages, every read and every write - upload with streaming multipart, download, edit, rename, copy, move, delete, permissions, compress and extract, wget - in the session and in the API.
  • Applications (#108, #110): the install, backup-dates, logs and maintenance pages of Joomla, Drupal, PrestaShop, OpenCart, Nextcloud, Moodle, MediaWiki, DokuWiki, Flarum, phpBB, Matomo, OJS, SofaWiki and TinyPhotoGallery from one shared table; the auto-installer hub; the Joomla toolkit list; GoAccess statistics; traceroute JSON; the PHP X-Ray API over a FastCGI client with the slow-log parser; /plugins; the ImunifyAV page; live chat (all nine routes); the backup wizard page, status and create; the malware scanner incl. its streamed scan; the native web-server configuration page and API.

Admin panel - hitechcloud-rustadmin, 180 routes​

  • JSON and REST API (admin #6–#13, #18): system and resource snapshots, user activity and combined activity, IP pool and available IPs, user activity and login logs, PHP default version, backup files, transfers, apps status/peers/IPs, web engines, migrate status, livechat, user export status, liveness probes; the JWT API with declared gates - whoami, users, plans, domains, ips, usage, plan and account detail, server crons/processes/swap/timezone/node, licence info, support report, metrics, SSH, migrate, feature sets, administrators, mailboxes and queue, services control, settings, security toggles, notifications, disk usage, zone and file templates, backups, Packages & Apps status, WireGuard peers, livechat, export status.
  • Pages (admin #14–#16, #22, #24): resource usage, plans, notifications, settings (general lists, locales, mirror, Caddy and its metrics, PHP versions, updates, modules), security (incl. malware), server (crons, swap, timezone, processes, IP addresses, reboot, migrate, SSH and SSH config, node, databases, resource history, applications, processes strace/kill), backups, licence, templates, dashboard, users, domains, Packages & Apps, administrators, emails (relay, send limits, queue and message view), resellers.
  • Writes (admin #17, #19, #20, #22, #24): API writes for plans, accounts and notifications; session forms for notifications, timezone, memory, zone templates, custom code, PHP, blacklist, basic auth, crons, plans, account, broadcast, plan edit, domain, IP pool; emails relay/send limits/queue actions and bulk actions; settings locales/mirror/Caddy/PHP versions/updates preference; malware scan; SSH actions/config/keys/settings; node; database kill/limits/phpMyAdmin sign-on; swap resize/drop; process actions. Routes that need the Enterprise licence hand over only after RequireEnterprise (session-admin+enterprise).

CLI - hitechcloud-rustcli, 171 commands​

Each command is byte-identical to the script it replaced on the native stack (stdout, stderr, exit code, resulting files, units and tables); hitechcloud-rustcli ported lists what runs where, and hitechcloudcli/rustcli/MIGRATION.md has one row per command with what was verified.

  • Scripts removed (#16–#21, #23–#26, #29–#39, #42, #45, #46, #49, #51): config, user-login, port, version, api, license, locale, phpmyadmin, backup, admin, domain, docker, imunify, proxy, repair, report, dev, faq, patch, waf, enterprise, dns-cluster; ftp-* (list, users, connections, logs, delete, password, path, add); plan-* (list, create, edit, delete, usage, emailpro, apply), ip-pool, db-limits; user-* (list, loginlog, quota, suspend, unsuspend, rename, block_ip, delete, limit, change_plan, password, email, 2fa, varnish, ip, snapshot, backup, restore, backupset, check, transfer); domains-* (user, whoowns, all, suspend, unsuspend, docroot, varnish, ssl, dns, add, delete, edit, hsts, stats, update_ns, dnssec); email-* (quotas, sendlimit, webmail, setup, manage, server, ratelimit); websites-* (all, user, vulnerability, secure, pagespeed, wp_autodownload, scan); php-domain, php-default; gitdeploy-* (list, key, setup, deploy, poll, remove); toolkit-* (harden, wp, joomla, laravel, nodejs, ruby, inventory); files-* (fix_permissions, purge_trash, calculate_resellers_storage); cache-forget_features; server-repair, server-logrotate, server-migrate; compliance-retention, compliance-run; docker-* (autostart, backup, collect_stats, images, logs, limits); mssql-db, mssql-remote; and the native stack commands native-http3, -redirect, -hotlink, -errorpages, -mimetypes, -protect, -event, -litespeed, -mailusage, -memcached, -resolver, -mailforward, -movedomain, -varnish (status/enable/disable/restart/show/site/rebuild/sync joined purge/warm), -healthcheck, -usage, -sslstore, -firewall, -meet.
  • Native stack commands whose script hands over (#41, #43, #46, #48–#51): native-vhost and native-engine (the site renderer for nginx, Apache and OpenLiteSpeed, incl. the TLS, force-HTTPS, HSTS and suspended branches), native-ssl (certificates on the native stack: self-signed, Let's Encrypt via acme.sh, deploy, remove, autossl), native-dns (add, delete, list, show, check, reload, tidy, authoritative, set-address, publish-dkim, publish-ds; tlsa/bimi/spf-*/consolidate/backfill stay in shell for now), native-mail (install, sync, branding, check, status, domains, dkim, arc, identity, tls, hostname, test, webmail-master), native-service, native-restricted-shell, native-cache, native-search. The thin script remains because other scripts, systemd units or acme.sh call it by path; it execs the binary, and HITECHCLOUD_NATIVE_SHELL=1 forces the shell body for comparison.
  • Still shell: thirty native/* bodies (dnssec, docker, install, mailautoconfig, mailpolicy, mailrelay, webmail, migrate, mongodb, mssql, mysql84, postgres, pgadmin, phpmyadmin, multiweb, php, user, …) plus user/add.sh, db.sh, sentinel.sh and update.sh.
  • hitechcloudcli update fetches the panels' Rust twins when a release publishes them and keeps the previous panel binaries as <binary>.prev (#27, #40); MIGRATION.md documents the panel twins' routes and the fidelity rules (#28).

Sentinel​

  • The health monitor (integrations/sentinel) is a Rust program (sentinel #1); the release workflow builds it with cargo (#97).

Fixed on the way​

The port compared every command and route against the old implementation on a live server, which turned up bugs that are fixed on both sides:

  • domains-dns, /api/domains (has_dns_zone), the domains list and dynamic DNS read the container stack's /etc/bind/zones on native servers, so no zone was ever found there (#26, #82).
  • The FTP API answered 503 on every native server - it asked podman for a container instead of systemd for pure-ftpd (#76).
  • /api/emails and the aliases API parsed * login ( used / limit ) wrongly (quota_limit: "("); email-setup never refreshed the account's emails.yml (a variable scoped inside a function) and exited 0 after an error (#82, cli #29).
  • The MySQL Remote access page showed an empty port (@@port is unsigned); the IP-blocker JSON encoded no address as [] where Go's nil slice is null.
  • user-limit --show always reported inactive (SIGPIPE under pipefail); files-fix_permissions --all crashed in jq; backup --destination without a value looped forever; domains-update_ns wrote NS records above $TTL (a zone named refuses); toolkit-laravel called an undefined function; the admin's report ran its collectors without the stack library and reported command not found sections (cli #32–#39).
  • phpMyAdmin answered 502 on a server with per-account PHP-FPM (the distribution's master lost its system pools); native-fpm repair re-points it and the include is kept from now on (cli #22).
  • native-user delete never removed the account's FTP logins from users.list (cli #18) and user-delete left the account's jail sudoers rule behind (cli #46).
  • native-dns add never wrote the site-verification TXT record the deliverability page checks - it called an undefined function, and bash only printed command not found (cli #50).
  • A new site ignored its owner's PHP Selector version and took the server default (cli #52).
  • native-ssl renewals from acme.sh's cron could skip the vhost re-render: the scripts call vhost.sh by path again, since cron's PATH has no dispatcher (cli #47).
  • plan-create / plan-edit rejected the stored form 1 GB of disk_limit, and PATCH /api/plans/{id} without a name blanked the plan's name (cli #44, admin #21).
  • The settings/modules page's ?output=json encoded no plugin as [] where Go's nil slice is null (admin #23); db-limits status was parsed as active) === (admin #24); the admin's formatInodes rendered 0 for real plan rows (admin #22).
  • Flash messages with non-ASCII text (the CLI's ✖ lines, Vietnamese text) were silently dropped on a hand-over; they travel as base64 JSON now (#100, admin #24).
  • WordPress hardening on nginx wrote rules the engine could not load (cli #23, #24).

Operator notes​

  • hitechcloudcli update installs both twins with the panel binaries and keeps the previous panel binaries as <binary>.prev; version/3.5.0/UPDATE.sh re-syncs the CLI tree (removing the retired scripts), fetches a missing or outdated twin, checks that each answers routes, restarts both panels, probes :2083/healthz and :2087/login, and puts the previous binaries back if a panel does not come up.
  • The twins are static musl binaries and run on glibc 2.28 hosts (AlmaLinux 8) as well as current distributions.
  • Logs: the twins write to the panel's own log files (/var/log/hitechcloud/user/panel.log, /var/log/hitechcloud/admin/admin.log), one line per start (RUSTPANEL - … serving N routes on …).
  • INSTALL.sh refuses to finish without both twins; the panel units check that the twin binary exists before starting unless the twin is switched off.
  • The end-to-end suite (test-native-stack.sh) gives each sandbox a hitechcloudcli dispatcher so scripts that call one another through it run in CI (#107).
  • Nothing to migrate in the database, the configuration files or the templates.
Was this helpful?