From 29c18c5af845b5b3bbc301c0c679bf60ed6edc35 Mon Sep 17 00:00:00 2001 From: NixReaper Date: Sat, 25 Apr 2026 05:37:31 -0500 Subject: [PATCH] fix: rename setInterval to setBilling, add deploy.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - pricing.php: rename setInterval() to setBilling() to stop shadowing the native window.setInterval — the billing toggle was silently broken - deploy.sh: full automated deploy script for nixpanel.io - DocumentRoot set to public/ (fixes /pricing, /login 404s) - AllowOverride All so public/.htaccess handles all routing - PHP 8.3-FPM via Apache mod_proxy_fcgi - composer install, DB migrations, .env setup, SSL via certbot --- deploy.sh | 295 ++++++++++++++++++++++++++++++++++++++++++++++ views/pricing.php | 8 +- 2 files changed, 299 insertions(+), 4 deletions(-) create mode 100644 deploy.sh diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..1005f29 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,295 @@ +#!/usr/bin/env bash +# ────────────────────────────────────────────────────────────────────────────── +# NixPanel Website — Deploy Script +# Deploys nixpanel.io (PHP frontend + customer portal) to a server. +# Run as root on the target server. +# ────────────────────────────────────────────────────────────────────────────── +set -euo pipefail + +RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m' +YELLOW='\033[1;33m'; BOLD='\033[1m'; RESET='\033[0m' + +info() { echo -e "${CYAN}[INFO]${RESET} $*"; } +success() { echo -e "${GREEN}[ OK ]${RESET} $*"; } +warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; } +error() { echo -e "${RED}[ERR ]${RESET} $*" >&2; exit 1; } +step() { echo -e "\n${BOLD}${CYAN}━━━ $* ━━━${RESET}"; } + +[[ $EUID -ne 0 ]] && error "Must be run as root" + +SITE_DIR="/var/www/nixpanel-website" +GITHUB_REPO="NixReaper/nixpanel-website" +SERVER_NAME="${1:-nixpanel.io}" + +echo "" +echo -e "${BOLD}${CYAN} NixPanel Website — Deployer${RESET}" +echo -e " Domain: ${SERVER_NAME}" +echo "" + +# ── 1. System deps ──────────────────────────────────────────────────────────── +step "Installing system dependencies" +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq + +# ondrej/php PPA for latest PHP on Ubuntu 24.04 +apt-get install -y -qq ca-certificates gnupg software-properties-common +if ! grep -rq "ondrej/php" /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null; then + add-apt-repository -y ppa:ondrej/php + apt-get update -qq +fi + +apt-get install -y -qq \ + apache2 \ + php8.3 php8.3-fpm php8.3-cli php8.3-mysql php8.3-curl \ + php8.3-mbstring php8.3-xml php8.3-zip php8.3-gd php8.3-intl \ + mariadb-server mariadb-client \ + certbot python3-certbot-apache \ + curl wget git unzip + +# Install Composer +if ! command -v composer &>/dev/null; then + info "Installing Composer…" + curl -fsSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer +fi +success "Dependencies installed" + +# ── 2. MariaDB ──────────────────────────────────────────────────────────────── +step "Configuring MariaDB" +systemctl enable --now mariadb + +if ! mysql -u root -e "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='nixpanel_website'" 2>/dev/null | grep -q nixpanel_website; then + DB_PASS=$(openssl rand -hex 24) + + mysql -u root < /root/.nixpanel_website_db_pass + chmod 600 /root/.nixpanel_website_db_pass + success "Database created (password saved to /root/.nixpanel_website_db_pass)" +else + DB_PASS=$(cat /root/.nixpanel_website_db_pass 2>/dev/null || echo "") + info "Database already exists" +fi + +# ── 3. Clone / update source ────────────────────────────────────────────────── +step "Deploying source code" +if [[ -d "$SITE_DIR/.git" ]]; then + info "Updating existing deployment…" + git -C "$SITE_DIR" pull --ff-only +else + git clone "https://github.com/${GITHUB_REPO}.git" "$SITE_DIR" +fi +success "Source at $SITE_DIR" + +# ── 4. Composer dependencies ────────────────────────────────────────────────── +step "Installing PHP dependencies" +cd "$SITE_DIR" +composer install --no-dev --optimize-autoloader --quiet +success "Composer packages installed" + +# ── 5. Run database migrations ──────────────────────────────────────────────── +step "Running database migrations" +if [[ -f "$SITE_DIR/migrations/001_schema.sql" ]]; then + mysql -u nixpanel_web -p"${DB_PASS}" nixpanel_website < "$SITE_DIR/migrations/001_schema.sql" + success "Migrations applied" +else + warn "No migration file found at migrations/001_schema.sql" +fi + +# ── 6. Environment file ─────────────────────────────────────────────────────── +step "Configuring environment" +if [[ ! -f "$SITE_DIR/.env" ]]; then + echo "" + info "Setting up .env — press Enter to leave values blank (configure later)" + echo "" + + read -rp " Stripe secret key (sk_live_...): " STRIPE_SK; STRIPE_SK="${STRIPE_SK:-}" + read -rp " Stripe publishable key (pk_live_...): " STRIPE_PK; STRIPE_PK="${STRIPE_PK:-}" + read -rp " Stripe webhook secret (whsec_...): " STRIPE_WH; STRIPE_WH="${STRIPE_WH:-}" + echo "" + info "Stripe Price IDs (leave blank to fill in later):" + read -rp " STRIPE_PRICE_SOLO_MONTHLY: " P_SOLO_M; P_SOLO_M="${P_SOLO_M:-}" + read -rp " STRIPE_PRICE_SOLO_ANNUAL: " P_SOLO_A; P_SOLO_A="${P_SOLO_A:-}" + read -rp " STRIPE_PRICE_HOST_MONTHLY: " P_HOST_M; P_HOST_M="${P_HOST_M:-}" + read -rp " STRIPE_PRICE_HOST_ANNUAL: " P_HOST_A; P_HOST_A="${P_HOST_A:-}" + read -rp " STRIPE_PRICE_AGENCY_MONTHLY: " P_AGCY_M; P_AGCY_M="${P_AGCY_M:-}" + read -rp " STRIPE_PRICE_AGENCY_ANNUAL: " P_AGCY_A; P_AGCY_A="${P_AGCY_A:-}" + echo "" + 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 "" + echo "" + read -rp " Licensing server URL [https://license.nixpanel.io]: " LIC_URL + LIC_URL="${LIC_URL:-https://license.nixpanel.io}" + read -rp " Licensing server API key: " LIC_KEY; LIC_KEY="${LIC_KEY:-}" + + SESSION_SECRET=$(openssl rand -hex 64) + + cat > "$SITE_DIR/.env" </dev/null || true + +cat > /etc/apache2/sites-available/nixpanel-website.conf < + ServerName ${SERVER_NAME} + ServerAlias www.${SERVER_NAME} + + # DocumentRoot points directly to public/ — only one .htaccess needed + DocumentRoot ${SITE_DIR}/public + + + Options -Indexes +FollowSymLinks + AllowOverride All + Require all granted + + + # Pass PHP to PHP-FPM + + SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost" + + + # Security headers + Header always set X-Frame-Options "SAMEORIGIN" + Header always set X-Content-Type-Options "nosniff" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + + ErrorLog /var/log/apache2/nixpanel-website-error.log + CustomLog /var/log/apache2/nixpanel-website-access.log combined + + +# HTTPS — populated by certbot + + ServerName ${SERVER_NAME} + ServerAlias www.${SERVER_NAME} + + DocumentRoot ${SITE_DIR}/public + + + Options -Indexes +FollowSymLinks + AllowOverride All + Require all granted + + + + SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost" + + + Header always set X-Frame-Options "SAMEORIGIN" + Header always set X-Content-Type-Options "nosniff" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" + + ErrorLog /var/log/apache2/nixpanel-website-error.log + CustomLog /var/log/apache2/nixpanel-website-access.log combined + + # SSL — certbot will fill these in + # SSLEngine on + # SSLCertificateFile ... + # SSLCertificateKeyFile ... + +APACHEEOF + +a2ensite nixpanel-website +systemctl enable --now apache2 php8.3-fpm +apache2ctl configtest && systemctl reload apache2 +success "Apache configured" + +# ── 9. SSL ──────────────────────────────────────────────────────────────────── +step "SSL certificate (Let's Encrypt)" +echo "" +echo -e " ${BOLD}Obtain SSL cert now?${RESET} (requires DNS pointing ${SERVER_NAME} → this server)" +read -rp " Get SSL cert? [Y/n]: " DO_SSL +DO_SSL="${DO_SSL:-Y}" + +if [[ "${DO_SSL,,}" == "y" ]]; then + read -rp " Email for Let's Encrypt notices: " LE_EMAIL + certbot --apache -d "$SERVER_NAME" -d "www.${SERVER_NAME}" \ + --non-interactive --agree-tos -m "$LE_EMAIL" --redirect \ + && success "SSL certificate installed" \ + || warn "certbot failed — run manually: certbot --apache -d ${SERVER_NAME}" +else + info "Skipped — run later: certbot --apache -d ${SERVER_NAME}" +fi + +# ── Done ────────────────────────────────────────────────────────────────────── +SERVER_IP=$(hostname -I | awk '{print $1}') + +echo "" +echo -e "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" +echo -e "${BOLD}${GREEN} NixPanel Website Deployed!${RESET}" +echo -e "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" +echo "" +echo -e " ${BOLD}URL:${RESET} https://${SERVER_NAME}" +echo -e " ${BOLD}Root:${RESET} ${SITE_DIR}" +echo -e " ${BOLD}Config:${RESET} ${SITE_DIR}/.env" +echo -e " ${BOLD}Logs:${RESET} /var/log/apache2/nixpanel-website-*.log" +echo "" +echo -e " ${BOLD}To redeploy after code changes:${RESET}" +echo -e " git -C ${SITE_DIR} pull && composer install -d ${SITE_DIR} --no-dev -o" +echo "" +if [[ -z "$(grep 'STRIPE_SECRET_KEY=sk_' "$SITE_DIR/.env" 2>/dev/null || true)" ]]; then + echo -e " ${YELLOW}⚠ Stripe keys not yet configured — edit ${SITE_DIR}/.env${RESET}" +fi +echo "" diff --git a/views/pricing.php b/views/pricing.php index 627b8b0..9126d76 100644 --- a/views/pricing.php +++ b/views/pricing.php @@ -25,11 +25,11 @@ $plans = [

Tied to your server IP. No per-user fees. Cancel anytime.

- -