Setting up Chrooted SFTP and Isolated PHP 8.2 Environments on Debian 12 Bookworm for Multi-Developer Workflows
Prerequisites and Initial Setup
This guide assumes a fresh Debian 12 (Bookworm) installation with root or sudo access. We’ll be setting up isolated SFTP users, each confined to their own directory, and ensuring they can execute PHP 8.2 scripts within their chroot environment. This is crucial for multi-developer workflows where code separation and controlled access are paramount.
First, ensure your system is up-to-date and install necessary packages:
- OpenSSH server for SFTP functionality.
- PHP 8.2 and its FastCGI Process Manager (php-fpm) for script execution.
- Jailed (chrooted) SFTP utilities.
Execute the following commands:
Installing Required Packages
Update package lists and install OpenSSH, PHP 8.2 FPM, and the `openssh-server` package (which usually includes the necessary SFTP server components).
sudo apt update sudo apt upgrade -y sudo apt install -y openssh-server php8.2-fpm
Configuring OpenSSH for Chrooted SFTP
We need to modify the SSH daemon configuration to enable chrooting for SFTP users. This involves defining a subsystem for SFTP that uses `internal-sftp` and then creating a `Match Group` block to apply chroot restrictions to a specific group of users.
Edit the SSH daemon configuration file:
sudo nano /etc/ssh/sshd_config
Locate the line that defines the SFTP subsystem. If it exists, comment it out. If not, add the following lines to the end of the file:
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
AllowTCPForwarding no
X11Forwarding no
Explanation:
Subsystem sftp internal-sftp: This tells SSH to use its built-in SFTP server, which supports chrooting.Match Group sftpusers: This block applies the following directives only to users who are members of the `sftpusers` group.ChrootDirectory %h: This directive confines the user to their home directory (`%h`).ForceCommand internal-sftp: This ensures that only SFTP connections are allowed, preventing shell access.AllowTCPForwarding noandX11Forwarding no: These disable unnecessary and potentially insecure forwarding options.
After saving the changes, restart the SSH service:
sudo systemctl restart sshd
Creating SFTP Users and Directories
Now, let’s create a group for our SFTP users and then add individual users. We’ll also set up their chrooted directories.
Create the `sftpusers` group:
sudo groupadd sftpusers
For each developer, create a user. Let’s use `dev1` as an example. We’ll create their home directory, set ownership, and add them to the `sftpusers` group. The user’s home directory will serve as their chroot jail.
# Create the user sudo useradd -m -g sftpusers -s /usr/sbin/nologin dev1 # Set a password for the user sudo passwd dev1 # Create the chroot directory structure # The user's home directory will be their root. # We need a writable directory for uploads. sudo mkdir -p /home/dev1/uploads sudo chown root:root /home/dev1 sudo chmod 755 /home/dev1 sudo chown dev1:dev1 /home/dev1/uploads sudo chmod 755 /home/dev1/uploads
Important Note on Permissions: The chroot directory itself (/home/dev1 in this case) MUST be owned by root and not writable by any other user. If it’s writable by the SFTP user, the chroot will fail for security reasons. We create a subdirectory (uploads) within the chroot directory that the user *can* write to.
Repeat this process for each developer, replacing `dev1` with `dev2`, `dev3`, etc., and adjusting the home directory paths accordingly (e.g., /home/dev2).
Configuring PHP-FPM for Isolated Environments
To allow SFTP users to execute PHP scripts within their chrooted environment, we need to configure PHP-FPM to listen on a specific socket for each user and ensure these sockets are accessible. This is a more advanced setup that requires careful management of FPM pools.
We’ll create a separate FPM pool for each SFTP user. This provides isolation and allows for distinct PHP configurations per user if needed.
First, create a directory to hold the FPM pool configuration files:
sudo mkdir -p /etc/php/8.2/fpm/pool.d/sftp
Now, create a pool configuration file for `dev1`. This file will define how PHP-FPM handles requests for this user.
; /etc/php/8.2/fpm/pool.d/sftp/dev1.conf [dev1] user = dev1 group = dev1 listen = /run/php/php8.2-fpm-dev1.sock listen.owner = dev1 listen.group = sftpusers listen.mode = 0660 pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 chdir = /home/dev1
Explanation of the FPM Pool Configuration:
[dev1]: Defines the name of the pool.user = dev1andgroup = dev1: Specifies the user and group under which PHP processes will run for this pool. This is crucial for file permissions.listen = /run/php/php8.2-fpm-dev1.sock: The Unix socket path for this pool. Each user gets a unique socket.listen.owner = dev1,listen.group = sftpusers,listen.mode = 0660: Configures the permissions for the socket file, allowing the `dev1` user to connect and members of the `sftpusers` group to access it.pm.*: Standard process manager settings for controlling the number of PHP worker processes.chdir = /home/dev1: Sets the default working directory for PHP scripts executed by this pool to the user’s chrooted home directory.
Repeat this configuration for each SFTP user, creating a corresponding `.conf` file in `/etc/php/8.2/fpm/pool.d/sftp/` (e.g., `dev2.conf`, `dev3.conf`) and ensuring the `user`, `group`, `listen` socket path, and `chdir` directives are correctly set.
After creating all pool configurations, restart PHP-FPM:
sudo systemctl restart php8.2-fpm
Integrating SFTP with PHP-FPM via a Web Server (Nginx Example)
To enable users to run PHP scripts via a web server, we need to configure Nginx (or Apache) to proxy requests to the appropriate PHP-FPM socket based on the requested domain or path. For simplicity, we’ll assume each developer has a dedicated subdomain or a specific directory structure.
Let’s assume `dev1.example.com` should be handled by `dev1`’s FPM pool.
Create an Nginx server block configuration for `dev1`:
server {
listen 80;
server_name dev1.example.com;
root /home/dev1/public_html; # Or a specific web root within their chroot
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Use the specific FPM socket for dev1
fastcgi_pass unix:/run/php/php8.2-fpm-dev1.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to hidden files
location ~ /\.ht {
deny all;
}
}
Explanation of Nginx Configuration:
root /home/dev1/public_html;: Defines the web root for this developer. This directory must exist within their chrooted environment (e.g.,/home/dev1/public_html). Ensure the `dev1` user has write permissions here if they need to upload files via SFTP that will be served by the web server.fastcgi_pass unix:/run/php/php8.2-fpm-dev1.sock;: This is the critical part. It directs PHP requests for this server block to the specific FPM socket created for `dev1`.
Create the web root directory and set appropriate permissions:
sudo mkdir -p /home/dev1/public_html sudo chown dev1:dev1 /home/dev1/public_html sudo chmod 755 /home/dev1/public_html
Enable the site and test Nginx configuration:
sudo ln -s /etc/nginx/sites-available/dev1.conf /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
Repeat this Nginx configuration for each developer, adjusting `server_name`, `root`, and `fastcgi_pass` directives to match their respective subdomains/directories and FPM sockets.
Testing the Setup
1. SFTP Access: Use an SFTP client (like FileZilla or `sftp` command-line tool) to connect to your server using `dev1`’s credentials. Verify that you can only access the `/` directory (which is actually `/home/dev1` on the server) and upload files to the `/uploads` directory.
sftp dev1@your_server_ip # Expected output: # Connected to your_server_ip. # sftp> pwd # Remote working directory: / # sftp> ls # uploads # sftp> cd uploads # sftp> pwd # Remote working directory: /uploads # sftp> put test.txt # Uploading test.txt to /uploads/test.txt # test.txt 100% 0KB 0.0KB/s 00:00 # sftp> quit
2. PHP Execution: Create a simple PHP file in the web root (e.g., `/home/dev1/public_html/info.php`) with the following content:
<?php phpinfo(); ?>
Access this file via the web browser (e.g., http://dev1.example.com/info.php). You should see the PHP information page. Crucially, check the `$_SERVER[‘DOCUMENT_ROOT’]` and `$_SERVER[‘SCRIPT_FILENAME’]` variables within the `phpinfo()` output. They should reflect paths within the chrooted environment (e.g., `/home/dev1/public_html`).
This setup provides a robust, isolated environment for each developer, enhancing security and manageability for multi-developer projects on a single Debian 12 server.
Leave a Reply
You must be logged in to post a comment.