Set base URL for TubeArchivist with Nginx This article provides configuration code for setting a custom base URL for TubeArchivist using Nginx. The setup involves a reverse proxy configuration that rewrites requests from `/multimedia/tubearchivist/` to the TubeArchivist server, along with a JavaScript filter that modifies HTML, CSS, and JS responses to replace absolute paths with the custom base URL prefix. reverse-proxy.conf 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 Show hidden characters js path "/etc/nginx/conf.d/"; js import main from ta filter.js; js set $body hash main.get hash; server { location /multimedia/tubearchivist/ { rewrite ^/multimedia/tubearchivist . $ $1 break; proxy pass http://{{subnets.multimedia}}.0.14:8000; proxy set header X-Forwarded-For $proxy add x forwarded for; proxy set header X-Forwarded-Proto $scheme; proxy set header X-Real-IP $remote addr; proxy set header Host $http host; proxy set header Accept-Encoding identity; proxy redirect ~^ . $ /multimedia/tubearchivist$1; js body filter main.apply base url; add trailer Body-Hash $body hash; } } ta filter.js 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 Show hidden characters var hash = ""; var res = ""; var buf = 0; // Modify the response body using regular expressions function apply base url r, data, flags { let requestUrl = r.uri; let fileExtension = getFileExtension requestUrl if fileExtension === "" || fileExtension === "css" || fileExtension === "js" { // Replace URLs in API responses if requestUrl.includes "/api/" { data = data.replace / " ^"\n\r\f\v " ?=\s : :" \/. ?" /g, '$1/multimedia/tubearchivist$2' ; } else { // Fix some hardcoded /api in JS scripts if fileExtension === "js" { data = data.replace / \/api. /g, ' /multimedia/tubearchivist$1' ; } data = data.replace / src|href|action = "' \/. ? "' /g, '$1="/multimedia/tubearchivist$2"' ; data = data.replace /' \/. '/g, '\'/multimedia/tubearchivist$1\'' ; } } if data.length buf++; res += data; // Collect the entire response, if flags.last { // until we get the last byte. try { hash = require 'crypto' .createHash 'sha1' .update res .digest 'base64' ; r.sendBuffer res, flags ; ngx.log ngx.INFO, FILTERED ${res.length} bytes in ${buf} buffers ; } catch e { ngx.log ngx.ERR, ERROR ${e} ; r.sendBuffer "", flags ; } } } // Extract the file extension from the URL function getFileExtension url { let match = url.match /\. a-z0-9 + ?: \? |$ /i ; return match ? match 1 .toLowerCase : ''; } function get hash { return hash; } export default { apply base url, get hash }