Securing Transmission Daemon using OAuth2-Proxy
transmission-daemon
is a very helpful tool for someone that downloads files from time to time using torrent (use torrent responsibly folks). For people that never use transmission-daemon before, transmission-daemon has a webpage to manage things. That means you need to set up an authentication method to secure it.
Previously, I set up .htpasswd
authentication method to access the transmission daemon’s web UI. Really simple and straightforward. In case you need to add a new user, you only execute htpasswd .htpasswd newuser
. Until I found a new way to optimize this so that I no longer execute htpasswd
commands anymore in case add a new user.
OAuth2-Proxy is a reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others) to validate accounts by email, domain, or group.
That means we can use our account like GitHub or Google to access our service, a perfect replacement for .htpasswd
. In this medium, we’ll walk through the required steps to make your transmission-daemon
protected by OAuth2-Proxy (I’m going to use GCP’s API and Service).
Google Cloud Platform’s Section
First, you need to create an OAuth2 Client ID and Secret from GCP. I assume you already have an GCP account and have an active project.
- Access “OAuth consent screen” under the “API & Services” section.
Set the “User type” to “Internal”. The rest is a general question, you can directly set up your custom consent page (like using your own logo when someone authenticates themselves. If you left it blank, it’ll use the Google logo). - Open “Credentials” under “API & Services” section.
Click on “+ CREATE CREDENTIALS” and click on “OAuth client ID”. Set the “Application type” to “Web application”. There are some fields that you need to pay attention to, the rest is up to you. I only left some guidance to make it easier for you to set it up.
Authorized JavaScript origins. The HTTP origins that host your web application. This value can’t contain wildcards or paths. If you use a port other than 80, you must specify it.
Fill in the domain that you want to integrate with your service. For example https://tr.example.com (without trailing slash and include the scheme —https://
).
Authorized redirect URIs. Users will be redirected to this path after they have authenticated with Google. The path will be appended with the authorization code for access and must have a protocol. It can’t contain URL fragments, relative paths, or wildcards, and can’t be a public IP address.
Like “Authorized JavaScript origins”, you need to fill in the domain that you want to integrate with your service, but you need to add an additional path to it. Default, you need to add/oauth2/auth
to the domain. For example https://tr.example.com/oauth2/auth. - If everything is OK, you’ll get a client id and client secret. We need this to integrate with OAuth2-Proxy. Until this step, we’re finished with the GCP’s part. Let’s continue to the VM and set up OAuth2-Proxy.
OAuth2-Proxy’s Part
- Download the latest release based on your computer architecture from the GitHub release page and extract it to your server. After that, you need to add execute permission to the
oauth2-proxy
binary by executingchmod +x oauth2-proxy-{{ version }}.linux-amd64/oauth2-proxy
and move it to/usr/bin
. - Create a directory
/opt/oauth2-proxy/
and then create a file namedtransmission-daemon.conf
. Copy these templates and paste them to yourtransmission-daemon.conf
. You need to replace some parts of the template with these.
<CLIENT_ID_FROM_GCP_OAUTH>
and <CLIENT_SECRET_FROM_GCP_OAUTH>
from the GCP’s latest part on this medium. You can open the webpage again to check your client id and secret in case you forgot to store it somewhere.
<COOKIE_SECRET>
can be generated using a random string. You can generate one by using this command and copying the output. You need to store it safely (because this is a secret). Basically the command will produce some random string with base64 encoded.
dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d -- '\n' | tr -- '+/' '-_'; echo
# General config
upstreams = ["http://127.0.0.1:9091"] # default transmission-daemon port
email_domains = [ "<DOMAIN_NAME>" ] # use your google-email domain
http_address = ":8080" # use port where the oauth2-proxy will be running
request_logging = true
ssl_insecure_skip_verify = false
# The OAuth Client ID, Secret
client_id = "<CLIENT_ID_FROM_GCP_OAUTH>"
client_secret = "<CLIENT_SECRET_FROM_GCP_OAUTH>"
#Cookie Settings
cookie_secret = "<COOKIE_SECRET>"
cookie_name = "transmission_daemon"
cookie_expire = "24h"
cookie_secure = true
cookie_httponly = true
- Install
supervisor
on your system and ensure/etc/supervisor/conf.d/
existed in your server (assuming you’re using a Debian-based operating system. Other OS may vary). Create a file namedtransmission-daemon.conf
and copy these template and paste it.
[program:transmission-daemon]
command=/usr/bin/oauth2-proxy --config=/opt/oauth2-proxy/transmission-daemon.conf --ssl-upstream-insecure-skip-verify --reverse-proxy=true
process_name=%(program_name)s
priority=1
user=root
group=root
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/supervisor/transmission-daemon.log
- Run
sudo supervisorctl reread
andsudo supervisorctl update
to load the configuration that we recently created. To ensure everything is running perfectly, watch the log by executingsudo supervisorctl tail -f transmission-daemon
. If everything is OK, we finally arrived at the last part. NGINX configuration. - Final part. Copy these templates and paste them to
/etc/nginx/conf.d/transmission-daemon.conf
. After that executenginx -t
to ensure the configuration is correct and working. If everything is OK, executenginx -s reload
to apply the configuration.
server {
listen 80;
server_name <DOMAIN_NAME>;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name <DOMAIN_NAME>;
access_log /var/log/nginx/transmission.access.log;
error_log /var/log/nginx/transmission.error.log;
ssl_certificate <SSL_CHAIN_CERTIFICATE_FILE>;
ssl_certificate_key <SSL_PRIVATE_KEY_FILE>;
# optional part. this one for SSL config.
# include /etc/nginx/options-ssl-nginx.conf;
# ssl_dhparam /etc/nginx/ssl-dhparams.pem;
location /oauth2/ {
proxy_pass http://127.0.0.1:8080;
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 $request_uri;
}
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Basically, the NGINX config said something like this. In case you’re not authenticated using the mail domain that you registered during the OAuth2-Proxy’s part, you’ll be redirected to /oauth/sign_in
to authenticate yourself against /oauth2/auth
.
If the authentication succeeds, the system will create a cookie named transmission_daemon
on your browser so the next time you access the transmission webpage, you won’t be asked anymore. Else, you’ll be kicked out and need to retry the authentication process.
Hasta la vista .htpasswd
and thank you for your service.