Created
March 30, 2023 07:25
-
-
Save blueforesticarus/b4125319d5afbf1db6ebdc5466011c55 to your computer and use it in GitHub Desktop.
A nix config for apache, with all php files being sent to php-fpm. Also Perl. Also simple user/pass protection.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ config, pkgs, lib, ... }: | |
let | |
test_domain = "test.example.com"; | |
perlEnv = pkgs.perl.withPackages (p: with p; [ | |
CGI | |
]); | |
in | |
{ | |
environment.systemPackages = [ | |
pkgs.php | |
perlEnv | |
]; | |
# This is the lets encrypt config, this what generates free ssl certs | |
# https://nixos.org/manual/nixos/stable/#module-security-acme-nginx | |
security.acme = { | |
acceptTerms = true; | |
defaults = { | |
email = "foo@whatever.com"; | |
# This would enable a larger, more secure key, but I'm disabling for fear of older browsers | |
# default is ex256 https://go-acme.github.io/lego/usage/cli/options/ | |
# keyType = "ec384";/* */ | |
}; | |
}; | |
# setup apache, the webserver | |
# nginx is less cringe, but doesn't support .htaccess files, which myapp seems to need | |
services.httpd = { | |
enable = true; | |
enablePHP = false; # use php-fpm | |
enablePerl = true; | |
# run apache as example user to simplify permissions (XXX fixme) | |
user = "example"; | |
extraModules = [ | |
"proxy" | |
"proxy_fcgi" | |
{ name = "fastcgi"; path = "${pkgs.apacheHttpdPackages.mod_fastcgi}/modules/mod_fastcgi.so"; } | |
"actions" | |
]; | |
virtualHosts = { | |
# Lets make a second virtualhost for testing | |
"${test_domain}" = rec { | |
enableACME = true; # use Let's Encrypt config above for ssl cert | |
forceSSL = true; # force https (http will NOT load if true) | |
documentRoot = "/home/example/${test_domain}/public_html"; # seperate folder for the test site | |
# put the test version of the site behind a password | |
# apache is cringe https://httpd.apache.org/docs/2.4/howto/auth.html#gettingitworking | |
# note that for password it must be a Directory section NOT a Location section | |
extraConfig = '' | |
<Directory "${documentRoot}"> | |
AuthType Basic | |
AuthName "Restricted Content" | |
AuthBasicProvider file | |
AuthUserFile "/etc/httpd/passwd" | |
Require valid-user | |
Options +ExecCGI | |
AddHandler cgi-script .cgi | |
DirectoryIndex index.html index.cgi index.php | |
AllowOverride All | |
</Directory> | |
# linode of all places: https://www.linode.com/docs/guides/install-php-fpm-and-apache-on-debian-8/#before-you-begin | |
# I could not get the more often suggested ProxyMatch method to work | |
AddType application/x-httpd-fastphp8 .php | |
Action application/x-httpd-fastphp8 /php8-fcgi | |
Alias /php8-fcgi ${documentRoot}/php_dummy | |
FastCgiExternalServer ${documentRoot}/php_dummy -socket ${config.services.phpfpm.pools.myapp.socket} -pass-header Authorization | |
<Directory ${documentRoot}/php_dummy> | |
Require all granted | |
</Directory> | |
''; | |
}; | |
}; | |
}; | |
# put perl and sendmail in apache's search PATH | |
# TODO sendmail | |
systemd.services.httpd.path = [ perlEnv ]; | |
# login for test site password | |
# create with `htpasswd -c /etc/httpd/ admin` | |
environment.etc."httpd/passwd".text = "admin:<insert hash>"; | |
systemd.services."phpfpm-myapp" = { | |
serviceConfig.ProtectHome = lib.mkForce false; | |
}; | |
# forward all myapp php requests to phpfpm | |
services.phpfpm.pools.myapp = { | |
user = "example"; #run myapp as example, simple but not very advisable | |
group = "users"; | |
settings = { | |
pm = "dynamic"; | |
"listen.owner" = config.services.httpd.user; | |
# https://spot13.com/pmcalculator/ | |
"pm.max_children" = 2; | |
"pm.start_servers" = 1; | |
"pm.min_spare_servers" = 1; | |
"pm.max_spare_servers" = 1; | |
"pm.max_requests" = 500; | |
"catch_workers_output" = 1; | |
"php_flag[display_errors]" = "on"; | |
#"php_admin_value[error_log]" = "/var/log/php-fpm/default/error.log"; | |
"php_admin_flag[log_errors]" = "on"; | |
}; | |
phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; | |
}; | |
# Tweak to ensure web server starts AFTER networking is initialized, likely unnessecary | |
systemd.services.httpd = { | |
after = [ "network-online.target" ]; | |
wants = [ "network-online.target" ]; | |
}; | |
# install mysql (mariadb should be compatible) | |
services.mysql = { | |
enable = true; | |
package = pkgs.mariadb; | |
ensureUsers = [ | |
{ | |
# create mysql user with same name as our primary user "example" | |
# we don't set a password. apache/myapp.php run as example; mysql will allow passwordless local access if the username matches | |
name = "example"; | |
ensurePermissions = { | |
"*.*" = "ALL PRIVILEGES"; | |
}; | |
#TODO restrict permissions on other tables | |
} | |
]; | |
# create db "myappdb" if it does not exist | |
ensureDatabases = ["myappdb"]; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment