installer: welcome accepts both form data and json input
diff --git a/core/installer/welcome/main.go b/core/installer/welcome/main.go
index c3279d8..03a4047 100644
--- a/core/installer/welcome/main.go
+++ b/core/installer/welcome/main.go
@@ -6,6 +6,7 @@
 	"fmt"
 	"log"
 	"net/http"
+	"net/url"
 
 	"github.com/labstack/echo/v4"
 
@@ -49,10 +50,39 @@
 	SecretToken   string `json:"secretToken,omitempty"`
 }
 
+func getFormValue(v url.Values, name string) (string, error) {
+	items, ok := v[name]
+	if !ok || len(items) != 1 {
+		return "", fmt.Errorf("%s not found", name)
+	}
+	return items[0], nil
+}
+
 func (s *Server) createAdminAccount(c echo.Context) error {
 	var req createAdminAccountReq
-	if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil {
-		return err
+	if err := func() error {
+		var err error
+		f, err := c.FormParams()
+		if err != nil {
+			return err
+		}
+		if req.Username, err = getFormValue(f, "username"); err != nil {
+			return err
+		}
+		if req.Password, err = getFormValue(f, "password"); err != nil {
+			return err
+		}
+		if req.GandiAPIToken, err = getFormValue(f, "gandi-api-token"); err != nil {
+			return err
+		}
+		if req.SecretToken, err = getFormValue(f, "secret-token"); err != nil {
+			return err
+		}
+		return nil
+	}(); err != nil {
+		if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil {
+			return err
+		}
 	}
 	// TODO(giolekva): accounts-ui create user req
 	{