<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Knowledge Base (Posts about proxy)</title><link>https://bgstack15.ddns.net/blog/</link><description></description><atom:link href="https://bgstack15.ddns.net/blog/categories/proxy.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2025 &lt;a href="mailto:bgstack15@gmail.com"&gt;bgstack15&lt;/a&gt; 
&lt;a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.html"&gt;
&lt;img alt="GNU General Public License v3.0"
style="border-width:0; margin-bottom:12px;"
src="https://bgstack15.ddns.net/.images/gplv3-127x51.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Mon, 29 Dec 2025 14:15:36 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>owntracks with reverse proxy</title><link>https://bgstack15.ddns.net/blog/posts/2025/12/29/owntracks-with-reverse-proxy/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I recently improved my &lt;a href="https://bgstack15.ddns.net/blog/posts/2025/11/11/trying-owntracks-to-track-my-mobile-devices/"&gt;owntracks deployment&lt;/a&gt; to put the frontends behind a reverse proxy! It took me some time to research, because I got distracted with websockets and CORS rabbit trails.&lt;/p&gt;
&lt;p&gt;What ended up working was the following process.&lt;/p&gt;
&lt;p&gt;Add these values to the &lt;code&gt;config.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;owntracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://storage3.ipa.example.com/owntracks-map/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;router&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/owntracks-map"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add to the Apache httpd reverse proxy virtual host(s) these configs. I bet some of this is redundant.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ProxyPreserveHost On
ProxyPass        /owntracks-map  http://server4.ipa.example.com:8085 upgrade=websocket
ProxyPassReverse /owntracks-map  http://server4.ipa.example.com:8085/ upgrade=websocket
ProxyPass        /owntracks-internal  http://server4.ipa.example.com:8083 upgrade=websocket
ProxyPassReverse /owntracks-internal  http://server4.ipa.example.com:8083/ upgrade=websocket
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/owntracks-internal/ws"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   RequestHeader append X-Forwarded-Prefix "/owntracks"
   RequestHeader append X-Script-Name "/owntracks"
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/owntracks-internal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   RequestHeader append X-Forwarded-Prefix "/owntracks"
   RequestHeader append X-Script-Name "/owntracks"
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/owntracks-internal/view/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   RequestHeader append X-Forwarded-Prefix "/owntracks"
   RequestHeader append X-Script-Name "/owntracks"
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/owntracks-internal/static/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   RequestHeader append X-Forwarded-Prefix "/owntracks"
   RequestHeader append X-Script-Name "/owntracks"
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/owntracks-map/ws"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   ProxyPass        http://server4.ipa.example.com:8085/ retry=3 connectiontimeout=5 timeout=8 upgrade=websocket
   ProxyPassReverse http://server4.ipa.example.com:8085/
   RequestHeader append X-Forwarded-Prefix "/owntracks-map/ws"
   RequestHeader append X-Script-Name "/owntracks-map/ws"
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/owntracks-map/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   ProxyPass        http://server4.ipa.example.com:8085/ retry=3 connectiontimeout=5 timeout=8 upgrade=websocket
   ProxyPassReverse http://server4.ipa.example.com:8085/
   RequestHeader append X-Forwarded-Prefix "/owntracks-map"
   RequestHeader append X-Script-Name "/owntracks-map"
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Please note that this &lt;code&gt;/owntracks-internal&lt;/code&gt; is not the path used by the owntracks android clients. It is for the web view of the app with different authentication, and not the per-device auth used by owntracks.&lt;/p&gt;
&lt;p&gt;And then the directory listing for these frontend paths is as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/owntracks-map/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/owntracks-map/&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; Location tracking (&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/owntracks-internal/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;bare app&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;References&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Sticking the frontend behind a virtual path &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/github.com/owntracks/frontend/blob/main/docs/config.md#apibaseurl"&gt;frontend/docs/config.md at main · owntracks/frontend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Second part of reverse proxy &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/github.com/owntracks/frontend/blob/main/docs/config.md#routerbasepath"&gt;frontend/docs/config.md at main · owntracks/frontend&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>owntracks</category><category>proxy</category><category>web</category><guid>https://bgstack15.ddns.net/blog/posts/2025/12/29/owntracks-with-reverse-proxy/</guid><pubDate>Mon, 29 Dec 2025 14:07:00 GMT</pubDate></item><item><title>Novel project: Luanti Web Services Proxy</title><link>https://bgstack15.ddns.net/blog/posts/2025/09/20/novel-project-luanti-web-services-proxy/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I wrote in 10 hours a small project that makes it easy to use multiple instances of &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/content.luanti.org/"&gt;ContentDB&lt;/a&gt; and &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/servers.luanti.org"&gt;Serverlist&lt;/a&gt; in Luanti. Because the official ContentDB is very picky about what mods are allowed (under the laws where they are hosted, among other reasons), there might be other places to get packages, i.e., games, mods, and texture packs. I'm not aware of any other public ContentDB instances, but my internal network has a private ContentDB instance and I want to use it as well as the public ContentDB.&lt;/p&gt;
&lt;p&gt;This new project is named &lt;a href="https://bgstack15.ddns.net/blog/cgit/luanti/lwsp"&gt;lwsp&lt;/a&gt; and runs in docker or else with python3/flask.&lt;/p&gt;
&lt;p&gt;Use LWSP for ContentDB and Serverlist when you want your Luanti client to easily access multiple ContentDB instances, or multiple Serverlist instances, or both.&lt;/p&gt;
&lt;p&gt;Because of the way a ContentDB instance enforces mod dependencies to be resolvable within that instance, any dependencies for a package will be resolvable from that one instance only.&lt;/p&gt;
&lt;p&gt;This is not designed for a general-purpose website to manage multiple ContentDB instances' packages; it is only a shim for Luanti clients to use.&lt;/p&gt;
&lt;h2&gt;Using LWSP&lt;/h2&gt;
&lt;h3&gt;Running the proxy server locally&lt;/h3&gt;
&lt;p&gt;Set up a python3 virtual environment and install any dependencies.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;python3 -m venv ~/venv-cdbp
source ~/venv-cdbp
pip3 install -r requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Adjust config.cfg from &lt;a href="https://bgstack15.ddns.net/blog/cgit/luanti/lwsp/tree/config.cfg.example"&gt;config.cfg.example&lt;/a&gt;. In this file, you can set the default backend servers, for when the client uses "default." You can even force the usage of only these backends (ignoring any that the client might send) in the configuration. You can also configure packages to ignore by tag, author name, or regular expression matching the name or title.&lt;/p&gt;
&lt;p&gt;Start the development server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;./start.sh
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Running proxy server in docker or docker-compose&lt;/h3&gt;
&lt;p&gt;See the example &lt;a href="https://bgstack15.ddns.net/blog/cgit/luanti/lwsp/tree/docker-compose.yml"&gt;docker-compose.yml&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Configuring Luanti client to use the proxy server&lt;/h3&gt;
&lt;p&gt;Any mods installed before configuring a client to use the proxy can be upgraded, but at the time of upgrade, the mod's &lt;code&gt;mod.conf&lt;/code&gt; field &lt;code&gt;author&lt;/code&gt; will be updated with the hostname+protocol as part of the author name. This change will make it harder to disable the usage of the LWSP for &lt;code&gt;contentdb_url&lt;/code&gt;, and will require manual updates to each mod.conf before then being able to update them when pointing directly to the canonical ContentDB.&lt;/p&gt;
&lt;h4&gt;Using multiplexer for ContentDB&lt;/h4&gt;
&lt;p&gt;Set &lt;code&gt;contentdb_url&lt;/code&gt; in &lt;code&gt;minetest.conf&lt;/code&gt; to a string similar to the following. The top of the virtual path is a &lt;a href="https://meyerweb.com/eric/tools/dencoder/"&gt;url-encoded&lt;/a&gt; representation of space-delimited connection strings (protocol, hostname, and optionally port).&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;http://localhost:5124/https%3A%2F%2Fcontent.luanti.org%2F+http%3A%2F%2Fvm4%3A5123%2F
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example, to list &lt;code&gt;https://content.luanti.org/&lt;/code&gt; and &lt;code&gt;http://vm4:5123/&lt;/code&gt; you would place this into a url encoder utility.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;https://content.luanti.org/ http://vm4:5123/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Optionally, you can set the list to "default" to use the backends configured by the proxy server, or even just omit the "default" virtual path.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;http://localhost:5124/default/

http://localhost:5124/
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Using multiplexer for Serverlist&lt;/h4&gt;
&lt;p&gt;Set &lt;code&gt;serverlist_url&lt;/code&gt; in &lt;code&gt;minetest.conf&lt;/code&gt; to a line formatted in the same way, but with serverlist urls.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;http://localhost:5124/https%3A%2F%2Fservers.luanti.org+http%3A%2F%2Fvm4%3Aserverlist
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Like contentdb config, you can omit the top virtual directory of the path, and use the default configured in the server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;http://localhost:5124/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/2025/scrot-luanti-browsing-content-with-contentdbproxy.png"&gt;Screenshot of browsing available packages in Luanti&lt;br&gt;&lt;img alt="" src="https://bgstack15.ddns.net/blog/2025/scrot-luanti-browsing-content-with-contentdbproxy.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Author&lt;/h2&gt;
&lt;p&gt;bgstack15&lt;/p&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;None. This is novel on the www.&lt;/p&gt;
&lt;h2&gt;Further reading&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/luanti-org/contentdb/blob/master/docs/luanti_client.md"&gt;https://github.com/luanti-org/contentdb/blob/master/docs/luanti_client.md&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>game</category><category>luanti</category><category>proxy</category><guid>https://bgstack15.ddns.net/blog/posts/2025/09/20/novel-project-luanti-web-services-proxy/</guid><pubDate>Sat, 20 Sep 2025 12:36:00 GMT</pubDate></item><item><title>Use Apache httpd as a reverse proxy for Minetest Mapserver</title><link>https://bgstack15.ddns.net/blog/posts/2025/05/11/use-apache-httpd-as-a-reverse-proxy-for-minetest-mapserver/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I use the &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/github.com/minetest-mapserver/mapserver"&gt;Luanti Mapserver&lt;/a&gt; project for my various worlds, one instance per world. And because I'm old-school, I'm still rocking &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/httpd.apache.org/"&gt;Apache httpd&lt;/a&gt; and still call it httpd like the old Enterprise Linux days and not "apache2" like the Devuanites. And I use httpd as a reverse proxy (for TLS termination, for one thing) for the mapserver.&lt;/p&gt;
&lt;p&gt;The webpage works without the websocket upgrade, but the mapserver throws a stack trace complaining about the lack of the upgrade token in the Connection header.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;level=error msg=ws-upgrade err="websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After enough Internet research I found the answer! So here is my snippet for mapserver in my httpd config (inside the virtual host) that makes the magic happen.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;RewriteEngine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;ProxyPreserveHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mapserver&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;RewriteRule&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^/&lt;/span&gt;&lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;luanti&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;world3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;luanti&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;world3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;R,L&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;"/games/luanti/world3/map/"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ProxyPreserveHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ProxyPass&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nl"&gt;server4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30011&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connectiontimeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;upgrade&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ProxyPassReverse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nl"&gt;server4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30011&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;RequestHeader&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;luanti&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;world3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;RewriteEngine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;RewriteCond&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;Connection&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NC&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;RewriteCond&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Upgrade&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NC&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;RewriteRule&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nl"&gt;server4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30011&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;P,L&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because not the whole world uses that new-fangled nginx.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;The secret sauce came from &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/stackoverflow.com/questions/60475454/apache2-cant-set-headers-connection-and-upgrade/60475533#60475533"&gt;apache - Apache2 can't set headers "Connection" and "Upgrade" - Stack Overflow&lt;/a&gt;&lt;/p&gt;</description><category>apache</category><category>game</category><category>httpd</category><category>proxy</category><guid>https://bgstack15.ddns.net/blog/posts/2025/05/11/use-apache-httpd-as-a-reverse-proxy-for-minetest-mapserver/</guid><pubDate>Sun, 11 May 2025 12:42:00 GMT</pubDate></item><item><title>Firefox proxy notes</title><link>https://bgstack15.ddns.net/blog/posts/2023/12/05/firefox-proxy-notes/</link><dc:creator>bgstack15</dc:creator><description>&lt;h2&gt;Run SOCKS proxy&lt;/h2&gt;
&lt;p&gt;I normally use Firefox with a SOCKS proxy, which I run with:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh -D 8880 &lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;@proxyserver -n -f -N
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Configure firefox proxy&lt;/h2&gt;
&lt;p&gt;Visit &lt;code&gt;about:preferences&lt;/code&gt;, search proxy (tab General -&amp;gt; heading Network Settings -&amp;gt; button Settings...), and choose &lt;code&gt;Manual proxy configuration&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SOCKS host: localhost, port 8880&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My &lt;code&gt;No proxy for&lt;/code&gt; box includes:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="mf"&gt;192.168.1.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.35.0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ipa&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Firefox extension to make it easier&lt;/h2&gt;
&lt;p&gt;If I want to use an extension that adds the setting to the toolbar, I use &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/addons.mozilla.org/en-US/firefox/addon/simple-proxy-toggle/"&gt;Simple Proxy Toggle – Get this Extension for Firefox (en-US)&lt;/a&gt; by Strega. It doesn't manage its own settings; it merely lets you switch easily between the high-level Firefox settings.&lt;/p&gt;
&lt;p&gt;I had to temporarily modify my chrome/userChrome.css file to the following:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;#unified-extensions-button, #unified-extensions-button &amp;gt; .toolbarbutton-icon{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So that that annoying puzzle piece button would appear, so I could then right-click the extension icon and make it apepar on the toolbar.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;h3&gt;Weblinks&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/addons.mozilla.org/en-US/firefox/addon/simple-proxy-toggle/"&gt;Simple Proxy Toggle – Get this Extension for Firefox (en-US)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;My blog&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/03/01/socks-proxy-command/"&gt;socks-proxy-command&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/04/10/firefox-111.0-fix-puzzle-piece-in-toolbar/"&gt;firefox-111.0-fix-puzzle-piece-in-toolbar&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Internal&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;file:///mnt/public/Support/Programs/Browsers/firefox-proxy-notes.md&lt;/li&gt;
&lt;/ol&gt;</description><category>config</category><category>extensions</category><category>firefox</category><category>proxy</category><guid>https://bgstack15.ddns.net/blog/posts/2023/12/05/firefox-proxy-notes/</guid><pubDate>Tue, 05 Dec 2023 13:35:32 GMT</pubDate></item><item><title>Newspipe support for reverse proxy</title><link>https://bgstack15.ddns.net/blog/posts/2023/09/04/newspipe-support-for-reverse-proxy/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I submitted this patch &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/lists.sr.ht/~cedric/newspipe/%3CCABSMGamXhBxjER1gCu6CZ+9OVViBw76uLk-Bm-OV5P7K1x6tcA%40mail.gmail.com%3E"&gt;upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I added a new option in the config, named &lt;code&gt;prefix&lt;/code&gt;. If you set this, all the internal urls will add it. We use a &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/wlog.viltstigen.se/articles/2021/09/13/flask-application-behind-a-reverse-proxy/"&gt;ReverseProxy&lt;/a&gt; trick to add the prefix. This solves the generated urls, but for the hardcoded urls built throughout the jinja2 templates, I had to just manually update those. We use a &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/stackoverflow.com/questions/60990119/how-to-use-a-python3-custom-function-within-a-template-file-of-flask/60990564#60990564"&gt;neat trick&lt;/a&gt; to add a custom function to the template-parsing context which we can use to get the prefix (which safely returns the empty string if we had not set it, because we initialize the variable as empty).&lt;/p&gt;
&lt;p&gt;Most of the lines of this patch are just adjusting all the templates to add  the function call to &lt;code&gt;{{&lt;/code&gt; &lt;code&gt;prefix()&lt;/code&gt; &lt;code&gt;}}&lt;/code&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="gh"&gt;diff --git a/instance/config.py b/instance/config.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 42e624c..af7617a 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/instance/config.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/instance/config.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -10,6 +10,9 @@ PORT = 5000&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;DEBUG = True&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;API_ROOT = "/api/v2.0"&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="gi"&gt;+# Optional, and useful if you are using a reverse proxy with this virtual path prefix&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+#PREFIX = "/newspipe"&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;CSRF_ENABLED = True&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;SECRET_KEY = "LCx3BchmHRxFzkEv4BqQJyeXRLXenf"&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;SECURITY_PASSWORD_SALT = "L8gTsyrpRQEF8jNWQPyvRfv7U5kJkD"&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/instance/sqlite.py b/instance/sqlite.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 1f8d620..c6eaa46 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/instance/sqlite.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/instance/sqlite.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -10,6 +10,9 @@ PORT = 5000&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;DEBUG = True&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;API_ROOT = "/api/v2.0"&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="gi"&gt;+# Optional, and useful if you are using a reverse proxy with this virtual path prefix&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+#PREFIX = "/newspipe"&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;CSRF_ENABLED = True&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;SECRET_KEY = "LCx3BchmHRxFzkEv4BqQJyeXRLXenf"&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;SECURITY_PASSWORD_SALT = "L8gTsyrpRQEF8jNWQPyvRfv7U5kJkD"&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/bootstrap.py b/newspipe/bootstrap.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 1204491..1c5c967 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/bootstrap.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/bootstrap.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -44,6 +44,14 @@ def set_logging(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            handler.setLevel(log_level)&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        logger.setLevel(log_level)&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="gi"&gt;+class ReverseProxied(object):&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    def __init__(self, app, script_name):&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        self.app = app&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        self.script_name = script_name&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    def __call__(self, environ, start_response):&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        environ['SCRIPT_NAME'] = self.script_name&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        return self.app(environ, start_response)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;# Create Flask application&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;application = Flask(__name__, instance_relative_config=True)&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -63,6 +71,11 @@ else:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;set_logging(application.config["LOG_PATH"])&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="gi"&gt;+_prefix = ""&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+if "PREFIX" in application.config:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    application.wsgi_app = ReverseProxied(application.wsgi_app, script_name=application.config["PREFIX"])&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    _prefix = application.config["PREFIX"]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;db = SQLAlchemy(application)&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;migrate = Migrate(application, db)&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -100,3 +113,9 @@ application.jinja_env.filters["datetime"] = format_datetime&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;application.jinja_env.filters["datetimeformat"] = datetimeformat&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;# inject application in Jinja env&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;application.jinja_env.globals["application"] = application&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+@application.context_processor&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+def utility_processor():&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    def prefix():&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        return _prefix.rstrip("/")&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    return dict(prefix=prefix)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/controllers/user.py b/newspipe/controllers/user.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 00ffb96..d2c5bc0 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/controllers/user.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/controllers/user.py&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -138,7 +138,7 @@ class LdapuserController:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        namelist = []&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        try:&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            query = dns.resolver.query(f"_ldap._tcp.{domain}", "SRV")&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-        except dns.resolver.NXDOMAIN:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            # no records exist that match the request, so we were probably&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            # given a specific hostname, and an empty query will trigger&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            # the logic below that will add the original domain to the list.&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/static/js/articles.js b/newspipe/static/js/articles.js&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index f1cee6e..29ebac2 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/static/js/articles.js&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/static/js/articles.js&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -86,7 +86,7 @@ Array.prototype.map.call(nodes, function(node) {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;      }&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;      // sends the updates to the server&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-      fetch(API_ROOT + "article/" + article_id, {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+      fetch(prefix + API_ROOT + "article/" + article_id, {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        method: "PUT",&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        headers: {&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;          'Content-Type': 'application/json',&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -157,7 +157,7 @@ Array.prototype.map.call(nodes, function(node) {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;      }&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;      // sends the updates to the server&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-      fetch(API_ROOT + "article/" + article_id, {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+      fetch(prefix + API_ROOT + "article/" + article_id, {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        method: "PUT",&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        headers: {&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;          'Content-Type': 'application/json',&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -189,7 +189,7 @@ Array.prototype.map.call(nodes, function(node) {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        data = JSON.stringify(data);&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;        // sends the updates to the server&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-        fetch(API_ROOT + "articles", {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        fetch(prefix + API_ROOT + "articles", {&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;          method: "DELETE",&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;          headers: {&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            'Content-Type': 'application/json',&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/static/js/config.js b/newspipe/static/js/config.js&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;new file mode 100644&lt;/span&gt;
&lt;span class="gh"&gt;index 0000000..7fad438&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- /dev/null&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/static/js/config.js&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -0,0 +1,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+/*&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+ * Set variables here for the javascript used by newspipe.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+ */&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+var prefix = "/newspipe";&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+/* Set exactly one trailing slash on prefix. */&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+prefix = prefix.replace(/\/+$/,"/");&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/article.html b/newspipe/templates/article.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index c62e3f0..d9cf9a6 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/article.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/article.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -4,7 +4,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;div class="row" data-article="{{ article.id }}" id="filters" data-filter="{{ filter_ }}"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        &amp;lt;div class="col"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;h2&amp;gt;&amp;lt;a href="{{ article.link  }}" target="_blank"&amp;gt;{{ article.title|safe }}&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-            &amp;lt;h3&amp;gt;{{ _('from') }} &amp;lt;a href="/feed/{{ article.source.id }}"&amp;gt;{{ article.source.title }}&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+            &amp;lt;h3&amp;gt;{{ _('from') }} &amp;lt;a href="{{ prefix() }}/feed/{{ article.source.id }}"&amp;gt;{{ article.source.title }}&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;a href="{{ url_for("article.delete", article_id=article.id) }}"&amp;gt;&amp;lt;i class="fa fa-times delete" aria-hidden="true" title="{{ _('Delete this article') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            {% if article.like %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="#"&amp;gt;&amp;lt;i class="fa fa-star like" aria-hidden="true" title="{{ _('One of your favorites') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/duplicates.html b/newspipe/templates/duplicates.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 38dc52b..d138226 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/duplicates.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/duplicates.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -1,7 +1,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;{% extends "layout.html" %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;{% block content %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;div class="container"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-    &amp;lt;p&amp;gt;&amp;lt;h1&amp;gt;{{ _('Duplicates in the feed') }} &amp;lt;a href="/feed/{{ feed.id }}"&amp;gt;{{ feed.title }}&amp;lt;/a&amp;gt;.&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    &amp;lt;p&amp;gt;&amp;lt;h1&amp;gt;{{ _('Duplicates in the feed') }} &amp;lt;a href="{{ prefix() }}/feed/{{ feed.id }}"&amp;gt;{{ feed.title }}&amp;lt;/a&amp;gt;.&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;div class="table-responsive"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        &amp;lt;table class="table table-striped"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;thead&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -19,8 +19,8 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            {% for pair in duplicates %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;tr&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                    &amp;lt;td&amp;gt;{{ loop.index }}&amp;lt;/td&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                    &amp;lt;td id="{{ pair[0].id }}"&amp;gt;&amp;lt;a href="{{ url_for("article.delete", article_id=pair[0].id) }}"&amp;gt;&amp;lt;i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&amp;amp;nbsp;&amp;lt;a href="/article/{{ pair[0].id }}"&amp;gt;{{ pair[0].title }}&amp;lt;/a&amp;gt; ({{ pair[0].retrieved_date }})&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                    &amp;lt;td id="{{ pair[1].id }}"&amp;gt;&amp;lt;a href="{{ url_for("article.delete", article_id=pair[1].id) }}"&amp;gt;&amp;lt;i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&amp;amp;nbsp;&amp;lt;a href="/article/{{ pair[1].id }}"&amp;gt;{{ pair[1].title }}&amp;lt;/a&amp;gt; ({{ pair[1].retrieved_date }})&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                    &amp;lt;td id="{{ pair[0].id }}"&amp;gt;&amp;lt;a href="{{ url_for("article.delete", article_id=pair[0].id) }}"&amp;gt;&amp;lt;i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&amp;amp;nbsp;&amp;lt;a href="{{ prefix() }}/article/{{ pair[0].id }}"&amp;gt;{{ pair[0].title }}&amp;lt;/a&amp;gt; ({{ pair[0].retrieved_date }})&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                    &amp;lt;td id="{{ pair[1].id }}"&amp;gt;&amp;lt;a href="{{ url_for("article.delete", article_id=pair[1].id) }}"&amp;gt;&amp;lt;i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&amp;amp;nbsp;&amp;lt;a href="{{ prefix() }}/article/{{ pair[1].id }}"&amp;gt;{{ pair[1].title }}&amp;lt;/a&amp;gt; ({{ pair[1].retrieved_date }})&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;/tr&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            {% endfor %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;/tbody&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/history.html b/newspipe/templates/history.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 153c2f1..00e22ef 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/history.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/history.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -43,7 +43,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;      &amp;lt;ul class="list-group"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        {% for date in articles_counter | sort(reverse = True) %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        {% for article in articles %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-        &amp;lt;li class="list-group-item"&amp;gt;{{ article.date | datetime }} - &amp;lt;a href="/article/{{ article.id }}"&amp;gt;{{ article.title | safe }}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        &amp;lt;li class="list-group-item"&amp;gt;{{ article.date | datetime }} - &amp;lt;a href="{{ prefix() }}/article/{{ article.id }}"&amp;gt;{{ article.title | safe }}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        {% endfor %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        {% endfor %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;      &amp;lt;/ul&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/home.html b/newspipe/templates/home.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 631b769..5feb18d 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/home.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/home.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -42,7 +42,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            {% if feed_id == feed.id %}&amp;lt;/b&amp;gt;{% endif %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                        &amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                        &amp;lt;li class="nav-item feed-commands {% if in_error.get(fid, 0) &amp;gt; 0 %}d-none{% endif %}" data-bs-feed="{{ feed.id }}"&amp;gt;&amp;lt;span class="nav-link"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                            &amp;lt;a href="/feed/{{ feed.id }}"&amp;gt;&amp;lt;i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                            &amp;lt;a href="{{ prefix() }}/feed/{{ feed.id }}"&amp;gt;&amp;lt;i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            &amp;lt;a href="{{ url_for('feed.form', feed_id=feed.id) }}"&amp;gt;&amp;lt;i class="fa fa-pencil-square-o" aria-hidden="true" title="{{ _('Edit this feed') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            &amp;lt;a href="{{ url_for('article.mark_as', new_value='unread', feed_id=feed.id) }}"&amp;gt;&amp;lt;i class="fa fa-square-o" aria-hidden="true" title="{{ _('Mark this feed as unread') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            &amp;lt;a href="{{ url_for('article.mark_as', new_value='read', feed_id=feed.id) }}"&amp;gt;&amp;lt;i class="fa fa-check-square-o" aria-hidden="true" title="{{ _('Mark this feed as read') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -73,7 +73,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                {% if feed_id == fid %}&amp;lt;/b&amp;gt;{% endif %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;li class="nav-item feed-commands {% if in_error.get(fid, 0) &amp;gt; 0 %}d-none{% endif %}" data-bs-feed="{{ fid }}"&amp;gt;&amp;lt;span class="nav-link"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                &amp;lt;a href="/feed/{{ fid }}"&amp;gt;&amp;lt;i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                &amp;lt;a href="{{ prefix() }}/feed/{{ fid }}"&amp;gt;&amp;lt;i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="{{ url_for('feed.form', feed_id=fid) }}"&amp;gt;&amp;lt;i class="fa fa-pencil-square-o" aria-hidden="true" title="{{ _('Edit this feed') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="{{ url_for('article.mark_as', new_value='unread', feed_id=fid) }}"&amp;gt;&amp;lt;i class="fa fa-square-o" aria-hidden="true" title="{{ _('Mark this feed as unread') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="{{ url_for('article.mark_as', new_value='read', feed_id=fid) }}"&amp;gt;&amp;lt;i class="fa fa-check-square-o" aria-hidden="true" title="{{ _('Mark this feed as read') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -102,7 +102,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                {% if feed_id == fid %}&amp;lt;/b&amp;gt;{% endif %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;li class="nav-item feed-commands {% if in_error.get(fid, 0) &amp;gt; 0 %}d-none{% endif %}" data-bs-feed="{{ fid }}"&amp;gt;&amp;lt;span class="nav-link"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                &amp;lt;a href="/feed/{{ fid }}"&amp;gt;&amp;lt;i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                &amp;lt;a href="{{ prefix() }}/feed/{{ fid }}"&amp;gt;&amp;lt;i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="{{ url_for('feed.form', feed_id=fid) }}"&amp;gt;&amp;lt;i class="fa fa-pencil-square-o" aria-hidden="true" title="{{ _('Edit this feed') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="{{ url_for('article.mark_as', new_value='unread', feed_id=fid) }}"&amp;gt;&amp;lt;i class="fa fa-square-o" aria-hidden="true" title="{{ _('Mark this feed as unread') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;a href="{{ url_for('article.mark_as', new_value='read', feed_id=fid) }}"&amp;gt;&amp;lt;i class="fa fa-check-square-o" aria-hidden="true" title="{{ _('Mark this feed as read') }}"&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -174,11 +174,11 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            {% if not feed_id %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                                &amp;lt;td class="d-none d-md-block"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                                    &amp;lt;img src="{{ url_for('icon.icon', url=feeds[article.source.id].icon_url) }}" width="16px"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                                    &amp;lt;a href="/article/redirect/{{ article.id}}" target="_blank"&amp;gt;{{ article.source.title | safe }}&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                                    &amp;lt;a href="{{ prefix() }}/article/redirect/{{ article.id}}" target="_blank"&amp;gt;{{ article.source.title | safe }}&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                                &amp;lt;/td&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            {% endif %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            &amp;lt;td {%if filter_ == 'all' and article.readed == False %}style='font-weight:bold'{% endif %}&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                                &amp;lt;a href="/article/{{ article.id }}" title="{{ article.title }}"&amp;gt;{{ article.title | truncate(100, False, '...') }}&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                                &amp;lt;a href="{{ prefix() }}/article/{{ article.id }}" title="{{ article.title }}"&amp;gt;{{ article.title | truncate(100, False, '...') }}&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            &amp;lt;/td&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                            &amp;lt;td class="date d-none d-lg-block"&amp;gt;{{ article.date | datetime(format='short') }}&amp;lt;/td&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                        &amp;lt;/tr&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/layout.html b/newspipe/templates/layout.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 2464040..466ff4e 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/layout.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/layout.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -21,7 +21,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    {% block menu %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;nav class="navbar navbar-expand-lg navbar-dark bg-newspipe-blue"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;       &amp;lt;div class="container-fluid"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-        &amp;lt;a class="navbar-brand" href="/"&amp;gt;Newspipe&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+        &amp;lt;a class="navbar-brand" href="{{ prefix() }}/"&amp;gt;Newspipe&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        &amp;lt;button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;span class="navbar-toggler-icon"&amp;gt;&amp;lt;/span&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        &amp;lt;/button&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -150,6 +150,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    {% block content %}{% endblock %}&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;!-- Placed at the end of the document so the pages load faster --&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+    &amp;lt;script type="text/javascript" src="{{ url_for('static', filename = 'js/config.js') }}"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;script type="text/javascript" src="{{ url_for('static', filename = 'js/articles.js') }}"&amp;gt;&amp;lt;/script&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;script type="text/javascript" src="{{ url_for('static', filename = 'js/feed.js') }}"&amp;gt;&amp;lt;/script&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;  &amp;lt;/body&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/login.html b/newspipe/templates/login.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index b995230..78af3c4 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/login.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/login.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -19,7 +19,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                    &amp;lt;div class="alert alert-warning" role="alert"&amp;gt;{{ message }}&amp;lt;/div&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                {% endfor %}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                {{ form.submit(class_="btn btn-primary") }}&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                {% if self_registration %}&amp;lt;a href="/signup" class="btn btn-info"&amp;gt;{{ _('Sign up') }}&amp;lt;/a&amp;gt;{% endif %}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                {% if self_registration %}&amp;lt;a href="{{ prefix() }}/signup" class="btn btn-info"&amp;gt;{{ _('Sign up') }}&amp;lt;/a&amp;gt;{% endif %}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;/form&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;        &amp;lt;/div&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;    &amp;lt;/div&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;diff --git a/newspipe/templates/management.html b/newspipe/templates/management.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gh"&gt;index 4e977f8..19dbded 100644&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;--- a/newspipe/templates/management.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/newspipe/templates/management.html&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -6,7 +6,7 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;            &amp;lt;div class="row"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                &amp;lt;div class="col"&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                    &amp;lt;h2&amp;gt;{{ _('Your subscriptions') }}&amp;lt;/h2&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-                    &amp;lt;p&amp;gt;{{ _('You are subscribed to') }} {{ nb_feeds }} &amp;lt;a href="/feeds"&amp;gt;{{ _('feeds') }}&amp;lt;/a&amp;gt;. &amp;lt;a href="{{ url_for("feed.form") }}"&amp;gt;{{ _('Add') }}&amp;lt;/a&amp;gt; {{ _('a feed') }}.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+                    &amp;lt;p&amp;gt;{{ _('You are subscribed to') }} {{ nb_feeds }} &amp;lt;a href="{{ prefix() }}/feeds"&amp;gt;{{ _('feeds') }}&amp;lt;/a&amp;gt;. &amp;lt;a href="{{ url_for("feed.form") }}"&amp;gt;{{ _('Add') }}&amp;lt;/a&amp;gt; {{ _('a feed') }}.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                    &amp;lt;p&amp;gt;{{ nb_articles }} {{ _('articles are stored in the database with') }} {{ nb_unread_articles }} {{ _('unread articles') }}.&amp;lt;/p&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                    &amp;lt;p&amp;gt;{{ _('You have') }} {{ nb_categories }} &amp;lt;a href="{{ url_for("categories.list_")}}"&amp;gt;{{ _('categories') }}&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;                    &amp;lt;a href="{{ url_for("articles.expire", weeks=10) }}" class="btn btn-primary" onclick="return confirm('{{ _('You are going to delete old articles.') }}');"&amp;gt;{{ _('Delete articles older than 10 weeks') }}&amp;lt;/a&amp;gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>flask</category><category>newspipe</category><category>proxy</category><guid>https://bgstack15.ddns.net/blog/posts/2023/09/04/newspipe-support-for-reverse-proxy/</guid><pubDate>Tue, 05 Sep 2023 02:30:40 GMT</pubDate></item><item><title>Coming soon to newspipe: reverse proxy support</title><link>https://bgstack15.ddns.net/blog/posts/2023/08/31/coming-soon-to-newspipe-reverse-proxy-support/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I have taken it upon myself to add reverse-proxy with prefix support to my &lt;a href="https://bgstack15.ddns.net/blog/posts/2023/06/25/newspipe-docker-image/"&gt;docker image for newspipe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So far I have written some basic parts such as a config option for specifying the expected prefix. See the commits in both the &lt;a href="https://bgstack15.ddns.net/blog/cgit/newspipe/log/?h=reverse-proxy"&gt;newspipe&lt;/a&gt; and &lt;a href="https://bgstack15.ddns.net/blog/cgit/newspipe-docker/log/?h=reverse-proxy"&gt;newspipe-docker&lt;/a&gt; repos.&lt;/p&gt;
&lt;p&gt;What I haven't done yet is update the &lt;code&gt;url_for&lt;/code&gt; function to also add the prefix to the generated urls for most links in the app. Once I do that, I'll send a pull request to &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/lists.sr.ht/~cedric/newspipe"&gt;upstream&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;h3&gt;Weblinks&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/wlog.viltstigen.se/articles/2021/09/13/flask-application-behind-a-reverse-proxy/"&gt;Flask application behind a reverse proxy - Wolfblog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/dlukes.github.io/flask-wsgi-url-prefix.html"&gt;How to mount a Flask app under a URL prefix (or really, any WSGI app) - Little Umbrellas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/radicale.org/v3.html#reverse-proxy"&gt;Radicale v3 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;My previous related work&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/cgit/fifconfig/tree/fifconfig.py"&gt;automatically detect X-Forwarded-Prefix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/cgit/stackbin/tree/stackbin.py"&gt;Set the configured prefix with a custom endpoint&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>flask</category><category>newspipe</category><category>proxy</category><guid>https://bgstack15.ddns.net/blog/posts/2023/08/31/coming-soon-to-newspipe-reverse-proxy-support/</guid><pubDate>Thu, 31 Aug 2023 12:47:51 GMT</pubDate></item><item><title>disabling webrtc temporarily</title><link>https://bgstack15.ddns.net/blog/posts/2023/03/17/disabling-webrtc-temporarily/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;To facilitate a proxy setting to prevent IP address leakage, disable WebRTC with &lt;code&gt;about:config&lt;/code&gt; setting:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;media.peerconnection.enabled = false
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can check with &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/whoer.net/"&gt;https://whoer.net&lt;/a&gt;&lt;/p&gt;</description><category>browser</category><category>proxy</category><category>web</category><category>webrtc</category><guid>https://bgstack15.ddns.net/blog/posts/2023/03/17/disabling-webrtc-temporarily/</guid><pubDate>Fri, 17 Mar 2023 12:43:42 GMT</pubDate></item><item><title>Improving radicale kerberos auth</title><link>https://bgstack15.ddns.net/blog/posts/2023/03/13/improving-radicale-kerberos-auth/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;My current setup for &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/radicale.org/"&gt;Radicale&lt;/a&gt; and &lt;a href="https://bgstack15.ddns.net/blog/cgit/radicaleinfcloud/"&gt;Infcloud&lt;/a&gt; for my web interface to my calendars depends on ldap authentication at the reverse-proxy level.&lt;/p&gt;
&lt;p&gt;I hacked the frontend in my branch of infcloud to use the browser localStorage javascript/devtools feature so I don't have to enter my username and password every time. Yes, it's insecure, and yes, I don't care.&lt;/p&gt;
&lt;p&gt;Using my web calendar works very well. However, when I go to download an event (usually to email it to someone to invite them), I get prompted with the browser basic auth prompt. So I got tired of having to do that, at least the first time in every session, and I wanted to find a better way. I use kerberos (gssapi) authentication in other places on my web server, and I wanted to bring that here.&lt;/p&gt;
&lt;p&gt;So I spent a bunch of time experimenting, and I learned that I didn't need to change the infcloud or radicale apps at all! Configuration of the apache httpd reverse proxy, and also my radicale rights file was all I needed.&lt;/p&gt;
&lt;h2&gt;Changes to apache httpd config&lt;/h2&gt;
&lt;p&gt;I only needed to change one line in my main config file: which auth.cnf file to include:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;RewriteEngine On
RewriteRule ^/radicale$ /radicale/ [R,L]
&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/radicale/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   ProxyPreserveHost On
   Include conf.d/auth-gssapi.cnf
   Require valid-user
   AuthName "GSSAPI protected"
   ProxyPass        http://localhost:5232/ retry=20 connectiontimeout=300 timeout=300
   ProxyPassReverse http://localhost:5232/
   RequestHeader    set X-Script-Name /radicale
&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Changes to auth-gssapi.cnf&lt;/h2&gt;
&lt;p&gt;I added entries to auth-gssapi.cnf, which was mostly complete.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;AuthType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GSSAPI&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiUseSessions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;Session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;SessionCookieName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1_session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiCredStore&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;keytab&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;keytab&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiCredStore&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;ccache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;krb5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;SessionHeader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;S1SESSION&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiSessionKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;file&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gssapisession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiImpersonate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiDelegCcacheDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ccache&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiDelegCcachePerms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0660&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;gid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiUseS4U2Proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiAllowedMech&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;krb5&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiBasicAuth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiBasicAuthMech&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;krb5&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiLocalName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;GssapiNameAttributes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;AuthBasicProvider&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ldap&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;AuthLDAPGroupAttribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;member&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;AuthLDAPSubGroupClass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;group&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;AuthLDAPGroupAttributeIsDN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;On&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;AuthLDAPURL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;"ldaps://dns1.ipa.internal.com:636 dns2.ipa.internal.com:636/cn=users,cn=accounts,dc=ipa,dc=internal,dc=com?uid,memberof,gecos?sub?(objectClass=person)"&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;#GSS_NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="nv"&gt;@IPA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EXAMPLE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;merely&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;additional&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;radicale&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rights&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;RequestHeader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X_REMOTE_USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;"%{GSS_NAME}e"&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Does&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;work&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;#RequestHeader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X_GROUPS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;"%{AUTHENTICATE_memberOf}e"&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mostly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;useless&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;values&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;#RequestHeader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X_REMOTE_GSS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;"%{GSS_NAME_ATTRS_JSON}e"&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Changes to radicale rights file&lt;/h2&gt;
&lt;p&gt;My radicale setup uses &lt;code&gt;/etc/radicale/rights&lt;/code&gt; to define the ACLS. The examples in the file are very useful. I merely needed to repeat entries and add the domain name.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;already&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;here&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RW&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;principal-domain&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;@IPA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INTERNAL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COM&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RW&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;calendars&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/[&lt;/span&gt;&lt;span class="n"&gt;^/&lt;/span&gt;&lt;span class="o"&gt;]+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;calendars-domain&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;@IPA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INTERNAL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COM&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/[&lt;/span&gt;&lt;span class="n"&gt;^/&lt;/span&gt;&lt;span class="o"&gt;]+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Specific&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;calendars&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user8-read-bgstack15-1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user8&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bgstack15&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user8-read-bgstack15-2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user8&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bgstack15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;c86bcd9f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7526&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8083&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ca5c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c68bc664ae03&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rwi&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user8-read-bgstack15-1-domain&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user8&lt;/span&gt;&lt;span class="nv"&gt;@IPA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INTERNAL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COM&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bgstack15&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;permissionsS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user8-read-bgstack15-2-domain&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user8&lt;/span&gt;&lt;span class="nv"&gt;@IPA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INTERNAL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COM&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nl"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bgstack15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;c86bcd9f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7526&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8083&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ca5c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c68bc664ae03&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rwi&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I find it worth duplicating entries, to accomplish my goal of being able to seamlessly download calendar events in my browser.&lt;/p&gt;</description><category>gssapi</category><category>httpd</category><category>kerberos</category><category>proxy</category><category>radicale</category><guid>https://bgstack15.ddns.net/blog/posts/2023/03/13/improving-radicale-kerberos-auth/</guid><pubDate>Mon, 13 Mar 2023 13:12:45 GMT</pubDate></item><item><title>ssh_config: new option in Devuan, March 2023</title><link>https://bgstack15.ddns.net/blog/posts/2023/03/05/ssh-config-new-option-in-devuan-march-2023/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;From the apt-listchanges message for this month:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;openssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;9.2&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unstable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;urgency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;medium&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;OpenSSH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;9.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;includes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;changes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;may&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;affect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;configurations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EnableEscapeCommandline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;controls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;whether&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;escape&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sequence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;provides&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Among&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;things&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;could&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;used&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;additional&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;defaults&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;"no"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;disabling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;was&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;previously&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Turning&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;off&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;allows&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;platforms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;support&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sandboxing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currently&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;only&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;OpenBSD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stricter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sandbox&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- Colin Watson &amp;lt;cjwatson@debian.org&amp;gt;  Wed, 08 Feb 2023 10:36:06 +0000&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So I had to run this on all Devuan systems, to keep my ssh client command-line enabled.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo updateval -a -v /etc/ssh/ssh_config '^\s*EnableEscapeCommandline.*' 'EnableEscapeCommandline yes'
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Where &lt;a href="https://bgstack15.ddns.net/blog/cgit/bgscripts/tree/src/usr/bin/updateval"&gt;updateval&lt;/a&gt; is from my bgscripts-core package.&lt;/p&gt;</description><category>browser</category><category>proxy</category><category>socks</category><category>ssh</category><category>web</category><guid>https://bgstack15.ddns.net/blog/posts/2023/03/05/ssh-config-new-option-in-devuan-march-2023/</guid><pubDate>Sun, 05 Mar 2023 13:54:19 GMT</pubDate></item><item><title>socks proxy command</title><link>https://bgstack15.ddns.net/blog/posts/2023/03/01/socks-proxy-command/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;Run this command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh -D 8880 &lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;@proxyserver -n -f -N
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Set socks proxy in browser settings.&lt;/p&gt;</description><category>browser</category><category>proxy</category><category>socks</category><category>ssh</category><category>web</category><guid>https://bgstack15.ddns.net/blog/posts/2023/03/01/socks-proxy-command/</guid><pubDate>Wed, 01 Mar 2023 14:29:10 GMT</pubDate></item></channel></rss>