extends article.pug

block append head
	link(rel='canonical' href='https://arav.top/stuff/article/nginx_recipes_and_tips')

block article
	header
		h2 NGiNX's recipes &amp; tips
		div.menu
			a(href='/stuff#articles') Go back to articles list
			time(datetime='2021-11-15') 15 November 2021
		nav
			h3 Contents
			ol
				li #[a(href='#art-1') Introduction]
				li #[a(href='#art-2') Userdir functionality like Apache's mod_userdir]
				li #[a(href='#art-3') Note on how NGiNX works with HTTP headers]
				li #[a(href='#art-4') Tell a Tor visitor of your clearnet site that you have an onion]
				li #[a(href='#art-5') Variables]

	h3#art-1 #[a(href='#art-1') 1. Introduction]
	p Here I'll place recipes for implementing different functionalities and notes on webserver's behaviour.

	h3#art-2 #[a(href='#art-2') 2. Userdir functionality like Apache's mod_userdir]
	p Once I wanted to have a &ldquo;tilde user directories&rdquo; like #[code /~user/] which is more known as Apache's #[code mod_userdir] feature. I work with NGiNX so regular expressions is the way to do that.
	p Nothing special in my case. I only need to keep files there, so others may get them. Thing is simple, but I took some time to realise what regexp to use here back then.
	p The implementation is quite simple:
	pre
		| location ~ ^/~(.+?)(/.*)?$ {
		|     alias /home/$1/pub$2;
		|     autoindex on;
		| }
	p Of course, you can choose whatever place for user's public directories. In my case you need to give a read and execute permissions to user's home directory and to public directories inside them to others (#[code chmod o=rX /home/user]), which may be a security concern.
	p #[code autoindex on] will make an index of files that lies by URL. And, of course, you can put there an #[code index.html] file.

	h3#art-3 #[a(href='#art-3') 3. Note on how NGiNX works with HTTP headers]
	p Let's say in #[code http] block you specified common headers like #[code X-Frame-Options], #[code X-XSS-Protection], and so on for all #[code server] directives to use. But, if you add some other header for a specific #[code server] or #[code location] block then all those headers would be dropped.
	p For now the only cure for it is to place all that headers in a separate file like #[code common-headers.inc] and using #[code include] directive to include them in all the #[code server] and #[code location] blocks where additional headers are added.

	h3#art-4 #[a(href='#art-4') 4. Tell a Tor visitor of your clearnet site that you have an onion]
	p There is a custom HTTP header #[code Onion-Location] that is being recognised by Tor Browser and it will show a ".onion available" button in an address bar.
	p The code for NGiNX is this simple:
	pre
		| add_header Onion-Location http://yoursite.onion$request_uri;
	
	h3#art-5 #[a(href='#art-5') 5. Variables]
	p Just wanna tell about this cool feature you can use to reduce code repetition. Alas, you can use them only in #[code server], #[code location] and #[code if] blocks. If only they could be declared in a #[code http] block, they'd be perfect. But still, they help a lot.
	p I heavily use aliases pointing to directories within the same base directory.
	p Judging from a little testing, variables doesn't decrease performance. Or I just don't notice it.
	p Variables could only store strings. To demonstrate the usage I'll just post here a part of my config:
	pre
		| set  $root  /srv/http/dwelling;
		| ...
		| location =/favicon.ico {
		| 	alias $root/shared/static/img/favicon.ico;
		| }
		| ...
		| location /assets/ {
		| 	alias $root/homepage/static/assets/;
		| }
	p The very reason why I had to use variables is that #[code alias] doesn't work with relative paths. I wish #[code alias] could be relative to #[code root], but we are forced to look for workarounds.
	p Update: Oh, I realised that you can declare variables in #[code http] block using #[code map] directive with #[code default] set to value you need. Funny, I've been using #[code map] to prevent LAN IPs from being logged all this time, heh. So, here's example:
	pre
		| map 1 $root {
		| 	default /srv/http/dwelling;
		| }
