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

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. 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 follows this priority order:

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 stores the resolved path and creates the folder:

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 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:

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 to generate the snapshot.

To perform a backup using curl:

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:

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 processes multipart uploads and delegates to TransferReader::read_then_import() in src/transfer/reader.rs:

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:

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:

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 and 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 and 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →