Docker Deployment
Who this page is for
NAS, single-machine, small-team, or existing container-orchestrated deployments. You can get it running in 10 minutes. For production launch, put a reverse proxy in front to handle HTTPS. Do not expose port 3000 directly to the public internet.
The official image runs as a non-root user by default (UID/GID fixed to 10001:10001, username aster) and includes a HEALTHCHECK based on /health/ready.
If you bind mount a host directory directly to /data (recommended, because backups and migration are clearer), create the directory first and change its owner to 10001:10001. Otherwise, container startup will fail with permission errors when generating config.toml, creating the SQLite file, or creating temporary directories:
mkdir -p ./data
sudo chown -R 10001:10001 ./dataIf you use a named volume (docker volume create or a volumes: section in Compose), Docker automatically sets the volume owner to the user running inside the container. You do not need to run chown manually.
Running the service in a container does not mean you should expose port 3000 to the public internet long term.
For production launch, you should still put a reverse proxy in front to handle HTTPS, HSTS, upload limits, WebDAV, and WOPI, and preserve the browser page baseline Content-Security-Policy returned by AsterDrive. Do not rewrite the whole site's CSP to a site-wide sandbox.
If this container should run as a follower node
Follower nodes now support reading bootstrap ENV during startup and completing enrollment directly.
If you want to attach another AsterDrive instance as a follower node with Docker, the old flow of manually running docker exec ... node enroll is no longer recommended. See Docker Follower Node Deployment instead.
What /data Usually Contains
If you bind mount ./data to the container's /data as shown above, you will usually see:
config.tomlasterdrive.dbuploads/avatar/(after users upload avatars).tmp/.uploads/
Among these:
config.toml,asterdrive.db,uploads/, andavatar/if avatar upload is enabled, must be kept long term..tmp/and.uploads/generally do not need backup, but they affect local disk usage.
See Backup and Restore for more complete backup / restore guidance.
Try It First
If you are still in a plain HTTP test environment, you can run:
mkdir -p ./data
sudo chown -R 10001:10001 ./data
docker run -d \
--name asterdrive \
-p 3000:3000 \
-e ASTER__SERVER__HOST=0.0.0.0 \
-e ASTER__AUTH__BOOTSTRAP_INSECURE_COOKIES=true \
-e ASTER__DATABASE__URL="sqlite:///data/asterdrive.db?mode=rwc" \
-v "$(pwd)/data:/data" \
ghcr.io/astercommunity/asterdrive:latestThis only disables the browser Cookie HTTPS requirement during first initialization.
After switching to HTTPS for production, change the corresponding system setting back to enabled in the admin panel, then remove this environment variable.
After startup, use docker ps to check container status. Normally it becomes healthy after a short time.
Long-Term Deployment: Edit config.toml on the Host
config.toml is now generated uniformly at /data/config.toml, in the same volume as the database and upload directories. It no longer needs to be mounted separately as read-only as older documentation described.
After binding ./data to /data with the command above, AsterDrive automatically generates ./data/config.toml on first startup. You can then edit that file directly on the host to override defaults, for example:
[auth]
jwt_secret = "replace-with-your-own-random-secret"
bootstrap_insecure_cookies = false
[server]
temp_dir = "/data/.tmp"
upload_temp_dir = "/data/.uploads"Restart the container after editing for changes to take effect.
Compose Example
services:
asterdrive:
image: ghcr.io/astercommunity/asterdrive:latest
ports:
- "3000:3000"
environment:
ASTER__SERVER__HOST: 0.0.0.0
ASTER__DATABASE__URL: sqlite:///data/asterdrive.db?mode=rwc
volumes:
- ./data:/data
- /etc/localtime:/etc/localtime:ro
restart: unless-stoppedBefore running docker compose up -d for the first time, prepare the host directory with mkdir -p ./data && sudo chown -R 10001:10001 ./data as described at the top. Otherwise, the in-container aster user (UID/GID 10001) cannot write to it, and startup will fail.
Enable aria2 Link Import with Compose
The repository root docker-compose.yml includes an optional aria2 profile. Plain docker compose up -d does not start it; aria2 is started only when the profile is enabled explicitly.
Prepare both the AsterDrive data directory and the aria2 configuration directory first. AsterDrive and aria2 must mount the same host ./data directory at the same in-container /data path, because AsterDrive passes task temporary file paths such as /data/.tmp/... to aria2 as absolute paths:
mkdir -p ./data ./aria2-config
sudo chown -R 10001:10001 ./data ./aria2-configSet an RPC secret and start both services. ASTERDRIVE_ARIA2_RPC_SECRET is required; do not start the aria2 profile with this variable unset, because the Compose service passes it directly to RPC_SECRET for p3terx/aria2-pro:
export ASTERDRIVE_ARIA2_RPC_SECRET="$(openssl rand -hex 24)"
docker compose --profile aria2 up -dThen open Admin -> System Settings -> File Processing -> Link Import and enable aria2 in the link-import engine registry. If you want the built-in downloader as fallback, keep builtin enabled after aria2; if you want aria2 only, disable builtin. Then set these runtime config values:
| Config key | Value |
|---|---|
offline_download_temp_dir | /data/.tmp/offline-download |
offline_download_aria2_rpc_url | http://aria2:6800/jsonrpc |
offline_download_aria2_rpc_secret | the value of ASTERDRIVE_ARIA2_RPC_SECRET above |
If you start only aria2 with Compose while running AsterDrive on the host with cargo run, use http://127.0.0.1:6800/jsonrpc instead. This mixed development mode still requires offline_download_temp_dir to be the same absolute path visible to both sides. For example, mount host ./data/offline-download-temp into the aria2 container at /srv/asterdrive/offline-download-temp, then put that host absolute path in AsterDrive.
When aria2 runs as a different OS user, AsterDrive must let that external writer create the downloaded temp file under the per-task token_dir. The compatibility path in allow_external_aria2_writer_chain makes the per-task directories world-writable, while leaving the shared parent tasks directory traversable only. This is acceptable for isolated single-tenant Compose deployments where the temp volume is not shared with untrusted local users. Safer production alternatives are to run both processes under the same UID, assign a shared group and use 0o770, or apply POSIX ACLs for the aria2 user on token_dir.
After saving, use Test aria2 in the link-import engine registry. The server calls aria2.getVersion with the current RPC URL and secret to confirm AsterDrive can reach the aria2 JSON-RPC endpoint.
You can also write the SQLite runtime config from the CLI during a maintenance window:
docker compose exec asterdrive /usr/local/bin/aster_drive \
config --database-url "sqlite:///data/asterdrive.db?mode=rwc" \
set --key offline_download_engine_registry_json \
--value '{"version":1,"engines":[{"kind":"aria2","enabled":true},{"kind":"builtin","enabled":true}]}'
docker compose exec asterdrive /usr/local/bin/aster_drive \
config --database-url "sqlite:///data/asterdrive.db?mode=rwc" \
set --key offline_download_aria2_rpc_url --value http://aria2:6800/jsonrpc
docker compose exec asterdrive /usr/local/bin/aster_drive \
config --database-url "sqlite:///data/asterdrive.db?mode=rwc" \
set --key offline_download_temp_dir --value /data/.tmp/offline-download
docker compose exec asterdrive /usr/local/bin/aster_drive \
config --database-url "sqlite:///data/asterdrive.db?mode=rwc" \
set --key offline_download_aria2_rpc_secret --value "$ASTERDRIVE_ARIA2_RPC_SECRET"Do not publish aria2 port 6800 to the public internet in production; if host-side AsterDrive does not need to reach it, do not publish it to the host either. aria2 still performs its own DNS resolution and outbound connection for downloads, so production deployments should also restrict its reachable network using Docker networking, host firewall rules, or upstream network policy.
For full configuration, security boundaries, and troubleshooting, see Offline Download.
First Deployment Checks Worth Doing
- Whether
auth.jwt_secrethas been fixed. - If this is temporarily a plain HTTP test, whether
bootstrap_insecure_cookies = truewas set only for first bootstrap. - After switching to HTTPS, whether the Cookie security switch in system settings has been changed back to enabled.
- Whether the home page response headers include the browser page baseline
Content-Security-Policyreturned by AsterDrive, and whether the proxy has removed it or replaced it with an incompatible policy. - If the site is publicly accessible, whether
Public Site URLis set to a realhttps://origin. Add multiple public domains one by one, with the default origin first. - If public registration, password recovery, or email rebinding will be enabled, whether a test email has been sent successfully.
- Whether the database, upload directory, and temporary directories all live in the bind-mounted
./datadirectory, with nothing accidentally written inside the container layer. - Whether the default policy group has been created.
- If external Office / WOPI openers are enabled, whether at least one real Office file can be opened and saved.
- If aria2 link import is enabled, whether
offline_download_aria2_rpc_urlpoints to the Docker-internal addresshttp://aria2:6800/jsonrpcfor full Docker deployments, whetheroffline_download_temp_diris the same absolute path visible to both sides, or whether RPC points tohttp://127.0.0.1:6800/jsonrpcfor host-sidecargo run+ Compose aria2 development; and whether the aria2 RPC port is not exposed publicly. - If you plan to use S3 / MinIO later, whether browser upload CORS rules and secret management for object storage have been planned.
- If this instance should actually run as a
follower, whether long-termstart_mode, single-use bootstrap ENV, and the primary-side default receiving target have been configured according to Docker Follower Node Deployment.
View Runtime Status
docker logs -f asterdriveUpgrade
If you use the Compose example above:
docker compose pull
docker compose up -dIf you run directly with docker run, the steps are the same: pull the new image, stop the old container, and start it again with the same command. The bind-mounted ./data is not affected:
docker pull ghcr.io/astercommunity/asterdrive:latest
docker rm -f asterdrive
# Run the docker run command from "Try It First" againAfter upgrading, reopen the browser page and recheck login, upload, sharing, policy groups, WebDAV, and any external openers currently in use.