Operations CLI
AsterDrive now includes a set of command-line tools for these scenarios:
- The service is already deployed, but you want to check the database and key settings offline first.
- The admin panel is temporarily inaccessible, and you need to view or modify system settings directly.
- You need to run
node enrollon a follower node shell. - You are preparing to migrate SQLite to PostgreSQL or MySQL, or migrate back the other way.
- You want check results to be handled by scripts, CI, or an operations platform.
These commands are still part of the same aster_drive executable.
Running ./aster_drive directly starts the service. Running it with a subcommand performs an operations task.
Command Quick Reference
Section titled “Command Quick Reference”| What you want to do | Command | When to use it |
|---|---|---|
| Check database, migrations, public site URL, mail, and default policies | doctor | New deployment, before launch, after upgrade |
| Deep-check capacity, blob references, object inventory, and folder tree | doctor --deep | When you suspect data and storage are inconsistent |
| Automatically fix some counter drift | doctor --deep --fix | After confirming the CLI is allowed to modify counters |
| View system settings offline | config list / config get | When the admin panel is inaccessible, or for scripts |
| Modify system settings offline | config set / config import | Maintenance windows, batch configuration, disaster recovery |
| Complete enrollment on a follower | node enroll | After the primary admin panel generates an enrollment command |
| Migrate between SQLite / PostgreSQL / MySQL | database-migrate | Switching database backends or rehearsing migration |
Prepare the Database URL First
Section titled “Prepare the Database URL First”The most common forms are:
sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwcpostgres://user:password@127.0.0.1:5432/asterdrivemysql://user:password@127.0.0.1:3306/asterdriveIf you use the official Docker container, the simplest approach is usually to enter the container first, then run these commands:
docker exec -it asterdrive shThat avoids confusion between SQLite paths, mounted volumes, and actual file locations inside the container.
Use Environment Variables Instead of Common Arguments
Section titled “Use Environment Variables Instead of Common Arguments”In operations scripts, if you do not want to repeat long arguments on every command, use the CLI-specific ASTER_CLI_* environment variables. They only affect the command-line tools and do not change service startup configuration.
| Environment variable | Corresponding argument | Applicable commands |
|---|---|---|
ASTER_CLI_DATABASE_URL | --database-url | doctor, config, node enroll |
ASTER_CLI_OUTPUT_FORMAT | --output-format | doctor, config, node, database-migrate |
ASTER_CLI_MASTER_URL | node enroll --master-url | node enroll |
ASTER_CLI_ENROLLMENT_TOKEN | node enroll --token | node enroll |
ASTER_CLI_SOURCE_DATABASE_URL | database-migrate --source-database-url | database-migrate |
ASTER_CLI_TARGET_DATABASE_URL | database-migrate --target-database-url | database-migrate |
doctor also has these script-friendly switches:
ASTER_CLI_DOCTOR_STRICT=trueASTER_CLI_DOCTOR_DEEP=trueASTER_CLI_DOCTOR_FIX=trueASTER_CLI_DOCTOR_SCOPE=blob-ref-counts,storage-objectsASTER_CLI_DOCTOR_POLICY_ID=3During database migration, if you need progress output or a smaller batch size, you can also use:
ASTER_CLI_PROGRESS=1ASTER_CLI_COPY_BATCH_SIZE=100Deployment Check: doctor
Section titled “Deployment Check: doctor”After first deployment, or before production launch, run this first:
./aster_drive doctor \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc"Default mode checks the places most likely to go wrong:
- whether the database can be connected
- whether pending migrations remain
- if the backend is SQLite, whether the
FTS5 + trigram tokenizersearch acceleration capability is available, and whether related FTS tables / triggers are complete - whether runtime system settings can be read normally
- whether
Public Site URLis empty or malformed - whether
Public Site URLis stillhttp://, which means production lacks HTTPS - whether mail delivery configuration is complete
- whether preview application configuration parses correctly
- whether the default storage policy and default policy group are ready
If you want warn to count as failure, add:
./aster_drive doctor \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --strictFor script processing, add an output format:
./aster_drive doctor \ --output-format json \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc"Best uses:
- first acceptance check after a new deployment
- health check after upgrade
- after changing
Public Site URL, mail, or preview applications, confirm the config was not broken - confirm a default SQLite deployment really has search acceleration instead of silently falling back to full table scans
If you suspect existing “data and storage inconsistency” in the database, run a deep check:
./aster_drive doctor \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --deep--deep adds these checks:
storage-usage: comparesusers.storage_used/teams.storage_usedwith actual usage from files and historical versionsblob-ref-counts: comparesfile_blobs.ref_countwith real references fromfiles/file_versionsstorage-objects: scans object paths under each storage policy to find missing blobs, untracked objects, and orphan thumbnailsfolder-tree: checks missing parent folders, cross-workspace parent folders, and folder cycles
If you only want part of the deep checks, narrow the scope:
./aster_drive doctor \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --scope blob-ref-counts,storage-objectsIf you only want to check a specific storage policy, add:
./aster_drive doctor \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --scope storage-objects \ --policy-id 3When counter drift is found, the CLI can fix it directly:
./aster_drive doctor \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --deep \ --fixPay attention to four things:
--scopeonly affects deep checks. It does not disable base checks such as database connection, migrations, and runtime configuration.--policy-idonly applies toblob-ref-countsandstorage-objects;storage-usageandfolder-treestill check the whole database.--fixcurrently only repairsstorage_usedandfile_blobs.ref_countcounters. It does not automatically delete objects or modify folder structure.- Deep scans run in database batches and object storage pages, but they only validate path-level existence. They do not read object contents or calculate checksums.
Offline System Settings: config
Section titled “Offline System Settings: config”For normal settings changes, prefer Admin -> System Settings.
config is better for these cases:
- the admin panel is temporarily inaccessible
- you do not want to use a web page during a maintenance window
- you want to export, validate, or import system settings in bulk
List current items:
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ listView one item:
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ get \ --key public_site_urlValidate first, then write to the database:
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ validate \ --key public_site_url \ --value '["https://drive.example.com"]'
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ set \ --key public_site_url \ --value '["https://drive.example.com"]'public_site_url supports multiple public origins. When writing from the command line, pass a JSON string array:
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ set \ --key public_site_url \ --value '["https://drive.example.com","https://panel.example.com"]'For bulk import, the input file can be either of these JSON shapes:
[ { "key": "public_site_url", "value": ["https://drive.example.com", "https://panel.example.com"] }, { "key": "auth_cookie_secure", "value": "true" }]{ "configs": [ { "key": "public_site_url", "value": ["https://drive.example.com", "https://panel.example.com"] }, { "key": "auth_cookie_secure", "value": "true" } ]}Import example:
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ import \ --input-file ./runtime-config.jsonExport existing config like this:
./aster_drive config \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --output-format pretty-json \ exportThe export result is better suited for review, backup, or script processing.
If you plan to import it again, first normalize it into the “key/value array” shape above or the {"configs": [...]} shape, then pass it to import.
If you only want to confirm whether a value is valid, prefer validate. Do not use set directly.
Follower Node Enrollment: node enroll
Section titled “Follower Node Enrollment: node enroll”This command is only for follower nodes. After the primary admin panel generates an enrollment token, run this on the follower machine:
./aster_drive node enroll \ --master-url https://drive.example.com \ --token enr_xxxxxIf you do not pass the database URL explicitly, the command reads [database].url from the current data/config.toml. You can also specify it directly:
./aster_drive node enroll \ --master-url https://drive.example.com \ --token enr_xxxxx \ --database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc"It performs these steps:
- confirms the current config is
[server].start_mode = "follower" - if the current directory has no config file, generates a default
data/config.tomlin follower mode first - exchanges the token with the primary for local binding information, and writes it into the follower database
- outputs the current listen address, config file path, and next connectivity check hints
The command does not create the primary node’s default remote storage target for you, and it does not start the HTTP service. After it succeeds, restart the follower process, then return to the primary admin panel to create or apply the default remote storage target.
For Docker followers, using startup environment variables to auto-enroll is recommended instead of entering the container manually to run this command. See Docker Follower Node Deployment.
Cross-Database Migration: database-migrate
Section titled “Cross-Database Migration: database-migrate”This command is for “switching database backends”.
It is not the automatic schema migration that runs during normal startup. It copies existing business data from one database to another.
Common scenarios:
- SQLite to PostgreSQL
- SQLite to MySQL
- switching between PostgreSQL and MySQL
Recommended sequence:
- Run
--dry-runfirst. - Prepare a downtime window so the source database is not written during migration.
- Run the real migration.
- Only cut production over to the new database after
ready_to_cutover = true.
Trial run:
./aster_drive database-migrate \ --source-database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --target-database-url "postgres://user:password@127.0.0.1:5432/asterdrive_new" \ --dry-runReal run:
./aster_drive database-migrate \ --source-database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --target-database-url "postgres://user:password@127.0.0.1:5432/asterdrive_new"Verify target database only:
./aster_drive database-migrate \ --source-database-url "sqlite:///var/lib/asterdrive/data/asterdrive.db?mode=rwc" \ --target-database-url "postgres://user:password@127.0.0.1:5432/asterdrive_new" \ --verify-onlyThis command currently handles:
- checking migration state for source and target databases
- automatically bringing the target schema up to the current version
- copying business tables in a fixed order
- validating row counts, unique constraints, and foreign keys
- writing checkpoints into the target database so the same command can resume after interruption
Remember three things when using it:
- The source database must already be at the “current schema”; pending migrations cause immediate refusal.
- Do not continue writing new data into the source database during migration.
- Only
ready_to_cutover = truein the report means the target database is ready for switching.
When to Read This Page First
Section titled “When to Read This Page First”- Deployment is complete, but you are not ready to launch confidently.
- The admin panel cannot open, and you urgently need to inspect configuration.
- A follower node has an enrollment token and needs to enroll from the shell.
- You are preparing to move from SQLite to PostgreSQL / MySQL.
- You want to turn checks into scripts.