New blog post: Setting up OwnTracks recorder and OAuth2 with nginx and
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
			
		
		
	
	
		
	
		
			Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			podman
This commit is contained in:
		
					parent
					
						
							
								463055c266
							
						
					
				
			
			
				commit
				
					
						cf5d4f6d7f
					
				
			
		
					 2 changed files with 160 additions and 12 deletions
				
			
		|  | @ -3,9 +3,9 @@ categories: | |||
| - linux | ||||
| - opensuse | ||||
| comments: true | ||||
| date: 2021-07-25 00:30:28+02:00 | ||||
| date: 2021-08-01 00:30:28+02:00 | ||||
| disable_share: true | ||||
| draft: true | ||||
| draft: false | ||||
| featured_image: /images/banner.jpg | ||||
| omit_header_text: true | ||||
| toc: true | ||||
|  | @ -166,14 +166,14 @@ podman run \ | |||
| 
 | ||||
| As you can see, the syntax is very close to what Docker does. You can omit the `--rm` switch if you don't want the container to be deleted when you stop it (it might be relevant for startup, as I'll explain later). | ||||
| 
 | ||||
| Check if the Recorder is actually running: | ||||
| Check if the Recorder is actually running (you can just use `podman ps` but here I show a slightly more complex approach to make output slimmer): | ||||
| 
 | ||||
| ```shell | ||||
| podman ps | ||||
| podman ps \ | ||||
|     -f 'name=ot_.*' \  # Only show containers starting with "ot" | ||||
|     --format '{{ .ID }}\t{{ .Image}}\t{{.Names}}\t{{.Status}}\t{{.Pod}}' | ||||
| 
 | ||||
| CONTAINER ID  IMAGE                                 COMMAND               CREATED      STATUS          PORTS                                                                       NAMES | ||||
| [...] | ||||
| 843222dacfd7  docker.io/owntracks/recorder:latest                         7 days ago   Up 7 days ago   127.0.0.1:6666->80/tcp,  127.0.0.1:8083->8083/tcp  ot_recorder | ||||
| 843222dacfd7  docker.io/owntracks/recorder:latest  ot_recorder  Up 2 weeks ago  ff8bb4e9dac2 | ||||
| ``` | ||||
| 
 | ||||
| You might want to check also the logs for possible errors with `podman logs ot_recorder`. | ||||
|  | @ -398,7 +398,7 @@ client_secret = "CLIENT_SECRET" | |||
| ## Additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -B" for bcrypt encryption | ||||
| ## enabling exposes a username/login signin form | ||||
| htpasswd_file = "/etc/nginx/owntracks.htpasswd" | ||||
| display_htpasswd_form = true | ||||
| display_htpasswd_form = false | ||||
| 
 | ||||
| ## Cookie Settings | ||||
| ## Name     - the cookie name | ||||
|  | @ -421,9 +421,11 @@ cookie_secure = true | |||
| cookie_httponly = true | ||||
| ``` | ||||
| 
 | ||||
| Note there are a few options to fill in, in particular the OAuth2 provider. There are plenty of options to choose from: they range from external services (GitHub, Google) to self-hosted ones (Nextcloud, Gitea, Gitlab, Keycloak...). Refer to the [oauth2-proxy documentation](https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/oauth_provider) on how to set them up. I'll go through my personal choice later. | ||||
| Note there are a few options to fill in, in particular the OAuth2 provider. There are plenty of options to choose from: they range from external services (GitHub, Google) to self-hosted ones (Nextcloud, Gitea, Gitlab, Keycloak...). Refer to the [oauth2-proxy documentation](https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/oauth_provider) on how to set them up. | ||||
| 
 | ||||
| You also need to create the static user(s) for the OwnTracks app. I have found no other way to avoid it. If you know a better way that avoids this, let me know. | ||||
| Personally, I wanted to use [mailcow](https://mailcow.github.io/mailcow-dockerized-docs/), which can also act as an OAuth2 authentication source, but [it does not support OpenID Connect fully](https://github.com/mailcow/mailcow-dockerized/issues/684), therefore I settled for my [Gitea](https://gitea.io) instance, which then in turn authenticates against mailcow. Complicated, but does the job. | ||||
| 
 | ||||
| Lastly, you also need to create the static user(s) for the OwnTracks app. I have found no other way to avoid it. If you know a better way that avoids this, let me know. | ||||
| 
 | ||||
| ```shell | ||||
| htpasswd -c /etc/nginx/owntracks.htpasswd | ||||
|  | @ -483,8 +485,154 @@ If you want to be fancier and want it to start only when required, you can alway | |||
| 
 | ||||
| Now, we need to add the relevant information to nginx. | ||||
| 
 | ||||
| First we create a `server` stanza for our authentication service: | ||||
| 
 | ||||
| ## The ideal source of authentication | ||||
| ```nginx | ||||
| server { | ||||
|   listen 443 ssl http2; | ||||
|   listen [::]:443 ssl http2; | ||||
| 
 | ||||
| ## Gluing it all together | ||||
|   server_name auth.example.com; | ||||
|   server_tokens off; | ||||
| 
 | ||||
|   # Add SSL data, etc. here | ||||
| 
 | ||||
|   location / { | ||||
|         proxy_set_header X-Real-IP  $remote_addr; | ||||
|         proxy_set_header Host       $host; | ||||
|         proxy_set_header X-Scheme   $scheme; | ||||
|         proxy_pass       http://127.0.0.1:4180; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Then we create a file called `/etc/nginx/oauth2.conf` which will contain an *internal* (not accessible from outside) location to handle authentication requests: | ||||
| 
 | ||||
| ```nginx | ||||
|   location /internal-auth/ { | ||||
|     proxy_pass       http://127.0.0.1:4180/; | ||||
|     internal; | ||||
|     proxy_set_header Host                    $host; | ||||
|     proxy_set_header X-Real-IP               $remote_addr; | ||||
|     proxy_set_header X-Scheme                $scheme; | ||||
|     proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; | ||||
|   } | ||||
| ``` | ||||
| 
 | ||||
| Lastly, we create a file called `/etc/nginx/oauth2_parameters` to specify the parameters used in the location stanzas we actually want to protect with authentication. The contents: | ||||
| 
 | ||||
| ```nginx | ||||
| auth_request /internal-auth/oauth2/auth; | ||||
| # the ?rd parameter ensures you are properly redirected after authentication | ||||
| error_page 401 = https://auth.example.com/oauth2/start?rd=$scheme://$host$request_uri; | ||||
| # pass information via X-User and X-Email headers to backend, | ||||
| # requires running with --set-xauthrequest flag | ||||
| auth_request_set $user   $upstream_http_x_auth_request_user; | ||||
| auth_request_set $email  $upstream_http_x_auth_request_email; | ||||
| proxy_set_header X-User  $user; | ||||
| proxy_set_header X-Email $email; | ||||
| # If you have set cookie refresh in oauth2-proxy, uncomment the two lines below | ||||
| # auth_request_set $auth_cookie $upstream_http_set_cookie; | ||||
| # add_header Set-Cookie $auth_cookie; | ||||
| ``` | ||||
| 
 | ||||
| You can use either `start` or `sign_in` for the `error_page` line. The former forwards you immediately to your authentication source, while the latter offers a "Sign up with XXX" and a form for httpasswd authentication, if enabled in the oauth2-proxy configuration. As the OwnTracks app will send the Basic Authentication requests directly, I decided not to enable the form and have users go directly to authentication. | ||||
| 
 | ||||
| ### Finishing touches | ||||
| 
 | ||||
| Once that's all and done, you just need to tell nginx to use what you just wrote. Modify the OwnTracks stanzas as follows: | ||||
| 
 | ||||
| ```nginx | ||||
| include oauth2.conf; | ||||
| 
 | ||||
| location / { | ||||
|     include oauth2_params; | ||||
|     proxy_pass              http://127.0.0.1:6666/; | ||||
|     proxy_http_version      1.1; | ||||
|     proxy_set_header        Host $host; | ||||
|     proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for; | ||||
|     proxy_set_header        X-Real-IP $remote_addr; | ||||
| } | ||||
| 
 | ||||
| # Only changed sections are shown | ||||
| 
 | ||||
| location /owntracks/ { | ||||
|     include oauth2_params; | ||||
|     proxy_pass      http://127.0.0.1:8083/; | ||||
|     proxy_http_version  1.1; | ||||
|     proxy_set_header    Host $host; | ||||
|     proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for; | ||||
|     proxy_set_header    X-Real-IP $remote_addr; | ||||
| } | ||||
| 
 | ||||
| # And further below... | ||||
| 
 | ||||
| location /owntracks/pub { | ||||
|     include oauth2_params; | ||||
|     proxy_pass              http://127.0.0.1:8083/pub; | ||||
|     proxy_http_version      1.1; | ||||
|     proxy_set_header        Host $host; | ||||
|     proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for; | ||||
|     proxy_set_header        X-Real-IP $remote_addr; | ||||
| 
 | ||||
|     # Optionally force Recorder to use username from Basic | ||||
|     # authentication user. Whether or not client sets | ||||
|     # X-Limit-U and/or uses ?u= parameter, the user will | ||||
|     # be set to $remote_user. | ||||
|     # proxy_set_header        X-Limit-U $remote_user; | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Ensure oauth2-proxy is running, then restart nginx. Try accessing `https://tracks.example.com` and you should be redirected to your authentication provider's login form. Once logged in, you should be redirected again to the OwnTracks frontend. | ||||
| 
 | ||||
| ## Adding our server to the OwnTracks app | ||||
| 
 | ||||
| Now that authentication is set up on the web page, we need to configure the OwnTracks app. | ||||
| 
 | ||||
| The following screenshots were made on Android. The IOS app may be different. YMMV. | ||||
| 
 | ||||
| First of all, tap the hamburger menu and select Preferences (click on all the images for a larger version): | ||||
| 
 | ||||
| {{< imgthumb src="images/2021/08/owntracks1.jpg" size="x300" caption="Hamburger menu" class="w-third center" >}} | ||||
| 
 | ||||
| Then, tap on Connection: | ||||
| 
 | ||||
| {{< imgthumb src="images/2021/08/owntracks2.jpg" size="x300" caption="Settings page" class="w-third center" >}} | ||||
| 
 | ||||
| Once on this screen, you can set both the URL and your username/password combination. First, ensure that mode is set to HTTP (if not, change it). | ||||
| 
 | ||||
| {{< imgthumb src="images/2021/08/owntracks5.jpg" size="x300" caption="Host setup form" class="w-third center" >}} | ||||
| 
 | ||||
| Then tap on host, and insert the url as `https://tracks.example.com/owntracks/pub` (the `pub` is important, as it's the HTTP API endpoint). | ||||
| 
 | ||||
| {{< imgthumb src="images/2021/08/owntracks3.jpg" size="x300" caption="Connection page" class="w-third center" >}} | ||||
| 
 | ||||
| Then, insert the username and password combination you generated earlier with `httpasswd`. | ||||
| 
 | ||||
| To test that the connection is actually working, exit the settings and enable location services on your phone. An up arrow icon in the OwnTracks app will light up (it's to manually upload the location). Hit it, and then tap again on the hamburger menu, selecting "Status", this time. If everything has gone well, you should see something like this: | ||||
| 
 | ||||
| {{< imgthumb src="images/2021/08/owntracks4.jpg" size="x300" caption="OwnTracks connection status page" class="w-third center" >}} | ||||
| 
 | ||||
| If you then go to the frontend, you should see a pin where your location has been successfully recorded. | ||||
| 
 | ||||
| And thus, everyhing is set up. We're done. | ||||
| 
 | ||||
| {{< figure src="/images/2021/08/hannibal.jpg">}} | ||||
| 
 | ||||
| ## Trouble? What kind of trouble? | ||||
| 
 | ||||
| In case something goes wrong, there are a few places you can check: | ||||
| 
 | ||||
| - For OAuth2-proxy, the oauth2-proxy logs with `journalctl -u oauth2-proxy`; | ||||
| - For OwnTracks, the podman logs with `podman logs ot_frontend` or `podman logs ot_recorder` | ||||
| - For all the rest, the nginx logs. | ||||
| 
 | ||||
| ## Wrap up | ||||
| 
 | ||||
| A nice bonus of this setup is that you can potentially add OAuth2 authentication to any application you have running if it does not provide authentication itself, as long as it runs in the same domain. | ||||
| 
 | ||||
| I wrote this guide because the (not large) resources on oauth2-proxy mainly deal with Kubernetes, and many, other essential bits of information are scattered throughout the net. I hope it will be useful to someone (well, at least it was useful to *me*, so that's a start). | ||||
| 
 | ||||
| Have fun! | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue