Every app ships as install_<app>.sh (source: impl/install_<app>.sh) and is
also reachable through the central launcher: deploy.sh <app> <action>.
Common actions: install, update, backup, restore, status,
status-json, doctor, verify, uninstall.
For instance-qualified commands, reverse-proxy TLS, and an export/import restore rehearsal, read the instances, TLS, and migration runbook.
Every app supports --help (lists configuration keys with current values) and
--dry-run <action> (previews what install/update/backup/uninstall would do
without touching the system). Configuration keys are environment variables; set them before the first install to
override script defaults. After a config file is persisted, that trusted file takes
precedence over ad-hoc environment variables on later commands.
The following ten apps share lib/binary_app.sh: alist, beszel,
filebrowser, frps, gitea, gotify, meilisearch, navidrome, newapi,
ntfy.
Common keys (defaults in parentheses):
| Key | Purpose |
|---|---|
DOMAIN |
Public domain (optional; used in summary) |
PORT |
Service port |
INSTALL_DIR |
Binary directory |
DATA_DIR |
Runtime data |
LOG_DIR |
Logs |
SERVICE_NAME / SERVICE_USER |
systemd unit / OS user |
GITHUB_REPO |
Upstream repository |
BACKUP_DIR / BACKUP_KEEP_DAYS |
Backups (default 30 days; retention uses find -mtime +N, so files may be kept about one extra day) |
BA_BIND_ADDR |
Listen address, 127.0.0.1 by default (reverse-proxy friendly). Set 0.0.0.0 only when the app is meant to be public; the install summary warns about plain-HTTP exposure |
BA_VERSION |
Pin an exact GitHub release tag (e.g. v1.2.3). Unset = latest. update upgrades to the pinned tag when set |
BA_SHA256_ASSET_TEMPLATE |
Optional upstream checksum asset published next to the release (supports ARCH, e.g. checksums.txt); when set, downloads are verified against it and a mismatch aborts the install/update |
BA_SHA256 |
Pin the expected sha256 of the release asset (64-hex). When set, any download whose digest differs is rejected |
INSTALLED_VERSION |
Recorded at install; do not edit |
App-specific defaults:
| App | Default port | Notes |
|---|---|---|
| alist | 5244 | First-run admin password: alist admin --data /var/lib/alist |
| beszel | 8090 | Health: /api/health; admin key in /etc/beszel.env |
| filebrowser | 8084 | Serves FB_ROOT (/srv/filebrowser); default admin admin/admin — change on first login |
| frps | 7000 | Public TCP proxy; BA_BIND_ADDR=0.0.0.0 by design. Auth token in /etc/frps/frps.toml |
| gitea | 3000 | Registration is disabled by default; create the first admin: sudo -u gitea gitea admin user create --admin --config /etc/gitea/app.ini |
| gotify | 8085 | Initial admin password (random) in /etc/gotify.env (GOTIFY_DEFAULTUSER_PASS) |
| meilisearch | 7700 | Master key (random) in /etc/meilisearch.env (MEILI_MASTER_KEY) |
| navidrome | 4533 | Music folder MUSIC_DIR (/srv/music) |
| newapi | 8080 | LLM API gateway (SQLite by default); SESSION_SECRET in /etc/newapi.env, BACKUP_CRON schedule, BA_ARCHIVE_PREFIX=new-api keeps historical backup names. Built-in default admin credentials — change on first login |
| ntfy | 2586 | Config /etc/ntfy/server.yml; listens on BA_BIND_ADDR |
Running status as root reports the installed release; a pinned install
(BA_VERSION) confirms a matching release or warns that the installed release
has drifted from the configured pin, while an unpinned install states that
install/update follow the moving latest release.
- Web Vault, Nginx reverse proxy, Let's Encrypt (certbot), fail2ban, daily
backups at 03:30 into
/opt/vaultwarden-backups. - Admin panel: the plaintext Admin Token is generated on install and
stored at
VW_ADMIN_TOKEN_FILE(/root/.vaultwarden-admin-token, mode 600). It is never printed to the terminal. View/rotate/delete it with:install_vaultwarden.sh token(view)install_vaultwarden.sh token rotateinstall_vaultwarden.sh token delete
- Registration:
SIGNUPS_ALLOWEDdefaults tofalse. To create the first account:install_vaultwarden.sh signups on, create the account, theninstall_vaultwarden.sh signups off.signups statusshows the current value. - Key config:
VW_DOMAIN,VW_PORT,VW_ENV_FILE(/etc/vaultwarden.env),VW_IMAGE_TAG, optionalVW_IMAGE_DIGEST,ENABLE_HTTPS(default true, requiresCERTBOT_EMAIL),VW_ADMIN_TOKEN_FILE. VW_IMAGE_TAGremains the readable version selector. To make image extraction immutable, setVW_IMAGE_DIGESTto a fullsha256:<64-hex>Docker image digest; it takes precedence over the tag. A successful install/update recordsINSTALLED_IMAGE_DIGESTandINSTALLED_VERSION; pinnedcheck-updateandstatus-jsoncompare the recorded and configured digests locally (source: docker_image,cache_state: pinned) without a network lookup.- Database is SQLite at
VW_DATA_DIR(/var/lib/vaultwarden); the backup script checkpoints and integrity-checks it before archiving.
- AI API gateway with PostgreSQL + Redis, nginx reverse proxy, daily backups at 03:30.
- PostgreSQL setup: on install the script creates
PG_USER/PG_DB(defaultsub2api/sub2api) with a random password. The connection DSN is written toCONFIG_DIR/.pg_dsn(/etc/sub2api/.pg_dsn, mode 600) and the backup script reads it from there — there is no second credential copy. SetPG_PASSto pin the password; identifiers are validated (letters, digits, underscore only). - Bind:
SUB2API_BIND_ADDRdefaults to127.0.0.1(nginx is the public entry point).SUB2API_TZreplaces the old hardcodedAsia/Shanghai(empty = server local time). - Restore:
install_sub2api.sh restoreloads the DB dump viapsql. - Release pin: set
SUB2API_VERSIONto an upstream tag (vX.Y.Z) to make install/update an immutable target. Pinned installs skip the GitHub-latest lookup, pinnedupdateskips re-downloading when the recorded version already matches, and rootstatusreports pin match/mismatch. Incheck-update/status-jsonthe pinned release is compared locally (cache_state: pinned) without a network request; leave it empty to follow the moving latest release. - Version records: the deployment config persists
INSTALLED_VERSIONfor the Sub2API release plusINSTALLED_POSTGRES_VERSIONandINSTALLED_REDIS_VERSIONafter a successful install/update.check-updateandstatus-jsonretain the Sub2API GitHub-release verdict at the top level and addversion_info.componentsentries forsub2api,postgresql, andredis; package dependencies are explicitlyupdate_state: not_checkedbecause the deployment script does not own a comparable package-feed policy.
- Python/Go AI gateway with optional nginx (
ENABLE_NGINX), optional HTTPS (CSAI_HTTPS), pip index / Go proxy mirrors (PIP_INDEX_URL,GOPROXY). - The backend binds
127.0.0.1; nginx (when enabled) is the public entry. OPEN_FIREWALLcontrols firewall port opening (default off).- Source:
GITHUB_BRANCHdefaults tomain. SetGITHUB_COMMITto a full 40-character git SHA to build from that exact source revision. In pinned mode,updatere-applies the configured commit; the successful checkout is recorded asINSTALLED_VERSION, andcheck-update/status-jsoncompare it locally with the configured pin (source: git_commit,cache_state: pinned) without a network request. LeaveGITHUB_COMMITempty to follow the moving branch.
- Native CLIProxyAPI (CPA) and CPA Manager Plus deployment with systemd, an
Nginx reverse proxy, and optional HTTPS (certbot). Config:
CPA_DOMAIN,CPAMP_DOMAIN,ENABLE_HTTPS,CPA_ALLOW_REMOTE,CERTBOT_EMAIL, install/data/env directories for both components. - Each component is installed from its repository's GitHub latest release
unless pinned.
CPA_VERSIONandCPAMP_VERSIONpin the CPA and CPAMP components to an exact upstream release tag (vX.Y.Z); pinnedinstalldownloads that tag from the release endpoint, and pinnedupdateskips re-downloading when the recorded version already matches the pin.statusrun as root reports the recorded versions (INSTALLED_CPA_VERSION/INSTALLED_CPAMP_VERSION) plus per-component pin match/mismatch warnings, andstatus-json/check-updateexpose the same state through the typedcomponentsmanifest. Pinned components are compared locally (cache_state: pinned) without querying the moving latest; leave both pins empty to follow the moving latest releases.
- Docker compose stock panel.
- Authentication:
TICKFLOW_AUTH_PASSWORDis generated randomly when neither the config nor an existing.envprovides one (no more unauthenticated public panel). An explicitly set password must be ≥ 6 characters. The panel password lives inTICKFLOW_ENV_FILE(/opt/tickflow-stock-panel/.env,AUTH_PASSWORD). - Bind:
TICKFLOW_BIND_ADDRdefaults to127.0.0.1; the compose port mapping follows it. Put the panel behind an HTTPS reverse proxy to publish it. - Source:
TICKFLOW_REPOdefaults toshy3130/tickflow-stock-panelandTICKFLOW_BRANCHdefaults tomain. SetTICKFLOW_COMMITto a full 40-character git SHA to check out that exact source revision. In this pinned mode,updatere-applies the configured commit rather than moving to branch HEAD; the successful checkout is saved asINSTALLED_VERSION, andcheck-update/status-jsoncompare locally with the configured pin (source: git_commit,cache_state: pinned) without a network request. LeaveTICKFLOW_COMMITempty to retain the moving-branch model. Other keys:TICKFLOW_BACKEND_EXTRAS,TICKFLOW_DOMAIN(summary only).
- Static blog with optional CMS backend. Config:
BLOG_TITLE,BLOG_AUTHOR,BLOG_LANG,SITE_DIR,PUBLIC_DIR,NGINX_ROOT,THEME_NAME,THEME_REPO,ENABLE_CMS,CMS_REPO,CMS_BRANCH,CMS_SITE_URL, and optionalHUGO_VERSION. - Leave
HUGO_VERSIONunset to install the latest Hugo release. Set an exact semantic version without a leadingv(for exampleHUGO_VERSION=0.150.1) to pin bothinstallandupdate; the successful package version is saved asINSTALLED_VERSION.check-updatereports the pinned target without a network lookup, while unpinned deployments compare against GitHub Releases. - The Hugo
.debis verified against the SHA-256 digest published in the GitHub release metadata beforedpkg -i. - Publishing:
blog-publish(installed to/usr/local/bin).
- Git-based applications follow their configured branch unless a full commit SHA is explicitly pinned; upstream force-pushes can change content.
- Web apps bind
127.0.0.1by default; publish through an HTTPS reverse proxy. - No firewall ports are opened automatically for the binary apps
(
BA_FIREWALL=0default; frps opts in withBA_FIREWALL=1). - Secrets (admin tokens, DB passwords, master keys) live in root-only files, never in the terminal output or operation logs.
- Installing blog or vaultwarden moves
/etc/nginx/sites-enabled/defaultaside recoverably (.default.deploy-bakin sites-available) and restores it on uninstall. - Uninstall exports the deployment config first (see the printed hint).