# r-Nacos Data Directory Structure: Complete Backup and Restore Guide

> Explore the r-nacos data directory structure and master backup and restore procedures. Learn to protect your Nacos data with our complete guide.

- Repository: [Nacos Group/r-nacos](https://github.com/nacos-group/r-nacos)
- Tags: how-to-guide
- Published: 2026-03-07

---

**r-Nacos stores all persistent state in a single directory (defaulting to `~/.local/share/r-nacos/nacos_db` on Linux/macOS or `nacos_db` on Windows) that you can back up via a built-in HTTP API or offline filesystem copy, and restore using the import endpoint or by replacing the directory contents.**

r-Nacos is a Rust implementation of the Nacos configuration and service discovery platform. Understanding the **r-Nacos data directory structure** is essential for operations teams who need to ensure data durability and perform disaster recovery. This guide explains how the embedded **sled** database organizes files on disk and provides step-by-step instructions for both online API-based and offline filesystem backup strategies.

## Locating the r-Nacos Data Directory

r-Nacos resolves its storage path at startup using the `get_data_dir()` helper in [`src/common/mod.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/common/mod.rs). The function checks environment variables first, then falls back to platform-specific defaults.

### Default Paths by Platform

- **Linux/macOS**: `~/.local/share/r-nacos/nacos_db`
- **Windows/Docker**: `nacos_db` (relative to the process working directory)

### Overriding with Environment Variables

You can override the default location by setting the **`RNACOS_DATA_DIR`** environment variable. For backward compatibility, the legacy **`RNACOS_CONFIG_DB_DIR`** variable is also supported.

The resolution logic in [`src/common/mod.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/common/mod.rs) follows this priority order:

```rust
fn get_data_dir(run_in_docker: bool) -> String {
    if let Ok(v) = std::env::var("RNACOS_DATA_DIR") {
        v
    } else if let Ok(v) = std::env::var("RNACOS_CONFIG_DB_DIR") {
        v
    } else if run_in_docker {
        DEFAULT_DB_PATH.to_owned()  // "nacos_db"
    } else {
        #[cfg(any(target_os = "linux", target_os = "macos"))] {
            if let Some(mut home) = dirs::home_dir() {
                home.push(".local/share/r-nacos/nacos_db");
                return home.to_string_lossy().to_string();
            }
        }
        DEFAULT_DB_PATH.to_owned()
    }
}

```

When the application starts, `AppSysConfig::init_from_env()` in [`src/starter.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/starter.rs) stores the resolved path and creates the folder:

```rust
std::fs::create_dir_all(sys_config.local_db_dir.as_str())?;

```

### Internal Directory Layout

Inside the data directory, r-Nacos creates subdirectories for each **sled** database table. The layout typically includes:

```

nacos_db/
├── config/       # Configuration data

├── naming/       # Service naming data

├── namespace/    # Namespace definitions

├── user/         # User and permission data

├── cache/        # Cached entries

└── mcp/          # MCP service data

```

Each subdirectory contains sled-specific files (such as `config.tree` and `naming.tree`) that represent the persistent key-value store.

## Backing Up r-Nacos Data

r-Nacos supports two backup methods: a hot backup via HTTP API that captures a consistent snapshot while the service runs, and a cold backup via filesystem tools that requires stopping the process.

### Configuring the Backup Token

Before using the HTTP API, you must define the **`RNACOS_BACKUP_TOKEN`** environment variable with at least 32 characters. If this token is empty or unset, the backup endpoint returns an error. The token validation logic resides in [`src/common/mod.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/common/mod.rs) within the `AppSysConfig` struct.

### HTTP Backup API

The built-in backup endpoint streams a binary `.data` snapshot containing every sled table. The handler is implemented in [`src/openapi/backup.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/openapi/backup.rs):

```rust
pub async fn backup(app_share_data: web::Data<Arc<AppShareData>>,
                    web::Query(params): web::Query<BackupParam>) -> impl Responder {
    if app_share_data.sys_config.backup_token.is_empty() {
        HttpResponse::InternalServerError().body("backup api is not open")
    } else if params.token.as_str() != app_share_data.sys_config.backup_token.as_str() {
        HttpResponse::InternalServerError().body("backup token is not matched")
    } else {
        download_transfer_file(app_share_data).await
    }
}

```

The `download_transfer_file` function delegates to `do_backup` in [`src/transfer/writer.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/transfer/writer.rs) to generate the snapshot.

To perform a backup using curl:

```bash
export RNACOS_BACKUP_TOKEN=1234567890abcdef1234567890abcdef

curl -G "http://127.0.0.1:8848/rnacos/backup" \
     --data-urlencode "token=${RNACOS_BACKUP_TOKEN}" \
     -o rnacos_backup_$(date +%F).data

```

### Offline Filesystem Backup

For a point-in-time copy without the API, stop the r-Nacos process and archive the data directory:

```bash
systemctl stop r-nacos

tar czf rnacos_data_$(date +%F).tar.gz ${RNACOS_DATA_DIR:-~/.local/share/r-nacos/nacos_db}

systemctl start r-nacos

```

## Restoring r-Nacos Data

Restore operations can replay a snapshot into a running instance via the import API, or replace the raw sled files while the service is stopped.

### Online Restore via Import API

The import endpoint consumes the binary format produced by the backup API. The handler in [`src/console/transfer_api.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/console/transfer_api.rs) processes multipart uploads and delegates to `TransferReader::read_then_import()` in [`src/transfer/reader.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/transfer/reader.rs):

```rust
pub async fn import_transfer_file(
    req: HttpRequest,
    payload: Multipart,
    data: web::Data<Arc<AppShareData>>,
) -> impl Responder {
    // ... read multipart body into a byte vec
    // TransferImportManager calls TransferReader::read_then_import(...)
}

```

Optional headers control which data categories are applied:

- `import-config`: Restore configuration data
- `import-user`: Restore user and permission data
- `import-cache`: Restore cache entries

To restore a backup:

```bash
curl -X POST "http://127.0.0.1:8848/rnacos/transfer/import" \
     -F "file=@rnacos_backup_2023-11-01.data" \
     -H "import-config: true" \
     -H "import-user: true"

```

After a successful import, restart the service to allow Raft to reload the state.

### Offline Restore from Filesystem

To restore from a tarball without using the API:

```bash
systemctl stop r-nacos

tar xzf rnacos_backup_2023-11-01.tar.gz -C ${RNACOS_DATA_DIR:-~/.local/share/r-nacos}

systemctl start r-nacos

```

## Summary

- **r-Nacos** stores all state in a single directory controlled by `RNACOS_DATA_DIR`, defaulting to `~/.local/share/r-nacos/nacos_db` on Unix systems.
- The **HTTP backup API** at `/rnacos/backup` requires a 32-character `RNACOS_BACKUP_TOKEN` and streams a binary snapshot managed by [`src/openapi/backup.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/openapi/backup.rs) and [`src/transfer/writer.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/transfer/writer.rs).
- The **import API** at `/rnacos/transfer/import` replays snapshots into a running instance using logic in [`src/console/transfer_api.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/console/transfer_api.rs) and [`src/transfer/reader.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/transfer/reader.rs).
- **Offline backups** require stopping the service and archiving the data directory, which contains **sled** database files organized into subdirectories for config, naming, namespace, user, cache, and mcp data.

## Frequently Asked Questions

### Where does r-Nacos store its database files?

By default, r-Nacos stores its embedded **sled** database in `~/.local/share/r-nacos/nacos_db` on Linux and macOS, or in a local `nacos_db` folder on Windows and Docker. You can override this path by setting the `RNACOS_DATA_DIR` environment variable before starting the service.

### Can I back up r-Nacos while it is running?

Yes. The **HTTP backup API** captures a consistent snapshot without downtime by streaming the sled database state through the `/rnacos/backup` endpoint. However, filesystem-level backups (simple directory copies) should only be performed while the service is stopped to avoid corrupting the sled files.

### What is the difference between the backup API and filesystem copy?

The **backup API** produces a portable `.data` snapshot that can be imported into any r-Nacos instance via the HTTP import endpoint, making it ideal for migrations and cloud storage. A **filesystem copy** creates an exact byte-level replica of the sled files, which is faster for local disaster recovery but requires identical paths and cannot be easily imported into a running instance.

### How do I migrate r-Nacos data to a new server?

Use the **HTTP backup and import workflow**. First, enable the backup token on the source server and download the snapshot using `curl`. Then start the target r-Nacos instance and POST the file to `/rnacos/transfer/import` with the appropriate headers (such as `import-config: true`). This replays the data into the new instance's sled store without manual file manipulation.