# Configuring Harbor with HTTPS Access

In versions up to and including 1.9.x, by default Harbor uses HTTP to serve registry requests. However, using HTTP is acceptable only in air-gapped test or development environments that do not have a connection to the external internet. Using HTTP in environments that are not air-gapped exposes you to man-in-the-middle attacks. In production environments, always use HTTPS. If you enable Content Trust with Notary to properly sign all images, you must use HTTPS. 

Harbor uses an `nginx` instance as a reverse proxy for all services. You use the `prepare` script to configure `nginx` to enable HTTPS.

You can use certificates that are signed by a trusted third-party CA, or  you can use self-signed certificates. The following sections describe how to create a CA, and how to use your CA to sign a server certificate and a client certificate. 

## Getting Certificate Authority

```
  openssl genrsa -out ca.key 4096
```
```
  openssl req -x509 -new -nodes -sha512 -days 3650 \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=yourdomain.com" \
    -key ca.key \
    -out ca.crt
```

## Getting Server Certificate

Assuming that your registry's **hostname** is **yourdomain.com**, and that its DNS record points to the host where you are running Harbor. In production environment, you first should get a certificate from a CA. In a test or development environment, you can use your own CA. The certificate usually contains a .crt file and a .key file, for example, **yourdomain.com.crt** and **yourdomain.com.key**.



**1) Create your own Private Key:**

```
  openssl genrsa -out yourdomain.com.key 4096
```

**2) Generate a Certificate Signing Request:**

If you use FQDN like **yourdomain.com** to connect your registry host, then you must use **yourdomain.com** as CN (Common Name).

```
  openssl req -sha512 -new \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=yourdomain.com" \
    -key yourdomain.com.key \
    -out yourdomain.com.csr
```

**3) Generate the certificate of your registry host:**

Whether you're using FQDN like **yourdomain.com** or IP to connect your registry host, run this command to generate the certificate of your registry host which comply with Subject Alternative Name (SAN) and x509 v3 extension requirement:

**v3.ext**

```
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=yourdomain.com
DNS.2=yourdomain
DNS.3=hostname
EOF
```

```

  openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in yourdomain.com.csr \
    -out yourdomain.com.crt
```

## Configuration and Installation

**1) Configure Server Certificate and Key for Harbor**

After obtaining the **yourdomain.com.crt** and **yourdomain.com.key** files,
you can put them into directory such as ```/root/cert/```:

```
  cp yourdomain.com.crt /data/cert/
  cp yourdomain.com.key /data/cert/
```

**2) Configure Server Certificate, Key and CA for Docker**

The Docker daemon interprets ```.crt``` files as CA certificates and ```.cert``` files as client certificates.

Convert server ```yourdomain.com.crt``` to ```yourdomain.com.cert```:

```
openssl x509 -inform PEM -in yourdomain.com.crt -out yourdomain.com.cert
```
Delpoy ```yourdomain.com.cert```, ```yourdomain.com.key```, and ```ca.crt``` for Docker:

```
  cp yourdomain.com.cert /etc/docker/certs.d/yourdomain.com/
  cp yourdomain.com.key /etc/docker/certs.d/yourdomain.com/
  cp ca.crt /etc/docker/certs.d/yourdomain.com/
```

The following illustrates a configuration with custom certificates:


```
/etc/docker/certs.d/
    └── yourdomain.com:port
       ├── yourdomain.com.cert  <-- Server certificate signed by CA
       ├── yourdomain.com.key   <-- Server key signed by CA
       └── ca.crt               <-- Certificate authority that signed the registry certificate
```

Notice that you may need to trust the certificate at OS level. Please refer to the [Troubleshooting](#Troubleshooting) section below.

**3) Configure Harbor**

Edit the file `harbor.yml`, update the hostname and uncomment the https block, and update the attributes `certificate` and `private_key`:

```yaml
#set hostname
hostname: yourdomain.com

http:
  port: 80

https:
  # https port for harbor, default is 443
  port: 443
  # The path of cert and key files for nginx
  certificate: /data/cert/yourdomain.com.crt
  private_key: /data/cert/yourdomain.com.key

  ......

```

Generate configuration files for Harbor:

```
  ./prepare
```

If Harbor is already running, stop and remove the existing instance. Your image data remain in the file system

```
  docker-compose down -v
```
Finally, restart Harbor:

```
  docker-compose up -d
```
After setting up HTTPS for Harbor, you can verify it by the following steps:

* Open a browser and enter the address: https://yourdomain.com. It should display the user interface of Harbor.

* Notice that some browser may still shows the warning regarding Certificate Authority (CA) unknown for security reason even though we signed certificates by self-signed CA and deploy the CA to the place mentioned above. It is because self-signed CA essentially is not a trusted third-party CA. You can import the CA to the browser on your own to solve the warning.

* On a machine with Docker daemon, make sure the option "-insecure-registry" for https://yourdomain.com is not present.

* If you mapped nginx port 443 to another port, then you should instead create the directory ```/etc/docker/certs.d/yourdomain.com:port``` (or your registry host IP:port). Then run any docker command to verify the setup, e.g.


```
  docker login yourdomain.com
```
If you've mapped nginx 443 port to another, you need to add the port to login, like below:

```
  docker login yourdomain.com:port
```


## Troubleshooting
1. You may get an intermediate certificate from a certificate issuer. In this case, you should merge the intermediate certificate with your own certificate to create a certificate bundle. You can achieve this by the below command:

    ```
    cat intermediate-certificate.pem >> yourdomain.com.crt
    ```
2. On some systems where docker daemon runs, you may need to trust the certificate at OS level.
   On Ubuntu, this can be done by below commands:

    ```sh
    cp yourdomain.com.crt /usr/local/share/ca-certificates/yourdomain.com.crt
    update-ca-certificates
    ```

   On Red Hat (CentOS etc), the commands are:

    ```sh
    cp yourdomain.com.crt /etc/pki/ca-trust/source/anchors/yourdomain.com.crt
    update-ca-trust
    ```
