diff options
| author | crupest <crupest@outlook.com> | 2022-11-22 14:11:37 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2022-11-22 14:11:37 +0800 | 
| commit | 813aa19d72bc98842cf86b15d95b677b36098b90 (patch) | |
| tree | 7b3606eed1c7b6831de2c863c0b7d04e23ed589f | |
| parent | 2359f2603e7d3a18bf183f5b248a8e4d915ba36a (diff) | |
| download | crupest-813aa19d72bc98842cf86b15d95b677b36098b90.tar.gz crupest-813aa19d72bc98842cf86b15d95b677b36098b90.tar.bz2 crupest-813aa19d72bc98842cf86b15d95b677b36098b90.zip  | |
Add auto-certbot.
| -rw-r--r-- | docker/auto-certbot/Dockerfile | 5 | ||||
| -rwxr-xr-x | docker/auto-certbot/daemon.bash | 29 | ||||
| -rw-r--r-- | template/docker-compose.yaml.template | 17 | ||||
| -rwxr-xr-x | tool/aio.py | 40 | ||||
| -rwxr-xr-x | tool/modules/nginx.py | 52 | 
5 files changed, 103 insertions, 40 deletions
diff --git a/docker/auto-certbot/Dockerfile b/docker/auto-certbot/Dockerfile index 345682c..655197d 100644 --- a/docker/auto-certbot/Dockerfile +++ b/docker/auto-certbot/Dockerfile @@ -1,5 +1,6 @@  FROM certbot/certbot:latest  ARG CRUPEST_DOMAIN -ARG CRUPEST_CERTBOT_RENEW_COMMAND +ARG CRUPEST_CERTBOT_RENEW_COMMAND=""  COPY daemon.bash /daemon.bash -CMD [ "/daemon.bash" ] +VOLUME ["/var/www/certbot", "/etc/letsencrypt", "/var/lib/letsencrypt"] +ENTRYPOINT [ "/daemon.bash" ] diff --git a/docker/auto-certbot/daemon.bash b/docker/auto-certbot/daemon.bash index 8927c4a..de21ba8 100755 --- a/docker/auto-certbot/daemon.bash +++ b/docker/auto-certbot/daemon.bash @@ -8,8 +8,11 @@ fi  # Check CRUPEST_CERTBOT_RENEW_COMMAND is defined.  if [ -z "$CRUPEST_CERTBOT_RENEW_COMMAND" ]; then -    echo "CRUPEST_CERTBOT_RENEW_COMMAND must be defined." -    exit 1 +    echo "CRUPEST_CERTBOT_RENEW_COMMAND is not defined or empty" +    CRUPEST_CERTBOT_RENEW_COMMAND="certbot renew --webroot -w /var/www/certbot" +    printf "Will use:\n%s\n" "$CRUPEST_CERTBOT_RENEW_COMMAND" +else +    printf "CRUPEST_CERTBOT_RENEW_COMMAND is defined as:\n%s\n" "$CRUPEST_CERTBOT_RENEW_COMMAND"  fi  # Check CRUPEST_CERT_PATH, default to /etc/letsencrypt/live/$CRUPEST_DOMAIN/fullchain.pem @@ -17,7 +20,7 @@ if [ -z "$CRUPEST_CERT_PATH" ]; then      CRUPEST_CERT_PATH="/etc/letsencrypt/live/$CRUPEST_DOMAIN/fullchain.pem"  fi -function check_and_renew_cert() { +function check_and_renew_cert {      expire_info=$(openssl x509 -enddate -noout -in "$CRUPEST_CERT_PATH")      # Get ssl certificate expire date. @@ -33,21 +36,15 @@ function check_and_renew_cert() {      echo "Renew SSL certificate at: $(date -d @$renew_timestamp)"      # Get rest time til renew. -    rest_time="$((renew_timestamp - $(date +%s)))" -    echo "Rest time til renew: $rest_time seconds" +    rest_time_in_second="$((renew_timestamp - $(date +%s)))" +    rest_time_in_day=$((rest_time_in_second / 86400)) +    echo "Rest time til renew: $rest_time_in_second seconds, aka, about $rest_time_in_day days"      # Do we have rest time? -    if [ "$rest_time" -gt 0 ]; then -        # Check CRUPEST_GREEDY_CHECK is defined. -        if [ -z "$CRUPEST_GREEDY_CHECK" ]; then -            # Sleep til renew. -            echo "Sleeping til renew..." -            sleep "$rest_time" -        else -            # Sleep 1 hour. -            echo "Seems like CRUPEST_GREEDY_CHECK is defined, sleep 1 day and check again..." -            sleep 86400 -        fi +    if [ $rest_time_in_second -gt 0 ]; then +        # Sleep 1 hour. +        echo "I'm going to sleop for 1 day to check again." +        sleep 1d      else          # No, renew now.          echo "Renewing now..." diff --git a/template/docker-compose.yaml.template b/template/docker-compose.yaml.template index acabf5a..6da2c3c 100644 --- a/template/docker-compose.yaml.template +++ b/template/docker-compose.yaml.template @@ -75,6 +75,23 @@ services:        - external        - internal +  auto-certbot: +    image: crupest/auto-certbot:latest +    build: +      context: ./docker/auto-certbot +      dockerfile: Dockerfile +      pull: true +      args: +        - CRUPEST_DOMAIN=$CRUPEST_DOMAIN +    container_name: auto-certbot +    volumes: +      - "./data/certbot/certs:/etc/letsencrypt" +      - "./data/certbot/data:/var/lib/letsencrypt" +      - "./data/certbot/webroot:/var/www/certbot" +    restart: on-failure:3 +    networks: +      - internal +    mailserver:      image: docker.io/mailserver/docker-mailserver:latest      pull_policy: always diff --git a/tool/aio.py b/tool/aio.py index 94e4460..cdb616c 100755 --- a/tool/aio.py +++ b/tool/aio.py @@ -408,21 +408,35 @@ if to_gen_nginx_conf:      domain = config["CRUPEST_DOMAIN"]      generate_nginx_config(domain) - -if not os.path.exists(os.path.join(data_dir, "code-server")): -    os.mkdir(os.path.join(data_dir, "code-server")) +if not os.path.exists(data_dir):      console.print( -        "I also create data dir for code-server. Because letting docker create it would result in permission problem.", style="green") -else: -    code_server_stat = os.stat(os.path.join(data_dir, "code-server")) -    if code_server_stat.st_uid == 0 or code_server_stat.st_gid == 0: +        "Looks like you haven't generated data dir. I'll create it for you.", style="green") +    os.mkdir(data_dir) +elif not os.path.isdir(data_dir): +    console.print( +        "ERROR: data dir is not a dir! Everything will be broken! Please delete it manually", style="red") + +if os.path.isdir(data_dir): +    if not os.path.exists(os.path.join(data_dir, "certbot")): +        console.print( +            "Looks like you haven't run certbot to get the init ssl certificates. You may want to run following code to get one:", style="cyan") +        console.print(certbot_command_gen(domain, "create"), +                      soft_wrap=True, highlight=False) + +    if not os.path.exists(os.path.join(data_dir, "code-server")): +        os.mkdir(os.path.join(data_dir, "code-server"))          console.print( -            "WARNING: The owner of data dir for code-server is root. This may cause permission problem. You had better change it.", style="yellow") -        to_fix = Confirm.ask( -            "Do you want me to help you fix it?", console=console, default=True) -        if to_fix: -            os.system( -                f"sudo chown -R {os.getuid()}:{os.getgid()} {os.path.join(data_dir, 'code-server')}") +            "I also create data dir for code-server. Because letting docker create it would result in permission problem.", style="green") +    else: +        code_server_stat = os.stat(os.path.join(data_dir, "code-server")) +        if code_server_stat.st_uid == 0 or code_server_stat.st_gid == 0: +            console.print( +                "WARNING: The owner of data dir for code-server is root. This may cause permission problem. You had better change it.", style="yellow") +            to_fix = Confirm.ask( +                "Do you want me to help you fix it?", console=console, default=True) +            if to_fix: +                os.system( +                    f"sudo chown -R {os.getuid()}:{os.getgid()} {os.path.join(data_dir, 'code-server')}")  console.print(":beers: All done!", style="green")  to_download_tools = Confirm.ask( diff --git a/tool/modules/nginx.py b/tool/modules/nginx.py index 422a823..3ec9fb8 100755 --- a/tool/modules/nginx.py +++ b/tool/modules/nginx.py @@ -76,19 +76,53 @@ def list_domains(domain: str) -> list:      return [domain, *list_subdomains(domain)] -def certbot_command_gen(domain: str, action, test=False) -> str: +def certbot_command_gen(domain: str, action, /, test=False, no_docker=False, *, standalone=None, email=None, agree_tos=False) -> str:      domains = list_domains(domain) + +    add_domain_option = True      if action == 'create': -        # create with standalone mode -        return f'docker run -it --rm --name certbot -v "{project_abs_path}/data/certbot/certs:/etc/letsencrypt" -v "{project_abs_path}/data/certbot/data:/var/lib/letsencrypt" -p "0.0.0.0:80:80" certbot/certbot certonly --standalone -d {" -d ".join(domains)}{ " --test-cert --dry-run" if test else "" }' +        if standalone == None: +            standalone = True +        certbot_action = "certonly"      elif action == 'expand': -        # expand with webroot mode -        return f'docker run -it --rm --name certbot -v "{project_abs_path}/data/certbot/certs:/etc/letsencrypt" -v "{project_abs_path}/data/certbot/data:/var/lib/letsencrypt" -v "{project_abs_path}/data/certbot/webroot:/var/www/certbot" certbot/certbot certonly --webroot -w /var/www/certbot -d {" -d ".join(domains)}{ " --test-cert --dry-run" if test else "" }' +        if standalone == None: +            standalone = False +        certbot_action = "certonly"      elif action == 'renew': -        # renew with webroot mode -        return f'docker run -it --rm --name certbot -v "{project_abs_path}/data/certbot/certs:/etc/letsencrypt" -v "{project_abs_path}/data/certbot/data:/var/lib/letsencrypt" -v "{project_abs_path}/data/certbot/webroot:/var/www/certbot" certbot/certbot renew --webroot -w /var/www/certbot{ " --test-cert --dry-run" if test else "" }' -    raise ValueError('Invalid action') - +        if standalone == None: +            standalone = False +        add_domain_option = False +        certbot_action = "renew" +    else: +        raise ValueError('Invalid action') +     +    if no_docker: +        command = "certbot " +    else: +        expose_segment = ' -p "0.0.0.0:80:80"' +        web_root_segment = ' -v "{project_abs_path}/data/certbot/webroot:/var/www/certbot"' +        command = f'docker run -it --rm --name certbot -v "{project_abs_path}/data/certbot/certs:/etc/letsencrypt" -v "{project_abs_path}/data/certbot/data:/var/lib/letsencrypt"{ expose_segment if  standalone else web_root_segment} certbot/certbot ' + +    command += certbot_action + +    if standalone: +        command += " --standalone" +    else: +        command += ' --webroot -w /var/www/certbot' + +    if add_domain_option: +        command += f' -d {" -d ".join(domains)}' + +    if email is not None: +        command += f' --email {email}' + +    if agree_tos: +        command += ' --agree-tos' + +    if test: +        command += " --test-cert --dry-run" + +    return command  def nginx_config_dir_check(dir_path: str, domain: str) -> list:      good_files = [*non_template_files, "ssl.conf", *  | 
