diff --git a/driver.go b/driver.go
index 39a0cb8bf65a9aeecba92cdbf9b22cd2b1514d9d..4868d1e434c1aa86ba6c5779ea7e7f7e5cd7d77a 100644
--- a/driver.go
+++ b/driver.go
@@ -20,6 +20,7 @@ import (
 	"golang.org/x/crypto/ssh"
 )
 
+// Driver contains hetzner-specific data to implement [drivers.Driver]
 type Driver struct {
 	*drivers.BaseDriver
 
@@ -70,6 +71,7 @@ const (
 	flagServerLabel       = "hetzner-server-label"
 )
 
+// NewDriver initializes a new driver instance; see [drivers.Driver.NewDriver]
 func NewDriver() *Driver {
 	return &Driver{
 		Image:         defaultImage,
@@ -83,10 +85,12 @@ func NewDriver() *Driver {
 	}
 }
 
+// DriverName returns the hard-coded string "hetzner"; see [drivers.Driver.DriverName]
 func (d *Driver) DriverName() string {
 	return "hetzner"
 }
 
+// GetCreateFlags retrieves additional driver-specific arguments; see [drivers.Driver.GetCreateFlags]
 func (d *Driver) GetCreateFlags() []mcnflag.Flag {
 	return []mcnflag.Flag{
 		mcnflag.StringFlag{
@@ -174,6 +178,8 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
 	}
 }
 
+// SetConfigFromFlags handles additional driver arguments as retrieved by [Driver.GetCreateFlags];
+// see [drivers.Driver.SetConfigFromFlags]
 func (d *Driver) SetConfigFromFlags(opts drivers.DriverOptions) error {
 	d.AccessToken = opts.String(flagAPIToken)
 	d.Image = opts.String(flagImage)
@@ -220,6 +226,7 @@ func (d *Driver) setLabelsFromFlags(opts drivers.DriverOptions) error {
 	return nil
 }
 
+// PreCreateCheck validates the Driver data is in a valid state for creation; see [drivers.Driver.PreCreateCheck]
 func (d *Driver) PreCreateCheck() error {
 	if d.IsExistingKey {
 		if d.originalKey == "" {
@@ -267,180 +274,244 @@ func (d *Driver) PreCreateCheck() error {
 	return nil
 }
 
+// Create actually creates the hetzner-cloud server; see [drivers.Driver.Create]
 func (d *Driver) Create() error {
-	if d.originalKey != "" {
-		log.Debugf("Copying SSH key...")
-		if err := d.copySSHKeyPair(d.originalKey); err != nil {
-			return errors.Wrap(err, "could not copy ssh key pair")
-		}
-	} else {
-		log.Debugf("Generating SSH key...")
-		if err := mcnssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
-			return errors.Wrap(err, "could not generate ssh key")
-		}
+	err := d.prepareLocalKey()
+	if err != nil {
+		return err
 	}
 
 	defer d.destroyDanglingKeys()
-	if d.KeyID == 0 {
-		log.Infof("Creating SSH key...")
+	err = d.createRemoteKeys()
+	if err != nil {
+		return err
+	}
 
-		buf, err := ioutil.ReadFile(d.GetSSHKeyPath() + ".pub")
-		if err != nil {
-			return errors.Wrap(err, "could not read ssh public key")
-		}
+	log.Infof("Creating Hetzner server...")
 
-		key, err := d.getRemoteKeyWithSameFingerprint(buf)
-		if err != nil {
-			return errors.Wrap(err, "error retrieving potentially existing key")
-		}
-		if key == nil {
-			log.Infof("SSH key not found in Hetzner. Uploading...")
+	srvopts, err := d.makeCreateServerOptions()
+	if err != nil {
+		return err
+	}
 
-			key, err = d.makeKey(d.GetMachineName(), string(buf))
+	srv, _, err := d.getClient().Server.Create(context.Background(), *srvopts)
+	if err != nil {
+		return errors.Wrap(err, "could not create server")
+	}
+
+	log.Infof(" -> Creating server %s[%d] in %s[%d]", srv.Server.Name, srv.Server.ID, srv.Action.Command, srv.Action.ID)
+	if err = d.waitForAction(srv.Action); err != nil {
+		return errors.Wrap(err, "could not wait for action")
+	}
+
+	d.ServerID = srv.Server.ID
+	log.Infof(" -> Server %s[%d]: Waiting to come up...", srv.Server.Name, srv.Server.ID)
+
+	err = d.waitForRunningServer()
+	if err != nil {
+		return err
+	}
+
+	err = d.configureNetworkAccess(srv)
+	if err != nil {
+		return err
+	}
+
+	log.Infof(" -> Server %s[%d] ready. Ip %s", srv.Server.Name, srv.Server.ID, d.IPAddress)
+	// Successful creation, so no keys dangle anymore
+	d.danglingKeys = nil
+
+	return nil
+}
+
+func (d *Driver) configureNetworkAccess(srv hcloud.ServerCreateResult) error {
+	if d.UsePrivateNetwork {
+		for {
+			// we need to wait until network is attached
+			log.Infof("Wait until private network attached ...")
+			server, _, err := d.getClient().Server.GetByID(context.Background(), srv.Server.ID)
 			if err != nil {
-				return err
+				return errors.Wrapf(err, "could not get newly created server [%d]", srv.Server.ID)
 			}
-		} else {
-			d.IsExistingKey = true
-			log.Debugf("SSH key found in Hetzner. ID: %d", key.ID)
+			if server.PrivateNet != nil {
+				d.IPAddress = server.PrivateNet[0].IP.String()
+				break
+			}
+			time.Sleep(1 * time.Second)
 		}
-
-		d.KeyID = key.ID
+	} else {
+		log.Infof("Using public network ...")
+		d.IPAddress = srv.Server.PublicNet.IPv4.IP.String()
 	}
-	for i, pubkey := range d.additionalKeys {
-		key, err := d.getRemoteKeyWithSameFingerprint([]byte(pubkey))
+	return nil
+}
+
+func (d *Driver) waitForRunningServer() error {
+	for {
+		srvstate, err := d.GetState()
 		if err != nil {
-			return errors.Wrapf(err, "error checking for existing key for %v", pubkey)
+			return errors.Wrap(err, "could not get state")
 		}
-		if key == nil {
-			log.Infof("Creating new key for %v...", pubkey)
-			key, err = d.makeKey(fmt.Sprintf("%v-additional-%d", d.GetMachineName(), i), pubkey)
-
-			if err != nil {
-				return errors.Wrapf(err, "error creating new key for %v", pubkey)
-			}
 
-			log.Infof(" -> Created %v", key.ID)
-			d.AdditionalKeyIDs = append(d.AdditionalKeyIDs, key.ID)
-		} else {
-			log.Infof("Using existing key (%v) %v", key.ID, key.Name)
+		if srvstate == state.Running {
+			break
 		}
 
-		d.cachedAdditionalKeys = append(d.cachedAdditionalKeys, key)
+		time.Sleep(1 * time.Second)
 	}
+	return nil
+}
 
-	log.Infof("Creating Hetzner server...")
-
+func (d *Driver) makeCreateServerOptions() (*hcloud.ServerCreateOpts, error) {
 	srvopts := hcloud.ServerCreateOpts{
 		Name:     d.GetMachineName(),
 		UserData: d.userData,
 		Labels:   d.serverLabels,
 	}
 
+	networks, err := d.createNetworks()
+	if err != nil {
+		return nil, err
+	}
+	srvopts.Networks = networks
+
+	firewalls, err := d.createFirewalls()
+	if err != nil {
+		return nil, err
+	}
+	srvopts.Firewalls = firewalls
+
+	volumes, err := d.createVolumes()
+	if err != nil {
+		return nil, err
+	}
+	srvopts.Volumes = volumes
+
+	if srvopts.Location, err = d.getLocation(); err != nil {
+		return nil, errors.Wrap(err, "could not get location")
+	}
+	if srvopts.ServerType, err = d.getType(); err != nil {
+		return nil, errors.Wrap(err, "could not get type")
+	}
+	if srvopts.Image, err = d.getImage(); err != nil {
+		return nil, errors.Wrap(err, "could not get image")
+	}
+	key, err := d.getKey()
+	if err != nil {
+		return nil, errors.Wrap(err, "could not get ssh key")
+	}
+	srvopts.SSHKeys = append(d.cachedAdditionalKeys, key)
+	return &srvopts, nil
+}
+
+func (d *Driver) createNetworks() ([]*hcloud.Network, error) {
 	networks := []*hcloud.Network{}
 	for _, networkIDorName := range d.networks {
 		network, _, err := d.getClient().Network.Get(context.Background(), networkIDorName)
 		if err != nil {
-			return errors.Wrap(err, "could not get network by ID or name")
+			return nil, errors.Wrap(err, "could not get network by ID or name")
 		}
 		if network == nil {
-			return errors.Errorf("network '%s' not found", networkIDorName)
+			return nil, errors.Errorf("network '%s' not found", networkIDorName)
 		}
 		networks = append(networks, network)
 	}
-	srvopts.Networks = networks
+	return networks, nil
+}
 
+func (d *Driver) createFirewalls() ([]*hcloud.ServerCreateFirewall, error) {
 	firewalls := []*hcloud.ServerCreateFirewall{}
 	for _, firewallIDorName := range d.firewalls {
 		firewall, _, err := d.getClient().Firewall.Get(context.Background(), firewallIDorName)
 		if err != nil {
-			return errors.Wrap(err, "could not get firewall by ID or name")
+			return nil, errors.Wrap(err, "could not get firewall by ID or name")
 		}
 		if firewall == nil {
-			return errors.Errorf("firewall '%s' not found", firewallIDorName)
+			return nil, errors.Errorf("firewall '%s' not found", firewallIDorName)
 		}
 		firewalls = append(firewalls, &hcloud.ServerCreateFirewall{Firewall: *firewall})
 	}
-	srvopts.Firewalls = firewalls
+	return firewalls, nil
+}
 
+func (d *Driver) createVolumes() ([]*hcloud.Volume, error) {
 	volumes := []*hcloud.Volume{}
 	for _, volumeIDorName := range d.volumes {
 		volume, _, err := d.getClient().Volume.Get(context.Background(), volumeIDorName)
 		if err != nil {
-			return errors.Wrap(err, "could not get volume by ID or name")
+			return nil, errors.Wrap(err, "could not get volume by ID or name")
 		}
 		if volume == nil {
-			return errors.Errorf("volume '%s' not found", volumeIDorName)
+			return nil, errors.Errorf("volume '%s' not found", volumeIDorName)
 		}
 		volumes = append(volumes, volume)
 	}
-	srvopts.Volumes = volumes
-
-	var err error
-	if srvopts.Location, err = d.getLocation(); err != nil {
-		return errors.Wrap(err, "could not get location")
-	}
-	if srvopts.ServerType, err = d.getType(); err != nil {
-		return errors.Wrap(err, "could not get type")
-	}
-	if srvopts.Image, err = d.getImage(); err != nil {
-		return errors.Wrap(err, "could not get image")
-	}
-	key, err := d.getKey()
-	if err != nil {
-		return errors.Wrap(err, "could not get ssh key")
-	}
-	srvopts.SSHKeys = append(d.cachedAdditionalKeys, key)
-
-	srv, _, err := d.getClient().Server.Create(context.Background(), srvopts)
-	if err != nil {
-		return errors.Wrap(err, "could not create server")
-	}
+	return volumes, nil
+}
 
-	log.Infof(" -> Creating server %s[%d] in %s[%d]", srv.Server.Name, srv.Server.ID, srv.Action.Command, srv.Action.ID)
-	if err = d.waitForAction(srv.Action); err != nil {
-		return errors.Wrap(err, "could not wait for action")
-	}
+func (d *Driver) createRemoteKeys() error {
+	if d.KeyID == 0 {
+		log.Infof("Creating SSH key...")
 
-	d.ServerID = srv.Server.ID
-	log.Infof(" -> Server %s[%d]: Waiting to come up...", srv.Server.Name, srv.Server.ID)
+		buf, err := ioutil.ReadFile(d.GetSSHKeyPath() + ".pub")
+		if err != nil {
+			return errors.Wrap(err, "could not read ssh public key")
+		}
 
-	for {
-		srvstate, err := d.GetState()
+		key, err := d.getRemoteKeyWithSameFingerprint(buf)
 		if err != nil {
-			return errors.Wrap(err, "could not get state")
+			return errors.Wrap(err, "error retrieving potentially existing key")
 		}
+		if key == nil {
+			log.Infof("SSH key not found in Hetzner. Uploading...")
 
-		if srvstate == state.Running {
-			break
+			key, err = d.makeKey(d.GetMachineName(), string(buf))
+			if err != nil {
+				return err
+			}
+		} else {
+			d.IsExistingKey = true
+			log.Debugf("SSH key found in Hetzner. ID: %d", key.ID)
 		}
 
-		time.Sleep(1 * time.Second)
+		d.KeyID = key.ID
 	}
+	for i, pubkey := range d.additionalKeys {
+		key, err := d.getRemoteKeyWithSameFingerprint([]byte(pubkey))
+		if err != nil {
+			return errors.Wrapf(err, "error checking for existing key for %v", pubkey)
+		}
+		if key == nil {
+			log.Infof("Creating new key for %v...", pubkey)
+			key, err = d.makeKey(fmt.Sprintf("%v-additional-%d", d.GetMachineName(), i), pubkey)
 
-	if d.UsePrivateNetwork {
-		for {
-			// we need to wait until network is attached
-			log.Infof("Wait until private network attached ...")
-			server, _, err := d.getClient().Server.GetByID(context.Background(), srv.Server.ID)
 			if err != nil {
-				return errors.Wrapf(err, "could not get newly created server [%d]", srv.Server.ID)
-			}
-			if server.PrivateNet != nil {
-				d.IPAddress = server.PrivateNet[0].IP.String()
-				break
+				return errors.Wrapf(err, "error creating new key for %v", pubkey)
 			}
-			time.Sleep(1 * time.Second)
+
+			log.Infof(" -> Created %v", key.ID)
+			d.AdditionalKeyIDs = append(d.AdditionalKeyIDs, key.ID)
+		} else {
+			log.Infof("Using existing key (%v) %v", key.ID, key.Name)
 		}
-	} else {
-		log.Infof("Using public network ...")
-		d.IPAddress = srv.Server.PublicNet.IPv4.IP.String()
-	}
 
-	log.Infof(" -> Server %s[%d] ready. Ip %s", srv.Server.Name, srv.Server.ID, d.IPAddress)
-	// Successful creation, so no keys dangle anymore
-	d.danglingKeys = nil
+		d.cachedAdditionalKeys = append(d.cachedAdditionalKeys, key)
+	}
+	return nil
+}
 
+func (d *Driver) prepareLocalKey() error {
+	if d.originalKey != "" {
+		log.Debugf("Copying SSH key...")
+		if err := d.copySSHKeyPair(d.originalKey); err != nil {
+			return errors.Wrap(err, "could not copy ssh key pair")
+		}
+	} else {
+		log.Debugf("Generating SSH key...")
+		if err := mcnssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
+			return errors.Wrap(err, "could not generate ssh key")
+		}
+	}
 	return nil
 }
 
@@ -471,10 +542,12 @@ func (d *Driver) destroyDanglingKeys() {
 	}
 }
 
+// GetSSHHostname retrieves the SSH host to connect to the machine; see [drivers.Driver.GetSSHHostname]
 func (d *Driver) GetSSHHostname() (string, error) {
 	return d.GetIP()
 }
 
+// GetURL retrieves the URL of the docker daemon on the machine; see [drivers.Driver.GetURL]
 func (d *Driver) GetURL() (string, error) {
 	if err := drivers.MustBeRunning(d); err != nil {
 		return "", errors.Wrap(err, "could not execute drivers.MustBeRunning")
@@ -488,6 +561,7 @@ func (d *Driver) GetURL() (string, error) {
 	return fmt.Sprintf("tcp://%s", net.JoinHostPort(ip, "2376")), nil
 }
 
+// GetState retrieves the state the machine is currently in; see [drivers.Driver.GetState]
 func (d *Driver) GetState() (state.State, error) {
 	srv, _, err := d.getClient().Server.GetByID(context.Background(), d.ServerID)
 	if err != nil {
@@ -508,6 +582,7 @@ func (d *Driver) GetState() (state.State, error) {
 	return state.None, nil
 }
 
+// Remove deletes the hetzner server and additional resources created during creation; see [drivers.Driver.Remove]
 func (d *Driver) Remove() error {
 	if d.ServerID != 0 {
 		srv, err := d.getServerHandle()
@@ -562,6 +637,7 @@ func (d *Driver) Remove() error {
 	return nil
 }
 
+// Restart instructs the hetzner cloud server to reboot; see [drivers.Driver.Restart]
 func (d *Driver) Restart() error {
 	srv, err := d.getServerHandle()
 	if err != nil {
@@ -581,6 +657,7 @@ func (d *Driver) Restart() error {
 	return d.waitForAction(act)
 }
 
+// Start instructs the hetzner cloud server to power up; see [drivers.Driver.Start]
 func (d *Driver) Start() error {
 	srv, err := d.getServerHandle()
 	if err != nil {
@@ -600,6 +677,7 @@ func (d *Driver) Start() error {
 	return d.waitForAction(act)
 }
 
+// Stop instructs the hetzner cloud server to shut down; see [drivers.Driver.Stop]
 func (d *Driver) Stop() error {
 	srv, err := d.getServerHandle()
 	if err != nil {
@@ -619,6 +697,7 @@ func (d *Driver) Stop() error {
 	return d.waitForAction(act)
 }
 
+// Kill forcefully shuts down the hetzner cloud server; see [drivers.Driver.Kill]
 func (d *Driver) Kill() error {
 	srv, err := d.getServerHandle()
 	if err != nil {
@@ -721,19 +800,19 @@ func (d *Driver) getKey() (*hcloud.SSHKey, error) {
 	return stype, nil
 }
 
-func (d *Driver) getRemoteKeyWithSameFingerprint(pubkey_byte []byte) (*hcloud.SSHKey, error) {
-	pubkey, _, _, _, err := ssh.ParseAuthorizedKey(pubkey_byte)
+func (d *Driver) getRemoteKeyWithSameFingerprint(publicKeyBytes []byte) (*hcloud.SSHKey, error) {
+	publicKey, _, _, _, err := ssh.ParseAuthorizedKey(publicKeyBytes)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not parse ssh public key")
 	}
 
-	fp := ssh.FingerprintLegacyMD5(pubkey)
+	fp := ssh.FingerprintLegacyMD5(publicKey)
 
-	remotekey, _, err := d.getClient().SSHKey.GetByFingerprint(context.Background(), fp)
+	remoteKey, _, err := d.getClient().SSHKey.GetByFingerprint(context.Background(), fp)
 	if err != nil {
-		return remotekey, errors.Wrap(err, "could not get sshkey by fingerprint")
+		return remoteKey, errors.Wrap(err, "could not get sshkey by fingerprint")
 	}
-	return remotekey, nil
+	return remoteKey, nil
 }
 
 func (d *Driver) getServerHandle() (*hcloud.Server, error) {