0

我已经在 docker (docker-compose) 上安装了 gitea,并使用 traefik (v2.3) 作为反向代理。我正在尝试设置 ssh,但无论是 SSH 进入还是(主要)执行 git clone 和推送都失败了。

我明白了

<user>@<domain>: Permission denied (publickey).

我尝试在 docker-compose 文件中为 traefik 容器指定端口

ports:
  - "22:22"

在 docker-compose for gitea 我有以下标签:

  # SSH
  - "traefik.http.routers.gitea_ssh.rule=HOST(`gitea.localhost`)"
  - "traefik.http.routers.gitea_ssh.entrypoints=ssh"
  - "traefik.http.routers.gitea_ssh.service=gitea_ssh"
  # Services
  - "traefik.http.services.gitea_ssh.loadbalancer.server.port=22"

我对 http 和 https 有类似的设置,http 被重定向到 https。

入口点在 traefik.yml 中定义为":22"

然而这不起作用。我认为信号流会是这样的:

ssh request -> server port 1234 -> docker port 22 -> traefik redirects -> gitea container port 22 

我已将公钥上传到

我通过此设置获得的 ssh 连接请求响应是:

<login on computer>:/ <user>$ ssh -v <address to gitea>
OpenSSH_8.1p1, LibreSSL 2.7.3
debug1: Reading configuration data /<Path to config>/config
debug1: /<Path to config>/config line 12: Applying options for <address to gitea>
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 47: Applying options for *
debug1: Connecting to <address to gitea> port 1234.
debug1: Connection established.
debug1: identity file /<Path to private key>/private-key type 0
debug1: identity file /<Path to private key>/private-key-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.1
debug1: kex_exchange_identification: banner line 0: HTTP/1.1 400 Bad Request
debug1: kex_exchange_identification: banner line 1: Content-Type: text/plain; charset=utf-8
debug1: kex_exchange_identification: banner line 2: Connection: close
debug1: kex_exchange_identification: banner line 3: 
kex_exchange_identification: Connection closed by remote host

当我尝试访问 git clone 时:

<login on computer>:/ <user>$ git clone git@<address to gitea>:<path to repo>.git
Cloning into 'some-repo'...
kex_exchange_identification: Connection closed by remote host
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
4

2 回答 2

1

我没有通过 traefik 代理 ssh 的第一手经验,但我之前看过这篇文章:

https://www.georglutz.de/blog/2020/06/20/homeassistant-with-traefik-and-ssh/

并且推荐它是有道理的,因为它是相同的设置。

我会指出你错误地使用了 http 路由器,你需要一个 tcp 路由器。

我使用 Gitea,我建议只在不同的端口上公开 SSH;Traefik 只会给你开销。

于 2021-02-24T19:23:07.910 回答
1

gitea ssh 的示例在端口 222 上可用,因为端口 22 用于主机 ssh。

  1. 为端口 222 创建一个名为 ssh 的 traefik 入口点
  2. 将端口配置添加到 traefik 容器 222:222/tcp(不需要 udp、sctp)
  3. 对于 gitea,您不需要公开端口
  4. 配置gitea,添加环境变量:
# details: https://docs.gitea.io/en-us/config-cheat-sheet/#admin-admin
# start gitea only ssh server, default use system which didn't work for me in any way
GITEA__server__START_SSH_SERVER: "true"
# this port is used in git clone, if not 22 this will add ssh:// to clone url which... i needed to remove everytime
GITEA__server__SSH_PORT: 22
# gitea ssh listen port
GITEA__server__SSH_LISTEN_PORT: 222
  1. 使用标签为 gitea 配置 traefik:
# host resolving doesn't work for ssh, so you can only use "*"
- "traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`)"
- "traefik.tcp.routers.gitea-ssh.entrypoints=ssh"
- "traefik.tcp.routers.gitea-ssh.service=gitea-ssh-svc"
- "traefik.tcp.services.gitea-ssh-svc.loadbalancer.server.port=222"
  1. 将您的 ssh 密钥添加到您的帐户,检查它是否是有效类型,最小位也是如此。https://docs.gitea.io/en-us/config-cheat-sheet/#ssh-minimum-key-sizes-sshminimum_key_sizes
  2. 创建一个名为 Example 的简单存储库
  3. 在客户端更新 ~/.ssh/config:
Host MyGiteaInstance
  HostName git.example.de
  IdentityFile ~/.ssh/gitea
  User username
  Port 222
  1. clone git@git.example.de:user/Example.git,对我来说,如果 url 中有端口信息或者有像 ssh:// 这样的协议前缀,它就会失败

调试提示:

  1. 检查 traefik 日志是否存在诸如找不到入口点之类的错误
  2. 使用详细的 ssh 进行克隆:GIT_SSH_COMMAND="ssh -v" git clone git@git.example.de:user/Example.git
  • 如果主机无法访问 -> 您这边的 ssh 端口错误或入口点未在 traefik 中设置
  • 主机真实性请求 = traefik 很好,客户端端口配置可能很好(多个 ssh 服务器)
  • 权限被拒绝 -> gitea 中的 ssh 服务器已启动,正确的端口设置,检查 gitea 日志或 ssh 密钥未添加到用户

如果我错过了上面的内容,请完成不是最小的示例:

networks:
  proxy:
    external: false
    internal: true
  web:
    external: false
  gitea:
    external: false
    internal: true

volumes:
  gitea:
  gitea_db:

services:
  traefik:
    image: traefik:v2.5
    command: --api.insecure=true --providers.docker
    ports:
      # entrypoint http
      - "80:80"
      # entrypoint https
      - "443:443"
      # entrypoint ssh
      - "222:222/tcp"
      # todo maybe behind vpn?
      # - "8080:8080"
    # todo create docker.sock proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik:/etc/traefik:ro
      - ./acme.json:/certs/acme.json
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    networks: 
      - proxy
      - web
  
  watchtower:
    image: containrrr/watchtower:latest
    environment:
      WATCHTOWER_CLEANUP: "true"
      WATCHTOWER_REVIVE_STOPPED: "true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    # disable for container?
    # LABEL com.centurylinklabs.watchtower.enable="false"
  

  gitea_db:
    image: postgres:14
    restart: unless-stopped
    environment:
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD: ${GITEA_DB_PASSWD}
      POSTGRES_DB: gitea
    networks:
      - gitea
    volumes:
      - gitea_db:/var/lib/postgresql/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro

  gitea:
    image: gitea/gitea:1.15
    depends_on:
      - gitea_db
    # https://docs.gitea.io/en-us/config-cheat-sheet/
    environment:
      USER_UID: 1000
      USER_GID: 1000
      # configuration:
      # some values are created from the documentation but untested, therefore uncommented
      # https://docs.gitea.io/en-us/config-cheat-sheet/#repository---local-repositorylocal
      ## default
      GITEA__default__RUN_MODE: prod
      GITEA__default__APP_NAME: "Gitea: Git with a cup of tea"
      ## database
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: gitea_db:5432
      GITEA__database__NAME: gitea
      GITEA__database__USER: gitea
      GITEA__database__PASSWD: ${GITEA_DB_PASSWD}
      ## server
      GITEA__server__DOMAIN: ${GITEA_DOMAIN}
      # ensuring unneccessary port isnt added
      GITEA__server__ROOT_URL: "https://%(DOMAIN)s"
      GITEA__server__HTTP_PORT: 80
      # if true SSH_LISTEN_PORT needs to be != 22
      GITEA__server__START_SSH_SERVER: "true"
      # SSH port in clone URL (needs to be 22 to remove ssh:// from clone url)
      GITEA__server__SSH_PORT: 22
      # disable forced ssh:// prefix of clone url
      GITEA__repository__USE_COMPAT_SSH_URI: "false"
      # SSH port for built-in SSH server (e.g. docker run ... -p SSH_PORT:LISTEN_PORT)
      GITEA__server__SSH_LISTEN_PORT: 222
      
      # mailer
      GITEA__mailer__ENABLED: "true"
      GITEA__mailer__HOST: "${GITEA_MAIL_HOST}"
      GITEA__mailer__FROM: "${GITEA_MAIL}"
      GITEA__mailer__USER: "${GITEA_MAIL}"
      # require email confirmation to register, enable email notifications
      # no effect: GITEA__server__REGISTER_EMAIL_CONFIRM: "true"
      # allows mails as notifications on updates
      # no effect: GITEA__server__ENABLE_NOTIFY_MAIL: "true"
      #
      # open-id sign
      GITEA__openid__ENABLE_OPENID_SIGNIN: "true"
      # disable self-registration
      GITEA__service__DISABLE_REGISTRATION: "true"
      # require sign in to view pages
      GITEA__service__REQUIRE_SIGNIN_VIEW: "true"
      # password hash argon2
      GITEA__security__PASSWORD_HASH_ALGO: "argon2"
      #
      # change default branch from master to x
      GITEA__repository__DEFAULT_BRANCH: "main"
      #
      # set manually during install, keys don't work for unknown reason:
      # Email Settings:
      # SMTP Password:
      # GITEA__mailer__PASSWD: "${GITEA_MAIL_PASSWORD}"
      # [x] Require Email Confirmation to Register
      # [x] Enable Email Notifications (to watch repos / issues aso.)
      #
      # set manually, no config option found:
      # Server and Third-Party Service Settings:
      # [x] Enable Local Mode (disable all third party content)
      #
      # Admin Account:
      # admin: ${GITEA_ADMIN_NAME}
      # pw: "${GITEA_MAIL_PASSWORD}"
      # mail: ${GITEA_MAIL}
      #
      # check configuration here:
      # https://${GITEA_DOMAIN}/admin/config
      # 
      # remember correct port isn't part of ssh clone url, but works with ~/.ssh/config

    restart: unless-stopped
    networks:
      - gitea
      - proxy
    volumes:
      - gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.gitea.loadbalancer.server.port=80"
      - "traefik.http.routers.gitea_insecure.rule=Host(`${GITEA_DOMAIN}`)"
      - "traefik.http.routers.gitea_insecure.entrypoints=http"
      - "traefik.http.routers.gitea_insecure.middlewares=https-redirect@file"
      - "traefik.http.routers.gitea.rule=Host(`${GITEA_DOMAIN}`)"
      - "traefik.http.routers.gitea.entrypoints=https"
      - "traefik.http.routers.gitea.tls.certresolver=tlsChallenge"
# https://community.traefik.io/t/routing-ssh-traffic-with-traefik-v2/717 
      # ssh cant be set on specific domain
      - "traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.gitea-ssh.entrypoints=ssh"
      - "traefik.tcp.routers.gitea-ssh.service=gitea-ssh-svc"
      - "traefik.tcp.services.gitea-ssh-svc.loadbalancer.server.port=222"

.env 文件:

GITEA_DOMAIN=git.example.de
GITEA_DB_PASSWD=securePassword
GITEA_ADMIN_NAME=admin name
GITEA_MAIL_PASSWORD=securePassword
GITEA_MAIL_HOST=smtp.mymail.de:465
GITEA_MAIL=yourEmail

./traefik/dynamic.yml

http:
  middlewares:
    https-redirect:
      redirectScheme:
        scheme: https

./traefik/traefik.yml

global:
  sendAnonymousUsage: false

log:
  level: INFO

entryPoints:
  http:
    address: :80
  https:
    address: :443
  ssh:
    address: :222

defaultEntryPoints:
  - https

api:
  insecure: true
  dashboard: true

providers:
  docker:
    endpoint: unix:///var/run/docker.sock
    watch: true
    exposedByDefault: false
    network: shared_proxy
  file:
    filename: /etc/traefik/dynamic.yml
    watch: true

certificatesResolvers:
  tlsChallenge:
    acme:
      email: MyEmailAdress
      storage: /certs/acme.json
      tlsChallenge: {}
      # https://doc.traefik.io/traefik/https/acme/#caserver
      # caServer: https://acme-staging-v02.api.letsencrypt.org/directory # For test certificates
于 2021-11-06T16:10:29.677 回答