Skip to content

Instantly share code, notes, and snippets.

@lmbacelar
Last active August 19, 2022 08:39
Show Gist options
  • Save lmbacelar/8623961 to your computer and use it in GitHub Desktop.
Save lmbacelar/8623961 to your computer and use it in GitHub Desktop.
Arch Linux Nginx install ($JAIL chroot according to arch wiki). Use sudo perl nginx_install.pl. Uncomment # system($_[0]); line to perform actions.
#a/usr/bin/perl
# This script was hastily cobbled together for my own use. It can
# probably break your system. Use at your own risk.
$JAIL = "/srv/http";
$USER = "http";
$GROUP = "http";
$WWW_DIR = "www";
sub run{
# Only print the commands that will be executed until the user
# manually decides to run them.
print "$_[0]\n";
# system($_[0]);
}
# Nginx Standard Installation
run("pacman -S nginx --noconfirm");
# Create Necessary Folders / Symlinks
@dirs = ("etc/nginx/logs", "etc/nginx/sites", "dev", "usr/{lib,bin}", "usr/share/nginx",
"tmp", "run", "var/{log,lib}/nginx", $WWW_DIR, "$WWW_DIR/cgi-bin", "$WWW_DIR/apps");
foreach (@dirs) {
run("mkdir -p $JAIL/$_");
}
run("cd $JAIL; ln -s usr/lib lib");
run("cd $JAIL; ln -s usr/lib lib64; ln -s usr/lib usr/lib64");
# Create Necessary Devices
@devs = ("null c 1 3", "random c 1 8");
foreach (@devs) {
run("/usr/bin/mknod -m 0666 $JAIL/dev/$_");
}
# Mount $JAIL/tmp and $JAIL/run
run("/usr/bin/mknod -m 0444 $JAIL/dev/urandom c 1 9");
run("mount -t tmpfs none $JAIL/run -o 'noexec,size=1M'");
run("mount -t tmpfs none $JAIL/tmp -o 'noexec,size=100M'");
# Preserve the mounts across reboots
run("cat >> /etc/fstab <<TEXT
# nginx chroot mounts
tmpfs /srv/http/run tmpfs rw,noexec,relatime,size=1M 0 0
tmpfs /srv/http/tmp tmpfs rw,noexec,relatime,size=100M 0 0
TEXT");
# Populate the chroot
## Copy over the easy files
run("cp -r /usr/share/nginx/* $JAIL/usr/share/nginx/");
run("cp -r /usr/share/nginx/html/* $JAIL/$WWW_DIR");
run("cp /usr/bin/nginx $JAIL/usr/bin/");
run("cp -r /var/lib/nginx $JAIL/var/lib/nginx");
## Copy over required libraries
@ldds = split("\n", `ldd /usr/bin/nginx`);
foreach (@ldds) {
if(m/((\/.*)?\/lib\/.*) \(0x/){
run("cp $1 $JAIL$1");
}
}
run("cp /lib64/ld-linux-x86-64.so.2 $JAIL/lib");
## Copy over some misc
run("cp /usr/lib/libnss_* $JAIL/usr/lib/");
# /etc{adjtime,hosts.deny} might also be needed.
run("cp -Lrfv /etc/{services,localtime,nsswitch.conf,nscd.conf,protocols,hosts,ld.so.cache,ld.so.conf,resolv.conf,host.conf,nginx} $JAIL/etc");
# Write new nginx.conf
run("cat > $JAIL/etc/nginx/nginx.conf <<TEXT
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/sites/*;
}
TEXT");
# Create restricted user/group files for the chroot
run("echo 'http:x:33:' > $JAIL/etc/group");
run("echo 'nobody:x:99:' >> $JAIL/etc/group");
run("echo 'http:x:33:33:http:/:/bin/false' > $JAIL/etc/passwd");
run("echo 'nobody:x:99:99:nobody:/:/bin/false' >> $JAIL/etc/passwd");
run("echo 'http:x:14871::::::' > $JAIL/etc/shadow");
run("echo 'nobody:x:14871::::::' >> $JAIL/etc/shadow");
run("echo 'http:::' > $JAIL/etc/gshadow");
run("echo 'nobody:::' >> $JAIL/etc/gshadow");
run("touch $JAIL/etc/shells");
run("touch $JAIL/run/nginx.pid");
# Set very restrictive permissions
run("chown -R root:root $JAIL/");
run("chown -R $USER:$GROUP $JAIL/$WWW_DIR");
run("chown -R $USER:$GROUP $JAIL/etc/nginx");
run("chown -R $USER:$GROUP $JAIL/var/{log,lib}/nginx");
run("chown $USER:$GROUP $JAIL/run/nginx.pid");
#run("chown -R $USER:$GROUP $JAIL/usr/bin/nginx");
run("find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod -rw");
run("find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod +x");
#run("find $JAIL/ -gid 0 -uid 0 -type f -print | xargs chmod -x");
run("find $JAIL/etc -gid 0 -uid 0 -type f -print | xargs chmod -x");
#run("find $JAIL/usr/lib -gid 0 -uid 0 -type f -print | xargs chmod -x");
run("find $JAIL/usr/bin -type f -print | xargs chmod ug+rx");
run("find $JAIL/ -gid 33 -uid 33 -print | xargs chmod o-rwx");
run("chmod +rw $JAIL/tmp");
run("chmod +rw $JAIL/run");
# Give the chrooted executable permission to bind these ports without root
run("setcap 'cap_net_bind_service=+ep' $JAIL/usr/bin/nginx");
# Modify nginx.service to start chroot
run("cp /usr/lib/systemd/system/nginx.service /etc/systemd/system/nginx.service");
run("cat > /etc/systemd/system/nginx.service <<TEXT
[Unit]
Description=A high performance web server and a reverse proxy server
After=syslog.target network.target
[Service]
Type=forking
PIDFile=/srv/http/run/nginx.pid
ExecStartPre=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -t -q -g 'pid /run/nginx.pid; daemon on; master_process on;'
ExecStart=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;'
ExecReload=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;' -s reload
ExecStop=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid;' -s quit
[Install]
WantedBy=multi-user.target
TEXT");
# Get rid of the non-chrooted nginx installation
run("pacman -Rsc nginx --noconfirm");
# Starting Service
run("systemctl enable nginx");
run("systemctl start nginx");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment