Jailspaces
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 nginx
and php-fpm
with a secure (A+ on Qualys SSL Labs) TLS
configuration out-of-the-box.
Table of contents
Feature overview
- 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
TLS
(https
) support with browser accepted certificates by Let's Encrypt for each webspace- A+
TLS
configuration for each webspace by default - Easy certificate renewal
- Flexible
- You can still have individual
nginx
andphp-fpm
configurations for each webspace. Just edit the files as you are used to.
Installation
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.
First install nginx
and php7.0-fpm
as described here and optimize your nginx configuration for enhanced security and better TLS performance.
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.
Manage 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 www.example.com
and 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.
Run 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 FQDNs
.
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 A+
.
Commandline interface
Run js
without arguments to get an overview of available commands. There are lots of commands available, but you probably will only need to use create
, status
, enable
, disable
, delete
and 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
Certificate management
The command
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.
Chroots
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.
- /data/user/www000/bind.conf
/dev/random
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 NGINX
or PHP-FPM
configuration of a certain webspace, just edit the according file in /etc/nginx/conf.d/<username>.conf
and /etc/php/7.0/fpm/pool.d/<username>.conf
and re-enable the webspace.
root@webhost:~# js disable <username> root@webhost:~# js enable <username>