Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

AZERIOID Stack Manager

One host. One panel. A full Linux web stack you control.

AZERIOID Stack Manager is a self-contained stack manager and web control panel for operators who run sites on a single Linux server. One installer bootstraps Caddy, a dedicated PHP 8.4 FPM pool, and a SQLite-backed admin UI on Laravel 13 + Livewire 4. Everything else — Nginx, Apache, databases, cache, PHP site runtimes, Node.js, Supervisor, mail, rootless Docker — installs on demand from the dashboard or the matching CLI, using official upstream packages.

Built for VPS and bare-metal operators who want a clean bootstrap, a real UI for day-two work, and a privileged broker that keeps package installs and host changes out of the web app process.

Screenshots

Captured from a live Ubuntu 24.04 panel host (UI anonymized where needed). Reflects the post–v1.6 Virtual Hosts redesign and current Mail / runtime pages.

OverviewVirtual hosts
OverviewVirtual hosts
Virtual hosts · row actionsDocker runtime filter
Virtual hosts actionsDocker vhosts
MailDatabases
MailDatabases
TerminalFile Manager + editor
TerminalFile Manager
ComponentsSecurity
ComponentsSecurity

What ships out of the box vs on demand

Bootstrap (automatic)

PieceRole
CaddyPanel vhost on port 3169; front door on :80/:443 for sites
PHP 8.4 FPMDedicated panel pool — isolated from site PHP versions
SQLitePanel state under /var/lib/azerioid-panel/
BrokerPrivileged host driver (sudoers); UI never runs apt/dnf itself
Queue workerBackground component install/remove jobs

On demand (Components page or azerioid component)

CategoryComponents
Web enginesNginx, Apache (loopback backends; Caddy terminates TLS)
DatabasesMariaDB, PostgreSQL, MongoDB
Cache / KVRedis, Memcached
RuntimesPHP 8.1–8.3 (site pools); Node.js 20 / 22 / 24
Process managerSupervisor (programs run as azerioid-supervised, never root)
Per-vhost app runtimesOpt-in: PHP-FPM (default), Laravel Octane / FrankenPHP, PM2 Node cluster, rootless Docker — chosen at create time or enabled later
MailPostfix + Dovecot + OpenDKIM (opt-in; authenticated submission only, virtual mailboxes, DKIM/SPF/DMARC guidance, direct or smarthost outbound)
ToolsAdminer (panel session–gated SQL UI; MariaDB / PostgreSQL / SQLite — not MongoDB)

Feature highlights

Proven on supported distros in operator testing — not marketing vapor:

  • Multi-engine virtual hosts — each site chooses Caddy, Apache, or Nginx independently; Caddy always owns :80/:443. Create-time runtime intent picks Traditional (PHP-FPM), Octane, PM2, or Docker up front; the Virtual Hosts list uses status/runtime badges, search/filters, and a consolidated row-actions menu
  • HTTPS — Let's Encrypt HTTP-01 (automatic), self-signed/tls internal (extensively used), DNS-01 via Cloudflare/DigitalOcean (supported; lightly tested vs internal TLS)
  • High-performance runtimes (opt-in per vhost) — Laravel Octane (FrankenPHP) for Laravel apps and PM2 cluster mode for Node apps, both on the same Supervisor + Caddy foundation, with reload paths aimed at zero-downtime worker replacement. New PHP vhosts stay on PHP-FPM unless you opt in; the panel’s own runtime never uses Octane
  • Rootless Docker (opt-in per vhost) — pull an image or build from Dockerfile/compose in the site tree; container shell and log streaming from the panel. Daemon runs only as azerioid-supervised (no docker group, rootful Docker masked) — least-privilege layout adversarially tested so a bind-mount cannot escalate to host root
  • Mail server (opt-in) — per-domain mailboxes and aliases on Postfix/Dovecot/OpenDKIM, copy-paste MX/SPF/DKIM/DMARC records with live verification, full send+receive when DNS is correct. Direct MX delivery and smarthost/relay are equally first-class: most cloud providers block outbound port 25, so the health strip probes reachability and steers you to a relay when needed — a duality many competing panels never surface. Replacing an existing MTA always requires a typed REPLACE-MTA; deleting a mail-enabled vhost requires DROP-MAIL
  • Databases with remote access modes — localhost / specific IPs / global (with explicit confirmation); MariaDB and PostgreSQL enforce per-database host rules; MongoDB remote access is instance-wide firewall
  • Adminer — installable SQL admin UI for MariaDB / PostgreSQL / SQLite, reachable only through the panel’s authenticated session (never independently exposed)
  • Per-vhost Terminal and File Manager — broker drops to the vhost user (az-vh-…); path traversal and symlink escape rejected
  • Supervisor processes — create/start/stop/logs from UI or CLI
  • CLI parityazerioid wraps the same broker path as the dashboard (origin=cli in audit)
  • Tag self-updateazerioid panel update check|apply installs semver git tags (latest or --v=<tag>), refuses dirty trees, and rolls back automatically if apply fails mid-update
  • White-label panel domain — bind the panel to a hostname on :443; IP:3169 and SSH tunnel stay as fallback

Honest limits: single admin (no multi-user RBAC yet). Archive extract is not offered in the File Manager (zip-slip scoped out). Mail ships without webmail, spam filtering, quotas, or catch-all addresses; deliverability still depends on reverse DNS you set at your VPS provider. Octane is Laravel-only; PM2 is Node-only; Docker compose host mounts are bounded by what azerioid-supervised can already access (not equivalent to root).

Supported operating systems

Verified end-to-end on the current stack (Laravel 13 + Livewire 4, including mail / Octane / PM2 / rootless Docker paths where those features apply):

OSSupportNotes
Ubuntu 24.04SupportedVerified
Debian 12 / 13SupportedVerified
AlmaLinux 9+SupportedVerified with SELinux Enforcing
Rocky Linux 9+SupportedVerified with SELinux Enforcing (same EL path as AlmaLinux)
CentOS Stream 9+SupportedVerified with SELinux Enforcing (same EL path; ID=centos)
RHEL / Oracle Linux 9+Supported (same EL path)Same installer/SELinux helpers
FedoraNot supportedInstaller refuses correctly

Requirements: root, outbound HTTPS, git.

Quick start

git clone https://github.com/azerioid/azerioid-stack-manager.git stack-manager && cd stack-manager
chmod +x stack-manager.sh
sudo ./stack-manager.sh

Interactive install (TTY) prompts for:

  • Access mode — tunnel (default, 127.0.0.1:3169) or public (HTTPS on the host IP)
  • Panel port, optional TOTP requirement, firewall, fail2ban, IP allowlist
  • Optional admin creation (email + password)

Non-interactive example:

sudo ./stack-manager.sh --non-interactive --access=public --create-admin=true --admin-email=you@example.com
# Set ADMIN_PASSWORD in the environment — never pass passwords on argv

Tunnel access after a default install:

ssh -L 3169:127.0.0.1:3169 user@host
# open http://127.0.0.1:3169/setup  (or /login if an admin was created)

Optional hardening flags: --firewall=true, --fail2ban=true, --require-totp=true. Full list: sudo ./stack-manager.sh --help.

On any public install, change the admin password immediately after first login if you used a weak or default value.

Security model (brief)

  • Least-privilege broker — privileged work is sudo + broker, not the Laravel process
  • Registry-gated installs — only components defined under registry/components/
  • Panel PHP isolated (dedicated FPM pool, locked-down disable_functions)
  • Livewire actions authorize server-side (Phase 2/3 hardening) — UI hiding is not the control boundary
  • Rootless Docker only for panel-managed containers — rootful docker.service / docker.socket are disabled and masked; no docker group path (group membership is root-equivalent)
  • Mail anti-abuse — not an open relay (mynetworks localhost-only; SASL on submission 587/465 only); open-relay self-test before “healthy”; typed confirms for REPLACE-MTA / DROP-MAIL
  • Localhost-first defaults for panel bind and managed DB/cache
  • Adminer only behind the panel session — not a separately published vhost
  • Optional TOTP, fail2ban jail, ufw/firewalld rules
  • DNS-01 API tokens (and mail/smarthost secrets) stored root-only; never accepted on argv

Details: docs/SPEC.md, docs/DECISIONS.md, docs/port-ownership.md.

CLI examples

azerioid status
azerioid vhost list --json
azerioid vhost add --domain=app.example.com --type=php --php=8.4 --root=/data/www/app.example.com --tls=auto
azerioid vhost add --domain=api.example.com --type=php --php=8.4 --runtime=octane --tls=auto
azerioid vhost octane enable --domain=api.example.com
azerioid vhost octane reload --domain=api.example.com
azerioid vhost pm2 enable --domain=node.example.com --instances=2 --entry=server.js
azerioid vhost docker enable --domain=app.example.com --mode=image --image=nginx:alpine --internal-port=80
azerioid db add --engine=mariadb --name=appdb --user=appdb
azerioid component install redis
azerioid component install mail   # refuses foreign Exim/Sendmail unless --option=confirm=REPLACE-MTA
azerioid component install adminer
azerioid process create --vhost=app.example.com --command='node server.js' --name=app-node
azerioid mail hostname set --hostname=mail.example.com
azerioid mail domain enable --domain=app.example.com
azerioid mail mailbox add --address=inbox@app.example.com   # password printed once
azerioid mail status   # “Direct mail delivery: available” or “…blocked… configure a relay”
azerioid mail smarthost set --host=smtp.provider.example --port=587 --username=apikey
# relay password: AZERIOID_RELAY_PASSWORD=… (never argv)
azerioid mail dns --domain=app.example.com
azerioid panel update check
azerioid panel update apply --v=v1.6.0 --confirm

Secrets (DB passwords, DNS tokens, backup passphrase, TOTP re-auth, mail/smarthost passwords) go through the environment or one-time stdout — not argv flags. Full surface: azerioid help.

Uninstall

Panel only:

sudo ./deploy/uninstall.sh --drop-db --remove-bootstrap

Full teardown (panel + broker-managed components + added repos). Intentionally retains site trees under /data/www and panel/broker logs under /var/log/azerioid-panel (audit trail after reinstall):

sudo ./deploy/uninstall.sh --full

License

MIT — see web/composer.json.

Contributing

Issues and pull requests: azerioid/azerioid-stack-manager. Architecture decisions live in docs/DECISIONS.md; keep ADR history intact when proposing changes.

关于 About

No description, website, or topics provided.

语言 Languages

PHP83.8%
Blade10.3%
Shell4.9%
Python0.6%
JavaScript0.4%
CSS0.1%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
155
Total Commits
峰值: 96次/周
Less
More

核心贡献者 Contributors