Docker Follower Node Deployment
Who this page is for
Use this if you want to run another AsterDrive instance as a follower with Docker, and you want it to auto-enroll from environment variables during first startup instead of manually running docker exec ... aster_drive node enroll.
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
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/
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
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.
If the follower is behind NAT or CGNAT
If the primary cannot reach the follower, but the follower can reach the primary public site URL, choose reverse tunnel or auto with an empty base_url when creating the remote node.
Reverse tunnel is still under test and is suitable for relay_stream upload/download. If you need remote presigned upload or download, you still need direct transport, and browsers must also be able to reach the follower base_url.
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
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 receiving target 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 receiving target.
2. Prepare the Follower Data Directory
If you use a bind mount, create the host directory first and change its owner:
mkdir -p ./data
sudo chown -R 10001:10001 ./dataIf you use a named volume, you can skip this step.
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 receiving targets pushed by the primary to this root directory | Keep if local receiving 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 |
Receiving targets are not passed in bootstrap ENV. The current flow is: the follower enrolls first, then the primary node pushes receiving targets through the follower API. The entry is Admin -> Follower Nodes, which is better for later review, modification, and troubleshooting.
4. First Startup
docker compose up -d
docker 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.
Bootstrap ENV must appear as a pair
ASTER_BOOTSTRAP_REMOTE_MASTER_URL and ASTER_BOOTSTRAP_REMOTE_ENROLLMENT_TOKEN must be set together.
If only one is set, the service will report incomplete configuration early in startup. If neither is set, it starts as a normal follower and does not auto-enroll.
5. Verify the Follower Is Ready
Check container status first:
docker psThen check health directly:
curl http://127.0.0.1:3001/health
curl 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 receiving target.
When the connection test passes, the primary also reads the follower's internal storage protocol capabilities. The current internal protocol version is v4, and the follower must support v4. If the capability summary says the protocol is incompatible, upgrade the primary or follower before creating remote policies.
For the first receiving target, choose:
- Driver:
local - Base path: a relative path such as
default - Check "Set as default receiving target"
The path for a local receiving 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 receiving target here too, not through bootstrap ENV.
After the receiving 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
After confirming the follower is ready, the primary connection test passes, and the default receiving 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
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
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
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
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.