# Backup + Migration

<p class="callout warning">Not tested yet!</p>

> ❓ I installed BookStack via Docker (as in [the guide](https://wiki.fabula.vision/books/learn-to-learn/page/install-your-own-bookstack-instance)). Could you please explain how to create backups (full content backup) so that I can migrate the website if needed, e.g., to another server/domain? [Here](https://www.bookstackapp.com/docs/admin/backup-restore/) is BookStack’s official guide.

## Full BookStack backup (Docker) – so that a move to *another server/domain* works 🧰📦

For a **complete, restorable backup**, you essentially need **two components**:

1. **Database** (all pages, books, users, permissions, settings …)
2. **Files/config** (uploads, attachments, `.env`/APP\_KEY, possibly themes/modules)

Since you have the setup like in your guide (`/opt/bookstack` with `docker-compose.yml`, volumes `./mariadb` and `./bookstack`), this is pleasantly simple.

---

## ✅ What exactly needs to be backed up?

### 1) Database (MariaDB)

- The content is in the DB container, and in your setup it’s persisted under: 
    - `./mariadb` (as volume `./mariadb:/config`)
- **Cleanest approach**: *SQL dump* (portable, tolerant across versions)

### 2) Files (BookStack container volume)

- Persistent data is located under: 
    - `./bookstack` (as volume `./bookstack:/config`)
- In it, especially important: 
    - `.env` (including **APP\_KEY**!)
    - uploads/attachments
    - possibly `www/themes/custom/...` (your hacks/modules)

### 3) Compose/Caddy (helpful for migration)

- `docker-compose.yml`
- `Caddyfile`
- Caddy data optional: 
    - `./caddy/data` &amp; `./caddy/config` (certificates/state).  
        *Not strictly required*, but sometimes saves re-issuing/rate limits.

---

## 🗂️ Create a backup (recommended approach)

> Assumption: project is located in `/opt/bookstack` and the containers are named as in your YAML:  
> `bookstack-mariadb` and `bookstack`.

### Step 1: Create a backup folder

```bash
cd /opt/bookstack
mkdir -p backups

```

---

### Step 2: Dump the database as SQL 💾

```bash
docker exec -i bookstack-mariadb \
  mysqldump -u bookstack -pbookstack \
  --single-transaction --routines --triggers \
  bookstack > backups/bookstack-db-$(date +%F).sql

```

**Important:** Replace `-pbookstack` with your real password (from `MYSQL_PASSWORD`).

> Alternative (safer because the password won’t end up in shell history):  
> Omit `-p...`, then `mysqldump` will prompt interactively for the password:
> 
> ```bash
> docker exec -it bookstack-mariadb mysqldump -u bookstack -p --single-transaction --routines --triggers bookstack > backups/bookstack-db-$(date +%F).sql
> 
> ```

---

### Step 3: Archive files/volumes 📦

```bash
tar -czvf backups/bookstack-files-$(date +%F).tar.gz \
  docker-compose.yml Caddyfile \
  bookstack mariadb caddy

```

If you **don’t** want to back up **Caddy**, you can do it leaner:

```bash
tar -czvf backups/bookstack-files-$(date +%F).tar.gz \
  docker-compose.yml Caddyfile \
  bookstack mariadb

```

---

### Step 4: (Optional) Integrity check ✅

```bash
ls -lh backups/
head -n 5 backups/bookstack-db-*.sql
tar -tzf backups/bookstack-files-*.tar.gz | head

```

---

## 🔁 Restore (on a new server) – incl. domain/URL migration

### Step 0: Prerequisites

- Docker + Docker Compose installed
- DNS of the new domain points to the new server (for HTTPS via Caddy)

---

### Step 1: Copy the backup over

Pack on the **old** server or copy directly:

```bash
scp -r /opt/bookstack/backups user@new-server:/opt/bookstack/

```

---

### Step 2: Restore files (Compose/volumes) 📂

On the **new** server:

```bash
cd /opt/bookstack
tar -xvzf backups/bookstack-files-YYYY-MM-DD.tar.gz

```

*(Adjust the date, of course.)*

---

### Step 3: Start containers (DB should already be running) 🐳

```bash
cd /opt/bookstack
docker compose up -d mariadb

```

Wait a few seconds until MariaDB is ready.

---

### Step 4: Import the database 🧩

```bash
cat backups/bookstack-db-YYYY-MM-DD.sql | \
  docker exec -i bookstack-mariadb mysql -u bookstack -pbookstack bookstack

```

Again: adjust the password or use interactive mode.

---

### Step 5: Start BookStack

```bash
docker compose up -d

```

---

## 🌍 Domain/URL changed? (very important!)

If you move to a **different URL/domain**, you must:

### 1) Adjust `APP_URL` in the `.env`

In your volume, the `.env` is typically located at:

- `./bookstack/www/.env` *(common with linuxserver/bookstack)*
- or `./bookstack/.env` *(depending on image/setup)*

Find it like this:

```bash
find /opt/bookstack/bookstack -maxdepth 3 -name ".env" -print

```

Then set `APP_URL=`[`https://new-domain.tld`](https://new-domain.tld).

> **Pay attention:** The `APP_KEY` **must remain the old one** (otherwise encrypted data will break, e.g., MFA secrets).

### 2) BookStack command: “Update System URL”

So that content/links in the DB are rewritten cleanly:

```bash
docker exec -it bookstack php /app/www/artisan bookstack:update-url https://old-domain.tld https://new-domain.tld

```

*(If the path in the container is different, this often also works:* `php artisan ...` *from* `/app/www`*.)*

---

## 🧠 Practical notes (so it’s truly “migration-safe”)

- Always store **backups offsite** (another system/storage).
- **Database dump + file archive** is the most portable.
- If you restore to a **newer BookStack version**:
    
    
    1. Restore DB
    2. Bring containers up
    3. Then run migrations (if needed):
        
        ```bash
        docker exec -it bookstack php /app/www/artisan migrate --force
        
        ```

---

## If you want: I’ll make you a “one-command backup script” 🧾

Just tell me briefly:

- Is your `.env` located at `bookstack/www/.env`?
- What are your containers actually named (`docker ps` output)?
- Do you want to back up Caddy certificates or preferably not?

Then I’ll give you a small script including rotation (e.g., “keep the last 7 backups”) and optional upload to S3/Hetzner Storage Box.