Skip to article frontmatterSkip to article content

Installation and deployment

1. Installing Docker

First we need to install Docker. We can use the following commands for Azure VM with Ubuntu 24.04:

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# Install Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add user to docker group
sudo groupadd docker
sudo usermod -aG docker $USER

VM needs to be restarted to make sure that Docker functions properly. After restart, make sure that docker ps command does not give any errors.

Then we clone this repository.

git clone --depth 1 https://ci.tno.nl/gitlab/zonmw-phaeton/phaeton-hub.git
cd phaeton-hub

2. Configuring network

When we are sure that Docker is functional, first we create a (virtual) network called jupyterhub-network .

docker network create jupyterhub-network

Change the domain name to your domain name or IP inside the config/Caddyfile.

your.domain.or.ip.com {
    reverse_proxy jupyterhub:8000
}

Make sure that ports 80 and 443 are available and open to outside such that Caddy can configure SSL certificates automatically.

3. Building images

Build Docker images that are going to be run by the users of the hub.

./build_images.sh

If this command fails first try chmod u+x build_images.sh and try running it again. You can also build images separately with the following command.

docker build -f "images/<docker file name>" -t "<image name>:latest" "images"

In this case you might need to add images you built to the inside c.DockerSpawner.allowed_images inside jupyterhub_config.py.

4. Running docker compose

Then we run docker compose.

docker compose up 

This command will create and run three containers, phaeton-hub-jupyterhub which is the Jupyterhub app, caddy:latest proxy server for HTTPS and dxflrs/garage:v1.0.0 which is the S3 storage. When we deploy it for the first time, we need to configure the Garage.

5. Configuring Garage

First we create an alias to run garage commands from the container.

alias garage="docker exec -it garage /garage"

Afterwards we need to create a cluster layout (see Garage docs). We run the following command:

garage status

It should give an output similar to this:

2025-04-28T09:27:09.622672Z  INFO garage_net::netapp: Connected to 127.0.0.1:3901, negotiating handshake...    
2025-04-28T09:27:09.664938Z  INFO garage_net::netapp: Connection established to c01dae13498aa25e    
==== HEALTHY NODES ====
ID                Hostname      Address         Tags  Zone  Capacity          DataAvail
c01dae13498aa25e  6cc0485836c5  127.0.0.1:3901              NO ROLE ASSIGNED

Here, we copy the ID of the node (c01dae13498aa25e) and run the following to create a cluster layout:

garage layout assign c01dae13498aa25e -z dc1 -c 1G -t phaeton

where dc1 is a name for the zone (irrelevant if we are using only one server for data), 1G is the capacity of the data storage (it is 1 gigabyte, we can choose the size we like, e.g. 500G or 1T), and phaeton is the tag (name) of the storage instance. Afterwards we can check the layout with

garage layout show 

and we will see such an output:

2025-04-28T10:52:48.813723Z  INFO garage_net::netapp: Connected to 127.0.0.1:3901, negotiating handshake...    
2025-04-28T10:52:48.855927Z  INFO garage_net::netapp: Connection established to c01dae13498aa25e    
==== CURRENT CLUSTER LAYOUT ====
No nodes currently have a role in the cluster.
See `garage status` to view available nodes.

Current cluster layout version: 0

==== STAGED ROLE CHANGES ====
ID                Tags     Zone  Capacity
c01dae13498aa25e  phaeton  dc1   1000.0 MB

2025-04-28T10:52:48.922957Z  INFO garage_rpc::layout::history: Layout history: pruning old invalid version 0

==== NEW CLUSTER LAYOUT AFTER APPLYING CHANGES ====
ID                Tags     Zone  Capacity   Usable capacity
c01dae13498aa25e  phaeton  dc1   1000.0 MB  1000.0 MB (100.0%)

Zone redundancy: maximum

==== COMPUTATION OF A NEW PARTITION ASSIGNATION ====

Partitions are replicated 1 times on at least 1 distinct zones.

Optimal partition size:                     3.9 MB
Usable capacity / total cluster capacity:   1000.0 MB / 1000.0 MB (100.0 %)
Effective capacity (replication factor 1):  1000.0 MB

dc1                 Tags     Partitions        Capacity   Usable capacity
  c01dae13498aa25e  phaeton  256 (256 new)     1000.0 MB  1000.0 MB (100.0%)
  TOTAL                      256 (256 unique)  1000.0 MB  1000.0 MB (100.0%)


To enact the staged role changes, type:

    garage layout apply --version 1

You can also revert all proposed changes with: garage layout revert

Afterwards we can apply the layout as suggested by the output of garage layout show and Garage service will be ready to use.

garage layout apply --version 1

We should see such an output as below, then we are done.

2025-04-28T10:56:13.123958Z  INFO garage_net::netapp: Connected to 127.0.0.1:3901, negotiating handshake...    
2025-04-28T10:56:13.165981Z  INFO garage_net::netapp: Connection established to c01dae13498aa25e    
2025-04-28T10:56:13.229611Z  INFO garage_rpc::layout::history: Layout history: pruning old invalid version 0
==== COMPUTATION OF A NEW PARTITION ASSIGNATION ====

Partitions are replicated 1 times on at least 1 distinct zones.

Optimal partition size:                     3.9 MB
Usable capacity / total cluster capacity:   1000.0 MB / 1000.0 MB (100.0 %)
Effective capacity (replication factor 1):  1000.0 MB

dc1                 Tags     Partitions        Capacity   Usable capacity
  c01dae13498aa25e  phaeton  256 (256 new)     1000.0 MB  1000.0 MB (100.0%)
  TOTAL                      256 (256 unique)  1000.0 MB  1000.0 MB (100.0%)


New cluster layout with updated role assignment has been applied in cluster.
Data will now be moved around between nodes accordingly.

After configuring Garage, stop the containers (either Ctrl+C inside the terminal or docker compose down) and restart them again with docker compose up.