Flower Federations with Authentication π§ͺΒΆ
The following steps describe how to start a long-running Flower server (SuperLink) and a long-running Flower clients (SuperNode) with authentication enabled. The task is to train a simple CNN for image classification using PyTorch.
[!TIP] Follow this how-to guide to learn more about Flowerβs Deployment Engine, how setting up secure TLS-enabled communications and SuperNode authentication works. If you are already familiar with how the Deployment Engine works, you may want to learn how to run this same example using Docker. Check out the Flower with Docker documentation.
Project SetupΒΆ
Start by cloning the example project. We prepared a single-line command that you can copy into your shell which will checkout the example for you:
git clone --depth=1 https://github.com/adap/flower.git _tmp \
&& mv _tmp/examples/flower-authentication . \
&& rm -rf _tmp && cd flower-authentication
This will create a new directory called flower-authentication with the following project structure:
flower-authentication
βββ authexample
β βββ __init__.py
β βββ client_app.py # Defines your ClientApp
β βββ server_app.py # Defines your ServerApp
β βββ task.py # Defines your model, training and data loading
βββ pyproject.toml # Project metadata like dependencies and configs
βββ certificate.conf # Configuration for OpenSSL
βββ generate.sh # Generate certificates and keys
βββ prepare_dataset.py # Generate datasets for each SuperNode to use
βββ README.md
Install dependencies and projectΒΆ
Install the dependencies defined in pyproject.toml as well as the authexample package.
pip install -e .
Generate TLS certificatesΒΆ
The generate_cert.sh script generates certificates for creating a secure TLS connection between the SuperLink and SuperNodes, as well as between the flwr CLI (user) and the SuperLink.
[!NOTE] Note that this script should only be used for development purposes and not for creating production key pairs.
./generate_cert.sh
Generate public and private keys for SuperNode authenticationΒΆ
The generate_auth_keys.sh script generates two privateβpublic key pairs for two SuperNodes by default. If you have more SuperNodes, you can specify the number of key pairs to generate.
[!NOTE] Note that this script should only be used for development purposes and not for creating production key pairs.
# Generate two key pairs by default
./generate_auth_keys.sh
# Or pass the desired the number of key pairs
./generate_auth_keys.sh {your_number_of_clients}
Start the long-running Flower server (SuperLink)ΒΆ
Starting long-running Flower server component (SuperLink) and enable authentication is very easy; all you need to do is to pass the --enable-supernode-auth flag. In this example we also enable secure TLS communications between SuperLink, the SuperNodes and the Flower CLI.
Letβs first launch the SuperLink:
flower-superlink \
--ssl-ca-certfile certificates/ca.crt \
--ssl-certfile certificates/server.pem \
--ssl-keyfile certificates/server.key \
--enable-supernode-auth
At this point your server-side is idling. Next, letβs connect two SuperNodes, and then weβll start a run.
Start the long-running Flower client (SuperNode)ΒΆ
[!NOTE] Typically each
SuperNoderuns in a different entity/organization which has access to a dataset. In this example we are going to artificially create N dataset splits and saved them into a new directory calleddatasets/. Then, eachSuperNodewill be pointed to the dataset it should load via the--node-configargument. We provide a script that does the download, partition and saving of CIFAR-10.
python prepare_dataset.py
Pre-registering SuperNodesΒΆ
Before connecting the SuperNodes we need to register them with the SuperLink. This means weβll tell the SuperLink about the identities of the SuperNodes that will be connected. We do this by sending to it the public keys of the SuperNodes that we want the SuperLink to authorize.
Letβs register the first SuperNode. The command below will send the public key to the SuperLink defined in the my-federation federation in the pyproject.toml.
flwr supernode register keys/client_credentials_1.pub . my-federation
# It will print something like:
# Loading project configuration...
# Success
# β
SuperNode 16019329408659850374 registered successfully.
Then, we register the second SuperNode using the other public key:
flwr supernode register keys/client_credentials_2.pub . my-federation
# It will print something like:
# Loading project configuration...
# Success
# β
SuperNode 8392976743692794070 registered successfully.
You could also use the Flower ClI to view the status of the SuperNodes.
flwr supernode list . my-federation
π Listing all nodes...
ββββββββββββββββββββββββ³βββββββββββββ³ββββββββββ³βββββββββββ³βββββββββββββββββββββββ
β Node ID β Owner β Status β Elapsed β Status Changed @ β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 16019329408659850374 β <none> β created β β N/A β
ββββββββββββββββββββββββΌβββββββββββββΌββββββββββΌβββββββββββΌβββββββββββββββββββββββ€
β 8392976743692794070 β <none> β created β β N/A β
ββββββββββββββββββββββββ΄βββββββββββββ΄ββββββββββ΄βββββββββββ΄βββββββββββββββββββββββ
Once the SuperNodes are connected, youβll see the status changes. Letβs connect them !
Connecting SuperNodesΒΆ
In a new terminal window, start the first long-running Flower client (SuperNode):
flower-supernode \
--root-certificates certificates/ca.crt \
--auth-supernode-private-key keys/client_credentials_1 \
--node-config 'dataset-path="datasets/cifar10_part_1"' \
--clientappio-api-address="0.0.0.0:9094"
In yet another new terminal window, start the second long-running Flower client:
flower-supernode \
--root-certificates certificates/ca.crt \
--auth-supernode-private-key keys/client_credentials_2 \
--node-config 'dataset-path="datasets/cifar10_part_2"' \
--clientappio-api-address="0.0.0.0:9095"
Now that you have connected the SuperNodes, you should see them with status online:
flwr supernode list . my-federation
π Listing all nodes...
ββββββββββββββββββββββββ³βββββββββββββ³ββββββββββ³βββββββββββ³βββββββββββββββββββββββ
β Node ID β Owner β Status β Elapsed β Status Changed @ β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 16019329408659850374 β <none> β online β 00:00:30 β 2025-10-13 13:40:47Z β
ββββββββββββββββββββββββΌβββββββββββββΌββββββββββΌβββββββββββΌβββββββββββββββββββββββ€
β 8392976743692794070 β <none> β online β 00:00:22 β 2025-10-13 13:52:21Z β
ββββββββββββββββββββββββ΄βββββββββββββ΄ββββββββββ΄βββββββββββ΄βββββββββββββββββββββββ
If you generated more than 2 client credentials, you can add more clients by opening new terminal windows and running the command above. Donβt forget to specify the correct client private key for each client (SuperNode) you created.
[!TIP] Note the
--node-configpassed when spawning theSuperNodeis accessible to theClientAppvia thecontextargument, i.e.,context.node_config. In this example, theClientAppuses it to load the dataset and then proceed with the training of the model.@app.train() def train(msg: Message, context: Context): # Read the node_config to know where dataset is located dataset_path = context.node_config["dataset-path"] # then load the dataset
Run the Flower AppΒΆ
With both the long-running server (SuperLink) and two SuperNodes up and running, we can now start the run. Note that the command below points to a federation named my-federation. Its entry point is defined in the pyproject.toml. You can optionally use the --stream flag to stream logs from your ServerApp running on SuperLink.
flwr run . my-federation --stream
