sablierapp / sablier

Start your containers on demand, shut them down automatically when there's no activity. Docker, Docker Swarm Mode and Kubernetes compatible.
https://sablierapp.dev/
GNU Affero General Public License v3.0
1.46k stars 50 forks source link

Create Middleware for Swag #110

Open rubylaser opened 2 years ago

rubylaser commented 2 years ago

I’ve been searching for something exactly like this to use with my Swag proxy. I hope that you can create middleware for it that would allow me to lazy load some of my over 50 running containers.

EmberLightVFX commented 1 year ago

+1 on Swag support

github-actions[bot] commented 9 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

acouvreur commented 5 months ago

Duplicate issue infos:

Describe the reverse proxy you'd like LinuxServer.io's reverse proxy SWAG is getting bigger and bigger and with included Fail2Ban + CrowdSec plugin it's the reverse proxy that me and many others have picked for ease to setup and security. It takes care of your certs and your ddns etc. A really powerful reverse proxy.

Does the reverse proxy provides middleware/module/extension support SWAG have a plugin/mod system, all open source, so the sablier implementation could be a simple mod. You can find the CrowdSec plugin here to see how it's build up: https://github.com/linuxserver/docker-mods/tree/swag-crowdsec

Additional context You can find more info about SWAG here: https://docs.linuxserver.io/general/swag

ykrasik commented 1 week ago

I got this to work some time ago with SWAG through NJS. I'm a bit fuzzy on the exact details at this point, so I hope I don't miss anything.

1. Enable NJS modules in SWAG

In order to install the NJS plugin for SWAG, we're going to need the universal-package-install docker mod.

With it we can install the NJS plugin by passing in an env variable: INSTALL_PACKAGES=nginx-mod-http-js

Everything together looks like this in your docker-compose:

environment:
  - DOCKER_MODS=linuxserver/mods:universal-package-install
  - INSTALL_PACKAGES=nginx-mod-http-js

2. Setup NGINX mostly according to the guide

The next part is similar to the setup guide for NGINX, with the exception that there is no need to load the NJS plugin (load_module modules/ngx_http_js_module.so;), its done for us by universal-package-install from step 1.

Download sablier.js and put it somewhere you'll be able to mount it to SWAG. I have a separate Sablier folder next to SWAG, so the relevant section from my SWAG's docker-compose looks like this, adjust to your structure:

volumes:
  - ../sablier/config/sablier.js:/etc/nginx/conf.d/sablier.js

Now we need to import sablier.js - I added it to site-confs/default.conf at the top, similar to the guide:

js_import conf.d/sablier.js;

3. Prepare NGINX scripts

I wanted to use Sablier like SWAG uses Authelia, so I created a similar set of scripts. I put them next to /config/nginx/authelia-location.conf. Assume Sablier runs on port 10000:

sablier-server.conf - Will be used in a similar way to authelia-server.conf. It creates a new path, /__sablier/, which will be redirected to the Sablier docker:

# The internal location to reach sablier API
set $sablierUrl /__sablier;

# Shared variable for default session duration
set $sablierSessionDuration 5m;

subrequest_output_buffer_size 64k;

# internal location for sablier middleware
# here, the sablier API is a container named "sablier" inside the same network as nginx
location /__sablier/ {
    internal;
    proxy_method GET;
    proxy_pass http://sablier:10000/;
}

sablier-location-dynamic.conf - Same idea as authelia-location.conf. I'm setting the default dynamic theme here as well, but this can be overridden in the route definition.

set $sablierDynamicShowDetails true;
set $sablierDynamicRefreshFrequency 5s;
set $sablierDynamicTheme shuffle;
js_content sablier.call;

sablier-location-blocking.conf - 60s as the default blocking timeout - hopefully apps are willing to wait that long :)

set $sablierBlockingTimeout 60s;
js_content sablier.call;

4. Usage example

And here's how to use it. I did not use Sablier's "group" functionality. Here is a full swag config for bazarr, which has both a dynamic config for the website and a blocking config for the api:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name bazarr.*;

    include /config/nginx/ssl.conf;
    include /config/nginx/authelia-server.conf;
    include /config/nginx/sablier-server.conf;
    # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    location / {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        include /config/nginx/authelia-location.conf;
        include /config/nginx/sablier-location-dynamic.conf;
        # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        set $sablierNginxInternalRedirect @root;
        set $sablierNames bazarr;
        set $sablierDynamicName "Bazarr";
    }

    location @root {
        set $upstream_app bazarr;
        set $upstream_port 6767;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }

    location /api/ {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        include /config/nginx/sablier-location-blocking.conf;
        # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        set $sablierNginxInternalRedirect @api;
        set $sablierNames bazarr;
    }

    location @api {
        set $upstream_app bazarr;
        set $upstream_port 6767;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}