How to Compile and Install OpenSSH from Source in Linux

OpenSSH is a free and open source, full implementation of the SSH protocol 2.0, which provides a number of tools for securely accessing and managing remote computer systems, and managing authentications keys, such as ssh (a secure replacement for telnet), scp, sftp (secure replacement for ftp), ssh-keygen, ssh-copy-id, ssh-add, and more.

Recently OpenSSH 9.3 was released and ships with many new features and bug fixes; you can read the SSH release notes for more information.

In this article, we will explain how to install and configure the latest version of the OpenSSH server and client on a Linux system from sources. We assume that you have an existing installation of the OpenSSH suite.


  • A Debian/Ubuntu or RHEL/CentOS Linux system
  • C compiler
  • Zlib 1.1.4 or or greater
  • LibreSSL or OpenSSL >= 1.0.1 < 1.1.0

Install OpenSSH Server from Source

Before installing the latest version of SSH, make sure to check the current version of SSH installed on your system using the following command.

$ ssh -V

OpenSSH_7.7p2 Ubuntu-4ubuntu2.5, OpenSSL 1.0.2g	1 Mar 2016

From the above result, the installed OpenSSH version is 7.7, to install the latest OpenSSH version, first, you need to install a few dependencies, i.e development tools or build essentials and the other required packages, as follows.

-------------- On RedHat-based Distros --------------
$ sudo yum update
$ sudo yum group install 'Development Tools'
$ sudo yum install zlib-devel openssl-devel

-------------- On Debian-based Distros --------------
$ sudo apt update 
$ sudo apt install build-essential zlib1g-dev libssl-dev 

To create a proper environment for installing the OpenSSH server, we need to create a new system user and group named “sshd”, as well as a safe place to chroot.

Note: Generally, if you have an existing installation, this environment should already be in place, you can skip this section and go to the next. Otherwise, run the following commands to set it up.
$ sudo mkdir /var/lib/sshd
$ sudo chmod -R 700 /var/lib/sshd/
$ sudo chown -R root:sys /var/lib/sshd/
$ sudo useradd -r -U -d /var/lib/sshd/ -c "sshd privsep" -s /bin/false sshd

Explaining the flags in the useradd command above:

  • -r – tells useradd to create a system user
  • -U – instructs it to create a group with the same name and group ID
  • -d – specifies the user’s directory
  • -c – used to add a comment
  • -s – specifies the user’s shell

Now, download the tarball of OpenSSH version 9.3 from any of the available HTTP mirrors or you can use the following wget command to download directly in your terminal.

$ wget -c
$ tar -xzf openssh-9.3p1.tar.gz
$ cd openssh-9.3p1/

Now we will build and install the OpenSSH server using the --with-md5-passwords, --with-privsep-path and --sysconfdir options, which will install all the files in /usr/local/ (this is the default installation PREFIX).

You can see all available options by running ./configure -h and customizing your installation further.

$ ./configure -h

For instance, to enable PAM and SELinux support, add the --with-pam and --with-selinux options, respectively, you need to install all the necessary header files for them to work.

## Install PAM and SELinux Headers ##
$ sudo apt install libpam0g-dev libselinux1-dev   [On Debian/Ubuntu]
$ sudo yum install pam-devel libselinux-devel     [On CentOS/RHEL]

## Compile and Install SSH from Sources ##
$ ./configure --with-md5-passwords --with-pam --with-selinux --with-privsep-path=/var/lib/sshd/ --sysconfdir=/etc/ssh 
$ make
$ sudo make install 

Once you have installed OpenSSH, restart SSH or open another terminal window and check the version of OpenSSH now installed on your system.

$ ssh -V

OpenSSH_9.3p1, OpenSSL 3.0.1 14 Dec 2021

The various OpenSSH configuration files are located at:

  • ~/.ssh/* – this directory stores user-specific ssh client configurations (ssh aliases) and keys.
  • /etc/ssh/ssh_config – this file contains system-wide ssh client configurations.
  • /etc/ssh/sshd_config – contains sshd service configurations.

To configure ssh aliases, see: How to Configure Custom SSH Connections to Simplify Remote Access

You might also like to read the following SSH-related articles.

That’s it! In this article, we’ve explained how to install and configure the latest version of the OpenSSH server from a source on a Linux system. If you have any questions or comments, use the feedback form below to reach us.

Hey TecMint readers,

Exciting news! Every month, our top blog commenters will have the chance to win fantastic rewards, like free Linux eBooks such as RHCE, RHCSA, LFCS, Learn Linux, and Awk, each worth $20!

Learn more about the contest and stand a chance to win by sharing your thoughts below!

Aaron Kili
Aaron Kili is a Linux and F.O.S.S enthusiast, an upcoming Linux SysAdmin, web developer, and currently a content creator for TecMint who loves working with computers and strongly believes in sharing knowledge.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.


Leave a Reply
  1. We have done the above step and the openssh version has been updated but when we remove old ssh like 8.9p1 we can able to get the ssh server.

    Please help me for removing the old one and work with the new openssh.

  2. I have followed all the guides. As a non-root user, it can display OpenSSH v8, but when as a root user it still shows OpenSSH v7. What’s wrong with my installation? thanks.

      • The good day Aaron:

        Is the SSH server directory included when you download the Ubuntu OS?

        Subsequently, is the micro Linux text editor a separate directory contained within a specific Ubuntu distribution?

        Please reply.

  3. Ah Sorry guys Adrian – All hopes the errors can be found in my posted script – there are some errors and also Note: the actual .configure command-line for each stage – must be all one line or if an error is encounter – being a vi conditioned fossil Control-4 and Control-6, at a line in question will take you too the beginning and or end of line – seeing that if you do copy as such the actual command could be broken shown when actually executing the code, – do the control-4 to end of what chars in that command-line that is failing at that point control-j will pull up the break – x out 1 char space recreating the proper syntax line – most break at dash dash of an option.

    SSL is to have -fPIC. Be honest to say – each compile session can throw one for a loop. make clean after attempts can help – read the READMEs and INSTALLs in each package if your attempting my similar fate.

    One can use my script and remove most all between apt-get gcc* Up-Too part actually installing openssh-8.0p1 .. Adrian is correct – simple method and does work.. Thanks all and hope success. I have re-written parts of the script. I will not repost unless request too. Only then to ask Adrian if he can “Clean my previous bad post” – well its no totally bad – errors contained in another expression, I’ll end here. myScript does provide a good framework to build from. (meHacker)

  4. Thanks for posting my Script. Its vanilla to run – the Chk part is simply an Exit 0 status check for steps in process if that makes sense ( does to me so I know when the script runs each step is progressing correctly. All hopes all can learn and feel free to fix any errors or other mistakes I may have made – this does work on the last 4 installs I have performed. Free to learn from. Cheers.

  5. One Caveat is to install the “build-essential” Pkg not with an S on the end that will mess you up: I’m going to fire my own script I wrote to speed up the Process: This does work for me.

    Although I have seen openssl go in and not go in correctly. So try this its basic – some work will be required by your part to set your Compile directories for openssh-8 for your “untar’d location after download”.

    This has all Adrians Steps and few addons prior for GCC 7 and 8 files which I found after these – all worked. Simply an attempt to share and help those to help themselves.

    # my configure script to install zlib-1.2.11 openssl-1.1.1a and openssh-8.0p1 Latest - all if pkgs are in
    # myDwn/newSoft/ as untarred directory contents ready to compile: This script will do it all
    # This script will perform all to install all 3 main system components for ssh support
    # Checks-Performed-Operated:
    # 1-rootUser only
    # 2-Pre-Liminary Setup name/dir/groups/perms - build-essential for compile
    # 3-Zlib
    # 4-openssl
    # 5-openssh w/checks inbetween per Completed response $?=0 if done wez all-In
    # Note: Take as learning experience: no accountability for what you may do with this script
    # tdk = Tap the AnyKey = Just tap the Enter Key on your keyboard

    HST1=`uname -n`
    CheckID2() {
    if [ "$ME" != root ]; then
    zenity --width="400" --error \
    --text="SU ROOT ONLY: $ME Sudo RootUser Operator Only: $HST1" 2>/dev/null
    echo -e "Cmdline Requirez: sudo su - ; Privileges Only: -tdk-"
    read junk
    exit 1

    zenity --width="400" --info --text="Operator Root: Amigo-Right!:" 2>/dev/null
    tput cup 10 28
    echo -e "Root Level Achieved: -TDK-"
    read junk

    PreLym() {
    #echo -e "SetUp Dirs Perms Owner group add and user set
    #-----# setup ssh dirs Part 1
    sudo mkdir /var/empty
    chmod -R 755 /var/empty
    sudo chown -R root:sys /var/empty
    #-----# setup ssh dirs Part 2
    sudo mkdir /var/lib/sshd
    sudo chmod -R 700 /var/lib/sshd
    sudo chown -R root:sys /var/lib/sshd/
    #-----# setup group add
    groupadd sshd
    useradd -g sshd -c 'sshd privsep' -d /var/empty -s /bin/false sshd
    #-----# setup fake user creds
    sudo useradd -r -U -d /var/lib/sshd/ -c "sshd privsep" -s /bin/false sshd
    sudo apt update
    #-----# HERE IT IS Start : basics Go
    sudo apt install gcc-7-base -y
    sudo apt install gcc-7-cross-base -y
    sudo apt install gcc-7-cross-base-ports -y
    sudo apt install gcc-8 -y
    sudo apt install gcc-8-base -y
    sudo apt install gcc-8-cross-base -y
    sudo apt install build-essential -y
    sudo apt install ekeyd-egd-linux -y
    sudo apt install zlib1g-dev -y
    sudo apt install libssl-dev -y
    #-----# Do It all from here

    # this shud help automagic the process - the read junks provide interactive step procedure -
    # having a Check last cmd exit status is a bonus to just watching it all happen after execution.

    ChkZero() {
    if [ $? = 0 ]; then
    echo -e "Compile Step Success-NextStep Proceeding Patience"
    # read junk
    echo -e "cmdLine wasNOT successful ERRORED....ERROR.....ERROR......ERROR......ERROR.....!"
    # read junk

    echo -e "See This: PreLiminary works all prepared and ready to ZoomUp All Security Compile and Updates -tdk-"
    cd /myDwn/newSoft/zlib-1.2.11
    echo -e "PWD The HERE: /myDwn/newSoft/zlib-1.2.11 directory and at last install to latest version ssh -tdk-"
    echo -e "Make Sure we are in Each Step Directory Prior to smacking the Enter AnyKey Pls -tdk- To go for it! -- yes This IS REAL .....!"
    read junk
    echo -e "Zlib-1.2.11 installing Steps: -tdk- configure complete"

    make test
    echo -e "Make TEST for Zlib-1.2.11 process installing full scratch compile"

    make install
    echo -e "Check Zero shows run okay -tdk- to Install Openssl-1.1.1a Next:"
    cd /myDwn/newSoft/openssl-1.1.1a
    echo -e "PWD The HERE: /myDwn/newSoft/openssl-1.1.1a directory and at last install to latest version ssh -tdk-"
    echo -e "Make Sure we are in Each Step Directory Prior to smacking the Enter AnyKey Pls -tdk- To go for it!"

    echo -e "Ready to install open-ssl layer now -tdk-"

    make clean
    dd if=/usr/bin/rand of=seed1 bs=1021M count=2041
    dd if=/usr/bin/rand of=seed2 bs=98304 count=1023
    dd if=/usr/bin/rand of=seed3 bs=294912 count=2048

    ./config -v --prefix=/opt/openssl --openssldir=/usr/local/ssl -Wl --enable-new-dtags --with-rand-seed=seed1,seed2,seed3 --with-zlib-include=/
    usr/local/include --with-zlib-lib=/usr/local/lib --no-Protocol1-method --no-dsa --no-ecdsa --enable-egd --zlib

    make test
    make install
    echo -e "Last Step openssh-8.0p1 Compile-Install"
    cd /myDwn/newSoft/openssh-8.0p1
    echo -e "PWD The HERE: /myDwn/newSoft/openssh-8.0p1 directory and at last install to latest version ssh -tdk-"
    make clean
    echo -e "Make Clean Done -CantHurt but- Ready Go Configure -tdk-"
    ./configure --prefix=/usr --with-md5-passwords --with-privsep-path=/var/empty --with-ssl-dir=/opt/openssl/include/openssl --with-ssl-engine -
    echo -e "\nINTENSE: - Executing NOW! -tdk-"
    make install
    echo -e "\nAll Compiling Completed: The End - zLib openSSL and openSSH-8.0p1 now Installed - next ssh -V to check version Ref\n"
    read junk

    exit $?
    #-----------------------------------------------------------------------------------------------End of script---------------------------------------------------------------------------------

    my Only hopes this does help people with this process. Keep trying reading digging answers are always available – sharing is much more fun when it does help .. So this is only my hope.. Enjoy learn and pass on..

  6. Hi,

    I followed your guide, and when I type command ssh -V it is showing 8.0, but when I type ssh -v localhost it is showing the following:

    debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4
    debug1: match: OpenSSH_7.4 pat OpenSSH_7.0*,OpenSSH_7.1*,OpenSSH_7.2*,OpenSSH_7.3*,OpenSSH_7.4*,OpenSSH_7.5*,OpenSSH_7.6*,OpenSSH_7.7* compat 0x04000002

    I’m failing PCI scans due to vulnerabilities in 7.4.

  7. Hi, This worked when I check ssh -V with normal user, but if I log in as root and check ssh -V it still shows the old version…

    [cyclesam10@super ~]$ ssh -V
    OpenSSH_8.0p1, OpenSSL 1.0.2k-fips  26 Jan 2017
    [myusername@super ~]$ sudo -s
    [root@super myusername]# ssh -V
    OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017
  8. @Aaron Kili, thanks for sharing.

    I followed your steps and got openssh-8.0p1 installed on my Ubuntu 16 machine.

    While issuing command: ssh -V, it gave back the correct version as:

    # ssh -V
    OpenSSH_8.0p1, OpenSSL 1.0.2g  1 Mar 2016

    but for some reason while I issued command: dpkg --list openssh-server, it still gave me the previous version came with the machine:

    root@localhost:~# dpkg --list openssh-server
    | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
    |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
    ||/ Name             Version              Architecture   Description
    ii  openssh-server   1:7.2p2-4ubuntu2.8   amd64          secure shell (SSH) server, 
                                                             for secure access from remote machines

    Could you please give me some hint of where I did wrong or where should I do extra to update the registry information on the machine? Or is it because we compiled the update rather than using system package manager so that there is ssh still missing update?


      • The same thing after reboot.

        • root@localhost:~# ssh -V gives output: OpenSSH_8.0p1, OpenSSL 1.0.2g 1 Mar 2016
        • root@localhost:~# dpkg --list openssh-server gives output: openssh-server 1:7.2p2-4ubuntu2. amd64

        I doubt if the cause is dpkg never got to know that I compiled a newer version into system.

  9. Although if you compile and install 7.9 successfully, this will not replace the existing sshd bin file (you can check with ssh -v localhost) , don’t know what’s the reason, but i had to rsync the compiled bin file to the existing sshd.

    OS: Ubuntu 18.04 LTS

    See the difference

    root@newsky:/home/it# /usr/local/sbin/sshd -V
    unknown option -- V
    OpenSSH_7.9p1, OpenSSL 1.1.0g  2 Nov 2017
    usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]
                [-E log_file] [-f config_file] [-g login_grace_time]
                [-h host_key_file] [-o option] [-p port] [-u len]
    root@newsky:/home/it# /usr/sbin/sshd -V
    unknown option -- V
    OpenSSH_7.6p1 Ubuntu-4ubuntu0.3, OpenSSL 1.0.2n  7 Dec 2017
    usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]
                [-E log_file] [-f config_file] [-g login_grace_time]
                [-h host_key_file] [-o option] [-p port] [-u len]

    I did rsync with below command (note: backup sshd bin file before you replace)

    # rsync -avP /usr/local/sbin/sshd /usr/sbin/sshd

    and then when i connect to ssh with debug (-v) it shows correct 7.9 version!.

    Just a doubt: is this way correct or anything more should be done?.

  10. On Ubuntu 18.04 when enabling selinux and PAM throws errors :

    configure: error: SELinux support requires selinux.h header
    configure: error: PAM headers not found

    Needs this additionally installed:

    # apt install libselinux1-dev libpam0g-dev
  11. one other caveat on linux there appears to be no prngd generator there is no info as to using replacement on Linux when working this type of additional number and cipher picks. Nice to see many methods and info towards this. It is hard finding a syntax example that works correctly.

    • Aarons awesome.

      This method does work great Now testing 2nd fresh install on Mint 19.1 Mate. A pre-install of latest tarball zlib and openssl-1-1-1a, plain out tar .configure then follow these steps – worked 2nd time assembling the steps into a script (I can fire it up if wish) to stream Line this openssh-7.9p1 update. (PRNGD or EGD be nice for Linux).

      I’m simply brain crammed as to why distro crews do not keep zlib openssl and openssh always to their latest. This represents our security and integrity using these OS distros and saying its a Debian stable etc is just plain weak for older levels.

      Other just as cool distros keep their Updates ie: Latest for the important integrity of their works. Please get the message. Just a few more pkg adjustments and you can keep us all more happy users with your work. Cheers

  12. I did manage to compile openssh-7.9p1 along with openssl and zlib. also without SElinux option or –sysconfdir=/etc/ssh – that didn’t seen to matter for the compile step – most likely I’m missing parts for correct compiling tools and library resource be my only thought to still seeing misses on the final ending.

    Work in progress – resorting to a Virtual Guest to attempt better learning steps. working to order logic zlib 1st openssl 2nd and openssh 3rd to raw compile. – BIG on my List to Wana Know is make clean and or “Re- runs to recompile and know I can remove my previous attempt to compile files and Start again. So when finally click with the right commandline and resources the end result will not be bloated scrap files around my system. ?

  13. possibly only caveat I may ask of – is For what Starting Directory should this Process be started from – if existing ssh version is already installed – i.e: in one form where should could the openssh*.tar.gz “tarball” go to work this – ~/username/temp dir or /tmp system directory and apt-get Newest Version of openssh and have it be downloaded and gunzip’d there ?


Got Something to Say? Join the Discussion...

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.