Changelog

What's New

New features, improvements and fixes in every release. Latest: Solo 1.19.1 (November 2, 2026), Agency 1.34.4 (November 2, 2026).

Solo Community and Solo Full

v1.19.1 security November 2, 2026

Fixed

  • Adding a site that still lives on another server no longer splits its visitors. With Cloudflare linked, adding a domain whose A record still pointed at the old host left that A alone (correct) but published an AAAA to this server, so IPv6 visitors reached the new, empty site while IPv4 stayed on the old one. The AAAA is now held back until the A is this server's.
  • Upgrades no longer pile up old release downloads. Every upgrade left its release archive in the backups folder and nothing removed it (27 archives, 2.2 GB on one server). Upgrade now keeps the newest two.

Security

  • Older servers get a host firewall and a private panel API on upgrade. Servers installed before the current installer kept the panel API (port 3090) listening on every address, so it answered from the internet past Nginx, its WAF and rate limits, and they never got ufw, so every port was open. Upgrade now binds the API to 127.0.0.1 and, when ufw is missing or off, installs and enables it with the installer's rules (SSH, web, panel, mail, FTP, DNS; incoming denied otherwise). The reference config example said 0.0.0.0 too; fixed. Found on host.amirapanel.com.
v1.19.0 feature November 1, 2026

Added

  • See what each app, container and service uses (Monitoring → Apps & services). The panel now records every minute how much CPU, memory and network each Docker container (including Git/Dockerfile apps and Compose services) uses, plus your sites' PHP, Node.js, Python and other apps, and the shared services (Nginx, PHP-FPM, MySQL, PostgreSQL, mail, the panel). Monitoring shows CPU and memory by kind right now and over 1 hour, 24 hours, 7 days or 30 days, the top consumers with a trend line, and every container against its memory and CPU limits. Click a row for its own history (CPU, peaks, memory and, for containers, network). The dashboard gets a What uses the server card with the top three. The same view as Amira Pro's Apps & accounts. Minute samples are kept 48 hours and hourly averages 30 days. Needs the new database migration (applied by the upgrade); no new permissions on the server.
v1.18.5 bugfix November 1, 2026

Fixed

  • Two-factor authentication can be switched on. Setup 2FA (Account → Security, and the 2FA-setup screen) failed with "Unknown error": the page posted an empty body that the server rejected ("EOF while parsing a value") before generating the QR code. The server now accepts an empty body and the page sends {}.
  • You can find where to change your password and turn on 2FA. The Account page (password, two-factor, sessions) had no link anywhere in Solo; the user menu at the bottom of the sidebar now has Account & security. (It was only reachable by typing /account.)
  • Backups to S3-compatible storage (Cloudflare R2, AWS S3, Wasabi, MinIO) work. The panel uploads with the AWS CLI, but no installer ever put it on the server (Ubuntu 24.04 has no awscli package), so every remote S3 backup failed with "failed to run aws CLI: No such file or directory". Install and upgrade now add the official AWS CLI v2 (pinned version, checksum checked).
  • "Test connection" for an S3 destination no longer fails on a working bucket. It ran aws s3 ls --max-items 1, which the AWS CLI rejects; it now lists a single key with s3api.
  • Large backups to Cloudflare R2 no longer fail with "InvalidPart". Recent AWS CLI versions add checksums R2 does not accept on multipart uploads; the panel now sends only the checksums the storage asks for.
v1.18.4 bugfix November 1, 2026

Fixed

  • Apps and Docker containers accept up to 200 environment variables (was 50). Real applications carry more: the Ohlom API has 77, and creating it was refused with "Maximum of 50 environment variables allowed".
v1.18.3 bugfix November 1, 2026

Fixed

  • Docker apps built from a Git repository start again. A container built from your own Dockerfile ran with every Linux capability removed, so images whose entrypoint runs as root (official nginx, postgres, many Node images) exited at once — nginx with chown("/var/cache/nginx/client_temp") failed. Containers without host bind mounts now get the same minimal startup set as other root containers (CHOWN, SETUID, SETGID, FOWNER, DAC_OVERRIDE, NET_BIND_SERVICE, KILL); containers that bind-mount host folders keep every capability dropped and the build log says so. Found while moving Easypanel apps to Solo.
v1.18.2 security November 1, 2026

Added

  • WordPress Security: administrators publishing spam are flagged. The "No administrator account looks planted" check now also lists administrators who published two or more spam-like posts (loans, payday, casino, betting, pharmacy …) in the last 180 days, with an example. It is a warning to review (a real lender may post about loans); Fix removes the administrator role and keeps the account and its posts. Found on lge.la, where an administrator planted in 2025 was publishing loan spam.

Fixed

  • WordPress: installs removed by hand are marked "missing". When the daily scan or opening a site finds no WordPress at an install's folder any more, the record is marked missing instead of showing its last known version forever (two removed installs on panel.hostmts.com were still listed as active 7.1.3).
v1.18.1 bugfix November 1, 2026

Added

  • AI Security Guard: a verdict on every incident. With the AI investigator on, each report now ends with a verdict — Likely real, Likely harmless or Unsure — and one plain sentence why. Alert e-mails say the verdict is coming, and a short follow-up e-mail brings it; the AI Actions page shows it as a badge. The verdict is advice only (it never triggers or approves an action), and evidence that tries to instruct the AI is never called harmless.

Fixed

  • AI Security Guard: fewer false alarms on busy WordPress servers (from panel.hostmts.com's first night). Database "dump" alerts need a whole-table read (normal WordPress reads with a WHERE clause are ignored); a plugin update spread over a few plugins (WPML updates two at once) is not a mass file change; public certificate bundles (cacert.pem, fullchain.pem) and dated media uploads are not "exposed secrets" unless named like a backup; a mailbox's "first sign-in from a new country" needs a sign-in history that recorded countries.
v1.18.0 security November 1, 2026

Added

  • AI Security Guard — root-permission misuse (PB-19), Solo Full. Same as Amira Pro: a process that became root under a hosting account, sudo/su attempts by hosting users, setuid programs in temp or home folders, /etc/passwd, /etc/group or /etc/ld.so.preload changed outside the panel, kernel crashes in hosting processes. Alert first; suspending the account is offered as an approval.
  • AI Security Guard — container review (PB-17), Solo Full. Every 10 minutes the guard lists the running Docker containers (read-only, never their environment variables) and reports any that are privileged, hold the Docker socket, have the server's /, /etc or /root mounted, use the server's network or process list, or were not started by the panel (its Docker apps and the compose stacks it deploys for your sites). Alert only — the guard never stops a container. Switch: Administration → AI Security Guard → Sensors → "Docker containers (PB-17)" (on).
  • AI Security Guard — software update advisories (PB-18), Solo Full, off by default. Once a day, when you switch it on, the guard downloads one advisory file (nothing about the server is sent) and compares it with the installed kernel, OpenSSH, OpenSSL, sudo, nginx, PHP-FPM, mail, database and Docker packages (read locally with dpkg-query), and tells you what to update. The only automatic step: if the running kernel is affected by a problem the panel protects against itself (CVE-2026-98432) and amira-net-mitigations.service is off, it is started again (act mode, undoable; after an Undo the guard leaves it off). It never installs packages or reboots.
  • AI Security Guard — linked servers (fleet link), Solo Full. Link your own other Amira servers, Pro or Solo, under Administration → AI Security Guard → Linked servers (a one-time link code, 2FA re-check). Linked servers share indicators only — attacker addresses this guard blocked, SHA-256 hashes of files it quarantined, attack-tool user agents — signed per link, never customer data, file contents, logs or site / user names; nothing goes to AmiraTech and with no linked server nothing leaves the server. Per server you choose "send only", "receive alerts" (default) or "receive and act": received addresses then go through this server's own gate, mode and caps as undoable blocks (never this server's own addresses, Cloudflare, allowlists or your recent logins), and a new script file with the same hash as one a linked server quarantined is treated as a backdoor. Linked servers also watch each other: one that goes silent for 15 minutes, or whose guard is switched off without its owner, alerts your channels. Security → AI Actions lists received and shared indicators and the server checks. New endpoint POST /api/v1/guard/fleet/indicators (signature only, rate-limited, a Cloudflare Access machine path).
  • Migrations 20261101000000_ai_guard_phase3.sql and 20261101001000_ai_guard_fleet.sql (additive).

Changed

  • The guard's quarantine now records each quarantined file's SHA-256 (shown with the quarantine entry and shared with linked servers).

Fixed

  • AI Security Guard worker starts on servers with a tightened install folder. Where the panel's install folder was set to 0750, the guard worker (its own amira-guard user) could not run the panel program and failed with "Permission denied". Install and upgrade now give that user enter-only access (one ACL entry, or the standard 0751).
v1.17.0 feature October 31, 2026

Added

  • AI Security Guard — Phase 2, Solo Full only (ported from Amira Pro on the shared amira-guard core; the Community build contains none of it). The guard still starts in shadow mode; each new sensor has its own switch under Administration → AI Security Guard → Sensors: — Exposed secrets (PB-16): daily per site (and right after a database dump appears in a public folder) the guard lists .env files, .git folders, database dumps, backup archives, wp-config.php copies and keys in the site's public folder as the site user, and checks with the server's own request (pinned to 127.0.0.1, content never kept) whether they can be downloaded. In act mode it blocks exactly that path with a panel-managed nginx rule in amira.d/<domain>/guard-exposed.conf (location = "/.env" { return 403; }; a folder also gets location ^~ "/.git/"), tested with nginx -t before the reload and put back on failure; Undo removes the rule. Only plain file names ever reach the config. The file itself is never changed. — Website content injection (PB-13): the home page fetched locally as a desktop browser, Googlebot and a phone from Google search; new outside scripts (card skimmers), hidden links and cloaked redirects are reported, and a recently changed file proven to inject the new host is quarantined. — Backup health (PB-14): failing or missing scheduled backups, sudden size drops, completed backups deleted outside the panel or the backup folder missing. Alerts only. — DNS / SSL hijack (PB-15): the certificate nginx serves vs the one the panel installed, and expiry (local). Outside lookups (public DNS at 1.1.1.1 / 8.8.8.8, Certificate Transparency on crt.sh, RDAP domain expiry) are a separate switch, off by default — they send your domain names to those services (nothing goes to AmiraTech). When your DNS is at Cloudflare or your registrar, a change is reported with advice; only a zone this panel's own PowerDNS serves gets "restore the panel's records" (owner approval + 2FA, undoable). — New administrator / 2FA turned off (PB-10): read from the audit log and a snapshot of the administrators, so a change made outside the panel (directly in the database) is caught too. Creating or promoting an administrator and switching off your own 2FA now write audit entries. — Let the AI act on Tier A (off by default): only for the provider + model that passed every case of "Test this model", only in act mode, and only when the gate verifies the evidence itself; Tier B always waits for you. AI Actions shows "Requested by the AI, evidence checked by the gate" and a "What the sensors found" summary. — Weekly digest to your critical-alert channels (incidents per playbook, done / would-do / waiting, top incidents, harmless-looking would-do items), with Preview and Send now. — Database: 20261031003000_ai_guard_phase2.sql (additive switches). No new sudoers rules (existing nginx snippet, test and reload grants).

Fixed

  • AI Security Guard: far fewer false alarms (found when the guard was first switched on on a busy server). PHP workers and wp-cron.php working in a site folder are no longer taken for web shells or miners (only a program file that itself sits in a web or temp folder counts); photos, PDFs and other static files no longer count as data leaving; a plugin, theme or WordPress core update is not a mass file change; WordPress's empty index.php placeholder is ignored. Alerts are pushed only when the guard did something, something needs your approval, or it is critical, and at most 10 per hour; the rest is on the AI Actions page and in the weekly digest.
  • WordPress Security: distinguish review warnings from compromise. BackWPup's exact 404-only index.php guard files no longer trigger the PHP-in-uploads warning; altered files still do. Administrator-registration bursts and suspicious PHP files are labelled for review rather than called planted accounts or backdoors. Confirmation text explains the uncertainty, and extra core-file warnings now list the paths to inspect.
  • AI Security Guard: fewer false data-theft alarms on quiet sites. The database-exfiltration check (PB-8) compared a visitor's download with the site's usual traffic only, so on a quiet site a normal page view (1.3 KB) counted as a bulk download and, in act mode, would have blocked the visitor. A bulk download must now also be at least 20 MB, and a read from a users/orders table at least 5,000 rows. Dumps with INTO OUTFILE, dump files in public folders and new database users are still caught at any size.
  • Xiaomi MiMo Token Plan keys work. A key starting with tp- is a MiMo Token Plan key: it is now sent as a Bearer token to the Token Plan server (token-plan-sgp.xiaomimimo.com). Before, the panel sent it to api.xiaomimimo.com, which answered "Invalid API Key". An endpoint override (for example the China Token Plan server) still takes precedence.
  • AI Security Guard (Solo Full): findings seen in shadow mode are acted on after you switch to act. Before, a shadow "would do" entry blocked the same action forever, and lasting conditions (exposed secrets, database dumps, auto_prepend lines, planted scripts, foreign cron lines, SSH keys / units / cron entries, suspicious listeners) were reported only once ever. Now a "would do" entry only counts in the mode that recorded it, and those conditions are seen again once per mode.
v1.16.0 security October 31, 2026

Added

  • Discord notifications (Settings → Security → Notifications), every edition. A new notification channel type: paste a Discord webhook URL and alerts arrive as a severity-coloured embed, with a Send test button. The URL holds a token, so it is stored encrypted and never shown back or logged; Discord's rate limit (HTTP 429) is honoured. A Discord channel can be marked for the AI Security Guard's critical alerts + approvals like the other channels.
  • AI Security Guard — Phase 1 (contain and report), Solo Full only (Security → AI Actions, Administration → AI Security Guard; the Community build contains none of it, and a Solo Full panel without a licence keeps it idle). Ported from Amira Pro on the shared amira-guard core — the same Action Gate, playbooks PB-1…PB-12, engine loop, red-team and incident-replay tests: — Sensors (tokio tasks inside amira-solo, Solo has no daemon): exec watcher every 3 s (a PHP-FPM pool spawning a shell/downloader, miners, binaries in temp or upload folders, CPU burners of your sites' users, probed as root by the narrow helper), file watcher every 5 min as the site user (backdoor signatures, new scripts in uploads, database dumps in public folders, .user.ini / .htaccess auto_prepend_file, mass change and ransom notes), site-user crontabs, database sensor (MySQL performance_schema digests, pg_stat_statements when loaded, unknown or remote DB accounts, failed-login bursts, canary rows), mailbox takeover (new sign-in countries/networks, impossible travel, outside forwarders, Sieve redirect/discard rules), panel and API/MCP-key abuse, server persistence (new SSH keys, systemd units, root cron lines, listening shells, mining-pool connections), guard integrity, and nginx access-log lines from the analytics run (web-shell requests, bulk downloads). — Playbooks act through the existing Solo features: nginx bot rules (+ Cloudflare when linked) for 24-hour blocks, the quarantine (restorable under Security → Quarantine), sending limits, mailbox login locks, webmail/IMAP session kicks, forwarder/Sieve switch-off, WordPress admin role removal, per-account PHP Hardening, plugin switch-off (moved aside in the site user's home), cron line removal, 1-hour outbound blocks, MySQL remote-login lock, panel sign-out, API key freeze, security-setting revert, persistence switch-off. Every action is recorded with its evidence, expiry and Undo; Tier B steps (suspend, salts, mailbox password reset, canary) always wait for your approval with your 2FA code or password. Default mode shadow; the always-act list (web shell + miner) contains those at once. — Alerts and one-tap approvals on every channel marked "critical alerts + approvals" (Telegram, Discord, e-mail, webhook): signed, single-use, 15-minute links; the gate re-checks before anything runs. — Read-only AI investigator (opt-in, your own provider/key, daily budget, masking): the same binary as amira-solo guard-worker in its own unit amira-solo-guard-worker.service as the unprivileged amira-guard user (no sudo, no access to the panel's config, outbound only loopback/DNS/443), talking to the panel over the loopback worker API with a scoped token. Its requests are never executed in Phase 1. "Test this model" runs the red-team cases against the chosen model. — MCP tools guard_status, guard_incidents, guard_action_undo, guard_approve (Solo Full; Undo and approve ask for a confirm_token; destructive approvals only in the panel). — Privacy (PB-12): you turning the guard off is a local audit entry only; nothing is sent to AmiraTech; an unexpected stop or outside change is reported to your own channels only. — Installer/upgrade: /usr/local/lib/amira-solo/guard-kill.sh (root helper shared with Pro) with exact regex sudo rules (sudo ≥ 1.9.10), the worker user, token, unit and its nftables filter; migration 20261031002000_ai_guard_phase1.sql.
  • AI assistant: more providers, any model, your own endpoint (Settings → AI Assistant). New providers: Anthropic (Claude) direct through the native Messages API (Claude Sonnet 5.5 default, Opus 5.5, Haiku 5.5, Fable 5.1; tool calls are converted both ways, thinking blocks are kept for the follow-up requests, refused requests fall back server-side where Anthropic offers it), Xiaomi MiMo (MiMo V2.6 Pro default, V2.6 Flash, V2.6 Pro UltraSpeed; sent with MiMo's api-key header), Z.ai (GLM) on the general API (GLM-5.3, GLM-5.3 Flash) next to the Z.ai GLM Coding Plan endpoint, and Custom (OpenAI-compatible): display name, base URL (a full /chat/completions URL or a base such as https://host/v1), free-text model name, optional API key (stored encrypted like the others) and optional auth header name/format (default Authorization: Bearer {}) for self-hosted vLLM, Ollama or LiteLLM. Every provider's model picker lists the current models plus Other model… for any id.
  • Test connection checks the form as it is, before saving: it sends a tiny request and shows the latency, or the provider's error with API keys removed.
  • WordPress → All sites (every edition): the WordPress page now opens on a list of every WordPress site on the server — domain, folder, WordPress version, last security check and waiting updates — with search, a domain filter, a security filter, sorting and 50 rows at a time, so it stays fast with many sites. Actions per site: Manage, one-click wp-admin login, update WordPress, delete. Find existing sites registers WordPress sites the panel did not list (copied by hand or imported); sites imported from cPanel are now registered automatically.
  • WP Toolkit per site (every edition, ported from Amira Pro): dashboard (version and core update, plugin and theme counts, active theme), one-click wp-admin login (single-use link, 60 s), plugins and themes (activate, deactivate, update, update all, delete, in bulk), hide from search engines, and a Security tab with ten checks (file editor, debug, xmlrpc.php, wp-config.php permissions, PHP in uploads, directory listing, "admin" user, changed core files, core update, table prefix) and Fix / Fix all. On Solo the rules are Nginx rules: xmlrpc.php is denied by a per-site snippet, PHP in uploads by the site block's uploads location.
  • Solo Full: WordPress Security & Toolkit (license feature wordpress_toolkit): the Security overview of every site (summary, filters, Scan all / Scan selected, Fix selected with plugin updates after a backup, per-site findings), a daily scan with an alert and a notification when a site gets a new serious problem; known plugin vulnerabilities from the Wordfence Intelligence feed (AmiraTech's mirror on amirapanel.com, sha256-checked, or your own Wordfence key; a failed download waits 6 hours); the break-in checks on live sites (planted administrators, backdoor files and web shells, wp2shell-affected core) with confirmed fixes (role removed, files to Security → Quarantine, minor core update); per site Clone (staging copy hidden from search engines, owner-locked uploads included), Copy data (staging → live, target backed up first) and Backups (newest 3, restore, disk guard). MCP wp_security_scan and wp_security_fix (Solo Full, the fix asks for a confirm_token first).
  • New WordPress sites get Pro's safe defaults: no PHP in uploads, file editor off, xmlrpc.php blocked by Nginx, WP_DEBUG off, wp-config.php 640.

Changed

  • One owner, many sites: a server can now hold up to 1000 WordPress sites per account (was 10, Pro's per-customer limit).
  • The settings list no longer returns settings of category secret (the Wordfence API key).
  • Database migration 20261031000300_wordpress_toolkit (job and clone columns on wordpress_installs, table wp_security_scans); installer and upgrade create data/wordfence.
  • Refreshed models: OpenAI (ChatGPT) GPT-6 Astra (default) and GPT-6 Luna; Google Gemini Gemini 3.8 Flash (default), Gemini 4 Argon, Gemini 3.5 Flash-Lite; DeepSeek deepseek-flash (V4.1 Flash, default) and deepseek-v4-pro. OpenAI requests now send max_completion_tokens and leave out temperature for reasoning models.
  • Saved settings carry over (migration 20261031000200): a saved z.ai setup becomes Z.ai GLM Coding Plan (the endpoint it was using), retired DeepSeek ids (deepseek-chat, deepseek-reasoner, deepseek-v4-flash) run as deepseek-flash, retired Gemini 2.0 / preview ids and MiMo V2.5 ids map to their current models; any other saved model id is kept as typed.

Fixed

  • Upgrades no longer fail with "Text file busy". The upgrader now stops the AI Security Guard worker (amira-solo-guard-worker) before it copies the new binaries, replaces each binary by renaming a fresh copy over it, and a rollback after a failed step always starts the panel and the worker again (a failed rollback could leave the panel stopped).
  • DeepSeek, Z.ai and MiMo thinking models can use tools across rounds: their reasoning_content is sent back on tool-call turns (DeepSeek answered later rounds with a 400). Conversations started before this update keep failing on their old tool rounds; start a new chat.
  • The WordPress version shown is the one really installed: it is read from wp-includes/version.php (WordPress updates itself) when a site is opened, checked or scanned, after restores, clones and copies, and by MCP wp_info (same fix as Amira Pro).

Security

  • Security: the panel user could write root's crontab. The sudo rule crontab -u usr_* - also matched crontab -u usr_a -u root - (a sudoers * matches spaces). The crontab rules now use exact regular-expression arguments (^-u usr_[a-z0-9_]+ -$, sudo 1.9.10+); upgrades replace the rules. Found while building the AI Security Guard.
  • AI endpoint URLs (custom provider and the per-provider endpoint override) must use https://. Plain http:// and loopback/private addresses need the new Allow plain HTTP on a private network switch; link-local and cloud-metadata addresses and the panel's own service ports are always refused, the host is resolved and checked before every request (and the connection pinned to the checked address), redirects are not followed and every request has connect/read timeouts. An existing http:// or private-address override stops working until the switch is turned on.
v1.15.2 security October 30, 2026

Added

  • Bot Protection shows who visits and attacks each site (Security → Bot Protection, Solo Full; ported from Amira Pro — the Community edition and an unlicensed panel no longer have Bot Protection, its background watch or outgoing limits). New tabs Activity (clients per site grouped by kind — attackers, browsers that read like machines, AI crawlers, scripts, SEO tools, search engines, link previews, monitors — with plain-language behaviour, cost, scraping score, verified / fake search engines, busiest networks, country flags), Scraping (findings of the bot watch: scraping by an address or a whole network, WordPress login campaigns, fake search engines, scanners, with evidence and one-click options), Rules (now per website or every website, network rules AS123, expiry), Auto-protect (temporary automatic blocks of scanners, login campaigns, fake search engines, repeat WAF offenders, trap-URL hits like /.env; never verified search engines, your own logins, Cloudflare or allowlisted addresses; at most N an hour) and Outgoing (new outgoing connections per account, counted by the root helper outbound-monitor.sh with nftables; throttle / block an account, and "direct mail": accounts may not connect to other servers' port 25 unless allowed). One-click blocks become nginx bot rules on the real visitor address ($remote_addr after real-IP) or Cloudflare IP Access rules (block / managed challenge); every action is audited and reversible. The per-site Block AI crawlers switch writes robots.txt and refuses their user agents with 403. Data comes from the nginx access logs (amira format) every 15 minutes; client addresses are kept 14 days. The DB-IP ASN Lite database is downloaded next to the country one (mirror first). Migrations 20261030000040 (bot activity, per-site rules), 0050 (Auto-protect), 0060 (outgoing). MCP (Solo Full, advanced_security like bot_protection_*): bot_activity, bot_block, bot_auto_protect, bot_outgoing_limit, bot_direct_mail, bot_ai_block (changes need a confirm_token).
  • Threat Map (Security → Threat Map, every edition): who probes or attacks the server and from where — closed-port probes the firewall blocked (open ports are not counted: late packets of normal visits), WAF blocks and current fail2ban bans, per country on a world map with DB-IP flags, the top attackers and a live feed; the server is shown at its GeoIP location or where you place it.
  • Security Checkup (Security → Security Checkup, every edition, and a card on the Security Dashboard): ~37 checks of the panel (2FA, IP allowlist, API keys, version, certificate and renewal, process owners), the system (security updates, unattended-upgrades, pending reboot, SSH), the network (firewall, open ports, loopback-only services, FTP TLS, Cloudflare Tunnel), the web server (nginx -t, server_tokens, PHP Hardening), protection (fail2ban, WAF, Auto-protect, ClamAV, malware scan schedule, rootkit, Lynis, RBL), mail (open relay with a live test, SPF/DKIM/DMARC, mail certificates) and hosting (site certificates, HTTPS, PHP end of life, world-writable files, backups), with a score, history, "new since last run", accepted risks (reason + expiry) and safe one-click fixes after a confirmation (unattended-upgrades, SSH key-only / hardening via the root helper security-checkup.sh, firewall, fail2ban restart, WAF, ClamAV definitions, PHP Hardening). Runs daily (03:30 by default) and alerts the notification channels when new critical/high findings appear or the score drops. Migration 20261030000070. MCP (every edition): security_checkup_run, security_checkup_results, security_checkup_fix.
  • Security summary (Security → Notifications): a weekly (default) or daily plain-language report to every notification channel — what was blocked, what was found, what needs you, the latest checkup score.
  • Country flags next to IP addresses on Firewall Logs, IP Blocklist, the Firewall page's fail2ban bans, WAF events, security events and Bot Protection (looked up on this server, POST /admin/security/geoip).

Security

  • Settings → Security "Enforce 2FA" and "Idle sign-out" are enforced (every edition; they were saved but nothing read them). Port of Pro's sign-in policy: a login starts a session (refresh_tokens.session_id, migration 20261031000010) whose id every access token carries; a browser session unused for longer than the timeout is signed out (401 session_idle_timeout, also on refresh) and the login page says why and returns to the page you were on. With "Enforce 2FA" on, an account without two-factor sign-in can use nothing but the new /2fa-setup page until it has set it up (403 2fa_setup_required), and 2FA cannot be switched off while enforced. The owner cannot enforce it before setting it up on their own account. Timeout: 0 = off or 5–10080 minutes. MCP connectors and API keys are not affected. The upgrade resets both settings to off (they never worked), so nobody is signed out or locked into setup by the upgrade.
  • amira-solo reset-2fa [<email or username>] (run as root on the server; no argument = the panel's only admin): turns two-factor sign-in off for an owner who lost the authenticator, clears a half-finished setup, signs the account's browser sessions out and writes an audit entry. MCP connectors and API keys keep working. Listed in amira-solo --help.
  • OAuth consent shows who is asking (MCP connectors): the registered client name, the host the code is sent to and the account being connected; Approve is disabled when the redirect address is not one the client registered (GET /api/v1/oauth/client).
  • No PHP from WordPress uploads: every PHP site's Nginx block now refuses .php/.phtml/.phar files under /wp-content/uploads/ (where web shells are planted), for new sites and — at the next panel start — for existing ones (the same pass that switched the access log format; one nginx -t + reload, previous files restored if Nginx refuses).
  • Fail2ban whitelist (Firewall page, every edition): addresses Fail2ban never bans, added and removed from the panel; adding one that is banned right now lets it in at once. Kept by the panel (panel_settings fail2ban_whitelist) and applied to every jail with fail2ban-client set <jail> addignoreip — re-applied after fail2ban restarts — because a jail.local would lose to the installer's jail.d/amira.local. No new sudo rule. Loopback is always listed.
  • PHP Hardening (Security → PHP Hardening, MCP php_hardening, every edition): each account's PHP-FPM pools now disable exec, passthru, shell_exec, system, proc_open, popen and pcntl_exec (php_admin_value, so no site or per-domain PHP setting can undo it) on top of the open_basedir they always had. On by default; switching an account off is kept as the admin's choice (accounts.php_hardening_opt_out, migration 20261030000020). Existing pools are rewritten hardened at the next start (PHP-FPM pool self-heal). WP-CLI, Composer, Artisan and cron jobs run the PHP command line and are not affected.
  • The cPanel import checks WordPress before the sites go live (Solo Full): a new step security reads the extracted backup of every imported WordPress (no symbolic links followed) for the wp2shell backdoors and generic web shells shared with Pro, moves the strong findings to the quarantine (Security → Virus scanner → Quarantine, restorable), takes the administrator role from accounts with the attacker's logins/addresses (WP-CLI on the imported database; never deletes, never the last real administrator), and lists everything in the import report (security_findings, shown at the top of the report), the audit log and a critical alert to the notification channels. The import never stops for it. (Solo has no WordPress Security fleet scan yet; the same checks run only at import.)

Added

  • Security dashboard: events have plain names and a one-line summary, can be acknowledged one by one or all at once (they could not be at all), the Threats card counts the last 30 days, Firewall and Fail2ban say "Unknown" when their status cannot be read instead of a false "Inactive", and the page shows an error state with "Try again".
  • Notifications list only events the backend really sends, with plain labels (GET /admin/security/events/types, from the writers' constants; the page hard-coded 11 names, four of which nothing ever sent), "All event types (including ones added later)", an Active switch in the dialog, and the last delivery of each channel (delivered, or failed with the error). Names nothing sends are dropped when a channel is saved.
  • Firewall: IPv6 badge on UFW's (v6) rule copies, an All Banned IPs table across jails with Unban, and enabling the firewall asks first (SSH lock-out warning) like disabling did.
  • RBL Monitor: one card per server IP (IPv4 and IPv6) with "listed", "clean", "could not check" (no list answered) or "not checked yet"; "Request removal" links to each list's delisting page; Check any IP (any public address, not stored; POST /admin/security/rbl/lookup).
  • MCP ip_reputation_check (every edition, read): blocklist status of the server's sending IPs (stored or recheck=true) or of any public IP, with each listing's delisting page and the lists that did not answer.
  • Virus, Lynis and rootkit scans run in the background. A scan can take longer than nginx keeps a request open, so the page used to fail on long scans. Starting a scan now answers at once (202), the page shows progress and updates when it finishes, and you can leave the page (GET /admin/security/scan/{id}, /admin/security/rootkit/{id}). Starting Lynis (or the same rootkit scanner) while one is running joins that run. MCP tools and schedules still wait for the result.
  • "The last scan did not complete" notice on the Virus Scanner, Lynis and Rootkit pages, with the scanner's error output. Scans cut off by a panel restart are marked failed at startup instead of staying "running".
  • Firewall Logs filters: Rate-limited and Audit actions, destination port, source address or prefix (e.g. 203.0.113.), Clear, a match count, and click any IP to see only its entries. "Blocked (24h)" now includes rate-limited connections. The page warns when /var/log/ufw.log is missing or unreadable (UFW logging off, or the panel user not in adm) instead of looking like a quiet firewall.
  • PHP Hardening: each account lists the websites its switch covers (Solo runs one PHP-FPM pool per account, shared by its sites, so the switch is per account), "Harden all", a confirmation dialog instead of the browser prompt, and Harden new accounts (on by default; an account created later starts hardened).
  • Shared addresses in mail login protection (on by default): an office, school, hotel or mobile network puts many people behind one address, and one misconfigured device there (a phone signing in hourly with the server name instead of a mailbox) got the whole address banned from IMAP and SMTP for 24 hours although it had hundreds of successful logins. Per source address the panel now counts successful logins (IMAP, POP3, SMTP AUTH, webmail) and failed ones over a window (6 h). With at least 3 successful logins by at least 2 mailboxes the address is trusted: failures with a username that is not a mailbox are no longer banned — you get one notice per address and username per day ("probably a mistyped setup"); wrong passwords for one or two real mailboxes lock just that mailbox for that address (24 h; the mailbox is told by email) instead of banning everyone there. Wrong passwords for 3 or more mailboxes (or more than 5 unknown usernames) are still an attack: banned right away, as before. Addresses without successful logins are banned exactly as before. Email Admin → Login Protection shows the shared addresses (good logins, mailboxes, recent failures, last decision), the locked mailboxes with Unlock, the notifications and the settings (on/off, logins, mailboxes, window, failures, lock hours); the mailbox's login security page lists and lifts its address locks. MCP: email_login_security returns shared_addresses and per-mailbox address_locks; email_login_lock mode=unlock also lifts address locks. Decisions, locks and unlocks are in the audit log. fail2ban's dovecot, postfix-sasl and amira-webmail jails ask a small script (ignorecommand, /usr/local/lib/amira-solo/mail-shared-address) before counting a failure; it says "ignore" only for an address in the panel's list (/opt/amira-solo/data/mail-shared-addresses) while that list is fresh, so with the panel down (list older than 15 minutes), the list or the script missing, fail2ban bans as before. Every edition. The upgrade installs the script and /etc/fail2ban/jail.d/amira-shared-address.local with the other jails; no sudo rule changes. Migration 20261030000030.
  • Server → Reboot (every edition): uptime and last boot, running vs newest installed kernel, whether updates are waiting for a reboot, what is running now, and the next scheduled reboot. Graceful reboot (services stop cleanly) and Forceful reboot (systemctl reboot --force, for when a graceful one hangs; data not yet saved by databases or mail may be lost). You type the server's hostname to confirm; the page waits while the server is down and says when it is back. While a backup, restore, cPanel import or panel upgrade is running, a reboot now is refused and the confirm dialog lists the jobs with a "Reboot anyway" box. Every reboot is in the audit log (who, which kind, from which IP, what it interrupted) and goes to the notification channels.
  • Scheduled reboot (off by default): switch it on, pick a time (server time) and Once (the next time it is that time; it then turns itself off) or Weekly on a chosen weekday. The panel itself starts the reboot. Saving refuses a time inside a backup window — each backup schedule's start, the longest of its last 5 runs (60 min when it has none) and 30 minutes on each side, past midnight too — and says which backup and which times are free; the page lists every window next to the time picker. When the reboot is due while a backup, restore, cPanel import or panel upgrade runs, it waits (checks every 5 minutes, up to 2 hours), then skips that time, writes it to the audit log and tells the notification channels; it never stops a job. Hourly backups leave no free hour, so they are not checked on save (the reboot waits for a running one). A time is never rebooted twice. The page shows the next reboot and the last scheduled result (ran / skipped and why).
  • MCP tool server_reboot (status, graceful, force, schedule_set; graceful and force report running jobs and need ignore_running to interrupt them; graceful, force and switching the schedule on ask for a confirm_token first).

Upgrade notes

  • Migration 20261031000010 (session id on refresh tokens; "Enforce 2FA" and the idle timeout reset to off — switch them on again in Settings → Security if you want them).
  • The upgrade adds two exact sudo rules (graceful timer, forceful reboot) and migration 20261030000020 (the scheduled reboot setting, off); servers get both from the upgrade itself.

Fixed

  • Ubuntu's own daily chkrootkit run is switched off, as on Pro: without a mail command it failed every day (chkrootkit.service red in systemctl --failed), and with one it mailed root known false positives. The panel's Rootkit Scanner runs chkrootkit and alerts through its channels.
  • Unlimited mailboxes stay unlimited. The Email page showed them as 250 MB, the edit dialog pre-filled 500 MB and a save without a quota gave them 250 MB. 0 now means unlimited (no Dovecot quota rule), an update without a quota keeps the current one and a new mailbox without one gets Settings → Email's default quota (Pro 1.24.5).
  • Mail Statistics, View Relayers and Sent Summary reload when the time range changes (only the label changed).
  • Email notification channels can be created from the page: it sent the address as email while the server wants to, so every save failed.
  • RBL checks of an IPv6 server address no longer fail the whole check (the stored check used the IPv4-only lookup).
  • Settings save sends number fields as text (an edited number made the whole save fail).
  • Disk Usage shows where all the space goes. The server breakdown had no Email row (238 GB of mail on panel.hostmts.com was invisible), no Docker, system files or root's home, counted backups twice (inside "Panel" too) and did not add up to the used space. It now lists Email (/var/mail/vhosts), Docker, Containers, System Files and Administrator Home, shows Panel without its backups and System Files without the web cache, and ends with an "Other" row so the rows add up to the disk. An account's own Disk Usage counts its domains' mail (it measured ~/mail, which Amira never uses), matching the account's usage meter.
  • Backups of accounts imported from cPanel with capital letters in a database name (meungtealaos_WP) failed every day ("invalid MySQL database name"); such names are accepted now.
  • FTP starts after a reboot on servers whose hostname resolves nowhere (a home server behind NAT): install and upgrade add 127.0.1.1 <hostname> to /etc/hosts when the name does not resolve (ProFTPD refused to start).
  • License page fits a phone.
v1.15.1 security October 30, 2026

Security

  • CVE-2026-98432 (Linux kernel, CVSS 9.8, remote root): the bug in the IPv4 TCP handshake needs a SYN that carries IP options, and Ubuntu has no fixed kernel yet. The install and every upgrade now drop IPv4 TCP packets with IP options (normal traffic never uses them) in their own nftables table, loaded at boot by amira-net-mitigations.service; ufw, Docker and fail2ban rules are untouched. Still install the fixed kernel and reboot once Ubuntu ships it.

Added

  • Version in the header for the admin, as in Pro.

Changed

  • License page: "Unlimited" limits, no Accounts or Clustering rows (one owner), the key shown shortened. Full-only pages wait for the license answer instead of flashing an upgrade notice.
  • Admin MCP page lists the server's real tools (174); dashboard sizes in MB / GB / TB; menu label "Backup Destinations"; only one menu item lit.
  • IP Pool: Update SPF asks first; SPF and config buttons are off while the pool is empty; event list in plain words. Backup destination fields show neutral hints instead of AWS sample keys.

Fixed

  • Live monitoring connects again (it stayed "Offline"): the socket is outside the login check (the admin IP allowlist still applies) and nginx passes the WebSocket upgrade — the upgrade adds that to existing servers.
  • RBL Monitor checks the server's detected public address (it failed with no address configured); the Security dashboard card shows the result.
  • Sending limits never hold the server's own system mail.
  • Rootkit Scanner: chkrootkit findings in packaged files, node_modules, the mail ports 465/4190 "bindshell" and empty headings are left out; the upgrade removes its unpacked files from /tmp (and earlier upgrades'), which chkrootkit reported as Linux.Xor.DDoS.
  • Pages no longer scroll sideways on a phone or at 1366 px: content area, tab rows, page and card headers, File Manager, Email, DNS, Email Marketing, MCP, firewall logs and audit log.
  • Doubled padding at the top of cards.
v1.15.0 feature October 29, 2026

Added

  • Website analytics upgrade (from Amira Pro). Custom from–to days next to the presets (UTC days, clamped to the 400 days of daily and 14 days of hourly numbers, with a note when a range was shortened; one or two recent days by hour); countries (page views by visitor country from a local DB-IP Country Lite database that Solo now downloads and refreshes monthly — only the code is counted, never the address); Export CSV of the current view (UTF-8 with BOM, Lao intact in Excel, formulas defused); Download PDF (print-ready report in the panel's fonts, the browser's Save as PDF).
  • Analytics → Live Traffic: world map with visitor dots and arcs, a live feed in plain words, a right-now panel, filters, pause and a 15-minute replay. The nginx access logs are tailed only while the page is open and nothing new is stored; addresses are masked and revealing one is written to the audit log.

Changed

  • The GeoIP database downloads from amirapanel.com's mirror first, then from db-ip.com (home and office lines that time out on db-ip.com).
  • A GeoIP download that failed is retried after 15 minutes instead of 6 hours while the database is missing.
v1.14.0 feature October 28, 2026

Added

  • fail2ban bans machines that try to send spam through the server (from Amira Pro). Bots that connect to port 25 and ask the server to pass mail on to outside addresses ("Relay access denied") were never banned. New jail amira-postfix-relay (in jail.d/amira.local, filter filter.d/amira-postfix-relay.conf, written by every upgrade): 3 refusals within a day ban the address from the mail ports for a week. Only clients without matching reverse DNS on port 25 count, so mail apps on 587/465 and real mail servers are never banned; the fail2ban whitelist applies. Firewall → Fail2ban and the MCP tool fail2ban_status describe every jail in plain words.
  • Delivery Logs: real mail first (from Amira Pro). Refused attempts (relay bots, spoofed senders, blocklists, unknown recipients — Postfix NOQUEUE rejects, not listed before) are now shown, but behind a "N refused attempts (spam / relay bots)" button; the default view is mail the server accepted. Common answers are in plain words with the raw text one click away, and the sender is shown on delivery lines (it was empty). The API takes kind=all|mail|refused and summary=true; the MCP tool email_view_logs returns kind, category, reason and a summary count (an object now, not a bare list).
  • Certificates for mail.<domain> (Outlook, phones). Mail apps set up with mail.<domain> or <domain> as their IMAP/POP3/SMTP server got the server's own certificate and warned or refused to connect. Postfix and Dovecot now present each domain's own certificate (SNI), and Let's Encrypt certificates also cover mail.<domain> when it points at this server. Kept in step after every certificate change and hourly; the upgrade turns it on (root helper /usr/local/lib/amira-solo/mail-sni.sh).
  • AutoSSL. A new domain or subdomain gets its Let's Encrypt certificate by itself as soon as its DNS points here (checked every 2 minutes for half an hour), and an hourly check gives one to domains still without a valid certificate (a failed order waits a day). Uploaded certificates are never replaced. Off with the panel setting auto_ssl_enabled = false.
  • Sending Limits (Email Admin → Sending Limits): recipients per hour and per day for each mailbox (default 200 / 1000) and for the whole server (500 / 3000), with overrides per mailbox; mail over a limit is held in the Postfix queue, not sent, to release or delete per sender. A mailbox that tries to send about twice its limit is paused automatically (probably hacked) with an alert; many bounces for one sender raise an alert. Email Marketing campaigns and panel notifications are not counted. An Rspamd plugin does the counting (Redis), installed by the upgrade. MCP: email_sending_status, email_sending_manage (confirmation for pause and deleting held mail).
  • Login Protection (Email Admin → Login Protection): failed IMAP/POP3/SMTP logins per mailbox and hour from the Dovecot and Postfix logs, with their IPs, and where each mailbox logged in from. Password guessing from many IPs — which fail2ban's per-IP bans cannot stop — raises an alert, the password is checked against common ones and ones built from the address (never shown), and with a weak password the mailbox is locked to the IPs it used in the last 30 days for 24 hours (setting: weak / always / off). Locks by hand: known IPs only or webmail only; the panel's webmail always works, a new password lifts an automatic lock. MCP: email_login_security, email_login_lock (with confirmation). Alerts go to Security → Notifications (mail_login_attack, mail_sending_abuse).

Fixed

  • Analytics shows Lao page names readably (/ຂ່າວສານ/ instead of /%e0%ba%82…/), and one page is no longer counted twice.
  • Analytics "Raw log report" works for every site (it failed with an internal error when a site's log contained bots' non-UTF-8 bytes).
v1.13.0 security October 28, 2026

Security

  • Mail logins are protected against password guessing again. fail2ban's postfix-sasl and dovecot jails watched no log file ("No file is currently monitored"), so nobody was ever banned for guessing mail passwords: Ubuntu's fail2ban defaults read the system journal instead of log files, Postfix and Dovecot do not log there under the names the jails look for, and the Dovecot jail pointed at the wrong file. The jails now read /var/log/mail.log (Postfix SMTP login) and /var/log/dovecot-info.log + /var/log/dovecot.log (IMAP/POP3), and a new proftpd jail protects FTP logins. The log files are created before fail2ban starts (on a fresh Ubuntu 24.04 a missing log kept fail2ban from starting at all, leaving SSH unprotected too). The upgrade rewrites the jails, starts fail2ban when it is not running and reports, for every jail, which files it watches. Check with fail2ban-client status dovecot.
  • Firewall bans work for IPv6 addresses. Blocking an IPv6 address on the Firewall page (or with firewall_deny) failed; deny rules are now put at the top with ufw prepend, for IPv4 and IPv6.
  • New WordPress sites get wp-config.php readable only by the site (mode 640). It holds the database password and was readable by every local user.
  • Installer and upgrader downloads give up after a timeout and retry instead of hanging forever on a stalled connection.

Fixed (found testing on a real home server)

  • An upgrade could stop the panel and leave it stopped. A step that is harmless to repeat (Docker apps → PostgreSQL / PostGIS) failed on every second upgrade, and nothing rolled back. The step is fixed, and any unexpected failure while the panel is stopped now restores the previous version and starts it again.
  • Solo Community compiles again (the "mail behind NAT" addition used a Full-only module).
  • Turning PostGIS off while a table uses it says so instead of "internal server error"; the Docker engine page no longer says docker-ce updates install by themselves.

Added

  • Spam goes to the Junk folder. Mail Rspamd scores as spam (6 points or more) used to land in the Inbox with only a header; it is now filed into each mailbox's Junk folder (created when missing).
  • Reliable spam blocklist checks. Spamhaus refuses lookups that come through public DNS resolvers (8.8.8.8, 1.1.1.1), so Rspamd let listed spammers through and the RBL monitor could not tell whether the server was listed. The upgrade installs a local resolver (Unbound, on 127.0.0.1 only; PowerDNS and the server's own DNS settings are untouched) that Rspamd and the RBL monitor use. The RBL monitor no longer counts a list's "query refused" answer as a listing, no longer checks the CBL (it is part of Spamhaus, already checked) and only asks lists that cover IPv6 about IPv6 addresses; Mailspike was added.
  • Backups refuse to fill the disk. A backup that would leave less than 5% of the disk (at least 2 GB) free is not started; the backup shows how much it needs and how much is free. A full disk stops the database, mail and every site.
  • Disk and bandwidth meters show real numbers. The dashboard's Disk Space and Bandwidth meters always read 0; the panel now measures each account's files and mail (hourly) and this month's web traffic.
  • cPanel import: certificates from the old server are renewed. They used to expire, because only Let's Encrypt certificates were renewed. They are now replaced by a Let's Encrypt certificate before they expire, as soon as the domain points to this server (imports made before this version are included).
  • cPanel import: mailboxes whose login was suspended on cPanel are imported locked (mail keeps arriving; set a new password to unlock) instead of being skipped.
  • Dovecot's log files are rotated weekly (8 weeks kept).
  • PostGIS (maps) per PostgreSQL database. Switch it on when creating a database (dialog, wizard, MCP create_database postgis: true) or later with the PostGIS switch in the PostgreSQL list. Never on by default. The panel creates the extension through a new root helper (/usr/local/lib/amira-solo/pg-extension.sh) that accepts only the PostGIS extensions and the panel's own usr_* databases. Backup restores and database-client imports of a PostGIS database switch it on by themselves. The upgrade installs postgresql-16-postgis-3 (packages only).
  • Docker apps can use PostgreSQL databases at a private subnet:5433` with the database user's password (the database wizard shows the address).
  • Docker engine tab on the Docker page: Docker/containerd version, whether a Docker update is pending and if automatic updates are on, disk usage, and cleanups of dangling images, all unused images, the build cache and unused networks. Never containers or volumes. MCP: docker_prune takes a kind; new read tool docker_engine_info.
  • Git builds get the app's environment variables as build arguments: every ARG NAME in the Dockerfile whose name is one of the app's variables gets its value, so frontends that bake NEXT_PUBLIC_* / VITE_* in at build time work like on Easypanel or Coolify.
  • Cloudflare Tunnel: move a hostname from another tunnel. A name served by another Cloudflare Tunnel (e.g. the old server) can be moved here after confirmation; the old record is put back when the route is removed.
  • Mail behind NAT on a public address of the server. A home server whose own address is private, with a public Email IP pool address configured on one of its interfaces (e.g. from a WireGuard hub), now sends all mail from that address (bounces and forwards included) and its MX follows that address's PTR name. Settings > DNS > Public Address shows it.

Changed

  • Asking for more Docker memory or CPU than the plan allows is refused with the plan's maximum instead of being lowered silently.
  • cPanel import leaves mail hosted elsewhere alone. Mailboxes and forwarders of a domain whose mail is at Google Workspace, Microsoft 365 or another server (its live MX, or the old zone when that cannot be looked up) are no longer imported: they made this server deliver that domain's mail locally, so mail your sites send to it (contact forms, shop orders) stayed in an unread mailbox here. The report says which domains were left alone.

Fixed

  • Cloudflare Tunnel and Access changes finish even when the browser tab is closed during "Setting up…" (no more tunnels created in Cloudflare whose token never reached the server).
  • Adding a domain that is refused (PHP version not installed, name already used) no longer leaves an empty folder behind.
  • The MCP page's copy-ready snippets no longer contain a shortened API key that looks real but does not work: they show the full key right after it is created, otherwise a placeholder.