$_ BSDHowTo.ch
How To... Why not..? Scripts Patches RSS logo

How to publish your web pages using SFTP

Last update: 2018-08-26

Introduction

In this post I show you how to leverage SFTP for publishing your web pages. All you need for this is OpenSSH and a dedicated user with a key pair for authentication. Of course I have tested the commands I show you in this post on OpenBSD.

Create the dedicated user

I want to restrict the new user as much as possible. Use the following command to create the account:

$ doas useradd webpub
doas (user@fqdn.example.com) password:
useradd: Warning: home directory `/home/publish' doesn't exist, and -m was not specified

I've left away the parameter -m because I don't want useradd(8) to create /home/webpub and populate it with the contents of /etc/skel. Up next you create the folder structure required for the new user:

$ doas mkdir -m 755 /home/webpub
$ doas mkdir -m 700 /home/webpub/.ssh
$ doas chown -R webpub:webpub /home/webpub

This user must only be used for transferring files to /var/www/htdocs/, so do not want to allow any other kind of log in. Using vipw(8) I set the shell for the user to /sbin/nologin:

$ doas vipw
:/^webpub/s/\/bin\/ksh/\/sbin\/nologin/
:wq

Create the public/private key pair

The user can only use a key pair to log in into SSH as the account doesn't have a password. With this commands you create valid key pair and install it:

$ doas -u webpub ssh-keygen -t ed25519
...
$ doas -u webpub mv /home/webpub/.ssh/ed25519.pub /home/publish/.ssh/authorized_keys
$ doas mv /home/webpub/.ssh/id_ed25519 ./id_webpub

Configure sshd(8)

In sshd_config(5) you can use Match blocks to change the behavior of sshd(8) depending on different variables. I add such a Match block to restrict the user webpub to /var/www/htdocs/ and prevent him from using any SSH functionality beside SFTP.

Match user webpub
    AllowTcpForwarding no
    ChrootDirectory /var/www/htdocs
    ForceCommand internal-sftp
    PasswordAuthentication no
    PermitTTY no
    PermitTunnel no
    X11Forwarding no        

I'm pretty sure that not all of the options are really required. But pretty sure is not sure enough, so I'm better safe than sorry. You must reload the configuration to let sshd(8) know about it:

$ doas rcctl reload sshd