TLS handshake timeout

I’m trying to setup Drone with a Gitea instance.

  • Everything is hosted by a nginx server running on a Raspberry Pi 3
  • gitea is hosted at https://victorlamoine.hopto.org/gitea
  • drone is at https://ci-victorlamoine.hopto.org
  • Both the domains are using and enforcing HTTPS

When I try to log-in on my gitea account on the drone webpage I get an error, see at the bottom of the log:

$ docker-compose up
Recreating git_drone-server_1
Recreating git_drone-agent_1
Attaching to git_drone-server_1, git_drone-agent_1
drone-server_1  | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
drone-server_1  |  - using env:	export GIN_MODE=release
drone-server_1  |  - using code:	gin.SetMode(gin.ReleaseMode)
drone-server_1  | 
drone-server_1  | [GIN-debug] GET    /logout                   --> github.com/drone/drone/server.GetLogout (12 handlers)
drone-server_1  | [GIN-debug] GET    /login                    --> github.com/drone/drone/server.HandleLogin (12 handlers)
drone-server_1  | [GIN-debug] GET    /api/user                 --> github.com/drone/drone/server.GetSelf (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/user/feed            --> github.com/drone/drone/server.GetFeed (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/user/repos           --> github.com/drone/drone/server.GetRepos (13 handlers)
drone-server_1  | [GIN-debug] POST   /api/user/token           --> github.com/drone/drone/server.PostToken (13 handlers)
drone-server_1  | [GIN-debug] DELETE /api/user/token           --> github.com/drone/drone/server.DeleteToken (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/users                --> github.com/drone/drone/server.GetUsers (13 handlers)
drone-server_1  | [GIN-debug] POST   /api/users                --> github.com/drone/drone/server.PostUser (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/users/:login         --> github.com/drone/drone/server.GetUser (13 handlers)
drone-server_1  | [GIN-debug] PATCH  /api/users/:login         --> github.com/drone/drone/server.PatchUser (13 handlers)
drone-server_1  | [GIN-debug] DELETE /api/users/:login         --> github.com/drone/drone/server.DeleteUser (13 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name   --> github.com/drone/drone/server.PostRepo (16 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name   --> github.com/drone/drone/server.GetRepo (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/builds --> github.com/drone/drone/server.GetBuilds (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/builds/:number --> github.com/drone/drone/server.GetBuild (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/logs/:number/:pid --> github.com/drone/drone/server.GetProcLogs (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/logs/:number/:pid/:proc --> github.com/drone/drone/server.GetBuildLogs (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/files/:number --> github.com/drone/drone/server.FileList (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/files/:number/:proc/*file --> github.com/drone/drone/server.FileGet (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/secrets --> github.com/drone/drone/server.GetSecretList (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/secrets --> github.com/drone/drone/server.PostSecret (16 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/secrets/:secret --> github.com/drone/drone/server.GetSecret (16 handlers)
drone-server_1  | [GIN-debug] PATCH  /api/repos/:owner/:name/secrets/:secret --> github.com/drone/drone/server.PatchSecret (16 handlers)
drone-server_1  | [GIN-debug] DELETE /api/repos/:owner/:name/secrets/:secret --> github.com/drone/drone/server.DeleteSecret (16 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/registry --> github.com/drone/drone/server.GetRegistryList (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/registry --> github.com/drone/drone/server.PostRegistry (16 handlers)
drone-server_1  | [GIN-debug] GET    /api/repos/:owner/:name/registry/:registry --> github.com/drone/drone/server.GetRegistry (16 handlers)
drone-server_1  | [GIN-debug] PATCH  /api/repos/:owner/:name/registry/:registry --> github.com/drone/drone/server.PatchRegistry (16 handlers)
drone-server_1  | [GIN-debug] DELETE /api/repos/:owner/:name/registry/:registry --> github.com/drone/drone/server.DeleteRegistry (16 handlers)
drone-server_1  | [GIN-debug] PATCH  /api/repos/:owner/:name   --> github.com/drone/drone/server.PatchRepo (16 handlers)
drone-server_1  | [GIN-debug] DELETE /api/repos/:owner/:name   --> github.com/drone/drone/server.DeleteRepo (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/chown --> github.com/drone/drone/server.ChownRepo (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/repair --> github.com/drone/drone/server.RepairRepo (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/move --> github.com/drone/drone/server.MoveRepo (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/builds/:number --> github.com/drone/drone/server.PostBuild (16 handlers)
drone-server_1  | [GIN-debug] DELETE /api/repos/:owner/:name/builds/:number --> github.com/drone/drone/server.ZombieKill (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/builds/:number/approve --> github.com/drone/drone/server.PostApproval (16 handlers)
drone-server_1  | [GIN-debug] POST   /api/repos/:owner/:name/builds/:number/decline --> github.com/drone/drone/server.PostDecline (16 handlers)
drone-server_1  | [GIN-debug] DELETE /api/repos/:owner/:name/builds/:number/:job --> github.com/drone/drone/server.DeleteBuild (16 handlers)
drone-server_1  | [GIN-debug] DELETE /api/repos/:owner/:name/logs/:number --> github.com/drone/drone/server.DeleteBuildLogs (16 handlers)
drone-server_1  | [GIN-debug] GET    /api/badges/:owner/:name/status.svg --> github.com/drone/drone/server.GetBadge (12 handlers)
drone-server_1  | [GIN-debug] GET    /api/badges/:owner/:name/cc.xml --> github.com/drone/drone/server.GetCC (12 handlers)
drone-server_1  | [GIN-debug] POST   /hook                     --> github.com/drone/drone/server.PostHook (12 handlers)
drone-server_1  | [GIN-debug] POST   /api/hook                 --> github.com/drone/drone/server.PostHook (12 handlers)
drone-server_1  | [GIN-debug] GET    /stream/events            --> github.com/drone/drone/server.EventStreamSSE (12 handlers)
drone-server_1  | [GIN-debug] GET    /stream/logs/:owner/:name/:build/:number --> github.com/drone/drone/server.LogStreamSSE (15 handlers)
drone-server_1  | [GIN-debug] GET    /api/info/queue           --> github.com/drone/drone/server.GetQueueInfo (13 handlers)
drone-server_1  | [GIN-debug] GET    /authorize                --> github.com/drone/drone/server.HandleAuth (12 handlers)
drone-server_1  | [GIN-debug] POST   /authorize                --> github.com/drone/drone/server.HandleAuth (12 handlers)
drone-server_1  | [GIN-debug] POST   /authorize/token          --> github.com/drone/drone/server.GetLoginToken (12 handlers)
drone-server_1  | [GIN-debug] GET    /api/builds               --> github.com/drone/drone/server.GetBuildQueue (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/         --> github.com/drone/drone/server/debug.IndexHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/heap     --> github.com/drone/drone/server/debug.HeapHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/goroutine --> github.com/drone/drone/server/debug.GoroutineHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/block    --> github.com/drone/drone/server/debug.BlockHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/threadcreate --> github.com/drone/drone/server/debug.ThreadCreateHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/cmdline  --> github.com/drone/drone/server/debug.CmdlineHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/profile  --> github.com/drone/drone/server/debug.ProfileHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/symbol   --> github.com/drone/drone/server/debug.SymbolHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] POST   /api/debug/pprof/symbol   --> github.com/drone/drone/server/debug.SymbolHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /api/debug/pprof/trace    --> github.com/drone/drone/server/debug.TraceHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /metrics                  --> github.com/drone/drone/server/metrics.PromHandler.func1 (13 handlers)
drone-server_1  | [GIN-debug] GET    /version                  --> github.com/drone/drone/server.Version (12 handlers)
drone-server_1  | [GIN-debug] GET    /healthz                  --> github.com/drone/drone/server.Health (12 handlers)
drone-agent_1   | {"time":"2018-05-12T11:23:23Z","level":"debug","message":"request next execution"}

drone-server_1  | time="2018-05-12T11:32:28Z" level=error msg="cannot authenticate user. Post https://victorlamoine.hopto.org/gitea/api/v1/users/VictorLamoine/tokens: net/http: TLS handshake timeout" 

This is my docker-compose.yaml file:

version: '2'

services:
  drone-server:
    image: kunde21/drone-arm

    ports:
      - 8000:8000
      - 9000
    volumes:
      - /var/lib/drone:/var/lib/drone/
    restart: always
    environment:
      - DRONE_OPEN=true
      - DRONE_HOST=https://ci-victorlamoine.hopto.org
      - DRONE_GITEA=true
      - DRONE_GITEA_URL=https://victorlamoine.hopto.org/gitea
      - DRONE_SECRET=IWillChangeLater

  drone-agent:
    image: drone/agent:linux-arm

    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_SERVER=drone-server:9000
      - DRONE_SECRET=IWillChangeLater

This is victorlamoine.hopto.org nginx configuration

server {
    listen 80 default_server;
    server_name victorlamoine.hopto.org;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/victorlamoine.hopto.org/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/victorlamoine.hopto.org/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    server_name victorlamoine.hopto.org;
    root /var/www/victorlamoine.hopto.org;
    access_log /var/log/nginx/access-victorlamoine.hopto.org.log;
    error_log /var/log/nginx/error-victorlamoine.hopto.org.log warn;
    index index.php index.html index.htm;

    # Set size for max uploaded content
    client_max_body_size 0; #max size disabled
    client_header_timeout 30m;
    client_body_timeout 30m;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 401 403 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/victorlamoine.hopto.org;
    }

    location ~ /favicon.ico {
        root /var/www/victorlamoine.hopto.org;
    }

    # Gitea
    location /gitea/ {
        rewrite /gitea(.*) $1 break;
        proxy_pass http://127.0.0.1:3000;
    }

    # PHP
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

This is ci-victorlamoine.hopto.org nginx configuration:

server {
    listen 80;
    server_name ci-victorlamoine.hopto.org;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/victorlamoine.hopto.org/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/victorlamoine.hopto.org/privkey.pem; # managed by Certb$
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    server_name ci-victorlamoine.hopto.org;
    root /var/www/ci-victorlamoine.hopto.org;
    access_log /var/log/nginx/access-ci-victorlamoine.hopto.org.log;
    error_log /var/log/nginx/error-ci-victorlamoine.hopto.org.log warn;

    location / {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;

        proxy_pass http://127.0.0.1:8000;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_buffering off;

        chunked_transfer_encoding off;
    }
}

How can I solve this TLS handshake timeout?

The TLS handshake timeout indicates a problem with the network configuration on your host machine (not with Drone itself). It indicates the server cannot be reached. There are dozens of possible root causes for this, including issues with dns or ip forwarding or http_proxy or no_proxy variables, so it is difficult to say, and it is unfortunately outside my area of expertise.

Since your Gitea server is public, I can confirm that I can configure my local Drone instance to access your Gitea server and am able to connect without any errors.

Since this appears to be a network-related error, you might also want to consider posting your question to StackOverflow where you will have access to network experts that are more qualified than myself to triage these types of problems. If you figure it out, post back. Good luck!

Ok ! Your message made me thought about something: this might be related to the fact that I self host my server and that my internet box does not have a NAT loopback; thus the Drone instance might fail to reach https://victorlamoine.hopto.org because the internet box doesn’t resolve that.

I’ll try to tweak my /etc/hosts file and will ask on StackOverflow if I fail to solve this on my own.

Thank you for taking the time to test and trying to help me :slight_smile:
When (if!) I get this working I will post my working configuration.