Edgeweir
Deployment

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.

Itemhostbundled
DatabaseLocal PostgreSQL (BaoTa 数据库 → PgSQL) or a cloud databaseBundled postgres:18.6-alpine, data in the Docker volume edgeweir_postgres-data
Compose filecompose.baota-host.ymlcompose.baota.yml
Container networknetwork_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.confDocker bridge; the database is not exposed
Web consoleProcess listens on 127.0.0.1:3000 (EDGEWEIR_HTTP_PORT)Port mapping 127.0.0.1:3000 (EDGEWEIR_HTTP_PORT) → 3000
Node channelProcess 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 formatNumbers onlyEDGEWEIR_HTTP_PORT numbers only; EDGEWEIR_NODE_API_PORT may include a bind address, e.g. 127.0.0.1:18443
EDGEWEIR_TRUSTED_PROXIESDefault 127.0.0.1,::1Docker gateway address, written by deploy.sh and synced at startup
Port column in the panel's container listEmpty (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

ItemRequirementBaoTa PanelaaPanel
DockerDocker Engine and Compose v2 (docker compose)Install on the Docker pageInstall on the Docker page
FirewallOpen 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 allowSecurity → Firewall → Add Port Rule: Protocol TCP, Source IP All, Strategy Allow
Cloud security groupOpen the same port——
DomainConsole 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
ImagesAccess to ghcr.io; otherwise docker load beforehand, see EDGEWEIR_NO_PULL in deploy-script.en.md——
Shellroot终端 or SSHTerminal or SSH

Other requirements: Deployment overview.

2. Install with deploy.sh

  1. Download the script:

    curl -fsSL -o deploy.sh https://raw.githubusercontent.com/marvinli001/edgeweir/master/deploy.sh
  2. 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 install

    The default install directory is /www/dk_project/edgeweir when /www/server/panel exists, otherwise /opt/edgeweir. The console URL is the address browsers use, e.g. https://cdn-admin.example.com; the node channel URL defaults to https://<console domain>:8443.

  3. 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 install

With 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).

StepBaoTa PanelaaPanel
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. CertificateSite settings SSL → Let's Encrypt → 申请证书, enable forced HTTPSSite settings SSL → Let's Encrypt
3. Reverse proxySite settings 反向代理 → 添加反向代理: target URL http://127.0.0.1:3000Set in step 1
  • If file validation of the certificate fails, use DNS validation.
  • Keep the default sent domain (Host): the console checks request origins against EDGEWEIR_PUBLIC_URL only.
  • If the console URL given at install time is not https://, run ./deploy.sh config after the certificate is active and change it to https://.

Generic nginx configuration and headers: networking.en.md.

4. Set up and verify

  1. Read the setup token (also printed by the installer):

    cd /www/dk_project/edgeweir   # install directory
    ./deploy.sh setup-token
  2. Open https://cdn-admin.example.com/setup and enter the setup token, name, email, and password to create the console account. Setup wizard: Quick start.

  3. Verify the web console:

    curl -s http://127.0.0.1:3000/healthz

    Expected: {"status":"ok","version":"<EDGEWEIR_VERSION from .env>"}.

  4. 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 -issuer

    Expected: 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

MethodConfigurationConstraint
Direct exposure (default)Open EDGEWEIR_NODE_API_PORT in the firewall and security group—
nginx stream passthroughThe console listens on local 18443; the panel's nginx passes TCP through on 8443The panel's nginx must include the stream module
Panel HTTP reverse proxy, CDNNot supportedTerminating 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:

  1. 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.

  2. Move the node channel to local 18443; keep EDGEWEIR_NODE_API_URL at :8443:

    ModeChange
    bundled.env: EDGEWEIR_NODE_API_PORT=127.0.0.1:18443
    host.env: EDGEWEIR_NODE_API_PORT=18443, EDGEWEIR_NODE_API_HOST=127.0.0.1
    ./deploy.sh start
  3. The panel's /www/server/nginx/conf/nginx.conf already has a stream { } block that includes /www/server/panel/vhost/nginx/tcp/*.conf; do not add another stream block, or nginx -t fails 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
  4. Verify as in section 4, step 4.

CaseConstraint
./deploy.sh configKeeps the step 2 EDGEWEIR_NODE_API_PORT; when the port in the node channel URL changes, adjust nginx's listen yourself.
./deploy.sh updateReplacing compose.yml leaves the step 2 settings in .env alone.
Restarting or updating the project in the panelThe 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

  1. Get a template: the output of bash deploy.sh template bundled (or host), or compose.baota.yml / compose.baota-host.yml from the repository.

  2. Generate the .env content 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
    ENV

    For host mode, replace the POSTGRES_PASSWORD line with DATABASE_URL=postgres://edgeweir:<URL-encoded password>@127.0.0.1:5432/edgeweir (append ?sslmode=verify-full for a cloud database).

  3. 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 .env field (aaPanel .env Content), and create it.

  4. Check the containers: edgeweir-console is healthy; bundled also runs edgeweir-postgres.

  5. Set the trusted proxy in bundled mode: put deploy.sh in the compose directory and run ./deploy.sh restart; the script writes the Docker gateway address to EDGEWEIR_TRUSTED_PROXIES and 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
  6. Read the setup token and continue with section 4:

    docker logs edgeweir-console 2>&1 | grep -o '"setupToken":"[^"]*"' | tail -n 1
VariableConstraint
.env fieldThe panel does not run commands in it; paste the values generated in the terminal.
EDGEWEIR_VERSIONA dated tag from GitHub Packages; latest only for evaluation.
BETTER_AUTH_SECRETLeave unset on new deployments. Deployments that set it keep the value; the console refuses to start once it is removed.
Other variablesSee 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.

  1. Create the network edgeweir: BaoTa Docker → 网络; aaPanel Docker → Network → Add Network; or in the terminal:

    docker network create edgeweir
  2. Create two containers: BaoTa Docker → 容器 → 创建容器; aaPanel Docker → Container → Create Container.

    Fieldedgeweir-postgresedgeweir-console
    Imagepostgres:18.6-alpineghcr.io/marvinli001/edgeweir:<dated tag>
    Networkedgeweiredgeweir
    PortsNone127.0.0.1:3000 → 3000; 8443 → 8443
    Volumeedgeweir-postgres → /var/lib/postgresql—
    EnvironmentPOSTGRES_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 policyunless-stopped or alwaysunless-stopped or always
    • Do not set EDGEWEIR_VERSION on the console container: inside the image it carries the running version.

    • Deployments that set BETTER_AUTH_SECRET keep 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, use docker run in the terminal.

  3. Upgrade: pull the new tag, remove edgeweir-console, and recreate it with the same settings and the new tag. Data stays in the edgeweir-postgres volume. 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 backup

Rotating 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.

CaseBehavior
Compose project created in the panelAll 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

SymptomCauseAction
Database check fails during installAddress, password, pg_hba.conf, allow list, or TLS certificateFollow the hint printed by the script; see Database check.
The user cannot create tables or schemasThe user does not own the databaseSelect 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 stoppedRun with sudo; start Docker on the panel's Docker page.
Image pull failsghcr.io unreachableImport the images with docker load, then set EDGEWEIR_NO_PULL=1.
Sign-in fails, or the session ends right after sign-inEDGEWEIR_PUBLIC_URL differs from the browser address in scheme, domain, or port./deploy.sh config.
Node enrollment fails with CA pin mismatchThe panel's nginx or a CDN terminates TLS on the node channel portUse direct exposure or stream passthrough; verify as in section 4, step 4.
Node enrollment times outThe firewall or security group blocks the node channel port, or the node channel domain resolves incorrectlyOpen the port; check DNS for the node channel URL's host.
host mode warns that the node channel listens on loopback onlyThe image does not support NODE_API_HOST./deploy.sh update.
host mode warns that compose.override.yml sets NODE_API_HOSTRestarting or updating the project in the panel skips the override file and loses the settingSet 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.
Edit on GitHub

On this page