Skip to content

EN Installation

章北海 edited this page Oct 9, 2026 · 7 revisions

Installation

中文版:安装与部署

Three ways, in order of preference. Feature documentation and the full list of settings live in the README; this page only covers getting it running.

Option 1 — one command (deploy.sh) (recommended)

It installs a systemd unit, so the panel comes back after a reboot and restarts if the process dies, and systemctl restart is all it takes after a code change. The panel and the database run on the host itself, which is what you want for a long-lived installation.

Requirements

Component Version Notes
Proxmox VE 8.x / 9.x one code path for both, no version branching
Python 3.11 or newer the backend
Node.js 18 or newer only needed to build the frontend; use --skip-frontend to reuse an existing dist/
MySQL 8.x (MariaDB works too) the panel only supports MySQL; create the database first, the panel creates the tables
CREATE DATABASE proxcenter_panel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

One command

git clone https://github.com/yjscloud/ProxCenter.git
cd ProxCenter
sudo ./deploy.sh

It asks nothing and runs straight through: installs the missing system dependencies per distribution → creates .venv and installs the backend → generates backend/.env with a random SECRET_KEY, database password and initial admin password → installs MariaDB if there is no local database, creates the database and user and verifies by connecting with the panel's own account → builds the frontend into dist/ → installs a systemd service enabled at boot → calls /api/health and prints the panel URL plus the one-time initial admin password.

Defaults are port 8080, database proxcenter_panel, user proxcenter. Pass your own values instead; it still will not ask:

sudo ./deploy.sh --port 9000 --db-name proxcenter_panel \
                 --db-user proxcenter --db-password '<strong password>' \
                 --mysql-root-password '<MySQL root password>'
Flag Purpose
--reconfigure Ask for each value (port, database, credentials, whether to install a database); defaults come from the existing .env, Enter keeps them
--port PORT Change the listening port (written back to .env)
--db-host / --db-port / --db-name / --db-user / --db-password Database credentials
--mysql-root-password MySQL administrator password used to create the database and user (not needed for a passwordless local root)
--skip-frontend Do not build the frontend, reuse the existing dist/
--skip-deps Only check system dependencies, install nothing
--no-systemd Prepare the environment and artifacts only, install no service (no root needed)
--reset-db-password Align an existing database account's password with the value in .env (do not use it when the account is shared)
--help All options and examples

Re-running is safe. It never damages an existing configuration: when .env already exists only the keys you passed on the command line are overwritten, and SECRET_KEY is never touched. That key is the encryption root for stored ciphertext, so replacing it makes every stored PVE token and SMTP password undecryptable.

Option 2 — Docker

Prefer not to install Python, Node or MySQL on the host? Run it in a container; the host only needs Docker:

curl -fsSLO https://raw.githubusercontent.com/yjscloud/ProxCenter/main/docker-compose.yml
docker compose up -d

Sign in at http://<your-ip>:8080 as admin / ProxCenter@2026. All three passwords (ADMIN_PASSWORD / DB_PASSWORD / MYSQL_ROOT_PASSWORD) live in the compose file, search for ★ 改这里. Its header explains ${NAME:-default} piece by piece, so the :- is not mistaken for part of the password. Upgrading is docker compose pull && docker compose up -d.

The host-security pages read nothing inside a container: /var/log and /proc belong to the container rather than the host. The mounts that fix it are commented out in the compose file.

Passwords only take effect on first initialisation, and SECRET_KEY is generated on first start into the panel_data volume. Leave it alone. Details in the README's Docker section.

Option 3 — manual (development)

# backend
cd backend
python -m venv ../.venv && source ../.venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python -c "import secrets; print('SECRET_KEY=' + secrets.token_urlsafe(48))"
python -c "import secrets; print('ADMIN_PASSWORD=' + secrets.token_urlsafe(16))"
# put both into backend/.env; the backend refuses to start if they are too weak
python run.py                      # listens on 0.0.0.0:8080

# frontend (second terminal)
cd ..
npm install
npm run dev                        # http://localhost:5173, /api proxied to 8080

Generated API documentation is at http://localhost:8080/api/docs. To run the production shape in the foreground, with the backend serving dist/ directly, use ./start-prod.sh with a built dist/.

systemd service

deploy.sh renders exactly this unit into /etc/systemd/system/proxcenter.service; adjust the paths to your installation directory:

[Unit]
Description=ProxCenter - Proxmox VE 管理面板 (FastAPI :8080)
After=network-online.target
Wants=network-online.target
Before=nginx.service

[Service]
Type=simple
User=root
WorkingDirectory=/data/proxcenter/backend
Environment=PYTHONUNBUFFERED=1
ExecStart=/data/proxcenter/.venv/bin/python /data/proxcenter/backend/run.py
Restart=always
RestartSec=5
# graceful exit is slow; force it after 15s so restarts are not held up
TimeoutStopSec=15
KillSignal=SIGTERM
StandardOutput=append:/data/proxcenter/logs/panel.log
StandardError=append:/data/proxcenter/logs/panel.log

[Install]
WantedBy=multi-user.target
systemctl enable --now proxcenter
systemctl status proxcenter
journalctl -u proxcenter -f      # or: tail -f /data/proxcenter/logs/panel.log

Nginx + HTTPS (required if it is reachable from the internet)

The panel does not speak TLS itself, so terminate it in Nginx or Caddy and proxy everything to 8080. Two things to get right: the proxy must forward the Upgrade header or the console cannot connect, and proxy_read_timeout has to be generous because the console is long-lived. The frontend is served by the backend by default; to serve dist/ from Nginx instead, add root /var/www/proxcenter/dist; and location / { try_files $uri $uri/ /index.html; }.

The complete configuration (80 → 443 redirect, certificates, HSTS, every proxy_set_header) is in the README's HTTPS section. What this page stresses is the panel side: reaching 8080 directly is still plaintext, so both of these belong in .env:

FORCE_HTTPS=true
FORWARDED_ALLOW_IPS=127.0.0.1   # do not widen this, or the public can forge X-Forwarded-Proto

Upgrading

git pull && sudo ./deploy.sh                   # either side may have changed: rebuild + restart + self-check
git pull && sudo ./deploy.sh --skip-frontend   # backend only: reuse dist/, much faster

A frontend-only change can also be handled by building locally and copying dist/ up, then restarting the service.

The update script checks the frontend and backend dependencies on every run. It returns in seconds when nothing changed and downloads nothing extra, so jumping straight from an old release does not leave new dependencies missing.

The first start after an upgrade adds any new columns and indexes by itself (you will see it in the log). That needs ALTER on the database account. Without it the panel still starts, it only logs a warning and the one feature that depends on it degrades. See Troubleshooting.

A Docker install upgrades differently: docker compose pull && docker compose up -d.

Passwords

  • To change one: top-right user menu → Profile → change password. An administrator can also reset their own under Settings → Users.
  • The initial password is printed once at the end of deploy.sh. Note it down and change it immediately.
  • ADMIN_PASSWORD in .env is only used to create the account when the database has none. On a deployment that already has an administrator, changing it does nothing to the existing login.
  • Forgotten it? With SMTP configured, the login page's "forgot password" flow sends a reset mail. Without a mail channel there is currently no command-line recovery path, so open an issue and describe the situation.

Clone this wiki locally