Migration Guide
Migrate an existing project — files, Docker services, databases — from a traditional server or local development environment into an encrypted Rediacc repository.
Prerequisites
rdcCLI installed (Installation)- A machine added and provisioned (Setup)
- Enough disk space on the server for your project (check with
rdc machine status)
Step 1: Create a Repository
Create an encrypted repository sized to fit your project. Allocate extra space for Docker images and container data.
rdc repo create my-project -m server-1 --size 20G
Tip: You can resize later with
rdc repo resizeif needed, but the repository must be unmounted first. It’s easier to start with enough space.
Step 2: Upload Your Files
Use rdc repo sync upload to transfer your project files into the repository.
# Preview what will be transferred (no changes made)
rdc repo sync upload -m server-1 -r my-project --local ./my-project --dry-run
# Upload files
rdc repo sync upload -m server-1 -r my-project --local ./my-project
The repository must be mounted before uploading. If it isn’t already:
rdc repo mount my-project -m server-1
For subsequent syncs where you want the remote to exactly match your local directory:
rdc repo sync upload -m server-1 -r my-project --local ./my-project --mirror
The
--mirrorflag deletes files on the remote that don’t exist locally. Use--dry-runfirst to verify.
Step 3: Fix File Ownership
Uploaded files arrive with your local user’s UID (e.g., 1000). Rediacc uses a universal user (UID 7111) so that VS Code, terminal sessions, and tools all have consistent access. Run the ownership command to convert:
rdc repo ownership my-project -m server-1
Docker-Aware Exclusion
If Docker containers are running (or have been run), the ownership command automatically detects their writable data directories and skips them. This prevents breaking containers that manage their own files with different UIDs (e.g., MariaDB uses UID 999, Nextcloud uses UID 33).
The command reports what it does:
Excluding Docker volume: database/data
Excluding Docker volume: redis/data
Ownership set to UID 7111 (245 changed, 4 skipped, 0 errors)
When to Run
- After uploading files — to convert your local UID to 7111
- After starting containers — if you want Docker volume directories to be auto-excluded. If containers haven’t been started yet, there are no volumes to exclude and all directories get chowned (which is fine — the containers will recreate their data on first start)
Force Mode
To skip Docker volume detection and chown everything, including container data directories:
rdc repo ownership my-project -m server-1
Warning: This may break running containers. Stop them first with
rdc repo downif needed.
Custom UID
To set a UID other than the default 7111:
rdc repo ownership my-project -m server-1 --uid 1000
Step 4: Set Up Your Rediaccfile
Create a Rediaccfile in your project root. This Bash script defines how your services are started and stopped.
#!/bin/bash
up() {
renet compose -- up -d
}
down() {
renet compose -- down
}
The two lifecycle functions:
| Function | Purpose | Error behavior |
|---|---|---|
up() | Start services | Root failure is critical; subdirectory failures are logged and continue |
down() | Stop services | Best-effort: always attempts all |
Important: Always use
renet compose --instead ofdocker composein your Rediaccfile. Therenet composewrapper enforces host networking, CRIU checkpoint/restore capabilities, IP allocation, and service discovery required by renet-proxy. Usingdocker composedirectly bypasses all of these and will be rejected during validation.Never use
sudo dockereither —sudoresets environment variables includingDOCKER_HOST, which causes containers to be created on the system Docker daemon instead of the repository’s isolated daemon. Rediaccfile functions already run with sufficient privileges.
See Services for full details on Rediaccfiles, multi-service layouts, and execution order.
Step 5: Configure Service Networking
Rediacc runs an isolated Docker daemon per repository. Services use network_mode: host and bind to unique loopback IPs so they can use standard ports without conflicts across repositories.
Adapting Your docker-compose.yml
Before (traditional):
services:
postgres:
image: postgres:16
ports:
- "5432:5432"
volumes:
- ./data/postgres:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
redis:
image: redis:7-alpine
ports:
- "6379:6379"
app:
image: my-app:latest
ports:
- "8080:8080"
environment:
DATABASE_URL: postgresql://postgres:secret@postgres:5432/mydb
REDIS_URL: redis://redis:6379
After (Rediacc):
services:
postgres:
image: postgres:16
volumes:
- ./data/postgres:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
command: -c listen_addresses=${POSTGRES_IP} -c port=5432
redis:
image: redis:7-alpine
command: redis-server --bind ${REDIS_IP} --port 6379
app:
image: my-app:latest
environment:
DATABASE_URL: postgresql://postgres:secret@${POSTGRES_IP}:5432/mydb
REDIS_URL: redis://${REDIS_IP}:6379
LISTEN_ADDR: ${APP_IP}:8080
Key changes:
- Remove
ports:mappings —renet composeuses host networking and strips port mappings automatically - Remove
network_mode: host—renet composeadds this for you - Restart policies are safe to keep — renet auto-strips them for CRIU compatibility and the router watchdog auto-recovers stopped containers
- Bind services to
${SERVICE_IP}environment variables (auto-injected by Rediacc) - Reference other services by their IP instead of Docker DNS names (e.g.,
${POSTGRES_IP}instead ofpostgres)
The {SERVICE}_IP variables are automatically generated from your compose file’s service names. The naming convention: uppercase, hyphens replaced with underscores, suffixed with _IP. For example, listmonk-app becomes LISTMONK_APP_IP.
See Service Networking for details on IP assignment and .rediacc.json.
Step 6: Start Services
Mount the repository (if not already mounted) and start all services:
rdc repo up my-project -m server-1 --mount
This will:
- Mount the encrypted repository
- Start the isolated Docker daemon
- Auto-generate
.rediacc.jsonwith service IP assignments - Run
up()from all Rediaccfiles
Verify your containers are running:
rdc machine containers server-1
Step 7: Enable Autostart (Optional)
By default, repositories must be manually mounted and started after a server reboot. Enable autostart so your services come up automatically:
rdc repo autostart enable my-project -m server-1
You will be prompted for the repository passphrase.
Security note: Autostart stores a LUKS keyfile on the server. Anyone with root access can mount the repository without the passphrase. See Autostart for details.
Common Migration Scenarios
WordPress / PHP with Database
my-wordpress/
├── Rediaccfile
├── docker-compose.yml
├── app/ # WordPress files (UID 33 when running)
├── database/data/ # MariaDB data (UID 999 when running)
└── wp-content/uploads/ # User uploads
- Upload your project files
- Start services first (
rdc repo up) so containers create their data directories - Run ownership fix — MariaDB and app data dirs are auto-excluded
Node.js / Python with Redis
my-api/
├── Rediaccfile
├── docker-compose.yml
├── src/ # Application source
├── node_modules/ # Dependencies
└── redis-data/ # Redis persistence (UID 999 when running)
- Upload your project (consider excluding
node_modulesand pulling inup()) - Run ownership fix after containers have started
Custom Docker Project
For any project with Docker services:
- Upload project files
- Adapt
docker-compose.yml(see Step 5) - Create a
Rediaccfilewith lifecycle functions - Run ownership fix
- Start services
Troubleshooting
Permission Denied After Upload
Files still have your local UID. Run the ownership command:
rdc repo ownership my-project -m server-1
Container Won’t Start
Check that services bind to their assigned IP, not localhost:
# Check assigned IPs
rdc term server-1 my-project -c "cat .rediacc.json"
# Check container logs
rdc term server-1 my-project -c "docker logs <container-name>"
Port Conflict Between Repositories
Each repository gets unique loopback IPs. If you see port conflicts, verify that your docker-compose.yml uses ${SERVICE_IP} for binding. Services not bound to SERVICE_IP listen on all interfaces and will conflict with other repositories.
Ownership Fix Breaks Containers
If you ran rdc repo ownership and a container stopped working, the container’s data files were chowned. Stop the container, delete its data directory, and restart — the container will recreate it:
rdc repo down my-project -m server-1
# Delete the container's data directory (e.g., database/data)
rdc repo up my-project -m server-1