Skip to content
Server Management

Setting Up Pydio Cells on Raspberry Pi 5/4/3 (Linux ARM64)

This documentation provides a comprehensive guide to setting up Pydio Cells on your Raspberry Pi 5 with the Linux ARM64 file. It includes instructions for preparing the environment, downloading and installing Pydio Cells, configuring storage, setting up SSL, and automating services.

Free Server for Personal Use

Running your own personal file server gives you something commercial cloud storage simply can’t — full control over your data. No subscriptions, no third-party access, no surprises. A Raspberry Pi 5 paired with Pydio Cells is one of the best ways to pull this off. It’s powerful enough to handle real workloads, and Pydio Cells is a mature, open-source platform that feels genuinely polished compared to many self-hosted alternatives.

In this guide, we’ll set up Pydio Cells via Docker on a Raspberry Pi 5 running 64-bit Linux (ARM64), and we’ll build in proper security practices from the start — because a file server that’s poorly secured is worse than no file server at all.

Prerequisites

Before diving in, get the following ready:

  1. A Raspberry Pi 5 (8GB RAM recommended) running a 64-bit OS — either Raspberry Pi OS Lite (64-bit) or Ubuntu Server 24.04 LTS for ARM64.
  2. One or two external HDDs for storage (e.g., 1 TB and 2 TB).
  3. A Cloudflare account for DNS management.
  4. A registered domain name (e.g., example.com).

Setting Up Pydio Cells with Docker on Raspberry Pi 5 (Linux ARM64)

This guide walks through everything from OS preparation to SSL-secured remote access. Docker keeps our services isolated, makes updates clean, and reduces the attack surface compared to running things directly on the host.


Step 1: Prepare the Environment

Security starts at the OS level. Unpatched software is one of the most exploited attack vectors, so update before doing anything else.

  1. Update your system:

    sudo apt update && sudo apt upgrade -y
    
  2. Install essential utilities:

    sudo apt install curl wget unzip -y
    
  3. Confirm you’re on a 64-bit kernel: Pydio Cells requires a 64-bit architecture. Verify with:

    uname -m
    

    You should see aarch64. If you see armv7l, you’re on a 32-bit OS and need to reinstall with the 64-bit image.

  4. Install Docker: Use the official install script, which handles the correct package for your architecture:

    curl -fsSL https://get.docker.com | sh
    

    After installation, add your user to the docker group so you don’t need sudo for every command. Keep in mind this grants effective root-level access — make sure your user account has a strong password and SSH is locked down with key-based auth.

    sudo usermod -aG docker $USER
    

    Log out and back in for the group change to take effect.

  5. Verify Docker is working:

    docker run --rm hello-world
    

Step 2: Securely Prepare Storage (External HDDs)

Proper filesystem setup matters when you’re storing personal data. We’ll use EXT4 with restricted mount options to limit exposure if something goes wrong.

  1. Format the drives: Find your drive identifiers first:

    lsblk
    

    Then format — replace sdX with your actual drive:

    sudo mkfs.ext4 /dev/sdX
    
  2. Create mount points:

    sudo mkdir -p /mnt/hdd1 /mnt/hdd2
    
Advertisement
  1. Configure auto-mount on boot: Using UUIDs instead of device paths (/dev/sdX) ensures the right drive gets mounted even if the boot order changes.

    Get your UUIDs:

    sudo blkid
    

    Edit the filesystem table:

    sudo nano /etc/fstab
    

    Add your entries:

    UUID=3fe457c5-0892-44ef-9f8e-5753f49e0cba /mnt/hdd1 ext4 defaults,noexec 0 0
    UUID=80fabc25-61d6-4448-ba0b-9a627ec348b4 /mnt/hdd2 ext4 defaults,noexec 0 0
    

    The noexec flag is important — it prevents binaries on those drives from being executed directly. It won’t stop malware from running elsewhere, but it does prevent uploaded files from being trivially executed off the storage drive.

    Apply the changes:

    sudo mount -a
    
  2. Verify and set ownership:

    df -h
    sudo chown -R $USER:$USER /mnt/hdd1 /mnt/hdd2
    sudo chmod -R 750 /mnt/hdd1 /mnt/hdd2
    

Step 3: Configure Docker for Pydio Cells

We’ll use a docker-compose.yml file to define our services. This declarative approach makes the setup reproducible and easy to update.

  1. Create the project directory:

    mkdir ~/pydio-cells && cd ~/pydio-cells
    nano docker-compose.yml
    
  2. Paste in the configuration: Replace the placeholder passwords with strong, randomly generated ones — at least 16 characters, mixing uppercase, lowercase, numbers, and symbols. You can generate one with openssl rand -base64 24.

    services:
      mysql:
        image: mysql:8
        restart: unless-stopped
        environment:
          MYSQL_ROOT_PASSWORD: your_strong_root_passwd
          MYSQL_DATABASE: pydio_db
          MYSQL_USER: pydio_user
          MYSQL_PASSWORD: your_strong_db_passwd
        volumes:
          - mysqldir:/var/lib/mysql
    
      cells:
        image: pydio/cells:latest
        restart: unless-stopped
        ports:
          - "8080:8080"
        environment:
          CELLS_WORKING_DIR: "/var/cells"
          CELLS_SITE_BIND: ":8080"
          CELLS_SITE_EXTERNAL: "https://dir.example.com"
        volumes:
          - cellsdir:/var/cells
          - /mnt/hdd1/pydio_data:/var/cells/data
        depends_on:
          - mysql
    
    volumes:
      mysqldir:
      cellsdir:
    
  3. Start the stack:

    docker compose up -d
    
  4. Check that containers are running:

    docker ps
    

Step 4: Initialize Pydio Cells

  1. Open a browser and go to http://<raspberry-pi-ip>:8080.
  2. The setup wizard will walk you through the initial configuration:
    • Enter the MySQL credentials you set above (pydio_user and your chosen password).
    • Create an admin account — avoid obvious usernames like admin or root. Use something unique paired with a strong passphrase.
    • Set your storage path to /var/cells/data, which maps to /mnt/hdd1/pydio_data on the host.

Advertisement

Step 5: Dynamic DNS with Cloudflare

If your home internet uses a dynamic IP address (most residential connections do), you need Dynamic DNS so your domain always points to the right place. Cloudflare’s DNS handles this well and can proxy traffic to mask your real IP.

  1. Install ddclient:

    sudo apt install ddclient -y
    
  2. Configure ddclient for Cloudflare:

    sudo nano /etc/ddclient.conf
    

    Use a scoped API Token rather than your Global API Key — this follows the principle of least privilege. Create a token in your Cloudflare dashboard with Zone:DNS:Edit permission for your specific zone.

    protocol=cloudflare
    use=web
    login=token
    password=your_cloudflare_api_token
    zone=example.com
    dir.example.com
    
  3. Lock down the config file — it contains your API token:

    sudo chmod 600 /etc/ddclient.conf
    sudo chown root:root /etc/ddclient.conf
    
  4. Enable and start the service:

    sudo systemctl enable ddclient
    sudo systemctl start ddclient
    

Step 6: Enforce Encryption with Let’s Encrypt

Accessing your file server over plain HTTP is a serious risk — passwords and files would be transmitted in cleartext. Let’s Encrypt provides free, trusted TLS certificates.

  1. Install Certbot:

    sudo apt install certbot -y
    
  2. Issue the certificate: Make sure port 80 is forwarded on your router to the Raspberry Pi for the domain validation challenge.

    sudo certbot certonly --standalone -d dir.example.com
    
  3. Mount the certificates into the Docker container: Edit your docker-compose.yml and update the cells volumes section:

      cells:
        # ... previous configuration ...
        volumes:
          - cellsdir:/var/cells
          - /mnt/hdd1/pydio_data:/var/cells/data
          - /etc/letsencrypt/live/dir.example.com:/etc/ssl/certs:ro
    

    The :ro flag mounts the certificates read-only, so the container can’t modify them. Restart to apply:

    docker compose down
    docker compose up -d
    
  4. Automate certificate renewal: Let’s Encrypt certificates expire every 90 days. Set up a cron job to renew automatically:

    sudo crontab -e
    

    Add this line — it attempts renewal daily at 2 AM and restarts the Pydio container if a new cert is issued:

    0 2 * * * certbot renew --quiet --deploy-hook "cd /home/pi/pydio-cells && docker compose restart cells"
    

    Replace /home/pi/pydio-cells with the actual path to your project directory.


Step 7: Final Security Hardening

A few last steps before you call this production-ready:

  1. Firewall: Configure ufw to allow only the ports you actually need:

    sudo ufw allow 22/tcp
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow 8080/tcp
    sudo ufw enable
    
  2. Access Control in Pydio Cells: Log in at https://dir.example.com. Review user permissions, enable Two-Factor Authentication (2FA) for all accounts, and set a strong minimum password policy under the security settings.

  3. Verify encryption: Check that your browser shows a valid padlock on the Pydio interface, and confirm your Cloudflare DDNS record is resolving to your current public IP with dig dir.example.com.

That’s it — you now have a self-hosted file server that’s encrypted in transit, authenticated, and reasonably hardened against the most common attack vectors. Your data stays on hardware you control.


Share article

Subscribe to my newsletter

Receive my case study and the latest articles on my WhatsApp Channel.

Warning