|
|
|
|
@ -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
|
|
|
|
|
|
|
|
|
|
@ -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};
|
|
|
|
|
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.
|
|
|
|
|
|