Skip to content

Commit 9288d12

Browse files
author
Vladimir Skubriev
committed
update https install section
1 parent d0b9481 commit 9288d12

File tree

2 files changed

+116
-174
lines changed

2 files changed

+116
-174
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
!/ssh/README.md
1414
node_modules
1515
/Mask_RCNN/
16+
/letsencrypt-webroot/
1617

1718
# Ignore temporary files
1819
docker-compose.override.yml

cvat/apps/documentation/installation.md

+115-174
Original file line numberDiff line numberDiff line change
@@ -327,29 +327,37 @@ If this is not the case, please complete the steps in the installation manual fi
327327

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

330-
- Move Docker Compose CVAT access port to 80/tcp.
331-
- Configure Nginx to pass one of the [ACME challenges](https://letsencrypt.org/docs/challenge-types/).
330+
- Setup containers on default 80/tcp port. Checkin and then down the containers.
331+
- Configure Nginx to pass one of the [ACME challenges](https://letsencrypt.org/docs/challenge-types/) - webroot.
332332
- Create the certificate files using [acme.sh](https://github.com/acmesh-official/acme.sh).
333333
- Reconfigure Nginx to serve over HTTPS and map CVAT to Docker Compose port 443.
334334

335335
#### Step-by-step instructions
336336

337-
##### 1. Move the CVAT access port
337+
##### 1. Make the proxy listen on standard port 80 and prepare nginx for the ACME challenge via webroot method
338+
339+
> The configuration assumes that on the docker host there will be only one instance of the CVAT site listens for incoming connections on 80 and 443 port. Also redirecting everything that does not concern renewal of certificates to the site via secure HTTPS protocol.
338340

339341
Let's assume the server will be at `my-cvat-server.org`.
340342
343+
Point you shell in cvat repository directory, usually `cd $HOME/cvat`:
344+
345+
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`.
346+
347+
Create enough directories for letsencrypt webroot operation and acme folder passthrougth.
348+
349+
and restart containers with a new configuration updated in `docker-compose.override.yml`
350+
341351
```bash
342-
# on the server
343-
docker-compose down
352+
# on the docker host
344353
345-
# add docker-compose.override.yml as per instructions below
354+
# this will create ~/.acme.sh directory
355+
curl https://get.acme.sh | sh
346356
347-
docker-compose up -d
357+
# create a subdirs for acme-challenge webroot manually
358+
mkdir -p $HOME/cvat/letsencrypt-webroot/.well-known/acme-challenge
348359
```
349360
350-
Add the following into your `docker-compose.override.yml`, replacing `my-cvat-server.org` with your own IP address.
351-
This file lives in the same directory as `docker-compose.yml`.
352-
353361
```yaml
354362
# docker-compose.override.yml
355363
version: "2.3"
@@ -359,194 +367,154 @@ services:
359367
environment:
360368
CVAT_HOST: my-cvat-server.org
361369
ports:
362-
- "80:80"
370+
- "80:80"
371+
- "443:443"
372+
volumes:
373+
- ./letsencrypt-webroot:/var/tmp/letsencrypt-webroot
374+
- /root/.acme.sh:/root/.acme.sh
363375
364376
cvat:
365377
environment:
366378
ALLOWED_HOSTS: '*'
367379
```
368380
369-
You should now see an unsecured version of CVAT at `http://my-cvat-server.org`.
381+
This will enable serving `http://my-cvat-server.org/.well-known/acme-challenge/`
382+
route from `/var/tmp/letsencrypt-webroot` directory on the container's filesystem which is bind mounted from docker host `$HOME/cvat/letsencrypt-webroot`. That volume needed for issue and renewing certificates only.
383+
384+
Update a CVAT site proxy template `$HOME/cvat/cvat_proxy/conf.d/cvat.conf.template` on docker(system) host. Site config updates from this template each time `cvat_proxy` container start.
370385

371-
##### 2. Configure Nginx for the ACME challenge
386+
Add a location to server with `server_name ${CVAT_HOST};` ahead others:
372387

373-
Temporarily, enable serving `http://my-cvat-server.org/.well-known/acme-challenge/`
374-
route from `/letsencrypt` directory on the server's filesystem.
388+
```
389+
location ^~ /.well-known/acme-challenge/ {
390+
default_type "text/plain";
391+
root /var/tmp/letsencrypt-webroot;
392+
}
393+
```
375394
You can use the [Nginx quickstart guide](http://nginx.org/en/docs/beginners_guide.html) for reference.
376395

396+
377397
```bash
378-
# cvat_proxy/conf.d/cvat.conf.template
398+
# on the docker host
399+
docker-compose down
400+
docker-compose up -d
401+
```
379402

380-
server {
381-
listen 80;
382-
server_name _ default;
383-
return 404;
384-
}
403+
Your server should still be visible (and unsecured) at `http://my-cvat-server.org`
404+
but you won't see any behavior changes.
385405
386-
server {
387-
listen 80;
388-
server_name ${CVAT_HOST};
406+
At this point your deployment is up and running, ready for run acme-challenge.
389407
390-
# add this temporarily, to pass an acme challenge
391-
location ^~ /.well-known/acme-challenge/ {
392-
allow all;
393-
root /letsencrypt;
394-
}
408+
##### 2. Setting up HTTPS with `acme.sh` helper
395409
396-
location ~* /api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.* {
397-
proxy_pass http://cvat:8080;
398-
proxy_pass_header X-CSRFToken;
399-
proxy_set_header Host $http_host;
400-
proxy_pass_header Set-Cookie;
401-
}
410+
There are multiple approaches. First one is to use helper on docker host.
402411
403-
location / {
404-
# workaround for match location by arguments
405-
error_page 418 = @annotation_ui;
412+
In a our approach
413+
* it is easier to setup automatic certificate updates and (than it can be done in the container).
414+
* leave certificates in safe place on docker host (protect from `docker-compose down` cleanup)
415+
* no unnecessary certificate files copying between container and host.
406416
407-
if ( $query_string ~ "^id=\d+.*" ) { return 418; }
417+
###### Create certificate files using an ACME challenge on docker host
408418
409-
proxy_pass http://cvat_ui;
410-
proxy_pass_header X-CSRFToken;
411-
proxy_set_header Host $http_host;
412-
proxy_pass_header Set-Cookie;
413-
}
419+
**Prepare certificates.**
414420
415-
# old annotation ui, will be removed in the future.
416-
location @annotation_ui {
417-
proxy_pass http://cvat:8080;
418-
proxy_pass_header X-CSRFToken;
419-
proxy_set_header Host $http_host;
420-
proxy_pass_header Set-Cookie;
421-
}
422-
}
423-
```
421+
Point you shell in cvat repository directory, usually `cd $HOME/cvat` on docker host.
424422
425-
Now create the `/letsencrypt` directory and mount it into `cvat_proxy` container.
426-
Edit your `docker-compose.override.yml` to look like the following:
423+
> Certificate issue and updates should be on docker host in this approach.
427424
428-
```yaml
429-
# docker-compose.override.yml
430-
version: "2.3"
425+
Let’s Encrypt provides rate limits to ensure fair usage by as many people as possible. They recommend utilize their staging environment instead of the production API during testing. So first try to get a test certificate.
431426
432-
services:
433-
cvat_proxy:
434-
environment:
435-
CVAT_HOST: my-cvat-server.org
436-
ports:
437-
- "80:80"
438-
volumes:
439-
- ./letsencrypt:/letsencrypt
440-
441-
cvat:
442-
environment:
443-
ALLOWED_HOSTS: '*'
427+
```
428+
~/.acme.sh/acme.sh --issue --staging -d my-cvat-server.org -w $HOME/cvat/letsencrypt-webroot --debug
444429
```
445430
446-
Finally, create the directory and restart CVAT.
431+
> Debug note: nginx server logs for cvat_proxy are not saved in container. You shall see it at docker host by with: `docker logs cvat_proxy`.
447432
448-
```bash
449-
# in the same directory where docker-compose.override.yml lives
450-
mkdir -p letsencrypt/.well-known/acme-challenge
433+
If certificates is issued a successful we should test a renew:
451434
452-
docker-compose down
453-
docker-compose up -d
454435
```
436+
~/.acme.sh/acme.sh --renew --force --staging -d my-cvat-server.org -w $HOME/cvat/letsencrypt-webroot --debug
437+
```
438+
If success:
455439
456-
Your server should still be visible (and unsecured) at `http://my-cvat-server.org`
457-
but you won't see any behavior changes.
440+
* remove test certificate
441+
* issue a production certificate
442+
* create a cron job for user (`crontab -e`).
458443
459-
##### 3. Create certificate files using an ACME challenge
444+
```
445+
~/.acme.sh/acme.sh --remove -d my-cvat-server.org --debug
446+
rm -r /root/.acme.sh/my-cvat-server.org
460447
461-
At this point your deployment is running.
448+
~/.acme.sh/acme.sh --issue -d my-cvat-server.org -w $HOME/cvat/letsencrypt-webroot --debug
462449
463-
```bash
464-
admin@tempVM:~/cvat$ docker ps
465-
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
466-
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
467-
b85497c44836 cvat_cvat_ui "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp cvat_ui
468-
d25a00475849 cvat "/usr/bin/supervisord" About a minute ago Up About a minute 8080/tcp, 8443/tcp cvat
469-
6353a43f55c3 redis:4.0-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp cvat_redis
470-
52009636caa8 postgres:10-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 5432/tcp cvat_db
450+
~/.acme.sh/acme.sh --install-cronjob
471451
```
472452
473-
We will attach `cvat_proxy` container to run `acme.sh` scripts.
453+
Down the cvat_proxy container for setup https with issued certificates.
474454
475455
```bash
476-
admin@tempVM:~/cvat$ docker exec -ti cvat_proxy /bin/sh
477-
478-
# install some missing software inside cvat_proxy
479-
/ # apk add openssl curl
480-
/ # curl https://get.acme.sh | sh
481-
/ # ~/.acme.sh/acme.sh -h
482-
[... many lines ...]
483-
484-
/ # ~/.acme.sh/acme.sh --issue -d my-cvat-server.org -w /letsencrypt
485-
[Fri Apr 3 20:49:05 UTC 2020] Create account key ok.
486-
[Fri Apr 3 20:49:05 UTC 2020] Registering account
487-
[Fri Apr 3 20:49:06 UTC 2020] Registered
488-
[Fri Apr 3 20:49:06 UTC 2020] ACCOUNT_THUMBPRINT='tril8-LdJgM8xg6mnN1pMa7vIMdFizVCE0NImNmyZY4'
489-
[Fri Apr 3 20:49:06 UTC 2020] Creating domain key
490-
[ ... many more lines ...]
491-
[Fri Apr 3 20:49:10 UTC 2020] Your cert is in /root/.acme.sh/my-cvat-server.org/my-cvat-server.org.cer
492-
[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
493-
[Fri Apr 3 20:49:10 UTC 2020] The intermediate CA cert is in /root/.acme.sh/my-cvat-server.org/ca.cer
494-
[Fri Apr 3 20:49:10 UTC 2020] And the full chain certs is there: /root/.acme.sh/my-cvat-server.org/fullchain.cer
495-
496-
/ # cp ~/.acme.sh/my-cvat-server.org/my-cvat-server.org.cer /letsencrypt/certificate.cer
497-
/ # cp ~/.acme.sh/my-cvat-server.org/my-cvat-server.org.key /letsencrypt/certificate.key
498-
/ # cp ~/.acme.sh/my-cvat-server.org/ca.cer /letsencrypt/ca.cer
499-
/ # cp ~/.acme.sh/my-cvat-server.org/fullchain.cer /letsencrypt/fullchain.cer
500-
/ # exit
501-
admin@tempVM:~/cvat$ ls letsencrypt/
502-
ca.cer certificate.cer certificate.key fullchain.cer
503-
admin@tempVM:~/cvat$ mkdir cert
504-
admin@tempVM:~/cvat$ mv letsencrypt/* ./cert
456+
docker stop cvat_proxy
505457
```
506458
507-
##### 4. Reconfigure Nginx for HTTPS access
508-
509-
Update Docker Compose configuration to mount the certificate directory.
459+
**Reconfigure nginx for use certificates.**
510460
511-
```yml
512-
# docker-compose.override.yml
513-
version: "2.3"
461+
Bring the configuration file `$HOME/cvat/cvat_proxy/conf.d/cvat.conf.template` to the following form:
514462
515-
services:
516-
cvat_proxy:
517-
environment:
518-
CVAT_HOST: my-cvat-server.org
519-
ports:
520-
- "443:443"
521-
volumes:
522-
- ./letsencrypt:/letsencrypt
523-
- ./cert:/cert:ro # this is new
524-
525-
cvat:
526-
environment:
527-
ALLOWED_HOSTS: '*'
528-
```
463+
* add location with redirect `return 301` to 80/tcp server.
464+
* change listen to `listen 443 ssl;` in main configururation server
465+
* add ssl certificates options and secure them.
529466
530-
Also, reconfigure Nginx to use `443/tcp` and point it to the new keys.
467+
Example of configuration file:
531468
532-
```bash
469+
```
533470
server {
534471
listen 80;
535472
server_name _ default;
536473
return 404;
537474
}
538475
539476
server {
540-
listen 443 ssl;
477+
listen 80;
478+
server_name ${CVAT_HOST};
479+
480+
location ^~ /.well-known/acme-challenge/ {
481+
default_type "text/plain";
482+
root /var/tmp/letsencrypt;
483+
}
484+
485+
location / {
486+
return 301 https://$server_name$request_uri;
487+
}
488+
}
489+
490+
server {
491+
listen 443 ssl;
492+
ssl_certificate /root/.acme.sh/my-cvat-server.org/my-cvat-server.org.cer;
493+
ssl_certificate_key /root/.acme.sh/my-cvat-server.org/my-cvat-server.org.key;
494+
ssl_trusted_certificate /root/.acme.sh/my-cvat-server.org/fullchain.cer;
495+
496+
# security options
497+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
498+
ssl_prefer_server_ciphers on;
499+
ssl_stapling on;
500+
ssl_session_timeout 24h;
501+
ssl_session_cache shared:SSL:2m;
502+
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!3DES';
503+
504+
# security headers
505+
add_header X-Frame-Options "SAMEORIGIN" always;
506+
add_header X-XSS-Protection "1; mode=block" always;
507+
add_header X-Content-Type-Options "nosniff" always;
508+
add_header Referrer-Policy "no-referrer-when-downgrade" always;
509+
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
510+
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
511+
541512
server_name ${CVAT_HOST};
542513
543514
proxy_pass_header X-CSRFToken;
544515
proxy_set_header Host $http_host;
545516
proxy_pass_header Set-Cookie;
546517
547-
ssl_certificate /cert/certificate.cer;
548-
ssl_certificate_key /cert/certificate.key;
549-
550518
location ~* /api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.* {
551519
proxy_pass http://cvat:8080;
552520
}
@@ -570,35 +538,8 @@ server {
570538
}
571539
```
572540
573-
Finally, restart your service.
541+
Start cvat_proxy container with https enabled.
574542
575-
```bash
576-
admin@tempVM:~/cvat$ docker-compose down
577-
Stopping cvat_proxy ... done
578-
Stopping cvat_ui ... done
579-
Stopping cvat ... done
580-
Stopping cvat_db ... done
581-
Stopping cvat_redis ... done
582-
Removing cvat_proxy ... done
583-
Removing cvat_ui ... done
584-
Removing cvat ... done
585-
Removing cvat_db ... done
586-
Removing cvat_redis ... done
587-
Removing network cvat_default
588-
admin@tempVM:~/cvat$ docker-compose up -d
589-
Creating network "cvat_default" with the default driver
590-
Creating cvat_db ... done
591-
Creating cvat_redis ... done
592-
Creating cvat ... done
593-
Creating cvat_ui ... done
594-
Creating cvat_proxy ... done
595-
admin@tempVM:~/cvat$ docker ps
596-
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
597-
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
598-
8428cfbb766e cvat_cvat_ui "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp cvat_ui
599-
b5a2f78689da cvat "/usr/bin/supervisord" About a minute ago Up About a minute 8080/tcp, 8443/tcp cvat
600-
ef4a1f47440f redis:4.0-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp cvat_redis
601-
7803bf828d9f postgres:10-alpine "docker-entrypoint.s…" About a minute ago Up About a minute 5432/tcp cvat_db
602543
```
603-
604-
Now you can go to `https://my-cvat-server.org/` and verify that you are using an encrypted connection.
544+
docker start cvat_proxy
545+
```

0 commit comments

Comments
 (0)