Building a Secure File Storage System on Your VPS
#security
#linux
#storage
#devops
Introduction
Running a private file storage system on a virtual private server (VPS) can be convenient, but it also introduces risk if not designed with security in mind. This guide walks through practical, repeatable steps to build a secure storage stack on a VPS, focusing on encryption at rest, encrypted transit, strong authentication, disciplined access control, reliable backups, and vigilant monitoring.
Prerequisites
- A VPS running a modern Linux distro (e.g., Ubuntu 22.04+ or Debian 12+).
- At least one dedicated data volume (or an additional disk) for storage.
- Administrative access (sudo) to the server.
- SSH public key authentication enabled.
- Basic familiarity with Linux commands and system services.
Commands in this guide are examples; adapt device names and paths to your environment.
Threat model and goals
- Protect data at rest: use disk encryption or file-system-level encryption to prevent data leakage if the disk is stolen or copied.
- Protect data in transit: force encrypted channels (SSH/SFTP, TLS for web services).
- Control access: restrict who can read/write data, and enforce least-privilege.
- Maintain integrity and availability: regular backups, monitoring, and timely patching.
- Resilience: plan for recovery from accidental deletion, corruption, or ransomware.
Architecture overview
- Data storage: encrypted at rest (LUKS on a dedicated volume or encrypted file system).
- Data access: via SSH/SFTP (or a controlled web UI behind TLS).
- Data in transit: SSH keys for authentication; TLS for any web interfaces.
- Access control: separate system user accounts, group-based permissions, and restricted directories.
- Backups: encrypted backups with regular rotation and offsite replication.
- Monitoring and logging: centralized logs, basic intrusion prevention (fail2ban), and regular audits.
Step-by-step: Build securely
- Baseline the system
- Update and upgrade packages, install core security utilities.
- Harden the firewall and login policies.
Code examples:
-
Update and install basics
- sudo apt-get update && sudo apt-get upgrade -y
- sudo apt-get install -y ufw fail2ban certbot logrotate
-
Basic firewall
- sudo ufw default deny incoming
- sudo ufw default allow outgoing
- sudo ufw allow 22/tcp # SSH (will tighten further)
- sudo ufw enable
- Create a dedicated storage volume (and prepare for encryption)
- If you have an extra disk, identify it (lsblk) and create a protected volume.
- Best practice: use LUKS to encrypt the disk, then format and mount.
Commands (example; adjust /dev/sdb1 to your disk):
- sudo apt-get install -y cryptsetup
- sudo lsblk -f
- sudo cryptsetup luksFormat /dev/sdb1
- sudo cryptsetup open /dev/sdb1 securestorage
- sudo mkfs.ext4 /dev/mapper/securestorage
- sudo mkdir -p /mnt/securestorage
- sudo mount /dev/mapper/securestorage /mnt/securestorage
- sudo blkid /dev/mapper/securestorage
- Persist the encryption (auto-unlock on boot, if supported)
- Add to /etc/crypttab (requires a method to unlock at boot, e.g., passphrase via early prompt or a keyfile; consult your provider).
- Example (interactive unlock; do not place a raw keyfile in insecure locations):
- echo “securestorage /dev/sdb1 none luks” | sudo tee -a /etc/crypttab
- echo “/dev/mapper/securestorage /mnt/securestorage ext4 defaults 0 2” | sudo tee -a /etc/fstab
Notes:
- On many VPS providers, boot-time disk encryption may be challenging. If auto-unlock isn’t feasible, you can rely on manual unlock at boot or use file-system encryption instead (see option below).
- Alternative: file-system level encryption (if LUKS isn’t practical)
- Use fscrypt or ecryptfs to encrypt specific directories or volumes without full-disk encryption.
- Example with ecryptfs (for individual directories):
- sudo apt-get install -y ecryptfs-utils
- Create a writable directory, then wrap it with ecryptfs-wrap-passphrase
- This is useful for per-user encrypted storage but requires careful key management.
- Harden SSH access and authentication
- Disable password login; require SSH key authentication.
- Change default SSH port (optional) and apply login attempts limits.
Edit /etc/ssh/sshd_config (examples):
- PermitRootLogin no
- PasswordAuthentication no
- ChallengeResponseAuthentication no
- UsePAM yes
- PermitEmptyPasswords no
- AllowUsers your-storage-user
Apply changes:
- sudo systemctl reload sshd
Optional: change SSH port
- In sshd_config, set Port 2222 (or another unused port), then open that port in the firewall.
- Create a dedicated storage user and proper permissions
- Avoid using root for storage access.
- Create a storage group, assign appropriate permissions to the storage directory.
Commands:
- sudo adduser storage
- sudo groupadd storagegrp
- sudo usermod -aG storagegrp storage
- sudo chown -R root:storagegrp /mnt/securestorage
- sudo chmod -R 750 /mnt/securestorage
- Access methods: SSH/SFTP or a controlled web UI (optional)
- SSH/SFTP: rely on OpenSSH with key-based authentication and restricted UID/GID mappings.
- Web UI (optional): deploy a secure web file manager behind TLS (e.g., Nginx + Let’s Encrypt) if you need a web-accessible UI.
If using SFTP with internal chroot:
- Configure /etc/ssh/sshd_config to add a Match block for the storage user:
- Match User storage
- ChrootDirectory /mnt/securestorage
- ForceCommand internal-sftp
- X11Forwarding no
- AllowTcpForwarding no
- Encrypt data in transit for any web interface
- If you run a web UI, set up TLS with Certbot (Let’s Encrypt).
Commands (example for Nginx + Let’s Encrypt):
- sudo apt-get install -y nginx certbot python3-certbot-nginx
- Configure a server block for your domain, then:
- sudo certbot —nginx -d your-domain.example
- Ensure TLS-only connections and strong cipher suites (disable weak ciphers).
- Backup strategy (encrypted, versioned, offsite)
- Plan: regular backups of the storage data to a remote, encrypted destination.
- Use a tool like restic or rsync over SSH for encrypted backups.
Example with restic (remote backup to an S3-compatible store or SSH server):
-
Install restic: sudo apt-get install -y restic
-
Initialize backup repository (on remote storage):
- restic -r s3:url=https://s3.example.com/bucket
backup /mnt/securestorage —password-file /path/to/password
- restic -r s3:url=https://s3.example.com/bucket
-
Or over SSH:
- restic -r ssh:user@backup.example.com:/backups
backup /mnt/securestorage —password-file /path/to/password
- restic -r ssh:user@backup.example.com:/backups
-
Automate with a cron job and rotate backups.
- Monitoring, logging, and intrusion prevention
- Enable and tune fail2ban to mitigate brute-force SSH attempts.
- Ensure logrotate handles security logs.
- Consider lightweight monitoring: UFW status, disk usage, and service health.
- Optional: enable auditd for integrity monitoring of critical files.
Examples:
- sudo systemctl enable —now fail2ban
- sudo ufw allow 22/tcp (and/or 2222 if you changed SSH port)
- sudo apt-get install -y auditd
- sudo systemctl enable —now auditd
- Regular maintenance and recovery testing
- Keep the system updated with security patches.
- Periodically test backup restoration to verify data integrity.
- Review SSH keys; rotate keys after incidents or on a cadence.
- Reassess access policies if team changes occur.
- Validation checklist
- Data at rest encryption verified (disk/volume is encrypted).
- Data in transit encryption verified (SSH/TLS configured, test with TLS checker).
- Access controls validated (users have least privilege; no root over storage).
- Backups tested (restore a sample file and verify integrity).
- Logs and alerts configured (fail2ban, system logs, backup logs).
Optional: sample commands quick-reference
- Create a non-root storage user and group:
- sudo adduser storage
- sudo groupadd storagegrp
- sudo usermod -aG storagegrp storage
- Harden SSH (basic):
- Edit /etc/ssh/sshd_config: disable password auth, disable root login
- sudo systemctl reload sshd
- Basic UFW rules:
- sudo ufw default deny incoming
- sudo ufw allow 22/tcp
- sudo ufw enable
- LUKS setup (on a new disk /dev/sdb1):
- sudo apt-get install -y cryptsetup
- sudo cryptsetup luksFormat /dev/sdb1
- sudo cryptsetup open /dev/sdb1 securestorage
- sudo mkfs.ext4 /dev/mapper/securestorage
- sudo mkdir -p /mnt/securestorage
- sudo mount /dev/mapper/securestorage /mnt/securestorage
- TLS with Let’s Encrypt (Nginx):
- sudo apt-get install -y certbot python3-certbot-nginx
- sudo certbot —nginx -d your-domain.example
Conclusion
A secure file storage system on a VPS is a combination of multiple layers: encryption at rest, encrypted transit, strict access control, reliable backups, and ongoing monitoring. By following the steps above, you can reduce risk substantially and be prepared to recover quickly from incidents. Security is a continuous process—review configurations after major updates, rotate credentials on a schedule, and run periodic audits to stay ahead of threats.