Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Apps | Demo | Docs | Install
  1. Cloudron Forum
  2. Support
  3. How to automate migrating/importing apps from Cloudron to Cloudron via API

How to automate migrating/importing apps from Cloudron to Cloudron via API

Scheduled Pinned Locked Moved Solved Support
import
12 Posts 5 Posters 2.9k Views 9 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • nebulonN nebulon

    If the goal is to move mostly everything, but only switch over one-by-one app, maybe you could restore the whole cloudron with dry-run option and then cut over DNS one-by-one? https://docs.cloudron.io/backups/#dry-run

    Otherwise, I guess writing a small script against the Cloudron API will come in handy.

    jdaviescoatesJ Offline
    jdaviescoatesJ Offline
    jdaviescoates
    wrote on last edited by
    #3

    @nebulon said in How to automate migrating/importing apps from Cloudron to Cloudron:

    maybe you could restore the whole cloudron with dry-run option and then cut over DNS one-by-one? https://docs.cloudron.io/backups/#dry-run

    But how could one restore onto a VPS with an already existing Cloudron with lots of other apps already there? 🤔

    I use Cloudron with Gandi & Hetzner

    robiR 1 Reply Last reply
    1
    • jdaviescoatesJ jdaviescoates

      @nebulon said in How to automate migrating/importing apps from Cloudron to Cloudron:

      maybe you could restore the whole cloudron with dry-run option and then cut over DNS one-by-one? https://docs.cloudron.io/backups/#dry-run

      But how could one restore onto a VPS with an already existing Cloudron with lots of other apps already there? 🤔

      robiR Offline
      robiR Offline
      robi
      wrote on last edited by
      #4

      @nebulon :
      @jdaviescoates is right.. Cloudron A needs preserving.

      Are you aware of anyone writing such a script?

      Conscious tech

      1 Reply Last reply
      1
      • jdaviescoatesJ Offline
        jdaviescoatesJ Offline
        jdaviescoates
        wrote on last edited by
        #5

        I will also nees to do this soon, so also interested...

        I use Cloudron with Gandi & Hetzner

        1 Reply Last reply
        1
        • fbartelsF Offline
          fbartelsF Offline
          fbartels
          App Dev
          wrote on last edited by
          #6

          Quite some time ago I did some exploration around the backup part of the Cloudron api in https://blog.9wd.eu/posts/cloudron-migration/. I could imagine looking into this. Are you offering a bounty?

          robiR 1 Reply Last reply
          3
          • fbartelsF fbartels

            Quite some time ago I did some exploration around the backup part of the Cloudron api in https://blog.9wd.eu/posts/cloudron-migration/. I could imagine looking into this. Are you offering a bounty?

            robiR Offline
            robiR Offline
            robi
            wrote on last edited by
            #7

            @fbartels Thanks for your thoughtful response Felix!

            This brings to mind another idea that Cloudron could have a 3rd party API plugin feature integration that would allow for such customizations just as Wordpress plugins do.

            For me this does clarify the idea that a tool/script should be run from the destination Cloudron A to pull an app from the App backups of Cloudron B.

            This would also allow for devs to share their pre-packaged Apps for testing and more (using group/domain visibility), similar to the Github fork feature, by sharing the backup configuration.

            The next bit would be to iterate that import process for a list of App IDs provided.

            If this were to be polished later as a plugin/feature, remote clone of an app across Cloudrons would be a few clicks away.

            Another external option would be to use N8N to automate the process in a more visual workflow.

            Conscious tech

            1 Reply Last reply
            2
            • robiR Offline
              robiR Offline
              robi
              wrote on last edited by
              #8

              @girish Looking at the Cloudron API docs, there doesn't seem to be an import path as there is in the UI.

              The Restore path doesn't seem to be the right thing to use as it expects a local backup id.

              How does the UI do the import via the API?

              Conscious tech

              1 Reply Last reply
              1
              • robiR Offline
                robiR Offline
                robi
                wrote on last edited by robi
                #9

                Here's a draft outline of running this from Cloudron A via N8N:

                Remote Cloudron B
                GET
                https://my.example.com/api/v1/apps
                https://my.example.com/api/v1/apps/{appid}
                use appStoreId, subdomain, domain
                https://my.example.com/api/v1/apps/{appid}/backups
                pick latest
                https://my.example.com/api/v1/backups
                https://my.example.com/api/v1/settings/backup_config
                merge backup config with app backup config??

                Local Cloudron A
                POST
                https://my.example.com/api/v1/apps/install
                use appStoreId, subdomain, domain; get id
                ??? import merged remote backup config
                https://my.example.com/api/v1/apps/{appid}/restore
                use payload from remote app backup config???

                What would the import calls looks like? @girish

                Conscious tech

                1 Reply Last reply
                1
                • R Offline
                  R Offline
                  roofboard
                  wrote on last edited by roofboard
                  #10

                  Here is the start of an N8N workflow.
                  Copy and paste all the JSON into your N8N instance it will detect the JSON and nodes.
                  We are using query auth here because we do not know how to do the Bearer Token.

                  And we are having trouble figuring out how to tell the destination cloudron to pull a backup from a remote location.

                  {
                    "meta": {
                      "instanceId": "8d8e1b7ceae09105ea1231dc6c31045b9d36dc713f8e22970f6eacf9f1f4d996"
                    },
                    "nodes": [
                      {
                        "parameters": {},
                        "id": "4be687c9-4a4b-4be3-a8fc-d1405a66fa95",
                        "name": "When clicking \"Execute Workflow\"",
                        "type": "n8n-nodes-base.manualTrigger",
                        "typeVersion": 1,
                        "position": [
                          680,
                          320
                        ]
                      },
                      {
                        "parameters": {
                          "url": "https://my.demo.cloudron.io/api/v1/apps",
                          "authentication": "genericCredentialType",
                          "genericAuthType": "httpQueryAuth",
                          "options": {}
                        },
                        "id": "33c66a41-753b-491a-bf03-8683f86b95c5",
                        "name": "PullAppsFromSource",
                        "type": "n8n-nodes-base.httpRequest",
                        "typeVersion": 4.1,
                        "position": [
                          900,
                          320
                        ],
                        "credentials": {
                          "httpHeaderAuth": {
                            "id": "11",
                            "name": "RobCloudron-Demo"
                          },
                          "httpQueryAuth": {
                            "id": "12",
                            "name": "Query Auth account"
                          }
                        }
                      },
                      {
                        "parameters": {
                          "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
                        },
                        "id": "a1d203d0-4d01-421a-9d88-7299f8f515ce",
                        "name": "ManipulateResponse",
                        "type": "n8n-nodes-base.code",
                        "typeVersion": 1,
                        "position": [
                          1120,
                          320
                        ]
                      },
                      {
                        "parameters": {
                          "url": "=https://my.demo.cloudron.io/api/v1/apps/{{ $json.apps[0].id }}/backups",
                          "authentication": "genericCredentialType",
                          "genericAuthType": "httpQueryAuth",
                          "options": {}
                        },
                        "id": "9c925efa-458f-4599-8172-7d9fafc3ce23",
                        "name": "PullBackupsFromSource",
                        "type": "n8n-nodes-base.httpRequest",
                        "typeVersion": 4.1,
                        "position": [
                          1320,
                          320
                        ],
                        "credentials": {
                          "httpHeaderAuth": {
                            "id": "11",
                            "name": "RobCloudron-Demo"
                          },
                          "httpQueryAuth": {
                            "id": "12",
                            "name": "Query Auth account"
                          }
                        }
                      }
                    ],
                    "connections": {
                      "When clicking \"Execute Workflow\"": {
                        "main": [
                          [
                            {
                              "node": "PullAppsFromSource",
                              "type": "main",
                              "index": 0
                            }
                          ]
                        ]
                      },
                      "PullAppsFromSource": {
                        "main": [
                          [
                            {
                              "node": "ManipulateResponse",
                              "type": "main",
                              "index": 0
                            }
                          ]
                        ]
                      },
                      "ManipulateResponse": {
                        "main": [
                          [
                            {
                              "node": "PullBackupsFromSource",
                              "type": "main",
                              "index": 0
                            }
                          ]
                        ]
                      }
                    }
                  }
                  
                  robiR 1 Reply Last reply
                  2
                  • R roofboard

                    Here is the start of an N8N workflow.
                    Copy and paste all the JSON into your N8N instance it will detect the JSON and nodes.
                    We are using query auth here because we do not know how to do the Bearer Token.

                    And we are having trouble figuring out how to tell the destination cloudron to pull a backup from a remote location.

                    {
                      "meta": {
                        "instanceId": "8d8e1b7ceae09105ea1231dc6c31045b9d36dc713f8e22970f6eacf9f1f4d996"
                      },
                      "nodes": [
                        {
                          "parameters": {},
                          "id": "4be687c9-4a4b-4be3-a8fc-d1405a66fa95",
                          "name": "When clicking \"Execute Workflow\"",
                          "type": "n8n-nodes-base.manualTrigger",
                          "typeVersion": 1,
                          "position": [
                            680,
                            320
                          ]
                        },
                        {
                          "parameters": {
                            "url": "https://my.demo.cloudron.io/api/v1/apps",
                            "authentication": "genericCredentialType",
                            "genericAuthType": "httpQueryAuth",
                            "options": {}
                          },
                          "id": "33c66a41-753b-491a-bf03-8683f86b95c5",
                          "name": "PullAppsFromSource",
                          "type": "n8n-nodes-base.httpRequest",
                          "typeVersion": 4.1,
                          "position": [
                            900,
                            320
                          ],
                          "credentials": {
                            "httpHeaderAuth": {
                              "id": "11",
                              "name": "RobCloudron-Demo"
                            },
                            "httpQueryAuth": {
                              "id": "12",
                              "name": "Query Auth account"
                            }
                          }
                        },
                        {
                          "parameters": {
                            "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
                          },
                          "id": "a1d203d0-4d01-421a-9d88-7299f8f515ce",
                          "name": "ManipulateResponse",
                          "type": "n8n-nodes-base.code",
                          "typeVersion": 1,
                          "position": [
                            1120,
                            320
                          ]
                        },
                        {
                          "parameters": {
                            "url": "=https://my.demo.cloudron.io/api/v1/apps/{{ $json.apps[0].id }}/backups",
                            "authentication": "genericCredentialType",
                            "genericAuthType": "httpQueryAuth",
                            "options": {}
                          },
                          "id": "9c925efa-458f-4599-8172-7d9fafc3ce23",
                          "name": "PullBackupsFromSource",
                          "type": "n8n-nodes-base.httpRequest",
                          "typeVersion": 4.1,
                          "position": [
                            1320,
                            320
                          ],
                          "credentials": {
                            "httpHeaderAuth": {
                              "id": "11",
                              "name": "RobCloudron-Demo"
                            },
                            "httpQueryAuth": {
                              "id": "12",
                              "name": "Query Auth account"
                            }
                          }
                        }
                      ],
                      "connections": {
                        "When clicking \"Execute Workflow\"": {
                          "main": [
                            [
                              {
                                "node": "PullAppsFromSource",
                                "type": "main",
                                "index": 0
                              }
                            ]
                          ]
                        },
                        "PullAppsFromSource": {
                          "main": [
                            [
                              {
                                "node": "ManipulateResponse",
                                "type": "main",
                                "index": 0
                              }
                            ]
                          ]
                        },
                        "ManipulateResponse": {
                          "main": [
                            [
                              {
                                "node": "PullBackupsFromSource",
                                "type": "main",
                                "index": 0
                              }
                            ]
                          ]
                        }
                      }
                    }
                    
                    robiR Offline
                    robiR Offline
                    robi
                    wrote on last edited by robi
                    #11

                    @roofboard There's an example of how to use a bearer token here: https://forum.cloudron.io/post/65043

                    Looks like this in N8N for single use:
                    05b953ab-3962-44e9-815d-69d7fa842c10-image.png

                    To reuse it in all nodes, this should work:
                    https://community.n8n.io/t/how-to-authorize-using-bearer-token/25674

                    Conscious tech

                    1 Reply Last reply
                    0
                    • robiR robi referenced this topic on
                    • robiR robi marked this topic as a question on
                    • robiR robi referenced this topic on
                    • robiR robi referenced this topic on
                    • robiR robi referenced this topic on
                    • robiR robi referenced this topic on
                    • robiR robi referenced this topic on
                    • jamesJ james has marked this topic as solved on
                    • robiR Offline
                      robiR Offline
                      robi
                      wrote last edited by
                      #12

                      @girish Is this use case covered in Cloudron 9?

                      Conscious tech

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Bookmarks
                      • Search