Nginx SSI

From time to time there is a need to host few small web pages. Instead of having some fancy CMS and even static site genrators we can use plain Nginx with Server Side Includes enabled.

Always forgetting things needs to be enabled for this to work, so decided to save small note

Here are sample configs

default.conf

server {
    location / {
        root /usr/share/nginx/html;
        ssi on;
    }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <!--# include file="/include/head.html" -->
    <title>HOME</title>
</head>
<body>
    <!--# include file="/include/header.html" -->
    <h1>HOME</h1>
    <!--# include file="/include/footer.html" -->
</body>
</html>

about/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <!--# include file="/include/head.html" -->
    <title>ABOUT</title>
</head>
<body>
    <!--# include file="/include/header.html" -->
    <h1>ABOUT</h1>
    <!--# include file="/include/footer.html" -->
</body>
</html>

include/header.html

<header>header</header>

And to run it just use

docker run -it --rm -p 8080:80 -v $PWD:/usr/share/nginx/html:ro -v $PWD/default.conf:/etc/nginx/templates/default.conf.template:ro nginx

With this in place home and about pages will be rendered with injected header and footer which will allow you to reuse code snippets between pages.

Also there is pretty cool idea on Nginx website - Dynamic SSI

Its advantage - you will have single layout file rather than including headers and footer, but on the other hand - you wont be able to modify things like page title.

Here is an modified example of how this may be done

server {
    charset utf-8;
    root /usr/share/nginx/html;
    ssi on;

    location / {
        set $inc $request_uri;
        if ($uri ~ ^/$) {
            set $inc '/home';
        }
        if (!-f $request_filename) {
            rewrite ^ /layout-home.html last;
        }
        if (!-f $document_root$inc.html) {
            return 404;
        }
    }
}

And layout

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home page</title>
</head>
<body>
   <header>header</header>
   <hr />
    <!--# include file="$inc.html" -->
    <hr />
    <footer>footer</footer>
</body>
</html>

If, for some reason, you still want to have markdowns, there is an module for this - ngx_markdown_filter_module, but to be fair not sure if that wors it - aka if you want markdown, then probably you want to render it once while deploying changes rather than rendering it on each request.

The beauty of such approach is that you have reusable snippets for repeated code, your pages are plain html, which means you are not limited by markdown and can do literally whatever you want and your web page still being simple static web site. The down side here is that you gonna need nginx to server it, so fara it seems that SSI is not supported by static web site hostings avaialble.