Browse Source

Add working phpfpm config for first few users

vhosts
m1cr0man 1 year ago
parent
commit
4788d5fcd1
8 changed files with 106 additions and 29 deletions
  1. +1
    -0
      .gitignore
  2. +9
    -0
      README.md
  3. +3
    -1
      common/variables.nix
  4. +18
    -6
      services/httpd/default.nix
  5. +21
    -0
      services/httpd/httpd-skip-setuid.patch
  6. +25
    -6
      services/httpd/ldap2nix.py
  7. +25
    -11
      services/httpd/php-fpm.nix
  8. +4
    -5
      services/httpd/vhosts.nix

+ 1
- 0
.gitignore View File

@@ -2,3 +2,4 @@
*.code-*
/configuration.nix
/nixpkgs
users.nix

+ 9
- 0
README.md View File

@@ -12,3 +12,12 @@ git clone $THIS_REPO .
ln -s hosts/$(hostname)/configuration.nix .
nixos-rebuild switch
```

## Deploying Apache/httpd

`users.nix` needs to be generated before deploying Apache. Use this command:

```bash
cd services/httpd
ldapsearch -b o=redbrick -h ldap.internal -xLLL objectClass=posixAccount uid homeDirectory gidNumber | python3 ldap2nix.py /storage/webtree/ > users.nix
```

+ 3
- 1
common/variables.nix View File

@@ -1,4 +1,4 @@
{
rec {
tld = "redbricktest.ml";

certsDir = "/var/lib/acme";
@@ -6,6 +6,8 @@
webtreeDir = "/storage/webtree";
homesDir = "/storage/home";

userWebtree = uid: "${webtreeDir}/${builtins.substring 0 1 uid}/${uid}";

dovecotHost = "192.168.0.135";
dovecotSaslPort = 3659;
dovecotLmtpPort = 24;


+ 18
- 6
services/httpd/default.nix View File

@@ -1,6 +1,7 @@
{ config, pkgs, ... }:
let
common = import ../../common/variables.nix;
vhosts = import ./vhosts.nix;
vhosts = import ./vhosts.nix { inherit config; };

# Define a base vhost for all TLDs. This will serve only ACME on port 80
# Everything else is promoted to HTTPS
@@ -27,7 +28,6 @@ let
documentRoot = "${common.webtreeDir}/redbrick/htdocs";
listen = [{ port = 443; }];
enableSSL = true;
extraModules = [ "suexec" ];
extraConfig = ''
Options Includes Indexes SymLinksIfOwnerMatch MultiViews ExecCGI

@@ -46,16 +46,30 @@ in {
./php-fpm.nix
];

# Enable suexec support
nixpkgs.overlays = [
(self: super: {
apacheHttpd = super.apacheHttpd.overrideAttrs (oldAttrs: {
patches = [ ./httpd-skip-setuid.patch ];
configureFlags = [ "--enable-suexec" ] ++ oldAttrs.configureFlags;
});
})
];

# NixOS has strict control over setuid
security.wrappers.suexec.source = "${pkgs.apacheHttpd.out}/bin/suexec";

services.httpd = {
enable = true;
extraModules = [ "suexec" "proxy" "proxy_fcgi" ];
adminAddr = "admins+httpd@${common.tld}";
multiProcessingModule = "event";
maxClients = 250;
sslServerKey = "${common.certsDir}/${common.tld}/key.pem";
sslServerCert = "${common.certsDir}/${common.tld}/fullchain.pem";

user = "root";
group = "root";
# user = "root";
# group = "root";

extraConfig = ''
ProxyRequests off
@@ -65,8 +79,6 @@ in {
AddHandler cgi-script .cgi
AddHandler cgi-script .py
AddHandler cgi-script .sh
AddHandler x-httpd-php .php
AddHandler x-httpd-php .php3
AddHandler server-parsed .shtml
AddHandler server-parsed .html



+ 21
- 0
services/httpd/httpd-skip-setuid.patch View File

@@ -0,0 +1,21 @@
diff --git a/Makefile.in b/Makefile.in
index 21c76f8..3e23164 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -278,14 +278,10 @@ install-suexec-binary:
fi
install-suexec-setuid: install-suexec-binary
- @if test -f $(builddir)/support/suexec; then \
- chmod 4755 $(DESTDIR)$(sbindir)/suexec; \
- fi
+ true
install-suexec-caps: install-suexec-binary
- @if test -f $(builddir)/support/suexec; then \
- setcap 'cap_setuid,cap_setgid+pe' $(DESTDIR)$(sbindir)/suexec; \
- fi
+ true
suexec:
cd support && $(MAKE) suexec

+ 25
- 6
services/httpd/ldap2nix.py View File

@@ -1,6 +1,11 @@
#!/usr/bin/env python3
# Redbrick - m1cr0man 2019
# stdin: ldif formatted user data with uid, homeDirectory and gidNumber fields
# stdout: Nix formatted list of user attrsets
# Make sure to run on a host with LDAP set up or everyone will have gid nobody
import functools
import os.path
import subprocess
import sys

def user2nix(uid: str, home: str, gid: str) -> str:
@@ -8,12 +13,20 @@ def user2nix(uid: str, home: str, gid: str) -> str:
' {',
f' uid = "{uid}";',
f' home = "{home}";',
f' gid = {gid};',
f' gid = "{gid}";',
' }'
])


def main():
@functools.lru_cache(maxsize=128)
def get_gid_from_number(gid: str) -> str:
group_query = subprocess.run(f'getent group {gid}', shell=True, encoding='utf8', stdout=subprocess.PIPE)
if group_query.returncode > 0:
return 'nobody'
return group_query.stdout.split(':')[0]


def main(webtree: str):
num_users = 0

print('[')
@@ -29,11 +42,14 @@ def main():
elif key == 'homeDirectory':
home = val
elif key == 'gidNumber':
gid = val
gid = get_gid_from_number(val)

if uid and home and gid:
print(user2nix(uid=uid, home=home, gid=gid))
num_users += 1
if os.path.exists(f'{webtree}/{uid[0]}/{uid}'):
print(user2nix(uid=uid, home=home, gid=gid))
num_users += 1
else:
print(f'Skipping {uid}: missing webtree', file=sys.stderr)
uid = home = gid = ''

print(']')
@@ -42,4 +58,7 @@ def main():


if __name__ == '__main__':
main()
if len(sys.argv) < 2:
print(f'Usage: {sys.argv[0]} webtree_path')
sys.exit(1)
main(sys.argv[1])

+ 25
- 11
services/httpd/php-fpm.nix View File

@@ -1,17 +1,31 @@
{ lib, ... }:
let
common = import ../../common/variables.nix;
users = import ./users.nix;

extraPools = with builtins; concatStringsSep "\n" (map (user: ''
[${replaceStrings ["global" "sharedfpm"] ["global_user" "sharedfpm_user"] user.uid}]
listen = /run/phpfpm/${user.uid}.sock
listen.owner = wwwrun
listen.group = wwwrun
chdir = ${common.userWebtree user.uid}
user = ${user.uid}
group = ${user.gid}
pm = ondemand
pm.process_idle_timeout = 1m
pm.max_children = 5
'') (lib.take 10 users));
in {
services.phpfpm.pools = with builtins; listToAttrs (map (user: {
name = user.uid;
value = {
user = user.uid;
group = user.gid;
settings = {
"pm" = "ondemand";
"pm.process_idle_timeout" = "1m";
"chdir" = user.home;
};
services.phpfpm.pools.sharedfpm = with builtins; {
user = "wwwrun";
group = "wwwrun";
settings = {
"pm" = "dynamic";
"pm.start_servers" = 10;
"pm.max_children" = 75;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 10;
};
}) users);
extraConfig = extraPools;
};
}

+ 4
- 5
services/httpd/vhosts.nix View File

@@ -11,7 +11,6 @@ let
inherit hostName documentRoot;
enableSSL = true;
serverAliases = [ "www.${hostName}" ];
extraModules = [ "suexec" ];
extraConfig = ''
Options ExecCGI Includes Indexes SymLinksIfOwnerMatch
'';
@@ -41,12 +40,11 @@ let
# This is appended at the bottom
# to ensure that custom vhosts take preference
userVhosts = builtins.map (user: let
documentRoot = "${webtree}/${builtins.substring 0 1 user.uid}/${user.uid}";
documentRoot = common.userWebtree user.uid;
in {
inherit documentRoot;
hostName = "${user.uid}.${tld}";
enableSSL = true;
extraModules = [ "suexec" ];
extraConfig = ''
<Directory "${documentRoot}">
AllowOverride AuthConfig FileInfo Indexes Limit AuthConfig Options=ExecCGI,Includes,IncludesNoExec,Indexes,MultiViews,SymlinksIfOwnerMatch
@@ -55,8 +53,8 @@ let
</Directory>

Options ExecCGI Includes Indexes SymLinksIfOwnerMatch
<FilesMatch \.php$>
SetHandler "proxy:unix:${config.services.phpfpm."${user.uid}".socket}|fcgi://localhost/"
<FilesMatch \.php3?$>
SetHandler "proxy:unix:/run/phpfpm/${user.uid}.sock|fcgi://localhost/"
</FilesMatch>
'';
}) users;
@@ -159,6 +157,7 @@ in [
(vhostRedirect "helpdesk.${tld}" "https://wiki.redbrick.dcu.ie/mw/Helpdesk")
(vhostRedirect "helpdeskexam.${tld}" "https://md.redbrick.dcu.ie/s/SJzip7F9X#")
(vhostRedirect "hoodies.${tld}" "https://redbrickdcu.typeform.com/to/Q4uIzR")
(vhostRedirect "parlour.${tld}" "http://www.songsfromtheparlour.com")
(vhostRedirect "radio.theinternets.be" "http://radio.redbrick.dcu.ie")
(vhostRedirect "techweek.${tld}" "https://techweek.dcu.ie")
(vhostRedirect "tickets.${tld}" "https://dcusu.ticketsolve.com/shows/873599383/events/128190598")


Loading…
Cancel
Save