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
Confirm These 4 Things First
Section titled “Confirm These 4 Things First”1. The Primary Node Is Running Normally
Section titled “1. The Primary Node Is Running Normally”At minimum:
- The primary admin panel can open normally.
Admin -> System Settings -> Site Configuration -> Public Site URLis 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.comhttp://10.0.0.23:3000http://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.
4. The Token Is Single-Use
Section titled “4. The Token Is Single-Use”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 NodesCreate 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_urltoken
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.
2. Prepare the Follower Data Directory
Section titled “2. Prepare the Follower Data Directory”If you use a bind mount, create the host directory first and change its owner:
mkdir -p ./datasudo chown -R 10001:10001 ./dataIf you use a named volume, you can skip this step.
3. Write compose.yaml
Section titled “3. Write compose.yaml”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-stoppedThe easiest confusion here is between two classes of environment variables:
ASTER__...These are long-term runtime configuration overrides. They use the same structure asconfig.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 variable | Purpose | Recommendation |
|---|---|---|
ASTER__SERVER__HOST | Makes the in-container service listen on all interfaces for Docker port mapping | Usually keep in Docker setups |
ASTER__SERVER__START_MODE | Switches the instance into follower mode | Keep long term for follower nodes |
ASTER__SERVER__FOLLOWER__REMOTE_STORAGE_TARGET_LOCAL_ROOT | Restricts local remote storage targets pushed by the primary to this root directory | Keep if local remote storage targets are needed |
ASTER__DATABASE__URL | Specifies the follower’s own database | Recommended to set explicitly in Docker |
ASTER_BOOTSTRAP_REMOTE_MASTER_URL | Primary address used during first enrollment | Remove after success |
ASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKEN | Single-use enrollment token generated by the primary | Remove 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.
4. First Startup
Section titled “4. First Startup”docker compose up -ddocker logs -f asterdrive-followerNormally, first startup completes these steps in order:
- Automatically generate config when
/data/config.tomldoes not exist. - Start in
followermode. - Use
ASTER_BOOTSTRAP_REMOTE_MASTER_URLandASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKENto exchange bootstrap information with the primary. - Write the primary binding into the local database.
- Continue follower runtime initialization.
You should see log messages like:
Configuration loaded from: /data/config.tomlbootstrapped follower enrollment from environmentstartup 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.
5. Verify the Follower Is Ready
Section titled “5. Verify the Follower Is Ready”Check container status first:
docker psThen check health directly:
curl http://127.0.0.1:3001/healthcurl http://127.0.0.1:3001/health/readyExpected result:
/healthreturns200./health/readyshould also return200after enrollment succeeds and startup completes.
Then go back to the primary admin panel:
Admin -> Follower NodesClick “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 PoliciesCreate 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_URLASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKEN
Then run again:
docker compose up -dThe 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.
Common Issues
Section titled “Common Issues”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_urlin 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.hostallows 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_modetofollowerin/data/config.toml - or keep
ASTER__SERVER__START_MODE=followerin 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.