Skip to content
AsterDrive
Security update: Docker images from v0.4.0-rc.1 fix the high-severity FFmpeg MagicYUV decoder vulnerability (CVE-2026-8461). Upgrade instances using older images immediately.View CVE advisory
Security update: v0.4.0-beta.3 fixes a WebDAV request issue that can terminate the server process. Upgrade older instances promptly.View advisory

Docker Follower Node Deployment

This page only covers follower node deployment in Docker. For how the primary node understands follower nodes and how to create follower storage policies, see Follower Nodes.

The biggest difference from the old workflow is one thing:

  • A follower container can now read bootstrap ENV at startup and complete enrollment automatically.

That means first startup no longer requires:

  • manually entering the container to run aster_drive node enroll
  • restarting the container once more after enrollment finishes

At minimum:

  • The primary admin panel can open normally.
  • Admin -> System Settings -> Site Configuration -> Public Site URL is set to a real reachable HTTP(S) origin. If multiple origins are configured, put the primary origin that the follower can reach on the first line.
  • You have decided this follower’s name, and whether it should use direct, reverse tunnel, or auto transport.

2. The Follower Must Have Its Own Independent data/

Section titled “2. The Follower Must Have Its Own Independent data/”

The primary node and follower must never share:

  • data/config.toml
  • database
  • upload directory
  • temporary directory

A follower node is not “another copy of the primary node”. It is another independent AsterDrive instance.

3. Decide Between Direct and Reverse Tunnel

Section titled “3. Decide Between Direct and Reverse Tunnel”

If you choose direct transport, the primary must be able to access the follower base_url. On different machines, it is usually one of:

  • https://follower.example.com
  • http://10.0.0.23:3000
  • http://host.example.com:3001

If both instances are in a Docker network and the primary can resolve the container name, you may also use the in-container address directly. Do not default to http://localhost:3000; that usually only works from the follower itself.

Enrollment tokens generated by the primary admin panel:

  • expire after 30 minutes by default
  • become invalid after one successful exchange

So these ENV values are only suitable for first-start bootstrap. Do not leave old tokens in Compose long term.

1. Create a Follower Node and Generate a Token in the Primary Admin Panel

Section titled “1. Create a Follower Node and Generate a Token in the Primary Admin Panel”

Entry:

Admin -> Follower Nodes

Create a follower node record first, and at least fill in:

  • name
  • transport mode
  • base_url: required for direct; optional for reverse tunnel; in auto mode, empty means reverse tunnel

After saving, the admin panel generates enrollment information. The Docker follower needs these two values at startup:

  • master_url
  • token

In the current version, the follower’s object destination is pushed by the primary node from the follower node details page. In other words, Docker bootstrap only binds the primary and follower identities. Whether objects are ultimately written to a follower local directory or S3 is configured later in the primary admin panel by creating a remote storage target.

If you use a bind mount, create the host directory first and change its owner:

Terminal window
mkdir -p ./data
sudo chown -R 10001:10001 ./data

If you use a named volume, you can skip this step.

This example assumes the follower is exposed on host port 3001:

services:
asterdrive-follower:
image: ghcr.io/astercommunity/asterdrive:latest
container_name: asterdrive-follower
ports:
- "3001:3000"
environment:
ASTER__SERVER__HOST: 0.0.0.0
ASTER__SERVER__START_MODE: follower
ASTER__SERVER__FOLLOWER__REMOTE_STORAGE_TARGET_LOCAL_ROOT: /data/remote-storage-targets
ASTER__DATABASE__URL: sqlite:///data/asterdrive.db?mode=rwc
ASTER_BOOTSTRAP_REMOTE_MASTER_URL: https://drive.example.com
ASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKEN: enr_replace_me
volumes:
- ./data:/data
- /etc/localtime:/etc/localtime:ro
restart: unless-stopped

The easiest confusion here is between two classes of environment variables:

  • ASTER__... These are long-term runtime configuration overrides. They use the same structure as config.toml, and values that should remain effective long term should stay here.
  • ASTER_BOOTSTRAP_REMOTE_* These are single-use bootstrap inputs. Remove them after first enrollment succeeds.

Understand the ENV values used on this page like this:

Environment variablePurposeRecommendation
ASTER__SERVER__HOSTMakes the in-container service listen on all interfaces for Docker port mappingUsually keep in Docker setups
ASTER__SERVER__START_MODESwitches the instance into follower modeKeep long term for follower nodes
ASTER__SERVER__FOLLOWER__REMOTE_STORAGE_TARGET_LOCAL_ROOTRestricts local remote storage targets pushed by the primary to this root directoryKeep if local remote storage targets are needed
ASTER__DATABASE__URLSpecifies the follower’s own databaseRecommended to set explicitly in Docker
ASTER_BOOTSTRAP_REMOTE_MASTER_URLPrimary address used during first enrollmentRemove after success
ASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKENSingle-use enrollment token generated by the primaryRemove after success

Remote storage targets are not passed in bootstrap ENV. The current flow is: the follower enrolls first, then the primary node pushes remote storage targets through the follower API. The entry is Admin -> Follower Nodes, which is better for later review, modification, and troubleshooting.

Terminal window
docker compose up -d
docker logs -f asterdrive-follower

Normally, first startup completes these steps in order:

  1. Automatically generate config when /data/config.toml does not exist.
  2. Start in follower mode.
  3. Use ASTER_BOOTSTRAP_REMOTE_MASTER_URL and ASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKEN to exchange bootstrap information with the primary.
  4. Write the primary binding into the local database.
  5. Continue follower runtime initialization.

You should see log messages like:

  • Configuration loaded from: /data/config.toml
  • bootstrapped follower enrollment from environment
  • startup complete - listening on 0.0.0.0:3000

On this path, you do not need to run node enroll manually, and you do not need an extra restart after first startup.

Check container status first:

Terminal window
docker ps

Then check health directly:

Terminal window
curl http://127.0.0.1:3001/health
curl http://127.0.0.1:3001/health/ready

Expected result:

  • /health returns 200.
  • /health/ready should also return 200 after enrollment succeeds and startup completes.

Then go back to the primary admin panel:

Admin -> Follower Nodes

Click “Test Connection”. Direct nodes access base_url; reverse-tunnel nodes use the outbound channel maintained by the follower, which may need a few dozen seconds after startup before it becomes online. After the test passes, open the follower node details and create a default remote storage target.

When the connection test passes, the primary also reads the follower’s internal storage protocol capabilities. The current primary uses v5 and supports followers down to v4. If the declared protocol ranges do not overlap, upgrade the primary or follower before creating remote policies.

For the first remote storage target, choose:

  • Driver: local
  • Base path: a relative path such as default
  • Check “Set as default remote storage target”

The path for a local remote storage target is restricted under the follower’s server.follower.remote_storage_target_local_root. If you want the follower to write to S3 / MinIO instead, create an s3 remote storage target here too, not through bootstrap ENV.

After the remote storage target is applied, go to:

Admin -> Storage Policies

Create a storage policy of type Follower Node.

If the follower policy uses presigned upload or download, also confirm the remote node uses direct transport, the browser can access the follower base_url, and the reverse proxy in front of the follower does not strip CORS headers from internal storage APIs. Uploads need to allow content-type and expose ETag; Range downloads need to allow range and expose Accept-Ranges, Content-Range, and Content-Length.

6. Remove Single-Use Bootstrap ENV After First Success

Section titled “6. Remove Single-Use Bootstrap ENV After First Success”

After confirming the follower is ready, the primary connection test passes, and the default remote storage target has been applied, remove these ENV values from Compose:

  • ASTER_BOOTSTRAP_REMOTE_MASTER_URL
  • ASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKEN

Then run again:

Terminal window
docker compose up -d

The primary binding has already been persisted in the database. Later follower restarts do not need bootstrap again. But long-term runtime settings such as ASTER__SERVER__START_MODE=follower should still remain.

Logs Say the Token Is Completed, Expired, or Replaced

Section titled “Logs Say the Token Is Completed, Expired, or Replaced”

This means you are using an old token. Generate a new enrollment token in the primary admin panel, then update Compose.

/health Is 200 but /health/ready Is Still 503

Section titled “/health Is 200 but /health/ready Is Still 503”

This usually means the follower process is alive, but the primary binding has not taken effect. Check first:

  • whether bootstrap ENV values are correct
  • whether the token has expired
  • whether the binding was actually written into the follower local database
  • whether bootstrap failure warnings appear in logs

The Follower Starts, but the Primary Connection Test Fails

Section titled “The Follower Starts, but the Primary Connection Test Fails”

Check these things first:

  • Whether the remote node transport mode is correct.
  • In direct mode, whether the base_url in the primary admin panel is an address the primary can actually reach.
  • In reverse tunnel mode, whether the follower can reach the primary public site URL, and whether proxies or firewalls block WebSocket / long-lived connections.
  • In direct mode, whether port mapping, reverse proxy, or NAT routes traffic correctly to the follower’s 3000.
  • Whether the follower server.host allows external access.

Existing /data/config.toml Still Says primary

Section titled “Existing /data/config.toml Still Says primary”

The safest options are:

  • directly change [server].start_mode to follower in /data/config.toml
  • or keep ASTER__SERVER__START_MODE=follower in Compose long term, as shown above

The bootstrap token does not automatically change an existing primary config to follower. Change start_mode explicitly, or keep the environment override long term.

If startup includes ASTER_BOOTSTRAP_REMOTE_* but the final loaded mode is still primary, the service stops and asks you to switch to follower first. This prevents accidentally enrolling a primary instance as a follower node.