Last active
August 11, 2025 14:38
-
-
Save refringe/6545132 to your computer and use it in GitHub Desktop.
Nginx configuration file example for Sendy (http://sendy.co/).
This file contains hidden or 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
| server { | |
| listen 80; | |
| listen [::]:80; | |
| server_name domain.com; | |
| autoindex off; | |
| index index.php index.html; | |
| root /srv/www/domain.com/public; | |
| access_log /srv/www/domain.com/logs/access.log; | |
| error_log /srv/www/domain.com/logs/error.log; | |
| location / { | |
| try_files $uri $uri/ $uri.php?$args; | |
| } | |
| location /l/ { | |
| rewrite ^/l/([a-zA-Z0-9/]+)$ /l.php?i=$1 last; | |
| } | |
| location /t/ { | |
| rewrite ^/t/([a-zA-Z0-9/]+)$ /t.php?i=$1 last; | |
| } | |
| location /w/ { | |
| rewrite ^/w/([a-zA-Z0-9/]+)$ /w.php?i=$1 last; | |
| } | |
| location /unsubscribe/ { | |
| rewrite ^/unsubscribe/(.*)$ /unsubscribe.php?i=$1 last; | |
| } | |
| location /subscribe/ { | |
| rewrite ^/subscribe/(.*)$ /subscribe.php?i=$1 last; | |
| } | |
| location ~ \.php$ { | |
| try_files $uri =404; | |
| fastcgi_split_path_info ^(.+\.php)(/.+)$; | |
| fastcgi_pass unix:/var/run/php5-fpm.sock; | |
| fastcgi_index index.php; | |
| include fastcgi_params; | |
| } | |
| location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ { | |
| access_log off; | |
| log_not_found off; | |
| expires 30d; | |
| } | |
| } |
🛠 Handling Pretty URLs in Sendy with nginx
If links like /logout or /settings download a .php file instead of loading the page, nginx is serving the file as static content instead of executing it with PHP-FPM.
Fix: Catch-all rewrite for extensionless URLs
This config snippet rewrites /route to /route.php if the file exists, otherwise falls back to index.php. It works for all routes, so you don’t need separate rules for /login, /logout, /settings, etc.
# Normal routing: serve files/dirs, else hand off to @extless
location / {
try_files $uri $uri/ @extless;
}
# Handle extensionless routes
location @extless {
if (-f $document_root$uri.php) {
rewrite ^ /$uri.php last; # internal rewrite → PHP-FPM
}
rewrite ^ /index.php?$args last; # fallback
}
# PHP handler
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock; # adjust PHP version if needed
}
# Sendy tracking rewrites (keep existing)
location ~ ^/(l|t|w|(un)?subscribe)/ {
rewrite ^/([^/]+)/(.*)$ /$1.php?i=$2 last;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
🛠 Fixing the Sendy
/loginRedirect LoopIf you get stuck in an infinite
/login?redirect=login?redirect=login...loop in Sendy, here’s what worked for me:
1️⃣ Normalize the
/loginroute in nginxAdd these rules inside your Sendy server block to strip extra
redirectparams and point directly tologin.php:2️⃣ Seed the required DB tables
Sendy needs at least one user and one brand (
appsentry) to operate.3️⃣ Fix PHP session permissions
If PHP can’t write sessions, login state won’t persist.
4️⃣ Verify
APP_PATHin configIn
includes/config.php:✅ After these changes, the login loop stopped and I could access Sendy normally.