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 8b1e42171a
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.
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
- 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.
- `update.sh` no longer blocked by local `package-lock.json` changes.
- `.gitignore` corrected for `nixserver/` and `nixclient/` dist paths.
### Planned
- NixServer (WHM) — full Rust backend
- NixClient (cPanel) — full Rust backend
- 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
- Login page now fetches version from `/api/health` dynamically instead of showing a hardcoded stale version number.
- Login page subtitle changed from "Web Host Manager" to "Admin Panel".
### Added
- **Installer** (`install.sh`) — fully automated Ubuntu 24.04 installer
- 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
### 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.
[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
+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
or internal business use, subject to the following conditions:
GRANT OF RIGHTS
1. REDISTRIBUTION PROHIBITED — You may not redistribute, resell, sublicense,
or offer this software (or any derivative) as a service without explicit
written permission from the copyright holder.
Subject to the terms of this License, NixPanel grants you a non-exclusive,
non-transferable, limited right to:
2. MODIFICATION — You may modify the software for your own use. Modified
versions may not be distributed publicly or commercially.
1. View and inspect the source code for personal evaluation and security
review purposes.
3. ATTRIBUTION — Any permitted use must retain this copyright notice and
license in all copies or substantial portions of the software.
2. Install and operate the software on servers that you own or control,
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
kind. The copyright holder is not liable for any damages arising from use.
RESTRICTIONS
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
+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
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.
**NixClient** (port 2083) — End-user panel for hosting account holders.
[![Latest Release](https://img.shields.io/github/v/release/NixReaper/nixpanel?style=flat-square&color=00c2a0&label=release)](https://github.com/NixReaper/nixpanel/releases)
[![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
| Component | Version |
|-----------|---------|
| OS | Ubuntu 24.04 LTS |
| Architecture | x86_64 |
| RAM | 2 GB minimum, 4 GB recommended |
| Disk | 20 GB minimum |
| Root access | Required |
| | |
|--|--|
| **OS** | Ubuntu 24.04 LTS (x86_64) |
| **RAM** | 2 GB minimum · 4 GB recommended |
| **Disk** | 20 GB minimum |
| **Access** | Root |
---
@@ -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)
```
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
curl -fsSL https://raw.githubusercontent.com/NixReaper/nixpanel/main/install.sh -o install.sh
less install.sh
bash install.sh
sudo bash install.sh
```
---
## What Gets Installed
| Component | Role |
|-----------|------|
| Apache 2 + PHP-FPM 8.2/8.3 | Web server |
| PowerDNS | DNS server |
| Exim4 | Mail transfer agent |
| Dovecot | IMAP / POP3 server |
| MariaDB | Database server |
| SpamAssassin | Spam filtering |
| Fail2ban | Brute force protection |
| Let's Encrypt (certbot) | Free SSL certificates |
| NixPanel | Control panel (ports 2083, 2087) |
---
## 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.
| Component | Version | Role |
|-----------|---------|------|
| Apache 2 + PHP-FPM | 8.2 & 8.3 | Web server with multi-PHP support |
| MariaDB | 10.x | Database server (WordPress-compatible) |
| PowerDNS | Latest | DNS server |
| Exim 4 | Latest | Mail transfer agent |
| Dovecot | Latest | IMAP / POP3 server |
| SpamAssassin | Latest | Spam filtering |
| Fail2ban | Latest | Brute-force protection |
| Let's Encrypt | Certbot | Free SSL certificates |
| **NixPanel** | Latest | Control panel |
---
## Stack
- **Backend** — Node.js (Fastify), SQLite (panel DB), Prisma ORM
- **Frontend** — React 18, Tailwind CSS, Vite
- **Auth** — JWT (access + refresh tokens), bcrypt
| Layer | Technology |
|-------|-----------|
| 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
See [CHANGELOG.md](CHANGELOG.md) for full version history.
See [CHANGELOG.md](CHANGELOG.md) for the full version history.
---
## 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.
+98 -251
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────────────
# NixPanel Installer · Ubuntu 24.04 LTS · x86_64
# Installs: WHM (NixServer), cPanel (NixClient), Licensing Server,
# Website API, and all system dependencies.
# Installs the NixPanel control panel (WHM + cPanel) on a customer server.
# License validation runs against https://license.nixpanel.io
# ──────────────────────────────────────────────────────────────────────────────
set -euo pipefail
@@ -44,14 +44,13 @@ ARCH=$(uname -m)
# ── Paths ─────────────────────────────────────────────────────────────────────
INSTALL_DIR="/opt/nixpanel"
BIN_DIR="$INSTALL_DIR/bin"
KEYS_DIR="$INSTALL_DIR/keys"
LOG_DIR="/var/log/nixpanel"
STEP_DIR="/var/lib/nixpanel/install"
SRC_DIR="$INSTALL_DIR/src"
GITHUB_REPO="NixReaper/nixpanel"
LICENSING_URL="https://license.nixpanel.io"
mkdir -p "$INSTALL_DIR" "$BIN_DIR" "$KEYS_DIR" "$LOG_DIR" "$STEP_DIR" "$SRC_DIR"
chmod 700 "$KEYS_DIR"
mkdir -p "$INSTALL_DIR" "$BIN_DIR" "$LOG_DIR" "$STEP_DIR" "$SRC_DIR"
mark_done() { touch "$STEP_DIR/$1.done"; }
step_done() { [[ -f "$STEP_DIR/$1.done" ]]; }
@@ -89,13 +88,15 @@ if ! step_done "resolved_stub"; then
fi
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"
if ! step_done "packages"; then
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
# 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
info "Adding ondrej/php PPA (required for PHP 8.2 on Ubuntu 24.04)…"
add-apt-repository -y ppa:ondrej/php
@@ -120,8 +121,8 @@ if ! step_done "packages"; then
spamassassin spamc \
certbot python3-certbot-apache \
fail2ban \
nodejs npm \
openssl
mark_done "packages"
fi
success "System packages installed"
@@ -129,13 +130,10 @@ success "System packages installed"
# ── 4. Rust toolchain ─────────────────────────────────────────────────────────
step "Installing Rust toolchain"
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
source "$HOME/.cargo/env"
rustup target add x86_64-unknown-linux-gnu
mark_done "rust"
else
# Ensure cargo is on PATH for subsequent steps
source "$HOME/.cargo/env" 2>/dev/null || true
fi
CARGO=$(command -v cargo) || error "cargo not found — Rust install may have failed"
@@ -152,47 +150,31 @@ if ! step_done "services_start"; then
fi
success "Service stack running"
# ── 6. MariaDB databases ──────────────────────────────────────────────────────
step "Configuring MariaDB databases"
# ── 6. MariaDB — panel database only ─────────────────────────────────────────
step "Configuring MariaDB"
if ! step_done "mariadb_setup"; then
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
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_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_licensing.* TO 'nixpanel_license'@'127.0.0.1';
GRANT ALL PRIVILEGES ON nixpanel_website.* TO 'nixpanel_web'@'127.0.0.1';
FLUSH PRIVILEGES;
SQL
# Store credentials for use below
echo "$DB_PASS_PANEL" > "$INSTALL_DIR/.db_pass_panel"
echo "$DB_PASS_LICENSE" > "$INSTALL_DIR/.db_pass_license"
echo "$DB_PASS_WEBSITE" > "$INSTALL_DIR/.db_pass_website"
chmod 600 "$INSTALL_DIR"/.db_pass_*
chmod 600 "$INSTALL_DIR/.db_pass_panel"
mark_done "mariadb_setup"
else
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
success "Databases created"
success "Database ready"
# ── 7. Download / update source ───────────────────────────────────────────────
# ── 7. Download / update panel source ────────────────────────────────────────
step "Downloading NixPanel source"
if ! step_done "source"; then
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"
info "Fetching tag: $LATEST_TAG"
@@ -208,130 +190,37 @@ if ! step_done "source"; then
fi
success "Source ready"
# ── 8. Build Rust binaries ────────────────────────────────────────────────────
step "Building nixpanel-licensing (Rust)"
if ! step_done "build_licensing"; then
cd "$SRC_DIR/nixpanel-licensing"
# ── 8. Build panel binary ─────────────────────────────────────────────────────
step "Building nixpanel (Rust)"
if ! step_done "build_panel"; then
if [[ -f "$SRC_DIR/Cargo.toml" ]]; then
cd "$SRC_DIR"
$CARGO build --release --quiet
cp target/release/nixpanel-licensing "$BIN_DIR/nixpanel-licensing"
cp target/release/keygen "$BIN_DIR/nixpanel-keygen"
chmod 755 "$BIN_DIR/nixpanel-licensing" "$BIN_DIR/nixpanel-keygen"
mark_done "build_licensing"
# Copy any produced binaries
[[ -f "target/release/nixpanel" ]] && \
cp target/release/nixpanel "$BIN_DIR/nixpanel" && chmod 755 "$BIN_DIR/nixpanel"
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
success "nixpanel-website-api built"
# ── 9. RSA key generation ─────────────────────────────────────────────────────
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 ───────────────────────────────────────────────────────────────
# ── 9. Secrets ────────────────────────────────────────────────────────────────
step "Generating secrets"
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)
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 "$LICENSING_API_KEY" > "$INSTALL_DIR/.licensing_api_key"
chmod 600 "$INSTALL_DIR"/.jwt_* "$INSTALL_DIR/.licensing_api_key"
chmod 600 "$INSTALL_DIR/.jwt_panel"
mark_done "secrets"
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")
LICENSING_API_KEY=$(cat "$INSTALL_DIR/.licensing_api_key")
fi
success "Secrets ready"
# ── 11. Environment files ─────────────────────────────────────────────────────
step "Writing environment files"
# 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"
# ── 10. Admin setup ───────────────────────────────────────────────────────────
step "Panel configuration"
if ! step_done "admin_account"; then
echo ""
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 " Server hostname/domain [$(hostname -f)]: " SERVER_HOST
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 -e " ${BOLD}Stripe billing (press Enter to skip — configure later in .env)${RESET}"
read -rp " Stripe secret key (sk_live_...): " STRIPE_SK; STRIPE_SK="${STRIPE_SK:-}"
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"
warn "Continuing install — fix license key in ${INSTALL_DIR}/.license_key and restart nixpanel"
fi
mark_done "admin_account"
else
SERVER_HOST=$(cat "$INSTALL_DIR/.server_host" 2>/dev/null || hostname -f)
fi
success "Admin account ready"
success "Panel configuration done"
# ── 14. systemd — website API ─────────────────────────────────────────────────
step "Installing systemd service: nixpanel-website-api"
if ! step_done "systemd_website"; then
cat > /etc/systemd/system/nixpanel-website-api.service <<EOF
[Unit]
Description=NixPanel Website API
Documentation=https://nixpanel.io/docs
After=network.target mariadb.service nixpanel-licensing.service
Wants=mariadb.service
[Service]
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
# ── 11. Environment file ──────────────────────────────────────────────────────
step "Writing environment file"
cat > "$INSTALL_DIR/.env" <<EOF
RUST_LOG=nixpanel=info,tower_http=warn
PORT=4000
JWT_SECRET=${JWT_SECRET_PANEL}
DATABASE_URL=mysql://nixpanel:${DB_PASS_PANEL}@127.0.0.1:3306/nixpanel
SERVER_HOST=${SERVER_HOST:-$(hostname -f)}
LICENSING_SERVER_URL=${LICENSING_URL}
LICENSE_KEY_PATH=${INSTALL_DIR}/.license_key
INSTALL_DIR=${INSTALL_DIR}
EOF
systemctl daemon-reload
systemctl enable nixpanel-website-api
systemctl start nixpanel-website-api
mark_done "systemd_website"
fi
success "nixpanel-website-api service running"
chmod 600 "$INSTALL_DIR/.env"
success "Environment file written"
# ── 15. systemd — main panel ──────────────────────────────────────────────────
# ── 12. systemd — panel ───────────────────────────────────────────────────────
step "Installing systemd service: nixpanel"
if ! step_done "systemd_panel"; then
cat > /etc/systemd/system/nixpanel.service <<EOF
@@ -437,7 +292,7 @@ Wants=mariadb.service
[Service]
Type=simple
User=root
ExecStart=${INSTALL_DIR}/bin/nixpanel
ExecStart=${BIN_DIR}/nixpanel
WorkingDirectory=${INSTALL_DIR}
EnvironmentFile=${INSTALL_DIR}/.env
Restart=on-failure
@@ -451,16 +306,21 @@ WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable nixpanel
# Only start if the binary exists
if [[ -f "$BIN_DIR/nixpanel" ]]; then
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"
fi
success "nixpanel service running"
success "nixpanel service configured"
# ── 16. Apache vhosts ─────────────────────────────────────────────────────────
# ── 13. Apache vhosts ─────────────────────────────────────────────────────────
step "Configuring Apache reverse proxies"
if ! step_done "apache_vhost"; then
# Add non-standard ports if not already present
for port in 2083 2087 4001; do
for port in 2083 2087; do
grep -q "^Listen ${port}" /etc/apache2/ports.conf \
|| echo "Listen ${port}" >> /etc/apache2/ports.conf
done
@@ -499,13 +359,6 @@ if ! step_done "apache_vhost"; then
ErrorLog /var/log/nixpanel/nixclient-error.log
CustomLog /var/log/nixpanel/nixclient-access.log combined
</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
a2ensite nixpanel
@@ -514,13 +367,13 @@ APACHEEOF
fi
success "Apache vhosts configured"
# ── 17. Fail2ban ──────────────────────────────────────────────────────────────
# ── 14. Fail2ban ──────────────────────────────────────────────────────────────
step "Configuring Fail2ban"
if ! step_done "fail2ban"; then
cat > /etc/fail2ban/jail.d/nixpanel.conf <<'EOF'
[nixpanel-auth]
enabled = true
port = 2083,2087,4001
port = 2083,2087
filter = nixpanel-auth
logpath = /var/log/nixpanel/*.log
maxretry = 10
@@ -532,23 +385,20 @@ EOF
fi
success "Fail2ban configured"
# ── 18. File permissions ──────────────────────────────────────────────────────
# ── 15. File permissions ──────────────────────────────────────────────────────
step "Setting permissions"
chown -R root:root "$INSTALL_DIR"
chmod 700 "$KEYS_DIR"
chmod 600 "$INSTALL_DIR"/.env \
"$INSTALL_DIR"/licensing.env \
"$INSTALL_DIR"/website.env 2>/dev/null || true
find "$INSTALL_DIR/bin" -type f -exec chmod 755 {} \;
chmod 600 "$INSTALL_DIR/.env" 2>/dev/null || true
find "$INSTALL_DIR/bin" -type f -exec chmod 755 {} \; 2>/dev/null || true
[[ -d "$INSTALL_DIR/nixserver/dist" ]] && \
find "$INSTALL_DIR/nixserver/dist" \( -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \)
[[ -d "$INSTALL_DIR/nixclient/dist" ]] && \
find "$INSTALL_DIR/nixclient/dist" \( -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \)
success "Permissions set"
# ── 19. Service health check ──────────────────────────────────────────────────
# ── 16. Service health check ──────────────────────────────────────────────────
step "Verifying services"
sleep 2 # give systemd a moment
sleep 2
check_service() {
if systemctl is-active --quiet "$1"; then
@@ -558,11 +408,13 @@ check_service() {
fi
}
check_service nixpanel-licensing
check_service nixpanel-website-api
check_service nixpanel
check_service apache2
check_service mariadb
check_service fail2ban
if [[ -f "$BIN_DIR/nixpanel" ]]; then
check_service nixpanel
fi
# ── Done ──────────────────────────────────────────────────────────────────────
SERVER_IP=$(hostname -I | awk '{print $1}')
@@ -574,16 +426,11 @@ echo -e "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━
echo ""
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}Website API:${RESET} http://${SERVER_IP}:4001"
echo -e " ${BOLD}Licensing server:${RESET} http://127.0.0.1:3000 (internal only)"
echo -e " ${BOLD}Licensing server:${RESET} ${LICENSING_URL} (central)"
echo ""
echo -e " ${BOLD}RSA public key:${RESET} ${KEYS_DIR}/license_public.pem"
echo -e " ${BOLD}Logs:${RESET} ${LOG_DIR}/"
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 -e " ${BOLD}Config:${RESET} ${INSTALL_DIR}/.env"
echo ""
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 ""