chore: polish repo — README badges, CHANGELOG, LICENSE, install.sh cleanup

- README: add shields.io badges, fix stack (Rust, not Node.js),
  add licensing plan table, improve structure throughout
- CHANGELOG: proper Keep a Changelog format, document v0.1.0-alpha
- LICENSE: expand source-available terms with clearer restrictions
- install.sh: strip licensing/website-api build steps (those run on
  nixpanel.io/license.nixpanel.io, not on customer servers); add
  license key prompt + activation against license.nixpanel.io; keep
  only the panel DB; fix Apache to only expose ports 2083/2087
This commit is contained in:
NixReaper
2026-04-25 05:05:04 -05:00
parent f54b5cd582
commit 26c25e73c7
4 changed files with 294 additions and 412 deletions
+47 -84
View File
@@ -1,97 +1,60 @@
# NixPanel Changelog # Changelog
All notable changes to NixPanel are documented here. All notable changes to NixPanel are documented here.
Versioning follows [Semantic Versioning](https://semver.org/). Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
Versions follow [Semantic Versioning](https://semver.org/).
--- ---
## [0.5.0] — 2026-04-11 ## [Unreleased]
### Bug Fixes ### Planned
- Clean install on every update — `node_modules` and lock file are always regenerated fresh on the server platform, eliminating rollup native binary mismatches between Windows dev machines and Linux servers. - NixServer (WHM) — full Rust backend
- `update.sh` no longer blocked by local `package-lock.json` changes. - NixClient (cPanel) — full Rust backend
- `.gitignore` corrected for `nixserver/` and `nixclient/` dist paths. - DNS zone editor
- Email account management
- SSL certificate management via Let's Encrypt
- File manager
- MySQL/MariaDB database manager
- WordPress one-click installer
- Backup / restore system
- Multi-server support (Agency plan)
--- ---
## [0.4.8] — 2026-04-11 ## [0.1.0-alpha] — 2025-04-25
### Bug Fixes ### Added
- Login page now fetches version from `/api/health` dynamically instead of showing a hardcoded stale version number. - **Installer** (`install.sh`) — fully automated Ubuntu 24.04 installer
- Login page subtitle changed from "Web Host Manager" to "Admin Panel". - Self-updating: always fetches the latest version from GitHub before running
- Idempotent step tracking — re-runnable after failures without redoing completed steps
- Installs Apache 2, PHP 8.2 + 8.3 (via ondrej/php PPA), MariaDB, PowerDNS, Exim 4, Dovecot, SpamAssassin, Fail2ban, Certbot
- Configures Apache reverse proxy on ports 2083 (NixClient) and 2087 (NixServer)
- Prompts for admin credentials, hostname, and license key during install
- License activation against `https://license.nixpanel.io` with grace period fallback
- **Licensing server** (`nixpanel-licensing`) — central SaaS licensing
- Rust · Axum · SQLx · MariaDB
- RSA-4096 signed JWT license tokens
- Server IP binding with conflict detection
- Plans: Free, Solo ($9.99/mo), Host ($29.99/mo), Agency ($79.99/mo)
- Admin API with Argon2id authentication
- Validation logging and grace period enforcement
- Repo: [NixReaper/nixpanel-licensing](https://github.com/NixReaper/nixpanel-licensing)
- **Website API** (`nixpanel-website-api`) — nixpanel.io customer portal backend
- Rust · Axum · SQLx · MariaDB
- Stripe subscriptions (checkout sessions, billing portal, webhooks)
- Customer auth: register, login, email verification, password reset (Argon2id)
- License management: view active license, IP change requests
- SMTP transactional email via Lettre
- Repo: [NixReaper/nixpanel-website](https://github.com/NixReaper/nixpanel-website)
- **Website frontend** — nixpanel.io marketing & customer portal
- React 18 · TypeScript · Tailwind CSS · Vite
- Pages: Home, Pricing (monthly/annual toggle), Login, Register, Dashboard, Email Verify, Password Reset
### Infrastructure
- `.gitattributes` enforcing LF line endings for `.sh`, `.rs`, `.toml`, `.sql`, `.md` files
--- ---
## [0.4.6] — 2026-04-11 [Unreleased]: https://github.com/NixReaper/nixpanel/compare/v0.1.0-alpha...HEAD
[0.1.0-alpha]: https://github.com/NixReaper/nixpanel/releases/tag/v0.1.0-alpha
### Changes
- Removed all WHM® trademark references throughout the panel. All instances replaced with "NixServer".
---
## [0.4.5] — 2026-04-11
### New Features
- **Day/Night mode toggle** — sun/moon flip switch in the dashboard info bar. Preference persisted across sessions.
### Bug Fixes
- Sidebar version refresh now clears stale value immediately and cache-busts the API response.
- `uptime` added to exec allowlist — fixes Hostname/OS showing `…` on the dashboard.
- Version fetch auto-retries every 5 s after failure (handles post-upgrade service restart window).
---
## [0.4.4] — 2026-04-11
### New Features
- **Server info bar** — cPanel-style strip at the top of the dashboard showing Username, Hostname, OS, NixPanel Version, live Load Averages, and Server Monitoring alert count.
---
## [0.4.3] — 2026-04-11
### New Features
- **Version display in sidebar** — shows installed version with up-to-date / update-available indicator.
- **One-click panel upgrade** — upgrade button in the sidebar footer runs `update.sh` in the background. Panel restarts automatically.
- **Check for updates** — refresh icon re-fetches version on demand.
---
## [0.4.2] — 2026-04-11
### New Features
- **NixServer sidebar redesigned** — full collapsible category sidebar with 29 categories and ~210 menu items. Live search, auto-expand active category, sidebar toggle.
---
## [0.4.1] — 2026-04-11
### Bug Fixes (Installer)
- SpamAssassin: Ubuntu 24.04 service name is `spamd`, not `spamassassin`.
- PowerDNS: `systemd-resolved` stub listener disabled before package install to free port 53.
- Git clone into pre-existing directory handled correctly.
- Apache 403 fixed — post-build `chmod 755/644` on all dist assets.
- Apache 500 fixed — `mod_proxy_http` and `mod_proxy_wstunnel` now enabled.
---
## [0.4.0] — 2026-04-11
### New Features
- Shell Access Manager — enable/disable SSH shell access per hosting account.
- Apache Log Viewer — view access/error logs per account.
- WebServer page rewritten to Apache-only stack.
---
## [0.3.x] — 2026-04-10
### Architecture
- Full service stack: Apache2 + PHP-FPM, PowerDNS, Exim4, Dovecot, MariaDB, SQLite (panel DB).
- Complete MariaDB management, email routing, certbot SSL, Fail2ban.
---
## [0.2.0]
- Initial development release. Renamed to NixServer / NixClient.
+42 -14
View File
@@ -1,22 +1,50 @@
NixPanel Source Available License v1.0 NixPanel Source-Available License
Version 1.0 — April 2025
Copyright (c) 2026 NixReaper Copyright (c) 2025 NixPanel. All rights reserved.
Permission is hereby granted to use, copy, and run this software for personal GRANT OF RIGHTS
or internal business use, subject to the following conditions:
1. REDISTRIBUTION PROHIBITED — You may not redistribute, resell, sublicense, Subject to the terms of this License, NixPanel grants you a non-exclusive,
or offer this software (or any derivative) as a service without explicit non-transferable, limited right to:
written permission from the copyright holder.
2. MODIFICATION — You may modify the software for your own use. Modified 1. View and inspect the source code for personal evaluation and security
versions may not be distributed publicly or commercially. review purposes.
3. ATTRIBUTION — Any permitted use must retain this copyright notice and 2. Install and operate the software on servers that you own or control,
license in all copies or substantial portions of the software. provided you hold a valid NixPanel license subscription issued by NixPanel
at https://nixpanel.io.
4. NO WARRANTY — The software is provided "as is", without warranty of any RESTRICTIONS
kind. The copyright holder is not liable for any damages arising from use.
For commercial licensing, white-labelling, or reseller arrangements contact: You may NOT:
a. Distribute, sublicense, sell, or resell the software or any derivative
work, in source or binary form, to any third party.
b. Offer the software as a managed service, hosting panel product, or
software-as-a-service to third parties.
c. Remove or alter any copyright, trademark, or attribution notices.
d. Use the NixPanel name, logo, or branding in any product or service without
prior written permission from NixPanel.
NO WARRANTY
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. IN NO EVENT SHALL
NIXPANEL BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM
YOUR USE OF THE SOFTWARE.
TERMINATION
This License is automatically terminated if you breach any of its terms. Upon
termination you must destroy all copies of the software in your possession.
CONTACT
For commercial licensing, white-labelling, or reseller enquiries:
[email protected]
https://nixpanel.io https://nixpanel.io
+91 -47
View File
@@ -1,21 +1,43 @@
<div align="center">
<img src="https://raw.githubusercontent.com/NixReaper/nixpanel/main/assets/logo.png" alt="NixPanel" width="120" />
# NixPanel # NixPanel
A modern, open-source web hosting control panel for Linux servers — a free alternative to cPanel/WHM. **A fast, modern web hosting control panel for Linux servers.**
Free and open alternative to cPanel/WHM — built in Rust.
**NixServer** (port 2087) — Server admin panel for managing accounts, DNS, email, databases, SSL, and services. [![Latest Release](https://img.shields.io/github/v/release/NixReaper/nixpanel?style=flat-square&color=00c2a0&label=release)](https://github.com/NixReaper/nixpanel/releases)
**NixClient** (port 2083) — End-user panel for hosting account holders. [![License](https://img.shields.io/badge/license-Proprietary-blue?style=flat-square)](LICENSE)
[![Platform](https://img.shields.io/badge/platform-Ubuntu%2024.04-E95420?style=flat-square&logo=ubuntu)](https://releases.ubuntu.com/24.04/)
[![Rust](https://img.shields.io/badge/backend-Rust-CE422B?style=flat-square&logo=rust)](https://www.rust-lang.org/)
[![GitHub Stars](https://img.shields.io/github/stars/NixReaper/nixpanel?style=flat-square)](https://github.com/NixReaper/nixpanel/stargazers)
[nixpanel.io](https://nixpanel.io) · [Documentation](https://nixpanel.io/docs) · [Pricing](https://nixpanel.io/#pricing) · [Changelog](CHANGELOG.md)
</div>
---
## Overview
NixPanel gives you everything cPanel/WHM does — without the legacy bloat or the $40/mo price tag.
| Panel | Port | Purpose |
|-------|------|---------|
| **NixServer** | `2087` | Server admin — accounts, DNS, mail, SSL, services |
| **NixClient** | `2083` | User panel — files, databases, email, domains |
--- ---
## Requirements ## Requirements
| Component | Version | | | |
|-----------|---------| |--|--|
| OS | Ubuntu 24.04 LTS | | **OS** | Ubuntu 24.04 LTS (x86_64) |
| Architecture | x86_64 | | **RAM** | 2 GB minimum · 4 GB recommended |
| RAM | 2 GB minimum, 4 GB recommended | | **Disk** | 20 GB minimum |
| Disk | 20 GB minimum | | **Access** | Root |
| Root access | Required |
--- ---
@@ -25,65 +47,87 @@ A modern, open-source web hosting control panel for Linux servers — a free alt
bash <(curl -fsSL https://raw.githubusercontent.com/NixReaper/nixpanel/main/install.sh) bash <(curl -fsSL https://raw.githubusercontent.com/NixReaper/nixpanel/main/install.sh)
``` ```
Or download and inspect first: > The installer is self-updating — it always fetches the latest version before running, so you never need to re-download it manually.
**Want to inspect before running?**
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/NixReaper/nixpanel/main/install.sh -o install.sh curl -fsSL https://raw.githubusercontent.com/NixReaper/nixpanel/main/install.sh -o install.sh
less install.sh less install.sh
bash install.sh sudo bash install.sh
``` ```
--- ---
## What Gets Installed ## What Gets Installed
| Component | Role | | Component | Version | Role |
|-----------|------| |-----------|---------|------|
| Apache 2 + PHP-FPM 8.2/8.3 | Web server | | Apache 2 + PHP-FPM | 8.2 & 8.3 | Web server with multi-PHP support |
| PowerDNS | DNS server | | MariaDB | 10.x | Database server (WordPress-compatible) |
| Exim4 | Mail transfer agent | | PowerDNS | Latest | DNS server |
| Dovecot | IMAP / POP3 server | | Exim 4 | Latest | Mail transfer agent |
| MariaDB | Database server | | Dovecot | Latest | IMAP / POP3 server |
| SpamAssassin | Spam filtering | | SpamAssassin | Latest | Spam filtering |
| Fail2ban | Brute force protection | | Fail2ban | Latest | Brute-force protection |
| Let's Encrypt (certbot) | Free SSL certificates | | Let's Encrypt | Certbot | Free SSL certificates |
| NixPanel | Control panel (ports 2083, 2087) | | **NixPanel** | Latest | Control panel |
---
## After Installation
| Panel | URL | Default credentials |
|-------|-----|---------------------|
| NixServer (admin) | `https://your-ip:2087` | Set during install |
| NixClient (user) | `https://your-ip:2083` | Per-account |
---
## Updating
```bash
bash /opt/nixpanel/scripts/update.sh
```
Or click **Upgrade Panel** in the NixServer sidebar.
--- ---
## Stack ## Stack
- **Backend** — Node.js (Fastify), SQLite (panel DB), Prisma ORM | Layer | Technology |
- **Frontend** — React 18, Tailwind CSS, Vite |-------|-----------|
- **Auth** — JWT (access + refresh tokens), bcrypt | Panel backend | Rust · Axum · SQLx · Tokio |
| Database | MariaDB |
| Web server | Apache 2 (reverse proxy) |
| Auth | JWT · Argon2id |
| Frontend | React 18 · TypeScript · Tailwind CSS · Vite |
---
## Licensing
NixPanel uses a **central licensing server** at `license.nixpanel.io`. A license key is required during installation.
| Plan | Monthly | Annual | Servers |
|------|---------|--------|---------|
| Free | $0 | $0 | 1 |
| Solo | $9.99 | $95.90 | 1 |
| Host | $29.99 | $287.90 | 5 |
| Agency | $79.99 | $767.90 | Unlimited |
[Get a license → nixpanel.io](https://nixpanel.io/#pricing)
---
## Post-Install
| Task | Command |
|------|---------|
| Add SSL | `certbot --apache` |
| View logs | `journalctl -u nixpanel -f` |
| Restart panel | `systemctl restart nixpanel` |
| Update panel | `bash /opt/nixpanel/scripts/update.sh` |
Access your panels:
```
http://YOUR_IP:2087 ← NixServer (admin)
http://YOUR_IP:2083 ← NixClient (users)
```
--- ---
## Changelog ## Changelog
See [CHANGELOG.md](CHANGELOG.md) for full version history. See [CHANGELOG.md](CHANGELOG.md) for the full version history.
--- ---
## License ## License
NixPanel is source-available software. See [LICENSE](LICENSE) for details. NixPanel is **source-available** software. You may inspect and self-host under the terms of the [NixPanel License](LICENSE). Redistribution, resale, or offering NixPanel as a managed service is not permitted without a commercial agreement.
© 2025 NixPanel. All rights reserved.
+97 -250
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ────────────────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────────────────
# NixPanel Installer · Ubuntu 24.04 LTS · x86_64 # NixPanel Installer · Ubuntu 24.04 LTS · x86_64
# Installs: WHM (NixServer), cPanel (NixClient), Licensing Server, # Installs the NixPanel control panel (WHM + cPanel) on a customer server.
# Website API, and all system dependencies. # License validation runs against https://license.nixpanel.io
# ────────────────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────────────────
set -euo pipefail set -euo pipefail
@@ -44,14 +44,13 @@ ARCH=$(uname -m)
# ── Paths ───────────────────────────────────────────────────────────────────── # ── Paths ─────────────────────────────────────────────────────────────────────
INSTALL_DIR="/opt/nixpanel" INSTALL_DIR="/opt/nixpanel"
BIN_DIR="$INSTALL_DIR/bin" BIN_DIR="$INSTALL_DIR/bin"
KEYS_DIR="$INSTALL_DIR/keys"
LOG_DIR="/var/log/nixpanel" LOG_DIR="/var/log/nixpanel"
STEP_DIR="/var/lib/nixpanel/install" STEP_DIR="/var/lib/nixpanel/install"
SRC_DIR="$INSTALL_DIR/src" SRC_DIR="$INSTALL_DIR/src"
GITHUB_REPO="NixReaper/nixpanel" GITHUB_REPO="NixReaper/nixpanel"
LICENSING_URL="https://license.nixpanel.io"
mkdir -p "$INSTALL_DIR" "$BIN_DIR" "$KEYS_DIR" "$LOG_DIR" "$STEP_DIR" "$SRC_DIR" mkdir -p "$INSTALL_DIR" "$BIN_DIR" "$LOG_DIR" "$STEP_DIR" "$SRC_DIR"
chmod 700 "$KEYS_DIR"
mark_done() { touch "$STEP_DIR/$1.done"; } mark_done() { touch "$STEP_DIR/$1.done"; }
step_done() { [[ -f "$STEP_DIR/$1.done" ]]; } step_done() { [[ -f "$STEP_DIR/$1.done" ]]; }
@@ -89,13 +88,15 @@ if ! step_done "resolved_stub"; then
fi fi
success "Port 53 free" success "Port 53 free"
# ── 3. System packages (including ondrej/php PPA for PHP 8.2 on Ubuntu 24.04) ─ # ── 3. System packages ────────────────────────────────────────────────────────
step "Installing system packages" step "Installing system packages"
if ! step_done "packages"; then if ! step_done "packages"; then
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
# Ensure PPA tooling is present, then add ondrej/php for PHP 8.2 # Prereqs for add-apt-repository
apt-get install -y -qq ca-certificates gnupg software-properties-common apt-get install -y -qq ca-certificates gnupg software-properties-common
# ondrej/php PPA is required for PHP 8.2 on Ubuntu 24.04
if ! grep -rq "ondrej/php" /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null; then if ! grep -rq "ondrej/php" /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null; then
info "Adding ondrej/php PPA (required for PHP 8.2 on Ubuntu 24.04)…" info "Adding ondrej/php PPA (required for PHP 8.2 on Ubuntu 24.04)…"
add-apt-repository -y ppa:ondrej/php add-apt-repository -y ppa:ondrej/php
@@ -120,8 +121,8 @@ if ! step_done "packages"; then
spamassassin spamc \ spamassassin spamc \
certbot python3-certbot-apache \ certbot python3-certbot-apache \
fail2ban \ fail2ban \
nodejs npm \
openssl openssl
mark_done "packages" mark_done "packages"
fi fi
success "System packages installed" success "System packages installed"
@@ -129,13 +130,10 @@ success "System packages installed"
# ── 4. Rust toolchain ───────────────────────────────────────────────────────── # ── 4. Rust toolchain ─────────────────────────────────────────────────────────
step "Installing Rust toolchain" step "Installing Rust toolchain"
if ! step_done "rust"; then if ! step_done "rust"; then
# Install for root (used by this script) and persist for system builds
curl -fsSL https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal curl -fsSL https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal
source "$HOME/.cargo/env" source "$HOME/.cargo/env"
rustup target add x86_64-unknown-linux-gnu
mark_done "rust" mark_done "rust"
else else
# Ensure cargo is on PATH for subsequent steps
source "$HOME/.cargo/env" 2>/dev/null || true source "$HOME/.cargo/env" 2>/dev/null || true
fi fi
CARGO=$(command -v cargo) || error "cargo not found — Rust install may have failed" CARGO=$(command -v cargo) || error "cargo not found — Rust install may have failed"
@@ -152,47 +150,31 @@ if ! step_done "services_start"; then
fi fi
success "Service stack running" success "Service stack running"
# ── 6. MariaDB databases ────────────────────────────────────────────────────── # ── 6. MariaDB — panel database only ─────────────────────────────────────────
step "Configuring MariaDB databases" step "Configuring MariaDB"
if ! step_done "mariadb_setup"; then if ! step_done "mariadb_setup"; then
DB_PASS_PANEL=$(openssl rand -hex 20) DB_PASS_PANEL=$(openssl rand -hex 20)
DB_PASS_LICENSE=$(openssl rand -hex 20)
DB_PASS_WEBSITE=$(openssl rand -hex 20)
mysql -u root <<SQL mysql -u root <<SQL
CREATE DATABASE IF NOT EXISTS nixpanel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE IF NOT EXISTS nixpanel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS nixpanel_licensing CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS nixpanel_website CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'nixpanel'@'127.0.0.1' IDENTIFIED BY '${DB_PASS_PANEL}'; CREATE USER IF NOT EXISTS 'nixpanel'@'127.0.0.1' IDENTIFIED BY '${DB_PASS_PANEL}';
CREATE USER IF NOT EXISTS 'nixpanel_license'@'127.0.0.1' IDENTIFIED BY '${DB_PASS_LICENSE}';
CREATE USER IF NOT EXISTS 'nixpanel_web'@'127.0.0.1' IDENTIFIED BY '${DB_PASS_WEBSITE}';
GRANT ALL PRIVILEGES ON nixpanel.* TO 'nixpanel'@'127.0.0.1'; GRANT ALL PRIVILEGES ON nixpanel.* TO 'nixpanel'@'127.0.0.1';
GRANT ALL PRIVILEGES ON nixpanel_licensing.* TO 'nixpanel_license'@'127.0.0.1';
GRANT ALL PRIVILEGES ON nixpanel_website.* TO 'nixpanel_web'@'127.0.0.1';
FLUSH PRIVILEGES; FLUSH PRIVILEGES;
SQL SQL
# Store credentials for use below
echo "$DB_PASS_PANEL" > "$INSTALL_DIR/.db_pass_panel" echo "$DB_PASS_PANEL" > "$INSTALL_DIR/.db_pass_panel"
echo "$DB_PASS_LICENSE" > "$INSTALL_DIR/.db_pass_license" chmod 600 "$INSTALL_DIR/.db_pass_panel"
echo "$DB_PASS_WEBSITE" > "$INSTALL_DIR/.db_pass_website"
chmod 600 "$INSTALL_DIR"/.db_pass_*
mark_done "mariadb_setup" mark_done "mariadb_setup"
else else
DB_PASS_PANEL=$(cat "$INSTALL_DIR/.db_pass_panel") DB_PASS_PANEL=$(cat "$INSTALL_DIR/.db_pass_panel")
DB_PASS_LICENSE=$(cat "$INSTALL_DIR/.db_pass_license")
DB_PASS_WEBSITE=$(cat "$INSTALL_DIR/.db_pass_website")
fi fi
success "Databases created" success "Database ready"
# ── 7. Download / update source ─────────────────────────────────────────────── # ── 7. Download / update panel source ────────────────────────────────────────
step "Downloading NixPanel source" step "Downloading NixPanel source"
if ! step_done "source"; then if ! step_done "source"; then
LATEST_TAG=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \ LATEST_TAG=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \
| grep '"tag_name"' | cut -d'"' -f4 || echo "main") | grep '"tag_name"' | cut -d'"' -f4 || true)
[[ -z "$LATEST_TAG" ]] && LATEST_TAG="main" [[ -z "$LATEST_TAG" ]] && LATEST_TAG="main"
info "Fetching tag: $LATEST_TAG" info "Fetching tag: $LATEST_TAG"
@@ -208,130 +190,37 @@ if ! step_done "source"; then
fi fi
success "Source ready" success "Source ready"
# ── 8. Build Rust binaries ──────────────────────────────────────────────────── # ── 8. Build panel binary ─────────────────────────────────────────────────────
step "Building nixpanel-licensing (Rust)" step "Building nixpanel (Rust)"
if ! step_done "build_licensing"; then if ! step_done "build_panel"; then
cd "$SRC_DIR/nixpanel-licensing" if [[ -f "$SRC_DIR/Cargo.toml" ]]; then
cd "$SRC_DIR"
$CARGO build --release --quiet $CARGO build --release --quiet
cp target/release/nixpanel-licensing "$BIN_DIR/nixpanel-licensing" # Copy any produced binaries
cp target/release/keygen "$BIN_DIR/nixpanel-keygen" [[ -f "target/release/nixpanel" ]] && \
chmod 755 "$BIN_DIR/nixpanel-licensing" "$BIN_DIR/nixpanel-keygen" cp target/release/nixpanel "$BIN_DIR/nixpanel" && chmod 755 "$BIN_DIR/nixpanel"
mark_done "build_licensing" mark_done "build_panel"
success "Panel binary built"
else
warn "Panel Rust source not yet present in repo — skipping build"
warn "This is expected during early development. Re-run installer when source is ready."
fi fi
success "nixpanel-licensing built"
step "Building nixpanel-website-api (Rust)"
if ! step_done "build_website_api"; then
cd "$SRC_DIR/nixpanel-website/api"
$CARGO build --release --quiet
cp target/release/nixpanel-website-api "$BIN_DIR/nixpanel-website-api"
chmod 755 "$BIN_DIR/nixpanel-website-api"
mark_done "build_website_api"
fi fi
success "nixpanel-website-api built"
# ── 9. RSA key generation ───────────────────────────────────────────────────── # ── 9. Secrets ────────────────────────────────────────────────────────────────
step "Generating RSA-4096 license signing keys"
if ! step_done "keygen"; then
# Run keygen from the licensing source dir so it finds ./keys/
cd "$SRC_DIR/nixpanel-licensing"
"$BIN_DIR/nixpanel-keygen"
cp keys/private.pem "$KEYS_DIR/license_private.pem"
cp keys/public.pem "$KEYS_DIR/license_public.pem"
chmod 600 "$KEYS_DIR/license_private.pem"
chmod 644 "$KEYS_DIR/license_public.pem"
mark_done "keygen"
fi
success "RSA keys generated → $KEYS_DIR"
# ── 10. Secrets ───────────────────────────────────────────────────────────────
step "Generating secrets" step "Generating secrets"
if ! step_done "secrets"; then if ! step_done "secrets"; then
JWT_SECRET_LICENSE=$(openssl rand -hex 64)
JWT_SECRET_WEBSITE=$(openssl rand -hex 64)
JWT_SECRET_PANEL=$(openssl rand -hex 64) JWT_SECRET_PANEL=$(openssl rand -hex 64)
LICENSING_API_KEY=$(openssl rand -hex 32)
echo "$JWT_SECRET_LICENSE" > "$INSTALL_DIR/.jwt_license"
echo "$JWT_SECRET_WEBSITE" > "$INSTALL_DIR/.jwt_website"
echo "$JWT_SECRET_PANEL" > "$INSTALL_DIR/.jwt_panel" echo "$JWT_SECRET_PANEL" > "$INSTALL_DIR/.jwt_panel"
echo "$LICENSING_API_KEY" > "$INSTALL_DIR/.licensing_api_key" chmod 600 "$INSTALL_DIR/.jwt_panel"
chmod 600 "$INSTALL_DIR"/.jwt_* "$INSTALL_DIR/.licensing_api_key"
mark_done "secrets" mark_done "secrets"
else else
JWT_SECRET_LICENSE=$(cat "$INSTALL_DIR/.jwt_license")
JWT_SECRET_WEBSITE=$(cat "$INSTALL_DIR/.jwt_website")
JWT_SECRET_PANEL=$(cat "$INSTALL_DIR/.jwt_panel") JWT_SECRET_PANEL=$(cat "$INSTALL_DIR/.jwt_panel")
LICENSING_API_KEY=$(cat "$INSTALL_DIR/.licensing_api_key")
fi fi
success "Secrets ready" success "Secrets ready"
# ── 11. Environment files ───────────────────────────────────────────────────── # ── 10. Admin setup ───────────────────────────────────────────────────────────
step "Writing environment files" step "Panel configuration"
# nixpanel-licensing
cat > "$INSTALL_DIR/licensing.env" <<EOF
HOST=127.0.0.1
PORT=3000
RUST_LOG=nixpanel_licensing=info,tower_http=warn
DATABASE_URL=mysql://nixpanel_license:${DB_PASS_LICENSE}@127.0.0.1:3306/nixpanel_licensing
JWT_SECRET=${JWT_SECRET_LICENSE}
JWT_EXPIRES_IN_SECS=86400
LICENSE_PRIVATE_KEY_PATH=${KEYS_DIR}/license_private.pem
LICENSE_PUBLIC_KEY_PATH=${KEYS_DIR}/license_public.pem
LICENSE_TOKEN_TTL_DAYS=30
LICENSE_GRACE_PERIOD_DAYS=7
EOF
# nixpanel-website-api (filled in after admin prompt below)
# Written at step 13
# Main panel
cat > "$INSTALL_DIR/.env" <<EOF
NODE_ENV=production
PORT=4000
JWT_SECRET=${JWT_SECRET_PANEL}
DATABASE_URL=mysql://nixpanel:${DB_PASS_PANEL}@127.0.0.1:3306/nixpanel
INSTALL_DIR=${INSTALL_DIR}
EOF
chmod 600 "$INSTALL_DIR/licensing.env" "$INSTALL_DIR/.env"
success "Environment files written"
# ── 12. systemd — licensing server ───────────────────────────────────────────
step "Installing systemd service: nixpanel-licensing"
if ! step_done "systemd_licensing"; then
cat > /etc/systemd/system/nixpanel-licensing.service <<EOF
[Unit]
Description=NixPanel Licensing Server
Documentation=https://nixpanel.io/docs
After=network.target mariadb.service
Wants=mariadb.service
[Service]
Type=simple
User=root
ExecStart=${BIN_DIR}/nixpanel-licensing
WorkingDirectory=${INSTALL_DIR}
EnvironmentFile=${INSTALL_DIR}/licensing.env
Restart=on-failure
RestartSec=5
StandardOutput=append:${LOG_DIR}/licensing.log
StandardError=append:${LOG_DIR}/licensing-error.log
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable nixpanel-licensing
systemctl start nixpanel-licensing
mark_done "systemd_licensing"
fi
success "nixpanel-licensing service running"
# ── 13. Admin account + website env ──────────────────────────────────────────
step "Creating admin account"
if ! step_done "admin_account"; then if ! step_done "admin_account"; then
echo "" echo ""
echo -e " ${BOLD}Create your NixPanel admin account${RESET}" echo -e " ${BOLD}Create your NixPanel admin account${RESET}"
@@ -343,88 +232,54 @@ if ! step_done "admin_account"; then
read -rp " Admin email: " ADMIN_EMAIL read -rp " Admin email: " ADMIN_EMAIL
read -rp " Server hostname/domain [$(hostname -f)]: " SERVER_HOST read -rp " Server hostname/domain [$(hostname -f)]: " SERVER_HOST
SERVER_HOST="${SERVER_HOST:-$(hostname -f)}" SERVER_HOST="${SERVER_HOST:-$(hostname -f)}"
read -rp " NixPanel license key: " LICENSE_KEY
# Prompt for Stripe keys (can be left blank for now) echo "$SERVER_HOST" > "$INSTALL_DIR/.server_host"
echo "$LICENSE_KEY" > "$INSTALL_DIR/.license_key"
chmod 600 "$INSTALL_DIR/.server_host" "$INSTALL_DIR/.license_key"
# Validate license key against central server
info "Validating license key with ${LICENSING_URL}…"
SERVER_IP=$(hostname -I | awk '{print $1}')
HTTP_STATUS=$(curl -s -o /tmp/lic_resp.json -w "%{http_code}" \
-X POST "${LICENSING_URL}/api/v1/activate" \
-H "Content-Type: application/json" \
-d "{\"license_key\":\"${LICENSE_KEY}\",\"server_ip\":\"${SERVER_IP}\"}" \
2>/dev/null || echo "000")
if [[ "$HTTP_STATUS" == "200" ]]; then
success "License activated"
elif [[ "$HTTP_STATUS" == "000" ]]; then
warn "Could not reach ${LICENSING_URL} — proceeding in grace period mode"
else
warn "License server returned HTTP ${HTTP_STATUS}:"
cat /tmp/lic_resp.json 2>/dev/null || true
echo "" echo ""
echo -e " ${BOLD}Stripe billing (press Enter to skip — configure later in .env)${RESET}" warn "Continuing install — fix license key in ${INSTALL_DIR}/.license_key and restart nixpanel"
read -rp " Stripe secret key (sk_live_...): " STRIPE_SK; STRIPE_SK="${STRIPE_SK:-}" fi
read -rp " Stripe webhook secret (whsec_...): " STRIPE_WEBHOOK; STRIPE_WEBHOOK="${STRIPE_WEBHOOK:-}"
read -rp " SMTP host [smtp.mailgun.org]: " MAIL_HOST; MAIL_HOST="${MAIL_HOST:-smtp.mailgun.org}"
read -rp " SMTP user: " MAIL_USER; MAIL_USER="${MAIL_USER:-}"
read -rsp " SMTP password: " MAIL_PASS; MAIL_PASS="${MAIL_PASS:-}"; echo ""
# Write website-api env now that we have the answers
cat > "$INSTALL_DIR/website.env" <<EOF
HOST=127.0.0.1
PORT=4001
RUST_LOG=nixpanel_website_api=info,tower_http=warn
DATABASE_URL=mysql://nixpanel_web:${DB_PASS_WEBSITE}@127.0.0.1:3306/nixpanel_website
JWT_SECRET=${JWT_SECRET_WEBSITE}
JWT_EXPIRES_IN_SECS=604800
APP_URL=https://${SERVER_HOST}
CORS_ORIGIN=https://${SERVER_HOST}
STRIPE_SECRET_KEY=${STRIPE_SK}
STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK}
STRIPE_PRICE_SOLO_MONTHLY=
STRIPE_PRICE_SOLO_ANNUAL=
STRIPE_PRICE_HOST_MONTHLY=
STRIPE_PRICE_HOST_ANNUAL=
STRIPE_PRICE_AGENCY_MONTHLY=
STRIPE_PRICE_AGENCY_ANNUAL=
LICENSING_SERVER_URL=http://127.0.0.1:3000
LICENSING_SERVER_API_KEY=${LICENSING_API_KEY}
MAIL_HOST=${MAIL_HOST}
MAIL_PORT=587
MAIL_USER=${MAIL_USER}
MAIL_PASSWORD=${MAIL_PASS}
MAIL_FROM=noreply@${SERVER_HOST}
EOF
chmod 600 "$INSTALL_DIR/website.env"
# Create admin via main panel script
node "$INSTALL_DIR/scripts/create-admin.js" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--email "$ADMIN_EMAIL" \
2>/dev/null || warn "Admin creation script not found — set credentials via panel after install"
mark_done "admin_account" mark_done "admin_account"
else
SERVER_HOST=$(cat "$INSTALL_DIR/.server_host" 2>/dev/null || hostname -f)
fi fi
success "Admin account ready" success "Panel configuration done"
# ── 14. systemd — website API ───────────────────────────────────────────────── # ── 11. Environment file ──────────────────────────────────────────────────────
step "Installing systemd service: nixpanel-website-api" step "Writing environment file"
if ! step_done "systemd_website"; then cat > "$INSTALL_DIR/.env" <<EOF
cat > /etc/systemd/system/nixpanel-website-api.service <<EOF RUST_LOG=nixpanel=info,tower_http=warn
[Unit] PORT=4000
Description=NixPanel Website API JWT_SECRET=${JWT_SECRET_PANEL}
Documentation=https://nixpanel.io/docs DATABASE_URL=mysql://nixpanel:${DB_PASS_PANEL}@127.0.0.1:3306/nixpanel
After=network.target mariadb.service nixpanel-licensing.service SERVER_HOST=${SERVER_HOST:-$(hostname -f)}
Wants=mariadb.service LICENSING_SERVER_URL=${LICENSING_URL}
LICENSE_KEY_PATH=${INSTALL_DIR}/.license_key
[Service] INSTALL_DIR=${INSTALL_DIR}
Type=simple
User=root
ExecStart=${BIN_DIR}/nixpanel-website-api
WorkingDirectory=${INSTALL_DIR}
EnvironmentFile=${INSTALL_DIR}/website.env
Restart=on-failure
RestartSec=5
StandardOutput=append:${LOG_DIR}/website-api.log
StandardError=append:${LOG_DIR}/website-api-error.log
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF EOF
systemctl daemon-reload chmod 600 "$INSTALL_DIR/.env"
systemctl enable nixpanel-website-api success "Environment file written"
systemctl start nixpanel-website-api
mark_done "systemd_website"
fi
success "nixpanel-website-api service running"
# ── 15. systemd — main panel ────────────────────────────────────────────────── # ── 12. systemd — panel ───────────────────────────────────────────────────────
step "Installing systemd service: nixpanel" step "Installing systemd service: nixpanel"
if ! step_done "systemd_panel"; then if ! step_done "systemd_panel"; then
cat > /etc/systemd/system/nixpanel.service <<EOF cat > /etc/systemd/system/nixpanel.service <<EOF
@@ -437,7 +292,7 @@ Wants=mariadb.service
[Service] [Service]
Type=simple Type=simple
User=root User=root
ExecStart=${INSTALL_DIR}/bin/nixpanel ExecStart=${BIN_DIR}/nixpanel
WorkingDirectory=${INSTALL_DIR} WorkingDirectory=${INSTALL_DIR}
EnvironmentFile=${INSTALL_DIR}/.env EnvironmentFile=${INSTALL_DIR}/.env
Restart=on-failure Restart=on-failure
@@ -451,16 +306,21 @@ WantedBy=multi-user.target
EOF EOF
systemctl daemon-reload systemctl daemon-reload
systemctl enable nixpanel systemctl enable nixpanel
# Only start if the binary exists
if [[ -f "$BIN_DIR/nixpanel" ]]; then
systemctl start nixpanel systemctl start nixpanel
else
warn "Panel binary not built yet — service enabled but not started"
warn "Re-run installer after panel source is added to the repo"
fi
mark_done "systemd_panel" mark_done "systemd_panel"
fi fi
success "nixpanel service running" success "nixpanel service configured"
# ── 16. Apache vhosts ───────────────────────────────────────────────────────── # ── 13. Apache vhosts ─────────────────────────────────────────────────────────
step "Configuring Apache reverse proxies" step "Configuring Apache reverse proxies"
if ! step_done "apache_vhost"; then if ! step_done "apache_vhost"; then
# Add non-standard ports if not already present for port in 2083 2087; do
for port in 2083 2087 4001; do
grep -q "^Listen ${port}" /etc/apache2/ports.conf \ grep -q "^Listen ${port}" /etc/apache2/ports.conf \
|| echo "Listen ${port}" >> /etc/apache2/ports.conf || echo "Listen ${port}" >> /etc/apache2/ports.conf
done done
@@ -499,13 +359,6 @@ if ! step_done "apache_vhost"; then
ErrorLog /var/log/nixpanel/nixclient-error.log ErrorLog /var/log/nixpanel/nixclient-error.log
CustomLog /var/log/nixpanel/nixclient-access.log combined CustomLog /var/log/nixpanel/nixclient-access.log combined
</VirtualHost> </VirtualHost>
# ── NixPanel Website API (port 4001) ──────────────────────────────────────────
<VirtualHost *:4001>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:4001/
ProxyPassReverse / http://127.0.0.1:4001/
</VirtualHost>
APACHEEOF APACHEEOF
a2ensite nixpanel a2ensite nixpanel
@@ -514,13 +367,13 @@ APACHEEOF
fi fi
success "Apache vhosts configured" success "Apache vhosts configured"
# ── 17. Fail2ban ────────────────────────────────────────────────────────────── # ── 14. Fail2ban ──────────────────────────────────────────────────────────────
step "Configuring Fail2ban" step "Configuring Fail2ban"
if ! step_done "fail2ban"; then if ! step_done "fail2ban"; then
cat > /etc/fail2ban/jail.d/nixpanel.conf <<'EOF' cat > /etc/fail2ban/jail.d/nixpanel.conf <<'EOF'
[nixpanel-auth] [nixpanel-auth]
enabled = true enabled = true
port = 2083,2087,4001 port = 2083,2087
filter = nixpanel-auth filter = nixpanel-auth
logpath = /var/log/nixpanel/*.log logpath = /var/log/nixpanel/*.log
maxretry = 10 maxretry = 10
@@ -532,23 +385,20 @@ EOF
fi fi
success "Fail2ban configured" success "Fail2ban configured"
# ── 18. File permissions ────────────────────────────────────────────────────── # ── 15. File permissions ──────────────────────────────────────────────────────
step "Setting permissions" step "Setting permissions"
chown -R root:root "$INSTALL_DIR" chown -R root:root "$INSTALL_DIR"
chmod 700 "$KEYS_DIR" chmod 600 "$INSTALL_DIR/.env" 2>/dev/null || true
chmod 600 "$INSTALL_DIR"/.env \ find "$INSTALL_DIR/bin" -type f -exec chmod 755 {} \; 2>/dev/null || true
"$INSTALL_DIR"/licensing.env \
"$INSTALL_DIR"/website.env 2>/dev/null || true
find "$INSTALL_DIR/bin" -type f -exec chmod 755 {} \;
[[ -d "$INSTALL_DIR/nixserver/dist" ]] && \ [[ -d "$INSTALL_DIR/nixserver/dist" ]] && \
find "$INSTALL_DIR/nixserver/dist" \( -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \) find "$INSTALL_DIR/nixserver/dist" \( -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \)
[[ -d "$INSTALL_DIR/nixclient/dist" ]] && \ [[ -d "$INSTALL_DIR/nixclient/dist" ]] && \
find "$INSTALL_DIR/nixclient/dist" \( -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \) find "$INSTALL_DIR/nixclient/dist" \( -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \)
success "Permissions set" success "Permissions set"
# ── 19. Service health check ────────────────────────────────────────────────── # ── 16. Service health check ──────────────────────────────────────────────────
step "Verifying services" step "Verifying services"
sleep 2 # give systemd a moment sleep 2
check_service() { check_service() {
if systemctl is-active --quiet "$1"; then if systemctl is-active --quiet "$1"; then
@@ -558,11 +408,13 @@ check_service() {
fi fi
} }
check_service nixpanel-licensing
check_service nixpanel-website-api
check_service nixpanel
check_service apache2 check_service apache2
check_service mariadb check_service mariadb
check_service fail2ban
if [[ -f "$BIN_DIR/nixpanel" ]]; then
check_service nixpanel
fi
# ── Done ────────────────────────────────────────────────────────────────────── # ── Done ──────────────────────────────────────────────────────────────────────
SERVER_IP=$(hostname -I | awk '{print $1}') SERVER_IP=$(hostname -I | awk '{print $1}')
@@ -574,16 +426,11 @@ echo -e "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━
echo "" echo ""
echo -e " ${BOLD}WHM (Admin panel):${RESET} http://${SERVER_IP}:2087" echo -e " ${BOLD}WHM (Admin panel):${RESET} http://${SERVER_IP}:2087"
echo -e " ${BOLD}cPanel (User panel):${RESET} http://${SERVER_IP}:2083" echo -e " ${BOLD}cPanel (User panel):${RESET} http://${SERVER_IP}:2083"
echo -e " ${BOLD}Website API:${RESET} http://${SERVER_IP}:4001" echo -e " ${BOLD}Licensing server:${RESET} ${LICENSING_URL} (central)"
echo -e " ${BOLD}Licensing server:${RESET} http://127.0.0.1:3000 (internal only)"
echo "" echo ""
echo -e " ${BOLD}RSA public key:${RESET} ${KEYS_DIR}/license_public.pem"
echo -e " ${BOLD}Logs:${RESET} ${LOG_DIR}/" echo -e " ${BOLD}Logs:${RESET} ${LOG_DIR}/"
echo -e " ${BOLD}Config:${RESET} ${INSTALL_DIR}/*.env" echo -e " ${BOLD}Config:${RESET} ${INSTALL_DIR}/.env"
echo ""
echo -e " ${YELLOW}Stripe Price IDs must still be added to:${RESET}"
echo -e " ${INSTALL_DIR}/website.env"
echo "" echo ""
echo -e " To add SSL: certbot --apache" echo -e " To add SSL: certbot --apache"
echo -e " To restart: systemctl restart nixpanel nixpanel-licensing nixpanel-website-api" echo -e " To restart: systemctl restart nixpanel"
echo "" echo ""