Jailspaces is an implementation of the webspace configuration described in my article „Secure webspaces with NGINX, PHP-FPM chroots and Let's Encrypt“.
It provides an easy-to-use solution to set up secure chrooted PHP webspaces with
php-fpm with a secure (A+ on Qualys SSL Labs)
TLS configuration out-of-the-box.
Table of contents
- Fully automated setup
- Automated and individual RSA key generation
- Automated and individual generation of Diffie–Hellman parameters
- Easy to use commandline interface
- Manage webspaces with one single commandline interface
- Safety first
- Automatic management of file permissions
- Each webspace runs in its own chroot jail
- PHP scripts will run as a separate user for each webspace
https) support with browser accepted certificates by Let's Encrypt for each webspace
TLSconfiguration for each webspace by default
- Easy certificate renewal
- You can still have individual
php-fpmconfigurations for each webspace. Just edit the files as you are used to.
For installation Debian 9 (Stretch) is recommended. If you want to run
Jailspaces on a different OS, you probably need to change some of the parameters in
/etc/jailspaces/js.conf. If you did this successfully, please contact me to share your configuration.
Jailspaces needs a specific system account which is used to manage the certificates. Run the following commands in order for installation.
root@webhost:~# apt-get install git sudo members python root@webhost:~# git clone https://github.com/diafygi/acme-tiny root@webhost:~# git clone https://github.com/68b32/jailspaces-js root@webhost:~# cp -r jailspaces-js/jailspaces /etc root@webhost:~# cp jailspaces-js/js /usr/local/sbin root@webhost:~# useradd -b /home -s /bin/bash -m certmanager root@webhost:~# cp jailspaces-js/env/certmanager /etc/sudoers.d root@webhost:~# cp jailspaces-js/env/acme_fallback.conf /etc/nginx/conf.d root@webhost:~# cp acme-tiny/acme_tiny.py /home/certmanager root@webhost:~# chmod o+x /home/certmanager/acme_tiny.py root@webhost:~# addgroup webspaceuser root@webhost:~# mkdir /home/www root@webhost:~# systemctl restart nginx root@webhost:~# js tls init
The initialization will create two 4098 bit
RSA keys for
NGINX and Let's Encrypt and a 4098 bit Diffie–Hellman group. These operations might take some time to finish. You will get recompensed for your time with a state-of-the-art TLS configuration.
When this is done, you can start creating webspaces.
js is the commandline tool to manage your webspaces.
The simplest way to create a new webspace is to run
root@webhost:~# js create www000 example.com www.example.com
which will create a new webspace with two associated domains. It is important that
example.com already resolve to the IP address
nginx listens to, since Let's Encrypt will query the domains for ownership validation to sign the requested TLS certificates.
js status to list information of the created webspace
root@webhost:~# js status www000 USERNAME : www000 [OK] USERGROUP : www000 [OK] PHP-FPM-CHROOT : /data/user/www000/chroot [OK] PHP-FPM-POOL : /etc/php/7.0/fpm/pool.d/www000.conf [DISABLED] NGINX CONFIG : /etc/nginx/conf.d/www000.conf [DISABLED] FQDNs : 2 example.com www.example.com TLS CERTIFICATE : Exists, valid [OK] FILE PERMISSIONS: All correct [OK] CHROOT BINDS : All bound [OK]
After creation, the webspace is disabled by default. The chroot for this webspace is in
/home/user/www000/chroot, which contains a
data-www000 directory from where
nginx will serve files at the domains listed in
To enable the webspace run
root@webhost:~# js enable www000
and point your browser to one of the listed domains. You will automatically get redirected to the secure
https version of the webspace. Click the link
Test SSL configuration to run a test on the TLS configuration. You should get the best rating of
js without arguments to get an overview of available commands. There are lots of commands available, but you probably will only need to use
list to manage your spaces.
root@webhost:~# js Usage: /usr/local/sbin/js <command> [<subcommand> [<subcommand>]] [<username>] [-n|-Y] <command> can be one of... list: List all usernames associated with webspaces create <username> [FQDN0 [FQDN1 [...]]]: Create a webspace associated with <username> with domains FQDN0 - FQDNn. If the domains are not provided from the commandline, they need to be provided interactively. status <username>: Show status of webspace associated with <username> enable <username> [-n]: Enable webspace associated with <username> -n prevents reload of services disable <username> [-n]: Disable webspace associated with <username> -n prevents reload of services delete <username> [-Y]: Delete webspace associated with <username>. If -Y is provided, none questions will be asked and the account and all data of this webspace will be deleted. fixperm <username>: Set permissions and ownerships in PHP-FPM chroot of <username> as defined in _PHP_FPM_CHROOT_DIRS binds list|status|bind|unbind|clean [-Y] <username>: list: List binds for <username> status: Show mount status of binds for <username> bind: Mount all binds for <username>'s chroot. Mountpoints will be created if they do not exist. unbind: Unmount all binds for <username>. clean [-Y]: Unmount all binds for <username> and delete mountpoints for binds. Without -Y it will just list the pathes that would be deleted and ask for confirmation interactively. binds systemd list|create|update|clean [-Y] These commands manage unit files for systemd to automatically create mountpoints for users on boot and mount binds for the user's chroots. list: List all systemd unit files managed by this script. create: Create systemd units for all users. update: Same as /usr/local/sbin/js binds systemd clean -Y && /usr/local/sbin/js binds systemd create This is idempotent and will bring the unitfiles in sync with the user's chroot binds. clean [-Y]: Delete all unit files managed by this script. Without -Y it will just list the pathes that would be deleted and ask for confirmation interactively. tls <subcommand> [<username>]: _LETS_ENCRYPT_ENABLE must be set to "true" to use these commands <subcommand> can be one of... init: Check preconditions and setup environment (directories, keys) for requesting TLS certificates using the "refresh" subcommand. refresh <username> [-n]: Request and apply certificate for webspace associated with <username> if no certificate is available, or if the actual certificate is expired or about to expire. -n prevents reload of services forcerefresh <username> [-n]: Same as "refresh" but always gets a new certificate -n prevents reload of services
root@webhost:~# js tls refresh <webspace>
will renew the certificate for the webspace if it is about to expire within 2 days (can be changed in
/etc/jailspaces/js.conf. You need to setup some monitoring / cronjob by your own to automate the renewal.
The chroots for the
PHP-FPM process are set up from the
_PHP_FPM_CHROOT_BIND configuration specified in
/etc/jailspaces/js.conf and can be extended for a specific chroot by placing a
bind.conf file in
/home/www/<username> listing additional binds.
The status command will show you that the new bind is missing
root@webhost:~# js status www000 [...] CHROOT BINDS : Binds missing [MISSING] /dev/random missing
to fix this run
root@webhost:~# js binds bind www000 Creating directory /data/user/www000/chroot/dev [DONE] Creating mountpoint /data/user/www000/chroot/dev/random (file) [DONE] Mount /data/user/www000/chroot/dev/random [DONE] Remount /data/user/www000/chroot/dev/random readonly [DONE]
After adding or removing any binds you need to update the
systemd configuration, so that the new binds will be set up on boot
root@webhost:~# js binds systemd update
Modifying NGINX or PHP-FPM configuration
To change the
PHP-FPM configuration of a certain webspace, just edit the according file in
/etc/php/7.0/fpm/pool.d/<username>.conf and re-enable the webspace.
root@webhost:~# js disable <username> root@webhost:~# js enable <username>