In Part 1 of this series, I explained why I have embarked on a long journey towards digital independence from Big Tech and Big Risk. Part 2 documented the first step of that journey – building a personal cloud, Part 3 discussed the security issues, and Part 4 described setting up an encrypted calendar in the personal cloud. This post is about a file server in the personal cloud as a partial replacement of Dropbox and Google Drive. It currently covers only the use of these services to sync between my own devices; I could extend it to include a couple of family members or close collaborators but not to a wider circle. This limited replacement is valuable because the privacy needs are greatest for material that I share only with the half a dozen devices (desktop, laptop, tablet, phone) that I use on a regular basis.
SFTP Server
The simplest solution to a file server is of course an FTP server, but for security reasons, several tweaks are necessary:
- First, to minimize the threat surface, I want to run everything over the SSH port, and so I use an SFTP server instead of a plain FTP server.
- Second, the file server will be accessed using unattended scripts and so the SSH key for this will have to be cached in the SSH-Agent or in a key ring. Therefore, the SFTP server will be accessed as a different highly restricted user that is allowed to run SFTP and nothing else. This is easily accomplished by creating a new group
sftponly
for this user and then adding the following lines to the end of/etc/ssh/sshd_config
:
Match Group sftponly
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PasswordAuthentication no
- Third, I want the SFTP server to host only encrypted files. So all uploads and downloads are done using scripts that encrypt and decrypt the files using a locally cached symmetric password. I currently use 7-Zip to archive, compress and encrypt the files using AES-256.
Encrypted Git Repo
SFTP servers are not suitable for frequently modified files that need to be under version control. For this I use git-remote-gcrypt. which is a git remote helper to push and pull from repositories encrypted with GnuPG, using a custom format. I basically followed Caloan’s simple instructions on how to set this up.
What is interesting about this setup is that git
is not running on the server at all. The server runs rsync
so that only the changed chunks are uploaded and downloaded. Only the clients run git
, and when stuff has to be pushed to or pulled from the remote, git-remote-gcrypt
steps in to handle this operation. Chunks are encrypted before uploading and decrypted after downloading using a key. The server does not even have the public key.
A known issue with git-remote-gcrypt
is that every git push
to the server effectively has --force
. We must therefore pull before pushing. The relevant part of my shell script is shown below:
git fetch $SERVER
local=$(git rev-parse HEAD) # hash of local head
remote=$(git rev-parse $SERVER/master) # hash of remote head
base=$(git merge-base HEAD $SERVER/master) # hash of common ancestor
if [ $local == $remote ]; then
action=none # local and remote are identical
elif [ $local == $base ]; then
action=pull # remote is one or more commits ahead of local
elif [ $remote == $base ]; then
action=push # local is one or more commits ahead of remote
else
action=merge # local and remote have diverged from common ancestor
fi
Once again, I want this user to run in a chroot
jail. There are many good introductions on how to do this: for example, John Otieno. There are only two commands needed inside the jail: sh
and rsync
. We add a section in /etc/ssh/sshd_config
to match this user and send it to the jail. It is also convenient to modify AuthorizedKeysFile
directive in /etc/ssh/sshd_config
to something like:
AuthorizedKeysFile /etc/ssh/authorized_keys/%u .ssh/authorized_keys
and create authorized_keys
in the new location.
Termux in Android Devices
The above setup is designed for easy access from laptops running Linux, but the greatest need for syncing content is to and from phones and tablets. Thankfully, termux
solved this problem for me by allowing me to run a Linux-like environment on my phone. I have termux
running in the background all the time, and from any Android App, I can share a file to termux
. I have setup ~/bin/termux-file-editor
to point to a script that uploads the file to the SFTP server.