BaoTa Panel and aaPanel
Deploy the console with Docker Compose on BaoTa Panel (宝塔) or aaPanel: compose modes, panel setup, and manual installs.
Compose modes
deploy.sh install writes the compose file for the selected database mode.
| Item | host | bundled |
|---|---|---|
| Database | Local PostgreSQL (BaoTa 数据库 → PgSQL) or a cloud database | Bundled postgres:18.6-alpine, data in the Docker volume edgeweir_postgres-data |
| Compose file | compose.baota-host.yml | compose.baota.yml |
| Container network | network_mode: host; 127.0.0.1 in the container is the host, so a local PostgreSQL listening on loopback only needs no change to listen_addresses or pg_hba.conf | Docker bridge; the database is not exposed |
| Web console | Process listens on 127.0.0.1:3000 (EDGEWEIR_HTTP_PORT) | Port mapping 127.0.0.1:3000 (EDGEWEIR_HTTP_PORT) → 3000 |
| Node channel | Process listens on 0.0.0.0:8443 (EDGEWEIR_NODE_API_HOST, EDGEWEIR_NODE_API_PORT) | Port mapping 8443 (EDGEWEIR_NODE_API_PORT) → 8443 |
| Port variable format | Numbers only | EDGEWEIR_HTTP_PORT numbers only; EDGEWEIR_NODE_API_PORT may include a bind address, e.g. 127.0.0.1:18443 |
EDGEWEIR_TRUSTED_PROXIES | Default 127.0.0.1,::1 | Docker gateway address, written by deploy.sh and synced at startup |
| Port column in the panel's container list | Empty (host networking has no port mappings) | Shows the mappings |
The image ghcr.io/marvinli001/edgeweir is public; the panel needs no registry entry or login. Tag format and version pinning: upgrade.en.md.
1. Prepare
| Item | Requirement | BaoTa Panel | aaPanel |
|---|---|---|---|
| Docker | Docker Engine and Compose v2 (docker compose) | Install on the Docker page | Install on the Docker page |
| Firewall | Open the node channel port (default 8443/TCP); do not open web port 3000. In bundled mode Docker publishes the ports past the system firewall; to limit sources, use the cloud security group | 安全 → 系统防火墙 → 添加端口规则: protocol TCP, source all IPs, policy allow | Security → Firewall → Add Port Rule: Protocol TCP, Source IP All, Strategy Allow |
| Cloud security group | Open the same port | — | — |
| Domain | Console domain (e.g. cdn-admin.example.com) resolves to this host | — | — |
| Database (host) | PostgreSQL 18; an empty database and its owner user; a cloud database allow list that includes this host's IP | 数据库 → PgSQL → 添加数据库 | Databases → PgSQL → Add DB |
| Images | Access to ghcr.io; otherwise docker load beforehand, see EDGEWEIR_NO_PULL in deploy-script.en.md | — | — |
| Shell | root | 终端 or SSH | Terminal or SSH |
Other requirements: Deployment overview.
2. Install with deploy.sh
-
Download the script:
curl -fsSL -o deploy.sh https://raw.githubusercontent.com/marvinli001/edgeweir/master/deploy.sh -
Run the installer and answer the prompts for install directory, database mode, database connection, console URL, and node channel URL. Prompts and defaults: deploy-script.en.md.
sudo bash deploy.sh installThe default install directory is
/www/dk_project/edgeweirwhen/www/server/panelexists, otherwise/opt/edgeweir. The console URL is the address browsers use, e.g.https://cdn-admin.example.com; the node channel URL defaults tohttps://<console domain>:8443. -
Record the setup token printed at the end.
.env in the install directory holds EDGEWEIR_MASTER_KEY. Back it up offline; losing it makes encrypted data unrecoverable. See backup.en.md.
Unattended install (run as root; variables: deploy-script.en.md):
EDGEWEIR_YES=1 EDGEWEIR_DB=host \
EDGEWEIR_PUBLIC_URL=https://cdn-admin.example.com \
DATABASE_URL='postgres://edgeweir:<URL-encoded password>@127.0.0.1:5432/edgeweir' \
bash deploy.sh installWith EDGEWEIR_DB=bundled, leave DATABASE_URL unset.
3. Reverse proxy and HTTPS
The panel's nginx terminates HTTPS and proxies to http://127.0.0.1:3000 (replace the port if EDGEWEIR_HTTP_PORT was changed).
| Step | BaoTa Panel | aaPanel |
|---|---|---|
| 1. Site | 网站 → PHP项目 → 添加站点: domain = console domain, PHP version 「纯静态」 (static) | Website → Proxy Project, add a site: domain = console domain, proxy target http://127.0.0.1:3000 |
| 2. Certificate | Site settings SSL → Let's Encrypt → 申请证书, enable forced HTTPS | Site settings SSL → Let's Encrypt |
| 3. Reverse proxy | Site settings 反向代理 → 添加反向代理: target URL http://127.0.0.1:3000 | Set in step 1 |
- If file validation of the certificate fails, use DNS validation.
- Keep the default sent domain (
Host): the console checks request origins againstEDGEWEIR_PUBLIC_URLonly. - If the console URL given at install time is not
https://, run./deploy.sh configafter the certificate is active and change it tohttps://.
Generic nginx configuration and headers: networking.en.md.
4. Set up and verify
-
Read the setup token (also printed by the installer):
cd /www/dk_project/edgeweir # install directory ./deploy.sh setup-token -
Open
https://cdn-admin.example.com/setupand enter the setup token, name, email, and password to create the console account. Setup wizard: Quick start. -
Verify the web console:
curl -s http://127.0.0.1:3000/healthzExpected:
{"status":"ok","version":"<EDGEWEIR_VERSION from .env>"}. -
Verify the node channel (from another host):
openssl s_client -connect cdn-admin.example.com:8443 -servername cdn-admin.example.com </dev/null 2>/dev/null \ | openssl x509 -noout -issuerExpected: the issuer contains
Edgeweir Node Channel CA.
Node release source and origin allow list are configured in System settings, see Clusters and system; GeoIP databases in Protection settings, see Protection settings; SMTP on the Alerts page, see SMTP. Adding nodes: Adding nodes; --server in the install command is "Node channel" in System settings (EDGEWEIR_NODE_API_URL while none is saved); to change it, see Node channel URL and certificate.
Node channel port
| Method | Configuration | Constraint |
|---|---|---|
| Direct exposure (default) | Open EDGEWEIR_NODE_API_PORT in the firewall and security group | — |
nginx stream passthrough | The console listens on local 18443; the panel's nginx passes TCP through on 8443 | The panel's nginx must include the stream module |
| Panel HTTP reverse proxy, CDN | Not supported | Terminating TLS makes node enrollment fail with CA pin mismatch; mTLS cannot be established |
stream block, mechanism, and verification: networking.en.md. Steps on BaoTa / aaPanel:
-
Check that the panel's nginx includes the stream module:
/www/server/nginx/sbin/nginx -V 2>&1 | grep -o -- '--with-stream[^ ]*'Expected: one line is exactly
--with-stream. Without that line, use direct exposure. -
Move the node channel to local
18443; keepEDGEWEIR_NODE_API_URLat:8443:Mode Change bundled .env:EDGEWEIR_NODE_API_PORT=127.0.0.1:18443host .env:EDGEWEIR_NODE_API_PORT=18443,EDGEWEIR_NODE_API_HOST=127.0.0.1./deploy.sh start -
The panel's
/www/server/nginx/conf/nginx.confalready has astream { }block that includes/www/server/panel/vhost/nginx/tcp/*.conf; do not add anotherstreamblock, ornginx -tfails with"stream" directive is duplicate. Create/www/server/panel/vhost/nginx/tcp/edgeweir.conf:/www/server/panel/vhost/nginx/tcp/edgeweir.conf server { listen 8443; proxy_pass 127.0.0.1:18443; proxy_timeout 1h; }When the node channel's DNS name has an AAAA record, add
listen [::]:8443;as well. Test and reload:/www/server/nginx/sbin/nginx -t && /www/server/nginx/sbin/nginx -s reload -
Verify as in section 4, step 4.
| Case | Constraint |
|---|---|
./deploy.sh config | Keeps the step 2 EDGEWEIR_NODE_API_PORT; when the port in the node channel URL changes, adjust nginx's listen yourself. |
./deploy.sh update | Replacing compose.yml leaves the step 2 settings in .env alone. |
| Restarting or updating the project in the panel | The panel runs docker compose -f <compose file>: it reads .env, so the step 2 settings hold; it skips compose.override.yml, whose changes apply only when you start, stop, and upgrade with ./deploy.sh. |
The host mode compose.yml lacks EDGEWEIR_NODE_API_HOST (an older template) | EDGEWEIR_NODE_API_HOST in .env has no effect, and ./deploy.sh start warns; change its NODE_API_HOST line as in ./deploy.sh template host. |
Install without the script
Compose project in the panel
-
Get a template: the output of
bash deploy.sh template bundled(orhost), orcompose.baota.yml/compose.baota-host.ymlfrom the repository. -
Generate the
.envcontent in the panel terminal (bundled):cat <<ENV EDGEWEIR_MASTER_KEY=$(openssl rand -base64 32) POSTGRES_PASSWORD=$(openssl rand -hex 24) EDGEWEIR_PUBLIC_URL=https://cdn-admin.example.com EDGEWEIR_NODE_API_URL=https://cdn-admin.example.com:8443 EDGEWEIR_VERSION=20260929-a1b2c3d ENVFor host mode, replace the
POSTGRES_PASSWORDline withDATABASE_URL=postgres://edgeweir:<URL-encoded password>@127.0.0.1:5432/edgeweir(append?sslmode=verify-fullfor a cloud database). -
Add the compose project: BaoTa Docker → 容器编排 → 添加容器编排; aaPanel Docker → Compose → Add Compose. Name it
edgeweir, paste the template as the compose content, paste the previous output into the.envfield (aaPanel .env Content), and create it. -
Check the containers:
edgeweir-consoleis healthy; bundled also runsedgeweir-postgres. -
Set the trusted proxy in bundled mode: put
deploy.shin the compose directory and run./deploy.sh restart; the script writes the Docker gateway address toEDGEWEIR_TRUSTED_PROXIESand recreates the containers. To set it by hand, use the address printed below; environment changes take effect after the containers are recreated.docker inspect -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' edgeweir-postgres -
Read the setup token and continue with section 4:
docker logs edgeweir-console 2>&1 | grep -o '"setupToken":"[^"]*"' | tail -n 1
| Variable | Constraint |
|---|---|
.env field | The panel does not run commands in it; paste the values generated in the terminal. |
EDGEWEIR_VERSION | A dated tag from GitHub Packages; latest only for evaluation. |
BETTER_AUTH_SECRET | Leave unset on new deployments. Deployments that set it keep the value; the console refuses to start once it is removed. |
| Other variables | See Environment variables. |
Standalone containers without Compose
The panel's Create Container form cannot set the read-only root filesystem, tmpfs, and no-new-privileges hardening of the compose files. For that hardening, run the docker run commands in docker.en.md from the terminal.
-
Create the network
edgeweir: BaoTa Docker → 网络; aaPanel Docker → Network → Add Network; or in the terminal:docker network create edgeweir -
Create two containers: BaoTa Docker → 容器 → 创建容器; aaPanel Docker → Container → Create Container.
Field edgeweir-postgresedgeweir-consoleImage postgres:18.6-alpineghcr.io/marvinli001/edgeweir:<dated tag>Network edgeweiredgeweirPorts None 127.0.0.1:3000→3000;8443→8443Volume edgeweir-postgres→/var/lib/postgresql— Environment POSTGRES_USER=edgeweir,POSTGRES_DB=edgeweir,POSTGRES_PASSWORD=<output of openssl rand -hex 24>ROLE=all,DATABASE_URL=postgres://edgeweir:<same password>@edgeweir-postgres:5432/edgeweir,EDGEWEIR_MASTER_KEY,EDGEWEIR_PUBLIC_URL,EDGEWEIR_NODE_API_URL,EDGEWEIR_TRUSTED_PROXIES=<gateway of the edgeweir network>Restart policy unless-stoppedoralwaysunless-stoppedoralways-
Do not set
EDGEWEIR_VERSIONon the console container: inside the image it carries the running version. -
Deployments that set
BETTER_AUTH_SECRETkeep the value. -
Gateway address:
docker network inspect -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}' edgeweir -
If the form cannot bind the port to
127.0.0.1, usedocker runin the terminal.
-
-
Upgrade: pull the new tag, remove
edgeweir-console, and recreate it with the same settings and the new tag. Data stays in theedgeweir-postgresvolume. Back up first, see backup.en.md.
Upgrades and backups
Run in the deployment directory:
cd /www/dk_project/edgeweir
./deploy.sh update # back up, then upgrade to the dated tag behind latest
./deploy.sh update 20260929-a1b2c3d # upgrade or roll back to a given tag
./deploy.sh backup # back up to backups/<time>/
./deploy.sh restore backups/<time> # back up, then replace the database with that backupRotating the master key: in .env, move the old value to EDGEWEIR_MASTER_KEY_PREVIOUS, write the new EDGEWEIR_MASTER_KEY, and run ./deploy.sh restart; once ./deploy.sh logs console shows no envelope uses EDGEWEIR_MASTER_KEY_PREVIOUS any more, delete that line and run ./deploy.sh restart again. Details: Rotating the master key.
Commands, backup layout, and abort behavior: deploy-script.en.md. Version policy and rollback constraints: upgrade.en.md. Restore: backup.en.md.
| Case | Behavior |
|---|---|
| Compose project created in the panel | All commands work after deploy.sh is placed in the compose directory; the script recognizes the deployment by .env and a compose file containing container_name: edgeweir-console, and keeps the panel's Compose project name. |
Image update in the panel after editing EDGEWEIR_VERSION (aaPanel Update Image) | No database backup is taken. |
Troubleshooting
| Symptom | Cause | Action |
|---|---|---|
| Database check fails during install | Address, password, pg_hba.conf, allow list, or TLS certificate | Follow the hint printed by the script; see Database check. |
| The user cannot create tables or schemas | The user does not own the database | Select this user when creating the database in BaoTa, or run ALTER DATABASE edgeweir OWNER TO edgeweir; and ALTER SCHEMA public OWNER TO edgeweir;. |
无法访问 Docker (cannot access Docker) | Not running as root, or Docker is stopped | Run with sudo; start Docker on the panel's Docker page. |
| Image pull fails | ghcr.io unreachable | Import the images with docker load, then set EDGEWEIR_NO_PULL=1. |
| Sign-in fails, or the session ends right after sign-in | EDGEWEIR_PUBLIC_URL differs from the browser address in scheme, domain, or port | ./deploy.sh config. |
Node enrollment fails with CA pin mismatch | The panel's nginx or a CDN terminates TLS on the node channel port | Use direct exposure or stream passthrough; verify as in section 4, step 4. |
| Node enrollment times out | The firewall or security group blocks the node channel port, or the node channel domain resolves incorrectly | Open the port; check DNS for the node channel URL's host. |
| host mode warns that the node channel listens on loopback only | The image does not support NODE_API_HOST | ./deploy.sh update. |
host mode warns that compose.override.yml sets NODE_API_HOST | Restarting or updating the project in the panel skips the override file and loses the setting | Set EDGEWEIR_NODE_API_HOST in .env instead (step 2 of Node channel port), remove NODE_API_HOST from the override file, and run ./deploy.sh start. |
All IPs in the audit log are the Docker gateway (172.x.x.1) | In bundled mode, EDGEWEIR_TRUSTED_PROXIES differs from the current gateway | ./deploy.sh restart. |
./deploy.sh start reports 「启动失败」 (startup failed) | .env lacks a variable, or the database is unreachable | ./deploy.sh logs console; fix .env, then ./deploy.sh start. |