gitlab-sshd
- Tier: Free, Premium, Ultimate
- Offering: GitLab Self-Managed
gitlab-sshd is a standalone SSH server
written in Go. It is a lightweight alternative to OpenSSH. It is part of the gitlab-shell package and
handles SSH operations.
While OpenSSH uses a restricted shell approach, gitlab-sshd:
- Functions as a modern multi-threaded server application.
- Uses Remote Procedure Calls (RPCs) instead of the SSH transport protocol.
- Uses less memory than OpenSSH.
- Supports group access restriction by IP address for applications running behind a proxy.
For more details about the implementation, see the blog post.
If you are considering switching from OpenSSH to gitlab-sshd, consider:
- PROXY protocol:
gitlab-sshdsupports the PROXY protocol, allowing it to run behind proxy servers like HAProxy. This feature is not enabled by default but can be enabled. - SSH certificates:
gitlab-sshdsupports instance-level SSH certificate authentication by using trusted CA keys configured inconfig.yml. For more information, see Instance-level SSH certificates withgitlab-sshd. - 2FA recovery codes:
gitlab-sshddoes not support 2FA recovery code regeneration. Attempting to run2fa_recovery_codesresults in the error:remote: ERROR: Unknown command: 2fa_recovery_codes. See the discussion for details. - Algorithm configuration:
gitlab-sshddoes not read/etc/ssh/sshd_config. For more information, see configure SSH algorithms. - Git protocol v2:
gitlab-sshdaccepts theGIT_PROTOCOLenvironment variable without additional configuration. TheAcceptEnvsetting described in configuring Git Protocol v2 applies to OpenSSH only.
The capabilities of GitLab Shell extend beyond Git operations and can be used for various SSH-based interactions with GitLab.
Enable gitlab-sshd
To use gitlab-sshd:
The following instructions enable gitlab-sshd on a different port than OpenSSH:
Edit
/etc/gitlab/gitlab.rb:gitlab_sshd['enable'] = true gitlab_sshd['listen_address'] = '[::]:2222' # Adjust the port accordinglyOptional. By default, Linux package installations generate SSH host keys for
gitlab-sshdif they do not exist in/var/opt/gitlab/gitlab-sshd. If you wish to disable this automatic generation, add this line:gitlab_sshd['generate_host_keys'] = falseSave the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
By default, gitlab-sshd runs as the git user. As a result, gitlab-sshd cannot
run on privileged port numbers lower than 1024. This means users must
access Git with the gitlab-sshd port, or use a load balancer that
directs SSH traffic to the gitlab-sshd port to hide this.
Users may see host key warnings because the newly-generated host keys
differ from the OpenSSH host keys. Consider disabling host key
generation and copying the existing OpenSSH host keys into
/var/opt/gitlab/gitlab-sshd if this is an issue.
The following instructions switch OpenSSH in favor of gitlab-sshd:
Set the
gitlab-shellchartssshDaemonoption togitlab-sshd. For example:gitlab: gitlab-shell: sshDaemon: gitlab-sshdPerform a Helm upgrade.
By default, gitlab-sshd listens for:
- External requests on port 22 (
global.shell.port). - Internal requests on port 2222 (
gitlab.gitlab-shell.service.internalPort).
Configure SSH algorithms
gitlab-sshd is a separate SSH server and does not read /etc/ssh/sshd_config.
Configure the algorithms it offers with GitLab settings instead.
You can set the key exchange algorithms, the ciphers, the message authentication code (MAC)
algorithms, and the public key algorithms accepted for client authentication.
These settings apply only when gitlab-sshd is enabled.
They apply only to the port gitlab-sshd listens on.
If OpenSSH serves Git SSH traffic on another port, you configure that separately in
/etc/ssh/sshd_config.
Removing algorithms from public_key_algorithms stops affected clients from
authenticating.
The example excludes ssh-rsa, which affects clients that can only produce SHA-1 RSA
signatures.
RSA SSH certificates continue to work, because clients present them with
rsa-sha2-256-cert-v01@openssh.com or rsa-sha2-512-cert-v01@openssh.com, whose
underlying algorithms remain allowed.
Only clients limited to ssh-rsa-cert-v01@openssh.com are affected.
Check your clients before you apply this change.
To restrict the algorithms that gitlab-sshd offers:
Edit
/etc/gitlab/gitlab.rb. For example, to exclude algorithms that use SHA-1:gitlab_sshd['kex_algorithms'] = %w(mlkem768x25519-sha256 curve25519-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group16-sha512) gitlab_sshd['macs'] = %w(hmac-sha2-512-etm@openssh.com hmac-sha2-256-etm@openssh.com) gitlab_sshd['public_key_algorithms'] = %w(ssh-ed25519 sk-ssh-ed25519@openssh.com sk-ecdsa-sha2-nistp256@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 rsa-sha2-256 rsa-sha2-512)No default cipher uses SHA-1, so the
cipherssetting does not need to change. To restrict ciphers separately, setgitlab_sshd['ciphers'].Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
The generated configuration is written to the sshd section of
/var/opt/gitlab/gitlab-shell/config.yml.
These settings apply only when sshDaemon is set to gitlab-sshd.
The sshDaemon default is openssh.
Set the
gitlab.gitlab-shell.configoptions. For example, to exclude algorithms that use SHA-1:gitlab: gitlab-shell: sshDaemon: gitlab-sshd config: kexAlgorithms: - mlkem768x25519-sha256 - curve25519-sha256 - ecdh-sha2-nistp256 - ecdh-sha2-nistp384 - ecdh-sha2-nistp521 - diffie-hellman-group16-sha512 macs: - hmac-sha2-512-etm@openssh.com - hmac-sha2-256-etm@openssh.com publicKeyAlgorithms: - ssh-ed25519 - sk-ssh-ed25519@openssh.com - sk-ecdsa-sha2-nistp256@openssh.com - ecdsa-sha2-nistp256 - ecdsa-sha2-nistp384 - ecdsa-sha2-nistp521 - rsa-sha2-256 - rsa-sha2-512Perform a Helm upgrade.
Each setting replaces the default list for that algorithm type. Settings you leave unset keep their defaults.
Default algorithms
When you leave a setting empty, gitlab-sshd uses the defaults of the
golang.org/x/crypto/ssh package that
GitLab Shell is built against.
The defaults change when GitLab updates that dependency.
Before GitLab 18.3, GitLab Shell carried its own hard-coded lists.
The defaults are permissive and include algorithms that use SHA-1. Configure the settings explicitly to exclude them.
When you configure these settings, the following behaviors apply:
- An algorithm name that GitLab Shell does not recognize is dropped from the list instead of reported as an error, so a mistake can leave a different set than intended. Always confirm a change took effect. For more information, see issue 870.
- A mistake in
public_key_algorithmsbehaves differently and is more serious. The value is checked for each connection rather than at startup, sogitlab-ctl reconfiguresucceeds and the server starts, but clients cannot authenticate. For more information, see issue 871. - Two names appear in scans that you did not configure.
curve25519-sha256@libssh.orgis added automatically when you listcurve25519-sha256.kex-strict-s-v00@openssh.comalways appears because it is a strict key exchange marker rather than an algorithm.
The sample sshd lists in the GitLab Shell
config.yml.example
file illustrate the format.
They are not the effective defaults.
To confirm a change took effect, scan the running server from a client. For example:
ssh-audit <hostname> -p <port>Host key algorithms
You cannot configure host key algorithms directly.
gitlab-sshd derives them from the host keys it loads, so an RSA host key causes the server
to offer rsa-sha2-256, rsa-sha2-512, and ssh-rsa.
The public_key_algorithms setting does not change this, because it applies only to client
authentication.
For more information, see issue 806.
To stop the server from offering ssh-rsa, exclude the RSA host key.
Removing a host key changes the host key fingerprints that clients see.
Users get host key warnings, and clients pinned to the removed key fail until their
known_hosts entries are updated.
Tell your users before you make this change.
For Linux package installations:
Edit
/etc/gitlab/gitlab.rb:gitlab_sshd['host_keys_glob'] = 'ssh_host_{ecdsa,ed25519}_key'Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
gitlab-sshd matches the pattern inside the host key directory, which defaults to
/var/opt/gitlab/gitlab-sshd.
If the pattern matches no files, gitlab-sshd does not start.
Metrics
gitlab-sshd exposes Prometheus metrics on the monitoring endpoint
configured with web_listen in the gitlab-shell configuration.
gitlab-sshd serves the metrics at the /metrics path of that address.
| Metric | Type | Description |
|---|---|---|
gitlab_shell_sshd_in_flight_connections | Gauge | Connections currently being served by gitlab-sshd. |
gitlab_shell_sshd_concurrent_limited_sessions_total | Counter | Number of times the concurrent sessions limit was hit. |
gitlab_shell_sshd_session_duration_seconds | Histogram | Duration of SSH sessions served by gitlab-sshd. |
gitlab_shell_sshd_session_established_duration_seconds | Histogram | Latency until an SSH session is established, used as the latency for the gitlab_sshd service Apdex. |
gitlab_sli:shell_sshd_sessions:total | Counter | Number of SSH sessions that have been established (post-authentication session channels). |
gitlab_sli:shell_sshd_sessions:errors_total | Counter | Number of SSH sessions that have failed. |
gitlab_sli:shell_sshd_connections:total | Counter | Number of SSH connections that reached authentication. |
gitlab_sli:shell_sshd_connections:errors_total | Counter | Number of SSH connections that failed due to a server-side error. |
Session-level and connection-level SLIs
gitlab-sshd exposes two sets of Service Level Indicator (SLI) counters for SSH reliability:
- Session-level (
gitlab_sli:shell_sshd_sessions:*) counts post-authentication session channels. This counter does not observe failures that occur during the authentication phase. - Connection-level (
gitlab_sli:shell_sshd_connections:*) counts each connection that reaches the authentication phase, and treats server-side errors during either the authentication or session phase as failures. Unlike the session-level counters, connection-level counters capture authentication-phase failures such asauthorized_keyslookup errors. The connection-level counters exclude connections that never get past the transport handshake, such as port scanners and health checks.
The connection-level counters provide broader coverage of user-facing failures and are the preferred signal for SSH reliability monitoring.
Other GitLab Shell metrics
gitlab-sshd also exposes metrics for the interactions that GitLab Shell has with other
services.
These metrics are part of GitLab Shell’s general instrumentation, and are not specific to the SSH
daemon.
The metrics cover connections to Gitaly, the GitLab internal API, Git LFS, and the Topology
Service.
When gitlab-sshd handles an SSH connection, gitlab-sshd runs these operations in its own
process and exposes the resulting counters on the same /metrics endpoint as the SSH metrics.
When you use OpenSSH instead of gitlab-sshd, GitLab Shell runs as a short-lived process for each
connection.
These short-lived processes increment the same counters, but do not expose a metrics endpoint, so
the counters are not available for scraping.
| Metric | Type | Description |
|---|---|---|
gitlab_shell_gitaly_connections_total | Counter | Number of Gitaly connections that have been established, labeled by status (ok or fail). |
gitlab_shell_http_requests_total | Counter | Number of requests to the GitLab internal API, labeled by code and method. |
gitlab_shell_http_request_duration_seconds | Histogram | Latency of requests to the GitLab internal API, labeled by code and method. |
gitlab_shell_http_in_flight_requests | Gauge | Requests to the GitLab internal API currently being performed. |
lfs_http_connections_total | Counter | Number of Git LFS-over-HTTP connections that have been established. |
lfs_ssh_connections_total | Counter | Number of Git LFS-over-SSH connections that have been established. |
gitlab_shell_topology_connections_total | Counter | Number of Topology Service connections that have been established, labeled by status (ok or fail). |
gitlab_shell_topology_requests_total | Counter | Number of Topology Service Classify requests, labeled by status (ok or fail). |
gitlab_shell_topology_request_duration_seconds | Histogram | Latency of Topology Service Classify requests. |
PROXY protocol support
Load balancers in front of gitlab-sshd cause GitLab to report the proxy IP address instead of the
client IP address. To obtain the real IP address, gitlab-sshd supports the
PROXY protocol.
To enable the PROXY protocol:
Edit
/etc/gitlab/gitlab.rb:gitlab_sshd['proxy_protocol'] = true # Proxy protocol policy ("use", "require", "reject", "ignore"), "use" is the default value gitlab_sshd['proxy_policy'] = "use"For more information about the
gitlab_sshd['proxy_policy']options, see thego-proxyprotolibrary.Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
Set the
gitlab.gitlab-shell.configoptions. For example:gitlab: gitlab-shell: config: proxyProtocol: true proxyPolicy: "use"Perform a Helm upgrade.