debian stretch + yubikey neo + first slot key/cert as nginx ssl key 0. wait for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=877122 to be fixed 1. apt install opensc-pkcs11 gnutls-bin libengine-pkcs11-openssl1.1 p11-kit 2. apt install nginx 3. get the URL of yubikey card's certificate in pkcs11 format: $ p11tool --provider /usr/lib/i386-linux-gnu/pkcs11/opensc-pkcs11.so --list-privkeys --login Token 'PIV_II (PIV Card Holder pin)' with URL 'pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=bf3b1b45cd94750a;token=PIV_II%20%28PIV%20Card%20Holder%20pin%29' requires user PIN Object 0: URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=bf3b1b45cd94750a;token=PIV_II%20%28PIV%20Card%20Holder%20pin%29;id=%01;object=PIV%20AUTH%20key;type=private Type: Private key Label: PIV AUTH key Flags: CKA_WRAP/UNWRAP; CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; ID: 01 4. use the following config in nginx (for some reason, PIN is always asked, so openssl.conf changes are not getting picked up) user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } ssl_engine pkcs11; http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; server { listen 8443 ssl; ssl_certificate /etc/nginx/thresh.crt; ssl_certificate_key "engine:pkcs11:pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=bf3b1b45cd94750a;token=PIV_II%20%28PIV%20Card%20Holder%20pin%29;id=%01;object=PIV%20AUTH%20key;type=private"; location / { return 200 'OK\n'; } } } 5. openssl.cnf changes (not needed, it seems): openssl_conf = openssl_def [openssl_def] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = /usr/lib/i686-linux-gnu/engines-1.1/libpkcs11.so MODULE_PATH = /usr/lib/i386-linux-gnu/opensc-pkcs11.so PIN = 12345678 6. start nginx manually: # nginx and enter PIN. 7. test with curl: $ time curl -v https://127.0.0.1:8443/ --insecure -vvv * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 8443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * TLSv1.2 (OUT), TLS header, Certificate Status (22): } [5 bytes data] * TLSv1.2 (OUT), TLS handshake, Client hello (1): } [512 bytes data] * TLSv1.2 (IN), TLS handshake, Server hello (2): { [104 bytes data] * TLSv1.2 (IN), TLS handshake, Certificate (11): { [964 bytes data] * TLSv1.2 (IN), TLS handshake, Server key exchange (12): { [333 bytes data] * TLSv1.2 (IN), TLS handshake, Server finished (14): { [4 bytes data] * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): } [70 bytes data] * TLSv1.2 (OUT), TLS change cipher, Client hello (1): } [1 bytes data] * TLSv1.2 (OUT), TLS handshake, Finished (20): } [16 bytes data] * TLSv1.2 (IN), TLS change cipher, Client hello (1): { [1 bytes data] * TLSv1.2 (IN), TLS handshake, Finished (20): { [16 bytes data] * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: C=RU; ST=Moscow; L=Moscow; O=THRE.SH; OU=SELF-MADE; CN=thresh * start date: Sep 26 11:44:53 2016 GMT * expire date: Sep 26 11:44:53 2019 GMT * issuer: C=RU; ST=Moscow; L=Moscow; O=THRE.SH; CN=internal users CA * SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. } [5 bytes data] > GET / HTTP/1.1 > Host: 127.0.0.1:8443 > User-Agent: curl/7.52.1 > Accept: */* > { [5 bytes data] < HTTP/1.1 200 OK < Server: nginx/1.13.5 < Date: Thu, 28 Sep 2017 21:49:06 GMT < Content-Type: application/octet-stream < Content-Length: 3 < Connection: keep-alive < { [3 bytes data] * Curl_http_done: called premature == 0 * Connection #0 to host 127.0.0.1 left intact OK