Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instructions on using HTTPS #1357

Merged
merged 8 commits into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Button to reset colors settings (brightness, saturation, contrast) in the new UI
- Option to display shape text always
- Dedicated message with clarifications when share is unmounted (https://github.com/opencv/cvat/pull/1373)
- Tutorial: instructions for CVAT over HTTPS

### Changed
- Increase preview size of a task till 256, 256 on the server
Expand Down
297 changes: 297 additions & 0 deletions cvat/apps/documentation/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Stop all containers](#stop-all-containers)
- [Advanced settings](#advanced-settings)
- [Share path](#share-path)
- [Serving over HTTPS](#serving-over-https)

# Quick installation guide

Expand Down Expand Up @@ -306,3 +307,299 @@ volumes:
You can change the share device path to your actual share. For user convenience
we have defined the environment variable $CVAT_SHARE_URL. This variable
contains a text (url for example) which is shown in the client-share browser.

### Serving over HTTPS

We will add [letsencrypt.org](https://letsencrypt.org/) issued certificate to secure
our server connection.

#### Prerequisites

We assume that

- you have sudo access on your server machine,
- you have an IP address to use for remote access, and
- that the local CVAT installation works on your server.

If this is not the case, please complete the steps in the installation manual first.

#### Roadmap

We will go through the following sequence of steps to get CVAT over HTTPS:

- Move Docker Compose CVAT access port to 80/tcp.
- Configure Nginx to pass one of the [ACME challenges](https://letsencrypt.org/docs/challenge-types/).
- Create the certificate files using [acme.sh](https://github.com/acmesh-official/acme.sh).
- Reconfigure Nginx to serve over HTTPS and map CVAT to Docker Compose port 443.

#### Step-by-step instructions

##### 1. Move the CVAT access port

Let's assume the server will be at `my-cvat-server.org`.

```bash
# on the server
docker-compose down

# add docker-compose.override.yml as per instructions below

docker-compose up -d
```

Add the following into your `docker-compose.override.yml`, replacing `my-cvat-server.org` with your own IP address.
This file lives in the same directory as `docker-compose.yml`.

```yaml
# docker-compose.override.yml
version: "2.3"

services:
cvat_proxy:
environment:
CVAT_HOST: my-cvat-server.org
ports:
- "80:80"

cvat:
environment:
ALLOWED_HOSTS: '*'
```

You should now see an unsecured version of CVAT at `http://my-cvat-server.org`.

##### 2. Configure Nginx for the ACME challenge

Temporarily, enable serving `http://my-cvat-server.org/.well-known/acme-challenge/`
route from `/letsencrypt` directory on the server's filesystem.
You can use the [Nginx quickstart guide](http://nginx.org/en/docs/beginners_guide.html) for reference.

```bash
# cvat_proxy/conf.d/cvat.conf.template

server {
listen 80;
server_name _ default;
return 404;
}

server {
listen 80;
server_name ${CVAT_HOST};

# add this temporarily, to pass an acme challenge
location ^~ /.well-known/acme-challenge/ {
allow all;
root /letsencrypt;
}

location ~* /api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.* {
proxy_pass http://cvat:8080;
proxy_pass_header X-CSRFToken;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
}

location / {
# workaround for match location by arguments
error_page 418 = @annotation_ui;

if ( $query_string ~ "^id=\d+.*" ) { return 418; }

proxy_pass http://cvat_ui;
proxy_pass_header X-CSRFToken;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
}

# old annotation ui, will be removed in the future.
location @annotation_ui {
proxy_pass http://cvat:8080;
proxy_pass_header X-CSRFToken;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
}
}
```

Now create the `/letsencrypt` directory and mount it into `cvat_proxy` container.
Edit your `docker-compose.override.yml` to look like the following:

```yaml
# docker-compose.override.yml
version: "2.3"

services:
cvat_proxy:
environment:
CVAT_HOST: my-cvat-server.org
ports:
- "80:80"
volumes:
- ./letsencrypt:/letsencrypt

cvat:
environment:
ALLOWED_HOSTS: '*'
```

Finally, create the directory and restart CVAT.

```bash
# in the same directory where docker-compose.override.yml lives
mkdir -p letsencrypt/.well-known/acme-challenge

docker-compose down
docker-compose up -d
```

Your server should still be visible (and unsecured) at `http://my-cvat-server.org`
but you won't see any behavior changes.

##### 3. Create certificate files using an ACME challenge

At this point your deployment is running.

```bash
admin@tempVM:~/cvat$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0a35cd127968 nginx:stable-alpine "/bin/sh -c 'envsubs…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, 0.0.0.0:8080->80/tcp cvat_proxy
b85497c44836 cvat_cvat_ui "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp cvat_ui
d25a00475849 cvat "/usr/bin/supervisord" About a minute ago Up About a minute 8080/tcp, 8443/tcp cvat
6353a43f55c3 redis:4.0-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp cvat_redis
52009636caa8 postgres:10-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 5432/tcp cvat_db
```

We will attach `cvat_proxy` container to run `acme.sh` scripts.

```bash
admin@tempVM:~/cvat$ docker exec -ti cvat_proxy /bin/sh

# install some missing software inside cvat_proxy
/ # apk add openssl curl
/ # curl https://get.acme.sh | sh
/ # ~/.acme.sh/acme.sh -h
[... many lines ...]

/ # ~/.acme.sh/acme.sh --issue -d my-cvat-server.org -w /letsencrypt
[Fri Apr 3 20:49:05 UTC 2020] Create account key ok.
[Fri Apr 3 20:49:05 UTC 2020] Registering account
[Fri Apr 3 20:49:06 UTC 2020] Registered
[Fri Apr 3 20:49:06 UTC 2020] ACCOUNT_THUMBPRINT='tril8-LdJgM8xg6mnN1pMa7vIMdFizVCE0NImNmyZY4'
[Fri Apr 3 20:49:06 UTC 2020] Creating domain key
[ ... many more lines ...]
[Fri Apr 3 20:49:10 UTC 2020] Your cert is in /root/.acme.sh/my-cvat-server.org/my-cvat-server.org.cer
[Fri Apr 3 20:49:10 UTC 2020] Your cert key is in /root/.acme.sh/my-cvat-server.org/my-cvat-server.org.key
[Fri Apr 3 20:49:10 UTC 2020] The intermediate CA cert is in /root/.acme.sh/my-cvat-server.org/ca.cer
[Fri Apr 3 20:49:10 UTC 2020] And the full chain certs is there: /root/.acme.sh/my-cvat-server.org/fullchain.cer

/ # cp ~/.acme.sh/my-cvat-server.org/my-cvat-server.org.cer /letsencrypt/certificate.cer
/ # cp ~/.acme.sh/my-cvat-server.org/my-cvat-server.org.key /letsencrypt/certificate.key
/ # cp ~/.acme.sh/my-cvat-server.org/ca.cer /letsencrypt/ca.cer
/ # cp ~/.acme.sh/my-cvat-server.org/fullchain.cer /letsencrypt/fullchain.cer
/ # exit
admin@tempVM:~/cvat$ ls letsencrypt/
ca.cer certificate.cer certificate.key fullchain.cer
admin@tempVM:~/cvat$ mkdir cert
admin@tempVM:~/cvat$ mv letsencrypt/* ./cert
```

##### 4. Reconfigure Nginx for HTTPS access

Update Docker Compose configuration to mount the certificate directory.

```yml
# docker-compose.override.yml
version: "2.3"

services:
cvat_proxy:
environment:
CVAT_HOST: my-cvat-server.org
ports:
- "443:443"
volumes:
- ./letsencrypt:/letsencrypt
- ./cert:/cert:ro # this is new

cvat:
environment:
ALLOWED_HOSTS: '*'
```

Also, reconfigure Nginx to use `443/tcp` and point it to the new keys.

```bash
server {
listen 80;
server_name _ default;
return 404;
}

server {
listen 443 ssl;
server_name ${CVAT_HOST};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please also add 301 redirect to https:// for this server_name on 80 port?

ssl_certificate /cert/certificate.cer;
ssl_certificate_key /cert/certificate.key;

location ~* /api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.* {
proxy_pass http://cvat:8080;
proxy_pass_header X-CSRFToken;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
}

location / {
# workaround for match location by arguments
error_page 418 = @annotation_ui;

if ( $query_string ~ "^id=\d+.*" ) { return 418; }

proxy_pass http://cvat_ui;
proxy_pass_header X-CSRFToken;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
}

# old annotation ui, will be removed in the future.
location @annotation_ui {
proxy_pass http://cvat:8080;
proxy_pass_header X-CSRFToken;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
}
}
```

Finally, restart your service.

```bash
admin@tempVM:~/cvat$ docker-compose down
Stopping cvat_proxy ... done
Stopping cvat_ui ... done
Stopping cvat ... done
Stopping cvat_db ... done
Stopping cvat_redis ... done
Removing cvat_proxy ... done
Removing cvat_ui ... done
Removing cvat ... done
Removing cvat_db ... done
Removing cvat_redis ... done
Removing network cvat_default
admin@tempVM:~/cvat$ docker-compose up -d
Creating network "cvat_default" with the default driver
Creating cvat_db ... done
Creating cvat_redis ... done
Creating cvat ... done
Creating cvat_ui ... done
Creating cvat_proxy ... done
admin@tempVM:~/cvat$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
71464aeac87c nginx:stable-alpine "/bin/sh -c 'envsubs…" About a minute ago Up About a minute 0.0.0.0:443->443/tcp, 0.0.0.0:8080->80/tcp cvat_proxy
8428cfbb766e cvat_cvat_ui "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp cvat_ui
b5a2f78689da cvat "/usr/bin/supervisord" About a minute ago Up About a minute 8080/tcp, 8443/tcp cvat
ef4a1f47440f redis:4.0-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp cvat_redis
7803bf828d9f postgres:10-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 5432/tcp cvat_db
```

Now you can go to `https://my-cvat-server.org/` and verify that you are using an encrypted connection.