Skip to content

Instantly share code, notes, and snippets.

@polyrand
Forked from olbat/ssh-tunnel-systemd.md
Last active November 26, 2020 18:07
Show Gist options
  • Select an option

  • Save polyrand/6f9987a7cfb09244a8e18f61b814c2d7 to your computer and use it in GitHub Desktop.

Select an option

Save polyrand/6f9987a7cfb09244a8e18f61b814c2d7 to your computer and use it in GitHub Desktop.

Revisions

  1. @olbat olbat revised this gist Sep 15, 2017. 1 changed file with 99 additions and 18 deletions.
    117 changes: 99 additions & 18 deletions ssh-tunnel-systemd.md
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,24 @@
    # Create SSH tunnels using systemd units


    ## Table of contents
    * [Overview](#overview)
    * [Setup the SSH agent systemd unit](#setup-the-ssh-agent-systemd-unit)
    * [Setup the SSH-tunnel systemd unit](#setup-the-ssh-tunnel-systemd-unit)
    * [Create tunnels using systemd services](#create-tunnels-using-systemd-services)
    * [Examples](#examples)
    * [Create a tunnel to a web server on a machine that's only accessible by SSH](#create-a-tunnel-to-a-web-server-on-a-machine-thats-only-accessible-by-ssh)
    * [Create a tunnel to a MySQL service only accessible through an SSH bastion (directly)](#create-a-tunnel-to-a-mysql-service-only-accessible-through-an-ssh-bastion-directly)
    * [Create a tunnel to a MySQL service only accessible through an SSH bastion (using SSH)](#create-a-tunnel-to-a-mysql-service-only-accessible-through-an-ssh-bastion-using-ssh)
    * [Further reading](#further-reading)


    ## Overview
    This systemd service scripts will allow you to create SSH tunnels in background
    using systemd in user mode and a configuration file.


    ## Setup the SSH authentication agent systemd unit
    ## Setup the SSH agent systemd unit
    To be able to run SSH tunnels in background while using a password protected SSH
    key to connect to the targeted host, we'll first have to setup an _ssh-agent_
    (see [ssh-agent(1)](https://linux.die.net/man/1/ssh-agent)).
    @@ -57,11 +70,11 @@ using ssh-add (see [ssh-add(1)](https://linux.die.net/man/1/ssh-add)).
    ```bash
    ssh-add
    ```
    _Note:_ __it have to be done at every boot in order for the tunnels to work !__
    _Note:_ __it has to be done at every boot in order for the tunnels to work !__


    ## Setup the SSH-tunnel systemd unit
    As for the [SSH authentication agent](#setup-the-ssh-authentication-agent-systemd-unit) service, we'll run our SSH tunnels ([ssh(1)](https://linux.die.net/man/1/ssh)) using a _systemd service unit_ but this unit will be instanciable (see [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [Lennart Poettering's blog](http://0pointer.de/blog/projects/instances.html), [Arch Linux wiki page](https://wiki.archlinux.org/index.php/Systemd#Using_units), [Fedoramagazine article](https://fedoramagazine.org/systemd-template-unit-files/)).
    As for the [SSH authentication agent](#setup-the-ssh-agent-systemd-unit) service, we'll run our SSH tunnels ([ssh(1)](https://linux.die.net/man/1/ssh)) using a _systemd service unit_ but this unit will be instanciable (see [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [Lennart Poettering's blog](http://0pointer.de/blog/projects/instances.html), [Arch Linux wiki page](https://wiki.archlinux.org/index.php/Systemd#Using_units), [Fedoramagazine article](https://fedoramagazine.org/systemd-template-unit-files/)).

    ```bash
    # (create the systemd config directory if it does not exists)
    @@ -92,7 +105,8 @@ WantedBy=multi-user.target
    EOF
    ```

    ## Create tunnels !

    ## Create tunnels using systemd services
    We'll now create _systemd service instances_ to run our tunnels.

    Our _ssh-tunnel_ service is going to look for it's configuration file into
    @@ -146,35 +160,102 @@ We can check the tunnel's status using:
    systemctl --user status -l ssh-tunnel@testtun
    ```

    Or list the _systemd services_ of current user:
    ```bash
    systemctl --user list-units --type=service
    ```

    ## Example: create an SSH tunnel to a MySQL service only accessible through an SSH bastion

    Let's create a configuration file to access to the MySQL service (_3306_ port)
    of the _machine001.domain.tld_ machine that's only through the
    _access.domain.tld_ bastion and make the tunnel accessible to other machines
    over the network:
    ## Examples

    ### Create a tunnel to a web server on a machine that's only accessible by SSH

    Let's create a configuration file to access to the web server (_80_ port)
    of the _www.privatecloud.domain.tld_ machine and make the tunnel accessible to
    other machines over the network:

    ```bash
    cat <<'EOF' > ~/.ssh/tunnels/machine001-mysql
    TARGET=user@access.domain.tld
    cat <<'EOF' > ~/.ssh/tunnels/privatecloud-www
    TARGET=user@www.privatecloud.domain.tld
    LOCAL_ADDR=0.0.0.0
    LOCAL_PORT=3307
    REMOTE_PORT=3306
    REMOTE_HOST=machine001.domain.tld
    LOCAL_PORT=8080
    REMOTE_PORT=80
    EOF
    ```

    Then start the tunnel and make it load at session loading:
    ```bash
    systemctl --user start ssh-tunnel@machine001-mysql
    systemctl --user enable ssh-tunnel@machine001-mysql
    systemctl --user start ssh-tunnel@privatecloud-www
    systemctl --user enable ssh-tunnel@privatecloud-www
    ```

    We can now connect to the machine001's MySQL service using:
    We can now connect to the web server using:
    ```bash
    mysql -h 127.0.0.1 -P 3307
    curl http://127.0.0.1:8080/
    ```

    or (from another machine that's in the same network):
    ```bash
    curl http://mymachine.domain.lan:8080/
    ```

    ### Create a tunnel to a MySQL service only accessible through an SSH bastion (directly)

    Let's create a configuration file to access to the MySQL server (_3306_ port)
    of the _mysql.privatecloud.domain.tld_ machine that's only through the
    _access.privatecloud.domain.tld_ bastion:

    ```bash
    cat <<'EOF' > ~/.ssh/tunnels/privatecloud-mysql
    TARGET=user@access.privatecloud.domain.tld
    LOCAL_PORT=3306
    REMOTE_PORT=3306
    REMOTE_HOST=mysql.privatecloud.domain.tld
    EOF
    ```

    Then start the tunnel:
    ```bash
    systemctl --user start ssh-tunnel@privatecloud-mysql
    ```

    We can now connect to the mysql.privatecloud's MySQL service using:
    ```bash
    mysql -h 127.0.0.1
    ```

    ### Create a tunnel to a MySQL service only accessible through an SSH bastion (using SSH)

    In this example, we want to create the same tunnel than the one in the
    [previous example](#create-an-ssh-tunnel-to-a-mysql-service-only-accessible-through-an-ssh-bastion-directly)
    but this time the MySQL service is not accessible directly from the bastion
    (on port _3306_).

    Fortunately, the _mysql.privatecloud_ machine is accessible from the bastion
    using SSH so we can create a tunnel using an ssh jump (see
    [ssh(1)](https://linux.die.net/man/1/ssh),
    [wikibooks article](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Proxies_and_Jump_Hosts)):
    ```bash
    cat <<'EOF' > ~/.ssh/tunnels/privatecloud-mysql
    TARGET=mysql.privatecloud.domain.tld
    LOCAL_PORT=3306
    REMOTE_PORT=3306
    REMOTE_HOST=127.0.0.1
    SSH_OPTS="-J access.privatecloud.domain.tld:22"
    EOF
    ```

    Then start the tunnel:
    ```bash
    systemctl --user start ssh-tunnel@privatecloud-mysql
    ```

    We can now connect to the _mysql.privatecloud.domain.tld_'s MySQL service using:
    ```bash
    mysql -h 127.0.0.1
    ```


    ## Further reading
    - systemd's [unit](https://www.freedesktop.org/software/systemd/man/systemd.unit.html) and [service](https://www.freedesktop.org/software/systemd/man/systemd.service.html) and manpages
    - Arch Linux wiki's [Systemd](https://wiki.archlinux.org/index.php/Systemd), [Systemd/User](https://wiki.archlinux.org/index.php/Systemd/User) and [SSH_keys](https://wiki.archlinux.org/index.php/SSH_keys) pages
  2. @olbat olbat revised this gist Oct 28, 2016. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions ssh-tunnel-systemd.md
    Original file line number Diff line number Diff line change
    @@ -78,11 +78,11 @@ After=network.target ssh-agent.service
    [Service]
    Type=simple
    Environment="LOCAL_ADDR=127.0.0.1"
    Environment="REMOTE_ADDR=127.0.0.1"
    Environment="REMOTE_HOST=127.0.0.1"
    EnvironmentFile=%h/.ssh/tunnels/%i
    ExecStart=/usr/bin/ssh -NT ${TARGET} ${SSH_OPTS} \
    ExecStart=/usr/bin/ssh -NT ${TARGET} \
    -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 \
    -L ${LOCAL_ADDR}:${LOCAL_PORT}:${REMOTE_HOST}:${REMOTE_PORT}
    -L ${LOCAL_ADDR}:${LOCAL_PORT}:${REMOTE_HOST}:${REMOTE_PORT} ${SSH_OPTS}
    RestartSec=10
    Restart=on-success
    RestartForceExitStatus=255
  3. @olbat olbat revised this gist Oct 28, 2016. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions ssh-tunnel-systemd.md
    Original file line number Diff line number Diff line change
    @@ -14,10 +14,10 @@ The agent will be run in background using a user _systemd service unit_ (see [sy

    ```bash
    # (create the systemd config directory if it does not exists)
    $ mkdir -p ~/.config/systemd/user/
    mkdir -p ~/.config/systemd/user/

    # create the ssh-agent.service unit
    $ cat <<'EOF' > ~/.config/systemd/user/ssh-agent.service
    cat <<'EOF' > ~/.config/systemd/user/ssh-agent.service
    [Unit]
    Description=SSH key agent
    Documentation=man:ssh-agent(1)
    @@ -65,10 +65,10 @@ As for the [SSH authentication agent](#setup-the-ssh-authentication-agent-system

    ```bash
    # (create the systemd config directory if it does not exists)
    $ mkdir -p ~/.config/systemd/user/
    mkdir -p ~/.config/systemd/user/

    # create the ssh-tunnel@.service unit
    $ cat <<'EOF' > ~/.config/systemd/user/ssh-tunnel@.service
    cat <<'EOF' > ~/.config/systemd/user/ssh-tunnel@.service
    [Unit]
    Description=SSH tunnel to %i
    Documentation=man:ssh(1)
    @@ -103,7 +103,7 @@ mkdir -p ~/.ssh/tunnels/

    We'll then have to create a configuration file for our tunnel:
    ```bash
    $ cat <<'EOF' > ~/.ssh/tunnels/testtun
    cat <<'EOF' > ~/.ssh/tunnels/testtun
    # This parameters will be used to run:
    # ssh ${TARGET} ${SSH_OPTS} \
    # -L ${LOCAL_ADDR}:${LOCAL_PORT}:${REMOTE_ADDR}:${REMOTE_PORT}
    @@ -155,7 +155,7 @@ _access.domain.tld_ bastion and make the tunnel accessible to other machines
    over the network:

    ```bash
    $ cat <<'EOF' > ~/.ssh/tunnels/machine001-mysql
    cat <<'EOF' > ~/.ssh/tunnels/machine001-mysql
    TARGET=user@access.domain.tld
    LOCAL_ADDR=0.0.0.0
    LOCAL_PORT=3307
  4. @olbat olbat revised this gist Oct 28, 2016. 1 changed file with 24 additions and 25 deletions.
    49 changes: 24 additions & 25 deletions ssh-tunnel-systemd.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Create SSH tunnels using systemd services
    # Create SSH tunnels using systemd units

    ## Overview
    This systemd service scripts will allow you to create SSH tunnels in background
    @@ -10,7 +10,7 @@ To be able to run SSH tunnels in background while using a password protected SSH
    key to connect to the targeted host, we'll first have to setup an _ssh-agent_
    (see [ssh-agent(1)](https://linux.die.net/man/1/ssh-agent)).

    The agent will be run in background using a user _systemd service unit_ (see [systemd.service(5)](https://www.freedesktop.org/software/systemd/man/systemd.service.html), [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [ArchLinux wiki page](https://wiki.archlinux.org/index.php/Systemd/User)).
    The agent will be run in background using a user _systemd service unit_ (see [systemd.service(5)](https://www.freedesktop.org/software/systemd/man/systemd.service.html), [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [Arch Linux wiki page](https://wiki.archlinux.org/index.php/Systemd/User)).

    ```bash
    # (create the systemd config directory if it does not exists)
    @@ -38,29 +38,30 @@ EOF

    Once it's done we can start the authentication agent:
    ```bash
    systemctl --user start ssh-agent
    systemctl --user start ssh-agent
    ```

    Or even make it load at session opening:
    ```bash
    systemctl --user enable ssh-agent
    systemctl --user enable ssh-agent
    ```
    After that, we make the `$SSH_AUTH_SOCK` env variable be loaded at our shell
    initialization (here [bash](https://www.gnu.org/software/bash/)):
    ```bash
    echo 'export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"' >> ~/.bashrc
    source ~/.bashrc
    echo 'export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"' >> ~/.bashrc
    source ~/.bashrc
    ```

    Finally we add our (default) private key identity to the authentication agent
    using ssh-add (see [ssh-add(1)](https://linux.die.net/man/1/ssh-add)).
    ```bash
    ssh-add
    ssh-add
    ```
    _Note:_ __it have to be done at every boot in order for the tunnels to work !__


    ## Setup the SSH-tunnel systemd unit
    As for the [SSH authentication agent](#setup_the_ssh_authentication_agent_systemd_unit) service, we'll run our SSH tunnels ([ssh(1)](https://linux.die.net/man/1/ssh)) using a _systemd service unit_ but this unit will be instanciable (see [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [Lennart Poettering's blog](http://0pointer.de/blog/projects/instances.html), [Archlinux wiki](https://wiki.archlinux.org/index.php/Systemd#Using_units), [Fedoramagazine article](https://fedoramagazine.org/systemd-template-unit-files/)).
    As for the [SSH authentication agent](#setup-the-ssh-authentication-agent-systemd-unit) service, we'll run our SSH tunnels ([ssh(1)](https://linux.die.net/man/1/ssh)) using a _systemd service unit_ but this unit will be instanciable (see [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [Lennart Poettering's blog](http://0pointer.de/blog/projects/instances.html), [Arch Linux wiki page](https://wiki.archlinux.org/index.php/Systemd#Using_units), [Fedoramagazine article](https://fedoramagazine.org/systemd-template-unit-files/)).

    ```bash
    # (create the systemd config directory if it does not exists)
    @@ -91,12 +92,14 @@ WantedBy=multi-user.target
    EOF
    ```

    ## Creating tunnels !
    ## Create tunnels !
    We'll now create _systemd service instances_ to run our tunnels.

    Our _ssh-tunnel_ service is going to look for it's configuration file into
    the `~/.ssh/tunnels/` directory so we start with creating the directory:
    mkdir -p ~/.ssh/tunnels/
    ```bash
    mkdir -p ~/.ssh/tunnels/
    ```

    We'll then have to create a configuration file for our tunnel:
    ```bash
    @@ -125,31 +128,22 @@ REMOTE_PORT=80
    EOF
    ```

    We'll then have to create a configuration file for our tunnel, the allowed
    parameters are the following:
    - `TARGET`: the target of the SSH command (ie. _user@hostname_)
    - `LOCAL_ADDR`: the local address to listen to (default: _127.0.0.1_)
    - `LOCAL_PORT`: the local port to listen to (ie. _8080_)
    - `REMOTE_HOST`: the remote host to forward to (default: _127.0.0.1_)
    - `REMOTE_PORT`: the remote port to forward (ie. _80_)
    - `SSH_OPTS`: additional -custom- SSH options

    Finally we can run our _systemd service unit_ that will create the tunnel:
    ```bash
    systemctl --user start ssh-tunnel@testtun
    systemctl --user start ssh-tunnel@testtun
    ```

    Or make it load a session loading:
    ```bash
    systemctl --user enable ssh-tunnel@testtun
    systemctl --user enable ssh-tunnel@testtun
    ```

    _Note:_ make sure your SSH authentication agent has been loaded properly using
    `ssh-add`, the tunnel will not work without it

    We can check the tunnel's status using:
    ```bash
    systemctl --user status -l ssh-tunnel@localhost-test
    systemctl --user status -l ssh-tunnel@testtun
    ```


    @@ -172,11 +166,16 @@ EOF

    Then start the tunnel and make it load at session loading:
    ```bash
    systemctl --user start ssh-tunnel@machine001-mysql
    systemctl --user enable ssh-tunnel@machine001-mysql
    systemctl --user start ssh-tunnel@machine001-mysql
    systemctl --user enable ssh-tunnel@machine001-mysql
    ```

    We can now connect to the machine001's MySQL service using:
    ```bash
    mysql -h 127.0.0.1 -P 3307
    mysql -h 127.0.0.1 -P 3307
    ```

    ## Further reading
    - systemd's [unit](https://www.freedesktop.org/software/systemd/man/systemd.unit.html) and [service](https://www.freedesktop.org/software/systemd/man/systemd.service.html) and manpages
    - Arch Linux wiki's [Systemd](https://wiki.archlinux.org/index.php/Systemd), [Systemd/User](https://wiki.archlinux.org/index.php/Systemd/User) and [SSH_keys](https://wiki.archlinux.org/index.php/SSH_keys) pages
    - DigitalOcean's [introduction to systemd units](https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files)
  5. @olbat olbat revised this gist Oct 28, 2016. 1 changed file with 177 additions and 7 deletions.
    184 changes: 177 additions & 7 deletions ssh-tunnel-systemd.md
    Original file line number Diff line number Diff line change
    @@ -1,12 +1,182 @@
    # ~/.config/systemd/user/ssh-agent.service
    systemctl --user enable ssh-agent
    # Create SSH tunnels using systemd services

    ## Overview
    This systemd service scripts will allow you to create SSH tunnels in background
    using systemd in user mode and a configuration file.


    ## Setup the SSH authentication agent systemd unit
    To be able to run SSH tunnels in background while using a password protected SSH
    key to connect to the targeted host, we'll first have to setup an _ssh-agent_
    (see [ssh-agent(1)](https://linux.die.net/man/1/ssh-agent)).

    The agent will be run in background using a user _systemd service unit_ (see [systemd.service(5)](https://www.freedesktop.org/software/systemd/man/systemd.service.html), [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [ArchLinux wiki page](https://wiki.archlinux.org/index.php/Systemd/User)).

    ```bash
    # (create the systemd config directory if it does not exists)
    $ mkdir -p ~/.config/systemd/user/

    # create the ssh-agent.service unit
    $ cat <<'EOF' > ~/.config/systemd/user/ssh-agent.service
    [Unit]
    Description=SSH key agent
    Documentation=man:ssh-agent(1)
    Wants=environment.target
    Before=environment.target
    [Service]
    Type=forking
    Environment="SSH_AUTH_SOCK=%t/ssh-agent.socket"
    ExecStart=/usr/bin/ssh-agent -a $SSH_AUTH_SOCK
    ExecStartPost=/bin/systemctl --user set-environment \
    SSH_AUTH_SOCK=${SSH_AUTH_SOCK}
    [Install]
    WantedBy=multi-user.target
    EOF
    ```

    Once it's done we can start the authentication agent:
    ```bash
    systemctl --user start ssh-agent
    ```

    Or even make it load at session opening:
    ```bash
    systemctl --user enable ssh-agent
    ```
    After that, we make the `$SSH_AUTH_SOCK` env variable be loaded at our shell
    initialization (here [bash](https://www.gnu.org/software/bash/)):
    ```bash
    echo 'export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"' >> ~/.bashrc
    source ~/.bashrc
    ```

    Finally we add our (default) private key identity to the authentication agent
    ```bash
    ssh-add
    ```
    _Note:_ __it have to be done at every boot in order for the tunnels to work !__


    ## Setup the SSH-tunnel systemd unit
    As for the [SSH authentication agent](#setup_the_ssh_authentication_agent_systemd_unit) service, we'll run our SSH tunnels ([ssh(1)](https://linux.die.net/man/1/ssh)) using a _systemd service unit_ but this unit will be instanciable (see [systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html), [Lennart Poettering's blog](http://0pointer.de/blog/projects/instances.html), [Archlinux wiki](https://wiki.archlinux.org/index.php/Systemd#Using_units), [Fedoramagazine article](https://fedoramagazine.org/systemd-template-unit-files/)).

    ```bash
    # (create the systemd config directory if it does not exists)
    $ mkdir -p ~/.config/systemd/user/

    # create the ssh-tunnel@.service unit
    $ cat <<'EOF' > ~/.config/systemd/user/ssh-tunnel@.service
    [Unit]
    Description=SSH tunnel to %i
    Documentation=man:ssh(1)
    Wants=ssh-agent.service
    After=network.target ssh-agent.service
    [Service]
    Type=simple
    Environment="LOCAL_ADDR=127.0.0.1"
    Environment="REMOTE_ADDR=127.0.0.1"
    EnvironmentFile=%h/.ssh/tunnels/%i
    ExecStart=/usr/bin/ssh -NT ${TARGET} ${SSH_OPTS} \
    -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 \
    -L ${LOCAL_ADDR}:${LOCAL_PORT}:${REMOTE_HOST}:${REMOTE_PORT}
    RestartSec=10
    Restart=on-success
    RestartForceExitStatus=255
    [Install]
    WantedBy=multi-user.target
    EOF
    ```

    ## Creating tunnels !
    We'll now create _systemd service instances_ to run our tunnels.

    Our _ssh-tunnel_ service is going to look for it's configuration file into
    the `~/.ssh/tunnels/` directory so we start with creating the directory:
    mkdir -p ~/.ssh/tunnels/

    We'll then have to create a configuration file for our tunnel:
    ```bash
    $ cat <<'EOF' > ~/.ssh/tunnels/testtun
    # This parameters will be used to run:
    # ssh ${TARGET} ${SSH_OPTS} \
    # -L ${LOCAL_ADDR}:${LOCAL_PORT}:${REMOTE_ADDR}:${REMOTE_PORT}
    # The target of the SSH command
    TARGET=user@hostname
    # The local port to listen to
    LOCAL_PORT=8080
    # The remote port to forward
    REMOTE_PORT=80
    # The local address to listen to (default: _127.0.0.1_)
    #LOCAL_ADDR=0.0.0.0
    # The remote host to forward to (default: _127.0.0.1_)
    #REMOTE_HOST=domain.tld
    # Additional -custom- SSH options
    #SSH_OPTS=-v
    EOF
    ```

    We'll then have to create a configuration file for our tunnel, the allowed
    parameters are the following:
    - `TARGET`: the target of the SSH command (ie. _user@hostname_)
    - `LOCAL_ADDR`: the local address to listen to (default: _127.0.0.1_)
    - `LOCAL_PORT`: the local port to listen to (ie. _8080_)
    - `REMOTE_HOST`: the remote host to forward to (default: _127.0.0.1_)
    - `REMOTE_PORT`: the remote port to forward (ie. _80_)
    - `SSH_OPTS`: additional -custom- SSH options

    Finally we can run our _systemd service unit_ that will create the tunnel:
    ```bash
    systemctl --user start ssh-tunnel@testtun
    ```

    Or make it load a session loading:
    ```bash
    systemctl --user enable ssh-tunnel@testtun
    ```

    _Note:_ make sure your SSH authentication agent has been loaded properly using
    `ssh-add`, the tunnel will not work without it

    We can check the tunnel's status using:
    ```bash
    systemctl --user status -l ssh-tunnel@localhost-test
    ```


    ## Example: create an SSH tunnel to a MySQL service only accessible through an SSH bastion

    Let's create a configuration file to access to the MySQL service (_3306_ port)
    of the _machine001.domain.tld_ machine that's only through the
    _access.domain.tld_ bastion and make the tunnel accessible to other machines
    over the network:

    ```bash
    $ cat <<'EOF' > ~/.ssh/tunnels/machine001-mysql
    TARGET=user@access.domain.tld
    LOCAL_ADDR=0.0.0.0
    LOCAL_PORT=3307
    REMOTE_PORT=3306
    REMOTE_HOST=machine001.domain.tld
    EOF
    ```

    Then start the tunnel and make it load at session loading:
    ```bash
    systemctl --user start ssh-tunnel@machine001-mysql
    systemctl --user enable ssh-tunnel@machine001-mysql
    ```

    # ~/.config/systemd/user/ssh-tunnel@.service
    # ~/.ssh/tunnels/localhost-test
    systemctl --user start ssh-tunnel@localhost-test
    systemctl --user enable ssh-tunnel@localhost-test
    systemctl --user status -l ssh-tunnel@localhost-test
    We can now connect to the machine001's MySQL service using:
    ```bash
    mysql -h 127.0.0.1 -P 3307
    ```
  6. @olbat olbat created this gist Oct 28, 2016.
    12 changes: 12 additions & 0 deletions ssh-tunnel-systemd.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    # ~/.config/systemd/user/ssh-agent.service
    systemctl --user enable ssh-agent
    systemctl --user start ssh-agent
    echo 'export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"' >> ~/.bashrc
    source ~/.bashrc
    ssh-add

    # ~/.config/systemd/user/ssh-tunnel@.service
    # ~/.ssh/tunnels/localhost-test
    systemctl --user start ssh-tunnel@localhost-test
    systemctl --user enable ssh-tunnel@localhost-test
    systemctl --user status -l ssh-tunnel@localhost-test