This is a document detailing our current webserver setup. It is intended to help anyone wishing to improve or maintain our online infrastructure.
#!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority filter; # Allow loopback (local connections) iifname lo accept # Allow established/related ct state established,related accept # Allow incoming pings ip protocol icmp limit rate 2/second accept meta l4proto ipv6-icmp limit rate 2/second accept # Allow SSH and HTTP(s) tcp dport { ssh,http,https } accept # Drop everything else drop } chain forward { type filter hook forward priority filter; # Disallow forwarding drop } chain output { type filter hook output priority filter; # Allow all outgoing traffic accept } }
Generally follow the Crowdsec install instructions https://docs.crowdsec.net/docs/getting_started/install_crowdsec/.
Install the NFTables firewall bouncer sudo apt install crowdsec-firewall-bouncer-nftables
Install following the standard Debian instructions https://caddyserver.com/docs/install#debian-ubuntu-raspbian.
Configure PostgreSQL to listen on a unix socket:
postgresql.conf
port = 5432 unix_socket_directories = '/var/run/postgresql' unix_socket_group = 'pguser' unix_socket_permissions = 0770
Check that local connections are using peer authentication:
pg_hba.conf
# "local" is for Unix domain socket connections only local all all peer
wiki
/srv
with the same user and group.sudo chmod g+s /srv/wiki
rwx
with the following sudo setfacl -Rdm g::rwx /srv/wiki
Once created, the service can be cloned or copied into this folder.
There are two files required, a .socket
and a .service
file. These will be placed in /etc/systemd/system/
Example /etc/systemd/system/website.socket
[Unit] Description=gunicorn socket [Socket] ListenStream=/run/website.sock # Our service won't need permissions for the socket, since it # inherits the file descriptor by socket activation. # Only Caddy will need access to the socket: SocketUser=caddy SocketGroup=caddy # Once the user/group is correct, restrict the permissions: SocketMode=0660 [Install] WantedBy=sockets.target
Example /etc/systemd/system/website.service
[Unit] Description=website daemon Requires=website.socket After=network.target [Service] # gunicorn can let systemd know when it is ready Type=notify NotifyAccess=main # the specific user that our service will run as User=website Group=website RuntimeDirectory=website WorkingDirectory=/srv/website ExecStart=/srv/website/.venv/bin/gunicorn -w 2 'hackspace_website:create_app()' ExecReload=/bin/kill -s HUP $MAINPID KillMode=mixed TimeoutStopSec=5 PrivateTmp=true # if your app does not need administrative capabilities, let systemd know # ProtectSystem=strict [Install] WantedBy=multi-user.target
; Start a new pool named 'wiki'. ; the variable $pool can be used in any directive and will be replaced by the ; pool name ('wiki' here) [wiki] ; Unix user/group of the child processes. user = wiki group = wiki ; The address on which to accept FastCGI requests. listen = /run/php/wiki.sock ; Set permissions for unix socket, if one is used. listen.owner = caddy listen.group = caddy ;listen.mode = 0660 ; Choose how the process manager will control the number of child processes. pm = dynamic ; The number of child processes to be created when pm is set to 'static' and the ; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. pm.max_children = 5 ; The number of child processes created on startup. pm.start_servers = 2 ; The desired minimum number of idle server processes. pm.min_spare_servers = 1 ; The desired maximum number of idle server processes. pm.max_spare_servers = 3 ; The number of rate to spawn child processes at once. ;pm.max_spawn_rate = 32 ; Redirect worker stdout and stderr into main error log. catch_workers_output = yes ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com ;php_flag[display_errors] = off php_admin_value[error_log] = /var/log/fpm-php.wiki.log ;php_admin_flag[log_errors] = on ;php_admin_value[memory_limit] = 32M
Simple gunicorn based services can have a minimal reverse proxy:
bristolhackspace.org { log reverse_proxy unix//run/website.sock }
PHP services require a little more setup:
mosparo.bristolhackspace.org { encode gzip zstd root * /srv/mosparo/public route { try_files {path} /index.php } php_fastcgi unix//var/run/php/mosparo.sock file_server }
Some services such as the Wiki will require more complicated rewrite rules (generally services originally designed to run under Apache)
Some services will require a connection to the postgresql database. This is done via a unix socket with a set group. To give a service access:
pguser
group.postgresql+psycopg2://website@/website
replacing website
with your service name./var/run/postgresql
and port to 5432.