Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Nginx configuration file example for Sendy (http://sendy.co/).
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;
}
}
@fabiopili

This comment has been minimized.

Copy link

@fabiopili fabiopili commented Mar 31, 2015

It'd be a good idea to add:

# Don't allow search engines to index any 
add_header X-Robots-Tag "noindex, noarchive";

before the first location / line to avoid search engines indexing the Sendy login page.

@kalelc

This comment has been minimized.

Copy link

@kalelc kalelc commented Mar 2, 2016

Hello, I have Nginx 1.4.6 with Sendy 2.0.7. With this configuration i get mod_rewrite is not enabled

@sergeifilippov

This comment has been minimized.

Copy link

@sergeifilippov sergeifilippov commented Mar 3, 2016

@kalelc php does is not able to detect mod_rewrite like functionality in nginx properly so it'll always say that but will continue working fine.

@viet

This comment has been minimized.

Copy link

@viet viet commented Apr 2, 2016

It's not really working for me. :\

@dillonbailey

This comment has been minimized.

Copy link

@dillonbailey dillonbailey commented Apr 9, 2016

@viet also not working for me, I've tried to start another thread with the Sendy admin...will see how we go.

@makecontact

This comment has been minimized.

Copy link

@makecontact makecontact commented Apr 21, 2016

Config works fine for me.

Incase you missed it remember to change the paths of the rewrite rules relative to your install e.g.

location /w/ { rewrite ^/w/([a-zA-Z0-9/]+)$ /w.php?i=$1 last; }

Might be:

location /sendy/w/ { rewrite ^/sendy/w/([a-zA-Z0-9/]+)$ /sendy/w.php?i=$1 last; }

Note THREE places where you must add the full path.

To be honest, I didn't want to risk this incase there are some direct links in emails and sendy's backend to worry about so I just installed it in the root folder - in which case the above config works fine.

@viettd

This comment has been minimized.

Copy link

@viettd viettd commented Jul 20, 2016

@viet, @dillonbailey I edit some config and it work for me:

location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
 }

Hope that work for you too.

P/S: I install sendy in subdomain.

@ahmadawais

This comment has been minimized.

Copy link

@ahmadawais ahmadawais commented Mar 17, 2017

It is hacky but works though it is not parsing the URLs. I cannot parse domain.tld/login and instead have to add domain.tld/login.php

@ahmadawais

This comment has been minimized.

Copy link

@ahmadawais ahmadawais commented Mar 17, 2017

This worked for me, make sure there are no other rules duplication or overlap

 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 php:9000;
     #     fastcgi_index index.php;
     #     include fastcgi_params;
     #     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     #     fastcgi_param PATH_INFO $fastcgi_path_info;
     # }

     location ~ \.php$ {
             try_files $uri =404;
             fastcgi_split_path_info ^(.+\.php)(/.+)$;
             fastcgi_pass 127.0.0.1:9000;
             fastcgi_index index.php;
             fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
             include fastcgi_params;
      }

@martingrega

This comment has been minimized.

Copy link

@martingrega martingrega commented Oct 25, 2017

Hey,
there is a bug in the config. You forgot to escape second dot.
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
should be
location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml)$ {

Our randomly generated tracking link ended with characters "pNg" and all links in newsletter stopped working.

@mj6uc

This comment has been minimized.

Copy link

@mj6uc mj6uc commented Nov 7, 2017

Thanks @perceptiveIO, your observation saved the day! :-)

@codegeek1001

This comment has been minimized.

Copy link

@codegeek1001 codegeek1001 commented Nov 29, 2017

For me, this one worked for prettifying urls

 location / {
        try_files $uri $uri/ /$uri.php?is_args$args;
}
@Lemmings19

This comment has been minimized.

Copy link

@Lemmings19 Lemmings19 commented Jul 11, 2018

Installing Sendy at https://mydomain.com/sendy, this worked for me:

    location /sendy {
        rewrite ^/sendy/(l|t|w)/([a-zA-Z0-9\/]+)$ /sendy/$1.php?i=$2&$args;
        rewrite ^/sendy/(u?n?subscribe)/(.*)$ /sendy/$1.php?i=$2&$args;
        try_files $uri $uri/ $uri.php?$args;

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }

If you're having issues, check https://mydomain.com//sendy/_compatibility.php?i=1 to see if anything isn't configured properly. mod_rewrite is not enabled will probably always show up if you're using Nginx.

@ttk

This comment has been minimized.

Copy link

@ttk ttk commented Aug 2, 2018

There is a bug on line 46 of the example code, the period needs to be escaped...

Should be:

location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
        access_log off;
        log_not_found off;
        expires 30d;
    }
@gnif

This comment has been minimized.

Copy link

@gnif gnif commented Sep 23, 2018

All these rewrites could be simplified to a single location match and rewrite like so:

location ~ ^\/(l|t|w|(un)?subscribe)\/ {
  rewrite ^\/([^/]+)\/(.+)$ "/$1.php?i=$2" last;
}
@saaiful

This comment has been minimized.

Copy link

@saaiful saaiful commented May 3, 2019

This configuration works for me in NGiNX.
https://gist.github.com/saaiful/6f0f32de64d5fccd793b3ce5059c8bb2

@cartpauj

This comment has been minimized.

Copy link

@cartpauj cartpauj commented May 23, 2019

I tried a whole bunch of stuff. This is what finally worked for me (with certbot https). Sub-domain install of Sendy using nginx and SSL/TLS.

# Marketing (Sendy) Installation
#
server {
        root /var/www/marketing.site.com;

        index index.php index.html index.htm;

        server_name marketing.site.com;

        autoindex off;

        add_header X-Robots-Tag "noindex, noarchive";

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~ /\.  { deny all; log_not_found off; access_log off; return 404; }

        location / {
                try_files $uri $uri/ /$uri.php$is_args$args; # $is_args converts to a ? if true
        }

        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 /confirm/ {
                rewrite ^/confirm/(.*)$ /confirm.php?i=$1 last;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

        location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
                access_log off;
                log_not_found off;
                expires 30d;
        }

        # Added by certbot - remove these when copying this vhost to a new server block
        # listen [::]:443 ssl http2; # managed by Certbot
        listen 443 ssl http2; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/marketing.site.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/marketing.site.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
        if ($host = marketing.site.com) {
                return 301 https://$host$request_uri;
        } # managed by Certbot

        listen 80;
        # listen [::]:80;

        server_name marketing.site.com;
        return 404; # managed by Certbot
}
@informdev

This comment has been minimized.

Copy link

@informdev informdev commented Aug 12, 2019

Do we not need to exclude some things like scheduled.php ?

@sudo-shubham

This comment has been minimized.

Copy link

@sudo-shubham sudo-shubham commented Sep 10, 2019

I tried a whole bunch of stuff. This is what finally worked for me (with certbot https). Sub-domain install of Sendy using nginx and SSL/TLS.

# Marketing (Sendy) Installation
#
server {
        root /var/www/marketing.site.com;

        index index.php index.html index.htm;

        server_name marketing.site.com;

        autoindex off;

        add_header X-Robots-Tag "noindex, noarchive";

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~ /\.  { deny all; log_not_found off; access_log off; return 404; }

        location / {
                try_files $uri $uri/ /$uri.php$is_args$args; # $is_args converts to a ? if true
        }

        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 /confirm/ {
                rewrite ^/confirm/(.*)$ /confirm.php?i=$1 last;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

        location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
                access_log off;
                log_not_found off;
                expires 30d;
        }

        # Added by certbot - remove these when copying this vhost to a new server block
        # listen [::]:443 ssl http2; # managed by Certbot
        listen 443 ssl http2; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/marketing.site.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/marketing.site.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
        if ($host = marketing.site.com) {
                return 301 https://$host$request_uri;
        } # managed by Certbot

        listen 80;
        # listen [::]:80;

        server_name marketing.site.com;
        return 404; # managed by Certbot
}

I Love you man.

@joglomedia

This comment has been minimized.

Copy link

@joglomedia joglomedia commented Oct 4, 2019

Hello, I have Nginx 1.4.6 with Sendy 2.0.7. With this configuration i get mod_rewrite is not enabled

mod_rewrite is Apache module, so PHP running with Nginx will not able to detect it

I use LEMPer to deploy Sendy its quiet easy

@tucq88

This comment has been minimized.

Copy link

@tucq88 tucq88 commented Nov 8, 2019

https://gist.github.com/refringe/6545132#gistcomment-2925206

I tried a whole bunch of stuff. This is what finally worked for me (with certbot https). Sub-domain install of Sendy using nginx and SSL/TLS.

Worked with me, thanks @cartpauj

@dirbey

This comment has been minimized.

Copy link

@dirbey dirbey commented May 2, 2020

try this
`
autoindex off;

add_header X-Robots-Tag "noindex, noarchive";

location / {
    # try_files $uri $uri/ /index.php?$query_string;
    try_files $uri $uri/ /$uri.php?$query_string;
}

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/php/php7.3-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
    access_log off;
    log_not_found off;
    expires 30d;
}

location ~ /\.(?!well-known).* {
    deny all;
}`
@easynotedotcom

This comment has been minimized.

Copy link

@easynotedotcom easynotedotcom commented Nov 15, 2020

I tried a whole bunch of stuff. This is what finally worked for me (with certbot https). Sub-domain install of Sendy using nginx and SSL/TLS.

# Marketing (Sendy) Installation
#
server {
        root /var/www/marketing.site.com;

        index index.php index.html index.htm;

        server_name marketing.site.com;

        autoindex off;

        add_header X-Robots-Tag "noindex, noarchive";

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~ /\.  { deny all; log_not_found off; access_log off; return 404; }

        location / {
                try_files $uri $uri/ /$uri.php$is_args$args; # $is_args converts to a ? if true
        }

        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 /confirm/ {
                rewrite ^/confirm/(.*)$ /confirm.php?i=$1 last;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

        location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
                access_log off;
                log_not_found off;
                expires 30d;
        }

        # Added by certbot - remove these when copying this vhost to a new server block
        # listen [::]:443 ssl http2; # managed by Certbot
        listen 443 ssl http2; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/marketing.site.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/marketing.site.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
        if ($host = marketing.site.com) {
                return 301 https://$host$request_uri;
        } # managed by Certbot

        listen 80;
        # listen [::]:80;

        server_name marketing.site.com;
        return 404; # managed by Certbot
}

Just tested this and worked like a charm :) Thank you!

@alexgarciab

This comment has been minimized.

Copy link

@alexgarciab alexgarciab commented Nov 21, 2020

Thanks @cartpauj. In my case, what I needed to pay attention to was this:

location / {
                try_files $uri $uri/ /$uri.php$is_args$args;
        }
@amanjuman

This comment has been minimized.

Copy link

@amanjuman amanjuman commented Jul 11, 2021

location ~ ^/(l|t|w|(un)?subscribe)/ {
rewrite ^/([^/]+)/(.+)$ "/$1.php?i=$2" last;
}

Correction

location ~ ^\/(l|t|w|confirm|(un)?subscribe)\/
{
	rewrite ^\/([^/]+)\/(.+)$ "/$1.php?i=$2" last;
}
@ulfie22

This comment has been minimized.

Copy link

@ulfie22 ulfie22 commented Aug 29, 2021

Here is a working config for Sendy v5.2.3 and Forge as of 8-28-2021

(1) change "yourdomain.com" to your domain
(2) note that you should use this to get the site installed, then add SSL in Forge, then make sure your sendy includes/config.php file uses "https://" in the APP_PATH

# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/sendy.yourdomain.com/before/*;

server {
    listen 80;
    listen [::]:80;
    server_name sendy.yourdomain.com;
    root /home/forge/sendy.yourdomain.com/;

    # FORGE SSL (DO NOT REMOVE!)
    # ssl_certificate;
    # ssl_certificate_key;
    
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!3DES';
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/nginx/dhparams.pem;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    autoindex off;

    index index.html index.htm index.php;

    charset utf-8;

    # FORGE CONFIG (DO NOT REMOVE!)
    include forge-conf/sendy.yourdomain.com/server/*;

        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 = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/sendy.yourdomain.com-error.log error;

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/sendy.yourdomain.com/after/*;


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment