Apache 2.4: Require (allow) either (mod_auth_basic) valid-user or a specific query string

Prerequisities:

  • Apache 2.4
  • you have set up your htpasswd file in /path/to/.htpasswd
  • the alternative, secret query parameter for access is secret_access_parameter

To make it work, add these lines to the appropriate section of your Apache vhost configuration:

Require all denied
<RequireAny>
  Require valid-user
  Require expr "%{QUERY_STRING} =~ /secret_access_parameter/"
</RequireAny>
AuthType Basic
AuthName "Authorization required"
AuthUserFile /path/to/.htpasswd

Switching Redis from TCP port to UNIX socket in Ubuntu 16.04, with Nextcloud running under Apache

This presumes that Apache, Nextcloud and Redis have already been installed, with Redis running on the default TCP port 6379 and Nextcloud is configured to use that port.

When switching from using a port to using a socket, any “Redis Server Went Away” issues that crop up in Nextcloud are probably due to file permissions: Apache’s www-data user needs access to Redis’ socket file inside /var/run/redis. Here’s the full list of steps I took to make it work:

  1. open ${NEXTCLOUD_WWW_ROOT}/config/config.php in a text editor
  2. turn on maintenance mode by setting 'maintenance' => true and saving the file
  3. in the 'redis' array,
    1. set 'host' => '/var/run/redis/redis.sock'
    2. set 'port' => 0
  4. save changes
  5. open /etc/redis/redis.conf in a text editor
  6. change port 6379 to port 0
  7. uncomment unixsocket /var/run/redis/redis.sock
  8. uncomment unixsocketperm 700
  9. change unixsocketperm 700 to unixsocketperm 770
  10. save changes
  11. sudo adduser www-data redis
  12. sudo systemctl restart apache2 (for the added group to take effect)
  13. sudo systemctl restart redis-server
  14. open ${NEXTCLOUD_WWW_ROOT}/config/config.php in a text editor
  15. turn off maintenance mode by setting 'maintenance' => false and saving the file

There’s no need to change the value of open_basedir, or to tweak Apache’s site configuration (but do remember step #12 above: restart Apache after adding www-data to the redis group).

Redirecting Signal Desktop’s log from syslog to a separate file

After switching from the old Chrome app to the new Signal Desktop app, my syslog began to get spammed with lines containing stuff like “Sending a keepalive message”.

They seemingly come from gnome-session, but it’s actually Signal operating under gnome-session. Not having the actual application name for filtering, I just made a slightly hackish /etc/rsyslog.d/20-redirect-signal.conf with the following contents:

:msg,contains,"{\"name\":\"log\",\"hostname\":\"saegusa\"" -/var/log/signal-desktop.log 
& stop

(Where saegusa is my hostname; you should obviously change this to match yours.)

Get GIT_WORK_TREE from the post-checkout hook

I was crafting a post-checkout hook and wanted to do something depending on the absolute path of $GIT_WORK_TREE in the current environment. In git 2.7.4 (and up to 2.4.14) at least, that environment variable was set to “.” when inside the post-checkout hook, which was a little unhelpful in this case. So I spent some time trying to google why and coming up empty.

Here’s where you’re entitled to laugh at my over-thinking this.

Since I’m in the work tree already (.) when inside the hook, the absolute path is the current working directory, or $PWD. No need to fiddle with GIT_WORK_TREE at all.

Apache 2.4 + Gitlab Omnibus (CE) with a relative URL: 404 (not found), 422 (The change you requested was rejected)

It’s been a painful month battling with this and I’m too tired to document everything thoroughly, so I’ll just throw this out there:

# "Note this config assumes unicorn is listening on default port 8080 and
# gitlab-workhorse is listening on port 8181."

Alias /lab "/opt/gitlab/embedded/service/gitlab-rails/public"

<Directory /opt/gitlab/embedded/service/gitlab-rails/public>
    Include conf-available/geoblock-non-fi.conf
    
    Options -MultiViews
    #DirectoryIndex disabled
</Directory>

<Location /lab>
    Include conf-available/geoblock-non-fi.conf
    
    ErrorDocument 404 /404.html
    ErrorDocument 422 /422.html
    ErrorDocument 500 /500.html
    ErrorDocument 502 /502.html
    ErrorDocument 503 /503.html

    RequestHeader set X-Forwarded-Proto https
    Header set Strict-Transport-Security: "max-age=15768000;includeSubdomains"

    ProxyPass "http://127.0.0.1:8181/lab"
    ProxyPassReverse "http://127.0.0.1:8181/lab"
</Location>

That one disabled line (#DirectoryIndex disabled) was required (uncommented) when I used the RewriteRules version of the recipe, otherwise it was 404 whenever logging in.

You also obviously need to either out-comment “Include conf-available/geoblock-non-fi.conf” or add your own geoblocking rules in the file it references.

Strange problems with self-hosted Mattermost? It might be your router’s fault

I spent the last few days online trying to get Mattermost working on my home server. It looks like a promising replacement for Slack, very polished and professional and the installation process is well documented. The only twist was that, since I’m already running Apache on the server, I figured I’d set it up to also function as a proxy for Mattermost. (The developers apparently favor nginx, whereas documenting usage with Apache rests on the community.)

Everything seemed to go smoothly, and the web app worked just fine when called locally. But when I tried to access it using my FQDN, it just kept failing with the “We’re having trouble connecting to Mattermost” page staring me bluntly. I’ve lost count how many times I’ve hit refresh only to see that page again and again.

Today I had a breakthrough when I realized that a statically served JavaScript file was failing to load, and bizarrelly only in Firefox: when I finally fired up Chrome out of desperation, everything was working just fine. With Firefox, or with wget for that matter, trying to load the JS file directly only resulted in loading a fraction of the file, or not at all.

This was only halfway towards the solution, I still spent hours tearing my hair out until I finally figured out the root of the problem: my home router doesn’t do NAT loopback.

After I pointed my FQDN to the home server in my desktop’s hosts file, the static JS came through in Firefox just as easily as it had in Chrome. (I shudder to think what it is that Chrome does that made it able to circumvent the problem.)

Now, I did try to access Mattermost from outside my home network previously, but being utterly disorganized in my debugging, I apparently had mangled the Apache configuration for the site each time I did those tests. With both the correct Apache configuration and the local hosts file fix in place, the FQDN works from inside the home LAN as well as from outside.

gnome-session: Expression error: unknown function bitrate()

The problem: my syslog is full of these three lines repeating

gnome-session[3926]: Expression error: unknown function
gnome-session[3926]:  Net: down  $ ( bitrate ( net.down ) ) , up  $ ( bitrate ( net.up ) )
gnome-session[3926]: ---------------^

So bitrate() is unknown.

The message is caused by the System Load Indicator (indicator-multiload), and more specifically a non-default value of the indicator-expressions key in the de.mh21.indicator-multiload.general schema. The value I had somehow managed to set there was:

['', 'Mem $(size(mem.user))', 'CPU $(percent(cpu.inuse))', 'Net $(bitrate(net.down))/$(bitrate(net.up))', 'Swap $(size(swap.used))', 'Load $(decimals(load.avg,2))', 'Disk $(speed(disk.read))/$(speed(disk.write))']

The default value, as I read it from /usr/share/glib-2.0/schemas/de.mh21.indicator-multiload.gschema.xml just now, is

[ "", "CPU $(percent(cpu.inuse))", "Mem $(size(mem.user))", "Net $(speed(net.down))/$(speed(net.up))", "Swap $(size(swap.used))", "Load $(decimals(load.avg,2))", "Disk $(speed(disk.read))/$(speed(disk.write))" ]

So the correct function to replace bitrate() is speed().

The Google browser

Looks like I’ve failed to mention that alongside the disposable Firefox I’m now using a regular Chrome window for all things Google. That means my Gmail, Google Calendar, Google+, some of my Hangouts use and age-verification requiring YouTube-viewing now happens within that profile.

This has freed me from having to sign in to Google in the disposable Firefox. It was a bit of hassle because of 2FV, but to be honest, I’m sure I could have lived with it; what I think this was more about was the satisfaction from dividing the uses between the two browsers: Google’s browser for the Googly stuff, disposable Firefox for everything else.

I’m still using Android on the mobile side, and prefer to use Chrome there because pretending to gain any privacy from alternatives would be just that, pretense. So the divide on the desktop follows this reasoning, to maintain the strong mental association of Google’s services to Google’s browser. I also picked Chrome proper instead of Chromium for this reason: I don’t see any point in pretending to be safe from Google’s prying eyes when using their services, signed in.

There’s one (perhaps notable) exception among those services: if I use Google to search things, I use Firefox. For me, search benefits from my being signed in mostly only on the mobile (where I do often want to repeat earlier searches to save typing), on the desktop not so much. And on the desktop, searching on Google proper is the exception for me, I usually just use Startpage.

On Chrome’s side (on the desktop), my use is pretty strictly limited to the Google services I listed. That means that any external links within those services I will copy and paste into a Firefox instance. Thankfully, of those services, Hangouts is currently the only one using redirect URLs causing some extra hassle. The same issue is much more severe on Twitter, which goes to irritating lengths to obscure the original addresses behind their stupid shortening service. It’s one of those issues I previously would have fixed simply by installing an add-on, but now have to contemplate whether those links are worth manually decrypting, or even the site worth browsing at all because of the irritation that it causes.

I should also mention that I’ve extended the disposable profile idea to Chrome, so that I can launch a disposable Chrome window (alongside the main profile) from Unity’s launcher. (Unlike Ubuntu’s Chromium package, the Google-provided .desktop for Chrome did not provide this function out of the box.) This is mainly to have a browser with Adobe Flash for the few remaining sites I still occasionally deem worth having it on (I can only think of one off the top of my head).