bring on more tildes hopefully

This commit is contained in:
deepend committed 2026-10-22 10:10:41 -06:00
1 parent c4d72ea94b
commit 109dda05c6
32 files changed
+2239 -1159

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
# Configuration examples
These are starting configurations for a **new** host. They are not a dump of
tilde.club's live configs and are not installed by applying the repository patch.
Replace example domains and accounts, read the linked chapter, and validate on
the target host before reloading a service.
| File | Context | Instructions |
| --- | --- | --- |
| `ssh/00-tilde.conf` | Global sshd config/drop-in | [SSH](../docs/ssh.md) |
| `nginx/tilde-static.conf` | nginx `http` context | [Web](../docs/web.md) |
| `nginx/member-php.inc` | nginx server block; ordering matters | [PHP](../docs/web.md#add-php-with-a-deliberate-execution-identity) |
| `php-fpm/member.conf` | PHP-FPM pool | [PHP](../docs/web.md#add-php-with-a-deliberate-execution-identity) |
| `dovecot/tilde.conf` | Standalone Dovecot 2.4 config | [Mail](../docs/mail.md) |
| `postfix/main.cf.fragment` | Merge into Postfix `main.cf` | [Mail](../docs/mail.md) |
| `postfix/master.cf.fragment` | Merge named submission services | [Mail](../docs/mail.md) |
| `gemserv/config.toml` | Version-matched Gemini configuration | [Publishing](../docs/publishing.md) |
| `gemserv/gemserv.service` | systemd service for the new-host layout | [Publishing](../docs/publishing.md) |
| `borgmatic/config.yaml` | borgmatic 2.x with Borg 1.x | [Backups](../docs/backups.md) |
The mail fragments deliberately do not overwrite distribution service entries,
install credentials, or open firewall ports. The backup example needs a remote
repository, protected passphrase file, and prepared database dumps.
+22
View File
@@ -0,0 +1,22 @@
# NEW-HOST example: borgmatic 2.x and Borg 1.x. See docs/backups.md.
source_directories:
- /home
- /etc
- /usr/local
- /usr/share/nginx
- /srv
- /var/backups/tilde-databases
source_directories_must_exist: true
repositories:
- path: ssh://backup@backup.example.net/./tilde
label: offsite
encryption_passcommand: cat /root/.config/borg/passphrase
compression: zstd,3
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
checks:
- name: repository
frequency: 1 week
- name: archives
frequency: 1 month
+52
View File
@@ -0,0 +1,52 @@
# Standalone NEW-HOST example for Dovecot 2.4 and local Unix accounts.
# Replace domain/cert paths and review the distro's /etc/pam.d/dovecot.
dovecot_config_version = 2.4.0
dovecot_storage_version = 2.4.0
protocols {
imap = yes
lmtp = yes
}
auth_mechanisms = plain login
auth_username_format = %{user | username | lower}
passdb pam {
service_name = dovecot
}
userdb passwd {
}
mail_home = /home/%{user | username}
first_valid_uid = 1000
mail_driver = maildir
mail_path = ~/.mail
ssl = required
ssl_min_protocol = TLSv1.2
ssl_server_cert_file = /etc/letsencrypt/live/tilde.example.net/fullchain.pem
ssl_server_key_file = /etc/letsencrypt/live/tilde.example.net/privkey.pem
namespace inbox {
inbox = yes
separator = /
}
service auth {
unix_listener /var/spool/postfix/private/auth {
user = postfix
group = postfix
mode = 0660
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
mode = 0600
}
}
protocol lmtp {
postmaster_address = postmaster@tilde.example.net
mail_plugins {
sieve = yes
}
}
sieve_script personal {
driver = file
path = ~/sieve
active_path = ~/.dovecot.sieve
}
+14
View File
@@ -0,0 +1,14 @@
# New-host example using the published gemserv interface/[[server]] schema.
# Confirm compatibility with your reviewed source revision before deployment.
interface = ["[::]:1965"]
log = "info"
[[server]]
hostname = "tilde.example.net"
dir = "/srv/gemini/content"
cert = "/etc/gemserv/cert.pem"
key = "/etc/gemserv/key.pem"
index = "index.gmi"
lang = "en"
usrdir = true
cgi = false
+20
View File
@@ -0,0 +1,20 @@
[Unit]
Description=Gemini publishing
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=gemini
Group=gemini
WorkingDirectory=/srv/gemini
ExecStart=/usr/local/sbin/gemserv /etc/gemserv/config.toml
Restart=on-failure
RestartSec=5s
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=read-only
[Install]
WantedBy=multi-user.target
+31
View File
@@ -0,0 +1,31 @@
# In the server block: AFTER dotfile denial, BEFORE generic script denial.
# Enable only after installing and testing the matching member FPM pool.
location ~ ^/(?:~|u/)member/(?<member_php_script>.+\.php)$ {
# try_files changes $uri; retain the original public script URL for PHP.
set $member_php_uri $uri;
root /home/member/public_html;
disable_symlinks on;
try_files /$member_php_script =404;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME /home/member/public_html/$member_php_script;
fastcgi_param SCRIPT_NAME $member_php_uri;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $member_php_uri;
fastcgi_param DOCUMENT_ROOT /home/member/public_html;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTP_PROXY "";
fastcgi_pass unix:/run/php-fpm/tilde-member.sock;
}
+39
View File
@@ -0,0 +1,39 @@
# HTTP bootstrap for a new host. Replace the domain, then add TLS.
# This file belongs inside nginx's http context, e.g. /etc/nginx/conf.d/.
server {
listen 80;
listen [::]:80;
server_name tilde.example.net;
root /usr/share/nginx/html;
index index.html;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/letsencrypt;
default_type text/plain;
try_files $uri =404;
}
# These precede the userdir regex so private files are denied there too.
location ~ (^|/)\. {
return 404;
}
# A static-only host must not download executable script source as text.
location ~* \.(?:php[0-9]*|phtml|phar|cgi|pl|py|sh|lua)(?:/|$) {
return 404;
}
location ~ "^/(?:~|u/)(?<tilde_user>[a-z_][a-z0-9_-]{0,31})(?<tilde_path>/.*)?$" {
alias /home/$tilde_user/public_html$tilde_path;
index index.html index.htm;
autoindex off;
disable_symlinks on;
}
location / {
try_files $uri $uri/ =404;
}
}
+18
View File
@@ -0,0 +1,18 @@
[tilde-member]
user = member
group = member
listen = /run/php-fpm/tilde-member.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
pm = ondemand
pm.max_children = 3
pm.process_idle_timeout = 10s
pm.max_requests = 500
request_terminate_timeout = 60s
clear_env = yes
security.limit_extensions = .php
php_admin_value[memory_limit] = 128M
php_admin_flag[display_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[session.save_path] = /home/member/.local/state/php/sessions
+20
View File
@@ -0,0 +1,20 @@
# New-host fragment. Merge into main.cf; retain distro defaults not shown here.
myhostname = tilde.example.net
mydomain = tilde.example.net
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost
inet_interfaces = all
inet_protocols = all
mynetworks = 127.0.0.0/8 [::1]/128
relayhost =
home_mailbox = .mail/
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = no
smtpd_tls_auth_only = yes
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtpd_tls_cert_file = /etc/letsencrypt/live/tilde.example.net/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/tilde.example.net/privkey.pem
+14
View File
@@ -0,0 +1,14 @@
# Merge these named services into the existing master.cf, replacing duplicates.
# Keep the distribution's smtp, local, cleanup, qmgr, and other required services.
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
+20
View File
@@ -0,0 +1,20 @@
# New-host baseline. Install only after key login and sudo work.
# The actual main sshd config must include this file at global scope.
# Check first-value precedence and verify sshd -T before reloading.
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
GSSAPIAuthentication no
HostbasedAuthentication no
UsePAM yes
AuthenticationMethods publickey
PermitEmptyPasswords no
PermitUserEnvironment no
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
# Optional MFA belongs in a later Match block in the main configuration.
# See docs/ssh.md. Leave the distribution's subsystem configuration in place.