Docker deploys certbot and nginx to obtain SSL certificates, add HTTPS and update automatically

Time:2022-1-7

cause

  • Originally, there was a 1-core and 1g server of Tencent cloud idle, which was only used occasionallyfrpTo map the development demonstration, I want to reuse it this time, so I try to build itbitwardenInstead, find smaller onesvaultwardenHowever, the actual browser plug-in test must behttpsJust go, so you must have a domain name and certificate. By the way, I want to trycertbotTo automatically renew.

  • Just get a domain name on Alibaba cloudtopYes, 10 years ¥ 189. If you want to parse the server, you need to file, so it takes about 7 or 8 working days to file on Tencent cloud. The filing is passed. At this time, you can access it normally, and then you need to file with the public security department within 30 days.

  • Due to on the servernginxfrpvaultwardenAlldockerTo deploy, thencertbotBy the waydocker, although the official provideddockerMirroring is not recommended, because it is difficult to trigger some external operations in the container, which will make some automatic configuration functions difficult to use. Refer to the official document:Running with Docker

certbot

Before issuing the certificate, you need to verify the legitimacy of the domain name to ensure that the domain name you apply for the certificate is yours. There are two main verification methods:

  • Through HTTP request authentication, theHttp: // your domain name / well-known/acme-challenge/Send a request.

  • Through DNS resolution, you need to add an entry in domain name resolution_ acme-challenge. Your domain nameTxt record for verification.

certbotThe command has many different parameters, which are mainly used to automatically generate HTTP authentication files or automatically add DNS parsing and other functions. The main parameters are as follows:

  • --manual, manual configuration. You can choose whether HTTP authentication or DNS authentication is OK. You need to configure HTTP authentication files or DNS parsing purely manually. I didn’t test it personally.

  • --nginx, go HTTP verification, if notdockerIt is most convenient to use nginx. It will automatically modify the configuration file of nginx and add the access configuration of HTTP request and subsequent SSL configurationcertbotYesdockerContainer, so you need to modify another onenginxThe container configuration file and control startup and shutdown are not easy to implement, so this method is not adopted. When I checked the data, I found that someone wouldnginxandcertbotadoptdockerfilePackage it into an image, which makes it easier to execute this command. I think it’s a good method, but I don’t know it through testing.

  • --dns-xxx, it is also convenient to use DNS resolution verification. After configuration, a record will be automatically added to the domain name resolution for domain name verification. However, at present, the official only supports some foreign DNS service providers. It seems that Alibaba cloud and DNSPod in China also have third-party plug-ins, which can be used by themselvesgithubLook up and down. There is no personal test at present.

  • --standalone, go HTTP verification, even if you don’t have it in this waynginxAnd other services, you can still verify the domain name and obtain the certificate. It will virtualize a service to verify, but you need to ensure your80Don’t occupy the port, because I have it herenginxTherefore, this method is not used for testing.

  • --webroot, use HTTP authentication. If there are already services like nginx, you can use this method, and the HTTP authentication file will be automatically generated in your configured directorystandaloneThe advantage is that you don’t need to reserve port 80, that is, the original website can apply for a certificate without stopping, but the disadvantage is that you still need tonginxAnd other services/.well-known/acme-challenge/Make it correspond to the automatically generated validation file. This is what we use in the future.

adoptwebrootAfter running in the mode of, files will be generated in two places:

  • One is configured on the command line--webroot-pathGenerate temporary files in the specified directory for HTTP authentication.

  • One is that if the verification is successful, a file for storing the certificate will be generated. By default, it is in the/Etc / letsencrypt / Live / your domain nameUnder the directory, it should be noted that these certificates are soft links corresponding to../archiveNext, so we’re doing itvolumeWhen mapping, do not only map toliveThis directory, but to map/etc/letsencryptThis directory, otherwise the relevant certificate file cannot be found.

Although the above two documents arecertbotContainer generated, but wenginxContainers will be used, so we need to use the host as a transitcertbotandnginxThe container is configured to map to the same directory of the host to achievecertbotContainers andnginxContainer shared files. My serverhome/ubuntu/dockerThe following table of contents can be referenced:

├── certbot
│♪ SSL // store certificate
│ └ - WWW // store temporary files for HTTP authentication
├── nginx
│   ├── conf 
│ │ └ - conf.d // configuration file
│   │       └── valtwarden. Conf // configuration file
│♪ log // log
│ └ - Web // store website
└── docker-compose. YML // docker compse file

prepare

  • There are servers

  • There are domain names that have been filed and resolved to the server

  • installdockeranddocker-compose, just follow the official website. It’s very detailed:Docker DocumentationdockerIf downloading images is slow, you can register an alicloud account, and then find the image accelerator under the image tool in the container image service and configure it according to the instructions.

  • dockerMirroring uses:

start

  • MainlyvolumeThe mapping is done and configured by the waynginxRelevant HTTP validation for:

    • docker-compose.yml:

      version: "3.9"
      services:
          nginx:
              container_name: nginx
              image: nginx
              restart: unless-stopped
              ports:
                  - "80:80"
                  - "443:443"
              environment:
                  TZ : 'Asia/Shanghai'
              volumes:
                  -/ home / Ubuntu / docker / nginx / conf: / etc / nginx # configuration file
                  -/ home / Ubuntu / docker / nginx / Web: / usr / share / nginx # website
                  -/ home / Ubuntu / docker / nginx / log: / var / log / nginx # log
                  -/ home / Ubuntu / docker / certbot / www: / usr / share / certbot / www: RO #http authentication directory. Ro can be set as read-only because the file is finally mapped through the certbot container
                  -/ home / Ubuntu / docker / certbot / SSL: / usr / share / certbot / SSL: RO # certificate location, ditto
              command:  nginx -g 'daemon off;'
          certbot:
            container_name: certbot
            image: certbot/certbot
            volumes:
                -/ home / Ubuntu / docker / certbot / www: / usr / share / certbot / www: RW #http authentication directory. You can set RW writable, which is consistent with the host directory corresponding to the nginx container
                -/ home / Ubuntu / docker / certbot / SSL: / etc / letsencrypt: RW # certificate location, as above. Note that it is not only mapped to live, but its upper level
    • Nginx configures valtwarden conf:

      server {
          listen 80;
          listen [::]:80;
      
          server_ name  bitwarden. xxx. top;# domain name
          server_tokens off;
      
          #Configure HTTP authentication accessibility
          location /.well-known/acme-challenge/ {
              #This directory is the directory in the nginx container, which corresponds to the HTTP authentication directory in the host volumes, and the directory of the host is consistent with the directory specified by the command Webroot path in the certbot container, so the whole directory is concatenated to solve the HTTP authentication problem
              root /usr/share/certbot/www;
          }
          #HTTP jump to HTTPS
          location / {
              return 301 https://bitwarden.xxx.top$request_uri;
          }
      }
  • The volumes mapping concatenation relationship above is as follows, which is implemented through the hostcertbotandnginxThe related directories in are actually the same directory, exceptcertbotMedium/etc/letsencrypt Except for the fixed ones, other directories can be placed in any directory, as long as they correspond.

    catalogue certbot Host computer nginx
    HTTP authentication directory /usr/share/certbot/www /home/ubuntu/docker/certbot/www /usr/share/certbot/www
    Certificate directory /etc/letsencrypt /home/ubuntu/docker/certbot/ssl /usr/share/certbot/ssl
  • docker-compose up -d nginxStart nginx first, and then test whether the certificate can be issued:

    #-- dry run is only testing but not actually generating-- Webroot path corresponds to the HTTP authentication directory in certbot- D followed by the domain name-- RM is deleted after running. The certbot container does not need to be opened all the time, but the certificate can be generated under startup
    docker-compose run --rm  certbot certonly --webroot --webroot-path /usr/share/certbot/www/ --dry-run -d bitwarden.xxx.top
  • Enter information such as mailbox, if promptedThe dry run was successfulIt indicates success and can be removed--dry-runParameter to actually obtain the certificate

    docker-compose run --rm  certbot certonly --webroot --webroot-path /usr/share/certbot/www/ -d bitwarden.xxx.top
  • If the upper part is normal, it willcertbotUnder container/etc/letsencryptNext, that isnginxUnder container/usr/share/certbot/sslIn this case, you only need to configure nginx and SSL, or in the file valtwarden In conf:

    server {
        listen 80;
        listen [::]:80;
    
        server_ name  bitwarden. xxx. top;# domain name
        server_tokens off;
    
        #Configure HTTP authentication accessibility
        location /.well-known/acme-challenge/ {
            #This directory is the directory in the nginx container, which corresponds to the HTTP authentication directory in the host volumes, and the directory of the host is consistent with the directory specified by the command Webroot path in the certbot container, so the whole directory is concatenated to solve the HTTP authentication problem
            root /usr/share/certbot/www;
        }
        #HTTP jump to HTTPS
        location / {
            return 301 https://bitwarden.xxx.top$request_uri;
        }
    }
    #SSL configuration
    server {
          listen       443 ssl;
          server_name  bitwarden.xxx.top;
          #Log
          access_log  /var/log/nginx/bitwarden.access.log  main;
          error_log  /var/log/nginx/bitwarden.error.log;
          #Certificate information. The path here is in the nginx container
          ssl_certificate /usr/share/certbot/ssl/live/bitwarden.xxx.top/fullchain.pem;
          ssl_certificate_key /usr/share/certbot/ssl/live/bitwarden.xxx.top/privkey.pem;
          ssl_session_timeout 5m;
          ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
          ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
          ssl_prefer_server_ciphers on;
    
          location / {
              proxy_ pass  http://vaultwarden # Here is the proxy to the valutwaden container
              proxy_set_header Host $http_host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header REMOTE-HOST $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          }
    }
  • abovedocker-compose exec nginx nginx -tCheck whether there is a problem with the configuration nginx file,docker-compose exec nginx nginx -s reloadOr directlydocker-compose restart nginxTo restart nginx

  • If it starts normally, there should be no problem. We then need to update the certificate regularly, mainly for this purpose. Otherwise, we can directly apply for a one-year free certificate from Tencent cloud and Alibaba cloud. Add planned tasks,sudo crontab -eOpen scheduled task editing and run it on the 1st and 15th of each month

    #1. Switch to docker compose Directory of YML; 2. Then update the certificate, and it will be really successful only within 30 days from the expiration time; 3. Then reload nginx to validate the new certificate
    0 0 1,15 * * root cd /home/ubuntu/docker && /usr/local/bin/docker-compose run --rm certbot renew  && /usr/local/bin/docker-compose exec nginx nginx -s reload

    The above is related to the planned tasks. At present, I have just deployed and have not seen the actual results. It may not be correct.certbotIn containerrenewAlthough there are--deploy-hookThe function of triggering the hook after the actual update, but due to andnginxBecause it is not in the same container, nginx restart cannot be triggered. Therefore, whether the above command is successfully updated or not, nginx will restart. It is best to execute it late at night. The next operation to control another container from one container is searched. One is to install dockers in this container, and then map dockers in the host Sock, so that the operation of docker in the container is consistent with that in the host; The other is SSH to connect to another container for operation. Both of them are very troublesome. There is no need to try here.

other

  • certbotThere is a limit on the number of times to apply for a certificate. If you repeat the application for more than 5 times, you will report it againtoo many certificates already issued...If there is an error, it will be disabled for a week before continuing. At this time, you can only change the domain name or wait for a week. Refer toRate limit
  • Reference documents other than the official website:HTTPS using Nginx and Let’s encrypt in Docker, very detailed.

Recommended Today

Proper memory alignment in go language

problem type Part1 struct { a bool b int32 c int8 d int64 e byte } Before we start, I want you to calculatePart1What is the total occupancy size? func main() { fmt.Printf(“bool size: %d\n”, unsafe.Sizeof(bool(true))) fmt.Printf(“int32 size: %d\n”, unsafe.Sizeof(int32(0))) fmt.Printf(“int8 size: %d\n”, unsafe.Sizeof(int8(0))) fmt.Printf(“int64 size: %d\n”, unsafe.Sizeof(int64(0))) fmt.Printf(“byte size: %d\n”, unsafe.Sizeof(byte(0))) fmt.Printf(“string size: %d\n”, […]