# Back up and restore (/operate/backup-and-restore)



This page shows how to back up the store of a KubeMQ server running in Docker and restore it in place. The store holds your messages, accounts, license records and the installation's identity. When you finish, you have an archive, and a restored server shows the same license and messages.

This page covers one Docker server. Kubernetes has no supported backup procedure yet. Scaling a cluster to zero to copy its volumes does not work: the operator never applies a changed server count. [Contact support](mailto:support@kubemq.io) before relying on a restore.

These commands are for bash on macOS and Linux. On Windows, run them in WSL (Windows Subsystem for Linux), or use the kmq tab of [Try KubeMQ](/deploy/quickstart), which runs natively on Windows.





## Before you start [#before-you-start]

* A KubeMQ server running in Docker as container `kubemq` on volume `kubemq-data`, as [Try KubeMQ](/deploy/quickstart), [Install with kmq](/deploy/install/kmq) and [Install with Docker](/deploy/install/docker) start it.
* kmq, installed as in [Try KubeMQ](/deploy/quickstart#install-kmq), for `kmq license` only.
* A short outage: the server stops while its store is archived, because a running store cannot be copied consistently.
* Free disk space at least the size of the store.

With Podman: run every command with `podman` in place of `docker`.

Create a private folder for the archive and work inside it:

```bash title="Terminal"
mkdir -p -m 700 kubemq-private
```

```bash title="Terminal"
cd kubemq-private
```

## Steps [#steps]

Steps 1 to 4 back up the store. Steps 5 to 10 restore it and prove your messages came back. A public Debian container does the archiving, because the KubeMQ image has no archive tools. It keeps each file's owner, user 1001.

<Steps>
  <Step>
    ### Send a check message [#send-a-check-message]

    Put one message on a new `backup-check` queue. Step 10 receives it after the restore.

    ```bash title="Terminal"
    curl -s -X POST http://localhost:9090/queue/send \
      -H "Content-Type: application/json" \
      -d '{"Channel":"backup-check","ClientID":"backup-check","BodyString":"backup-check"}'
    ```



    You should see:

    ```text title="Output"
    {"is_error":false,"message":"OK","data":{"MessageID":"…","SentAt":…}}
    ```
  </Step>

  <Step>
    ### Stop the server [#stop-the-server]

    ```bash title="Terminal"
    docker stop kubemq
    ```

    You should see:

    ```text title="Output"
    kubemq
    ```
  </Step>

  <Step>
    ### Archive the volume [#archive-the-volume]

    ```bash title="Terminal"
    docker run --rm -v kubemq-data:/data:ro -v "$(pwd)":/backup \
      docker.io/library/debian:stable-slim \
      sh -c 'tar --numeric-owner -cpf /backup/kubemq-store.tar -C /data . && tar -tf /backup/kubemq-store.tar | head -n 1'
    ```

    The output is the first entry of the new `kubemq-store.tar`. You should see:

    ```text title="Output"
    ./
    ```

    On a Linux host with SELinux enforcing, add `:z` to the `$(pwd)` mount: `-v "$(pwd)":/backup:z`.

    Keep the archive private and encrypted, with a copy away from this machine. It holds the installation's identity and license records.
  </Step>

  <Step>
    ### Start the server again [#start-the-server-again]

    ```bash title="Terminal"
    docker start kubemq
    ```

    You should see:

    ```text title="Output"
    kubemq
    ```
  </Step>

  <Step>
    ### Stop the server before the restore [#stop-the-server-before-the-restore]

    The restore reuses the same container and volume. Nothing is recreated, so the installation keeps its identity.

    ```bash title="Terminal"
    docker stop kubemq
    ```

    You should see:

    ```text title="Output"
    kubemq
    ```
  </Step>

  <Step>
    ### Keep a safety archive [#keep-a-safety-archive]

    Archive the store you are about to replace. If the restore goes wrong, repeat the next step with `kubemq-store-before-restore.tar` to put it back.

    ```bash title="Terminal"
    docker run --rm -v kubemq-data:/data:ro -v "$(pwd)":/backup \
      docker.io/library/debian:stable-slim \
      sh -c 'tar --numeric-owner -cpf /backup/kubemq-store-before-restore.tar -C /data . && tar -tf /backup/kubemq-store-before-restore.tar | head -n 1'
    ```

    You should see:

    ```text title="Output"
    ./
    ```
  </Step>

  <Step>
    ### Replace the store with the backup [#replace-the-store-with-the-backup]

    <Callout type="warn" title="Data loss: this step deletes the current store">
      **Data loss:** this command deletes everything in `kubemq-data` before it unpacks the archive. Run it only after the safety archive succeeded. Never run two servers from copies of the same store: they share one installation identity.
    </Callout>

    ```bash title="Terminal"
    docker run --rm -v kubemq-data:/data -v "$(pwd)":/backup:ro \
      docker.io/library/debian:stable-slim \
      sh -c 'find /data -mindepth 1 -delete && tar --numeric-owner -xpf /backup/kubemq-store.tar -C /data && echo restored'
    ```

    You should see:

    ```text title="Output"
    restored
    ```
  </Step>

  <Step>
    ### Start the server and wait until it is ready [#start-the-server-and-wait-until-it-is-ready]

    ```bash title="Terminal"
    docker start kubemq && for i in $(seq 60); do curl -fs -o /dev/null http://localhost:8080/ready && echo ready && break; sleep 2; done
    ```

    You should see:

    ```text title="Output"
    kubemq
    ready
    ```
  </Step>

  <Step>
    ### Check the license [#check-the-license]

    ```bash title="Terminal"
    kmq license
    ```



    The license is the one the server had at backup time. You should see:

    ```text title="Output"
    SERVER  STATE   PLAN   SERVERS LICENSED  EXPIRES  DAYS LEFT  RUNS UNTIL  VERSION  CHECKED  PROBLEM
    kubemq  …
    ```
  </Step>

  <Step>
    ### Receive the check message [#receive-the-check-message]

    ```bash title="Terminal"
    curl -s -X POST http://localhost:9090/queue/receive \
      -H "Content-Type: application/json" \
      -d '{"Channel":"backup-check","ClientID":"backup-check","MaxNumberOfMessages":1,"WaitTimeSeconds":5}'
    ```



    The message from step 1 comes back, with its body base64-encoded. You should see:

    ```text title="Output"
    {"is_error":false,"message":"OK","data":{…,"Messages":[{"MessageID":"…","ClientID":"backup-check","Channel":"backup-check","Body":"YmFja3VwLWNoZWNr",…}],"MessagesReceived":1}}
    ```
  </Step>
</Steps>

## If something goes wrong [#if-something-goes-wrong]

* The server does not start, or never becomes ready: check `docker logs kubemq`.
* `kmq license` reports a problem: see [Troubleshooting](/licensing/troubleshooting).
* You cannot sign in to the dashboard: the restore brought back the accounts the store held when you archived it. See [Dashboard Access and Recovery](/operate/dashboard-access#reset-a-forgotten-password).

## Next steps [#next-steps]

* [Upgrade KubeMQ](/deploy/upgrade): back up first, then upgrade.
* [Production checklist](/deploy/production-checklist): what else a server you rely on needs.
