Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Setting Up a Self-Hosted Backup Server with Minarca and RAID1 on Debian

profile picture
Author
Kürşad Ölmez
Published
2026-09-16
Time to read
19 minutes reading time

Introduction

Minarca is an open-source, self-hosted backup solution built on top of rdiff-backup. It gives you a central web interface where you can manage backup clients, browse and restore files from past backups, and monitor backup status across multiple machines - without relying on a third-party cloud backup service.

This tutorial covers a complete, production-ready Minarca server setup on Debian, including a step that's easy to get wrong or skip entirely: building redundant storage with RAID1 for the backup data itself. There's not much point in a backup server whose only copy of your backups lives on a single disk. Along the way, this tutorial also covers a real post-installation issue that can leave the service unable to start after a reboot, a firewall and reverse proxy setup so the web interface isn't exposed over plain HTTP, and account-level hardening (changing the default credentials, email notifications, and two-factor authentication) that's easy to forget once the server "just works."

By the end of this tutorial, you will have:

  • A Minarca server with backup data stored on a RAID1 array, so a single disk failure doesn't cost you your backups.
  • A correctly configured temporary storage area, sized to fit within limited RAM.
  • A firewall, an SSL-terminated reverse proxy, hardened SSH, and fail2ban protecting the server.
  • Email notifications configured, and the default admin account replaced with hardened, 2FA-protected accounts.
  • At least one client machine configured to back up to the server.

Prerequisites

  • A server or VM running Debian 12 or 13, with at least two additional disks (beyond the OS disk) for the RAID1 array. This tutorial uses two disks of equal size; any size works as long as both disks match.
  • At least 4 GB of RAM (6 GB or more recommended - see Step 2 for why).
  • Root or sudo access.
  • A domain name pointed at your server's IP, for the reverse proxy's SSL certificate in Step 8.
  • An SMTP account (from your email provider, or a transactional email service) to send notifications and two-factor authentication codes in Step 9.
  • Basic familiarity with the Linux command line.

Example terminology

This tutorial uses the following placeholders. Replace them with your own values:

  • Server hostname: <your_host>
  • Backup storage mount point: /backups
  • RAID disks: /dev/sdb and /dev/sdc (adjust to match your own disk names - check with lsblk first)
  • Domain: <example.com>

Do not use actual IPs or domains when following along.

Step 1 - Install Debian

During installation, in the "Software selection" screen, select only:

  • SSH server
  • standard system utilities

Skip the desktop environment and web server options - this is a headless backup server, it doesn't need a GUI. After installation, you can confirm exactly what the "standard" task installed with:

tasksel --task-packages standard

Step 2 - Configure Temporary Storage

On a minimal Debian install, root's default PATH sometimes doesn't include /sbin and /usr/sbin, where commands like mkswap and swapon live. If a command below fails with command not found even though the package providing it is installed, check your PATH first:

echo $PATH

If /sbin and /usr/sbin are missing, add them for your current session:

export PATH=$PATH:/sbin:/usr/sbin

To make this permanent for future root sessions, add the same line to ~/.bashrc:

echo 'export PATH=$PATH:/sbin:/usr/sbin' >> ~/.bashrc
source ~/.bashrc

Minarca's documentation recommends 8 GiB or more of temporary storage, ideally as tmpfs, for better performance during restore operations. tmpfs lives in RAM, so on a server with limited memory, allocating a full 8 GiB this way would starve every other service on the box, including SSH.

If your server has 6 GB of RAM or less, use a combination of a smaller tmpfs and swap space instead of a pure 8 GiB tmpfs. This keeps restore performance reasonable without risking the server running out of memory under load.

Create an 8 GB swap file:

sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Set /tmp to a 5 GB tmpfs (adjust this down further if your server has less RAM):

sudo mkdir -p /etc/systemd/system/tmp.mount.d
sudo tee /etc/systemd/system/tmp.mount.d/override.conf > /dev/null <<'EOF'
[Mount]
Options=mode=1777,strictatime,size=5G
EOF
sudo systemctl daemon-reload
sudo systemctl restart tmp.mount

Verify both are active, and confirm they persist across a reboot before continuing:

free -h
df -h -t tmpfs
swapon --show

Step 3 - Build a RAID1 Array for Backup Storage

Identify your two additional disks:

lsblk

If either disk is 2 TB or larger, you must use GPT rather than a classic MBR partition table, or the partition will be silently truncated at 2 TB. parted handles this cleanly. It isn't always installed by default on a minimal Debian image, so install it first:

sudo apt update
sudo apt install parted -y

Run the following for both disks (/dev/sdb and /dev/sdc in this example):

sudo parted /dev/sdb
mklabel gpt
mkpart primary 0% 100%
set 1 raid on
quit

Install mdadm and create the RAID1 array from the two new partitions:

sudo apt update
sudo apt install mdadm -y
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1

If asked whether to enable a write-intent bitmap, accept it - it lets the array recover from an unexpected reboot by resyncing only the changed regions instead of the entire disk, at a negligible cost to write performance.

Make the array definition persistent. If you skip this step, the array may still assemble correctly after a reboot, but under a different, unpredictable device name (/dev/md127 instead of /dev/md0), which makes the server harder to administer later:

sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u

Format the array and mount it:

sudo mkfs.ext4 /dev/md0
blkid /dev/md0

Take the UUID printed by sudo blkid and add it to /etc/fstab:

echo 'UUID=<your_md0_uuid>  /backups  ext4  defaults,relatime  0  0' | sudo tee -a /etc/fstab
sudo mkdir -p /backups
sudo systemctl daemon-reload
mount -a

Confirm the array is healthy and mounted:

lsblk
cat /proc/mdstat
df -h /backups

Note that the initial RAID resync can take several hours on large disks - this happens in the background and the array is already usable in the meantime (you'll see [UU] next to it in /proc/mdstat once both disks are in sync, or [UU] with an ongoing percentage while resyncing).

Step 4 - Install Minarca Server

Add the required dependencies and the Minarca APT repository as explained in the official documentation:

sudo apt update
sudo apt upgrade
sudo apt install ca-certificates curl lsb-release gpg -y

sudo curl -L -o /etc/apt/keyrings/minarca-keyring.asc https://www.ikus-soft.com/archive/public.asc

sudo tee /etc/apt/sources.list.d/minarca.sources > /dev/null <<EOF
Types: deb
URIs: https://nexus.ikus-soft.com/repository/apt-release-$(lsb_release -sc)/
Suites: $(lsb_release -sc)
Components: main
Architectures: amd64
Signed-By: /etc/apt/keyrings/minarca-keyring.asc
EOF

Install the server package:

sudo apt update
sudo apt install minarca-server -y

By default, Minarca listens for HTTP requests only on the loopback interface (127.0.0.1:8080) - it isn't reachable from other machines yet. Confirm it's running locally before continuing:

curl -I http://127.0.0.1:8080

You should see an HTTP/1.1 200 OK response. Don't log in yet - you'll do that in Step 9, once the firewall and reverse proxy from Step 8 are in place, so you're never sending credentials over plain, unencrypted HTTP.

Step 5 - Fix a Known Startup Issue After Reboot

At the time of writing, a packaging issue can leave Minarca's database files (rdw.db, rdw.db-wal, rdw.db-shm under /etc/minarca/) owned by root:root, even though the service itself is configured to run as the minarca user. The service works fine on first install, but after a reboot you may see a 500 Internal Server Error in the web interface, caused by the minarca user being unable to write to its own database.

You can check whether this affects you:

sudo sh -c 'ls -la /etc/minarca/rdw.db*'

If the files are owned by root:root rather than minarca:minarca, fix the ownership now, and add a systemd override so this corrects itself automatically on every future start - this also ensures the service waits for /backups to be mounted before starting, which matters if your RAID array ever takes a moment longer to assemble at boot:

sudo mkdir -p /etc/systemd/system/minarca-server.service.d
sudo tee /etc/systemd/system/minarca-server.service.d/override.conf > /dev/null <<'EOF'
[Unit]
RequiresMountsFor=/backups
After=backups.mount

[Service]
ExecStartPre=/bin/sleep 5
ExecStartPre=/bin/sh -c 'chown minarca:minarca /etc/minarca/rdw.db* 2>/dev/null || true'
EOF
sudo systemctl daemon-reload
sudo systemctl restart minarca-server

The ExecStartPre commands run as root, before the service drops to the minarca user, so the chown succeeds regardless of the files' current ownership. The || true prevents the service from failing to start on a very first boot, before any database files exist yet.

Reboot and confirm the fix holds:

sudo reboot

After it comes back up:

systemctl status minarca-server --no-pager
sudo sh -c 'ls -la /etc/minarca/rdw.db*'

The web interface should load without a 500 error, and the database files should show minarca:minarca ownership.

Step 6 - Harden SSH

Minarca clients connect to the server over SSH to transfer backup data, so this server's SSH configuration deserves more care than a typical internal server. At minimum, move off the default port, disable root login, and disable password authentication in favor of key-based auth.

First, make sure you have a working SSH key pair set up and added to this server's ~/.ssh/authorized_keys for your admin user before disabling password authentication, or you will lock yourself out.

If you don't already have an SSH key pair on the machine you administer this server from (not on the server itself), generate one there:

ssh-keygen -t ed25519

Press Enter to accept the default file location, and optionally set a passphrase. Then copy the public key to this server (while password authentication is still enabled), replacing <your_user> and <your_host> with your actual values:

ssh-copy-id <your_user>@<your_host>

If ssh-copy-id isn't available on your system, copy the key manually instead:

cat ~/.ssh/id_ed25519.pub | ssh <your_user>@<your_host> "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Test that key-based login works before continuing to the next step:

ssh <your_user>@<your_host>

You should be logged in without being prompted for a password. Only proceed once this works.

Edit /etc/ssh/sshd_config:

Port 6022
Protocol 2
PermitRootLogin no
PasswordAuthentication no

Check the configuration for syntax errors before restarting the service - this catches typos before they can lock you out:

sudo sshd -t
sudo systemctl restart sshd

Install ufw if it isn't already present, and allow the new SSH port before removing access to the old one - test the new port works before you disconnect, so you always have a way back in:

sudo apt install ufw -y
sudo ufw allow 6022/tcp comment 'SSH'
sudo ufw enable
sudo ufw status

Test a fresh SSH connection (in a new terminal window, without closing your current session):

ssh -p 6022 <your_user>@<your_host>

Once you've confirmed the new port works, if you had a rule allowing the old port 22, remove it:

sudo ufw delete allow 22/tcp

Step 7 - Install fail2ban

Add fail2ban to automatically block IPs that repeatedly fail to authenticate over SSH:

apt install fail2ban -y

Create a local jail configuration matching your custom SSH port:

sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[sshd]
enabled = true
port = 6022
maxretry = 5
bantime = 3600
findtime = 600
EOF
sudo systemctl enable --now fail2ban
systemctl status fail2ban

Step 8 - Set Up a Firewall and Reverse Proxy for the Web Interface

Minarca's own documentation recommends putting a reverse proxy with SSL termination in front of the web interface for production use, rather than exposing port 8080 directly.

If your server sits behind a router or NAT (a home network or office setup, rather than a server with a directly-routable public IP such as most Hetzner Cloud or dedicated servers), configure your router to forward three ports to this server: 80 (HTTP), 443 (HTTPS), and 6022 (mapped to this server's SSH port from Step 6 - this is what carries client backup traffic). If your server already has a public IP directly assigned, skip this and just make sure the firewall rules below are in place.

Allow HTTP and HTTPS through the firewall you started configuring in Step 6:

sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw status

Install Nginx and Certbot:

sudo apt install nginx certbot python3-certbot-nginx -y

Create a site configuration that proxies to Minarca's loopback address:

Replace <example.com> with your own domain.

sudo tee /etc/nginx/sites-available/minarca > /dev/null <<'EOF'
server {
    listen 80;
    server_name <example.com>;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF
sudo ln -s /etc/nginx/sites-available/minarca /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

nginx -t checks the configuration for syntax errors before you reload - worth checking every time you edit an Nginx config, since a typo here would take down the site.

Now obtain a certificate. Certbot will detect the existing server block and automatically add the HTTPS configuration and an HTTP-to-HTTPS redirect for you:

sudo certbot --nginx -d <example.com>

Certbot rewrites /etc/nginx/sites-available/minarca in place, adding a second server block that listens on 443 with your certificate, and turning the original port 80 block into a redirect to HTTPS. You can confirm this by viewing the file afterward - it should now look like this:

server {
    listen 80;
    server_name <example.com>;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name <example.com>;

    ssl_certificate /etc/letsencrypt/live/<example.com>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<example.com>/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The exact contents of the ssl_certificate* and include lines are generated by Certbot for your domain - don't copy these paths literally, just use them to confirm Certbot's edit produced a similar structure to what's shown here. If the 443 block is missing after running Certbot, check /var/log/letsencrypt/letsencrypt.log for the reason it failed (a common cause is port 80 not actually being reachable from the internet yet, if you skipped the port-forwarding step above).

Once this completes, the web interface is reachable at https://<example.com>.

Now tell Minarca about this setup, so it stops accepting direct, unencrypted connections and knows what public address to use in links and client configuration. Add the following to /etc/minarca/minarca-server.conf:

server-host=127.0.0.1
external-url=https://<example.com>
minarca-remote-host=<example.com>:6022
  • server-host=127.0.0.1 restricts Minarca to the loopback interface, so the only way in is through Nginx - port 8080 is never directly reachable from outside the server.
  • external-url is the address used in notification emails and web interface redirects.
  • minarca-remote-host is the address and SSH port clients will use for backup transfers - this is the 6022 port you configured in Step 6, not the reverse proxy's port 443.

Restart the service to apply these:

sudo systemctl restart minarca-server

Step 9 - First Login and Account Hardening

With the reverse proxy in place, log in for the first time at https://<example.com> using Minarca's default credentials:

  • Username: admin
  • Password: admin123

You'll be prompted to set a new password immediately - do this before anything else, since the default credentials are publicly documented and predictable.

Configure email notifications. Two-factor authentication (set up next) sends its verification codes by email, so this needs to be working first. Add your SMTP provider's details to the same config file:

sudo tee -a /etc/minarca/minarca-server.conf > /dev/null << 'EOF'

# Email (SMTP) notification settings
email-host=<smtp_host>:587
email-encryption=starttls
email-sender=<sender_address>
email-username=<smtp_username>
email-password=<smtp_password>
email-send-changed-notification=true
EOF
sudo systemctl restart minarca-server

If you're using Gmail as the SMTP provider, use an App Password rather than your regular account password.

Verify email delivery by changing a password from the web interface and confirming the notification arrives. If it doesn't, check the logs for the SMTP error:

sudo tail -f /var/log/minarca/server.log

Enable two-factor authentication on the admin account: from the user profile page, find the Two-Factor Authentication section, enable it, and confirm with the code sent to your email.

Create a second, named admin account, rather than relying solely on the shared admin account for daily use - this also gives you a way back in if something goes wrong with one account. From the Administration → Users page, add a new user, set its role to Admin, and enable 2FA on it the same way as above. Once this second account works, consider whether the original admin account should be disabled or kept only as a break-glass fallback.

Step 10 - Configure a Backup Client

Create a User Account for the Client

Minarca accounts are separate from the operating system accounts on either the server or the client - a client can't connect until a matching user exists in Minarca itself. Rather than reusing an admin account for a regular client, create a dedicated, non-admin account for it:

  1. Log in to the web interface and go to Administration → Users.
  2. Click Add User, set a username and a temporary password, and leave the role as the default (non-admin) user.
  3. Save.

You'll use this username and password (or a token, if you enabled 2FA on it) when configuring the client below.

Install and Configure the Client

Minarca offers both a graphical setup wizard and a command-line interface - use whichever fits how you're deploying it. A single machine you're sitting in front of is usually easiest with the GUI; a headless server or a scripted rollout across many machines is easier with the CLI.

Linux (GUI):

Download and install the .deb package for Debian/Ubuntu from the Minarca download page:

wget https://www.ikus-soft.com/archive/minarca/minarca-client-latest.deb
sudo apt install --no-install-recommends ./minarca-client-latest.deb

Launch Minarca from your desktop environment's application menu. If the client isn't linked to a server yet, the setup wizard opens automatically - click Setup under Online Backup, then enter your server's URL (https://<example.com>) and the username/password you created above.

For a distribution without a .deb package, download the portable package instead, extract it, and run the minarcaw executable (or minarca from the command line for the CLI path below).

Linux (CLI) - for headless servers or scripted deployments:

minarca configure -r https://<example.com> -u <client_username>

You'll be prompted for that account's password, then asked to name this backup repository and select which folders to back up.

Windows (GUI):

Download and run the Windows installer from the Minarca download page. Once installed, launch Minarca from the Start menu - the setup wizard opens automatically if it isn't linked to a server yet. Click Setup under Online Backup, enter your server's URL and the client account's credentials, then choose which folders to back up.

Windows (CLI):

The same minarca configure command works from PowerShell or Command Prompt if Minarca was installed with the command-line tools:

minarca configure -r https://<example.com> -u <client_username>

Whichever path you use, since you already set minarca-remote-host on the server in Step 8, the client automatically receives the correct SSH host and port for backup transfers - you won't need to specify it separately.

Step 11 - Validate

  • https://<example.com> loads with a valid certificate, and port 8080 is not reachable from outside the server.
  • Logging in with the original admin/admin123 credentials no longer works.
  • cat /proc/mdstat shows the RAID1 array as healthy ([UU]).
  • A test client successfully completes its first backup.
  • You can browse and restore a file from that backup through the web interface.
  • SSH only accepts key-based authentication on the new port; a password login attempt is rejected.
  • systemctl status fail2ban shows the sshd jail active.
  • sudo ufw status shows only the ports you intended open (SSH port, 80, 443).
  • A password change on the web interface triggers a notification email.
  • Logging in prompts for a 2FA code on both admin accounts.
  • Reboot the server once more and confirm the web interface still loads without a 500 error.

Conclusion

You now have a self-hosted backup server with redundant storage, correctly sized temporary storage for restore operations, a firewall and SSL-terminated reverse proxy in front of the web interface, hardened SSH with fail2ban, and admin accounts protected by two-factor authentication instead of the default credentials. From here, you can add more clients the same way, customize the login page branding through Minarca's brand-* configuration options, or extend the RAID array to RAID6 or RAID10 if you need more redundancy or performance as your storage needs grow.

Next steps:

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get €20/$20 free credit!

Valid until: 31 December 2026 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more