Skip to content

Provisioning on server side#60

Merged
Javier-varez merged 21 commits into
mainfrom
storage-provisioning
Apr 10, 2026
Merged

Provisioning on server side#60
Javier-varez merged 21 commits into
mainfrom
storage-provisioning

Conversation

@Javier-varez

@Javier-varez Javier-varez commented Mar 31, 2026

Copy link
Copy Markdown
Member

Implements the basic provisioning functionality on the server-side. Provisioning is divided in the following steps:

  • Storage provisioning: formatting the external drive that will be used for the LEAP data. At this time, it does accept using partitions instead of whole disks, but the disk needs to be externally pre-partitioned, since there is not code to actually partition the disk. Whole disks can be used as well. In either case an ext4 filesystem is created in the selected block device, with a LEAP_DATA label, so that systemd can find it and mount it on boot.
  • Network provisioning: configures the network settings, and validates that the connection can be established correctly. It supports DHCP and manual IPv4 configuration, as well as Wireless and Wired networks. IPv6 is disabled for now.
  • LEAP configuration: configures the parameters for the downloader (concurrent downloads, retries, etc) as well as the remote server configuration (S3 settings). Checks that the S3 parameters can access the remote bucket. We might consider adding an option to bypass the validation of the S3 server, in case we are trying to provision a system at a time when we don't yet have any internet connectivity. For now I have kept it simple.
  • Completion: Saves a record of the provisioning settings to disk and triggers an ordered reboot.

In order to configure the LEAP device when network settings are not yet configured, LEAP falls back to a LEAP-setup access point (generated by the raspberry pi) that allows users to connect to it. It provides a DHCP server so that clients can obtain an IP address. This connection can then be used to follow the provisioning process via the network. When the connection is wired, the same can be achieved via the wired connection if the wired network has a DHCP server.

@Javier-varez

Javier-varez commented Apr 1, 2026

Copy link
Copy Markdown
Member Author

@jfrohnhofen, @chithams This PR is not really ready for review, but I'm posting it so that we can discuss the HTTP API of the provisioning process. Please have a look at the leap-server/src/api/provision.rs file and let's discuss if we are missing something important or if this will work to write the provision frontend.

I have tested the provision process with this simple script that just runs each step in sequence:

curl -v -X POST -H "Content-Type: application/json" http://leap.local/provision/network --data @network_config.json
curl -v -X POST http://leap.local/provision/storage/format?name=/dev/sda
curl -v -X POST -H "Content-Type: application/json" http://leap.local/provision/config --data @leap_config.json
curl -v -X POST http://leap.local/provision/finish

Contents of network_config.json:

{
  "Wired": {
    "ip_config": "Dhcp"
  }
}

Contents of leap_config.json:

{
    "downloader_config": {
        "concurrent_downloads": 2,
        "update_interval": "5 min",
        "retry_params": {
            "initial_backoff": "30 s",
            "backoff_factor": 1.0,
            "max_backoff": "30 s"
        }
    },
    "s3_config": {
        "bucket": "s3://vds-test-bucket",
        "access_key_id": "REDACTED",
        "secret_access_key": "REDACTED",
        "endpoint_url": "REDACTED"
    }
}

This works fine for CLI usage, but of course, the point is to make it workable for the provisioning frontend. Note that, at this time, networking configuration is not really implemented, but the rest is working.

@Javier-varez Javier-varez changed the title Storage and leap configuration provisioning on server side Provisioning on server side Apr 6, 2026
@Javier-varez

Copy link
Copy Markdown
Member Author

@jfrohnhofen, @chithams, I went ahead and added the network configuration code as well using the NetworkManager D-BUS api. This should be complete from the server side. I have a mostly-vibe-coded frontend in this branch that I used to test the logic and process. We might want to use this as the first step for the frontend.

@jfrohnhofen

Copy link
Copy Markdown
Contributor

I haven't started on the UI yet, so more than happy to use your vibe-coded version for now. If there is anything that needs changing, I will base that off of your branch. Let us know once things are ready to be reviewed.

Comment thread leap-linux/configs/leap_defconfig
Comment thread leap-server/src/provision/mod.rs
Comment thread leap-server/src/provision/network.rs Outdated
@Javier-varez
Javier-varez marked this pull request as ready for review April 7, 2026 17:12
@Javier-varez

Copy link
Copy Markdown
Member Author

@jfrohnhofen thanks, I think this is really ready now. I know this is a pretty massive PR, let me know if you need me to split it.

jfrohnhofen
jfrohnhofen previously approved these changes Apr 10, 2026

@jfrohnhofen jfrohnhofen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot! Left a few comments, but nothing major.
I also only skimmed the auto-generated code.

Comment thread leap-api/src/types.rs Outdated
Comment thread leap-api/src/types.rs
) -> impl Responder {
match provision_data.try_lock() {
Ok(mut lock) => match lock.provision.configure_network(&network_config).await {
Ok(()) => HttpResponse::Ok().body(""),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this return valid JSON (null?) instead of an empty body? this applies to all handlers of course.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we plan on doing anything with those return values? Or is the 200 http code enough? Note that the only reason I'm calling body() here is because otherwise the return type for the handers cannot be deduced, as branches have different types returned.

Comment thread leap-server/src/api/provision.rs Outdated
Comment thread leap-server/src/provision/network/dbus.rs
Comment thread leap-server/src/provision/network/dbus.rs
Comment thread leap-server/src/provision/cfg.rs Outdated
Comment thread leap-server/src/provision/network.rs Outdated
Comment thread leap-server/src/provision/network/dbus.rs Outdated
Comment thread leap-server/src/provision/mod.rs
@Javier-varez

Copy link
Copy Markdown
Member Author

Thanks for the review @jfrohnhofen ! I addressed the comments :) The autogenerated code is pretty awful IMO, but not worth reviewing, seems to be just fine either way.

jfrohnhofen
jfrohnhofen previously approved these changes Apr 10, 2026
@Javier-varez

Copy link
Copy Markdown
Member Author

Hmm, interestingly cargo deny now fails, and it's related to its latest update. cargo deny 0.19.1 was released today at 13:00... and it brings this change:

EmbarkStudios/cargo-deny@a1728a7

which brings a couple of important fixes:

EmbarkStudios/krates#106
EmbarkStudios/krates#109

So now a license that we were not handling has just been detected! I'll fix it

@Javier-varez
Javier-varez merged commit a9b811d into main Apr 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants