This guide covers backup, restore, and database migration operations for Aviary.
Aviary provides comprehensive data management capabilities through its built-in export/import system. This system can handle:
- Complete system backups: Database + user files + configurations
- Selective exports: Specific users or data types
- Database migrations: SQLite ↔ PostgreSQL
- Disaster recovery: Full system restoration
This system is included for ease of use and to aide in cross-database migrations. You can also backup the system yourself outside of Aviary by:
- Backing up the database (SQLite or Postgres)
- Backing up the storage directory
Admin Interface:
- Log in as an admin user
- Navigate to Admin Panel → System Settings
- Click "Backup & Restore"
- Click "Create Backup"
- Monitor job progress in "Recent Backups" section
- Download completed backups when ready
Each backup includes metadata with:
- Aviary version and git commit
- Export timestamp
- Database type (SQLite/PostgreSQL)
- Users included in export
- Total document count and file sizes
- Exported database tables
Aviary backups are compressed tar.gz archives with a standardized internal structure. Understanding this structure can help with troubleshooting and manual data recovery if needed.
Warning
These backups contain sensitive information, such as usernames, hashed passwords, email addresses, users' reMarkable folder structure cache, and the device pairing file needed to interact with their cloud accounts. They should be treated accordingly.
backup-filename.tar.gz
├── metadata.json # Export metadata and compatibility info
├── database/ # Database exports (JSON format)
│ ├── users.json # User accounts, settings, and rmapi configs
│ ├── api_keys.json # API keys and permissions
│ ├── user_sessions.json # Active user sessions
│ ├── documents.json # Document metadata and references
│ ├── system_settings.json # System-wide configuration
│ ├── login_attempts.json # Authentication logs
│ └── user_folders_cache.json # Cached folder structures
└── filesystem/ # User files and configurations
└── documents/ # User-uploaded documents
└── {user-id}/ # Per-user document storage
├── document1.pdf
├── subfolder/
└── document2.pdf
metadata.json Contains export information and compatibility data:
{
"aviary_version": "1.0.0",
"git_commit": "abc123def",
"export_timestamp": "2024-01-15T10:30:00Z",
"database_type": "sqlite",
"users_exported": ["user-uuid-1", "user-uuid-2"],
"total_documents": 150,
"total_size_bytes": 524288000,
"exported_tables": ["users", "api_keys", "documents", ...]
}Database Files (database/)
- users.json: User accounts, passwords (hashed), settings, preferences, and rmapi configurations
- api_keys.json: API keys, expiration dates, and usage tracking
- user_sessions.json: Active login sessions and JWT tokens
- documents.json: Document metadata including filenames, upload dates, and file paths
- system_settings.json: System-wide configuration and admin settings
- login_attempts.json: Authentication attempt logs and security data
- user_folders_cache.json: Cached reMarkable folder structures for performance
Filesystem Files (filesystem/)
- documents/{user-id}/: Documents archived by each user
Each JSON file in the database directory contains an array of records from the corresponding database table. The structure matches the internal database schema:
Example users.json structure:
[
{
"id": "uuid-string",
"username": "admin",
"email": "admin@example.com",
"password": "$hashed_password",
"is_admin": true,
"is_active": true,
"rmapi_host": "remarkable.cloud",
"default_rmdir": "/Books",
"coverpage_setting": "current",
"rmapi_config": "[auth]\ndevicetoken=...\nusertoken=...\n",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]Note
As of v1.6.0, the rmapi_config field in the users table contains the complete rmapi configuration as a text string. This eliminates the need for separate config files in the filesystem.
You can manually extract and examine backup contents:
# Extract backup archive
tar -xzf backup-filename.tar.gz
# View metadata
cat metadata.json | jq '.'
# Examine database exports
cat database/users.json | jq '.'
# List user documents
ls -la filesystem/documents/*/Important
Restore operations are destructive. Always backup current data first.
Note
Uploaded restore files and extracted archives are stored in temporary system storage (/tmp) and are automatically cleaned up after restoration or when cancelled.
- Navigate to Admin Panel → System Settings → Backup & Restore
- Click "Upload Restore"
- Select and upload your
.tar.gzbackup file - Wait for upload and validation to complete
- Click "Restore" on the uploaded file
- Confirm
The system validates backups during upload:
- Checks backup file integrity and format
- Validates metadata compatibility
- Warns about version differences
- Analyzes backup contents before restoration
To migrate from SQLite to PostgreSQL:
- Create backup from admin interface while running on SQLite
- Download backup file
- Set up PostgreSQL database and configure connection
- Update environment variables:
DB_TYPE=postgres DB_HOST=your-postgres-host DB_PORT=5432 DB_USER=aviary DB_PASSWORD=your-password DB_NAME=aviary
- Restart Aviary (creates new PostgreSQL schema)
- Restore backup through admin interface
To migrate from PostgreSQL to SQLite:
- Create backup from admin interface while running on PostgreSQL
- Download backup file
- Update environment variables:
DB_TYPE=sqlite # Remove PostgreSQL-specific variables - Restart Aviary (creates new SQLite database)
- Restore backup through admin interface
/data/
├── aviary.db # SQLite database (if using SQLite)
└── users/
└── {user-id}/
└── pdfs/ # User's uploaded documents
├── document1.pdf
└── subfolder/
Note
As of v1.6.0, rmapi configurations are stored in the database (in the rmapi_config column of the users table) rather than in the filesystem.
When enabling multi-user mode (MULTI_USER=true), Aviary automatically performs a single-user to multi-user migration. The following happens upon the initial admin user's first login in the background:
- Existing cloud pairing (if present) is migrated to the admin user
- Existing archived PDF files (if present) are moved to the admin user's directory
- Environment-based API key (if present) is migrated to the admin user's account
Important: Single-user to multi-user migration requires using the same storage backend. If you need to change storage backends, use the cross-storage-backend migration process below.
To migrate between different storage backends (e.g., filesystem to S3, or S3 to filesystem), use the backup and restore process.
-
Create a backup while running with filesystem storage:
# Current environment with filesystem storage STORAGE_BACKEND=filesystem # or unset (defaults to filesystem) DATA_DIR=/data
-
Download the backup from the admin interface
-
Update environment variables for S3 storage:
STORAGE_BACKEND=s3 S3_ENDPOINT=https://s3.amazonaws.com S3_REGION=us-east-1 S3_BUCKET=my-aviary-bucket S3_ACCESS_KEY_ID=your-access-key S3_SECRET_ACCESS_KEY=your-secret-key
-
Restart Aviary with the new configuration
-
Restore the backup through the admin interface
-
Create a backup while running with S3 storage:
# Current environment with S3 storage STORAGE_BACKEND=s3 S3_BUCKET=my-aviary-bucket # ... other S3 config
-
Download the backup from the admin interface
-
Update environment variables for filesystem storage:
STORAGE_BACKEND=filesystem # or unset (defaults to filesystem) DATA_DIR=/data # Remove S3-specific variables
-
Restart Aviary with the new configuration
-
Restore the backup through the admin interface
To migrate between different S3 providers (e.g., AWS S3 to MinIO):
- Create a backup with the current S3 configuration
- Update S3 environment variables for the new provider:
STORAGE_BACKEND=s3 S3_ENDPOINT=https://minio.example.com # New endpoint S3_BUCKET=new-bucket-name # New bucket S3_FORCE_PATH_STYLE=true # Often required for MinIO # ... update credentials as needed
- Restart Aviary with the new configuration
- Restore the backup through the admin interface
Combining multiple migrations is supported, but may require two migration steps.
Due to the backup capabilities exposed in multi-user mode it is recommended to perform the single-user → multi-user migration first before changing storage backends.
Combined migrations between database and storage providers in a single step is fully supported by the restore process in multi-user mode.
-
Stage 1: Single-user → Multi-user (same storage)
# Current: Single-user + filesystem + SQLite (implicit) MULTI_USER=true AUTH_USERNAME=admin AUTH_PASSWORD=secure-password # Keep: STORAGE_BACKEND=filesystem, DB_TYPE=sqlite
-
Restart and verify single→multi migration works
-
Stage 2: Create backup and configure S3 + PostgreSQL
MULTI_USER=true STORAGE_BACKEND=s3 S3_BUCKET=my-bucket # ... S3 config DB_TYPE=postgres DB_HOST=postgres-host # ... PostgreSQL config
-
Restart and restore backup
-
Single-user rmapi.conf: In single-user mode, the
rmapi.conffile is always stored in the filesystem at/root/.config/rmapi/rmapi.conf, regardless of storage backend. Ensure this is properly mounted as a volume for persistence. -
Backup verification: Always verify that backups complete successfully before changing storage backends. Check the backup metadata and file counts.
-
Temporary storage: Backup files are temporarily stored in
/tmpduring the restore process and are automatically cleaned up.
Regardless of STORAGE_BACKEND setting, these components are always stored locally:
| Component | Location | Volume Mount Required |
|---|---|---|
| SQLite database | /data/aviary.db |
Yes |
| Single-user rmapi.conf | /root/.config/rmapi/rmapi.conf |
Yes |
| Temporary files | /tmp |
No (ephemeral) |
The Aviary container can run completely stateless (no volume mounts) only with:
MULTI_USER=true # Multi-user mode
DB_TYPE=postgres # External PostgreSQL database
STORAGE_BACKEND=s3 # S3-compatible object storage
# + PostgreSQL and S3 connection detailsIn this configuration:
- Database: External PostgreSQL server
- Documents: S3-compatible object storage
- User configs: Stored in PostgreSQL database
- No local persistence needed
| Configuration | Required Mounts | Reason |
|---|---|---|
| Single-user mode | /root/.config/rmapi/ |
rmapi.conf always filesystem-based |
| SQLite database | /data |
Database file stored locally |
| Filesystem storage | /data |
Documents stored locally |