Skip to content

Instantly share code, notes, and snippets.

@michele-tn
Last active October 4, 2025 21:41
Show Gist options
  • Select an option

  • Save michele-tn/6185f852f80297dec232b67ecad85c3e to your computer and use it in GitHub Desktop.

Select an option

Save michele-tn/6185f852f80297dec232b67ecad85c3e to your computer and use it in GitHub Desktop.
Secure Guest SFTP User on Ubuntu 22.04 - test on Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-156-generic x86_64)

Secure Guest SFTP User on Ubuntu 22.04.5

Abstract

In multi-user environments, providing controlled access to file transfer services is a recurring requirement. This document describes a structured procedure for configuring a non-privileged user account on Ubuntu 22.04.5 with access restricted exclusively to SFTP. Additionally, it outlines the optional configuration of reverse TCP tunneling over SSH, intended for controlled administrative or connectivity use cases. The configuration ensures compliance with security best practices by removing administrative privileges, enforcing a chroot environment, disabling shell access, and applying strict directory permissions. An automation script is provided to facilitate reproducibility and reduce manual intervention.


Overview

In many deployment scenarios, it is necessary to provide external users with controlled access to a server for the purpose of file exchange. Granting full SSH shell access in such cases may expose the system to unnecessary risk. This document demonstrates how to establish an SFTP-only environment for a dedicated user (guest), ensuring that the user remains confined to a restricted directory while being prevented from executing arbitrary commands on the host system.

The approach is based on the following principles:

  • Principle of least privilege
  • Isolation of the user via OpenSSH chroot
  • Enforcement of proper file system permissions
  • Removal of any administrative or shell access capabilities

Objectives

  1. User Creation: Establish a dedicated non-privileged account named guest.
  2. Privilege Restriction: Ensure that the user has no membership in administrative groups such as sudo or adm.
  3. SFTP Jail Configuration: Modify the SSH daemon configuration to force SFTP access within a chrooted environment.
  4. Directory Permissions: Apply strict ownership and permission rules to the home directory and working directory to satisfy OpenSSH requirements.
  5. Shell Access Removal: Assign /usr/sbin/nologin as the user’s shell, effectively preventing interactive login attempts.
  6. Security Hardening: Disable password-based authentication for the user and restrict forwarding features to limit potential abuse.

Implementation

Automation Script

The following script, create_guest_sftp.sh, automates the configuration process. It is designed for execution on Ubuntu 22.04/22.05 and should be run with administrative privileges.

#!/bin/bash
# Script to create a secure guest SFTP-only user on Ubuntu 22.04/22.05

USER="guest"
HOMEDIR="/home/$USER"
DATADIR="$HOMEDIR/data"
SSHD_CONFIG="/etc/ssh/sshd_config"

echo "=== Creating user $USER ==="
if id "$USER" &>/dev/null; then
    echo "User $USER already exists, skipping creation."
else
    sudo adduser --disabled-password --gecos "" "$USER"
    echo "User $USER created."
fi

echo "=== Removing extra privileges ==="
sudo deluser "$USER" sudo 2>/dev/null
sudo deluser "$USER" adm 2>/dev/null

echo "=== Configuring SFTP jail ==="
# Backup sshd_config
if [ ! -f "${SSHD_CONFIG}.bak" ]; then
    sudo cp "$SSHD_CONFIG" "${SSHD_CONFIG}.bak"
    echo "Backup created: ${SSHD_CONFIG}.bak"
fi

# Add configuration block if not already present
if ! grep -q "Match User $USER" "$SSHD_CONFIG"; then
    cat <<EOL | sudo tee -a "$SSHD_CONFIG"

# SFTP configuration for $USER
Match User $USER
    ForceCommand internal-sftp
    ChrootDirectory $HOMEDIR
    AllowTcpForwarding yes
    X11Forwarding no
    PasswordAuthentication no
EOL
    echo "sshd_config updated."
else
    echo "sshd_config block for $USER already exists."
fi

echo "=== Setting directory permissions ==="
sudo chown root:root "$HOMEDIR"
sudo chmod 755 "$HOMEDIR"

if [ ! -d "$DATADIR" ]; then
    sudo mkdir "$DATADIR"
fi
sudo chown "$USER:$USER" "$DATADIR"

echo "=== Disabling shell (SFTP only) ==="
sudo usermod -s /usr/sbin/nologin "$USER"

echo "=== Restarting SSH service ==="
sudo systemctl restart ssh

echo "Configuration completed successfully."

Execution Procedure

  1. Save the script to a file named create_guest_sftp.sh.
  2. Assign execution permission to the file:
    chmod +x create_guest_sftp.sh
  3. Execute the script:
    ./create_guest_sftp.sh

Upon successful execution, the guest account will be ready for SFTP-only access.


Directory and Permission Structure

The final directory structure is as follows:

  • /home/guest
    • Owned by root:root with permissions 755.
    • Serves as the chroot base, preventing the user from accessing paths outside this directory.
  • /home/guest/data
    • Owned by guest:guest.
    • This is the only writable location available to the user, ensuring controlled file exchange.

These permissions are critical, as OpenSSH requires the chroot directory (/home/guest) to be owned by root and not writable by the restricted user.


Security Considerations

  • No Shell Access: By assigning /usr/sbin/nologin, the user cannot initiate shell sessions.
  • No Sudo Privileges: Group memberships such as sudo and adm are explicitly removed.
  • Key-Based Authentication: Password authentication is disabled for the guest user, encouraging the use of SSH keys for improved security.
  • Limited Forwarding: Although TCP forwarding is allowed in this configuration, administrators may set AllowTcpForwarding no if forwarding is unnecessary.
  • Configuration Backup: The script automatically creates a backup of /etc/ssh/sshd_config before applying modifications.

Restoration Procedure

If it becomes necessary to revert to the previous SSH configuration, the backup can be restored as follows:

sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
sudo systemctl restart ssh

Conclusion

This configuration establishes a secure and minimal environment for controlled SFTP access. By enforcing a chroot jail, disabling shell access, and applying strict permission policies, the guest account is effectively limited to file transfer operations only. This approach is particularly well-suited to scenarios such as managed hosting, controlled uploads, and environments where external collaborators require data exchange capabilities without broader system access.

@michele-tn
Copy link
Author

Updated Script.

#!/bin/bash
#
# Script to create a secure guest SFTP-only user on Ubuntu 22.04/22.05
# Automatically sets up SSH public key authentication for the guest user.

USER="guest"
HOMEDIR="/home/$USER"
DATADIR="$HOMEDIR/data"
SSHD_CONFIG="/etc/ssh/sshd_config"
PUBKEY_SOURCE="/root/guest_id_rsa.pub"

echo "=== Creating user $USER ==="
if id "$USER" &>/dev/null; then
    echo "User $USER already exists, skipping creation."
else
    sudo adduser --disabled-password --gecos "" "$USER"
    echo "User $USER created."
fi

echo "=== Removing extra privileges ==="
sudo deluser "$USER" sudo 2>/dev/null
sudo deluser "$USER" adm 2>/dev/null

echo "=== Configuring SFTP jail ==="
# Backup sshd_config
if [ ! -f "${SSHD_CONFIG}.bak" ]; then
    sudo cp "$SSHD_CONFIG" "${SSHD_CONFIG}.bak"
    echo "Backup created: ${SSHD_CONFIG}.bak"
fi

# Add configuration block if not already present
if ! grep -q "Match User $USER" "$SSHD_CONFIG"; then
    cat <<EOL | sudo tee -a "$SSHD_CONFIG"

# SFTP configuration for $USER
Match User $USER
    ForceCommand internal-sftp
    ChrootDirectory $HOMEDIR
    AllowTcpForwarding yes
    X11Forwarding no
    PasswordAuthentication no
EOL
    echo "sshd_config updated."
else
    echo "sshd_config block for $USER already exists."
fi

echo "=== Setting directory permissions ==="
sudo chown root:root "$HOMEDIR"
sudo chmod 755 "$HOMEDIR"

if [ ! -d "$DATADIR" ]; then
    sudo mkdir "$DATADIR"
fi
sudo chown "$USER:$USER" "$DATADIR"

echo "=== Setting up SSH key authentication for guest ==="
if [ -f "$PUBKEY_SOURCE" ]; then
    sudo mkdir -p "$HOMEDIR/.ssh"
    sudo chmod 700 "$HOMEDIR/.ssh"
    sudo cp "$PUBKEY_SOURCE" "$HOMEDIR/.ssh/authorized_keys"
    sudo chmod 600 "$HOMEDIR/.ssh/authorized_keys"
    sudo chown -R "$USER:$USER" "$HOMEDIR/.ssh"
    echo "Public key installed for $USER."
else
    echo "Warning: Public key file $PUBKEY_SOURCE not found. Skipping key installation."
fi

echo "=== Disabling shell (SFTP only) ==="
sudo usermod -s /usr/sbin/nologin "$USER"

echo "=== Restarting SSH service ==="
sudo systemctl restart ssh

echo "Configuration completed successfully."

@michele-tn
Copy link
Author

michele-tn commented Oct 4, 2025

sudo mkdir -p /home/guest/.ssh
sudo chmod 700 /home/guest/.ssh
sudo chown guest:guest /home/guest/.ssh

sudo cp /root/id_rsa.pub /home/guest/.ssh/authorized_keys
sudo chmod 600 /home/guest/.ssh/authorized_keys
sudo chown guest:guest /home/guest/.ssh/authorized_keys

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment