Repository navigation
EN 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.
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.
| 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;git clone https://github.com/yjscloud/ProxCenter.git
cd ProxCenter
sudo ./deploy.shIt 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.
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 -dSign 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_KEYis generated on first start into thepanel_datavolume. Leave it alone. Details in the README's Docker section.
# 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 8080Generated 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/.
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.targetsystemctl enable --now proxcenter
systemctl status proxcenter
journalctl -u proxcenter -f # or: tail -f /data/proxcenter/logs/panel.logThe 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-Protogit 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 fasterA 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.
- 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_PASSWORDin.envis 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.
ProxCenter · Apache-2.0 · 仓库 · 报错与建议 · 本 wiki 与仓库 README 同步维护,功能以 README 为准
ProxCenter · Apache-2.0 · repository · issues · this wiki is kept in sync with the repository README, which remains the authoritative source.