Skip to main content Skip to navigation Skip to footer

Migration Guide

Migrate existing projects into encrypted Rediacc repositories.

Migration Guide

Migrate an existing project — files, Docker services, databases — from a traditional server or local development environment into an encrypted Rediacc repository.

Prerequisites

  • rdc CLI 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 resize if 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 --mirror flag deletes files on the remote that don’t exist locally. Use --dry-run first 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 down if 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:

FunctionPurposeError behavior
up()Start servicesRoot failure is critical; subdirectory failures are logged and continue
down()Stop servicesBest-effort: always attempts all

Important: Always use renet compose -- instead of docker compose in your Rediaccfile. The renet compose wrapper enforces host networking, CRIU checkpoint/restore capabilities, IP allocation, and service discovery required by renet-proxy. Using docker compose directly bypasses all of these and will be rejected during validation.

Never use sudo docker either — sudo resets environment variables including DOCKER_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:

  1. Remove ports: mappingsrenet compose uses host networking and strips port mappings automatically
  2. Remove network_mode: hostrenet compose adds this for you
  3. Restart policies are safe to keep — renet auto-strips them for CRIU compatibility and the router watchdog auto-recovers stopped containers
  4. Bind services to ${SERVICE_IP} environment variables (auto-injected by Rediacc)
  5. Reference other services by their IP instead of Docker DNS names (e.g., ${POSTGRES_IP} instead of postgres)

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:

  1. Mount the encrypted repository
  2. Start the isolated Docker daemon
  3. Auto-generate .rediacc.json with service IP assignments
  4. 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
  1. Upload your project files
  2. Start services first (rdc repo up) so containers create their data directories
  3. 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)
  1. Upload your project (consider excluding node_modules and pulling in up())
  2. Run ownership fix after containers have started

Custom Docker Project

For any project with Docker services:

  1. Upload project files
  2. Adapt docker-compose.yml (see Step 5)
  3. Create a Rediaccfile with lifecycle functions
  4. Run ownership fix
  5. 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