# SixPanel release notes

> Source: https://test-allsweb.allsweb.net/sixpanel/changelog
> Markdown for agents: https://test-allsweb.allsweb.net/sixpanel/changelog.md
> Publisher: AllsWeb (www.allsweb.com)

Runs 6amMart directly on Ubuntu or Debian — nginx, PHP-FPM, MariaDB and Redis from the distribution’s own packages under systemd, with no containers in the running stack. The recommended runtime, and the one still being developed.

Which build a particular server runs is read from that server (`sudo sixpanel version`, or Settings in the panel), never from this page. Version numbers on the 1.4 line are renumbered from time to time — several same-day releases merge into one entry — so no single number here is a fixed landmark.

## SixPanel 1.5 — published on the Stable release channel, installable

### 1.5.0 — 2026-09-30

- **Websites and apps, beside your shop.** **Projects → Create project** now asks for
  the name, then the kind: **6amMart** — exactly as before — or a **static website**,
  a **Node.js app**, a **PHP website**, **WordPress**, or **Create with AI**. Each one
  runs as its own Linux account in its own folder and gets only what its kind needs:
  a static site has no PHP, no process and no database; a PHP site has no Node.js
  process. One website can never read another's files, and a Node.js app only ever
  listens on the server itself, so every visitor arrives through Cloudflare. Nothing
  about your 6amMart projects changes.

- **Static websites.** Upload a folder straight from your computer (no zipping), a
  ZIP, or deploy from git. The first `index.html` sets the folder that is served;
  single-page apps and `404.html` pages are recognised; a Vite, Create React App or
  Astro source is built on the server. Every deploy clears the Cloudflare cache, the
  last three versions stay on the server, and switching back is instant.

- **Node.js apps.** Choose no database or MariaDB when you create it. Your `.env`
  files are imported automatically and `.env.example` shows what is missing; the app
  is built and started once its address is live. The framework and package manager
  are detected and every command is editable. A new version starts beside the old
  one and goes live only after it answers, so a broken build never takes the site
  down — and a build that is only files is served with no process at all. Start,
  stop, restart, live logs and scheduled jobs are on the project's own pages.

- **PHP websites.** No database or MariaDB; the folder to serve is found from the
  framework; Composer runs when there is a `composer.json`. Deploys update in place,
  compared file by file by content, and never touch uploads, your own commands run
  after each one, and each site has its own PHP limits, worker pool, logs and
  scheduled jobs.

- **WordPress, managed.** The panel installs it on your address, signs you in to WP
  Admin with one click, takes a restore point before every update (the last three are
  kept, one click to go back — and putting one back keeps what is there first, so a
  restore that stops part way is undone rather than left half done), moves WordPress
  with you when you change its primary address, manages plugins and themes, and
  serves visitors from a page cache that clears itself when you publish. Hardening is
  on from the start: no file editor, no `xmlrpc.php`, no PHP in uploads, a sign-in
  rate limit and no username listing. Debug log, maintenance mode and search & replace
  are one switch each, and scheduled posts publish on time from a server timer.

- **Create with AI.** Describe the website and Tia writes it in Next.js; the
  panel builds it and publishes it on your address. Every chat message is one change,
  shown live beside the chat, stoppable while it runs and undoable afterwards, and a
  build error goes back to Tia to fix by herself. Bring your own provider: Claude with your Anthropic key, or any
  OpenAI- or Anthropic-compatible service — OpenAI, OpenRouter, Gemini, DeepSeek,
  Groq, Mistral, xAI, a gateway such as LiteLLM or OmniRoute, or a model on the server
  itself (Ollama). Providers live in the new **AI** section of the main menu: keep
  several, choose the one in use, load every model the provider offers and pick the
  default. Keys stay on the server. Next.js is installed the moment the project is
  created; the chat says what is missing with the button that fixes it, takes images,
  PDFs and text files (your logo and photos go onto the site, a screenshot guides the
  design), offers the AI's ideas for the next change, and previews the site at
  desktop, tablet and phone width.

- **Deploy on every git push.** Any website deployed from git can deploy itself on
  each push: the panel gives a webhook address and secret for GitHub, GitLab, Gitea
  or Forgejo, and only the branch you chose deploys.

- **Every website is in your backups, and comes back from its own page.** Each
  backup of the server now carries every website's database and files, on the same
  schedule and storage as your shops. A website's new **Backups** page says whether
  that is happening and lists the backups that hold it; **Restore** puts back the
  files, the database or both, for that website only. What is there now is kept
  first — a WordPress restore point, or an export of the database — and a static
  site, Node.js app or AI site builds and goes live from the backup like a deploy.
  Over SSH: `sudo sixpanel backup restore latest --site NAME`. The Backups page's own
  Restore lists the websites a backup holds beside your shops, so a server with only
  websites no longer offers a restore into a shop it does not have.

- **A website's Overview answers four questions at a glance** — is it live, can
  visitors reach it over HTTPS, is anything failing (errors in the last 24 hours),
  and when did it last change — each opening the page that fixes it.

- **An Errors tab for every website.** **Logs → Errors** lists each failure of the
  last day once, with how often and when it last happened — from the web server,
  PHP or the app. A bot asking for pages that do not exist is not counted as your
  site failing, and **Mark all as seen** starts the count again after a fix.

- **The full file manager for websites.** A website's **Files** page is now the one
  your shops have: select several files to copy, move, compress, extract, change
  permissions or delete; drag files in with a progress bar per file; search names;
  preview pictures; and an editor that saves with Ctrl+S and asks before throwing
  away changes.

- **Server → Scheduled lists every website's cron jobs** beside your shops' tasks,
  with how each one's last run went, and a server that has only websites no longer
  shows a "default" project there.

- **phpMyAdmin for website databases.** The website's **Database** page starts
  phpMyAdmin and opens it; you sign in with that website's own database user. It
  also works on a server that has only websites and no shop.

- **Two release channels: Stable and Latest.** **Settings → Release channel** lets you
  choose: **Stable**, the most tested and the one recommended for a live site, where
  1.4 stays; and **Latest**, the newest production release, where 1.5 starts. Every
  server keeps following Stable until you choose otherwise, including every server
  installed before channels existed. Switching installs nothing by itself, a Latest
  server is still offered a newer Stable release, and moving back never downgrades.
  Each choice shows the version that channel carries, and a switch can never move a
  server back: Stable opens to a Latest server only once Stable has reached the version
  it runs, and the card says so.

- **Tia, an AI assistant that runs the server with you.** **AI → Tia**, or **Ask Tia**
  on any page: ask in your own words and in your own language — "is my server
  healthy?", "why is the shop slow?", "create a WordPress site on blog.example.com",
  "take a backup now" — and she does the work through the same checks as the panel's
  own buttons, across every kind of project: 6amMart, static, Node.js, PHP, WordPress
  and Create with AI. You watch each step as it runs, and she suggests what to ask
  next. **Ask mode** (the default) waits for your approval before any change; **Auto
  mode** lets changes that can be undone run on their own. Anything that cannot be
  undone — a delete, a restore, a file write, a reboot — always shows you exactly what
  will run first, and a file change shows its lines before and after. A password or
  key goes into a secure field Tia never sees. She can never change who gets into
  the panel, read your secrets back, or approve her own request, and everything she
  changes is on the **Activity** page marked **AI**. Root shell commands are off unless
  you turn them on, and then each one asks for your password.

- **Tia's chat, rebuilt to feel like the AI apps you already use.** Her answers appear
  word by word as plain text beside her mark, with **Copy**, **Try again**, and code
  blocks with their own **Copy**; the steps she takes fold into one line you can open.
  Your conversations are listed by day, named from their first message, searchable,
  and can be renamed or deleted. Type **/** for commands and your saved prompts, switch
  **Ask** and **Auto** mode under the box, edit your last message with **↑**, stop her with
  **Esc**. A failed answer says why where it happened, with **Try again**. Her first
  words now start sooner: a new conversation and its first message go in one request.

- **Automations: Tia works on a schedule.** **AI → Automations**, or ask her: "every
  morning at 9, check the backups and the disk and send me a summary on Telegram". Each
  run is a conversation you can open, its report goes to the AI page, the alert email or
  an alert channel, and a quiet watch ("tell me when the disk is above 85%") speaks only
  when something needs you. Four ready-made ones to start from. On her own she only
  reads unless you allow safe changes and she is in Auto mode; anything that cannot be
  undone always waits for your approval, root commands never run unattended, and a
  restart never runs one twice.

- **AI monitoring.** The panel now watches the server every minute — stopped services,
  failed jobs, CPU, memory and disk (with a forecast of when the disk fills), sign-in
  attacks, every project's address, the health checks and each website's new errors —
  and opens an incident for each problem, closing it itself once it is gone. This
  costs nothing and needs no AI. Turn on AI analysis and Tia reads each new warning
  or critical incident and writes the cause and what to do, with a one-click fix when
  she found one; turn on auto-fix and she may run one fix that can be undone per
  incident. Alerts go to the alert email and to **Telegram**, **Slack**, **Discord** or
  any webhook, and a daily report can arrive every morning. **Dismiss** keeps an
  incident quiet while its problem lasts (it opens again only if it gets worse), a
  service must stay failed for two checks before it counts, and a failed job — which
  the panel already emails — goes to your channels without a second email. A critical
  incident is alerted at once; a warning's alert waits up to five minutes for the AI's
  cause, and goes out without it when the analysis cannot run or a restart cuts it
  short. An incident that gets worse is alerted again, and a website with recurring
  errors stays one incident. **Run the fix** only runs what the server can take back,
  shows it before it runs, and runs in the background — the incident shows its answer.
  At most six monitoring emails an hour; the channels get every alert.

- **Connect your own AI agent (MCP).** **AI → Connect**: Claude Code, Claude Desktop,
  Cursor, VS Code, Windsurf, Hermes Agent or any MCP client can manage the server
  with Tia's tools — over SSH with `ssh root@<server-ip> sixpanel mcp` (on AWS
  and Google Cloud images, which refuse root, the tab names your login account and adds
  `sudo -n`), or at `https://<panel domain>/mcp` with a token that carries its own limits: look only,
  changes that can be undone, or everything; dangerous actions approved in the panel
  or by the client; the whole server or only chosen projects; an expiry. A token is
  shown once, can be revoked at any time, and every change it makes is on the
  **Activity** page under its name.

- **More AI providers.** **Nous Portal (Hermes)** and **LM Studio** on the server join
  the list; OpenRouter requests are attributed to SixPanel; and the providers now serve
  Tia and monitoring as well as Create with AI — with a separate, cheaper
  model for monitoring if you like, and a daily token budget for each. An
  OpenAI-compatible provider is now asked for its token count on every streamed
  answer: before, most of them sent none, the count stayed at 0 and a budget could
  never stop anything.

- **One-click sign-in from AllsWeb.** A server you order from AllsWeb with
  SixPanel now opens its panel from your AllsWeb dashboard with one click, with
  no password to copy. The link works once and only for about a minute, and it
  stands in for your username and password only — with two-factor on, the panel
  still asks for the code. A browser that is already signed in keeps its session.
  Every such sign-in is in your activity log, and `sudo sixpanel sso off` switches
  it off.

- **The saved alert-email password only goes to the server it was saved for.**
  Changing the SMTP server in **Settings → Alerts** and leaving the password empty
  used to send the saved password to the new server — at the next alert, or at once
  with **Send a test email**. A different server now needs its password typed again,
  and the empty field says so.

- **The panel's address now works on servers with a long hostname.** On Google Cloud
  a server's own name is about 70 characters, and giving the panel its address failed
  there: the web server refused its whole configuration, and the half-made change was
  left behind, so its next reload for anything would have failed too. The web server
  now accepts names of any realistic length, and a refused change to the panel's
  address is put back exactly as it was.

- **A Node.js app stops cleanly.** A deploy or **Stop** sends your app the stop signal
  even when npm, pnpm or yarn started it, and gives it 15 seconds to finish; the
  version it replaces reads stopped, never "failed".

- **An update no longer fails when Ubuntu is updating itself.** Ubuntu's automatic
  updates hold the package system for a few minutes twice a day; a SixPanel update
  that arrived then stopped with "Could not get lock", with its new version unpacked
  but not running. Every package step of an update now waits for the other run to
  finish (up to ten minutes) and carries on, and if it is still busy after that, the
  message says to let it finish and run the update again — not to repair a package
  system that is not broken.

- The new pages are in all eight languages, and the manual has a new chapter,
  **Websites and apps**.

### Easier from the first page to the last

- **A website's Deploys page works like a 6amMart project's.** With nothing live it
  offers the three ways in — drop a ZIP or a whole folder anywhere on the page, or
  connect git — in words that fit the kind of website. Once live one card says where
  it stands: the version visitors get, since when and who put it live (by hand, a git
  push, Tia or a rollback), the repository and branch, **Deploy the latest commit**,
  and whether pushes deploy by themselves. A Node.js app's first upload is read, its
  `.env` files imported, and a checklist (**Files read**, **Environment**, **Domain**)
  says what is left; the app builds and starts by itself the moment its address
  answers over HTTPS. A deploy, build or rollback ticks off its steps on the page, and
  **History & rollback** lists every version with **Make live**.

- **Connect git in a window, private repositories included.** **Connect git** walks
  through the repository, what the deploy will do, and automatic deploys — and
  **Back** keeps what you typed. A private repository is read with an access token,
  or with a read-only **deploy key**: the panel makes one (or takes yours) and shows
  the public half to add to the repository, so `git@…` addresses work too. The
  connection is tested and the branches listed before anything is saved.
  **Automatic deploys** checks its own address first — a signed test delivery through
  Cloudflare — and notices the repository's first delivery by itself.

- **WordPress has a Deploys page.** It shows WordPress as it stands — version, theme,
  plugins and what waits to be updated — with **Update everything** as the next
  step, and its restore points as **History & rollback**. **Deploy your own theme or
  plugin** takes a ZIP, a folder or its git repository (and every push, if you like):
  the files are read the way WordPress reads them, a restore point is taken, only
  that theme's or plugin's folder is replaced — compared file by file by content, so
  an edit that kept its size and date still lands — it is turned on, and if WordPress
  stops loading with it the code that was there before is put back by itself. A theme
  already installed under the same name is updated in its own folder, so its
  settings stay, and a full marketplace download names the ZIP inside it.

- **A window closes only from its own buttons.** A click beside a confirmation,
  **Connect git** or a restore no longer closes it and throws away what was typed —
  **Cancel**, **Close** or **Done** does.

- **Each project keeps its own history.** Jobs used to be the server's last twenty,
  whoever ran them, so one night of backups pushed a website's deploys and their logs
  off its pages; each project now keeps its own newest eight as well.

- **A website's Backups page opens on the storage that holds it.** With more than
  one storage it asked the first alone, and an empty local disk read "not backed up
  yet" while S3 held every copy.

- **PHP settings show their defaults**, and a field left empty goes back to its
  default rather than to 0 — which PHP reads as "no limit". The extensions list shows
  what is installed, and searching finds one to add.

- **Dates read in the panel's language**, to the minute, and **Activity** files
  self-heal's repairs under a kind of their own (they read as Security).

- **A website's Domain & HTTPS page tells whether each address really works.** One card
  per address: does the name reach this server (directly, through Cloudflare, or
  somewhere else), and the certificate (valid until, renewing, expiring, missing a
  name). A name that does not point here shows the exact record to create — or a
  **Create the DNS record** button when your Cloudflare account holds the domain — and
  a name in that account that skips Cloudflare is reported and put right. One **Connect
  & get HTTPS** button appears only when something is not secure yet, and the connect
  shows its progress on the page.

- **One Projects page for every kind.** 6amMart projects and websites share one list
  with search and filter; an empty server shows the six kinds as cards. **Create a new
  project** asks the kind first, then everything on one screen — a website's address
  can be given right there and is connected as soon as the website exists. Creating
  while another job runs now waits its turn instead of being refused. WordPress gets
  an administrator name that is not "admin". **Home** lists every project, websites
  included.

- **New backup storage joins the automatic backups.** Adding S3 while nightly backups
  were on left them going to the server's own disk only. New storage is now included
  (the last step says where nightly backups go), removing storage never leaves the
  schedule pointing nowhere, and a server already in that state is put right when the
  panel starts. **Backup status** shows each storage's newest backup, count and size,
  and restoring opens on the storage that holds the newest backup.

- **The restore test proves your websites' databases too**, not only the 6amMart ones;
  a WordPress backup must bring back its settings and its users.

- **Alert email sets itself up.** **Settings → Alerts** has buttons for Resend, Gmail,
  Outlook / Microsoft 365, Brevo, SendGrid, Mailgun, Amazon SES and Zoho that fill the
  server, port and encryption; typing a port picks the encryption that belongs to it
  (a Resend setup on port 2465 with STARTTLS used to time out); a test email that
  arrives saves the settings it proved. The first-run wizard's last screen offers the
  same form, and its Cloudflare token field no longer shows what you paste.

- **AI → Providers checks the model it will use.** **Save and check** asks the chosen
  model a short question: a wrong key, address or model is refused with the provider's
  own reason, and running out of credit is saved with a warning. Provider cards with a
  **Get a key** link, a searchable model list with a suggested model, and **Check** on
  every saved provider. **AI → Monitoring** shows what it watches, when each check last
  ran and every alert it sent with what each destination answered, with **Analyse with
  AI** on each incident. **AI → Connect** makes a token in one click (90 days, look-only
  unless you choose otherwise) with the configuration to paste. Tia can set up
  a provider inside the chat and suggests questions about the page you are on.

- **Home and Health stop listing what you have just done.** Right after the first-run
  setup (two-factor login, the panel's address, backups, closing the bare IP) both
  pages went on listing those as to-dos for up to five minutes. Any change you make
  now refreshes the checks, and so does every finished job.

- **"Modules enabled with no code" is fixed on the Health row itself.** The row used
  to send you to SixPreflight's Fix button — but plain CodeCanyon 6amMart does not
  ship SixPreflight, so most shops reached a page with nothing on it. The row now
  carries **Switch off the missing modules**, and Health checks again when it is done.

- **A project's Overview lists what Health found for it.** The four tiles could not
  see problems such as CodeCanyon activation refusing the admin panel, so a project
  with three failures read "open and healthy — nothing is failing". Those findings now
  sit under the tiles, worst first, each with a button to where it is fixed.

- **SixPreflight connects itself.** The first time you open its page, the panel sets
  the tool's password and runs its first check — before, the page read "installed but
  not connected", then "never been run", and needed a press for each. A SixPreflight
  that had never been opened in a browser no longer has to be.

- **The database's memory comes back from swap by itself.** A memory spike — a
  storefront build is the usual one — can push MariaDB's cache into swap, and every
  page then waits on the disk. The panel now brings it back once nothing is running
  and there is room (**Settings → Automatic repairs** lists it), instead of asking you
  to run a command — and **Health** reports it from the same 128 MB at which the panel
  repairs it, so the row never promises a repair the panel has decided not to make. One repair that worked no
  longer turns **Automatic repairs** amber with "something keeps breaking": it is named
  in green, and the row warns only when an attempt failed or the same problem came back.

- **A PHP website's database goes into its `.env` in one press.** **Database** on a
  PHP website has **Write these into the app's .env**, which sets `DB_HOST`,
  `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` and the rest in place and keeps
  everything else in the file. Rotating the password updates an `.env` that uses it.

- **Installing 6amMart takes one press.** On the guided install, typing the address
  and pressing **Install** saves the address and starts; it used to need **Save**
  first. The screen also no longer says "the files win" when it keeps your database.

- **The disk page answers at once.** It shows the last measurement immediately and
  replaces it when the new one is ready (about 20 seconds on a server with eight
  projects), instead of showing nothing until then.

- **A website's Backups page opens at once.** It used to ask the backup storage for
  its list on every open — 4 to 5 seconds on S3. It now shows the list the panel
  read most recently and refreshes it in the background; a backup run always makes
  the next open read it fresh. Restoring still reads the storage live first, so a
  backup removed in the meantime is refused with the reason, never restored.

- Smaller: the project switcher at the top no longer draws its arrow over the
  project's name; the **Slow queries** card starts with its name; the database's
  version reads "MariaDB 11.8.6" instead of a cut-off package string; on a phone, a
  table's row buttons (Restore, Remove, Sign out, Log, Run now) stay at the card's
  edge while the table scrolls, instead of sitting past it.



## SixPanel 1.4 — published on the Stable release channel, installable

### 1.4.15 — 2026-09-29

- **A panel update could take the admin of a project running our optimised code offline.**
  When an update rebalanced the memory each project's cache may use — which happens when
  the number of projects has changed — it rebuilt that project's settings cache while
  reading the panel's own settings, and baked in the wrong database. The admin then
  answered with an error page until the cache was rebuilt by hand. It now rebuilds it with
  the project's own settings, and a test keeps every such step that way. Projects on the
  untouched CodeCanyon code were never affected.

- **`sudo sixpanel artisan config:cache` now takes effect at once.** PHP on your server
  keeps compiled files in memory and does not re-read them, so a settings cache rebuilt
  from the command line was not used until PHP was reloaded — the site went on answering
  from the old one. When an artisan command writes or changes one of Laravel's cache
  files, the command now reloads PHP itself and says so. Commands that only read, or
  that clear a cache, leave PHP alone, so the other sites on the server keep their warm
  cache.

- **The timezone you pick at setup now moves the panel's own schedules too.** The
  nightly backup, the weekly restore test and certificate renewal are timed by the panel
  itself, and they stayed on the clock it started with until someone restarted it — so on
  a server set to India time, "every night at 03:30" ran at 09:00 in the morning. Changing
  the timezone now restarts the panel once, on its own, as soon as nothing else is
  running. Nobody is signed out.

- **Live order updates behind Cloudflare: the advice now matches the certificate.** After
  giving websockets their own address, the panel told you to set Cloudflare's SSL/TLS mode
  to "Full, not Full (strict)" — even when it had just issued a real Let's Encrypt
  certificate for that address. Following it would have weakened every site on your
  Cloudflare account. It now says Full (strict), and keeps the old advice only for a
  self-signed certificate.

- **Installing the untouched CodeCanyon download, as it really works now.** The install
  screen no longer says 6amMart's own browser wizard will ask for your details again — the
  panel finishes that installer for you. The zip carries a log file from the vendor's own
  computer; it is no longer placed on your server, where the project Overview offered to
  show you "1 error" about a database that never existed here. And Overview's error card is
  green when nothing went wrong in the last 24 hours, instead of an amber "0 errors".

- **The setup wizard says only true things.** Its last screen no longer puts a tick next
  to "daily backups are not on yet" or "no email server is set up". The panel-address step
  no longer claims the server's IP address stopped working — it keeps working until you
  close it, which the panel offers right after setup and the Security page does any time.
  Certificate logs no longer open with a large warning banner printed by Ubuntu's own
  Cloudflare plugin, or say "self-signed" a moment before a real certificate is issued.
  Smaller things from the same walk: the product is spelled 6amMart everywhere, every
  drop-down wears the same arrow, the customer website's git step asks for the website's
  repository, the database clock card says how many hours apart the clocks are, and the
  Disk page no longer lists empty rows for a default project you never used.

- **SixPanel and your customer website now run on Node.js 26.10.0**, the newest release
  of the Node.js 26 line (it was 26.8.1), so the fixes Node.js has published since then
  reach your server. The update installs it before the panel restarts onto the new
  version, then restarts your website onto it too — there is nothing for you to do. Your
  server keeps holding exactly this version, so a routine system update can never move
  it underneath the panel. The panel's own components are on their newest releases as
  well.

- **An update that the server interrupted is now finished, not reported as failed.** If the
  panel is restarted in the middle of its own update — by a reboot, or, as happened on a
  customer's server, by Ubuntu's daily automatic updates starting at that moment — it used
  to come back and show the update as FAILED, even when the new version had already been
  installed and was running. The panel now checks this as it starts. If the new version is
  in place, it finishes the steps that had not run and the update ends as done, in the
  same entry. If the update had not installed anything yet, it says so, and that it is
  safe to run again. If it stopped while the new version was being put in place, it says
  how to finish it. Every update also checks that Node.js is still held at the version the
  panel needs. So an update stopped while it was installing Node.js cannot leave it free for
  the next system update to move. When it finishes an interrupted update, the panel restarts
  the database exactly as the update would have, including when the step that applies the
  new settings had failed. If the panel is restarted again while it is finishing, the entry
  says the update was interrupted, never that none of it ran.

- **An update that also moves Node.js could stop half way through.** When a new version
  of the panel needs a newer Node.js, the update installs it first. On Ubuntu, a system
  tool that runs after every package install (needrestart) then restarts every program
  whose files just changed — the panel included, which kills the update running inside
  it. The steps after that point (configuration, database migrations, restarting your
  services) would never run, and Node.js would be left unprotected against the next
  automatic system update. Updates now install Node.js, and every other package they
  need, without letting anything restart, and restart your services themselves once the
  new version is in place. If the server's own automatic updates are running at that
  moment, the update now waits for them instead of failing, and it checks that Node.js is
  really held at the right version afterwards. It used to put that hold back without
  checking, and the hold could quietly fail while the system updates were running. Your
  customer website is also restarted onto the new Node.js on servers that got Node.js from
  nodejs.org rather than from a package.

- **An update no longer sets off a "queue worker failed" alert.** An update restarts your
  server's services in two groups, and a project's Redis restarted while that project's
  queue worker was still running. The worker checks Redis on every loop, so it stopped
  with an error; it was started again a second later, but the failure alert had already
  gone out — about an update in which nothing had gone wrong. The worker is now paused
  before Redis restarts and started again after it, as it already was for the database.
  Restarting a project's Redis from the Services page does the same, and so does an
  update that changes Redis's own settings.

- **A panel restart can no longer leave your queue worker switched off.** The panel pauses
  your queue worker and scheduler for a few seconds while it restarts the database or
  Redis, deploys, or updates itself, and starts them again afterwards. If the panel itself
  was restarted during that pause — by a reboot, or by Ubuntu's daily automatic updates —
  nothing started them again. Orders stopped being processed and scheduled tasks stopped
  running, with nothing reported as failed. The panel now writes each pause down, and when
  it starts it restarts any worker that an earlier run of the panel paused and never
  resumed. Stopping a project's cache (Redis) on its Services tab now also keeps that
  project's queue worker and scheduler stopped, instead of starting them again ten minutes
  later while the cache is still off, where they could only fail. They start again on their
  own once the cache is running, however you start it.

- **A project you moved to another server now stays stopped on the old one.** A move
  leaves the original copy on the old server, stopped, so you can go back to it. About 75
  minutes after the move began, its queue worker, scheduler, websocket service and website
  were started again. From then on two copies of your shop
  were processing background jobs and scheduled tasks, each against its own copy of the
  data. The copy left behind now stays stopped until you start or delete it. A whole-server
  migration leaves every project behind in the same stopped state. Bringing a shop over from
  another server also no longer restarts its queue worker a second time ten minutes after it
  finishes.

- **Weekly maintenance no longer drops its security update after updating the panel.** The
  maintenance window updates the panel, the panel restarts, and the window then carries on
  with the server's security updates. It picks up again 45 seconds after the restart, and
  if the panel was still finishing its own update at that moment, the window counted that
  as "busy" and skipped the rest. You were emailed that maintenance was skipped, and the
  week's security updates were not installed. The window now waits for the panel to finish
  (up to 30 minutes) and then completes. If you run the window yourself during that wait,
  it does not run again on top of yours. Pressing Run now during a project move or a server
  migration is refused with the reason, instead of answering that maintenance started.

- **The panel no longer freezes while it sets up a project's cache.** Creating or deleting a
  project, applying a tune, or changing a setting that restarts its Redis could lock the whole
  panel for several seconds. Pages stopped loading and live job logs paused until it was done. That work now
  runs alongside the panel, so the panel keeps working meanwhile.

- **The panel is back several seconds sooner after every restart.** Each time the panel
  started (after an update, a reboot, or Ubuntu's automatic updates), it first spent about
  five seconds compressing its own page scripts, and longer on a busy server. Until that
  finished it answered nothing, and it did not pick up what it had been doing, such as
  restarting paused workers or finishing an interrupted update. The compression now runs
  alongside while the panel answers. For those first few seconds your browser downloads a
  slightly larger copy of the same page.

- **A failed download during an update can no longer leave the panel unable to start.** An
  update refreshes the panel's own components from the internet. If that download failed
  part way, because of a network blip or the package registry being down, the old
  components had already been deleted. The panel kept running until its next restart and
  then could not start at all, and repairing it needed SSH. The new components are now
  downloaded beside the old ones and swapped in only once the download is complete, so a
  failure leaves the panel exactly as it was. The same applies when you run the installer
  again over SSH.

- **Updating your customer website took the live shop apart while it built — and a build
  that failed left it broken.** The storefront used to be rebuilt inside the folder it is
  served from, and the build's first act is to empty the part of that folder the running
  site loads its scripts from. Measured on our own server: a build that ran out of memory
  stopped half way, and from then on every page still appeared but none of them worked — the
  home page's 20 scripts all failed to load, so there was no signing in and no cart — until
  someone rebuilt it by hand. Even a build that succeeded did the same thing for the four or
  so minutes it ran, on every update and every push-to-deploy.

  The new version is now built in a separate folder beside the live one, and only a build
  that finished is switched in, in a few seconds, right before the site restarts onto it.
  **If a build fails, nothing on your live website changes** — it keeps serving the version
  it had, and the log says why the build stopped. New dependencies are installed in the
  separate folder too, so the running site never loses its modules mid-install. If the
  build ran out of memory, the log now says what is actually true: the build is given as
  much memory as is free when it starts, so running it again while the server is quieter
  often gets through (it used to say a retry would fail the same way, and on our server the
  retry succeeded).

- **After a deploy, the websocket server kept running the previous release.** Live order
  tracking and the other real-time features run in a long-lived process that loads your
  shop's code once, at start. Every deploy, rollback and zip update refreshed PHP and
  restarted the queue workers, but never that process, so it went on running the old code
  until something else happened to restart it. Found on our own server: a fix that stopped
  every rider location update being handled twice was deployed, and the websocket server —
  up for two days — was still doing it twice. Deploys now restart it too, and only if it
  was running: a websocket server you switched off stays off.

- **A PHP setting the server rejects can no longer take every shop down.** PHP's settings
  are shared by all the shops on the server, and a reload onto a configuration PHP refuses
  stops all of them at once — measured on our own server, a single invalid line took every
  site down for four seconds. The panel now tests the configuration before every reload,
  and if PHP rejects it, it leaves the running shops exactly as they were and shows you
  PHP's own reason.

- **Turning an addon on or off in your shop's admin panel said "updated successfully"
  and nothing happened.** Reported on a live shop: the Rental addon would not enable —
  the green notification appeared every time and the addon stayed off. This was ours,
  not your shop software's, and it is the reason the same click works on other panels.

  SixPanel keeps your PHP code compiled in memory and, for speed, tells PHP never to
  re-check the files on disk. Your shop's admin panel stores the addon switches *in* a
  PHP file and rewrites it when you click. So the click really did save — the file on
  disk was correct — and the server went on running the version it had already
  compiled, indefinitely. Measured on the reported server: the file said the addon was
  on, the running site said it was off, in the same request.

  The panel now excludes exactly those files from the compiled cache, so a switch takes
  effect the moment you click it, with no restart and nothing for you to do. The speed
  work is untouched everywhere else: this covers a handful of small settings files, not
  your translations or your application code, which is where that speed actually comes
  from.

  **The same fault was also silently affecting payments.** The payment-gateways addon
  rewrites one of your shop's payment code files by itself, and that file was being
  cached the same way — so after it updated, the server could keep running the previous
  version of your checkout code. That file is now covered too.

  If you have been fighting an addon switch that would not stick, it will stick after
  this update.

- **"Server security updates" could be stopped dead by a setting your server image
  shipped, and the panel only said "exit code 100".** Reported on a fresh install on a
  Linode Ubuntu 26.04 server. Some provider images record the wrong thing where the boot
  loader's disk should go, and nothing notices, because the boot loader only reads that
  setting when it is itself updated. So the server looked perfectly healthy — every check
  passed, the install was clean — and then the first security update upgraded that package,
  its setup step failed on the bad setting, and the whole update stopped with around 200
  packages half applied. The only explanation on screen was "the server command failed
  (exit code 100) — read the log above", which is true and no help at all.

  Three things changed. **The update now looks for the fault before it starts**, not only
  for packages that are already broken, and repairs it — your server keeps working either
  way, so it never refuses the update over this. **If an update does stop part way, it
  finishes the job instead of handing you a failure**: it repairs whatever the system left
  unfinished and runs the install once more. That matters beyond this one fault, because an
  unfinished package blocks *every* later install on the server, so one unlucky update used
  to break updates for good until someone logged in over SSH. **And when it genuinely
  cannot fix something, it names the package** and tells you the one command whose output
  identifies the real problem — instead of a number.

  `sixpanel server os-update` got all of the same: it had none of this before, so the same
  server behaved differently depending on whether you used the panel or the command line.

- **`sixpanel info` refused to run on a brand-new server — the one place you most need it.**
  When the installer finishes, it prints your panel address and, if it could not work out
  this server's public address, it tells you to run `sixpanel info` to get the URL; it does
  the same for your username. On a server with no project yet, that command answered "there
  is no 6ammart project on this server yet, so there is nothing to act on" — so if you had
  closed that terminal, there was no way back to your own panel from the command line. Nothing
  `info` prints is about a project: it is the panel address, the panel domain, your username,
  the version, the port and where things are kept. It now runs on any server, and still tells
  you if you name a project that does not exist.
- **Three places where the panel said a job had done something it had not.** Each of these
  was found by installing a shop from scratch and then checking the server rather than the
  screen. **A shop install that stopped early no longer reports itself as finished.** If the
  install needed your browser to complete it and you never went there, the project used to
  show as installed anyway — with an empty database, and a storefront that failed on every
  page because it was asking your shop for settings that did not exist yet. The project page
  now tells the two apart. **The website is no longer announced as live when it has been
  stopped.** On a first install the panel deliberately stops a website that cannot serve yet,
  so your visitors get the friendly "coming soon" page instead of an error — but it then said
  the site was live, with the address, in the same job. It now says what actually happened.
  **And `sixpanel db import` now really replaces what it warns you it will replace.** It asks
  you to type your database name because every row is about to go, and then could not do it:
  most shop dumps create tables without removing the old ones first, so the import stopped on
  the very first one. Worse, it then said the database "may be half-loaded" about a database
  it had not touched at all — advice that would have had you restore a backup over data that
  was perfectly fine. It now clears the old tables first (your database user and password are
  untouched), skips that when the dump already does it, and, if an import does fail, tells you
  plainly whether anything was changed.

- **"Update the admin app" now tells you what is wrong, and lets you fix it on the spot.**
  If your shop's code lives in a private repository, pressing Update could come back with
  nothing but "The request failed (502)" — a gateway error about a panel that was working
  fine and already knew the answer: it had no access token for that repository, so it could
  not look for new commits. The reason was being sent, but as a server error, and Cloudflare
  replaces those with its own "Bad gateway" page before your browser ever sees them. The
  panel now says plainly that the repository is private, asks for a token right there, and
  runs the update with it — and keeps it, so later updates and deploy-on-push work without
  asking again. If the repository is simply unreachable it says that instead, rather than
  asking for a token that would not help.

- **Health now watches the one thing that can slow your whole server down silently.** Your
  server compiles your shop's code once and reuses it, which is most of the reason pages
  answer quickly. If that store ever fills up it does not make room — it stops storing, and
  the code is compiled again on every single visit. Every page gets slower and stays slower,
  and until now nothing anywhere would have told you: not a log, not a warning, not a number
  on any page. **Server → Health** now reports it, with how full it is, how much of it is
  still in use, and how often it is doing its job. Nothing to switch on. On both of our own
  servers it reads healthy, so if yours does too, that is the answer and there is nothing to
  do.
- **The panel no longer reports its own files as tampering.** On some servers Health could
  warn that "server setting file(s) that SixPanel writes have changed … and no panel
  operation ran that would explain it", name a file or two, and advise treating the server as
  compromised. The panel had written those files itself, moments earlier, and they were still
  exactly where it left them — it was keeping a note about files it then looked for in the
  wrong place. That warning was wrong every time it appeared, on every server that saw it, and
  a warning that cries wolf is worse than none: it teaches you to scroll past the ones that
  are real. It clears itself the next time the panel writes anything, with nothing for you to
  press. A genuine hand edit is still reported, exactly as before.

- **"Get the latest code" no longer refuses because of a file the panel wrote itself.** On a
  site set up through the 6amMart installer, updating could stop with "local changes present
  — a deploy will not throw a hand edit away" and name
  `app/Providers/RouteServiceProvider.php`, a file you never touched. The panel writes that
  file itself when it finishes setting your site up, and it was then reading its own work as
  somebody's hand edit. Worse, the way out it offered would have undone that setup and left
  your admin panel and API answering on every hostname instead of yours. Updates now go
  through, and a real hand edit is still stopped, exactly as before. This affected the plain
  CodeCanyon 6amMart download most: there it refused every update once the site was live.
- **Image uploads work again in the admin panel.** On a server where this had gone wrong,
  every image upload failed with "Image upload failed. Please try again." — product photos,
  banners, logos, all of them — while the rest of the panel looked perfectly healthy. The
  cause was ours: the private scratch folder each site's PHP uses for an in-progress upload
  had been created so that PHP could not reach it, so every upload was thrown away with
  nothing in your site's log to explain why. Sites already affected are repaired
  automatically when the panel next starts; nothing for you to do.
- **The Addon on/off switches and a few other panel actions work again.** Turning
  "Payment & SMS Gateways" (or another addon) on or off did nothing at all — the switch
  moved back and no message appeared. 6amMart looks for a handful of its own files using a
  path relative to your site's main folder, which is how it is written and how it works on
  other control panels. SixPanel serves your site from its `public` folder, which is the
  safer arrangement — it keeps your `.env`, your uploads and your installed libraries off
  the public web — and that difference is what stopped those files being found. The panel
  now gives each site the working directory its code expects, so both arrangements work.
  **This also fixes a quieter one:** on a shop using the Rental addon, a trip that was
  completed and paid could record no transaction against it, silently. Same cause.
- **Nothing to change on your side, on any of it.** These are all server-side, applied when
  the panel starts, and they work the same on the plain CodeCanyon 6amMart download as on a
  customised one.

- **"Apply tuning" now shows that it worked.** On the Performance tab the rows could keep
  showing the OLD size after a successful tune — "Database memory 256 MB,
  suggested 7168 MB" on a server already running the bigger value — so the suggestion
  stayed highlighted and pressing the button again appeared to do nothing. The tuning had
  been applied every time; only the page was reading the wrong line of the database's
  configuration (the installer's starting value instead of the tuned one that overrides
  it).
- **And the cache row was telling the truth about a real mistake.** Chasing the same
  report to the bottom found that the cache memory budget was being divided by one count of
  your projects and then written to a different one — so on a server whose default project
  has no site in it yet, EVERY project's cache was given the whole budget instead of a
  share of it, twice the memory the server had set aside. The panel now divides by exactly
  the list it writes to, so the shares add up to the budget you were shown. If your cache
  rows drop after this update, that is the correction: the old numbers were over-committed,
  not the new ones under-sized. Both rows also now read what the server is actually
  running, so after a tune they match the suggestion and the button goes quiet.
- **An install's own record now says which way it installed your shop.** When you chose
  to finish the setup in your browser, the job's step list said so at one step and then
  said the opposite at four others — "this install ran headlessly", "already done on the
  headless path" — about work that had not been done at all. Nothing was broken by it,
  but that list is the only record of what SixPanel did on your behalf, and it
  contradicted itself. Each of those lines now names what actually happened: the panel
  installed it for you, you chose the browser wizard, or your codebase ships no installer
  the panel can run, so the wizard finishes it.
- **A project name you have used before can be used again.** If a project's server
  account had been removed without the panel doing it — an uninstall finished by hand, a
  half-completed wipe, a restore from another server — a leftover group with that name
  stayed behind, and from then on creating a project with that name always failed at
  "Provision native runtime" with a message about `useradd` and `-g` that looked like a
  fault in SixPanel. The panel now recognises the leftover group and uses it, which is
  what it was for, so the name works again with nothing to clean up by hand.
- **A panel that cannot start now says so, instead of reporting that it is running.**
  If the panel's port was still held by something else at the moment it started — which
  can happen for a second when the panel restarts — it carried on with nothing actually
  listening. The install finished, every step was green, the closing message printed your
  panel address, and that address refused to connect. The panel now waits and retries a
  few times, then stops properly so the server restarts it; and the installer asks the
  panel port whether it answers before it tells you SixPanel is running, naming the one
  command that fixes it if it does not.
- **Installing your shop from a private repository works with the deploy key the panel
  gave you.** "Test connection" passed and the install right after it failed at the very
  first step with git's "Host key verification failed" — on the same address, the same
  key and the same repository. The install was the one place that never used the deploy
  key you had just pasted into GitHub or GitLab, so it tried to connect with no
  credential at all. Almost every CodeCanyon repository is private, so this was the
  usual path. The key is now used for the first clone and written into the installed
  copy, so "Get the latest code", deploy-on-push and rollback keep working afterwards.

- **"Create the DNS record" appears where it was meant to.** Earlier in this release
  the button could never show up: it was shown only for addresses that already resolve
  through Cloudflare, and an address with no DNS record does not resolve at all — which
  is exactly the row that needs it. The panel now asks whether your Cloudflare account
  holds that domain, which is the question that decides whether it can create the
  record, so the button appears on the row that says "it has to go to this server".
- **And it no longer says a record was created when none was.** If the name could not
  enter the plan at all, the panel reported success. It now says plainly that nothing
  was created and what to do next.
- **A web address is never added to two roles at once.** When a certificate covered a
  name that belonged to your website, the admin side could take a copy of it — two
  https server blocks for one address, which nginx resolves by picking one, so the
  wrong app answers with every screen reporting fine.
- **The `www` address the panel adds for you is checked like one you typed.** It could
  previously land on the panel's own hostname, or on a placeholder name a fresh server
  invents for itself, both of which the panel refuses when you type them by hand.
- **A rebuild that keeps failing is retried a few times, then reported.** The previous
  release stopped queueing repeated rebuilds, which fixed the churn by going silent
  instead — after one failed build, nothing was queued again and no screen said so. It
  now retries up to three times and then records that it gave up, so the work is either
  done or visible.
- **A rebuild that is owed is remembered even when the panel cannot tell from the
  files.** On some installs the check that decides "is a rebuild needed" read the very
  file the panel had just corrected, so a failed build looked like nothing to do and the
  site quietly kept its old address.
- **A redirect you set while a certificate was being issued now takes effect.** Your
  choice was kept in the panel's own records and left out of the configuration nginx
  serves, so the redirect silently did not fire until some later change happened to
  re-write it.
- **One link to Cloudflare's IP list, in a language the panel actually has.** The list
  of languages included nine the panel does not ship, so those entries could never be
  chosen.
- **Reading a Cloudflare record is faster and cannot spin.** Following a `www` address
  to where it ends up asked Cloudflare once per step, including for domains outside
  your account; it now reads the zone once, and an address pointing at itself stops
  immediately.

- **A web address that is in your certificate but was left off https is repaired by
  itself.** If a name ended up inside the certificate while the panel's own list said it
  had no certificate, that address answered a Cloudflare 525 error for every visitor
  while the panel reported everything as fine. Not creating that state was only half of
  it; the panel also repairs the servers where it had already happened. On start-up
  the panel compares each address against the certificate it is actually served with, and
  any name the certificate really carries gets its https server block back. It never
  works the other way — an address that is serving today is never taken off https — and
  your redirect and primary choices are left exactly as they were.

- **A web address on Cloudflare that reaches this server through another name is read
  correctly now.** If your `www` address is set up as a CNAME pointing at your root domain
  — the commonest way there is — the panel compared that name against this server's IP
  address, found them different, and told you "goes through Cloudflare to a different
  server" about an address that was working. "Fix everything automatically" then refused
  to touch it, because the panel had classified it as somebody else's machine. It now
  follows the name to where it actually lands.
- **"Point this at my server" works on those addresses.** It sent the address the name
  resolves to — a Cloudflare address, not the record's own value — so the panel checked
  that against your DNS record, found a mismatch and refused every single time with
  "so nothing was changed". It now sends what your DNS record actually says, and when the
  record has to be replaced rather than edited (Cloudflare cannot turn a CNAME into an A
  record) the confirmation says so, including the moment in between when the name will
  not resolve.
- **Adding a root domain adds its `www` form, everywhere a domain is added.** Type
  `example.com` and `www.example.com` appears on the list beside it, serving the same site,
  whether you added it on the Domain & SSL page or during the create-project or install
  wizard. Both were meant to do this; neither did.
- **And you can set it up from the row that reports it.** An address that does not point
  here yet said "it has to go to <this server>" and offered nothing that would put it
  there — you had to find the whole-page fix button or open Cloudflare by hand. That row
  now carries the one action it needs: create the DNS record, or repoint it if it goes
  somewhere else.
- **Every address in your certificate is served over https.** A `www` address added while
  the certificate was being issued ended up inside the certificate and outside nginx: the
  root domain answered normally and `www` answered a Cloudflare 525 error, with every step
  of the job reporting success. On a website that also made the panel publish `http://`
  links in every page's canonical address, share preview and sitemap entry.
- **The website is no longer rebuilt when a restart would do.** Changing the address the
  website publishes about itself queued a full rebuild — minutes of work — where a
  two-second restart applies it, so a few clicks on the Domain page could mean three
  rebuilds in five minutes. The panel now checks whether the value is compiled into the
  site or read when it starts, and does the smaller of the two.
- **A rebuild that fails is remembered.** The panel decided a rebuild was needed by
  looking at the last one that finished, so a build that ran out of memory left every later
  domain change queueing another full rebuild — or, on some installs, quietly stopped
  retrying and left the site on its old address. It now records what it owes before it
  starts, and clears that only when a rebuild finishes.
- **One link to Cloudflare's IP list on the Firewall page**, chosen by the panel's own
  language, instead of two links to the same page in different languages.

- **The customer website is installed through a wizard now, like the admin app.** It used
  to be a collapsed card on the Deploys page: you opened a disclosure and the repository,
  the credential, the connection test and the branch all appeared inline underneath, in a
  card competing with everything else on the screen. It is the same numbered, one-question-
  at-a-time wizard the admin app opens, and it starts on the CodeCanyon zip — the file most
  people actually have — instead of asking for a repository address first.
- **The first-run setup no longer sends you back to step one.** On a server where the
  welcome, password and address steps were done and only two-factor was left, opening the
  panel showed "Welcome to SixPanel" and asked for the country, timezone and email again —
  while every other page said "finish the first-run setup first". It now opens on the step
  that is genuinely unfinished, with the finished ones ticked.
- **"A brand-new project" is no longer overruled into a migration.** If the code you point
  the panel at carries its own settings file, the panel reads it as a shop that has already
  been running — true, and for a fresh install beside the point. It then asked for a
  database dump and an uploads zip that a new project does not have, and refused to install
  without them, so following the screen led nowhere. Your answer on the first screen now
  decides; what the files say is reported beside it.
- **Re-installing after an uninstall works.** `sixpanel server uninstall` ends by saying
  "undo: re-run the installer", and the installer then refused with "this does not look like
  a fresh server" — because SixPanel's own nginx was still holding ports 80 and 443. It now
  recognises its own configuration and continues as a re-install.
- **The website's install button starts the install.** In the new wizard it produced only a
  small error message and no job. Fixed, with a build check that keeps that class of failure
  from coming back.
- **A second install cannot be started while one is running.** The website's install button
  is disabled again while a job is in flight, like every other action on that page.

- **The customer website can be installed from a private repository over SSH.** Until now
  the storefront's install form offered one credential — an access token — so a website
  repository that only answers over SSH could not be installed from the panel at all, and
  a website already using a `git@…` address failed every later update with git's own
  "Permission denied (publickey)". The website now gets the same two choices the admin app
  has, and its own deploy key: separate from the admin app's, so the two repositories can
  use different keys, and the key you paste into the repository is the one this server
  really presents.
- **The website's install screen asks the repository before it asks you.** It now has the
  step the admin app grew: press **Test connection** and in about a second you know whether
  this server can read the repository and which branches it has — so the branch is picked
  from the real list instead of typed, and a wrong token is found now rather than several
  minutes into a build. The install button stays off until that test passes. Previously the
  branch box came pre-filled with `main`, which is a guess about a repository nobody had
  asked yet.
- **A working certificate is no longer reported as broken.** On a server whose own DNS
  resolver had not caught up with the record the panel created seconds earlier, the last
  step of the certificate job said the site was "not usable from the internet yet" and told
  you to check your Cloudflare proxy and your provider's firewall — when the certificate
  was real, on disk, and being served correctly. The panel now asks your domain's own
  nameservers when its resolver comes up empty, and says so in the log when that is what
  happened.
- **A failed certificate no longer takes the install away.** If the certificate step went
  red during the install wizard, the "Set it up" button stayed greyed out with no way
  forward and no way back: the address was saved, the code was ready, and the only escape
  was to cancel and start again. The certificate was never required to install — you can
  finish, and get HTTPS afterwards from Domain & SSL.

- **A domain on Cloudflare that points at somebody else's server was shown as active.**
  A proxied record hides the real server behind Cloudflare's own addresses, so every
  proxied domain on earth looked identical to one of yours — added a domain, saw a green
  tick, and nothing was serving it. The panel now reads the record's real destination
  through your Cloudflare token and says one of three things: reaches this server, goes
  somewhere else (naming where), or unconfirmed when it genuinely cannot tell. Only the
  first is a tick.
- **A root domain and its www name, and a choice between them.** If you add
  `example.com`, `www.example.com` almost certainly points at the same place, so the
  panel offers to add it and to send visitors from one spelling to the other — the single
  address search engines prefer. Available on the admin site, the storefront and the
  websocket address, wherever the address is a root domain. The redirect happens in the
  web server itself, so it costs a visitor nothing and needs no Cloudflare rule.
- **A domain already pointing at another server can be moved here.** Previously that
  just failed. The panel now shows what the record says, and offers to repoint it —
  re-reading the record immediately before it writes, so one that moved in the meantime
  is left alone and reported instead.
- **Notifications you can actually see.** They now carry a heading that says what
  happened, a tinted background per kind, and a deeper shadow. Errors stay on screen
  until dismissed instead of vanishing while you are still reading them.
- **Mac and Windows junk files are deleted.** `.DS_Store`, `__MACOSX`, `._*` and
  `Thumbs.db` are removed from every archive the panel unpacks, and Disk cleanup can
  sweep the whole disk for them. That sweep runs at the lowest CPU and disk priority,
  skips database directories, `node_modules` and `.git`, and never deletes a file your
  own git repository tracks — one that does gets left alone, because removing it would
  stop every future deploy.
- **The email-alert form names the ports that are not blocked.** Many hosts block 25,
  465 and 587 outbound; 2465, 2525 and 2587 usually go through, and Resend uses 2465.
  The form lists them with what each one means, before a test send fails for a reason
  the error cannot explain.
- **The Cloudflare setup page tells you where the token actually is.** It links straight
  to the account API-tokens page (an account token is what the panel needs, not a user
  token) and walks the screens with four annotated screenshots.

Fixes to the above, found by auditing this release's own changes:

- Making a name your primary address while it was redirecting elsewhere left your
  application registered on a hostname that answered only a redirect — every API URL
  a 404, while the panel's own pages looked fine. Promoting a name now clears its
  redirect and tells you it did.
- A www name set up as a CNAME — the commonest way — read as unconfirmed, and the panel
  blamed a missing Cloudflare token when one was connected and working.
- A successful repoint kept reporting the old destination for up to a minute afterwards.
- The www/redirect controls did not appear at all for about a hundred domain endings,
  including `.com.my`, `.co.id`, `.com.ph` and `.org.uk`.
- On a server that briefly could not determine its own public address, "Get free SSL"
  was disabled for every Cloudflare-proxied domain.
- **A rebuilt server showed a panel full of errors, and nothing was wrong with it.**
  If you wiped a server and installed SixPanel again on the same panel address, your
  browser still remembered the project you had before — a project the new server has
  never heard of. Every page then asked about it and was turned away: Home said "The
  request failed", the Cloudflare tab said "no such project", and the whole panel read
  as broken on a server where everything was fine. Opening the same address in a fresh
  browser proved it. Three things were wrong and all three are fixed: pages that have
  nothing to do with a project are no longer refused because of the name attached to
  the request, the panel now forgets a project the server does not have, and a
  bookmarked project page can no longer put that name back.
- **The Cloudflare address lists were missing from the Firewall tab on some servers.**
  The two lists of Cloudflare addresses — IPv4 and IPv6, with their Copy buttons — are
  one of the main reasons to open that tab, and they only appeared if your addresses
  were already behind Cloudflare. On a server where some were and some were not, and on
  a brand-new server with no domain added yet, they were not there at all — which is
  exactly the server whose owner is setting up a firewall for the first time. They are
  now always on the tab, on every server, because they are simply the addresses
  Cloudflare's proxy connects from and those are the same everywhere. What changes with
  your setup is the sentence above them: paste these as the sources of your 80/443
  rule; paste them only if every one of your addresses goes through Cloudflare (the tab
  names which ones do not); or, when none of them does yet, do not build that rule on
  this server — it would cut off your visitors and stop your certificates renewing. The
  tab also links Cloudflare's own pages, including the India address, so you can check
  the lists at the source any time.

- **Installing a project's code failed at the last step, and the reason was a file permission.**
  The install got as far as generating the app key and stopped with "Failed to open stream:
  Permission denied" on the project's own `.env`. The panel runs as root, so it had written
  that file as root inside a folder owned by the project's own account — and the app, which
  runs as that account, could not read its own settings. The step that writes the file now
  hands it to the right owner immediately, so this cannot depend on which path the install
  took. An existing project is repaired by its next deploy.
- **The install wizard asked your browser for the git address, and got your panel login.**
  Password managers offer a saved login by web address, and the panel's own sign-in page
  lives at the same address — so the "Git repository URL" box could come up holding your
  panel username, with a saved password in the token box below it. Then "Test connection"
  failed against an address you never typed. Both fields now tell the browser to leave them
  alone.
- **An admin password was generated before you asked for one.** The install screens filled
  in a password on open and captioned it "copy it now, it is shown once", on a form you had
  not started, and printed the same secret a second time below the form. Now nothing is
  generated until you press "Suggest a strong password", and it appears in the password box
  itself — readable while you are there, hidden again when you click away, with one place to
  copy it from.
- **A domain pointing at another server can now be moved from the install screen too.** It
  told you the name already points somewhere else and suggested a button that only exists on
  the Domain & SSL page. The button is now on the screen that found the problem: it replaces
  the record with this server's address and continues to the certificate. If the record
  changed since it was shown, nothing is overwritten and you are told instead.


### 1.4.14 — 2026-09-14

**Take this one. Updating the panel did not work on any server before 1.4.14, and this
release is what fixes it — so this is the last update you will have to start by hand.**

The fixes below came from installing a server from scratch and using the panel the way a new
buyer does, plus a code audit of everything that walk could not reach. The panel-update fix
that makes this release matter is further down, under *From the first 1.4.14 build*.

- **Restoring a backup could write outside the project.** The step that copies your files
  back checked the file it was about to write, but not the folders leading to it. A project
  whose own website code had replaced one of those folders with a shortcut to somewhere else
  on the server — which the website's own user is allowed to do — had its restore follow that
  shortcut and write there instead. Each entry's whole path is now checked, and one that
  leads through a shortcut is skipped by name while the rest of the restore continues.
- **Turning on Cloudflare could replace a working HTTPS certificate.** When a project's
  addresses had been secured at different times, the check for "is there already a good
  certificate here?" looked at only the first address, so it decided the existing
  certificate did not cover the rest and swapped in a self-signed one — and then removed the
  real certificate that did cover them. On a zone set to Full (strict) that is an error page
  for every visitor and every phone. The check now asks about all the addresses at once.
- **A deleted project could lose its restore window.** You get 7 days to change your mind
  after deleting a project. If the clean-up that finally removes the data hit a problem —
  a database that was down for a moment, say — the panel put the deletion marker back with
  *today's* date instead of the day you deleted it. So the countdown started again on data
  that was already being removed, and the next sweep left it alone for another week.
- **A customer website installed from a private repository could never be updated.** The
  access token you type when installing it was not kept, so "Get the latest code",
  rollback and automatic deploys had no way to read the repository afterwards and failed
  every time. The token is now stored the same way the admin app's already was. If you hit
  this, install the website once more with your token and updates will work from then on.
- **Automatic deploys were refused on projects where they would have worked.** The check
  that decides whether a push can deploy asked the repository *without* your stored token,
  so a private repository always looked unreachable and the panel told you to set up a
  deploy key you did not need.
- **A shop could be given the panel's own web address.** One of the two screens that accept
  a project address did not check for that. nginx then serves the panel at your shop's
  address, the shop is unreachable, and every screen reports it healthy. Both screens now
  refuse it and say what to do.
- **Turning Cloudflare protection on could write no firewall rules at all.** If Cloudflare
  refused the first attempt, the retry that would have fitted the rules into the space
  available crashed instead — including the rule that keeps payment callbacks working.
- **"Update the server's operating system" showed you the wrong preview.** With "full
  upgrade" ticked, the list you approved — and the before/after lists in the job's own
  report — described the *plain* upgrade. Package **removals**, which only a full upgrade
  performs, appeared nowhere. The preview now simulates exactly what the run will do.
- **An operating-system update could restart nginx onto a configuration it rejects**,
  leaving every site on the server down. The config is now tested first, and a reload is
  preferred so no request is dropped.
- **The panel's own "Get HTTPS" could report your domain as unpointed** moments after
  creating its DNS record, because it asked the server's local cache instead of the
  domain's own nameservers.
- **Bringing an existing project here wrote its uploads through a symlink** if one had been
  planted at the uploads path, which could put files outside the project's own folder.
- **A project could be made to turn one of the server's own private files into its
  own.** A project's code runs as its own account and owns its folder, so it could put a
  shortcut where its settings file belongs, pointing at a file elsewhere on the server.
  The next deploy followed that shortcut: it read the other file, wrote its contents into
  the project's settings, and then handed ownership of the result to the project. Every
  write of a project's settings file now refuses a shortcut and says so, and the step that
  creates the file removes one that is in the way instead of following it.
- **The login lockout never engaged for most visitors.** Wrong passwords and wrong 2FA
  codes were counted under one form of the caller's address and looked for under another, so
  the count never reached the limit and the 30-minute lock never tripped. On most servers
  that meant unlimited guesses at the login screen. Nothing else about the lock changes.
- **A project could run a program of its own choosing as the server's administrator.** The
  panel already blocks the settings a code checkout can use to make `git` run a program —
  but the block only matched lower-case spellings, and one capital letter walked straight
  past it. Now matched regardless of case.
- **Three more places where a project could redirect one of the server's own writes.** A
  shortcut left where the panel writes its status file, clears a log, or archives one made
  those writes land on a different file. All three now refuse a shortcut.
- **"Update the panel" inside the weekly maintenance window was never actually watched.** It
  was recorded as successful the moment it started, so a failed update was reported as a
  clean maintenance run.
- **A database import's warning about its own safety pause went missing.** If the pause on
  the queue and scheduler expired while a long import was still running — the case worth
  telling you about, because the app may then have written to a half-imported database —
  the panel crashed while writing that note instead of recording it.

### From the first 1.4.14 build (13 September)

**This is the fix that makes 1.4.14 the one to take.** Updating the panel did not work on
any server, and this release is what fixes it — so this is the last update you will have to
start by hand.

- **"Update this panel" failed on every server, every time.** Not intermittently, and not
  only from the button: the weekly maintenance window and the command line hit the same
  fault. What made it confusing is where it stopped. The new version was already
  unpacked onto the disk before the failure, so afterwards your panel reported
  *"SixPanel 1.4.14 is installed on this server, but 1.4.13 is still the one running.
  Your last update is not finished yet"* — and it was right. The files were there; the
  step that finishes the job was not reached, so the panel kept running the old version.
  Every following week the scheduled attempt failed at exactly the same place and left a
  red line in Activity.
  If you have been restarting the panel by hand to finish an update, that is why, and
  you can stop after this one.
- **A server with nothing on it showed a project you never created**, named after the
  machine — something like `srv1959329.hstgr.cloud`, sitting at "not installed, 3 steps
  left", with no way to remove it. Your hosting provider gives the server a throwaway
  hostname, and the panel was mistaking that for a real shop address you had set up. It
  now recognises the machine's own name for what it is, in either of the two forms it
  can take, so a fresh server correctly shows no projects until you make one. A real
  domain is still treated as real — nothing changes for a shop that is already running.
- **The Projects link is always in the left menu now.** It used to disappear on a server
  with no projects yet, and during first-time setup — the two moments you need it, since
  "Create a new project" lives behind it.

### And then the whole panel was audited, defect by defect

The fixes above came from real servers. These came from reading the code against every
way it could go wrong. Each one is something a server could already have hit.

- **"Get the latest code" could fail for ever on one project, with no way to tell why.**
  If a code update was ever interrupted at exactly the wrong moment — a reboot, a killed
  process — git leaves a lock file behind and nothing removed it. Every later update on
  that project then failed at the same step, permanently, while reporting that it had
  found the new code. Measured on one of our own servers: a lock five days old, no
  process holding it, five days of failed updates. The panel now clears a lock no live
  process can be holding, and says so in the job log.
- **"Force deploy (discard local changes)" destroyed those changes and then did not
  deploy.** It threw an internal error immediately after discarding them, so the update
  never ran. It failed this way every time there was actually something to discard —
  which is the only reason to use that button.
- **Deleting a project could take a DIFFERENT project's website offline.** The cleanup
  matched site files by name fragment, so deleting a project called `shop` also removed
  the files of one called `my-shop`. The victim's site went dark at the next reload and
  nothing named it.
- **A rejected web-server configuration could take every site on the server down.** When
  a reload failed, the panel escalated to a full restart without first checking whether
  the configuration was valid — and a restart onto an invalid one leaves nothing serving,
  including the panel that would explain it. It now tests first, and leaves the server
  running exactly as it was if the configuration is bad.
- **Cloudflare security rules could all silently fail to apply.** When Cloudflare refused
  the request for want of free rule slots, the retry that trims the request to fit hit an
  internal error — so a zone with free slots ended up with NO rules written, including the
  payment-callback exemption that keeps a firewall rule from eating a gateway callback.
- **Restoring a project brought it back with a dead storefront.** Restore started the
  queue and the scheduler but never re-enabled live order updates or the customer website,
  so a restored shop answered 502 on its storefront — on a job whose every step read ok.
- **`sixpanel block clear <address>` unblocked EVERY address** when the panel service was
  down, while reporting that only the one address had changed.
- **The Performance page could report memory settings the database was not using.** Two
  fixes: pressing Apply wrote back old fixed ceilings instead of the values calculated for
  your machine, and deleting the tuning file (which the file itself tells you how to do)
  left the page reporting the tuned buffer pool while the database ran the much smaller
  default.
- **A fresh install could stop right after installing Node.js, naming no reason.** A
  routine check on a file that is normally absent was treated as a fatal error.

### The rest of that audit, finished

Every remaining finding from the same review, each confirmed against the running code
before it was touched.

- **Restoring files could write outside the project.** The guard that removes a symlink
  standing in the destination's place covered single files but not folders — and folders
  under `storage/` are exactly the ones your shop's own code can create and rename. A shop
  could arrange for a restore to write its snapshot into a system directory instead. Fixed
  for both, and the folder copy no longer follows a link planted deeper in the tree either.
- **Installing from a repository that keeps its `.env` in git deleted that file from the
  repository.** The install commit was made in the moment between unpacking the code and
  writing the new `.env`, so git recorded the file as removed and pushed that.
- **The panel could be told to serve a shop on its own web address.** Nothing checked the
  shop hostname against the panel's, and the panel wins that collision — so the shop was
  unreachable at its own address while every screen called it healthy. It is now refused,
  the way the panel already refused it the other way around.
- **"All files match" could be reported about a check that ran out of time.** The
  dependency check gets under a second for tens of thousands of files, so on a busy server
  it often does not finish — and it said everything matched anyway. It now says how much it
  actually compared.
- **The first-run timezone step could move the server clock under a shop that already had
  orders in it.** It decided the server was empty from a panel setting alone, which a
  restored or hand-installed shop never sets. It now looks at the disk, like every other
  screen does. Moving the clock shifts every order time and report boundary.
- **A schedule of "every second" was accepted for backup verification** — each tick a full
  restore test, back to back, which would starve your real backups. Five fields only now,
  like the backup schedule beside it.
- **Moving a whole server carried across projects you had deleted** and brought them back
  running on the new machine.
- **A backup verification that failed to finish could leave a deleted project looking
  live** — recreated at every reboot and never cleaned up again.
- **Turning websockets off left their web address serving an error** instead of removing
  it, and the Services page showed the feature as half-on for ever.
- **Deleting a project left its "live order updates off" choice behind**, so the next
  project reusing that name inherited a setting its owner never chose.
- **The sign-in form could clear itself while you were typing** — if your session expired
  with the panel open, a background check reset the form every minute.
- **Two smaller ones:** a Spanish verdict headline named the wrong cause (a stopped service
  was reported as "Domain does not point here"), and the light/dark button kept its old
  language until the next page change.
- **Command line:** `sixpanel db info` on a server with no project reported an empty
  database that does not exist, instead of saying there is no project yet. Twelve commands
  shared that fault; all twelve are fixed.


### 1.4.13 — 2026-09-13

**Take this one if you install from a git repository, or if you add a second address to a
project.** Both of those had faults that left a shop unreachable while every screen in the
panel reported it healthy — and one of them could put your repository's template credentials
back over the live ones your shop runs on.

### And then found by asking whether it all still works once the shop is LIVE

The install succeeding is not the end of the flow. These were found afterwards, on a
shop that was serving perfectly.

- **A shop installed from a private git repository could never be updated again.** Not
  "failed sometimes" — never. The panel deliberately does not write your access token
  into the code folder's git settings, and nothing else kept it, so every later read of
  your repository had no way to sign in:
  - **Get the latest code** could not fetch, and the "what changed?" preview would not
    open at all;
  - **automatic deploys** could never work — a push from your forge carries no
    credential and there is nobody to ask for one;
  - **roll back** could not fetch either, for the admin app or the website.
  The token you gave at install is now kept for the project (on the server only, never
  sent to a browser) and used by all of those. A project deleted takes its token with
  it. An SSH deploy key was never affected — that credential lives in the code folder.
- **Bringing a shop you already run onto this server, from a git repository, left it
  with no history.** The "a shop that already runs" path did none of the repository
  work the fresh-install path does, so the code arrived with a brand-new one-commit
  history instead of yours, and the same three buttons above had nothing to compare
  against. Both paths now share one piece of code, so they cannot drift apart again.
- **The commit the installer makes could not be pushed on a token repository**, and the
  message then told you to give write access to a deploy key that does not exist on
  that kind of connection.
- **A malformed access token is now refused with a clear message** instead of being
  treated as "no token given" and reported as a repository problem.

### Found by installing this release from scratch, the way you do

Everything in this section was found by wiping a server and taking it from the install
command through to a live shop — not by reading code. Each one is on the path every new
buyer walks.

- **A project named "Demo Shop" could not be opened at all.** Any project whose short name
  starts with `demo` — `demo`, `demo-shop`, `demo-store` — showed the **login form** on every
  one of its pages, on a panel you were already signed in to. Signing in again returned to
  the same screen. The panel has a sign-in link for sharing a read-only demo (`#demo` on the
  end of your panel address), and the check for it was loose enough to match the address of
  any page belonging to a project with that name.
- **Installing from a private git repository left the code with no history.** The install
  cloned your repository correctly and then, because the follow-up read of the repository had
  no access token to use, silently gave up and kept a brand-new one-commit history instead of
  yours. Everything looked finished — every step green — but "Get the latest code", rollback
  and deploy-on-push had nothing to compare against, permanently. The same step also failed
  to push the commit it makes for the changes the installer writes, and then blamed a deploy
  key on a repository you had authenticated to with a token.
- **On a server that had ever hosted a project, a re-install left PHP switched off.** PHP
  refuses to start with no site configured, and the panel parks the server's default
  configuration as soon as your first project gets its own. Re-installing after removing that
  project — what you do when a first attempt went wrong — left neither, so the install printed
  "SixPanel is running" while nothing PHP could serve. It now puts the default configuration
  back and confirms PHP is up again.
- **A restart during a job could stop the job dead.** If the panel restarted while it was
  working — an update, or a restart you triggered — the two processes could collide writing
  the panel's own settings file, and the job that was writing it crashed outright. Seen on a
  certificate renewal: the renewal simply stopped, with all four of its steps unstarted.
- **The first-run wizard's timezone step could stop PHP on a brand-new server** — the one
  screen every buyer walks through. Fixed here too.

### The reasons to take it today

- **"Force reinstall" threw away the credentials it had just promised to keep.** The step
  listed your `.env`, the vendor route file and the other files it protects — and then
  reverted every tracked file in the checkout, that list included, *before* the step that
  saves them ran. Measured on a real project: afterwards the database password was the
  repository's template, the app key was gone, and the shop came back on the repository's
  credentials rather than its own. Each unexpected file is now reverted by name, and the
  cleanup is limited to the files it actually listed.
- **An install wrote your `.env` into the checkout's history.** The app key, the database
  password and the payment and websocket secrets — 157 lines of them — went into a commit the
  panel made. Nothing pushed it, because the deploy key it uses is read-only by construction,
  but a backup or a copy of that folder would have carried your secrets out of the server.
  6ammart's own `.gitignore` does not list a plain `.env`, so nothing was protecting it. Now
  three separate things keep it out, including for a `git add` you type yourself later, and a
  repository that *already* tracks an `.env` has it taken out of the index rather than
  committed over.
- **Deleting a project left things behind that cost money or leaked.** A live Cloudflare API
  token in two places; a gzipped copy of the entire shop database, which then rode into every
  later backup; the project's scheduled commands, still armed and still firing every minute
  against a service the delete had removed; and the deploy key, file baseline and self-repair
  history, all of which the *next* project to take that name inherited. Delete now removes its
  remaining panel-side state as a named step, and frees held uploads immediately instead of
  waiting out their expiry.
- **Removing an address could delete a DNS record pointing at a different machine.** The guard
  that limits the deletion to records aimed at *this* server did nothing when the server's own
  address could not be looked up — the check simply did not run. It now refuses rather than
  proceeds.
- **The public half of a deploy key could be deleted, and the panel then minted a second
  key.** The in-use refusal only recognised the private half by name, so deleting
  `…_ed25519.pub` was permitted, the card then showed no key at all, and the next use created
  another one — the duplicate-key fault this store had already been fixed for once, arriving
  from the other end. "Not found" is now a refusal instead of permission.

### Installing from a git repository is a conversation now

The git side of **Install 6ammart Admin** used to be a form you filled in blind and pressed
Install on. Now: you paste the repository address, the panel says which of the two protocols
that is and what it needs, offers to create the deploy key when the repository is private,
tests the connection while you watch, and reads the branch list off the repository instead of
asking you to remember it.

- **The address you type is the admin panel's address.** It used to ask for a base domain and
  invent four names from it, so typing `shop.example.com` produced an admin panel at
  `dash-shop.example.com` — a name nobody asked for, and not the one you hand your staff. What
  you type is what the admin panel answers on. The storefront and websocket addresses are
  added afterwards on **Domain & SSL**, which is where they were always going to be. One
  transformation is still *offered*: a name two levels below your domain cannot be covered by
  Cloudflare's free certificate, so the screen says so and shows the spelling that works,
  with a button — it never silently rewrites what you typed.
- **The branch is read from the repository, and it is the real default.** The old code took the
  first branch in alphabetical order and called it the default, so a repository whose default
  is `develop` with an `alpha` branch present pre-filled `alpha`.
- **A git install keeps your repository's history.** A project deployed seconds earlier
  reported "353 updates behind". It was not behind: the install had created a brand-new,
  unrelated history, so every comparison it made was against a past it did not share. It now
  fetches your branch and moves onto it without touching a single installed file.
- **And what the install rewrote is committed.** The installer edits files your repository
  tracks, so without this the checkout sits permanently modified — which is exactly what the
  deploy-on-push guard refuses on the next delivery. Committed on the server, never pushed.
- **The deploy key is named for where it lives** — `sixpanel-<project>-<server address>`
  rather than just "sixpanel", so a forge listing several servers' keys tells you which is
  which.
- **Six more faults in the key store, each of which could lose a key you had already
  registered with your forge.** Generating a key deleted the old one *first*, so any failure
  after that point — a full disk is enough — left the slot empty with the working key gone.
  A single-project install's key read as unused, so the page offered to delete it. One
  repository setting could make the whole keys page fail to load, which also meant no key on
  the server could be deleted. And the button that opens your forge's deploy-key settings
  built a wrong address for repository names containing a dot, for browser-style URLs, and for
  addresses carrying an SSH port.
- **Generating a key or testing a connection no longer stalls.** A prompt from the key tool
  could wait for ever and hold up every other job behind it; and each key generation spent
  about twenty seconds looking up the server's public address on a server with no outbound
  access. Both are bounded now — 13 milliseconds and 2 seconds respectively, in the bad cases.
- **Restarting the panel no longer throws away a zip you had already uploaded.**
- **Testing the connection after creating a storefront key used the admin key.** So it
  authenticated with the wrong one and created a second key in the wrong slot.
- **The install commit no longer stages the deletion of 6ammart's uploads placeholder** — the
  file whose absence is what later lets your shop's entire uploads folder be committed by
  accident.
- **Re-running an install no longer destroys a local branch of the same name**, and the
  install's own commit message no longer states a secrets policy that the code had stopped
  implementing.

### Domains and HTTPS

- **Adding an address now sets it up.** This is the one to read twice. Adding a name on
  **Domain & SSL** created the registry entry and the web-server file and then *read* DNS to
  report whether the name pointed here — it never created the record, so a name on a domain
  this panel's own Cloudflare token manages sat "not pointed" with "Get free SSL" greyed out,
  while the dialog promised records and HTTPS were automatic. The add now runs the same
  point-and-secure chain the "Fix everything automatically" button runs.
- **And that chain no longer dies on the first name from a different domain.** With two
  domains in play, one name being refused abandoned the certificates for the names that *had*
  been set up. Names are now grouped per domain and applied one call each, so a domain your
  token cannot see is that group's problem instead of the whole run's.
- **The dialog asks where the domain lives — on this page too.** The install wizard has asked
  properly for a while: type a name and, before you press anything, the panel tells you which
  of three situations you are in and offers the matching next step. The page where you add a
  project's second, third and fourth address was a bare text box that said nothing, so a name
  whose domain the panel cannot touch was accepted in silence and sat unpointed for ever. It
  is the same flow on both screens now, not a second copy of it. Typing a name and pressing
  Enter within a second no longer skips the check either — the answer is waited for.
- **Changing which address is the main one makes your shop answer on it.** Everything the
  panel owns was already correct — the settings file, the web-server file, the certificate —
  but 6ammart binds its pages to the address baked into its own cache, so the shop answered
  404 on the new address, permanently. The repair for exactly this had existed for weeks and
  was wired to only one of the five routes that can change the address. All of them now run
  it, and the screen can watch it finish.
- **Removing an address can take its Cloudflare record with it, and the dialog says what
  happens either way.** The old wording said the name "stays yours at your domain provider",
  which is true and hides the part that matters: the record stayed in Cloudflare, still
  pointing at this server, with nothing behind it. There is now a tick box — offered only when
  the panel can actually do it, off by default, and limited to the one record for that exact
  name that points at this server. The outcome is reported rather than left to guess at.
- **Removing a secured extra name now warns you that the certificate still lists it.** On its
  own that is untidy. Combined with removing the DNS record it is an outage on a timer:
  renewal has to prove every name on the certificate, so the whole certificate stops renewing
  and the names you kept go insecure about sixty days later with nothing saying why. The
  warning names the certificate and tells you to press "Get SSL"; the panel does not silently
  re-issue, because issuing has a weekly limit that a tidy-up session can burn through.
- **A certificate is matched by the names it covers, not by its name.** A project that had
  been through several name changes had four certificates for one address; the panel handed
  the web server the one that sorted last, which covered a single name while the site served
  two — so the second answered 404 with the panel reporting it secured. It now picks one that
  covers every name requested, and updates that certificate in place instead of forking
  another sibling.
- **A server with no IPv6 route no longer fails a certificate that is working.** The final
  check dialled Cloudflare's IPv6 addresses, both failed instantly for want of a route, and
  those two errors were the entire verdict — the IPv4 addresses never got a turn. So the last
  step of a first install failed and sent the owner to go hunting a Cloudflare and firewall
  problem that did not exist, on a site that answered normally seconds later.

### The first screen after a fresh install

- **The timezone step no longer stops PHP.** A brand-new server has no project yet, and PHP
  refuses to start with no site configured — so the first-run wizard's "apply timezone" step
  took PHP down and needed a command typed by hand to bring it back. That is the one screen
  every buyer walks through. It now un-parks the default configuration first, the way the rest
  of the panel already does.

### The projects page

- **Each card names the app it runs and the release it is** — read out of the application's own
  code rather than from a settings file, which on the plain CodeCanyon download reports the
  wrong number. Where the two disagree, both are shown.
- **The card's name opens the project**, so middle-click and "copy link" work, and the action
  at the foot says where it goes instead of reading as one more row.
- **Two cards to a row, by decision.** The grid fitted as many as the window allowed, so at a
  common laptop width you got three squeezed cards whose contents then broke onto extra
  lines. One column narrow, exactly two from a wide window, never three. A project with
  nothing set up yet is no longer stretched to the height of the finished card beside it, and
  on a phone the rows wrap only where they have to.
- **`rename…` was painted in the same alarm colour as `delete…`.** Only the destructive one is
  red now.
- **Deleting a project for the 7-day grace period no longer deletes its scheduled commands.**
  They are switched off — visibly, one click from running again — because a restore promises
  the project back exactly as it was. Disarming still happens immediately, which is what
  stops the failing runs. A full delete still removes them.

### The live log

- **It opens when you ask for it.** Every job start raised the log panel over the lower half of
  whatever page you were reading — including the step list you were watching. The log still
  streams and fills; only the panel is now shown on request.
- **And "View log" opens it.** Making the panel on-demand meant nine buttons whose entire
  purpose is to show the log stopped showing it: the click ran, the job streamed, the panel
  stayed hidden, so the button did nothing you could see. Activity's "View log", the deploy
  history's, and the "watch the running job" control on seven pages.


### 1.4.12 — 2026-09-11

**Take this one now — it closes two ways in that a plain CodeCanyon shop was reachable from
the internet, and stops your backups quietly leaving out your sellers' photos.**

### Fixed again in a later build the same day

Everything in this section is a fault in an *earlier build of this same release*, found by
re-reviewing that build's own changes rather than by waiting for a report. If you installed
earlier today, these are the reasons to update again.

- **The confirmation before a command that wipes your database could still be skipped.** The
  earlier build fixed one way past it and introduced another: putting `--step`, `--realpath`
  or `--pretend` before the command name made the check miss it entirely, so
  `artisan --pretend migrate:rollback` — which people type precisely *because* they believe
  it is a dry run — dropped tables with no prompt. The check no longer tries to work out
  which word is the command; it refuses if any word in the line names a destroying command,
  so no arrangement of options can walk past it. `database:refresh`, which wipes the
  database *and* deletes uploaded files, was also missing and is now included.
- **And a shorter spelling of the same command skipped that confirmation entirely.** Artisan
  lets you abbreviate a command and lets you leave a part of it out altogether, so
  `artisan :wipe` runs `db:wipe` and `artisan :fresh` runs `migrate:fresh` — dropping every
  table. Typed that way, no prompt appeared. This is the fifth time this one check has been
  wrong in a day, and every time the cause was the same: it was written around the spellings
  somebody imagined being typed. It is now derived from the rule your own copy of Laravel
  uses to resolve a command name, and a test compares the two across 686 spellings of every
  destroying command and fails if they ever disagree — so the next spelling is a build
  failure here rather than a lost database on your server.
- **Swap could stop surviving a reboot on a server that already had a swap entry.** If your
  `/etc/fstab` mentioned something like `/swapfile2` or `/swapfileOLD`, the installer thought
  its own entry was already there and wrote nothing, so the swap it had just created worked
  until the next restart and then quietly vanished — on the smallest servers, which are the
  ones that need it most.
- **A permissions change from the file manager could still hand out your database password.**
  The earlier build stopped that for a directory that shares a credential file's name, and in
  doing so looked at one thing and changed another; if the two differed at that instant, a
  real `.env` could come out readable by anyone with an account on the server. Both steps now
  happen on the same file, so nothing can be substituted in between.
- **An update could hang instead of failing.** The check that makes sure the panel's own
  dependencies are loadable got a time limit in the earlier build, and the limit did not
  hold: a leftover background process could keep the check waiting for ever, with the panel
  mid-update. It now gives up on schedule and says what happened, and it no longer throws
  away a good answer that arrived just as the clock ran out.
- **"PHP is enabled but not serving" was reported when nothing had changed.** Starting PHP
  for shops that were already running, on a server where the web server then refused to
  reload, told you your shops were left half-applied. Nothing had moved; the message now
  says so.
- **Updating the panel could still leave it unable to start.** The earlier build's safety
  check asked the running panel whether its own dependencies were loadable — and a program
  that has already loaded something keeps answering yes after the files are gone. So the
  check passed on a broken install and restarted the panel anyway. It now asks a fresh
  process, which is what a restart actually creates.
- **After a web-server restart the panel told you "no request was dropped" when they had
  been.** The reassurance was reading a value that had moved, so every outcome reported as
  the gentle one. A restart that interrupted visitors now says so.
- **Stopping PHP for several shops at once only stopped one of them** and reported success
  for the rest, and whether the whole server's PHP went down depended on the order the shops
  were named in. Each named shop is now handled on its own.
- **A recursive permission change could still expose your CodeCanyon purchase code**, which
  6amMart keeps in a settings file the panel deliberately locks down. That file is now left
  alone like your other credentials.
- **A third place that writes a database dump was still leaving it readable** by any account
  on the server — the copy taken when you migrate a shop from another server.
- **A failed PHP reload could restart a shop you had deliberately stopped.** When stopping
  PHP for several shops at once, if the reload failed the panel put back every named
  shop's PHP — including one you had switched off earlier — while reporting that nothing
  had changed. It now puts back only what that command itself stopped, and says so plainly
  if it cannot.
- **Two more from the same review:** a folder whose name looked like a settings file could
  be made unreadable by a permissions change (it is now left alone, since a folder needs
  its traversal bit), and an update could abort naming a package that does not exist,
  because a harmless warning from Node was being read as the name of a missing one.
- **And a fourth way: capital letters.** Artisan does not care about case either, so
  `MIGRATE:FRESH` and `MIG:FRE` both ran and both slipped past the check. It now matches
  the way your shop's framework does, in any case. Worth naming the command this protects
  most: `database:refresh` wipes the database *and* deletes your uploaded files, and it has
  no confirmation of its own at all — this check is the only one it can ever have.
- **The confirmation before a database-wiping command could still be skipped, a third way.**
  Artisan lets you shorten a command name — `mig:fre` runs `migrate:fresh`, `db:w` runs
  `db:wipe` — and the check was looking for the full names, so a shortened one went
  through with no prompt and dropped every table. It now understands shortened names the
  same way your shop's framework does. Typing a shortened name of a *harmless* command
  (`ca:cl`, `rou:lis`, `db:s`) is unaffected.
- **On a server not set to UTC, none of the panel's automatic repairs could run.** The panel
  reads how long each service has been up from the system, and the system prints that time
  with a local zone name — `IST`, `CEST` and most others — which the panel could not
  understand. It read "no start time at all", decided every service was too new to touch, and
  every automatic repair silently did nothing: the scheduler restart, the queue restart, the
  Redis restart, the certificate reload. The SixPreflight report had the same blind spot and
  showed every service as never started. Servers on UTC were unaffected, which is why this
  survived testing. Times are now read in a form that has no timezone in it.
- **A recursive permission change did not repair a file that was already exposed** — it left
  it as it found it, and on the server we checked one Passport signing key had already been
  widened this way. It is now put back to owner-only. The same protection was also missing
  when you change permissions on a single file rather than a folder.
- **The installer could report that it had cleaned up a stale swap entry when it had not**,
  if the entry had a slightly different name.
- **An install could still start on a server with no room left.** A completely full disk
  reports "0 bytes free", which the new check read as "cannot tell" and allowed. A full disk
  now refuses, which was the entire point of adding the check.

### Security — the reason to take this one today

- **Two addresses on an untouched CodeCanyon shop were answering the internet, and one of them
  could hand over your server's own hosting credentials.** 6amMart's own code ships two pages
  that ask for no login: one fetches any web address you give it and shows you the result, and
  one empties your shop's caches. Both were already blocked here — but only at their exact
  spelling. Add a single slash on the end and the block was stepped over, because your shop
  treats `/that-page` and `/that-page/` as the same page while the web server treats them as
  two different ones. Measured from outside a real shop before the fix: the plain address was
  refused, the same address with a slash reached the application. The dangerous half is the
  first page — pointed at your hosting provider's internal address, it returns the keys to
  your own server. Both spellings are refused now, and addresses that merely begin with the
  same letters (a `/testimonials` page, say) still work normally. **Our own optimised code
  never had either page**, so this only affected shops running the plain CodeCanyon download —
  which is most of them.
- **Two panel addresses meant for the server itself were answering anyone who knew your
  panel's web address.** One confirmed a panel was there; the other made your server email you
  "a service has failed", for any service name the caller typed. Both now tell a request
  forwarded from outside apart from a program running on the box.

### Your backups were leaving out your sellers' and staff photos

- **Every backup and every restore was silently dropping one folder of uploads.** 6amMart
  keeps seller and employee profile photos in a folder named `vendor`, and the backup was told
  to skip anything by that name — a rule meant for a folder of program libraries that is not
  in the backup at all. So the rule protected nothing and quietly removed real photos. Nothing
  reported it: the backup said it had succeeded, and the gap only showed up if you ever
  restored. Checked on a live server, it was hitting all three shops on it. Fixed — and the
  check that exists to catch this class of mistake could not see it before, which is fixed too.

### Fixed

- **Updating the panel could leave it unable to start, with nothing telling you.** If the
  package download failed part-way through an update — a brief network problem is enough — the
  update carried on and restarted the panel into a state where it could not load. Your shop
  kept serving customers throughout, so nothing looked wrong from outside; you simply lost the
  panel, with no email about it, and getting it back needed a command over SSH. The update now
  confirms the panel can still load before it restarts anything, and stops with instructions if
  it cannot, leaving the panel running the version it was already on.
- **One shop's database backup could be read by another shop on the same server.** Ad-hoc
  "back up now" downloads and the per-shop dumps taken for scheduled backups were written so
  that any account on the server could open them — on a server with more than one shop, that
  included the other shops. They are now readable only by the server's administrator.
- **Stopping one shop's PHP stopped it for every shop.** From the command line,
  `--project <shop> service stop php` stopped the shared PHP service, taking down every other
  shop on the server from a command naming one. It now stops only that shop's own share,
  exactly as the panel's Services page already did, and refuses when it is the last one left,
  because PHP cannot run with none.
- **A command that wipes your database could run without asking you to confirm.**
  `sixpanel artisan migrate:fresh` asks you to type the command name first — but putting any
  option before it (`--force`, for instance) walked straight past that question and dropped
  every table. `migrate:refresh`, which destroys just as much, was not on the list at all. Both
  fixed. Your shop's framework does not ask on its own here, on either version of the code, so
  this confirmation is the only one there is.
- **"Change permissions on everything in this folder" could expose your passwords.** Your
  shop's settings file holds its database password and its login-signing keys sit beside it; a
  recursive permission change from the file manager was widening both along with everything
  else. Those files now keep their own permissions. On the server we checked, one of those keys
  had already been widened this way.
- **The panel's own scheduled-task repair never ran.** The panel is meant to notice a shop's
  per-minute scheduler wedging and restart it. The switch was on and the repair could not fire,
  because of how the scheduler's clock was being read — so timed jobs (subscriptions, payouts,
  cleanups) getting stuck would have been reported to you and never repaired.
- **Installing on a server with too little disk failed halfway with a confusing error.** The
  installer now checks free space first and says what is needed — 6 GB minimum, 12 GB
  comfortable — and the requirements list you check before buying a server now includes it.
- **The address printed at the end of a fresh install could be one that never loads.** When the
  installer could not look up your server's public address it printed the server's internal one
  instead, which works from nowhere but the server itself. It now asks more than one source,
  refuses to print an internal address as though it were public, and tells you to run
  `sixpanel info` when it genuinely cannot tell.
- **Re-running the installer after a failed install was refused.** The instructions say a
  re-run is how you resume, and the installer's own fresh-server check then treated the
  half-finished install as a conflicting panel and stopped. It recognises its own work now.
- **A swapfile that could not be created still got written into the boot configuration**,
  leaving every boot afterwards reporting a failed item for a file that was never there.
- **`sixpanel prune` reported success for a shop that does not exist.** A mistyped shop name
  cleaned the server-wide files, skipped the shop's own log, and said it had finished.
- **A deleted shop's temporary folder could end up belonging to a shop created later**, because
  the system reuses account numbers. It is removed with the rest of the shop now.

**Also in this release, from earlier the same day:**

**Take this one if you ever invite someone to help on your server, and for a panel that
loads faster on a slow connection.**

### Privacy

- **A temporary login no longer sees your CodeCanyon identity.** When you invite someone for
  a day, the activation page was showing them your Envato username, the address your licence
  is registered to, and the username saved in your shop's own settings file. Your purchase
  code was never shown to them and still is not — but the username is half of what the
  licence server checks, so it belongs with the rest of your account details. They still see
  whether the shop is activated and which part is waiting, because that is the difference
  between "this is broken" and "the owner needs to finish something", and a helper chasing a
  fault that does not exist wastes your time as well as theirs. The activation form itself is
  now hidden from them with a line saying it is yours to complete — before, it was on screen
  and every attempt to use it was refused.

### Speed

- **The panel no longer writes its own code to disk on the way to your browser.** The panel's
  interface is one large file, and nginx was holding it in a 32 KB buffer — too small, so
  every visitor on a slower connection made the server write the whole thing into a temporary
  file and read it back before sending it. It now goes straight through. The difference is
  largest exactly where it hurt most: a phone on mobile data, or the panel opened from far
  away. Nothing changes for your shop's own pages, which were measured and were never
  affected.

### Housekeeping

- Two checks that were written and never wired into the release suite now run with it, so
  they cannot go quiet again.

**Take this one if you installed an update earlier today.** It fixes something one of those
earlier builds broke, and a rescue command that could not do the one job it exists for.

### Fixed in an earlier build from the same day

- **"Turn on two-factor" showed an error instead of the QR code.** An earlier build the same
  day started asking for your panel password before setting up an authenticator, which is
  right — but the button on
  the Security page was never given a password box to ask with, so it failed every time.
  That button is the only way to turn 2FA on if you chose "not now" when the panel first
  asked, so for those servers the feature was unreachable. The page now asks for your
  password the same way the "reset two-factor" form beside it always has. If your server
  forces 2FA at first login, that screen was never affected.

### Fixed

- **"No such file or directory" database errors, from two different causes.** Some servers
  were emailing this error now and then, and it reads like your database has moved when it
  has not. Two unrelated things caused it, and both are fixed.
  First, updating the server restarted the database without first pausing the two background
  workers that keep your shop running. Those workers hold a database connection open, so
  restarting underneath them made their next query fail, and the server mailed you about it.
  They are now paused for the few seconds the restart takes and started again straight
  afterwards — only the ones that were actually running, so a worker you deliberately
  switched off stays off.
  Second, the location of your database's socket was written down in the panel rather than
  read from the database itself. On the servers this product installs those are the same
  place, so nothing was broken — but a future system that arranges its files differently
  would have turned that into the same error permanently, on every page. The panel now asks
  the database where it is listening, records it in your shop's settings, and re-checks it on
  every deploy. Restoring a backup taken on a *different* server now corrects those settings
  too, instead of leaving your shop pointed at the machine the backup came from.
  Server ▸ Health gained a row for this, so if it ever does go wrong the page names the
  problem instead of leaving you with the error text.
- **`sixpanel unlock <address>` could not clear the lock that hides the panel.** There are
  two separate locks: one for too many wrong passwords, and a 30-minute one for too many
  wrong entry codes — the second makes the whole panel answer "not found", login page
  included. Unlock cleared the first and silently missed the second, because the two were
  filing the same visitor under two different spellings of their address. It told you the
  address was unlocked, and you stayed locked out with nothing left to try. Both locks now
  answer to the address you type. Addresses already locked are covered; you do not need to
  do anything special.
- **The server page now says when this box is running more shops than its memory supports.**
  Each shop's PHP pool is held at a four-worker minimum, because a smaller pool cannot serve
  a shop at all — and on a small server that minimum quietly overrules the memory budget.
  The Server ▸ Health row already warned about storefront and queue memory; it now includes
  the PHP pools, which are the larger number, and says how much over the box is. Nothing
  changes on a server with room: every box of 4 GB or more reports zero.
  **The install itself now says it too.** The warning had existed only on that page, so an
  install on a 1–2 GB server scrolled past looking perfectly clean and the owner could only
  find out later, by opening a page they had no reason to open. It now prints one line while
  installing, with the same numbers.
- **New: Server ▸ Services — the web server, PHP, the database and each shop's cache, with a
  Restart button and their live logs.** These are the programs the whole machine shares, and
  the panel had no page for them: when the database was down, the health row told you to
  "start the db service on the Services tab" and that tab only listed one shop's own
  programs, so the instruction could not be carried out. The page that instruction meant now
  exists, and the health rows point at it. There is deliberately **no Stop** for the shared
  programs — stopping one takes every shop on the server down until somebody comes back —
  and each shop's cache is its own row, so restarting one leaves the others alone.
- **Restarting the web server no longer reports a failure for something that worked.** The
  panel is served through the same web server you were restarting, so the reply never reached
  your browser: you saw an error, the restart had in fact succeeded, and every visitor on the
  site at that moment lost their page. It is now a graceful reload — settings are re-read
  without dropping a single request, including your own — and the configuration is checked
  first, so a bad one is reported instead of taking the site down.

**Take this one if you have ever blocked an IPv6 address, or if you run more than one
shop on the server.** Two of the fixes are things that looked like they were working: a
block that quietly let the address straight through, and one address on your shop's own
website that listed every project on the box to anyone who asked.

### Security

- **Fixed: blocking an IPv6 address often did nothing at all.** The same address can be
  written several correct ways — `2001:db8::1` and its long form are one address — and the
  panel was comparing the *spelling* rather than the address. So a block only worked if the
  address you typed was written exactly the way your visitor's happened to be. Everything
  looked right: you got a confirmation, the address appeared on the Blocked addresses list
  with your note and the date, and the visitor kept getting in. This is why it is worth
  acting on rather than waiting: the failure was invisible in the one direction that
  matters. Any address you typed in a form your provider or an abuse report gave you — the
  long form is what those usually print — is now blocked whichever way it is written.
  Addresses already on your list start working with this release; you do not need to
  re-enter them. IPv4 blocking was never affected.
- **Fixed: one address on your shop's website listed every project on the server.** The
  page this panel uses to hand a report over to SixPreflight is deliberately open — it has
  to be — but it was also being treated as belonging to a particular shop. On a server
  where every shop has its own name, that combination made it answer with the names of all
  of them, to anyone on the internet, with no login and no valid token. It also meant the
  hand-off itself never worked on those servers. Both are fixed by the same change.
- **Fixed: a demo viewer could read your licence details.** Every other page holding
  credentials was already hidden from demo mode; this one had been missed.

### Reliability

- **Your licence check no longer assumes the best.** When the panel reads your shop's code
  to see whether it locks the admin panel without an activated licence, it used to treat
  anything it did not recognise as "no lock". It now says it does not recognise the check
  and treats the shop as locked — so an unusual copy of 6amMart cannot end in a dark admin
  panel while the panel reports nothing wrong.
- **Turning on the slow query log now turns itself off.** It had no off switch and nothing
  pruning it, so on a busy shop it grew until it filled the disk. It now expires 24 hours
  after you enable it.
- **Adding or removing a database index can no longer hold up your shop.** Each one now
  gives up after ten seconds if something else is holding the table, instead of queueing
  behind it.
- **Going back to the safe database settings really goes back to them.** The panel prints
  an instruction for undoing its tuning, and following it used to leave your database with
  about a ninth of the memory it should have — one setting was missing from the fallback.
- **A big or crowded project folder no longer makes the panel briefly stop answering**
  while it checks that folder for changes.
- **The server page now names each unfinished package** instead of reporting a count that
  could include a blank.
- **The deploy page accepts the same domain names the rest of the panel does.** It was
  slightly more permissive, so it could accept a name the server then refused.
- **`sixpanel migrate-side` typed by hand now explains itself** rather than half-running.
  It is the far side of a server-to-server move, driven by your other SixPanel.

**Take this one if you host more than one shop, or if your shop runs plain CodeCanyon
code. It closes three ways a break-in through one shop's website could have reached the
rest of the server — two of them present in 6amMart itself, not in this panel.**

### Security — the reason to take this one today

- **Fixed: two addresses your shop's own code opens to the public.** Untouched 6amMart
  registers two web addresses that need no login, and this panel was publishing them along
  with the rest of your shop:
  - one fetched **any** web address a caller asked for and handed back the result. On a
    cloud server that includes the addresses only the server itself can reach — the ones
    that hand out its access keys. Anyone on the internet could have used your shop as the
    messenger.
  - the other cleared your shop's speed caches on request. One visit undid the tuning this
    panel does for you, and nothing rebuilt it until your next deploy.

  Both are now refused by the web server before your shop ever sees them. Your own code is
  untouched — nothing is patched, so a 6amMart update cannot undo this — and no address
  your shop actually uses is affected. If you run the optimised build, these two were
  already removed from it and nothing changes for you.
- **Fixed: activating your licence could change a file outside your shop.** When the panel
  tightened permissions on the activation file after activating, it followed a shortcut if
  one had been put in that file's place — so a break-in through the website could have
  aimed it at a file belonging to the server itself, or to another shop on the same box.
  The panel now refuses a shortcut there and tells you it found one, which is worth acting
  on: nothing the panel does creates one.

### Everything else

- No behaviour changes. Every gate this release adds is a test, not a switch: the two
  refused addresses, the activation-file check, and the checks that keep them from
  drifting apart across the two kinds of project this panel runs.

**A security release, and the panel now finishes the plain CodeCanyon install itself.
Take this one if you host more than one shop on a server.**

### Security — the reason to take this one today

- **Fixed: a shop's own code could take ownership of directories outside it.** When the
  panel sets file ownership after a deploy, a restore or an upload, it hands a folder
  name to the system as the administrator. A specially named shortcut planted inside
  your shop's folder — by a vulnerable plugin, a compromised admin login, or a
  neighbouring shop on a multi-shop box — could redirect that onto a directory
  elsewhere on the server. Every one of those paths is now opened step by step and
  followed by handle rather than by name, so a shortcut swapped in halfway through
  cannot move the target. Two guards added earlier in this line checked one folder
  level too few; both check the whole path now.
- **Fixed: the panel's own update left code that runs as the administrator owned by an
  ordinary account.** After a self-update, files the server executes with full
  privileges could be left owned by the account that unpacked them. They are now
  re-owned before anything runs.
- **Fixed: two file-upload ownership checks compared a value to itself**, so they
  passed whatever they were given. They now check what they were written to check.
- **Fixed: a git setting was appended as the administrator through a shortcut a shop
  could plant.**
- **Updated a dependency with a published advisory** (`qs`, GHSA-x5fp-wj9c-mxmx).

### The plain CodeCanyon install finishes on its own

- **New: the panel completes the 6amMart installer for you.** Installing untouched
  CodeCanyon code used to leave you at 6amMart's own browser setup wizard — the path
  most buyers are on. The panel now drives that step itself and hands you a shop that
  is ready to sign in to.
- **New: a chapter on activation.** If every admin page bounces you back to an
  activation form, that is 6amMart checking its licence with its author, not a broken
  install. The manual now has a page on it, and the panel completes the check where it
  can and says plainly when a build does not carry one.
- **New: an Activity page.** One list of everything that has happened on this server,
  so "who changed that?" and "did the backup run?" have the same answer in the same
  place.

### Your shop stays fast, and the panel stops guessing

- **Fixed: the panel recommended the wrong cache setting on plain CodeCanyon code.**
  The App .env page advised switching cache to `failover`. On our optimised build that
  means Redis first and files second, which is right. On untouched CodeCanyon code —
  which does not define that setting itself — the same word resolves to *database
  first*, the exact round trip the advice exists to remove. Measured on one server, one
  endpoint: 53 database queries per request on the database-led setting against 6 on
  Redis, and 73-77 ms against 27-30 ms. The page now recommends `redis` on such a shop,
  and lists `failover` among the settings it warns about there.
- **Fixed: deleting a project and then pressing "finish setting up" rebuilt its
  services behind the panel's back.** A deleted project keeps its data for seven days
  so you can restore it, but its cache server, its PHP workers and its background
  workers should stop. Pressing the repair button on a deleted project brought them
  back — and because the panel sizes the server by the projects it is serving, those
  workers were then outside every budget it calculates. That button now points you at
  Restore instead.
- **Faster: the health sweep no longer stalls the panel on a busy server.** The check
  that decides whether a shop's settings can be cached ran twice per project per sweep
  with no cache — about three seconds of the panel's only thread. It now runs off to
  one side, so pages stay responsive while the sweep runs, and a sweep that runs out of
  time shows you the rows it did finish instead of an empty page and a false alert.
- **Faster: several pages stopped repeating work.** The Resources page ran two full
  disk walks of every project where one would do; the error report re-read the log on
  every tick; the Cloudflare zone lookup re-asked for every zone on every call; and
  every page waited on a third round trip that nothing depended on.
- **Fixed: a scheduled job that was merely slow got a second copy started on top of
  it**, and a worker that escaped its process group outran its deadline twelvefold.
  Both are bounded now.
- **Fixed: an unreadable panel settings file was overwritten in the same boot** rather
  than kept for you to recover.
- **Fixed: removing one row from the backup page made a raw internal dump reachable.**

### Smaller things

- The restore dialog no longer aims at a project the server had to invent.
- Attaching files and then saving the address no longer throws the files away.
- "We could not read your nameservers" no longer reads as "you are not on Cloudflare".
- A red "server may be overloaded" banner no longer also says nothing needs your
  attention.
- A project with nothing set up yet says so once instead of four times.
- Three time strings were English in all seven languages; three locales had dropped the
  one fact with a consequence (changing your password signs out your other sessions),
  and one had dropped every benchmark figure. All are back in every language.

**Bring a shop you already run onto this server, set a new one up in one screen, and
read a panel that says one thing at a time. Plus a security fix — take this release
today if you host more than one shop.**

If your panel showed a higher number than this yesterday, nothing has gone backwards:
the release ladder was renumbered, and everything those builds carried is described in
this entry. Your panel will offer this as an update and install it normally.

### Security — the reason to take this one today

- **Fixed: a shop's own code could take over the whole server.** Your shop's files
  are owned by a limited account, deliberately — so that a break-in through the
  website cannot reach anything else on the box. But the panel runs `git` as the
  administrator when it deploys, checks for local changes, or opens the file
  browser, and git can be told by a *file inside your shop's folder* to run a
  program of its choosing. So anything that could write into that folder — a
  vulnerable plugin, a compromised admin login, one shop on a multi-shop box —
  could have had its program run with full control of the server. Every one of
  the panel's git commands now refuses those instructions, and the ones that
  cannot be made safe are refused outright rather than run. Nothing you do
  changes; this closes a door that should never have been open.
- **Fixed: saving a file in the file browser could change a file it should not.**
  A specially named shortcut inside your code folder could redirect a permission
  change onto a file elsewhere on the server, and a filename containing a line
  break could slip past the check that protects committed code from being
  overwritten.
- **Fixed: a temporary login could bring another shop onto your project.**
  Temporary logins are meant to let a helper run your site, not replace it. Loading
  an uploaded database and settings over your project is now the owner's decision
  only, like the equivalent action from another server already was.
- **Fixed: a certificate could quietly fall back to an untrusted one.** One of the
  SSL paths accepted an email address that looks valid and that Let's Encrypt then
  refuses — including the address SixPanel itself used to suggest. The certificate
  request failed at the last step and the site was left on a self-signed
  certificate, which browsers warn about. That address is now refused up front,
  where you can see it and fix it.

### Bring a shop you already run onto this server

- **New: move a running 6amMart shop here from files.** It used to need SSH access to
  the old server. Now you can upload what you have: the code as a zip **or straight
  from your git repository**, the database as a `.sql` export, and your uploaded
  images. Your orders, customers, settings and product photos come with them.
  Deploys → **Put 6amMart on this project**, and there is a full walkthrough in the
  manual under *Bring your shop here from files*.
- **New: the panel reads your upload before it installs anything.** It tells you
  which 6amMart release the zip holds, and whether it is a brand-new shop or one
  that has been running, and then asks only for the pieces the zip did not already
  contain. If your zip already carries your settings file and your images, you are
  not asked for them. A wrong or partial download is caught before it touches the
  project, instead of six minutes into an install.
- **New: a private git repository can be read two ways.** Either an access token over
  https, or a deploy key this server generates for you that you add to the repository
  as read-only. The panel asks which — public, token, or key — and on the key path
  nothing secret is stored here. If the clone fails, the key is shown right there
  with a link to the page to paste it into.
- **Git is offered for a brand-new project and for one you are moving, and
  recommended for both.** The code comes from your repository, and the step after it
  still asks for your database and your uploaded images — so a migration cannot
  quietly finish as an empty shop.

### Setting up a project is one screen with one question on it

- **Creating a project asks for the name. That is all.** It used to ask seven
  things: a domain, three separate hostnames, a www checkbox, the name, and a
  "Short id" field left open with two paragraphs about folder and database names.
  The panel works all of that out. The short id only appears if your project name
  has no letters it can use.
- **You no longer need the domain first.** Upload the code, and give the address
  while the upload is still going; the install starts when both are ready. The
  wizard asks for it on the same screen rather than sending you to another page, and
  the deploy card, the by-hand install form and the manual all point at that path
  now instead of telling you to add a domain first.
- **The address is set up in one place, and it finishes the job.** When you give the
  web address during setup, the panel registers it, creates the DNS records and gets
  the HTTPS certificates — all on that screen. If the DNS records are not visible
  yet it says so and offers a "Check DNS and get HTTPS" button rather than failing
  twice, slowly.
- **The Deploys page opens on one action instead of six cards.** On a new project it
  showed two "not installed" cards with four buttons between them, two rows about
  automatic deploys for code that did not exist yet, and the old install form fully
  open with seven inputs — under a warning saying that form needed an address
  first. Now: one card, one button. The by-hand form is still there under "Set it up
  by hand (advanced)" if you prefer typing a git URL yourself.
- **A Cloudflare domain you would rather point yourself is a proper choice.** If your
  domain is on Cloudflare but you do not want to hand over an API token, the panel
  shows the exact records to create, you create them, and it takes over from there.
  It always tells you to keep the record **Proxied** (orange) — the panel never asks
  you for a DNS-only record. And when the panel cannot get a certificate for a
  proxied address it falls back to a self-signed one, which means Cloudflare must be
  set to **Full**, not **Full (strict)** — under strict every visitor gets a 526
  error page. That warning, and the "check again" button beside it, are on that
  screen.
- **The wizard called your project a "shop".** It now says project, which is what the
  rest of the panel calls it — and 6amMart is not always a shop.

### Pages that were shouting all at once now say one thing at a time

Every page was opened, photographed and measured — how much you have to read, how far
it scrolls, how many buttons compete to be the one you press.

- **Activity showed the panel talking to itself.** Of the 300 newest entries, 179
  were the panel's own command channel being polled and 29 were logins — so the real
  history (a deploy, a backup, a project deleted) was scattered thinly between them,
  down twenty screens of scrolling. Those polls are no longer recorded at all. This
  also protects your history: the log keeps a fixed number of lines, so the noise was
  pushing genuine events — including refused logins — out of it. The page now opens
  on the newest 40 with everything else one click away, and searching and filtering
  still look through all of them, so nothing is hidden.
- **Health told you eighteen things at once.** Every finding was fully expanded, each
  with its own paragraph and its own "Take me there" button, so the page you open to
  learn what to fix *first* gave you eighteen equal answers. Each finding is now one
  line you can open, with the most serious one already open — and only a real problem
  takes that place, never a purely informational note while an actual failure stays
  shut.
- **Projects had seven main buttons.** "Create a new project" plus a filled "Open" on
  every card. Opening a project is just moving around, so those are quieter now, and
  the sentence about remaining steps no longer repeats under every card.
- **Two buttons on Deploys had the same words on them** — "Get the latest code",
  once for the admin app and once for the website. They now say which is which.
- **The disk breakdown hid the big folders among the tiny ones.** Nineteen of its 44
  rows were 4 KB or 20 KB, on a page whose own verdict was "there is plenty of
  space". Anything under 1 MB is now behind a single line you can open.
- **Backups showed three "do this" buttons at once** — add storage, run a backup,
  test a restore. They are three steps of one sequence, not three choices: with no
  storage there is nothing to run, and with nothing ever run there is nothing to
  test. Only the step you are actually on is highlighted, every button still works,
  and after a backup that *failed* the highlighted step is running one that works
  rather than testing a restore.
- **The Cloudflare address lists are back on the Firewall page.** If you want ports
  80 and 443 reachable only through Cloudflare, you need Cloudflare's own IPv4 and
  IPv6 ranges to paste at your provider. They now show whenever they are useful —
  not only when every address on the server is already behind Cloudflare — with a
  line beside them naming exactly which of your addresses would be cut off if you
  applied the rule as-is (narrowing those two ports for an address that is not
  proxied stops its certificate renewing).

### Pages no longer sit empty while they load

- **Switching a tab showed a blank area until the content arrived.** Opening a page
  from the menu always showed placeholder cards while it loaded, but clicking a tab
  inside a page did not — so Server, Settings, Security and a project's Advanced page
  all went briefly empty on every tab click, with nothing to say the panel was
  working. They now show the same placeholders. Checked across all 20 tabs in the
  panel.
- **Server → Scheduled took several seconds to show anything.** It waited for every
  project to answer before drawing a single thing, and reading a project's schedule
  means starting its app — about a second each, one after another, so the wait grew
  with the number of shops on the server. It now draws the layout as soon as it knows
  your projects, with one card per project, and each card fills in as its own answer
  arrives: something on screen in well under a second instead of a blank page.
  Nothing is asked of the server that was not asked before.

### Fixes across the rest of the panel

- **Fixed: renaming a project's domain left parts of the shop on the old name.**
  Changing the address wrote one setting and not the three others that decide
  where the admin panel answers, whether live order tracking connects, and what
  address the customer website was built with. Depending on your setup that showed
  up as a 404 on every admin page, order tracking that never updated, or a
  storefront warning about the wrong certificate. The rename now repairs all of it
  and tells you what it did.
- **Fixed: an update did not add the settings a new 6amMart release expects.**
  Updating the code ran the database migrations but not the release's own settings
  work, so features the new version added could be quietly missing or
  half-configured. The panel now runs 6amMart's own settings writers — only the
  ones that ADD what is missing, never anything that would touch what your shop
  already has — and says in the log how many rows it added, or plainly that it
  could not.
- **Fixed: a project installed from git was recorded as a zip install.** Its Update
  button would then have asked for a new zip upload for ever, instead of pulling from
  the repository.
- **Fixed: the panel could stop answering while it checked a large upload.** A
  shop's image folder can hold thousands of files, and checking it froze every
  page, for every project on the server, until it finished. It now stays
  responsive throughout.
- **Fixed: deleting a few hundred files at once had the same effect.** The delete
  held everything up for as long as it ran. The panel now asks you to work in
  smaller batches, or on the folder above them, and stays responsive.
- **Fixed: a stuck database import could block every other job on the server.**
  Backups, certificate renewals and deploys queue behind one another by design, and
  an import waiting on a database lock could hold that queue indefinitely with
  nothing in the log to say why. An import that stops making progress is now
  stopped and reported, while a genuinely slow large import is left alone.
- **Fixed: the Resources page could show freed space as still used.** If you
  opened it while a cleanup was running, the old numbers could come back and stay
  for five minutes. It now shows what the disk actually holds.
- **Fixed: on Activity, "Show older" appeared to do nothing.** It fetched the older
  entries correctly and then still showed the same ones, so the screen never changed.
  It now shows what it fetched, and the two similar-sounding buttons are no longer
  offered side by side: "Show all on this page" comes first, and "Show older activity"
  appears once everything already loaded is on screen.
- Also: the uploaded zip is no longer kept inside your shop's folder after an
  install, the space used by an abandoned upload is freed promptly rather than
  waiting on the weekly cleanup, a shop that runs on a bare IP address is no
  longer mistaken for an unconfigured one when you move it here, and one label in
  the new domain field showed its internal name instead of the word "Saving…".

### If you use the panel in a language other than English

- **Fixed: 1705 lines of the panel were still showing you English.** Set the panel
  to German, Indonesian, French, Portuguese, Spanish, Bengali or Arabic and whole
  sections still came up in English — the two-factor setup, the backup wizard's
  storage fields, the security page's explanation of closing your server's IP
  address, most of the screens for bringing a project you already run onto this
  server, and a long tail of buttons and headings throughout. Every one of them now
  reads in the language you chose. What deliberately stays as it is: names like
  Cloudflare, MariaDB, Node.js, PHP and Google Drive, and the handful of words that
  are genuinely the same word in the target language.
- **Fixed: two "everything is fine" messages read as failures.** In Portuguese and
  Indonesian, the line shown when a project's own settings have nothing outstanding
  described a check that had failed and asked you to run it again — so a clean
  result looked like a broken one. Three Spanish messages had been shortened to
  "Todo está bien" for three different things (this project's settings, this
  project's health, the whole server), and a German and a French one had lost the
  half of the sentence that said what had been checked.


### 1.4.11 — 2026-09-01

**A security fix, and a version check before an install. If you run any earlier
version, take this one.**

- **New: SixPanel now checks your 6amMart version before it installs or updates.**
  SixPanel supports **6amMart 4.0 and newer**. Older code is a different application
  underneath — a different Laravel, a different websocket package, and a different set
  of database tables — so the panel now stops and tells you, instead of spending six
  minutes installing something it cannot run properly. Nothing on your server is
  changed when it stops: on a zip upload the check runs on the uploaded file before
  anything is written to your site, and on a git deploy it runs on the pushed code
  before it is merged, so a live shop keeps serving exactly what it was serving.

- **New: your project's card now shows which script and which version it runs** — for
  example "6amMart 4.1" — so you can see at a glance what is on each project.

- **Where the version comes from, and why your admin footer may disagree.** SixPanel
  reads it from your code, in `app/Http/Controllers/InstallController.php`, because that
  is the line 6amMart's own installer writes. It deliberately does **not** trust `.env`:
  a fresh 6amMart download ships an `.env` left over from the previous release, so a
  genuine 4.1 download says `SOFTWARE_VERSION=3.9` in that file — and that is the value
  your 6amMart admin footer shows you. When the two disagree, SixPanel is reading the
  reliable one.

- **Fixed: opening the panel in several tabs after a quiet spell made it slow.** Each
  reader started its own full health sweep — about forty live checks, including a
  scan of your app's files and a PHP start-up — so three tabs meant three of
  everything at once, and each one made the others slower. Every reader now shares
  one sweep. Measured on a two-core server under full load: a sweep that took 11.8
  seconds now takes 4.3.

- **Fixed: on a very busy server the Health tab could come back with no rows at
  all.** The page gives itself ten seconds and answers empty if it runs over, and a
  slow check could push it past that — hiding the very row that would have named the
  problem. Checks now stop waiting while there is still time to draw the page.

- **Fixed: saving the Settings page restarted your background workers.** If your
  server's timezone was stored under an older name, saving that page — even after
  changing only your alert email — was read as a timezone change: it set the system
  clock, rewrote every project's service settings and restarted the queue and
  scheduler. It happened on every save, and repeated for ever. Only a real change of
  clock does anything now.

- **Fixed: a brand-new server showed its maintenance window twice**, once in the
  panel's timezone and once in UTC, saying the same thing.

- **Fixed: the maintenance window's first line now shows when it starts AND when it
  ends**, in your own timezone, instead of only the start.

- **Fixed: the "someone is scanning for your panel" email gave advice that did not
  fit.** It said changing your entry code would achieve nothing — untrue if your
  panel still uses a short code from an older install, where changing it is the one
  worthwhile upgrade. It also offered the login allowlist as a way to stop an address
  reaching your panel, which that feature does not do; the address block, which does,
  is what it names now.

- **Fixed: China's old timezone name mapped to another old name** the panel did not
  recognise, so picking it left the country list unable to offer China's zones.

- **Fixed: your timezone was shown under an old name.** India reads `Asia/Kolkata`,
  not `Asia/Calcutta` — the same zone and the same clock, renamed in 1993. The panel
  displayed whichever spelling its configuration happened to carry, and the country
  list, which knows only current names, then could not offer your country's zones
  beside it. Both places that report the zone now give the current name. Nothing
  about your clock changes.

- **Fixed: the maintenance window was shown in UTC first.** Your server's window is
  stored in UTC, and the card led with that — so an owner in Asia/Kolkata read
  "Sun 03:30 → 03:50 UTC" and had to do the arithmetic to know when their own server
  goes down. Your panel's own timezone leads now, with UTC underneath for when you
  are comparing servers.

- **Fixed: "Panel files unchanged since install" could describe a file that is not
  there.** When one of the panel's compiled files had been deleted and a plain
  JavaScript file left in its place, the row said the plain file "sits beside the
  panel's compiled code" — beside something that was gone. It now says plainly that
  the compiled file was REPLACED, and tells you to treat the server as compromised
  if you did not do it yourself. Both cases were, and remain, a red row.

- **Fixed: a check that was merely slow the first time was reported as a problem.**
  On a two-core server the first health sweep after the panel starts pays costs no
  later sweep pays, so rows like "Cache & queue store (Redis)" and "Storage folder
  writable" said *this check did not finish within its 2 second budget* about
  services that answer in milliseconds. Measured here: four such rows on the first
  sweep, none on the next four. A check that runs late is now given a little longer
  to finish, and only a check that is genuinely stuck is reported — with how long
  it was actually waited for. Nothing was hidden and no budget was widened: a
  service that really is not answering still shows up.

- **Fixed: a row that needed your attention could open by telling you everything
  was fine.** The Home list shows one line per row, and "Panel files unchanged
  since install" led with *240 panel file(s) match the release exactly* while it
  was amber because other files were present that the release did not install. The
  reason now comes first, so the line under an amber row says why it is amber.

- **Changed: the email about a wrong panel address no longer tells you to change
  your entry code.** That email means someone guessed your secret panel address
  wrongly 20 times and was locked out — the outermost gate doing its job, with no
  way to reach even the login page. It now says so, and explains that a panel
  hostname becomes publicly known through the certificate logs every HTTPS site is
  published in, so this happens without you sharing your address with anyone.
  Changing the entry code breaks every bookmark and saved tab you have and stops
  nobody, so it is now suggested only for the one case that warrants it: the code
  itself having been seen somewhere — a chat, a screenshot, a shared shell history.

- **Fixed: a repository address of the form `git@someone@127.0.0.1:repo.git` was
  accepted, and reached this server.** SSH reads the address after the LAST "@";
  the panel checked the part after the first one. So the real destination hid in
  plain sight, the check passed, and git connected to it — proved with a real
  connection to this machine. Anyone who can start a deploy could do it, including
  a temporary login. Addresses are now read exactly the way SSH reads them.

- **Fixed: two private IPv6 ranges were accepted again.** A change in the previous
  release that closed one spelling of a local address opened another — addresses
  beginning `fc00:` and `fe80:` were converted to the wrong form internally and
  passed the check. Both are refused again, and public IPv6 addresses are
  unaffected.

- **Fixed: the saved-address check covered your customer website but not your admin
  app.** The previous release re-checked the stored address for one of the two
  repositories and not the other, so an address stored by an older release was still
  used on every admin update. Both are checked now.

- **Fixed: the stored rule limit for a Cloudflare site now expires after a week.**
  The panel remembers how many firewall rules your site allows so it can stop
  reporting rules that will not fit. If you later upgraded your Cloudflare plan,
  that remembered number kept the page quiet about rules your site could now hold.
  It is re-checked weekly, and immediately whenever a write succeeds or is refused.


### 1.4.10 — 2026-08-31

A security and correctness release. Every repository address the panel accepts is
now read the way the tools that use it read them, and a further set of faults was
found by auditing the panel against itself — each one reproduced on a real server
before it was fixed, and re-tested afterwards. Some of them could be triggered by
somebody who had broken into ONE shop on a shared server, so if you host more than
one shop on a box, this is a release to take.

- **Fixed: every spelling of an address that points at this server is now refused.**
  When you install a shop from git, the panel hands the address you type to `git`,
  which runs with full access to the machine. It checked only that the address
  *looked* like a git URL — so a `file://` address made it copy a folder from the
  server into the shop's own files, and a `http://127.0.0.1:…` address made it fetch
  from a service running only on that machine. The same address can also be written
  many other ways, and each of these was proved with a real connection: an IPv4
  address in IPv6 form (`[::ffff:127.0.0.1]`), a trailing dot (`localhost.`), the
  `git@[…]` form of an IPv6 address, `::127.0.0.1` without the usual prefix, and the
  short and numeric spellings of loopback (`https://127.1/…`, `https://2130706433/…`
  and the hex form). Addresses are now reduced to one canonical form before they are
  checked, by one shared check used everywhere — so a different spelling of the same
  address cannot pass. Local files are refused outright, and so is any address naming
  this server or a private network. Every normal address still works — GitHub, GitLab,
  Bitbucket, your own git server, a custom port, an address with a token in it.

- **Fixed: the check was skipped entirely when updating your website's code.**
  The address you type was only checked on the FIRST deploy of the customer
  website. Every deploy after that skipped it, and the address was saved for later
  automatic deploys too. Now checked every time, and a saved address is
  re-checked before it is used.

- **Fixed: the panel said it had written fewer firewall rules than your site
  allows, for ever.** After a partial write, the row stayed "different from the
  recommendation" on every page load, with no way to clear it — the note
  explaining why was recorded and then immediately overwritten by the panel's own
  read-back. The panel now remembers your site's real rule limit and measures the
  row against the room that exists, so a site configured as well as it can be
  reads as in sync.

- **Fixed: a full rule list was reported as a bot-protection problem.** On a paid
  Cloudflare plan, running out of rule slots produced a message about Super Bot
  Fight Mode refusing your payment callbacks — quoting a Cloudflare sentence that
  says nothing about bots — and sent you to the wrong settings page. Worse, it
  quietly stopped checking that the payment-callback exemption had landed. The
  panel now reads Cloudflare's actual refusal.

- **Fixed: using an access token with an SSH-style repository address killed the
  job.** If your project was set up with a `git@…` address and you later supplied a
  token, the deploy stopped mid-run with no explanation — and where the address had
  been saved earlier, it failed mid-deploy with an alert email rather than a plain
  message. It now tells you a token needs an `https://` address, before the job
  starts, and leaves SSH-key deploys alone.

- **Fixed: refusing your project's saved repository address refused nothing.** The
  panel dropped the address and then fetched from the checkout's own remote, which
  is the same address it had just refused. It now stops and tells you which
  address to replace.

- **Fixed: a health-page sentence could read "this undefined MB box"** when the
  server did not report its memory size. It now says the size could not be read.

- **Fixed: one panel message was still untranslated in all seven languages.** The
  check meant to catch that was only looking at a third of the panel's text.

- **Fixed: a Cloudflare firewall write could fail completely on a paid plan.**
  When Cloudflare declined one part of the rule AND the rule list was full, the
  panel's retry put the declined part back — so nothing was written at all, on a
  site that had room for the rule that protects payment confirmations.

- **Fixed: the panel said it had written more rules than it did.** After a partial
  write it reported the full count and dropped the sentence explaining what was
  short and how to free a slot. It now reports what actually landed, with the
  explanation, and the row no longer shows as permanently out of sync — it says
  the site's rule list is full instead of asking you to fix something you cannot.

- **Fixed: copying or moving files no longer records which files.** The journal
  entry said "copied 2 of 3" and named no path, on every operation including the
  successful ones. Names are back. A bulk failure also produced an unreadable
  wall of text in one disappearing message, and the file list did not refresh when
  some files had landed — both fixed. A selection whose files are simply missing
  now reports "not found" rather than a server error.

- **Fixed: a Cloudflare plan bought through a hosting partner was treated as the
  free plan.** Cloudflare reports a resold plan as `partners_pro` (or
  `partners_business`, `partners_enterprise`), and the panel did not recognise
  those names — so a Pro site got the free plan's protection: one rate limiting
  rule instead of two, a 10-second window instead of a minute, a plain block
  instead of a managed challenge, and no managed WAF or Super Bot Fight Mode at
  all. It happened silently, with nothing on the page saying the protection had
  been reduced. A partner plan now gets exactly what that plan is entitled to. A
  plan name the panel genuinely does not know still falls back to the safe
  free-plan shape, as before, and if Cloudflare ever refuses the stronger rule the
  panel writes the basic one and tells you what Cloudflare said.

- **New: the Health page tells you when your shops are allowed more memory than
  the server has.** Each shop's storefront and queue worker get a memory limit
  sized from this machine. The panel already worked out when those limits add up
  to more than the RAM left over after the database, cache and PHP workers — and
  then did nothing with it. There is now a "Service memory budget" row that says
  so, with the numbers. It is a warning, not an error: these are ceilings, not
  reservations, so nothing is allocated up front and the shops usually run fine.
  What an over-committed server has lost is the safety net — if the shops ever
  peak together, the machine slows down or loses a service instead of one shop
  hitting its own limit. The row names the two real answers (fewer shops, or more
  RAM) and deliberately does not suggest lowering the limits, because they are
  already this server's sized values.

- **Fixed: copying or moving several files told you nothing when one failed.** The
  panel stopped at the first problem and answered with a single message naming no
  file — while some files had already been copied and one folder was left half
  copied. It now attempts every file, then tells you exactly which ones worked and
  which did not, and why. Nothing about a successful copy changes.

- **Fixed: each shop's PHP could see the server's internal service settings.**
  Alongside its own configuration, every shop's PHP was handed the housekeeping
  values the system uses to run PHP itself — including the address of *another*
  shop's PHP socket. Nothing in 6amMart reads any of them, and none of them let a
  shop do anything it could not already do, but they are the server's business,
  not the shop's, so they are no longer passed along.

- **Fixed: a full Cloudflare firewall list left a shop with no rules at all.**
  Cloudflare allows a limited number of firewall rules per site — five on the free
  plan, for the whole site. If your own rules (or another server sharing the site)
  had used most of them, the panel asked for all three of its rules at once,
  Cloudflare refused the lot, and the shop got none. The most valuable of the
  three is the one that lets payment confirmations through, and losing it can mean
  a paid order that never confirms. The panel now writes as many of its rules as
  there is room for, that one first, and tells you how many landed and how to free
  a slot for the rest.

- **Clearer: what still protects your shop when those rules do not fit.** That
  message used to say the scanner paths were "still blocked by nginx". Checked on
  a real server, that was only partly true: three of them are refused outright,
  while others reach the app and get a "not found". It now says which is which,
  so you can judge the risk yourself.

- **Fixed: a value from the server could run code in your browser.** This one
  matters most if you have ever pressed a "Fix this" button on the SixPreflight
  page. The
  SixPreflight page puts a fix's id into the button, reads it back when you press
  it, and used it to build the confirmation text — but the text was inserted into
  the page as markup rather than as words, so anything that looked like markup was
  treated as markup and ran. Proved end to end in a test browser: a crafted id
  executed. It also meant that dialogue never showed a real sentence, on any
  press. It now shows plain text, escaped.

- **Fixed: a second server sharing one Cloudflare site deleted the first
  server's rules.** The panel decides which rules are its own by asking its own
  host list, so another SixPanel server on the same Cloudflare site is invisible
  to it — and it claimed that server's rules as its own and replaced them. The
  other shop lost its payment-callback exemption, its never-cache rule and its
  login rate limit, and the run reported success. Rules that name another server
  are now left alone whatever else the panel thinks.

- **Fixed: the panel could strip a protection off a rule you wrote yourself.**
  When Cloudflare refuses one part of the panel's firewall rule, the panel retries
  without that part — and the retry rewrote EVERY rule in the site, yours
  included. If you had hand-written a rule to let your Shiprocket or Twilio
  webhooks past Super Bot Fight Mode, the panel quietly removed that exemption and
  said "1 of your own rules kept". It now only ever rewrites its own rules. On a
  Free site, where the panel never asks for that part at all, your rule could also
  make any unrelated Cloudflare error report itself as a bot-protection problem
  and send you to the wrong page — that too is fixed.

- **Fixed: restoring a backup could write your settings file outside the shop.**
  If something had left a shortcut where a restored file belongs, the restore
  followed it and wrote the snapshot's contents — database password included —
  wherever it pointed, and reported success while the shop itself got nothing. The
  restore now removes the shortcut and writes the real file.

- **Fixed: a Cloudflare rate-limit page you could never clear.** On a Free plan
  Cloudflare allows one rate-limiting rule, and if your own rule is using it the
  panel correctly leaves it alone — but then reported that Cloudflare had accepted
  its rule and dropped it, which never happened, and left the row as a job that
  could never finish. It now says your rule is using the slot, and where to free
  one if you would rather have the panel's.

- **Also: Terraform and other tools keep their rule references.** When the panel
  has to re-send a Cloudflare rule list, it used to strip the reference names such
  tools use to recognise a rule. The rules survived; their identity did not.

- **Fixed: a break-in on one shop could become control of the whole server.**
  When the panel updates a shop's settings file it writes a temporary file beside
  it first. That temporary name was predictable, and the folder belongs to the
  shop — so code running as that shop could leave a booby-trap there in advance
  and have the panel, which runs as the administrator, write wherever the
  attacker chose, with contents the attacker chose. A routine "Update" or a push
  from your repository was enough to set it off. The panel now creates that file
  in a way the system itself refuses to redirect.

- **Fixed: one shop could read another shop's uploads-in-progress.** Every shop's
  PHP shared one scratch folder, so a shop could list the files another shop was
  in the middle of uploading, and read anything that shop's code wrote there.
  Databases, passwords and settings files were never exposed — this was the
  scratch folder only. Each shop now has its own, readable by nobody else, and it
  is created on a fresh install and on an update alike: PHP does not fall back to
  anywhere else when the folder it is told to use is missing, so a shop that got
  the setting without the folder could not have written a temporary file at all.

- **Fixed: one shop could throw away every shop's compiled code.** Servers keep a
  compiled copy of your PHP so pages do not have to be re-read on every visit.
  That store was shared, and any shop could empty it — for every shop on the
  server — even one whose files it could not read at all. Each emptying makes
  every site on the box slow until the code is compiled again. Shops can no
  longer reach it.

- **Fixed: one file operation could take the panel down.** Copying or renaming a
  file onto a broken shortcut crashed the panel outright, along with whatever it
  was in the middle of — a backup, a deploy, an install — with no error anywhere.
  An ordinary code checkout can contain such a shortcut, so this did not need an
  attacker. Both operations now refuse the shortcut and say so.

- **Fixed: weekly maintenance repeated its backup and skipped the security
  updates.** When the weekly window installed a panel update, the panel restarted
  and picked the window up again — and then took a SECOND full backup, which the
  code specifically set out not to do. If that duplicate failed (likely, since the
  first one had just finished with the same storage), the window stopped there and
  that week's operating-system security updates and reboot never happened. The
  mail said the backup had failed and said nothing about the updates being
  skipped. The resumed window now runs only the steps that were left.

- **Fixed: self-repair could stop for good, while the panel reported it was
  fine.** The once-a-minute checks that restart a stalled queue or a stopped
  scheduler had no time limit. One database query that connected and never
  answered was enough to freeze them permanently — no more checks, ever, until
  the panel was restarted — and the Health page still read "Automatic repairs are
  on and there has been nothing to fix". Every check is now time-limited, and
  that row now fails loudly when the checks have stopped running.

- **Fixed: moving to a new server left the panel open to the internet.** If you
  had restricted panel sign-in to your own IP addresses, that list did not travel
  with a whole-server move: the new server accepted sign-in attempts from
  anywhere, and the move reported success. The blocked-addresses list did travel,
  which is what made this easy to miss. It travels now, and so do the checks that
  are supposed to notice a setting nobody classified.

- **Fixed: the "panel domain" escape hatch did not stay open.** `sixpanel domain
  none` reopens the panel on its IP address when a custom domain breaks. It
  worked, but your "close the IP" preference survived it — so setting the same
  domain again silently closed the IP once more, on a name that had just proved
  unreachable, and the only way back in was SSH. Clearing the domain now clears
  that preference too.

- **Fixed: certificates could be issued for a name Cloudflare cannot secure.**
  Cloudflare's free certificate covers your domain and one level below it. The
  panel checks this for every hostname you type, but the `www.` version it adds
  for you was never checked — so on a shop like `shop.example.com` it quietly put
  `www.shop.example.com` on the certificate, which visitors of that address then
  cannot reach securely while the panel reports SSL as live. It is now checked
  like everything else, and the panel suggests the spelling that does work.

- **Fixed: the same check could be fooled by a capital letter.** The rule that
  decides whether a name is too deep for Cloudflare's free certificate compared
  text without tidying it up first, so a capital letter or a stray dot in the
  domain made it answer "this is fine" about a name that is not. Five of six ways
  of writing the same name got the wrong answer.

- **Fixed: unused certificates were never reported.** The check that asks "is this
  certificate still used by a site?" matched loosely enough that any name
  containing another name counted — and the panel's own naming style guarantees
  that. So an abandoned certificate that keeps failing to renew looked in use and
  kept sending mail, which is exactly the noise that hides a real renewal
  failure.

- **Fixed: a demo login could stall the whole server.** The panel blanks email
  addresses out of what it shows a demo login. That rule got dramatically slower
  as text grew — 2.5 seconds on a large answer, a minute at the largest the panel
  allows — and a visitor could trigger it at will with ordinary requests. On a
  2-core server that is both cores taken from your shops. It is now instant.

- **Fixed: the activity log could fill the disk.** It kept the newest 5,000
  entries, but nothing limited how LONG an entry could be, and part of each entry
  comes from the request — so a few thousand requests could write tens of
  megabytes onto the disk your shops share. Entries are now capped in length as
  well as in number.

- **Fixed: a long-open panel tab made needless requests.** Signing in again in the
  same tab — after a session expired, say — left an extra listener behind each
  time, so a tab that had signed in many times re-checked running jobs once per
  sign-in every time you returned to it.

- **Fixed: one panel answer could tie up a processor core for 13 seconds.** The
  panel blanks credentials out of what it sends back to a demo or temporary
  login. The rule that recognises a credential's NAME was written in a way that
  gets exponentially slower as the text grows: a large answer took 0.9 seconds to
  blank at 50 KB and 13.7 seconds at the size the panel allows. On a 2-core
  server that is a core taken from your shop's PHP and database for as long as it
  runs. The same answer now takes under a millisecond. This is the same problem as
  the job-log blanking fixed below, in the one remaining place that had it — the
  whole blanking path has now been measured end to end.

Corrections to the previous day's release, found by reviewing its own changes.

- **Fixed: a long line in a job log could slow the whole server down.** The panel
  blanks credentials out of every line of every job log — deploys, backups,
  installs. The way that blanking was written in 1.4.9, a single very long line
  (composer and npm both print them) cost seconds of processor time instead of
  milliseconds: 4.7 seconds for one 50 KB line. On a 2-core server that time comes
  straight out of your shop's PHP and database, so a deploy could make the site
  slow while it ran. One 50 KB line now costs 17 milliseconds. Two older rules in
  the same file had the same problem and are fixed with it.

- **Fixed: two credential spellings were still shown in job logs.** `MYSQL_PWD`
  and `SSHPASS` — the names the panel's own database and transfer commands use —
  were not recognised as credentials, so they appeared unblanked in a job log and
  in the alert email for a failed job.

- **Fixed: a temporary login lost two things it is meant to do.** 1.4.9
  tightened what a temporary login may change, and went too far: deploying and
  updating the code, and starting or restarting services, are exactly what a
  helper is invited to do, and both are listed in the manual as things a
  temporary login CAN do. Both work again. Pulling another server's data over
  this one stays refused, as it always has been, and everything 1.4.9 correctly
  locked down — DNS, certificates, domains, scheduled jobs, database migrations —
  stays locked down.

- **Fixed: test results were blanked out of job logs.** The credential blanking
  added in 1.4.9 treated the word "pass" as a credential name, so a line like
  `Tests: 100, pass: 98, fail: 2` was stored as `pass: ****`. Composer and test
  output is now readable again, while `db_pass`, `MYSQL_PWD` and the rest are
  still blanked.

- **Security: two more places could be tricked into writing outside your
  project.** 1.4.9 fixed this for saving a file and missed the same trick in two
  others: creating a zip archive, and an upload that has to cross disks. A
  shortcut left at the target name — something a downloaded theme or module could
  include — sent the content elsewhere on the server. Both now refuse it.

- **Fixed: saving the same file from two tabs at once could lose your work.** The
  new save path in 1.4.9 had the two saves fight over one scratch file: one
  editor's content could be published under the other's, and the second save
  answered an error. Each save now uses its own scratch file, and a failed save no
  longer leaves one behind.

- **Fixed: the "send a test email" refusal named two ports that could never
  work,** and three small corrections with no visible effect: a project-scoping
  rule that did nothing, two refusal messages that had stopped explaining
  themselves (a temporary login trying to create a root-level scheduled job now
  gets told exactly that again), and a comment claiming a check did something it
  did not.


### 1.4.9 — 2026-08-30

- **Security: a folder name could run commands as root.** The weekly clean-up
  reclaims space from PHP's private temporary folder. It built the command it runs
  by pasting that folder's name into it, and a folder name can contain almost any
  character — so anyone with a login on the server, including the limited account
  your shop's PHP runs as, could create a folder whose NAME was a command and have
  the panel run it as root the next time the clean-up went round. Nothing had to be
  clicked: the clean-up runs by itself on Sunday mornings. The folder name is now
  handed to the command as data, and a name that is not one of PHP's own folders is
  skipped rather than used.

- **Security: the file manager could be tricked into writing outside your
  project.** Saving a file writes to a scratch file beside it first, and while the
  file you asked for was checked against your project's folders, that scratch file
  was not. A shortcut left in place at the scratch name — something a downloaded
  theme or module could include — sent your saved content wherever it pointed, and
  left your file replaced by that shortcut, so everything you opened afterwards
  came from somewhere else. The panel now refuses to follow anything already
  sitting at that name and tells you which file to remove.

- **Security: passwords could appear in the alert email for a failed job.** The
  panel blanks credentials out of job logs before it stores or sends them, but it
  only recognised them in CAPITALS. The lower-case and mixed-case spellings — the
  ones in your app's own settings file, the ones Laravel prints when it reports an
  error, the ones the backup tools use — went through unblanked, and the last few
  lines of a failed job are emailed to you. All spellings are now covered, while
  ordinary words like "passed" and "bypass" are still left readable.

- **Security: a temporary login could change things it should not.** A temporary
  login is a helper you invite to look at a problem. It was blocked from a long
  list of actions, but that list had to name each one, so anything added since it
  was written was allowed by default: rewriting your Cloudflare DNS, re-issuing or
  removing a certificate, adding or removing a domain, creating a scheduled job,
  running a database migration, installing code, and stopping services. Reading
  stays open, so a helper can still do the job — everything that changes your
  server is now yours alone.

- **Security: three payment credentials were shown in full.** The App settings page
  masks anything that looks like a password or a key, and reveals one value at a
  time on request so there is a record of it. Three real names slipped past the
  check and were shown in plain text: SSLCommerz's store password, the licence code
  when spelled the American way, and Flutterwave's signing hash.

- **Security: the "send a test email" button could probe your private network.**
  It is meant to dial a mail server, and it checked the address but not the port —
  so it could be pointed at anything else on your network and would hand back
  whatever answered. It now dials mail ports only, and says which ones. Sending
  your real email is unaffected, whatever port your provider uses.

- **Fixed: pages with tabs did not remember which tab you were on.** Opening
  Settings or Security left the address bar naming the page but not the tab, so the
  tab you were reading could not be bookmarked, shared, or returned to by reloading.
  Browsing into a folder under Advanced ▸ Files bounced you back to the first tab
  for the same reason, and a Cloudflare link for a project that had since been
  renamed did the same.

- **Fixed: switching tabs left the previous tab still working.** Each tab refreshes
  its own readings while you look at it, and the tab you left never stopped. Ten
  switches between Health and Firewall left ten sets of refreshes running at once,
  all asking the server for the same things — enough for the panel to start
  refusing its own requests. Only the tab you are on now does any work.

- **Fixed: the Server ▸ Info tab could read "NaN MB".** When a memory or disk
  figure was missing, the panel printed that instead of a dash.

- **Fixed: the Cloudflare page could come up completely empty.** On most sites the
  panel hit an internal error while building the rate limiting row, and because
  that row is built alongside all the others, every one of the 33 settings
  disappeared with it — the page looked blank and "Set this up for me" answered an
  error. The row now also shows the exact limits YOUR plan would get (a free site
  and a Pro site get different numbers), instead of one fixed sentence.

- **Fixed: restoring a backup could overwrite a different shop's database.** The
  check meant to ask "does this database belong to another project on this server?"
  could never actually answer yes. If two projects had somehow ended up naming the
  same database, restoring either one would have written over the other's live
  shop while the log said the import succeeded. Both are now refused, and the
  message names the other project and where to fix it.

- **Fixed: a deploy that failed left your shop's background work stopped.** The
  panel pauses the queue and scheduler while it updates your code and starts them
  again at the end. If any step in between failed — a bad database migration being
  the common one — that last step never ran, so for ten minutes your shop sent no
  order notifications and ran no scheduled task, with nothing saying so. They are
  now always started again, whatever happened.

- **Fixed: an update that stalled could freeze every other job for six hours.** If
  your git host accepted the connection and then went quiet, the panel waited for
  ever — and because it runs one job at a time, the nightly backup and the database
  maintenance queued up behind it. It now gives up on a transfer that has moved
  less than 1 KB/s for a minute, which tells a stalled connection apart from a
  genuinely slow one: a large download that is still making progress is never
  interrupted.

- **Fixed: a half-finished database import was reported as a live shop.** When
  setting up a shop from an untouched CodeCanyon copy, if the database import
  stopped part-way the panel carried on and said "the shop is live" over a shop
  missing tables — and every retry then skipped the database, so the only way out
  was the command line. It now checks the import really finished, against the
  number of tables that code's own file creates, and tells you how to start over if
  it did not.

- **Fixed: you were told the disk was nearly full and never told it was fine
  again.** The "disk critically low" email had no matching all-clear, and worse, it
  blocked a second warning for six hours — so if the disk filled again that
  afternoon, you would not have heard about it.

- **Fixed: a "certificate is working again" email about a certificate that was
  never checked.** The check that notices when a renewed certificate has not been
  picked up was asking the wrong address and could not see anything at all. It now
  asks correctly, and when it cannot get an answer it stays quiet instead of
  sending reassurance it has not earned.

- **Fixed: the websocket status said "nothing is listening" when the service was
  crash-looping.** Those are different problems with different fixes — one is a
  port or firewall, the other is a process that cannot stay up — and the status now
  says which.

- **Fixed: pressing "Apply" on the database indexes, then being told they were
  still missing.** The Health page could keep showing the old count for up to five
  minutes after a successful apply.

- **Faster.** The nightly database index check read your whole database layout
  again after every single index it built — around 86 times over on a first pass.
  It now reads it once. The Health page's copy of that check is cached rather than
  re-read every minute, and the Settings → Performance page no longer measures the
  disk twice per load. On a real shop's 192-table database: 63ms down to 0ms for
  the cached read.

- Also: the `sixpanel domain` command accepted some names the panel then refused;
  the Database page could hang indefinitely on a database that stopped answering
  mid-question; and a server configuration warning listed the same item twice.

- **The "deploy failed" email now tells you what to do about it.** When a deploy
  stops because files were edited on the server, the alert used to say only
  "commit, stash or revert them" — three things the panel does not offer. It now
  gives you the two commands for your project, ready to paste: one to see what
  changed, one to discard it. The manual's copies of those commands were missing
  the project name too, so on a server with more than one project they could not
  run as printed; both are corrected.

- **Fixed: the command the manual gives you for a refused update crashed.** When a
  deploy stops with "local changes present", the manual tells you to run
  `sixpanel exec php git status --short` to see which files were edited. On a
  server running more than one project that command failed with an internal error
  instead — it looked for a user that only exists on single-project servers. It now
  means the project you have selected, tells you to name one if you have not, and
  says plainly when a project has no such service rather than reporting an internal
  bug. It could also have shown you the panel's own files instead of your shop's;
  it now refuses rather than looking in the wrong place.

- **Fixed: the snapshot list could tell you that you have no backups when you do.**
  On a server with both a local and an off-server destination — the pair the panel
  itself recommends — `sixpanel backup list` read the local disk, which is usually
  empty because the real backups go off-server, and printed "the repository is
  initialized but holds no snapshots" without saying which repository it had looked
  at. Measured on three servers whose off-server destination held two complete
  backups each. The listing now reads the destination that actually has backups,
  and naming one with `--target` still wins. Backups themselves were never
  affected, and where new backups get written has not changed.

- **Fixed: turning on "block traffic that skips Cloudflare" made the panel warn you
  about your own server.** After arming that protection, the Health page reported
  one of its own setting files as changed by hand, with advice ending "treat this
  server as compromised" — about a file nobody had touched. Measured on three
  servers: the file's contents were identical on all three and two of them were
  still comparing against the older, switched-off version. The panel now records
  that change like every other change it makes, so the warning means what it says.
  **If you saw that warning about `origin-lock.conf`, this release clears it** —
  and it really does clear: the panel is meant to take your server's current
  settings as the new baseline when an update lands, and the first thing it wrote
  after an update used to stamp the new release onto the OLD readings instead,
  destroying the signal that triggers that baseline and making the wrong reading
  permanent. Nothing on your server was ever wrong. A file you really did edit
  yourself is still reported, both before an update and after it.

- **New: the panel now removes a "config cache" that is quietly switching off your
  live settings.** Some versions of the 6ammart code read a handful of settings —
  the websocket keys your phones use for live order tracking, and on some shops
  the payment credentials — in a way that stops working the instant that cache is
  built. The app reports no error: the admin panel looks perfect while the phones
  receive an empty key and the map never moves. 6ammart's own installer and its
  updater both build that cache, so a shop can end up like this without anybody
  doing anything unusual. The panel already showed it on **Health → Config cache
  safety** and told you which command to run; now it does the repair itself, once
  a minute, and reloads PHP so the change actually takes effect. Nothing is lost —
  the cache is derived from your settings file, and the panel builds it back as
  soon as a future update of your app no longer needs this. It leaves your cache
  alone if it cannot read your app's code to be sure.
- **Fixed: installing the untouched CodeCanyon code could leave the shop serving
  the installer.** After the panel finished 6amMart's own install steps it
  switched the site to its normal pages, but PHP kept running the installer pages
  it had already loaded into memory. The install now rebuilds the caches and
  reloads PHP at that point, so the shop serves its real pages immediately.
- **Fixed: repairing a half-finished install could ignore the admin account you
  asked for.** On a project whose database already had rows — which is exactly
  when you use that repair — the email and password you typed were silently not
  created, and the panel then printed a login address for an account you did not
  have. It now creates the account you asked for, and says plainly when the shop
  also has admins of its own.
- **Fixed: four smaller things on that same install path** — the admin password no
  longer appears in the server's process list while it is being hashed; the login
  page addresses are written the way 6ammart itself reads them (a wrong order here
  could move your admin login or duplicate the setting); a database import that
  fails on its first line now reports the import error instead of a panel error;
  and "N storage entries" counts what the install added rather than everything
  already in the folder.


### 1.4.8 — 2026-08-29

The big one here is for anyone installing the 6amMart code exactly as it comes
from CodeCanyon, which is most people.

- **New: the panel now finishes the 6amMart installer for you, on the untouched
  CodeCanyon code too.** Until now, a fresh install of the code as CodeCanyon
  ships it stopped halfway: the panel put the files in place, set up the database,
  the certificates and the services — and then handed you a browser link and asked
  you to complete 6amMart's own six-step install wizard by hand. If you did not,
  you had a server where every page answered with an error, and nothing said which
  half was missing. The panel now runs those steps itself: it loads the database
  6amMart ships, creates your admin account, sets your business name, unpacks the
  shop's default images, and switches the site out of installer mode. One install,
  nothing left for you to finish. (Our own optimised code was always installed this
  way; this brings the CodeCanyon code up to the same standard. Your CodeCanyon
  purchase code is untouched — the panel drives only the steps that come after it.)
  The built-in manual describes this too: the "Install your 6ammart code" page now
  says what the panel does in place of 6amMart's six-step wizard, instead of warning
  that your copy of the code might not support it.
- **New: "Finish install" repairs a shop that was left half-installed.** If you
  have a project sitting in that state — files on the server, no database, every
  page an error — the Deploys page's Finish install button now completes it instead
  of refusing and pointing you at a browser. The manual covers this as well.
- **Fixed: the certificate list contradicted itself.** `sixpanel ssl status` would
  list a valid Let's Encrypt certificate for your panel's domain and then, three
  lines below, warn that the domain "has no certificate yet" and send you to
  re-issue one — which Let's Encrypt refuses as a duplicate. The warning now asks
  the same question the certificate list answers.
- **Fixed: the panel's port had five separate definitions inside the panel.**
  Nothing was wrong on your server, but two of those five decided different
  things — which port the panel listens on, and which port the web server sends
  visitors to. If they had ever disagreed, the panel would have been running and
  unreachable at the same time. They are now one setting, checked automatically.
  Your panel's port is unchanged, and a new install still picks a random one.

- **Fixed: the restart was missing from the record of the window that performed
  it.** A window that restarts your server wrote its history without the restart
  step in it, so the Maintenance card, the Activity row and the summary email all
  showed one step fewer than actually ran — the very step that took your shop
  offline. The restart itself was always correct; only the record of it was wrong.
  It is now recorded like every other step, together with *why* it restarted, so
  when you read the history later you can tell a restart the operating system asked
  for from one your own "Every window" setting caused.
- **Fixed: the Maintenance card could say "Ready" for a window that was going to
  refuse.** Maintenance takes a full backup before it changes anything, and it
  refuses to start at all when there is nowhere to put one. But the readiness line
  did not ask that question — so a server with no backup destination showed a green
  **Ready** line with a "no backup destination" warning directly underneath it, and
  then quietly refused every window, week after week. The readiness line now asks
  the same question the window does, in the same words.

- **Fixed: on the Maintenance tab, the restart row could say the opposite of the
  setting right below it.** The checkbox read "Restart the server when one is
  needed", and described itself as restarting "only when the operating system says
  a restart is required" — while the **Restarting** dropdown three lines below it
  was set to **Every window**. Both halves of the page were describing real
  behaviour; only one of them was describing *your* server. On the one step in the
  window that takes your shop offline, that is the worst place for the page to
  disagree with itself. The row now says what the step does, and the sentence
  underneath is filled in from the setting you actually chose — so the two can no
  longer drift apart. Your servers restarted exactly as your dropdown said
  throughout; what was wrong was the description, not the behaviour.
- **Fixed: if maintenance could not read your backup destinations, it told you that
  you had none.** Before touching anything, the maintenance window takes a full
  backup, and it refuses to run at all when there is nowhere to put one — the
  message being "no backup destination is set up, so there is nothing to back up
  to". A fault while *reading* your destinations produced that same message, which
  would have sent an owner to the Backups page to add a destination they already
  had. It now says what actually went wrong. No backup was ever skipped or sent to
  the wrong place because of this.
- **The maintenance window's choice of backup destination is now tested, all six
  ways it can pick one.** When a server has several destinations, maintenance picks
  the one you scheduled first, and prefers off-server over local when it has to
  break a tie. That order had never been exercised — it is now, along with what
  happens when a schedule names a destination you have since deleted, and what
  happens to a window that was interrupted by SixPanel updating itself: it does not
  repeat the backup it already took, it puts your own choice of steps back
  afterwards, and a window left mid-flight by a server that was switched off for a
  day is abandoned rather than started at lunchtime.

- **Internal tidy-up, no change you can see.** The check that finds a package your
  system left half-installed was written out three separate times inside SixPanel,
  and two of those copies had already started to differ from each other. Nothing
  behaved wrongly because of it, but a rule written down three times is a rule that
  will eventually disagree with itself — so there is now one copy, and the other two
  ask it. Your server behaves exactly as it did before.

- **The repair is now proven on a real server, not only in tests.** We put a
  server's boot-loader package into exactly the broken state a customer would see —
  the package unfinished, its recorded boot device meaningless, and the system
  refusing to install anything at all — and let the shipped repair fix it: the
  boot-loader was written to the correct disk, the package finished, and installing
  worked again, with the server's shops serving normally throughout.

- **The panel now finishes a package your system left half-installed, instead of
  telling you to.** If a package never finished installing — an interrupted update,
  or a server image that shipped that way — your system's package manager refuses
  to install *anything* until it is dealt with, and says nothing useful about why.
  That one package silently breaks server updates, SixPanel's own updates, and
  every future install on the box. SixPanel now finds it, finishes it, and checks
  afterwards that it really is finished, before it starts any other work. It only
  repairs what it can be sure of; anything else it names for you rather than
  guessing. **Measured on our own server:** a boot-loader package had been left
  unfinished by the server image itself, and every update had been failing on it
  with an error that pointed at the wrong thing entirely.
- **Fixed: the update could fail on a step that had nothing left to do.** It
  checked that three small tools were installed. They already were — but the
  request still failed, because of the half-installed package above, and the
  message blamed the three tools. It now checks what is actually missing before
  asking for anything.
- **The install address is now `installer.allsweb.net/sixpanel/`.** Shorter, and it
  is the address on the website and in the manual from here on. **Nothing on a
  running server changes** — your box keeps updating from whichever address it was
  installed with, and the older addresses (`/native/`, `/sixpanel-native/`) still
  work if you have one saved.

- **Fixed: the maintenance window reported a step as failed when it had worked.**
  The step that updates the panel finishes by restarting the panel — which is also
  what stops the window watching it, so the window recorded "the job disappeared"
  and emailed you a failed summary for an update that had installed correctly. The
  window itself always carried on afterwards; only the report was wrong.
- **Fixed: server updates could fail with an unexplained error, every time.** If
  your server has a package the system never finished installing, the update tool
  refuses to run at all — and the message it prints does not say which package, so
  the panel could only pass it on as "the server command failed". The panel now
  checks for that before it starts, names the packages, and tells you the one
  command that clears them. Nothing is attempted until it is clear.
- **Fixed: two more places that restarted your database without pausing its
  background workers first.** A worker whose database vanishes for a moment stops
  with an error and emails you an alert — for maintenance you asked for yourself.
  It always restarted on its own, so nothing stayed broken; the cost was an alarm
  you had no reason to trust. The auto-tune step and the timezone setting both
  pause them properly now, as updating and restarting already did.
- **SixPreflight's own documentation is no longer readable from your shop's
  address.** Its README and change history were served like any other file. They
  hold no data of yours, but there is no reason for them to be public.

- **A temporary login can no longer turn your scheduled backup off.** Sharing a
  temporary login let the holder change the backup schedule — and saving an empty
  schedule switches backups off altogether, quietly, with nothing about your site
  looking any different until the day you need a backup that was never taken. The
  same login could also start a backup run whenever it liked, which ties up the
  server. Both now belong to you alone. A temporary login can still SEE whether
  your site is being backed up, and when the last one finished, because that is
  part of knowing the site is healthy.
- **Fixed: the health report claimed your server was running old settings when it
  was not.** One of the web-server settings is now sized to your disk, so the value
  on your server correctly differs from the one in the release — and the check that
  compares them read that as "out of date". It said the improvements in this
  release were not switched on, on servers where they were, and the repair it
  offered would have changed nothing and left the warning in place.
- **Fixed: "check this project" pointed at a command that refused to run.** The
  health report ends by naming your other projects and printing the command to see
  each one. On a server with more than one project that command answered "this
  panel's health report has no per-project sections" and did nothing. It works now.
- **Fixed: compressing a file whose name begins with a hyphen.** It was read as an
  instruction rather than a name, and the archive was not written.

- **Fixed: a server address containing an unusual character could confuse the
  copy-a-site tool.** An address or username beginning with a hyphen was read as
  an instruction rather than a name. Only the owner could reach this, and nothing
  was at risk, but it now cannot happen.

- **The fix that stops your panel address being written to the log reaches servers
  that already exist, too.** The panel's own web-server entry is normally rewritten
  only when you change your panel address, so on a server that was already running
  the old file would have stayed and the address gone on being logged. Caught by
  checking the server itself rather than trusting the release. The panel now
  re-writes that file when it starts, exactly as it already did for your shops' own
  files, and reloads the web server only if something actually changed and the new
  configuration is valid. It also refuses to make that change if the result would
  lose your panel address's certificate — a certificate that had expired and been
  tidied away, or was removed, or that a restore left out, must never turn your
  panel address into an unencrypted "not found" — and it says so in its log when it
  decides to leave things alone.

- **A temporary login can no longer see your secret panel address.** The address
  you use to reach the panel is a password, and your web server was writing every
  panel request into its own access log — which a temporary login could read on
  the Logs page. Two things changed: the panel's own requests are no longer logged
  at all, and anything a temporary login reads now has that address removed from
  it first. Nothing about how you reach the panel changes, and the error log,
  which is what diagnoses a fault, still records everything.
- **A temporary login can no longer read your database password.** It was already
  refused the `.env` file. But your site keeps a compiled copy of those same
  settings, under an ordinary name, and that copy was readable. It and the site's
  other compiled caches are now yours alone.
- **A temporary login can no longer pull another server's site over this one.**
  That does the same thing as importing a database, which it was already refused.
- **More things now belong to you alone**, each one already listed as off-limits
  in the manual: clearing the server's logs, the self-healing actions, the
  first-run settings, the licence code, the monitoring key, the SixPreflight
  password, starting phpMyAdmin, the database clean-up, adding or removing
  database indexes, testing a backup, and which Cloudflare account this server
  uses. What a temporary login is FOR is unchanged — deploying, updating, rolling
  back, restarting a service, reading logs and files, and the database pages.
- **Fixed: your shop's background workers could start up in the middle of a move
  or a restore.** Both jobs pause a shop while they copy, and the safety net that
  restarts a paused shop assumed the pause would be short. On a shop with real
  data it is not, so the workers came back while the copy was still running —
  writing orders after the copy had been measured, or starting up against a
  half-restored database. Both now hold for as long as the work takes, and if the
  net does fire, the job says so instead of reporting a clean finish.
- **Fixed: two "Get HTTPS" presses in a row could undo each other.** Asking for a
  certificate on two addresses of the same site, within a minute, left the second
  one recording the first as not secured — and the next time the panel started, it
  stopped serving HTTPS on that address. Each certificate now records only the
  addresses it is actually about.
- **Fixed: a move interrupted by a restart blocked every later move.** If the
  panel restarted while a project was being moved, the panel went on believing
  that move was still running — for ever — and refused every move and every server
  migration after it. Such a move is now recorded honestly as interrupted, with
  the step it had reached.
- **Fixed: a move could finish "successfully" onto a broken server.** If the other
  server could not finish setting the site up, the move noted it and carried on,
  because the copy itself was perfect — so you were told to point your domain at a
  server whose every page was an error. It now stops, with your shop still running
  here and nothing switched over. A move also asks the other server up front
  whether it is new enough, instead of failing halfway.
- **Fixed: scheduled backups could pile up.** If a backup took longer than the gap
  to the next one, each run queued another, and the queue grew until the panel
  appeared to ignore every button. A scheduled backup now sees that one is already
  running and lets it finish — your data is in that run either way.
- **Fixed: maintenance could start in the middle of a move.** The weekly window
  can update the system and restart the server, and it could not see that a
  project was being moved to another server, so it could restart the box mid-copy.
  Each now waits for the other, and the Maintenance page tells you what it is
  waiting for.
- **Fixed: a migration or import could run while a backup was being taken.** The
  guard covered one direction only, so a job already waiting in the queue could
  start in the middle of a database change — and the backup it produced would
  match no version of your site.
- **Fixed: database indexes that failed to build left no trace.** If none of them
  could be built, the Database page still showed the last successful pass. It now
  shows the failure and names them.
- **Fixed: a setting you type by hand in the panel's own settings file is now
  read.** Two ways of writing the same line — both accepted everywhere else — were
  understood by some parts of the panel and ignored by others, and a change made
  from the panel could then add a second line for the same setting.
- **Fixed: the temporary file used while changing your backup password is always
  removed**, even if the panel restarts mid-change.


### 1.4.7 — 2026-08-28

- **A move now checks every table, not a sample.** The check that compares both
  servers before a shop is called moved was looking at eight tables out of roughly
  190. A difference in any other table would have passed unnoticed. It now compares
  all of them, and refuses to report a comparison it could not complete.
- **A move that cannot read one side now says why.** "The database could not be
  counted on both sides" used to hide the actual reason — an unreachable panel, a
  permission problem, a timeout. The reason is now in the log.
- **Fixed: the "same page online" link at the foot of each manual page.** It
  pointed at an address with a version in it, which the site only handled by
  redirecting you to the real page. It now links straight there.
- **Your panel now tells search engines to stay away.** The panel's web address
  contains your private access key, so it should never appear in a search result.
  Every page, file and API response now carries a no-indexing instruction, the
  phpMyAdmin area included. Nothing about how you reach the panel changes.

- **The duplicate move entries already on your server are hidden too.** The
  previous release stopped creating them; this one tidies away the ones that were
  already recorded — without removing older moves that only have that one entry, so
  nothing disappears from your history.

- **Fixed: a completed move was listed twice.** Every successful move appeared
  twice under Recent moves, the second time as an empty entry with no start time
  and no log to open. One entry per move now, carrying what was checked on both
  sides.

- **Fixed two things on the Migration page.** A linked server's name and its
  SixPanel version were printed with no space between them, and the version shown
  could be out of date while looking current — it is the version SixPanel saw the
  last time it checked, so it now appears next to when that was.

- **New: empty a shop's error log from the panel.** Once you have fixed what was
  going wrong, **Logs → App errors → Empty this log** clears the record so the page
  shows only what happens from now on. Your shop, its data and its settings are
  untouched, and new errors are still written as they happen.

- **A migration now checks the other server first.** If the server you are moving
  to runs an older SixPanel than the one you are moving from, you are told so
  before anything is copied — with what to do about it — instead of the migration
  stopping part-way with a technical message. Nothing is copied until that check
  passes.

- **Fixed: linking another server with a password did not work.** SixPanel offered
  a password as a way to link a server, but the tool it needs to use one was not
  installed — so the link was accepted and then failed later, when it was used.
  That tool now ships with SixPanel, including on servers that simply update to
  this release, and a server that somehow lacks it says so straight away instead
  of storing a login it cannot use. This mattered most for moving to a brand-new
  server, where a password is usually the only login you have.

- **New: move everything to a new server.** Give SixPanel a brand-new, empty
  server and its SSH login, and it installs itself there, sends your settings, and
  moves every shop across one at a time — comparing every table's row count and
  every uploaded file before it calls each shop moved. Your DNS is never touched,
  so customers keep reaching the old server until you point the domains yourself,
  and nothing on the old server is deleted: every shop stays there with its data,
  workers stopped, so you can go back at any moment. A shop that fails to move
  does not stop the rest, and the result says "partly done" rather than pretending
  otherwise. The new server keeps its own panel address and password — see
  **Move everything to a new server** in the manual.
- **New: a Migration page in the panel.** Linking another server, moving one
  shop, and moving the whole server are now all on **Migration**, instead of
  being available only from the command line.

- **Fixed: a moved project's uploaded files landed in the wrong place.** The
  images and other uploads arrived on the receiving server one directory too high,
  so the shop would have had none of them. SixPanel noticed by itself — the move
  compares both sides before switching anything over, so it stopped and left the
  project running on the original server. Files now keep their structure, and the
  storefront's own configuration goes to the storefront rather than to the admin
  application.

- **Fixed: the last step of a project move could not load the database.** The
  import connected to the receiving server's database the wrong way and was
  refused by it, so a move got as far as copying every file and then stopped. It
  now connects the same way everything else on the box does. A move that stopped
  there changed nothing: the original server kept its data, and the half-built
  project on the receiving side was removed automatically.

- **A project move now insists on being told which project.** If the project was
  not named — a mistyped field in a script, for instance — the request was taken to
  mean the server's main project. It is now refused instead, and the main project
  is refused by name with the reason: every server already has one, so it can
  never be moved across one project at a time. Nothing was ever at risk of being
  overwritten; a move refuses to write over an existing project either way.

- **Fixed: the second half of a project move could not run at all.** Every step
  that ran on the receiving server — importing the database, counting the rows,
  checking the copied files, repairing ownership, cleaning up after a failure —
  was passed which project it was about, and that value was being dropped before
  it arrived. Each of those steps then stopped with a "usage" message naming the
  very thing it had been given. Nothing was at risk: a move stopped rather than
  doing the wrong thing. Fixed in one place, so all five steps read it the same way.

- **A move that fails now cleans up after itself, so you can just try again.**
  Previously a failure part-way through left a half-built project on the receiving
  server, and because a move refuses to write over an existing project, every
  later attempt for that shop was then refused — with nothing obvious to do about
  it. SixPanel now removes what it created there itself. It only ever removes a
  project it created for that move: one you made on that server, or one with a
  shop installed, is never touched.

- **Fixed: moving a project failed while copying its files.** On a server SixPanel
  reaches as `ubuntu` rather than `root` — which is most cloud images — the copy
  had no permission to write into the receiving project's directory and stopped
  with "Permission denied". It now copies with the same elevation it uses for
  every other command, and then hands the received files back to the project's own
  user, so the shop can read its own uploads. Nothing on the original server was
  affected by the failure: it kept its data and its safety backup.

- **Fixed: moving a project could hang before it started.** The move took a
  safety backup first and then waited for it — but the panel runs one job at a
  time, so the backup was queued behind the move and the move was waiting for the
  backup. Neither could finish. The move now runs alongside the panel's job queue
  instead of inside it, and reports its progress step by step.

- **Linking a server now works when it does not allow root logins.** Most cloud
  images — AWS and Google among them — refuse an SSH login as `root` and give you
  a user like `ubuntu` instead. Give SixPanel that user; it elevates each command
  itself. A server you reach as `root` is unaffected.

- **Link two servers, and move a project between them.** Settings → Server links
  pairs this panel with another SixPanel — you give it the other server's SSH
  details once, and the pairing stays. From then on you can move any project
  across, one at a time, and the projects you do not move keep running exactly
  where they are. Both servers stay live.

  A move copies the project's configuration, its uploaded files and its database,
  and the **other** server creates the project itself, so it gets its own
  database user, its own PHP pool, its own Redis instance and its own ports —
  nothing collides with what is already running there.

  **What it checks before it starts:** that the other server answers, that
  SixPanel is installed on it, that the project name is free there, and that it
  has enough disk space. Any of those failing stops the move before anything is
  copied.

  **What it checks afterwards:** it counts the rows in your database on BOTH
  servers and compares them, and it fingerprints every uploaded file on both
  sides and compares that too. If anything does not match, the move fails, says
  what differed, and your project stays live on this server.

  **A backup is taken first**, on this server, and verified — so there is
  something to come back to.

  **Your domain is not moved and nothing is deleted.** When the move finishes,
  the project is still here with all its data, only its background workers are
  stopped. You point the domain at the other server when you are ready, check the
  shop yourself, and delete the old copy by hand when you are happy. The panel
  never makes that decision for you.

  The full page is **Move a project to another server** in the manual, reachable
  from the Help link on that tab.

- **A backup test that had nothing to test no longer reports a pass.** On a server
  whose app is not installed yet, the weekly test found no database to restore —
  and said *"PASSED"*, which the Server → Health page then reported as *"the whole
  database restored from the backup and read back correctly."* Nothing had been
  restored. Zero databases were loaded and zero rows were counted.

  That row is the one thing that tells you your backups are real before you need
  them, so it now says plainly that there was nothing to prove, and what to do:
  install your app, take a backup, and test again. An amber row, not a green one.

  The Health page also no longer claims *"the whole database"* when the test did
  not record how much it read back. A test that proved nothing was making a
  BOLDER claim than one that proved 190 tables.

  **If your app IS installed, nothing changes** — that path already restored the
  database into a throwaway copy, counted its tables and rows, and failed if they
  were short.

- **`sixpanel block` prints a table again.** It was printing raw JSON, one line
  per blocked address, instead of the Address / Blocked / Reason columns. The
  panel's own Blocked addresses page was never affected.

- The address box on that page was too narrow to show its own example.

- **You can block an address.** Panel → Security → **Blocked addresses** takes one
  address (`203.0.113.5`), a whole range (`203.0.113.0/24`) or one IPv6 address,
  with a note saying why, and shuts it out of the panel completely. The list shows
  every blocked address with the day you blocked it and your reason, and an
  **Unblock** button beside each one.

  It is stronger than the login address list above it in two ways. It takes effect
  **at once**, even on somebody signed in from that address right now — they stop
  being able to reach the panel mid-session. And it covers the **whole panel**
  rather than the login page, so a blocked address cannot even see that the panel
  is there.

  It covers the panel only. Nobody is blocked from your shop or your apps.

  Two things the panel refuses to block: **your own address**, which is named on
  screen so you can see what it is, and **`127.0.0.1`** — the web server in front
  of the panel reaches it over that address, so a rule covering it would refuse
  every visitor to the panel rather than one, you included, on every device.

  From the server, `sudo sixpanel block` shows the list, `sudo sixpanel block
  <address>` adds one, and `sudo sixpanel block clear [<address>]` lets one or all
  of them back in. That last command is why blocking is safe to use at all: the
  block lives in the panel's own settings, so it can always be lifted from the
  server itself, even when the panel is the thing refusing you.

- **Monitoring is now its own card on Home, with a range you choose.** The three
  charts under the meters have become a card of their own, and you can ask for the
  **last hour, six hours or 24 hours** — the panel keeps a full day of history now,
  where it used to keep four.

  Each chart carries a red dashed line at 90%. That is what makes a small chart
  answerable: 40% and 95% look identical on a thin line with nothing to compare
  against, and the question you actually have is "is this close to trouble". The
  number beside each label is where it is right now.

  At the foot of the card, **Per-service usage right now** opens a table of which
  service is using what — the database, the web server, PHP, the panel itself.
  It is read only when you open it, so a closed card costs the server nothing, and
  neither does the longer history: the panel still takes one sample a minute, the
  same as before.

- **The panel's own files are locked down tighter.** Everything in the panel's data
  directory is now readable only by root, including the login history. Nothing
  could read those files before either — the directory itself was already
  closed — but each file's own permissions disagreed with it, and one directory
  setting was the whole protection. This puts both in agreement.

- **You can now choose the panel's port when you install.** The panel never sits
  on 80 or 443 — those serve your shop — so it takes a port of its own, and by
  default the installer picks a random one and prints it at the end. That is the
  safer default: a panel on a predictable port is one every scanner finds.

  But most cloud firewalls are written *before* the server exists — an AWS
  security group, a Google Cloud rule — and a random port means installing first,
  reading the port off the summary, then going back to edit the rule. So you can
  name it:

  ```
  sudo PANEL_PORT=31149 bash install.sh
  ```

  Write it in that order. `PANEL_PORT=31149 sudo bash …` looks equivalent and is
  not: `sudo` clears the environment it is handed, so the installer would never
  see it and would quietly pick a random port instead.

  The installer refuses an unusable port before it changes anything, and says
  which problem it is: below 1024 (reserved, and 80/443 belong to your shop), the
  port this stack uses for live order updates, out of range, or something already
  listening on it.

  **An already-installed server is never moved by this.** If you re-run the
  installer with a different `PANEL_PORT` than the one your panel is on, it keeps
  the port you have and tells you the command that can change it
  (`sudo sixpanel port <number>`), which restarts the panel and re-renders the web
  server together. Moving it silently would break your bookmark and your firewall
  rule in the same second.

- **Fixed: a warning inside the installer could abort the install.** One branch —
  the one that runs when the build does not name a Node.js version — called a
  warning helper that had never been defined. The installer runs with "stop on any
  error" set, and calling something that does not exist counts as an error, so a
  path whose whole purpose was to warn and continue would exit instead.

- **SixPanel is ready to be published for arm64 servers, and can no longer
  install the wrong one.** The panel is shipped as compiled code, which only runs
  on the processor type it was built for. Until now the update service held a
  single build, so there was no way to offer amd64 and arm64 side by side — and,
  more seriously, a server could be handed a correctly-signed build for the wrong
  processor and end up with a panel that could not start.

  Three things changed. The update service now holds one build per processor
  type; your server asks for its own and says which one it asked for. The panel
  refuses a build for another processor before downloading anything, and says so
  plainly — the installer has always done this, the update button had not. And a
  build with no processor recorded is treated as amd64, which every release
  before today was.

  Nothing to do on your side. An amd64 server keeps updating exactly as before.

- **The install page no longer promises arm64 support that is not published
  yet.** Its requirements table said "x86_64, or arm64", which was true of the
  installer and false of the release: an arm64 server was refused. It now names
  x86_64, explains why, lists the common arm64 machine types (AWS Graviton,
  Ampere, Hetzner CAX) and says what to do if you already have one. The
  installer's own refusal also stopped claiming the missing build was "a
  one-command rebuild at our end", which it was not.

- **Your server can now look after itself, once a week, at an hour you pick.**
  Left alone, a server drifts: security updates pile up, SixPanel goes stale, a
  certificate creeps toward expiry, and a restart the operating system asked for
  never happens. Settings ▸ Updates and restart now has a maintenance window —
  Wednesday 02:00 to 02:20 UTC by default, shown in your own timezone as well —
  and when you turn it on, that window does the lot in an order chosen so that a
  failure is always recoverable:

  1. It checks that starting is safe at all: enough free disk, the server not
     already busy, no other job running. If not, it skips the week and emails you
     why. Skipping changes nothing.
  2. It takes a **full backup** — before anything else, every time. If the backup
     does not succeed, the window stops there and your server is untouched. It
     will not even start without somewhere to back up to.
  3. Database care, then any certificate that is due, then SixPanel itself, then
     your operating system's security updates.
  4. A restart, only when the operating system says one is needed — and never
     after a step that failed.

  Every step is the same job you could run by hand, so it appears in Jobs with
  its own log, and Activity says the maintenance window did it rather than
  pretending somebody signed in at 2am. There is a "Run maintenance now" button
  for when you would rather not wait for Wednesday.

- **New: Server ▸ Info — everything you might be asked for, on one page.** Your
  public IPv4 and IPv6 addresses as copy-and-paste fields (the values an A or
  AAAA record needs), the processor and how many cores, memory and swap, which
  Ubuntu or Debian this is, the exact PHP, MariaDB, nginx, Redis and Node.js
  versions, how long the server has been up and how busy it is. One button
  copies all of it as plain text for a support ticket.

  It also tells you two things nothing in SixPanel used to: whether your server
  is **using swap** — memory kept on disk, which makes everything on the box feel
  slow and usually means it is short of RAM — and whether the address the
  internet sees is different from the one configured on the server, which is what
  being behind your provider's NAT looks like and is a common reason a domain
  points at the wrong place.

- **Updating your app no longer logs an error in your app's own log.** While an
  update rebuilds your app's caches, the per-minute scheduler kept starting your
  app anyway — and for a minute or two the file it needs was not there, so your
  own log filled with `routes-v7.php: Failed to open stream` on a shop where
  nothing was wrong. It also made the Scheduler row on the Server page look
  broken, because that row is driven by the scheduler's heartbeat and the failed
  tick never wrote one.

  SixPanel now pauses the queue and scheduler while the app is mid-change and
  starts them again when it is done. Queued jobs are not lost — they wait in the
  queue. And if an update ever fails halfway, those workers are started again on
  their own within ten minutes rather than staying paused.

- **Restarting the database no longer reports its own queue worker as failed.**
  A queue worker whose database goes away exits immediately, so restarting
  MariaDB — from the Services page, or as part of a SixPanel update — took the
  workers down with it and emailed you that a queue worker had FAILED. The
  workers always came back on their own, so nothing was actually broken; the
  problem was the alert, arriving for maintenance you had just done yourself.
  Queue workers are where orders, notifications and payment callbacks are
  processed, so that is the last alert that should ever cry wolf.

  SixPanel now pauses those workers before the database moves and starts them
  again afterwards. Queued jobs are not lost — they wait in the queue and are
  picked up when the worker returns. Stopping the database on purpose still
  leaves the workers stopped, which is what you asked for.

- **A scheduled backup could get stuck and quietly stop everything behind it.**
  If the database dump hit a filesystem error at the wrong moment, the backup
  stayed on "running" for ever instead of failing — and because SixPanel runs
  one job at a time, everything queued behind it never started. On the server
  this was found on, that meant the offsite backup and both nightly
  database-care passes had silently not run, while every page still looked
  healthy.

  Two changes. The dump now always finishes one way or the other, and says why
  if it failed. And any job that stops responding is cleared automatically after
  six hours with an explanation on it, so the queue keeps moving even if
  something new ever gets stuck. Six hours is deliberately long — nothing normal
  comes close, so honest slow work is never cut short.

- **A failed SSL renewal that was not actually a failure.** When two renewal
  runs overlap, one of them is refused by certbot's own lock — it does nothing
  and reports an error. That was being shown as "ssl-renew failed" on servers
  whose certificates were all perfectly current. SixPanel now waits for the
  other run to finish instead of treating "something else is doing this right
  now" as a problem. A real renewal failure is still reported immediately, and
  is never retried.

- **Two health rows pointed at versions that do not exist.** One offered an
  update "from 1.5.23 onwards" and another said a feature "arrived in 1.5.5" —
  version numbers from the Docker edition, not this one. Both rows now describe
  your server and point at the update button.

- **Your database was storing the same thing over and over, and the nightly
  care pass now removes it.** 6amMart saves a copy of the ordered item inside
  every order line, and that copy included the whole "module" record — the
  module's description text and its translations — even though nothing ever
  reads it back. On a real shop with 66,701 orders that was **87 MB of the
  database taken up by 42 distinct blocks of text repeated 113,231 times**:
  16% of everything stored.

  Removing it took that shop's database from **539 MB to 434 MB — 19.5%
  smaller** — and its backup from 42 MB to 36 MB. Nothing was lost: order
  lines still show the item exactly as it was ordered, and the "Database care"
  card tells you how much is waiting to be reclaimed before it runs.

  This runs on any 6amMart install, including a completely stock one from
  CodeCanyon. On stock code the app keeps writing those copies as new orders
  come in, so the nightly pass is what keeps them out — verified on an
  untouched v4.1 install, where the duplicate is 38% of each order line.

  Disk space comes back on the Sunday rebuild, as with everything else the care
  pass removes.

- **A slow money report got faster.** The day-wise earning report was looking
  up every order twice to read one column, on every load. It now reads each
  order once: the earning totals went from **419-487 ms to 252-336 ms**, and
  from **210 ms to 48 ms** when you filter to a single month. The figures it
  reports are identical to the paisa — that was checked before and after, not
  assumed.

- **The panel itself opens faster.** Signing in was asking the server the same
  two questions twice each, and waiting for two independent answers one after
  the other instead of together. Nine requests instead of eleven, and the panel
  appears in about **3.3 s instead of about 3.8 s** on a server behind
  Cloudflare. Where you are in the world affects this more than the server
  does — each request has to cross the internet, so what matters is how many
  there are.


### 1.4.6 — 2026-08-27

- **Ubuntu 26.04 LTS and Debian 13 are now supported, and Ubuntu 26.04 is the
  one to pick for a new server.** The three supported releases install these,
  each from its own distribution's archive, so security patches arrive the same
  way the rest of the system's do:

  | | PHP | MariaDB | nginx | Redis |
  |---|---|---|---|---|
  | Ubuntu 26.04 LTS | 8.5 | 11.8 | 1.28 | 8.0 |
  | Debian 13 | 8.4 | 11.8 | 1.26 | 8.0 |
  | Ubuntu 24.04 LTS | 8.3 | 10.11 | 1.24 | 7.0 |

  Which one is fastest was measured rather than assumed, on identical servers
  with the same 66,701-order shop on each. The honest answer: the differences
  between these stacks are small enough that any of the three is a good choice —
  pick on how long the release is supported, not on speed.
- **Ubuntu 26.04 installs no longer fail on the PHP version Ubuntu itself
  ships.** The installer refused PHP 8.5, so the recommended operating system
  could not be installed at all — it stopped with "PHP 8.5 cannot run 6amMart".
  That was read off a library's declared version range rather than measured;
  running the code proved 6amMart works on 8.5, including the spreadsheet export
  the limit was about. Checked on both the plain CodeCanyon code and the
  optimised build.
- **Debian 12 is no longer supported**, and the installer now says so by name
  and points at Debian 13. Debian 12's security support ended on 11 July 2026,
  and the only PHP in its archive stops getting security fixes on 31 December
  2026 — so a box installed on it would have quietly stopped receiving patches.
- **A fresh install no longer tells its owner the server might be compromised.**
  On the first boot after installing, the panel's file-integrity check reported
  14 of the installer's own files as hand-edited, with the advice "change this
  server's passwords" — the most alarming message the panel can produce, on a
  server nobody had touched yet.
- **The panel no longer names the wrong operating system.** Five places said
  "Ubuntu" to an owner running Debian, in the health report, the disk page and
  three translations.
- Node.js is now one stated version (26.8.1) that the build and the installer
  both read from a single file, instead of each deciding for itself. A
  side-effect of the old arrangement: on a server upgraded across Node major
  versions, `yarn` could go missing while the install still reported success,
  and the failure only surfaced later when deploying the customer website.
- **The customer website can now be installed before you have a certificate.**
  It used to be pointed at `https://` your admin address no matter what, so on
  a shop that had not finished Domain & SSL yet the website could not render a
  single page: every page asks your admin panel for its configuration from the
  server side, and that call was refused because there was no certificate to
  trust. The deploy failed with "the website started but answers HTTP 500" and
  nothing said why. It now uses `http://` while a host has no certificate — which
  is the address that actually works then — and `https://` once it has one.
- **Getting a certificate now rebuilds the website by itself.** The address is
  compiled into the website when it is built, so changing a file afterwards
  changes nothing that runs. Finishing Domain & SSL now schedules the rebuild,
  says in the job log which address moved and why, and skips the rebuild when
  nothing moved.
- The website's own published address (the one in its canonical and share-preview
  tags) follows its OWN certificate, separately from your admin address — so one
  can be secured before the other without either of them advertising a link that
  does not open.
- If the website still answers an error after a deploy, the failure now names
  this cause when it is the cause, instead of only reporting the error code.


### 1.4.5 — 2026-08-26

- The read-only demo no longer names the other websites on your Cloudflare
  site. The check-up row that lists them ("served somewhere else, not by
  this server") was still printing them in full — those are your own other
  addresses, so they are now shortened like everything else.

- Tightened the shortened values in the read-only demo. A very short email
  address or machine name was being shown in full, and a plain machine name
  (no dots) was passed through as it was. Everything that names someone is
  now shortened, however short it already is. `localhost` and names like
  `box.local` are still shown as they are — they are true of every server
  and hide nothing.

- Hidden values in the read-only demo now keep their shape, so a row still
  makes sense. A domain reads `da***.al***.net`, an email
  `ow***@al***.net`, an address `203.*.*.*`, a folder `/home/***` — the
  visitor can see what kind of thing the row is about without learning
  whose it is. Before, all of them were replaced with `*****`, which hid
  the point of the row along with the value.
- Passwords, keys, tokens and the database user are unchanged: those are
  still hidden completely, because half a password is still a password.

- The read-only demo is now stopped at the control it pressed, instead of
  being asked to confirm a change that could never happen. Four places
  opened a confirmation or a whole multi-step wizard first — creating a
  project, adding backup storage, turning automatic backups off, applying
  Cloudflare settings — and only refused at the end. Every confirmation and
  every wizard in the panel now answers a demo visitor straight away with
  the same read-only note.
- A new temporary login's password is labelled "Password" again; it read
  "Demo password".

- A new temporary login is now handed to you as three separate fields —
  the address to open, the username, the password — each with its own Copy
  button. Before, all three sat in one box that only kept a single line, so
  copying it produced one run-together string; pasted into the address bar
  that read as a broken panel ("unauthorized") when nothing was broken. The
  all-in-one-block form is still there, folded away, for pasting into a
  message.
- The language and theme buttons in the header are square again inside a
  project. The project switcher was taking the space they needed, and the
  browser squeezed them into ovals with the icon pressed against both
  edges.
- The read-only demo no longer shows any of this server's addresses. Every
  shop domain, and the panel's own address, is now hidden from it the same
  way passwords, email addresses and file paths already were — the demo
  password is public, so an address is an identity too. Your own login, and
  temporary logins, still see everything as before.
- The "demo" marker in the sidebar is one short word now, with the full
  wording in its tooltip; it used to be wider than the sidebar and wrapped
  under the version number.

- The read-only demo now shows every page in the navigation — nothing is
  tucked away. The Security page answers it with one honest owner-only
  card, pages whose data the demo may not see say so in place of it, and
  the server keeps refusing every write and every secret regardless of
  what is visible.

- Testing a fresh temporary login finally works the way an owner actually
  tries it. The share block's address now carries the username
  (…#u=temp1), and opening it shows the sign-in form with the username
  filled in — even in the browser that is already signed in as you, which
  used to land in your own panel and make every new login look broken.
  Signing in there switches the session; the hint under the block explains
  both that and the private-window way to test side by side.
- When a demo visitor presses any button that would change something, the
  refusal now says, in their own language, that this is demo mode — you can
  look at everything, change nothing. A live battery of 47 checks (every
  mutating request family, every secret-carrying read, every showcase page)
  now proves the read-only demo: all writes refused, all secrets refused,
  all pages readable.
- The theme button shows the sun in light mode again (the one-release flip
  to target-mode icons is reverted), and header icons can no longer be
  clipped at odd browser zoom levels — the icon used to sit on the text
  baseline, which at some zooms pushed its bottom edge under the button's.
- When temporary logins expire, the log line now names them — "temp1
  stopped working" is only diagnosable if the trail says temp1 expired.

- The Cloudflare page no longer lists a ghost project called "localhost" on a
  fresh install. That row was the panel's own hidden default project wearing
  the installer's DOMAIN placeholder as a name; it is now hidden here exactly
  as it is everywhere else, and a placeholder domain can never become a
  project's display name.
- The project switcher draws its own clear chevron — the browser's native
  select arrow was a hairline glyph that all but disappeared inside the pill
  (light, dark and right-to-left languages each get theirs).
- The theme button now shows the mode a click gives you — a moon while the
  panel is light, a sun while it is dark — matching the words in its own
  tooltip. It used to show the mode you were already in, which read as the
  wrong icon.
- The read-only demo's backup page: the custom-schedule storage list now also
  says the demo hides storage destinations, instead of claiming none exist.

- The read-only demo now shows much more of the panel, and never lies about
  what it hides. A demo session can see real job history and the live
  "job running" pill (step error text stays hidden — those lines are raw
  command output); the pages whose data the demo may not see — the activity
  feed, cron entries, backup destinations — now say exactly that in the
  demo's own words instead of a red error or a false "nothing here yet".
  Every write stays refused and every secret stays masked, exactly as before.
- Passwords pasted with a stray trailing space or newline now sign in. A
  password copied out of a terminal, an email or the temporary-login share
  block usually arrives with one, and the login then failed on a value that
  was right. The trimmed form is tried only after the exact one fails — a
  password that genuinely ends in a space still works, and nothing gets
  looser.
- After creating a temporary login, the panel now tells you the one thing
  that makes it look broken when you test it yourself: this browser is
  already signed in as you, so open the address in a private (incognito)
  window to see the login form.

- The Settings page's "Automatic disk cleanup" row no longer says **off** on a
  server where the cleanup is actually on. Never touching the setting means ON
  (every option, Sunday 04:30) — the Disk page and the timer itself have
  always honoured that default, but this one row read the raw saved value and
  showed "off" until the owner saved the setting once. It now asks the same
  module the timer does, so the three places can never disagree again.
- Reverb (the live order tracking websocket) now writes its log to the
  application's own log folder — `storage/logs/reverb.log`, beside Laravel's —
  instead of the system journal. That is where everything already looked for
  it: the panel's Error logs page, SixPreflight's "Where Reverb writes" row,
  and both log rotators cover that file by name. Existing projects pick this
  up on their next panel restart, which re-renders the service definition and
  restarts Reverb onto it.

- The "Database care and speed indexes" health row no longer claims a build
  attempt failed when none did. A panel update can add a new speed-index rule
  during the day, and until the 04:10 nightly pass has run the index is simply
  not there yet — the row used to read that as "the last attempt could not
  build them", blaming a job that did nothing wrong. It now says both
  possibilities honestly, and the Run-now job log names which one it was.

- The two remaining slow first-loads after a panel restart are gone as well. The
  version check used to dial the update service
  inline on the first request after every restart — 1.7 seconds, riding in the
  boot burst of the first sign-in — and now answers instantly ("checking" on a
  server that has never checked, the last verdict otherwise) while one
  background refresh fills the cache; the badge and the Settings page quietly
  re-read a few seconds later. The explicit "Check now" button still waits for
  a live answer, as a pressed button should. And the dashboard overview used
  to pay its cold costs — a CPU sample plus spawning PHP and the database
  client for their version strings — in the first request after a restart
  (measured 1.6 s against 0.5 s warm); the server now pays those once at boot,
  before anyone signs in.

- The panel opens noticeably faster, and never as a blank page. Two causes,
  both measured: the panel-address endpoint made a live call to Cloudflare's
  API on its first request after every restart — 2.3 seconds, sitting on the
  boot path of every sign-in — and now serves its last answer instantly while
  refreshing in the background (the what-is-my-IP lookup got the same
  treatment). And while the panel boots on a slow connection, the screen used
  to be pure white for the whole download; it now shows the SixPanel mark and
  a spinner from the very first paint, with no script involved — so even a
  boot that dies shows motion instead of a void.

- Five refinements to the new busy buttons and notifications, found by an
  adversarial review the same day: a notification being read (pointer on it,
  or keyboard focus on its close button) is never the one evicted when five
  stack up, and it leaves with the same fade as a dismissal; keyboard focus
  now holds a notification open exactly the way hovering does; on phones a
  tap anywhere on a notification dismisses it (tap used to pin it open,
  because a touch "hover" never ends); after a failed login the keyboard
  focus returns to the password field instead of being dropped; and the
  busy-spinner's internal marker was renamed so it can never collide with
  the job system's own button tagging.

- Every button you press now shows that it is working: the moment an action
  disables its button, a small spinner joins the label and stays until the
  panel answers. A grey button used to read as broken; now it reads as busy.
  The Log in button does this too — a click on a slow connection no longer
  feels dead.
- Notifications were redesigned to actually be seen: each one opens with a
  coloured verdict icon (green tick, red cross, amber mark), can be dismissed
  with its own close button, and holds on screen while your pointer is over
  it — an error stays up longer than a success. At most five stack up; the
  oldest makes room.
- The "Panel files unchanged since install" health check no longer raises an
  alarm about the panel's own phpMyAdmin download — over four thousand files
  the panel itself fetched (and checksum-verified) were being reported as
  "present that the release did not install".

- Push-to-deploy no longer refuses a push whose commits were made earlier
  and pushed later (a rebase, or local work pushed after the fact). The
  anti-replay staleness bound now measures when the PUSH happened — the
  forge signs that timestamp — instead of when the commit was written, which
  once made the panel record a perfectly genuine delivery, answer GitHub
  "stale delivery", and deploy nothing. A replayed old delivery still
  carries its original push time, so the protection stands unchanged.

- The utf8mb4 fix button works on its very first press: the first release
  read the list of narrow tables in a shape the database client never
  returns, so the fix widened the database default and then stopped with
  "Table 'undefined' doesn't exist" before converting anything. The fix now
  names each real table, and a new build gate replays the exact wire shape
  the client answers in, so this class of mistake cannot ship again.

- The SixPreflight page can now FIX two findings itself: "Whether emoji and
  every language are safe to store" (the panel converts every still-narrow
  table and column to utf8mb4, re-checking the live schema first) and
  "Modules enabled but not installed" (the ghost entries are switched off in
  modules_statuses.json so the file reflects reality). Each fix is a real job
  with a live log, runs only for the signed-in owner, and says in its last
  line that the reading clears on SixPreflight's next check.
- Alert emails got a design: one clean card — who is talking and which
  server, a coloured verdict line readable from the inbox preview (red =
  needs you, green = resolved, blue = information), the details in readable
  paragraphs, and a footer that says why the email arrived. The same words
  still travel as plain text beside the HTML, and no email ever carries the
  panel's secret address.
- The panel opens in your language when you arrive from the AllsWeb site
  (?hl=<language> on any panel link — the same eight languages both sides
  speak), and every link out to allsweb.com returns you to the site in the
  language you are reading the panel in.
- An uploaded .php file under /storage/app/public/ is now refused outright
  (404) instead of being served as text — the nested vhost rule the `^~`
  prefix always needed. SixPreflight's "upload folder runs PHP files"
  reading turns green on the next check.
- tmp_table_size / max_heap_table_size floor is 128M on servers with 3 GB+
  of RAM: measured on the reference box, 64M spilled a third of all
  temporary tables to disk mid-query with gigabytes free.

- Updates no longer stop on a tree the app itself dirtied: 6amMart's
  translate() appends any missing key to resources/lang/*/messages.php at
  request time, so on a live shop the tracked file drifts modified just from
  pages being viewed, and every later update refused with "local changes
  present". The update now reverts those files before the clean-tree check —
  lossless, because the app re-adds any missing key the next time its page
  renders, while keeping the old copy would clobber the keys a new drop ships.
- The index pack gains order_details (item_id, order_id, quantity, price,
  discount_on_item): the item-wise and store-sales report aggregates become
  index-only instead of paying ~113k row lookups for the summed columns
  (measured on the reference dataset: 610-1,060 ms unstable → ~310 ms stable).

- The Activity page's project filter listed the hidden built-in "default"
  project on servers that never used it; its rows (panel self-updates,
  mostly) now read as server-wide, the way every other page treats it.

- **A new Activity page** (panel menu, next to Backups): everything that
  happened on this server in one stream — every admin action with the
  address it came from, and every job with its status and a "View log"
  button. Filter it every way at once: WHO (a signed-in admin, or the panel
  acting by itself — and the badge says whether that was the schedule, a
  push deploy, self-heal or the CLI), WHICH PROJECT it touched (or
  server-wide), WHAT KIND of thing it was (backups, deploys, domain & SSL,
  database, security…), plus a text search over the details. Filtering
  repaints in place — no page jump, no lost scroll.
- Jobs now record who set them off. New jobs carry their origin (admin /
  schedule / webhook / self-heal / CLI); history from before this release
  shows an honest "—" rather than a guess.

The running-job work, finished the way it feels rather than the way it reads
in code — three reports from real use, three fixes:

- **The page no longer jumps to the top when a job starts or ends.** Press a
  button halfway down a page and the page stays exactly where you are — the
  button under your finger, now quiet, with the running strip beside it.
  Opening a different page still starts at the top, as it should.
- **The end of a job is announced by name, everywhere.** "“backup full →
  Contabo S3” finished ✓" appears wherever you are — another page, another
  tab, scrolled away — and a failure says FAILED in red with a pointer to
  the log. Before this, a finished job changed one small chip and nothing
  else; which action had finished was anyone's guess.
- **The live log now ends with a verdict, not a last line.** The log closes
  with an unmissable "✓ ✓ ✓ THIS JOB FINISHED — every step completed." (or
  the red ✗ version naming failure), and the log panel itself takes the
  verdict's colour along its edge.


### 1.4.4 — 2026-08-25

- **A queued certificate request could quietly undo another one.** Ask for
  HTTPS on the website while the admin domain's certificate was still being
  issued, and the second job — finishing later — wrote the domain records
  back the way they looked when it was QUEUED: the admin domain's fresh
  certificate flag included. Nothing visible broke until the next panel
  restart re-rendered the web server from those records and dropped the
  admin domain's https server — the shop's admin went unreachable hours
  after every job had reported success. A certificate job now saves only
  what it certified, merged into the records as they are at that moment.

- **A release that cannot start can no longer be published.** The build now
  refuses to package any release whose compiled tree does not boot and serve its
  own login page first — so a missing file that the panel reads at its own startup
  is caught here rather than on your server.

**The panel always knew only one job runs at a time; now every page does too.**

- **A running job shows everywhere.** A pill in the page header names
  whatever is running, on every page; clicking it opens the live log. The
  page whose flow it is paints a progress card — each step ticking off as
  it finishes — and that card is still there after a reload, in another
  tab, and for jobs the panel started by itself (a push deploy, the
  scheduled backup).
- **While it runs, the buttons that would collide with it go quiet** — and
  come back by themselves the moment it finishes, with the page repainting
  to show what changed.
- **The same action cannot be started twice.** A second "run backup now"
  while one runs is refused with a sentence, not queued behind it; same for
  a certificate request (Let's Encrypt rate-limits repeats, so a double
  press had a cost), the websocket wizard, a .env apply. Installs, updates,
  rollbacks and restores refuse while anything at all is running — including
  the narrow window two browser tabs used to be able to win.
- **A refused upload costs a second, not ten minutes.** The zip upload used
  to go up completely and only then learn a job was running; it is refused
  before the first piece now. The database import gained the same manners.
- **A successful install now says so.** A leftover error in the success path
  meant the one flow everyone runs first finished silently — no message, and
  the page still saying "not installed" until a manual reload.
- The website zip update asks before shipping, the way the admin one always
  did — a slip on the file picker used to rebuild and restart the live
  storefront with no way back.
- "Run now" on a scheduled task now follows the run to its end and reports
  how it went; failures used to vanish.

- **A minute-by-minute error in the log of a shop nobody had broken.** From
  the moment an install's code lands until the install (or the vendor's own
  web installer, which can take a while) finishes, the scheduler was already
  ticking — against a database with no tables in it, one error line per
  minute, ending in a "15 errors in 24h" warning on the shop's first
  check-up. The workers now stay off from the moment the code lands until the
  install has finished.
- **The restore test mentioned a project you cannot see.** On a server whose
  built-in "default" project was never used (every server installed since it
  became hidden), the test still listed it: "localhost — empty database —
  nothing to prove". It no longer appears anywhere on the Backups page.
- **The storefront install ended with wrong directions.** "Set the website
  domain, then turn the website vhost on" — on a server where both had
  happened automatically at project create. It now says the site is live at
  its address, or names the one thing actually missing.
- The Home page's backup card says when the next automatic backup runs.

A night on the database and on the panel itself, measured with a real shop's
data (a 410 MB database) on the optimised codebase and on the untouched
CodeCanyon download.

### Your database is looked after by itself now

- **The speed indexes apply themselves.** 6amMart's tables lack the indexes
  the admin panel and the apps need for the queries they run most, and the
  card that offered to add them had a button nobody pressed — the shop
  installed from the CodeCanyon zip on the second server was missing 34 of
  them. They are now added at the end of every path that puts data into a
  project's database: install, the vendor's own web installer, update, zip
  update, transfer, database import and restore. Measured: 36 indexes added to
  the vendor shop in 1.0 s, the shop answering throughout. Two new ones make
  the order reports faster — the store report 151 → 36 ms, the earning report
  180 → 77 ms on the real data.
- **Nightly database care, nothing to set up.** Every night at 04:10 the
  panel removes what the app can never use again — expired and revoked sign-in
  tokens (24,578 on the real shop, which 6amMart never purges), day-old
  one-time codes (4,956), stale password-reset tokens, expired cache rows,
  failed jobs older than 90 days — re-checks the speed indexes, and on Sundays
  rebuilds tables that have freed a lot of space, after checking the disk can
  hold the rebuild. Measured: 33,232 rows gone in 1.2 s, shop answering
  throughout. Your own rows — in-app notifications, visit and search logs — are
  kept for ever until you choose otherwise on the Database page, where each
  choice says exactly how many rows it would remove.
- The check-up page has a row for both, and the Database page shows the last
  pass and what tonight's will remove.

### Things that were wrong and looked fine

- **Every server kept a spare set of services for a project you never see.**
  The first thing the setup wizard saved created a PHP pool with two idle
  workers, a Redis server and four service units for the built-in "default"
  project — on every server installed from the public command — and the
  services table listed them as four stopped services. They are retired when
  idle, and a server where it already happened cleans up at its next restart
  (verified: both shops answered throughout). A follow-up read found that a
  push from GitHub could bring them back, from the internet, unsigned — the
  webhook no longer can, and an unsigned push answers 401 and creates nothing.
- **Turning phpMyAdmin off could stop PHP for every shop on the server**
  when its pool was the last one. It keeps one pool serving now.
- **A new project's live-updates address sat as "needs you" until you found
  the wizard for it.** Creating a project registers the address; nothing could
  serve it until the app existed; and the step that finishes it was a wizard on
  the Domain page. The install finishes it now, and the apps are pointed at the
  address only once it answers. Verified on both shops of the second server,
  through Cloudflare.
- **The check-up said "7 files changed by hand — treat this server as
  compromised"** after the panel itself had re-written its own server files at
  boot. Every write the panel makes is on the ledger now.
- **"15 error lines in the last 24 hours" on a shop installed an hour ago**
  were the log's previous life. Errors are counted from the moment the app was
  installed.
- **A table rebuild that ran out of disk was logged as space given back.**
  MariaDB reports that failure in the result rows, not the exit code; the rows
  are read now, the disk is re-checked per table, and one failing rule no
  longer cancels the rest of the night.
- A PHP-extensions row that warned "user does not exist" on fresh servers, a
  website row that timed out on a site answering in 100 ms because every check
  ran at once at boot, and a check-up that the Home page waited for before it
  painted anything — all three fixed. Home paints in about 90 ms and the
  attention card fills in when the verdict lands.

### The panel is lighter

Every page was read for what it repeated, what it asked for no reason, and
what it showed about a different project than the one in the heading.

- The check-up folds its healthy and informational rows behind a count; what
  needs you is all that is open. Every "Take me there" opens the row's own
  project.
- The Cloudflare tab no longer draws twenty-five full cards to say "nothing to
  do" twenty-five times: what differs stays open, the rest folds, and the
  verdict counts only the settings "Set this up for me" would change. The
  "how is Cloudflare set up" question can be answered with one click.
- Backups: one schedule card instead of the same plan stated three times, the
  first storage's snapshots load with the page, and the restore test says which
  databases it proved rather than printing the same list twice. Every "next
  run" on the panel reads "in 9h · date" — a server clock on UTC and a browser
  elsewhere used to show two different times for one backup.
- Deploys: a shop installed from the CodeCanyon zip shows the zip, "by hand",
  and the buyer username it was installed with — no branch, no automatic
  deploys, no mode switch, and the admin password is generated for you.
- Logs: one tab per service that actually runs for this project.
- Projects, Overview, Database, Settings: the permanent green hero, the
  finished setup meter, two cards that repeated the sidebar, the clock essay
  and the self-heal service list are gone or folded to a line.
- The setup wizard's last screen turns daily backups on itself instead of
  sending you to the Backups page, and has one "Exit setup" instead of two
  kinds of skip.
- Weekly disk cleanup is on by default on a server that never chose.
- Eight languages: this round's new and reworded text is translated, not left
  in English.


### 1.4.3 — 2026-08-23

A second server, wiped to a bare Ubuntu and installed with the public install
command, then driven end to end twice over: once with a real shop's data on the
optimised codebase, and once with the untouched CodeCanyon download. Everything
below is something that walk found.

### Things that were broken and looked fine

- **Your apps could be told your shop has no live order tracking, and every
  page on this panel said it was working.** 6amMart hands the phone apps their
  websocket address out of its own settings table, and restoring a backup — or
  importing a database from another install — replaces that table with whatever
  the backup held. The websocket server was running, this server was routing to
  it, and the address handed to the apps was empty. Live order tracking was dead
  in every app on the shop and nothing said so.

  Two things changed. The check-up page now asks the question the apps ask, so a
  shop whose apps cannot see the address is a failure with the one button that
  repairs it. And restoring a database now corrects the address by itself, so you
  do not need the check-up page to notice.

- **Your customer website could be down and the check-up page stayed entirely
  green.** Nothing on it asked about the website at all — every row was about the
  admin panel, the API, the database or the workers. Measured with the website
  stopped: shoppers were getting an error page while all twenty-two rows were
  green and the server reported no failed service. There is a row for it now, and
  it asks over your own server rather than trusting what a visitor's cache
  answers.

- **A website that was down still answered "everything is fine" to the internet.**
  The friendly "This shop is not open yet" page was served with a success code, so
  Cloudflare cached it as a good page, a search engine would index it as your
  home page, and any uptime monitor stayed green through the outage. It now
  answers with the correct temporary-error code and says when to come back.

- **"Alerts go to you@example.com" did not mean any alert had ever arrived.** The
  row checked that the settings were filled in. A wrong password, a wrong port, or
  a mail provider that started refusing — all of which leave the settings looking
  perfect — meant every alert this panel produced was being thrown away while the
  page said alerts were fine. It now reports what actually happened to the last
  one: refused (quoting the mail server's own words), accepted (with when), or
  never needed yet — and it says which.

- **The row that promises PHP is confined to its own folders was reading the
  wrong thing.** The confinement is fixed when PHP starts, so a change that was
  never followed by a restart is on disk and not in force — and the row was
  reading the configuration on disk. It now asks the PHP that is actually serving
  your shops.

### The CodeCanyon zip could not be uploaded at all

The 6amMart admin download is 354 MB, and installing from that zip is how most
buyers start. It could not arrive: too large for the panel's own web address, too
large for Cloudflare in front of it, and the panel's direct address is closed once
it has a domain of its own — which it does, on any properly set-up server.

The panel now sends a large zip up in pieces and puts it back together on the
server. Proven on the real download: 354 MB, in 45 pieces, none of which needed
retrying, followed by a clean install of the untouched vendor codebase.

Three things had to be right for that, and each was found by doing it rather than
by thinking about it: the pieces are sized for a slow home connection rather than
for the size limit (the first attempt died two-fifths of the way through), a piece
whose connection is cut is now noticed instead of hanging for ever, and retrying
one cannot corrupt the file.

Also: the message shown when a file really is too big used to be a piece of
internal shorthand — literally `upload.tooBig` on screen — and the advice it gave
pointed at an address that is closed. Both fixed, in all eight languages.

### For the untouched CodeCanyon codebase specifically

- **A shop installed with 6amMart's own web installer told its apps no websocket
  address.** That installer rewrites the settings file from scratch and leaves out
  the three values that say where to connect, and this panel only filled in values
  that were already there. It now writes them outright.
- Installing from the vendor download was walked end to end for the first time —
  its own web installer, then this panel's "Finish setup" — and the panel repairs
  what that installer leaves behind, including a line it writes malformed.

### A restore finished green and left the shop down

- **Restoring a backup rebuilt the configuration and never told PHP.** This
  server compiles PHP once and never re-reads a file (that is a large part of
  why it is fast), so the freshly restored configuration sat on disk while
  every worker went on serving the one it started with. Measured on a fresh
  install: the restore job reported success at every step, and the admin panel,
  the API and the storefront all answered 500 until `php-fpm` was reloaded by
  hand — on the one job you reach for when things have already gone wrong.
  Four other places had the same gap: the boot-time repair of your websocket
  settings, the automatic repair that puts your site back on its normal routes,
  and turning websockets off and on. All five now hand the result to the
  running site, and there is a check that will not let a sixth appear.
- **One stray file could block every future update.** Anything your project's
  own user ran — an update's dependency install, or a single command typed over
  SSH — could leave a dot-folder in the app directory, and the update then
  refused to start with "commit, stash or revert them", which is not something
  you can do from the panel. Updates now clear those two known folders first.

### Your shop could go down the first time you cleared its cache

- **The app could not read its own settings file, and nothing said so.** On a
  freshly installed project `.env` ended up owned by root while your shop runs
  as its own user. It worked anyway — every page was being served from the
  cached configuration, which had the database password baked into it. The
  moment that cache was cleared, by an update or by this panel's own "Clear
  Laravel's caches" button, every page returned 500 and the error named a
  database called `forge` that does not exist on your server. Measured on a
  fresh install: the shop ran fine for ninety minutes and then went down on a
  routine update.

  Three things changed. The file's owner is now set alongside its permissions,
  every deploy re-asserts it (so a server already in this state repairs itself
  the next time you press "Get the latest code"), and the health page has a
  check that sees it *before* the cache is cleared rather than after.

The fresh-box round: a server wiped back to a bare Ubuntu, installed with the
public install command, then walked all the way through — the first-run wizard,
a project, its domain and HTTPS, the 6ammart app, the customer website, backups
to cloud storage, email alerts and Cloudflare. Everything below is something
that walk found.

### Things that would have failed you quietly

- **Your panel's own HTTPS certificate never renewed** on a server with no
  project on it yet — which is exactly where a new install sits the moment the
  wizard finishes. The nightly renewal asked whether any *project* had a
  certificate, and the panel's own is not a project. Nothing else would have
  caught it: Ubuntu's own certbot timer is switched off on these servers. Your
  panel would have gone to an expired certificate at 90 days with every page
  still reporting green.
- **A private repository for your customer website could not be installed at
  all.** The admin app's install form has a box for an access token; the website
  form did not, and there was no other way in — the deploy key is only offered
  for a checkout that already exists. The clone came back with git asking for a
  username. The box is there now.
- **Your restore test reported a shortfall on every server, for ever.** Every
  install carries a starter project with no app in it, and an empty database was
  counted the same way as a database the test could not check: "PASSED for 1 of
  the 2 … NOT proved". Empty and untested are different news and now read
  differently.

### Things that told you the wrong thing

- **"You skipped the setup steps"** appeared on a brand-new server whose owner
  had just finished all three of them — and it named their password and their
  address as still waiting. The reminder now only counts the steps the wizard
  actually walks you through, and it lists the ones genuinely left.
- **The Cloudflare page said "not on your plan"** about the cache rules, the
  firewall rules and the rate limit when the only thing wrong was that the shop
  belongs to another project on the same Cloudflare site. Free has all three.
  The rows now say "not needed on this site" and the summary line counts them
  separately.
- **A full rate-limiting slot blamed you for it.** Free allows one rate limiting
  rule per Cloudflare *site*, not per project, so a second shop on the same site
  found the slot taken — and was told "0 rules of your own are using all of it"
  and to go and delete them. It now says who is actually holding it, that nginx
  on your server still limits those addresses, and the two real ways out.
- **A full firewall phase answered with Cloudflare's API string** — "exceeded
  the maximum number of rules in the phase http_request_firewall_custom: 6 out
  of 5" — and left the shop with no Cloudflare firewall rules and no idea why.
  Same treatment: who filled it, what still protects you, what to do.
- **A failed test email said only "timed out after 15s".** Most hosts (Linode,
  Google Cloud, Oracle, AWS, Vultr) block outbound mail ports on a new server
  until you ask them to open it — measured on a stock server: 25, 465 and 587
  all hang while the same provider's 2465 connects at once. The message now says
  so and names the alternative ports mail providers offer. A mail server that
  answered and then stalled says that instead.
- **`server uninstall` did not mention the project accounts it leaves behind.**
  It has to leave them — they own the files and databases it deliberately keeps
  — but a later install checks for them to decide whether a project already
  exists, so the next "fresh" install behaved differently for reasons nothing
  had mentioned.
- **The origin-lock explanation was missing in all seven translations.**

The Cloudflare round. Everything below was found by auditing what SixPanel already
does against what Cloudflare actually offers, and checking each finding twice.

### Switching something off could break your shop

- **The encryption row's off switch would have taken your whole shop down.** It set
  Cloudflare to talk to your server without encryption, and your server answers
  that by sending the visitor back to the secure address — round and round, for
  your storefront, your admin panel and all three phone apps. One click, nothing
  asking if you were sure. Three other rows had the same shape: switching off
  "0-RTT — off" turned 0-RTT **on**, switching off "Rocket Loader — off" turned
  Rocket Loader **on**, and the cipher row's off switch quietly did the on action
  and reported success. None of those four has an off switch any more. If you want
  the panel to stop deciding one of them, press **Keep**.
- **The panel could switch off "I'm under attack" mode while you were under
  attack.** It read the setting as something to correct, and the confirmation you
  saw said only `Set "Security level: medium" to medium`. It now leaves it alone
  and explains what that mode costs — every caller is asked to run a browser
  check, and your phone apps cannot run one, so ordering stops while your website
  still looks fine. Every setting now names what it is about to replace.

### Your phone apps

- **On a paid Cloudflare plan the rate limit would have shown your apps a browser
  puzzle.** The customer, store-owner and rider apps cannot solve one — to them it
  is a blocked request with no explanation. It blocks on every plan now, which is
  something an app can understand and retry. Cloudflare would have rejected the
  old setting anyway, so paid plans were getting nothing.
- **The exemption that protects your payment confirmations now also covers
  Cloudflare's bot protection**, which is the part most likely to stop a payment
  provider's call — those calls come from a machine, which is exactly what bot
  protection looks for.

### Your Cloudflare site may have other websites on it

- **The panel's rules used to apply to every website on your Cloudflare account,
  not just this shop.** If you keep a WordPress site on the same domain, setting
  up the rules here would have blocked its admin area and broken its appearance.
  The rules now name your shop's addresses, and a new check-up row lists any other
  website sharing your Cloudflare site.

### Not everyone uses Cloudflare

- **The Firewall page gave every server the same instructions**, written for a
  server behind Cloudflare — close everything except Cloudflare's addresses. On a
  server that is not behind Cloudflare, following them takes your shop offline;
  following only half of them looks fine for about three months and then every
  HTTPS certificate on the server expires at once. The page now checks each of
  your addresses and gives the right instructions, and when it cannot tell, it
  gives the safe ones.
- **Files like database dumps and configuration backups are now refused by your
  server itself**, not only at Cloudflare — including the compressed names people
  actually use, such as `.sql.gz`.
- **A new check-up tells you if your order emails can be forged**, which until now
  you could only find out through the Cloudflare page.

### Somebody could run up your SMS bill

- One address in the customer app sends a real text message to any phone number
  the caller types, and nothing anywhere limited it — not your server, not
  Cloudflare, not the application. It is limited on both now.

### Refuse visitors that skip Cloudflare (new, and off until you turn it on)

- If someone learns your server's address they can go straight to it and skip
  every protection Cloudflare gives you. Your server can now refuse anyone who
  does. It stays **off** until you switch it on, it refuses to switch on if any of
  your addresses would be cut off by it, certificate renewals and the panel's own
  checks keep working, and if anything goes wrong you can lift it over SSH with
  `sixpanel origin-lock off` even with the panel down.

### Smaller things

- **Tiered cache is included on the free Cloudflare plan** and the panel was
  telling you to buy Pro for it, while reading a setting your plan cannot change.
- **The HTTPS-only setting is now checked properly.** A policy lasting five
  minutes used to be reported as correct.
- **Rules and blocks you set by hand in Cloudflare are now listed** in the check-up,
  so a rule nobody remembers is not invisible.
- If you skipped the first-run setup, there is now a **Finish setting up** button
  to go back to it. Before, skipping it once was permanent.

- **The Deploys page could say your website has no repository while deploying it
  from one.** The website's repository address is recorded at the end of the
  first install, so an install that was interrupted left it blank forever. The
  panel now reads it from the checkout itself, which knew all along.

### The website build stops leaving files in your app folder

- Building your storefront ran as your project's own user, and that user's home
  folder *is* your app checkout — so Next.js wrote its telemetry file to
  `.config/` there and npm wrote its logs to `.npm/`. Two visible consequences:
  your Home page reported them as application files that had changed since the
  last deploy, and the next app update would have refused to run because it saw
  a modified folder. Builds now use a home of their own, and the next website
  deploy clears what the old ones left — only those two names, only at the top
  of the checkout, and only if your code does not track them. The running website
  service had the same problem, from the same cause: systemd also takes the home
  folder from your project's user, so `npm run start` recreated `.npm/_logs` in
  your app checkout minutes after the deploy had cleaned it. All four per-project
  background services now use the same dedicated home.

### An update could leave the old panel running under the new version number

- **This one is worth reading even though it is short.** An update lays the new
  release over your server without deleting anything, which is exactly right —
  your settings, your data and your apps have to survive it. But if a plain
  JavaScript file was ever left beside the panel's compiled code, the panel
  loads *that* file instead, and goes on reporting the new version while running
  the old code. SixPanel now removes those during every install and every
  update, using the list of files the release actually shipped, so it can only
  ever remove a stray copy and never one of its own. It matches whole paths when
  it decides that — an earlier attempt asked whether the release ships
  `…/deploy.js` and got "yes" because that text appears inside `…/deploy.jsc`,
  which made every stray look like a shipped file and removed nothing, silently.
  A test now creates a tree with three strays, a shipped loader and an innocent
  file, and counts what survives.
- The same trick is the cheapest way for someone to swap out a piece of a
  protected panel on your server, so the **Panel files unchanged since install**
  check now reports it separately and in its own words: not "a file changed" but
  "this file is being loaded instead of the panel's own".

The hardening round. Everything below was found on a server installed from
scratch the way you install one, and fixed and re-measured on the same server.

### A shop installed into the wrong database

- **This is the one to read.** On a server with more than one project, the
  second project's installation ran against the FIRST project's database. Every
  step of the job reported success; the project's own database was left empty
  and its live site read the neighbour's data. The cause is that SixPanel's own
  settings file names a database, and the application never overrides a setting
  that is already in the environment it was started in. The rule that keeps
  those apart existed for the background workers and did not cover the jobs the
  panel runs itself — which is where a shop is installed. It does now.
- If you have one project, this never affected you. If you have more than one
  and installed the second recently, open **Database** for that project and
  check the name it is using.

### Rate limiting

- **Adding nine characters to a web address used to skip every rate limit on
  this server.** `/index.php/login_submit` and `/login_submit` are the same page
  to the application and were two different things to the web server, so the
  tight limit on sign-in — one a second — never applied to the first spelling.
  Measured: thirty attempts, all thirty admitted. Now six admitted and
  twenty-four refused, the same as the ordinary address. The Cloudflare rule
  SixPanel writes was walked past by the same trick.
- **Every limit now applies to a visitor's whole address range on IPv6, not to
  one address.** The smallest allocation anybody is given is 18 quintillion
  addresses. Keyed one at a time, the limits were free to walk around.
- **There is a ceiling on the whole server**, not just on each visitor. Four
  requests per PHP worker may be in front of your shop at once; past that the
  next one is refused in under a millisecond. Without it a handful of visitors
  staying politely inside their own limit could still fill the queue, and what
  everybody got then was not a "try again" — it was a broken page, including
  the customer who made one request.
- **A refused request never touches your shop.** Nothing here reaches PHP.

### Your customer website

- **The website could not be built on a 4 GB server while the shop was
  running.** The build asks Node for a memory ceiling, and that ceiling was
  worked out from free memory alone — so on a normal server it came out around
  1 GB and the build died on it, with two and a half gigabytes of swap sitting
  untouched. SixPanel creates that swap itself during installation. It now
  counts towards the build, and the same server that could not finish reported
  a 2,332 MB ceiling and built the site.
- **A build that was interrupted used to poison the next one.** If a build was
  cut short — a restart, an update, a reboot — the half-finished dependencies
  were left behind, and the next deploy saw a folder full of them and skipped
  the install. The build then failed with `code 127` and said nothing useful.
  SixPanel now checks whether the last install actually *finished*, not whether
  it started, and says which of the two it is repairing.
- **Pictures on your storefront have their own speed limit.** Resizing an image
  is the single most expensive thing your server does per request, and it runs
  on the same process that draws your pages. It used to share one limit with
  everything else. Now a flood of resize requests is pinned at its own rate
  while ordinary browsing is untouched — measured: 900 requests in 13 seconds
  from one address, none refused; 2,000 in 12 seconds, held at the limit.
- **The web server now keeps its connections to the website open** instead of
  opening a new one for every request. Measured: 200 page loads used to leave
  200 spent connections behind and now leave two live ones. Under a flood that
  is the difference between serving and running out of connection slots.

### Cloudflare

- **A new check-up row tells you if Cloudflare has added addresses your server
  does not know about.** If that happens, every visitor arriving through those
  parts of Cloudflare looks like one visitor to your server, and the rate limits
  start refusing real customers in whichever regions they cover — while
  everything else looks perfectly normal. SixPanel reads Cloudflare's published
  list, checks it looks genuine before believing it, and tells you. It never
  rewrites anything on its own from something it read off the internet.

### What can run on your server

- **Only one file can run as a program.** Your shop has exactly one entry
  point, in both the CodeCanyon version and ours. The web server used to be
  willing to run any file ending in `.php` that existed under your site;
  now it runs that one and answers "not found" to everything else. The entry
  point itself is no longer reachable from outside at all.
- **Probes for software you do not run are refused by the web server.**
  `/wp-admin/`, `/phpmyadmin`, `/telescope` and a dozen more used to start your
  whole application and run a database query, once per probe, to build a "not
  found" page.
- **Repeated failed SSH logins are banned** — five tries in ten minutes, one
  hour out. Port 22 is open on every server, and nothing here used to watch it.
  **Server → Health** shows how many addresses are banned. On the test server
  the first ban happened within four hours.
- **The server's network settings are sized for a burst of traffic** rather
  than for a general-purpose desktop, and Health reads the live values back so
  you are told if something else changes one.

### Would you know if something changed?

- **SixPanel now checks its own files** against a list every release carries.
- **And your shop's files** against what you deployed, which is what a file
  dropped into your site by somebody else looks like.
- **And the settings files it writes for you** — about forty of them. Edit one
  by hand and the panel tells you, instead of quietly writing over it later.
- **The background workers now run with the same confinement the web server
  has.** They run your shop's code and had none of it.

### The panel's own address

- **The door that never closed.** Direct access on the server's IP address and
  port is switched off once the panel has answered on your domain from the
  internet. On a new server that check ran about forty seconds after the DNS
  record was created — often a few seconds before the record had finished
  spreading — so it correctly refused to close the door and told you to try
  again. Nobody tries again. The panel now keeps checking on its own and closes
  it the moment your address answers.
- **The lock is on the connection, not on what the caller claims.** It used to
  be decided by the hostname in the request, which the caller writes: dialling
  the IP address and claiming your domain walked past it.
- **`/healthz` answered `{"ok":true}` to anyone on the internet**, from the
  first line of the code whose whole job is to make this port look closed.

### Backups

- **A project's backup contained different things depending on which project it
  was.** The first project's backup swept in log files and compiled pages that
  nothing would ever restore; every other project's contained the uploads and
  nothing else. Both now contain the same list: the settings file, the
  database, the uploads, and the keys.
- **Those keys are the third thing this found.** Both versions of 6amMart keep
  the key that signs every phone's login in a place the backup was not looking.
  A restore would have signed out every customer, driver and store owner, and
  nothing would have said why.
- **The database password no longer appears on a command line** during a backup
  or a restore, where any other account on the server could read it.

### When something is wrong

- **A job interrupted by the panel restarting now says so.** It used to end as
  a bare red "failed" with no reason and no failed step — a backup that stopped
  on "initialising the repository" with nothing after it. It now says the panel
  stopped underneath it and that nothing after the last line happened. A job
  that was still waiting says nothing of it ran and it is safe to repeat.
- **The check-up can see whether the rate limits are firing**, and tells apart
  somebody trying passwords from ordinary customers being throttled.
- **It reads your shop's own rate limiting too** — the CodeCanyon version ships
  almost none, and that is worth knowing.
- **And whether your customer website will re-serve images from any address on
  the internet.** The CodeCanyon storefront is configured to, which turns your
  server into somebody else's image host.

### Smaller things

- The language menu no longer says "(coming soon)" beside seven languages that
  are finished. It had been asking the wrong question since the panel started
  loading one language at a time.
- **A new server no longer starts on an Indian clock.** The timezone defaulted
  to Asia/Kolkata everywhere in the world, which also put PHP five and a half
  hours away from the database on a brand-new server. It takes the server's own
  clock now, and the first-run wizard can move the server's clock with it —
  which is only safe before a shop exists, and is refused afterwards.
- The wizard remembers that you filled in the welcome step. It used to remember
  that in your browser, so the same server asked you again on your laptop.
- An upload too large to reach the panel is refused in your browser, with the
  real limit in the message, instead of by an error page the panel never sees.
- The page header no longer lets the page scroll through it.
- The customer website now answers with the same four security headers the
  admin panel always has.

Two things the panel could see and never told you about, and one warning it kept
raising about a comment.

### When something is wrong

- **Failed background jobs are now on the check-up.** "The queue worker is
  running" and "the work is getting done" are different things, and until now
  nothing here could tell them apart: a worker that starts, takes jobs and throws
  on every one looks perfectly healthy from the outside. What it leaves behind is
  a list of failed jobs, and each one of those is an order email, a push
  notification or a payment callback that never happened — with nothing telling
  you or your customer.
- **It measures whether jobs are failing NOW, not whether they ever failed.**
  One failure last month is history and is not counted against your server;
  anything in the last hour, or five in a day, is a live fault and says so. The
  wording, the windows and the verdicts are the same ones the settings check-up
  uses on the same table, so the two can never tell you two different things.
  Nothing here retries a job for you: re-running a queued payment callback can
  charge a customer twice, so that stays your decision.
- **The panel now reports which dangerous PHP functions are blocked.** The
  settings check-up has been quietly marking this down on every SixPanel server,
  and nothing in the panel mentioned the setting at all. It does now, including
  why two names on the usual hardening lists are deliberately left out: they are
  the same function twice, they block nothing your server was not already able to
  do, and switching them off breaks the error page you need on the day something
  goes wrong. Measured, on both 6amMart codebases.

### Serving configuration

- **"This server is still running an older serving configuration" stopped being
  raised about a comment.** The check compared the whole configuration file
  character for character, so a single comment line left over from the product
  being renamed was enough to tell you the improvements in your release were not
  switched on. It now compares the settings themselves and ignores comments and
  blank lines. A genuine settings difference is still reported exactly as before.

### The settings check-up (SixPreflight)

- **It can now see your backups.** SixPanel takes the backups on this server
  itself — a schedule, a repository and an off-server copy that live outside your
  shop's folder — so the check-up, which looks from inside the shop, found
  nothing and reported "unknown" while this panel knew the answer to the hour. The
  panel now writes the state down where the check-up reads it: whether it is
  scheduled, when the last one finished, whether a test restore has actually
  passed, and whether a copy exists somewhere that is not this server. All three
  are reported separately, because they fail separately.
- **And it stops claiming your web settings are current when they are not.**
  Three of its rows printed values with "as SixPanel wrote it into nginx.conf"
  and a green tick, while this panel was reporting the same server as running an
  older configuration. The panel now hands over that verdict too, so the check-up
  either confirms the value or says plainly that it could not.
- **Update to SixPreflight 1.5.1** on your projects to get both, from the
  SixPreflight page in the panel.

An update now finishes the job: it removes what a release took away as well as
laying down what it added. And the health check-up stopped disagreeing with the
server's own supervisor about whether anything had failed.

### Updates

- **An update deletes the files a release removed.** Until now an update only
  ever added and overwrote, so anything a release took out stayed on your server
  for as long as the server lived — while a server installed from scratch on the
  same day did not have it. Two dead brand images, shipped by an earlier build
  the same day, are the case that showed it. A release now carries the list of
  what it retired, worked out by comparing the release you are running with the
  one you are getting, and the update removes each one.
- **A file you changed yourself is never deleted.** A retired file is removed
  only while its contents are still exactly what SixPanel wrote. If you edited
  it, it stays where it is and the update says so. Nothing outside SixPanel's own
  folder is ever touched — not your sites, not your projects, not your settings,
  not your backups.

### When something is wrong

- **The check-up now asks the server's own supervisor.** Every other check looks
  at something SixPanel already knew to look at. This one asks systemd — the
  part of Ubuntu that starts everything on your server — for its verdict, which
  is the only question that catches a failure nobody wrote a check for. On a real
  server, systemd called the machine "degraded" all day while this page said
  "Healthy overall".
- **A failed service that is not ours is still reported, as exactly that.** You
  are told the server reads as degraded, which service it is, and that nothing
  SixPanel or your shop runs is affected — instead of a green headline that
  contradicts what you see the moment you log in over SSH.
- **The scheduler no longer marks the whole server broken for an application
  error.** A project whose code is deployed but whose 6ammart installation was
  never finished had its once-a-minute scheduler failing every minute, which put
  the entire machine into a "degraded" state and sent a failure notice each time.
  A failed tick is now reported once, where you can act on it — the Scheduler row
  tells you when the last successful run was — and the details are still in the
  service log.

### Also

- **The settings check-up (SixPreflight) on your projects is at 1.5.0**, so the
  numbers SixPanel quotes on the Health page come from the current check set.

Housekeeping after the two-step sign-in: the product's own name in the mail it
sends you, an honest answer from two screens that were quietly saying the wrong
thing, and the sign-in card sitting exactly where it should.

### What you read

- **Alert emails say SixPanel.** The name on the From line and at the start of
  every alert subject — a service failed, a login lockout, a repair, a job
  failure, the disk filling up — still said "6ammart panel". An alert arrives at
  3am with a subject and nothing else, so it is the line where the name matters
  most. The files the panel writes onto your server say SixPanel too, which is
  what you see when you look at your own web-server configuration.
- **The sign-in card no longer shifts by a pixel** when the second step is
  taller than the first. It was pinned already; the pin was rounded to a whole
  pixel and the card is centred on a half one.

### When something is wrong

- **A login lock now tells you what locked it.** If five wrong six-digit codes
  locked an address out, `sixpanel unlock` and the Security page used to show
  "wrong codes: 0" — the count is cleared when the lock trips, so that the
  address gets a clean set of tries when the lock lifts. Beside an unrelated
  wrong password from an hour earlier, the table pointed at the wrong cause at
  the one moment anyone reads it. It now reports the count that caused the lock,
  for as long as the lock lasts.
- **"Test my backup now" no longer shows five green ticks for a test that
  tested nothing.** When there is no backup it can read — an empty storage, a
  full disk — the steps it skips now say so instead of finishing green and
  silent. The result itself was already recorded honestly and the health page
  already warned; it was the job you watch that looked fine.
- **And the advice underneath that warning matches the reason.** It used to send
  you to the Disk page whatever had happened, including when the disk was fine
  and the storage simply had no database in it yet.

**Signing in is now two steps**, and a deploy tells you before it signs your
customers out.

### Signing in

- **The 6-digit code has its own page.** You type your username and password
  first; if two-factor login is on, the next page asks for the code alone, says
  which account is signing in, and gives you one way back. The old form put all
  three boxes on one page.
- **Six digits is enough — there is no button to find.** Type or paste the code
  and it submits itself. Pasting the "123 456" your authenticator app shows,
  space and all, now works; before, the space was counted as one of the six
  characters and the last digit was thrown away, so nothing happened.
- **A wrong code does not cost you your password.** You stay on the code page
  with the box cleared and ready. Only a wrong password, a locked address or a
  blocked address sends you back to the first page.
- **On a phone, and in your language.** The page is drawn for a 390px screen in
  both themes, and the new wording is translated in all eight panel languages.
- **The same protection as before.** The code page is not a new door: it is the
  same sign-in, with the same limits. Five wrong codes within fifteen minutes
  still lock the address out for thirty, and while it is locked the first page
  refuses too.

### Also in this release

- **An update that would sign everyone out now says so first.** On a shop that
  keeps its sessions in the cache, the cache-clearing step of an admin update
  ends every session on the server — admins, vendors, delivery riders and
  shoppers, mid-order. That is how Laravel is built, not something on this
  server, and the panel now reads your shop's own settings and warns before it
  starts instead of after.
- **Build caches can no longer grow without a limit.** The space your website's
  build tools keep between deploys is now capped.
- **You can restore one project on a server that runs several.** Restoring used
  to be all-or-nothing. The database it writes into is taken from that project's
  own settings and checked against them, so a restore cannot land another shop's
  data on top of a live one.
- **The panel can no longer lock itself out through Cloudflare.** Its own
  address was left out of the check that decides the zone's SSL mode, so a
  server whose shops all held real certificates could switch to a setting that
  rejected the panel — and the one address that answers with a login started
  returning an error page.
- **The tools that build a release are now pinned by content, not by version.**
  A release is signed, but until now the two programs that produce the signed
  files were downloaded fresh on every build with nothing checking what arrived.
  Every one of them, and everything they depend on, is now verified against a
  recorded hash before it runs.

**This release is mostly a name and a logo.** The product is called **SixPanel**
— no suffix. The Docker-based sibling is **SixPanel Docker**, and it carries a
different mark, so it is obvious which of the two a server is running. Nothing
about how you install or update changes: the install line, the address it comes
from and the update button are all exactly what they were.

### The name

- **"SixPanel Native" is gone from everywhere you can read it.** The manual, the
  installer's own messages, the command-line tool's help and manual page, the
  header comment on every configuration file the panel writes onto your server,
  and the description systemd shows for every service it manages
  (`systemctl status sixpanel` said "SixPanel (native)" and now says "SixPanel").
- **Your install and update commands are unchanged, deliberately.** The address
  `installer.allsweb.net/sixpanel-native/` is the one your server already
  updates from and it stays. `/sixpanel/` is a different product. Nothing you
  have written down or scripted needs editing.

### The logo

- **The panel now wears the SixPanel mark** — on the browser tab, the sign-in
  card, the sidebar and the setup wizard. It replaces the AllsWeb logo the panel
  had been showing, which named the company that builds it rather than the
  product you are running.
- **The tab icon is drawn for tab size.** A heavier cut of the same mark, because
  the thin end of the original disappears at the ~18px a browser tab actually
  renders.
- **The name beside the mark is now text, not a picture.** It follows your light
  or dark theme and sits properly next to the version number. On a phone the
  name steps aside and the mark stands alone, so the row keeps the version, the
  update badge and every navigation icon.
- **The sidebar stopped saying the name twice.** The product name used to be
  printed under the logo because the logo said "AllsWeb"; now that the logo says
  SixPanel, the line below it carries the version alone.

### Also in this release

- **Your website records can no longer be switched to "DNS only" by accident.**
  The Cloudflare page drew an on/off switch next to "Orange cloud on your website
  records". Turning it off published your server's real address for every one of
  that project's records — the thing the rest of the panel spends its effort
  hiding. The switch is gone, along with two quieter paths that could freeze a
  grey record in place; the Fix button, which is the only press that was ever
  right, stays.
- **A record that is already "DNS only" is now reported as something to fix.**
  Every box set up before that rule has them, and the Domain page had been
  calling them correct. It now says which records are one flag away and offers
  the change — it does not make it for you, because your customers are already
  being served through those names.
- **Your project settings check-up stops losing points for being hardened.**
  Two things SixPreflight could not see about a SixPanel server — how long the
  web server will let a request run, and whether the application logs are being
  rotated — were being answered as "unknown" or, worse, as "no". Both are now
  reported by the panel, so the score reflects the server you actually have and
  you are not advised to add a log rule the panel already manages.
- **A deploy started by GitHub or from the command line is filed under the right
  project.** Those two paths had no way to say which project they were for, so
  the run appeared on the default project's Deploys page — or on every project's
  page — instead of on the one it had just deployed. Nothing deployed wrongly;
  the history was in the wrong place.


### 1.4.2 — 2026-08-22

**The most important thing in this release: if you run the 6amMart code exactly
as it comes from CodeCanyon, the panel could not take you from a zip file to a
serving shop.** Three separate stops on that one path, plus a websocket setting
that named an address the server never used, and a database-clock gap the panel
now tells you about instead of quietly widening.

### Getting a stock CodeCanyon shop online

- **"Automatic install" no longer promises something your code cannot do.** The
  automatic option needs a command that our optimised 6amMart ships and the
  stock CodeCanyon code does not. The panel offered it anyway — already
  selected, described as "the panel does everything" — and then failed eight
  steps into a fourteen-step job, *after* it had deleted your 190 MB upload and
  spent six minutes installing dependencies, telling you to start over and pick
  the other option. It now looks at the code you just uploaded, before any of
  that, and if the command is not there it finishes with the browser wizard and
  says so in the log. Nothing is lost and nothing has to be re-uploaded.
- **Putting your shop into production mode no longer fails on the shops that
  need it.** The job that turns off the developer settings your code ships with
  — including the debug page that shows your database password to anyone who
  triggers an error — cleared the caches first, and one of those caches lives in
  a database table that stock 6amMart does not create until it is installed. So
  on a shop between "uploaded" and "wizard finished", the job wrote the fix
  correctly, then went red without ever loading it. It now finishes, and says
  which cache it could not clear and why. A genuine failure is still a failure.
- **Your visitors keep the "coming soon" page until your website can actually
  show them something.** The friendly holding page appeared whenever nothing was
  answering on your website's port — so the moment the website service started,
  it went away, even if every page it produced was an error. Building your
  website before installing your shop did exactly that: every page asks the shop
  for its settings, the shop is not there yet, and visitors got a bare error page
  instead. The panel now checks that your website really serves a page before
  it calls the deploy done, and if it cannot, it stops it again so visitors keep
  the "coming soon" page — and tells you which of the two reasons it was.

### Live order tracking

- **The websocket settings written into your app now match what actually runs.**
  Every project's settings file said the live-updates server listens on all
  network addresses, on port 9006. On this server it listens on the local
  address only, on a port allocated per project — so on a server with more than
  one shop, the file named the wrong port as well as the wrong address. Nothing
  was affected while the panel ran it, because the panel passes the real values
  directly. It mattered the moment anyone started that server by hand to look at
  a problem: it would then have opened a *public* port, unencrypted, that no
  certificate covers and nothing else on the server points at. Existing servers
  are corrected automatically on update.

### Your database's clock

- **The Database page now tells you that your database and your shop disagree
  about what time it is.** They do, on every server: your shop runs on the
  timezone set in your 6amMart admin panel, and the database runs on the
  server's own clock. Almost nothing is affected — your shop writes and reads
  its own dates with the same clock — but a small number of columns are filled
  in by the database itself, and one of them is what "trending searches" reads.
  On a shop east of about +05:30 that six-hour window works out at nearly zero,
  so trending search quietly shows random categories instead. The new card names
  the exact columns on *your* database, what the gap costs, and — deliberately —
  offers no button, because changing the database's timezone would silently
  re-label every date you have already stored. An order placed at 21:28 on the
  29th would start reading as 02:58 on the 30th, every daily report would move
  with it, and nothing would look broken.
- **The timezone step no longer tells you the database will catch up on its
  own.** It said so, and it was not true on this server — that sentence dated
  from the Docker version of SixPanel, where it was.

### Also in this release

- **A file inside an uploaded zip can no longer publish something it does not
  contain.** A shortcut entry in a deploy archive was being restored and then
  followed by the web server, so one entry could serve any file the web server
  can read at an address on your own shop's domain. Deploy archives are now
  refused if they contain one.
- **Nothing was rotating your application's log file.** On an idle demo shop it
  reached 41 MB in five days. Every project's Laravel log is now rotated daily
  and compressed, including projects created later.
- **The disk breakdown adds up.** It accounted for 4.79 GiB of 21.17 GiB used,
  counted your uploads twice, named only one of two storefronts, and never
  mentioned the 5.34 GiB build cache or the 2 GiB swap file our own installer
  created. It now covers the disk, and offers the large reclaimable items.
- **"This backup can be restored" now means all of it was checked.** The restore
  test proved one of the three things it reported on.
- **Health, services and the file manager say what they actually did.** Stopping
  PHP on one project's card stopped PHP for every project on the server; an
  action on a shared service reported itself as project-scoped; the file manager
  created entries owned by root inside project folders; the health page claimed
  a completeness it did not have; and `doctor` ignored which project you asked
  about while other commands exited with an error and no message.

- **Your deploy now actually reaches your website.** PHP is told, for speed, to
  never re-read a file it has already loaded — which means the only thing that
  makes new code run is restarting PHP, and the deploy did not do it. So
  `Deploy` pulled your new code, ran your database changes, rebuilt the caches
  and restarted the background workers, and your site carried on serving the
  old code. Your queue worker and your website were running two different
  versions of your shop. Measured on our test server: a file changed on disk
  kept serving its previous contents on every request, indefinitely, until PHP
  was restarted.
  The same was true of **rolling back** — the thing you reach for when a deploy
  has broken your shop — which quietly did nothing to what visitors saw. And of
  **activating your CodeCanyon licence**: the panel wrote the activation, said
  it had worked, recorded it in your activity trail, and your admin panel
  stayed locked, because the running site never re-read the file. Uploading a
  zip was the one path that already did this correctly; now all of them do. If
  activation cannot restart PHP it now tells you so instead of claiming success.
- **After an update, the panel tells you its real address again.** On a server
  whose panel has its own domain, direct address-and-port access is switched
  off — and the closing lines of an update printed the address-and-port URL
  anyway, told you to open a firewall port you do not need, and warned about a
  certificate warning you will never see. Following it looked like the update
  had broken your panel. It now prints the domain you actually use.
- **German, Spanish and Portuguese now say what a button will do.** Three of the
  lines that appear before an action — "your project AND this panel go offline
  for 60 to 90 seconds, no orders are lost", and the two like it — had been
  reduced to bare labels in those three languages: "Server restart". So the
  warning and the reassurance were both missing at the moment you needed them.
  Arabic, Bengali, French and Indonesian already had the full sentence.
- **Your server's files belong to your server again.** Every file SixPanel
  installs was arriving owned by a user account from the machine the release is
  built on — a user that does not exist on your server — including SixPanel's
  own command line and installer. Nothing could be written by anyone who could
  not already write anything, so nothing was at risk; it was simply wrong, and
  it is corrected on updating servers as well as new ones.

**The thing that installs an update is now checked before it is allowed to run,
and nothing can quietly change which key your server trusts.**

- **Your server now verifies the installer itself, not just the release.**
  Every SixPanel release is signed, and your server checks that signature
  against a key it pinned when SixPanel was installed. But the small script
  that fetches and unpacks a release — the installer — was fetched over the
  network and run as root without being checked at all. It was trusted because
  it arrived over an encrypted connection, and an encrypted connection only
  proves who you are talking to, not that what they said is genuine. Signing
  exists for the day the download service itself cannot be trusted, and this
  was the one step it did not cover. The signed release record already carried
  the installer's fingerprint; your server now reads that record first, checks
  the installer against it, and refuses to run anything that does not match —
  printing both fingerprints so it can be reported.
- **Nothing can replace your server's pinned key except a proper replacement.**
  The installer used to overwrite that key with whichever one it happened to
  carry, every single time it ran. That meant anyone able to serve you a
  modified installer could hand your server a release signed with a key of
  their own *and* leave that key in place, so that nothing afterwards would
  ever object. Now the key on your server wins: a release is checked against
  it, and it is only ever replaced by a new key that arrives signed by the key
  being replaced. A first install has no key yet and still works exactly as
  before.
- **An installer you saved a while ago still works.** As a side effect of the
  above, an older copy of the install command no longer refuses to run after we
  replace a signing key — your server's own key is what decides, so the release
  still verifies. It tells you the copy is out of date rather than stopping.
- **A first install no longer reports failure after succeeding.** In one narrow
  case the installer's very last line could end a completely successful install
  with an error and advise a retry that was not needed.

**One thing worth saying plainly:** if your server is on an earlier version, it
will take *this* update through the old, unchecked path — that is unavoidable,
because the check ships inside the update it is checking. From this release onward
every update your server applies is verified before it runs.

- **The "restore everything" button on the Backups page could not be pressed.**
  If you had visited one of your projects earlier in the session, the Backups
  page remembered it and sent the restore to that project instead of to the
  server — and per-project restore is not built yet, so it refused. The only way
  to find out was to type RESTORE into a red confirmation box and watch it fail.
  The button now does what it says. The dialog also tells you, before you
  confirm, what a restore actually puts back: a backup holds every project on
  the server, and restore puts back the main one. On a server with more than one
  project it says so, in all seven languages.
- **The dashboard's app-error headline was blank.** The card said "errors in the
  last 24 hours" and then showed nothing, on a server whose health check was
  counting eleven. The number was being dropped on its way to the page. It is
  the fix in this release most worth glancing at after you update: open the
  dashboard and the error card should show a real count, or a zero.
- **Uninstalling SixPanel left services running.** The uninstaller counted a
  service template — a blueprint, not a running thing — as a service it had
  switched off, and stopped short. Measured on our test server: it was reaching
  31 of the 36 things it should have, and the five it missed included a
  database cache per shop and two services for a project nobody had opened since
  the machine last booted.
- **Five phrases showed in English in every other language.** They had been
  filled in with the English text so that nothing was missing, which is the
  right thing for a check and the wrong thing to ship — including the dashboard
  error card, which had been translated and went back to English. All seven
  languages have them properly now.
- **The replacement of our release signing key can now actually happen.** Every
  update your server accepts is checked against a key pinned when SixPanel was
  installed, and a key that can never be replaced is a key you are stuck with.
  Replacing one requires the new key to arrive signed by the old one, and three
  separate pieces of that were missing — the download service had no address for
  the signature, never published it, and the `sixpanel server update --check`
  command had no notion of a replacement at all, so it would have reported a
  perfectly good server as tampered with. All three are fixed and the whole path
  is now tested end to end against a throwaway key. Nothing changes for you: your
  server still refuses any release that is not signed by the key it already
  trusts, and it will only ever accept a new key that the old one has vouched
  for. Neither we nor anyone who took over the download service can hand your
  server a key it did not already have a reason to trust.
- **Your website build no longer runs with a "continuous integration" switch
  set.** It had been added to make build logs quieter, which is not what it
  does — it changes how the build tools themselves behave. Measured on the same
  project with nothing else different: with the switch on, a build missing part
  of its toolchain stops instead of repairing itself, and the build prints one
  extra advisory line rather than fewer. No shop was harmed by it, and it is gone
  because a flag whose effects were not known has no business in the step that
  builds your shop.

**If you run the 6amMart code exactly as it came from CodeCanyon, this release
is the one that matters.** Four things were broken specifically for you and
worked only for people running our modified version of the code. SixPanel had
never been tested against a plain CodeCanyon shop end to end; now it has.

- **Your admin panel was locked and SixPanel never mentioned it.** 6amMart
  checks its CodeCanyon licence before it will show any admin page. Signing in
  worked — and then every single admin page bounced straight back to an
  activation form, on a shop SixPanel had just reported as successfully
  installed. SixPanel now asks for your CodeCanyon purchase code and completes
  the activation for you, from the **Deploys** page. It says plainly what
  happened: activated, refused (with the address it was refused for), or "the
  licence server did not answer, so 6ammart has let you in for now and will
  check again within a day". Your code is kept on your own server, in a
  root-only file outside the app, so you can re-activate in one click when you
  move the shop to a new address — it never appears in a log, in the activity
  trail or in any page the panel serves. Your storefront is licensed separately
  by 6ammart, and if that one is not activated your shop's home page loads and
  shows nothing; the same screen activates it.
  Two smaller things went with it: activating a shop, or turning a module on in
  the admin panel, used to make SixPanel refuse every future update ("local
  changes present"), and an update or a rollback could throw the activation away
  and lock you out again. Both files are now kept safe across updates,
  rollbacks and zip uploads.
- **Your storefront could only be installed from a git repository — and you have
  a zip.** There was no way to get the customer website onto your server from
  the CodeCanyon download at all, so its address answered "502 Bad Gateway"
  forever. You can now upload the website zip on the **Deploys** page, and a
  newer zip later the same way. Upload the whole download if you like: it
  contains the site and a "changed files" folder next to it, and the panel takes
  the complete one and says which it skipped. Everything is built on your own
  server — there is nothing to build on your computer.
  And while the storefront is not there yet, its address no longer shows a bare
  error: it serves a short page saying the shop is not open yet and where to go
  next, which disappears by itself the moment the site starts.
- **Your shop was running in the developer mode 6ammart ships with.** The
  settings file that comes with the code is meant for a programmer's laptop, and
  SixPanel copied it as-is. On a real shop that printed the login page's
  security-code answer into the page for anyone to read, turned off certificate
  checking in one payment gateway, and — because of a mistake in 6ammart's own
  installer — put your payments on your gateways' TEST credentials while
  everything looked normal. A debug error page could also show your database
  password to whoever triggered it. New installs are now set up for production
  from the start. **If your shop is already installed, open App .env: a banner
  at the top lists exactly what is wrong and fixes it in one click.**
- **Every add-on module's styling and buttons were missing.** 6ammart's pages
  ask for their modules' stylesheets and scripts at an address that only works
  on the folder layout shared hosting uses. SixPanel serves your site the safer
  way, which put those files out of reach — so on a plain CodeCanyon shop
  *every* admin page was missing a stylesheet, and module screens lost their
  buttons and icons. They are now linked into place for whatever modules you
  have, including one you turn on later, and nothing else in the module folders
  becomes reachable. Updating applies this by itself the next time the panel
  starts.

**Read this one.** Several of the fixes below are about things that were quietly
wrong on every server rather than visibly broken on any of them, and the first
one needs a minute of your time after you update.

- **Your backups did not contain your database. Take a fresh one after you
  update.** SixPanel dumps your database, hands the dump to the backup tool, and
  tells the tool to skip the folder the dump is written into — a folder that also
  holds half-finished uploads and the scratch space a restore works in. The
  "skip" applied to the dump as well, so the backup tool stored the folder and
  nothing in it. Every snapshot still held your uploads, your settings, your web
  server configuration and your certificates, and the Backups page still said the
  backup had finished and told you how large the repository was. Measured on our
  own test server: six snapshots, one of them a database-only backup, 10,888
  files each, and not one database among them.
  The dumps now live somewhere the skip cannot reach, and a check that holds the
  two lists against each other runs before every release, so this cannot come
  back silently. **After updating, open Backups and press "Back up now", then
  press "Test my backup now" and read the result.** The test is the part that
  matters: it loads the newest backup into a temporary copy of your database,
  counts the rows and deletes it again, and it is what found this.
- **Your customer website was reachable on a plain, unencrypted port.** The
  storefront listens on a port that only SixPanel's web server is supposed to
  reach, and it was accepting connections from anywhere instead. Anyone who knew
  your server's address and tried that port got your shop over plain HTTP —
  around the certificate, around the request limits, around the page cache and
  around the security headers. Nothing needed that; every part of SixPanel that
  talks to the storefront talks to it over the machine's internal address, which
  is what the install log has always said it was doing. It now listens only
  there. The update applies this by itself the next time the panel starts; you do
  not need to do anything.
- **The file manager's "Compress" button never worked.** The tool it runs was
  not among the packages SixPanel installs, so it failed with a line of
  programmer's shorthand. The package is installed now, on updating servers as
  well as new ones.
- **A non-English panel opened in English.** The first page load of every new
  browser session put the whole panel into English while keeping your own
  language's layout around it — right-to-left for Arabic, with English words
  inside it. Reloading fixed it, which is why it survived this long. Measured on
  clean browser profiles: 8 of 12 first loads were wrong before, 0 of 14 after.
  Three pieces of copy that had drifted are fixed with it, including a Spanish
  confirmation box that said the whole server would restart when the English one
  says your shop stays open, and a German backup schedule that showed times that
  were not the ones being used. The backup-password card no longer changes
  language halfway down.
- **The optional "www" address a new project offers now uses the right
  hostname.** On a Cloudflare domain the panel shortens names so they can stay
  proxied, and the create form was not doing the same shortening as the server.
  The result was a www address that had a certificate but no DNS record, and a
  DNS record with no certificate — so anyone typing it got an SSL error, and
  nothing anywhere reported a problem.
- **The disk is described the same way everywhere.** The dashboard, Server →
  Health and Server → Resources were giving three different answers for one
  disk, and the headline on Resources overstated free space by 4 GB. They now
  all use the same measurement. The "Database files" row was also missing from
  "where the space goes" entirely — it was being measured at a path from the
  Docker version of SixPanel — so on a 15 GB-used server the breakdown accounted
  for less than 4 GB and did not say the rest was unmeasured.
- **The dashboard's app-error count is shown again**, and labelled with what it
  actually counts. It was reading a field the server does not send, so the chip
  never appeared at all.

- **"Check this server" no longer reports a failure you cannot fix.** A project
  you have created but not yet installed an app into has a queue worker that
  correctly does nothing, and `sixpanel doctor` was calling that a failed
  service and telling you to start it — which could not work, because there is
  nothing to start until the app is there. It now says the project is waiting for
  its app, and `sixpanel status` says so too instead of reporting the worker as
  dead.

**The panel and the installer now size your server the same way.** They were
supposed to already — both were written from the same measurements, and each
carried a note saying to keep them matching. They did not match. Running both
across 36 combinations of server size and project count produced 66 different
answers.

- **Settings → Auto-tune was offering changes your server did not need.** On a
  server with one shop it always offered to change the database's open-table
  cache, whatever the server was already running. On a server with several
  shops it offered two or three times as many PHP workers as the install had
  chosen. And on a server with 10 GB of memory or more it offered to **shrink
  the database's transaction log** — a setting the installer had deliberately
  sized larger, and one that SixPreflight, our own server grader, would then
  have marked down. All three are gone: the suggested column is now the same
  calculation the installer used, so on a server whose hardware has not changed
  it says there is nothing to do.
- **The PHP worker count on a multi-project server was settled by measuring
  it.** The panel's reasoning was that a shop that is busy while its neighbours
  are idle should be allowed to use the whole machine. On a two-processor server
  with three shops, giving the busy one 16 workers instead of 4 served **no more
  requests per second at all**, made the slowest one page in a hundred 57%
  slower, and used 193 MB more memory. Four workers already keep two processors
  busy; the rest only take turns. The install's answer was right and the panel
  now agrees with it.
- **The database's open-table cache on a single-shop server goes from 2048 to
  4096.** The generated tuning file was writing a *smaller* number than the
  baseline file SixPanel ships alongside it, and the generated one wins. This is
  the one setting that changes on a server that is already running; it costs
  about 2 MB and is applied by the normal update, which checks the file before
  the database is asked to use it and restarts the database only because a
  number really changed.
- **Two database settings are now recorded where you can see them.** The log
  buffer and the open-table cache were calculated and written into the
  database's configuration but never written into the server's settings file, so
  they were the only two the panel had to guess at when it showed you "current",
  and the only two a re-install could quietly lower.
- **"Queue workers" is gone from the tuning table.** It was left over from the
  Docker version of SixPanel, where it decided how many queue containers ran.
  Here each shop's queue is a single service and nothing on the server reads
  that setting, so the row offered a change that only ever edited a line in a
  file.
- **If a tuning change would lower something, the job now says so first.** The
  installer only ever raises these numbers, so anything the panel lowers stays
  lowered — worth knowing before you press the button, not after.
- **Nothing else moves on a server that is already running.** The PHP workers,
  database memory, transaction log, cache budget and listing budget your server
  was set up with are all kept as they are.

**Updating now gives you the whole release.** Until this version an update
delivered the new panel and a small part of everything else. Three releases in
a row shipped work that only a *freshly installed* server ever received, and
each one was found by accident rather than by a test. This release closes the
whole class and adds a check that refuses to build a release which reopens it.

- **The `sixpanel` command line was never updated on a server installed from
  the published link.** Not "sometimes" — never, on any of them, for as many
  releases as the server lived. The update looked for the installer in a place
  that kind of install does not have, decided there was nothing to run, and
  wrote a line in the log saying the command line was behind. It matters
  because the rescue commands — reset a password, reset the entry code, turn
  off two-factor, clear the allowlist, unlock — are all command-line commands,
  and they are what you reach for when the panel itself will not let you in.
  Now the command line is replaced during the update, and by the version being
  installed rather than the one after it.
- **`sixpanel version` was reporting a number that was not the command line's.**
  It read the version of the folder it points at, so a command line several
  releases old still printed the current number and the "these do not match"
  warning could never appear. It now reports its own, and says "unknown" rather
  than guessing.
- **Your server's settings are brought up to this release too.** An update now
  applies the web-server and PHP settings, the database tuning and its sizing
  numbers, the pool your site's PHP runs in, the shared location rules every
  site includes, the failure alerting, the panel's own service definition and
  the server-level tuning — all of which previously only ever arrived on a
  fresh install. A server that has been updated for months and one installed
  today now end up the same.
- **It is careful about it.** Anything a service has to read is checked before
  that service is asked to use it — the web-server config and the shared
  location rules are validated together and put back together if either is
  bad, and the database config is parsed before the database is restarted.
  The database is restarted only if something actually changed, so an update
  that changes nothing for it no longer costs you a database restart.
- **An update will not upgrade software you already have.** It installs only a
  package this release newly needs and your server is missing. Nothing already
  installed is touched, so an update cannot restart your web server or database
  for a reason the release did not ask for. It also never rewrites your
  database passwords.
- **The old `certbot` renewal timer is switched off on servers that only ever
  updated.** SixPanel has been the single certificate-renewal driver since
  1.4.1, but the step that turns the distribution's own timer off ran only on a
  fresh install, so updated servers had both running.

- **Services & Logs drew the cache row as "not created".** The page asked for a
  row per project cache and the server never filled it in, so a running cache
  looked like one that had never been made — with a Start button that would
  have done nothing. It now shows its real state, with Live logs, Start,
  Restart and Stop, per project.
- **The server dashboard stopped calling the cache a shared service.** Its
  status strip listed one dot for "redis" alongside the web server and the
  database. There is no server-wide cache any more, so that dot was reporting
  the first project's private one as if it spoke for the whole machine.
- **Stopping a project's cache now sticks.** Stop it on Services & Logs and it
  stays stopped — through a panel restart, through an update, through an
  installer re-run — exactly like that project's queue worker and websocket
  service already did. A brand-new project still gets its cache turned on for
  it; nobody has to remember to.

- **The old shared cache service is stopped once nothing is pointed at it.** A
  server with no shop installed yet would otherwise have kept an unused cache
  service running for ever, so a freshly installed server and an updated one did
  not end up in the same state. It is left alone the moment anything still uses it.

**If you run more than one project on this server, update now.** Your shops
shared one cache, and sharing a cache turned out to mean sharing secrets.

- **One project could read — and change — every other project's cache.** All
  the shops on a server used one cache service behind one password, and that
  password has to sit inside each shop's own settings file for its own site to
  work. So anybody with access to one shop had the key to all of them.
  Measured on a real two-project server, starting from nothing but one
  project's Linux account: the other shop's **mail password, Firebase
  credentials, Google Maps keys, SMS gateway key, reCAPTCHA secret and two
  payment gateways' secret keys** were all readable, along with everyone's
  signed-in sessions — and writing was allowed too, which means the other
  shop's saved mail settings could have been replaced.
- **Every project now has its own cache service.** It listens on a file inside
  a folder only that project's Linux user may open, so another project is
  refused by the operating system before it can even offer a password — and it
  has its own password as well. Re-run on the same server afterwards, every
  attempt was refused, in both directions, even when the test was handed the
  target's real password on purpose.
- **Updating does the move for you, and it is not disruptive.** Your cache is
  copied across before the switch, so nothing starts cold, and **nobody is
  signed out** — verified on a live shop by holding a real browser session open
  right through the update. On the server this was measured on, 46 cache
  entries moved in 14 milliseconds.
- **The cache no longer empties itself when you update 6ammart.** 6ammart's own
  "update the software" step rewrites a setting the cache keys were built from,
  which quietly threw away the whole cache and signed everyone out every time
  it ran. The panel owns those key names now, so that stops happening.
- **The memory limit is now per project, and the panel divides it for you.**
  The server has one cache memory budget — six per cent of its RAM. Adding a
  project divides it instead of multiplying it, so a shop's cache can never
  promise memory the machine does not have; removing a project hands the share
  back. It is applied without restarting anything. On a 4 GB server that is
  245 MB for one project or 81 MB each for three.
- **A related limit was set wrong and is now right.** The share of the cache
  the product-listing cache may use was allowed to be *larger* than the cache
  it has to fit inside — on a three-shop server, 64 MB of listings inside a
  78 MB cache — which defeated the whole point of capping it: stopping a flood
  of search results from evicting people's logins.
- **"Restart the cache" now restarts only yours.** Services & Logs, Health, the
  dashboard, the command line and the automatic self-healing all speak of a
  project's own cache. Before, one shop's cache going quiet made the panel
  restart the cache for *every* shop on the server.
- **The fifteen-project ceiling is gone.** Projects used to be handed one of
  sixteen numbered slots in the shared cache, and the sixteenth project was
  refused. There are no slots any more.
- **Nothing changes for the plain CodeCanyon 6ammart code**, which keeps its
  cache in the database and its sessions in files. Measured rather than
  assumed: with that project's cache service stopped entirely, its pages
  answered in exactly the same time.

**Also for servers running more than one project:** one fix, and one answer to a
question about upload sizes.

- **A project's background services were talking to the FIRST project's
  database.** Every project has its own queue worker, scheduler and websocket
  service. Those three were being started with the first project's database
  name, user and password already in their environment — and the framework
  6ammart is built on never lets a project's own settings file override
  something already set that way. So on a server with two or more projects, the
  second project's queued work (emails, notifications, exports, scheduled
  tasks) was reading and writing the FIRST project's data, and its own queue
  never ran at all. Measured on a two-project server before the fix: a job put
  in the first project's queue was picked up and run by the second project's
  worker, and the second project's own jobs sat untouched. After it, each
  project's worker answers with its own database, works only its own jobs, and
  leaves the other project's alone.
- **It hit the plain CodeCanyon 6ammart code hardest** — which is what most
  people run. Our optimised build caches its settings at deploy time and so
  never re-read the wrong ones; the unmodified code cannot cache them (that
  would kill live order tracking) and so read them on every single start. If
  you have been running more than one project, it is worth looking at the first
  project's failed jobs after updating.
- **Nothing to do by hand.** Updating applies it, and the panel restarts only
  the services whose definition actually changed. No data is touched, and the
  first project on a single-project server behaves exactly as it did before.
- **The panel's own passwords are no longer handed to your shops.** The same
  environment carried SixPanel's admin password and the database root password
  into every project's background services, where any queued job could read
  them. They are gone from there.
- **"My image will not upload" now has a real answer.** A report said the
  server was silently dropping anything over a couple of megabytes. It is not:
  measured on a live install, a 50 MB upload reaches the application intact,
  and the same is true on the unmodified CodeCanyon code. The ceiling is
  6ammart's own rule — 2 MB as it ships from CodeCanyon, 5 MB on our optimised
  build — and no web-server or PHP setting moves it. The Troubleshooting page
  now says exactly that, with the one command that reads the number off your
  own server. Nothing about the serving stack was changed, because there was
  nothing there to change.

**A second wall around your shops' PHP. Nothing to do, nothing gets slower.**

- **PHP can no longer read its way around your server.** Until now, if
  something got into one of your shops — through a plugin, a theme, an upload —
  it could not touch any other shop's files, but it could still *read* a lot
  about the machine: the settings SixPanel writes for every site on it — which
  is the list of every domain on this server — SixPanel's own program files,
  the shared temporary folder with whatever other programs had left in it, and
  the command line of every other program running. No passwords were ever among
  them, but it is a map, and it was free to take. From this release PHP starts
  inside its own view of the server where the whole disk is read-only except
  the folders your shops actually write to, those files are simply not there,
  and its temporary folder is its own.
- **And it costs nothing.** The usual way to do this is a PHP setting called
  `open_basedir`, which some other panels use. It was measured on this exact
  application first: it makes every request 17 to 23 milliseconds slower,
  forever, because PHP stops remembering where files are and looks them up
  again on every include. The way SixPanel does it is set up once when PHP
  starts, so the measurements before and after are the same to within the
  normal run-to-run wobble.
- **New shops are covered the moment they are created**, including ones added
  months after the server was set up — proven by creating a shop after the
  change was live and watching it write. If you have moved a folder onto a
  second disk by hand, the Troubleshooting page has the one command that tells
  SixPanel to look again.
- **phpMyAdmin, uploads, invoices, exports, queued jobs and logins all keep
  working.** Each was exercised rather than assumed: a real image uploaded
  through the admin panel and fetched back from the site, a log line written
  from a live request, a queued job dispatched from the web and worked off, a
  cache rebuild, and a login followed by an authenticated page.
- **Health has a new row that can see what the old one could not.** "Storage
  folder writable" asks the question from a command line, which is outside the
  confinement — so it can say "writable" while the PHP serving your site is
  looking at the same folder read-only. The new row compares what PHP is
  actually running with against what this server needs, so if an update ever
  lands without being switched on, the panel says so instead of you finding out
  through a failed upload.
- What deliberately stays readable: the machine's user list, PHP's own pool
  directory, and this server's nginx configuration. Linux needs the first to
  turn a user id into a name, PHP needs the second to know what to run, and
  SixPreflight reads the third to report your upload limit and compression
  settings. None of them holds anything private, and all three are read-only.


### 1.4.1 — 2026-08-21

**A correctness fix in the response cache. Update this one.**

- **Shops with more than one delivery zone could be shown another zone's
  modules.** The list of modules your app asks for changes depending on which
  zone the customer is in — and the server's cache was not treating those as
  different questions. So a customer in one zone could be handed the answer
  built for another: the wrong service list, briefly, until the entry expired
  five seconds later. Fixed, and proved with a before-and-after: the same
  request in two zones now keeps two separate answers where it previously
  returned one zone's bytes for both. This affected signed-out visitors as
  well, and it predates the widening of the cache described above.
- **Two pages were removed from the shared-response list.** One of them changes
  its answer depending on filters the cache was not looking at. Neither was
  actually being cached, so nothing gets slower — but they should never have
  been on the list, and now they cannot be.
- **The safety check is no longer something someone has to remember.** A page
  can only be served from one customer to another if it provably returns the
  same bytes to everyone, and a release now refuses to build if that is not
  demonstrably true — checked against both the untouched 6amMart code and our
  optimised version, so a future 6amtech update that makes a page personal
  stops the release instead of quietly leaking.
- All 26 remaining shared pages were re-checked by fetching each one as two
  different signed-in customers and requiring identical bytes, including six
  that previously had no data behind them to compare.

**This is what makes the speed work above real on a server that updates rather
than installing fresh.**

- **Updates now switch on the settings they bring.** A SixPanel update carries
  improvements to how your server serves pages, and until now those arrived on
  disk and were never applied: the server kept running the settings written the
  day it was first installed. So an update could report success, show the new
  version, and change nothing about your shop's speed. Updates now apply them,
  checking the new settings before switching over and putting the old ones back
  if anything is wrong — without dropping a single request.
- **The panel now tells you when your server is behind its own build.** Because
  an update is run by the version you already have, a server updating from an
  older release still has to be brought forward once. Health checks now say so
  plainly and give you the one command that does it, instead of leaving the
  improvements switched off and silent.

A speed release, and everything in it was measured on a real shop with 66,701
orders before it was shipped.

- **The app is dramatically faster for customers who are signed in.** Until now
  the server's response cache only helped visitors who were not logged in — the
  moment someone signs in, their phone sends a token with every call, and the
  cache stopped helping them. That was backwards: signed-in customers are the
  ones using your shop. The settings call every app makes on launch now answers
  in **0.6 ms instead of 16.9 ms**, and 27 other pages — your terms, privacy
  policy, refund policy, zone and module lists, banners — are served the same
  way instead of being rebuilt for every single request.
  Anything that genuinely differs per customer is still built fresh for them,
  every time; that boundary is checked by a test that fetches each page as two
  different customers and refuses to ship if the answers differ.
- **A way to knock your shop's cache out has been closed.** Anyone could send
  requests with made-up location headers and push everything useful out of the
  cache, putting the load straight back on your database — a few thousand
  requests were enough, and nothing in the rate limits stopped it. A page is
  now only cached once it has genuinely been asked for twice, which costs
  nothing and makes the trick pointless.
- **PHP's just-in-time compiler is on** where the server has the memory for it,
  worth about 6% across the board. It was off pending a measurement; the
  measurement is now five paired runs on a real dataset.
- Servers with less than 2 GB of memory keep the compiler off — there the
  memory is worth more than the speed.

- **The customer manual ships with the panel.** All 24 pages are readable in the
  panel and over SSH, reached by the Help link beside each feature, and a release
  can no longer be built without them.
- **Bot fight mode is now your choice, not a recommendation.** Cloudflare
  cannot aim it at part of your site — not from this panel, and not with a rule
  you add yourself — so it also sees the calls your customer, store and rider
  apps make, and the call your payment provider makes to confirm a paid order.
  Those callers cannot answer the challenge it sends. "Set this up for me" no
  longer switches it on; the page explains what it would cost and leaves the
  decision to you.
- **Your panel's own address is protected like everything else.** It was being
  left out of the orange-cloud check, on a reason that stopped being true when
  the live job log started sending a keepalive. The one address on your server
  that answers with a login is now covered by the same rule as your shop.
- **Alerts: the settings page names the address that actually receives them.**
  It used to show your account address, which is not where alerts are sent — so
  changing it did nothing. It now shows the real recipients.
- **The firewall page stops guessing about port 80.** It warned every owner
  that closing port 80 would expire every certificate on the server in about 90
  days. If your certificates renew through Cloudflare's DNS, that is simply not
  true. The page now reads your own certificates and tells you which case you
  are in.
- Setting up a dedicated address for live updates no longer asks you to create
  a DNS record by hand — the panel makes it for you, always behind Cloudflare's
  proxy.

**The first no-Docker SixPanel release.** SixPanel runs 6amMart directly on
Ubuntu 24.04 — nginx, PHP-FPM 8.3, MariaDB 10.11, Redis and Node from the
distribution archive, managed by systemd. There are no containers anywhere in
the running stack, which is what makes it fast on a small VPS: nothing is
virtualised, nothing is proxied through a container network, and the database
talks to PHP over a unix socket.

- **Several shops on one server.** Each project gets its own unix user, its own
  PHP-FPM pool, its own database, its own queue worker, scheduler and websocket
  server, and its own hostnames. One project cannot read another's files.
- **Domains and HTTPS without the guesswork.** Type your domain and the panel
  plans the rest: it creates the DNS records on Cloudflare (always proxied, so
  your server's address is never published), issues real Let's Encrypt
  certificates — through DNS-01 when Cloudflare is connected, so it works even
  with the orange cloud on — writes the nginx configuration and renews daily.
- **Install and update your shop from the panel.** Install from git or from a
  zip, see exactly what a update would change before it runs, one-click
  rollback, and optional push-to-deploy.
- **Backups you can actually restore.** Encrypted snapshots to this server, S3
  or SFTP, a scheduled test-restore that proves they work, and the backup
  password is yours to see, change and copy out at any time.
- **The panel tells you when something is wrong.** Health checks that ask the
  app whether it really answers, watch certificates, disk, queue and scheduler,
  and email you when something breaks — plus SixPreflight, the deeper
  check-up of the shop's own settings.
- **Your panel, your address.** Serve the panel on your own domain with its own
  certificate; direct IP access switches itself off once the domain works.

The three entries below are this product's own earlier development milestones:
internal builds used in testing, never served to anyone and not installable now.
Their dates say when the work happened and nothing more. SixPanel Docker is a
separate product line with its own changelog and its own numbering; nothing in
this file refers to it.



## SixPanel 1.3 — development milestones, never served to a customer

### 1.3.0 — 2026-07-27 (development milestone, not published)

Development milestone, in testing only. The last of the pre-release rounds: the
product was far enough along to be driven end to end on real servers rather than
reasoned about, and what remained was proving it behaved the same way twice. This
build was never published and nobody received it.



## SixPanel 1.2 — development milestones, never served to a customer

### 1.2.0 — 2026-07-06 (development milestone, not published)

Development milestone, in testing only. The middle of the work, where the parts
began to be tested together rather than one at a time. This build was never
published and nobody received it.



## SixPanel 1.1 — development milestones, never served to a customer

### 1.1.0 — 2026-06-22 (development milestone, not published)

Development milestone, in testing only. Early development: the shape of the
product being settled and the first pieces made to run. This build was never
published and nobody received it.


