Lightweight SSL/TLS reverse proxy with authorization(via Telegram and SSH) for self-hosted apps

  • By null
  • Last update: Apr 7, 2023
  • Comments: 0


Jauth is a lightweight SSL/TLS reverse proxy with authorization. Great for protect your self-hosted applications.

Login screenshot


  • Single binary executable with no dependencies
  • SSL/TLS encryption using autogenerated self-signed certificates or Let's Encrypt
  • User authorization via SSH or Telegram
  • Optional Singe Sign-On
  • Minimal configuration required
  • Whitelist-based access control
  • Support for multiple domain names
  • Security for bloated and vulnerable modern applications
  • Doesn't use any Telegram bot API
  • No passwords. No registration

Getting Started

  1. Download the latest release:
  1. Make executable:
chmod +x ./jauth
  1. Run ./jauth

Without the configuration, there will be the following behavior:

  • Generate a self-signed certificate valid for one year. It will be saved in the current directory and used on restart.
  • Run ssh server on for authorization. The list of authorized keys and their corresponding usernames is taken from ~/.ssh/authorized_keys. Server key from ~/.ssh/id_rsa
  • Run web server on which will redirect all incoming connections to port 443
  • Run web server on with generated certificate. It accepts connections from any domain or directly by ip address. Displays the login page.
  • After authorization, requests will be redirected to


By default, the server tries to open the ./jauth.toml file. You can specify any path/name as the first command line argument.

Simple but useful config example

# Use Let's Encrypt
Certificate.Type = "autocert"
SSO = ""
    # Telegram Id is a safe way because the ID never changes
    354339153 = "Jipok"
    # But using a username is more convenient. Need to add @
    "@Jipok" = "Jipok"
    # Username on right can be omitted, so telegram one will be used
    "@Jipok" = ""
    87654321 = "Other User"
    "@SomeFriend" = "Friend1"
[[Domains]] # Paperless NGX
    domain = ""
    target = "8080" # Will be ``
[[Domains]] # Grist
    domain = ""
    target = "8081" 
    # Some applications use e-mail for identification
    UserSuffix = "@local"
    # By default every user has access to every domain
    Whitelist = ["Jipok", "Friend1"]
    WidgetBotName = "JipokSelfHosted_bot"


  • To be able to authorize via telegram, you need to register your own bot. It's simple. WidgetBotName and WidgetBotToken must be received from the telegram bot @botfather. You also need to run the /setdomain command for this bot and specify the appropriate domain. Telegram will only allow authorization from this domain. jauth does not use a bot in any way. The token is needed only for authorization validation, the api is not called.
  • One telegram bot = one domain.
  • Each domain will require(from LE) its own certificate. This process is fast, but not instantaneous. Unfortunately, there may be no information about the process in the logs. You can just wait a little (30 seconds) and try to open the page in the browser.
  • The certificates will be saved in the ./jauth-autocert folder.
  • Login via ssh is enabled by default. The standard authorized_keys file format is used: each line contains a public key and a username. You can safely use your ~/.ssh/authorized_keys (default) from the system ssh server. You can also easily change the username specified there to the desired one, for sshd it means almost nothing.
  • The list of authorized users is preserved between restarts in ./jauth-tokens.txt
  • An authenticated user's username is passed to the server through the Remote-User HTTP header.

Full configuration example

# A more detailed SSH configuration is provided below
SSH.Enabled = false # Default true
# Used if target not specifies in some [[Domains]] section
# And for direct access via IP address in manual or self-signed mode
DefaultTarget = "8080"
# If true will drop privileges if started from root. 
# Will not be able to save state(tokens) between restarts.
DropPrivileges = false 
# Interface to listen
Listen = ""
# Start server on 80 port that will redirect all to 443 port
RedirectHTTP = true
# Time (in hours) after which an inactive session will be logged out.
MaxNonActiveTime = 30
# URL for log out
LogoutURL = "/jauth-logout"
# The page that is given for authorization. You can download index.html from
# the repository and modify the design, then specify this file.
# If empty, the built-in default is used.
CustomPage = ""
# Single Sing-On. It's really just the default value for the LoginFrom option
# on every domain. See its description below.
SSO = ""

    Enabled = true
    Port = "2222"
    ServerKey = "~/.ssh/id_rsa"
    AuthorizedKeys = "~/.ssh/authorized_keys"
    # Type can be:
    #   autocert - use Let's Encrypt
    #   self-signed - autogenerate
    #   manual - specify certificate. Example:
    Type = "manual" # Default self-signed
	Cert = "some-cert.crt" # Default "self-signed.crt"
	Key = "some-cert.key" # Default "self-signed.key"

    # Must not be empty
    domain = ""
    # If empty, will use DefaultTarget option 
    target = ""
    # Some applications use e-mail for identification
    UserSuffix = ""
    # List of users who will be allowed to use site. 
    # The rest will get NotInWhitelist.html
    Whitelist = []
    # If empty, then the telegram login widget will be hidden
    WidgetBotName = ""
    WidgetBotToken = ""
    # This is the domain to which user will be redirected for authorization.
    # In addition to Single Sing-On function, it is also necessary in order
    # not to produce a lot of telegram bots, since telegrams are allowed to
    # log in through the bot on only one domain. An empty value means that
    # the current domain will be used.
    LoginFrom = ""

Thanks to


I am a lover of minimalism (in the style of suckless). So for me the project is mostly finished. If you want to add some feature, then start a discussion before writing the code, as I can simply dismiss the idea.