bennetimo/ghost-backup

Issue with json backups

Closed this issue · 1 comments

When I'm trying to use the JSON backup feature I am receiving this error:

docker exec backup backup -D -F -P
Wed Oct 23 19:00:38 UTC 2019: Checking if a mysql container exists on the network at mysql:3306
Wed Oct 23 19:00:38 UTC 2019:  ...no mysql container exists on the network. Using sqlite mode
Wed Oct 23 19:00:38 UTC 2019: -D set: excluding db archive in backup
Wed Oct 23 19:00:38 UTC 2019: -F set: excluding ghost files archive in backup
Wed Oct 23 19:00:38 UTC 2019: -p set: not purging old backups (limit is set to 1000)
Wed Oct 23 19:00:38 UTC 2019: creating backup: 20191023-1900...
Wed Oct 23 19:00:38 UTC 2019: backing up ghost database
Wed Oct 23 19:00:38 UTC 2019:  ...skipped
Wed Oct 23 19:00:38 UTC 2019: backing up ghost content files
Wed Oct 23 19:00:38 UTC 2019:  ...skipped
Wed Oct 23 19:00:38 UTC 2019: backing up ghost json file
Wed Oct 23 19:00:38 UTC 2019:  ...checking if a ghost container exists on the network at my-ghost-url:443
Wed Oct 23 19:00:38 UTC 2019:  ...found ghost service on the network
Wed Oct 23 19:00:38 UTC 2019:  ...retrieving client secret for client: ghost-backup
Wed Oct 23 19:00:38 UTC 2019:  ...retrieved client secret: 12345 for client slug: ghost-backup
parse error: Invalid numeric literal at EOF at line 1, column 3

Any idea why this would happen?

Docker-compose looks like this

    blog:
      image: ghost:alpine
      container_name: blog
      restart: always
      ports:
        - 2368:2368
      volumes:
        - './blog/content:/var/lib/ghost/content'
      environment:
        mail__transport: "SMTP"
        mail__options__service: "Mailgun"
        mail__options__auth__user: ${MAILGUN_USER}
        mail__options__auth__pass: ${MAILGUN_PASS}
        url: 'https://my-url.com'
      labels:
        - "traefik.enable=true"
        - "traefik.basic.frontend.rule=Host:blog.${website}"
        - "traefik.basic.port=2368"
        - "traefik.basic.protocol=http"
      networks:
        - http_network

    backup:
      image: bennetimo/ghost-backup:1.25
      container_name: backup
      restart: always
      volumes:
        - './blog/content:/var/lib/ghost/content'
        - '/mnt/google-drive/blog/backups:/backups'
        - './backuplogs:/backuplogs'
      environment:
        - "BACKUP_LOCATION=/backups"
        - "BACKUP_TIME=0 2 * * *"
        - "BACKUPS_RETAIN_LIMIT=1000"
        - "GHOST_SERVICE_NAME=blog.my-url.com"
        - "GHOST_SERVICE_PORT=443"
        - "GHOST_SERVICE_USER_EMAIL=my.email%40gmail.com"
        - "GHOST_SERVICE_WORKER_PASSWORD=12345&8731"
        - "LOG_LOCATION=/backuplogs/ghost-backup.log"
        - "BACKUP_FILE_PREFIX=myblog"

Hi @Poltergeisen, sorry for the really slow response! Looks like the error is thrown when trying to retrieve the client bearer token from your ghost db. This could be a permissions issue perhaps, but hard to know without some more debugging. For whatever reason when trying to retrieve the token an invalid response is coming back, which is then causing jq to throw the error you see: parse error: Invalid numeric literal at EOF at line 1, column 3, as the response does not contain the .access_token that it is expecting.

To debug why you could try to:

  1. Open a shell inside your ghost-backup container when it is running:
    docker exec -it backup /bin/bash
  2. Manually set the CLIENT_SECRET, using the value from your logs
    CLIENT_SECRET=12345
  3. Manually try to retrieve the bearer token, using:
curl -s \
    -H "Accept: application/json" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -X POST -d "grant_type=password&username=$GHOST_SERVICE_USER_EMAIL&password=$GHOST_SERVICE_USER_PASSWORD&client_id=$CLIENT_SLUG&client_secret=$CLIENT_SECRET" \
    $GHOST_SERVICE_NAME:$GHOST_SERVICE_PORT/ghost/api/v0.1/authentication/token

You should be able to use that curl as is, as all the other vars should already be set in the container if you have set everything up correctly.

The response should look something like:

{
  "access_token": "xxx",
  "refresh_token": "xxx",
  "expires_in": 2628000,
  "token_type": "Bearer"
}

If it is different (i.e. doesn't have the access_token field) then the next step will fail, which is what you're seeing. But it should be much more obvious then what the cause is. e.g. if there is an authentication issue, you would see something like this instead:

{
  "errors": [
    {
      "message": "Access denied.",
      "context": "Client credentials were not valid",
      "errorType": "UnauthorizedError"
    }
  ]
}

Hope that helps (if this is still relevant to you anyway! ;))