Issue:
I’m setting up my Ubuntu 24.04 LTS (GNU/Linux 6.8.0-36-generic x86_64) server to handle my Django site. We’re going to run everything in a docker environment.
docker-compose up --build
Everything builds with no error messages but the issue comes with
/.well-known/acme-challenge/
/.well-known/acme-challenge/test-file/
Error messages for acme-challenge:
nginx_1 | 123.45.67.89 - - [06/Aug/2024:11:06:34 +0000] "GET /.well-known/acme-challenge/ HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
nginx_1 | 2024/08/06 10:20:00 [error] 29#29: *12 "/var/www/allhoa/certbot/.well-known/acme-challenge/test-file/index.html" is not found (20: Not a directory), client: 123.45.67.891, server: mydjangosite.com, request: "GET /.well-known/acme-challenge/test-file/ HTTP/1.1", host: "www.mydjangosite.com"
nginx_1 | 123.45.67.891 - - [06/Aug/2024:10:20:00 +0000] "GET /.well-known/acme-challenge/test-file/ HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
nginx_1 | 123.45.67.891 - - [06/Aug/2024:10:20:50 +0000] "GET / HTTP/1.1" 200 27800 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
web_1 | 172.18.0.6 - - [06/Aug/2024:10:20:50 +0000] "GET / HTTP/1.0" 200 27800 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
Ideal Outcome:
Successfully set up HTTPS via letsencrypt and certbot with auto renew
Relevant code:
file: /var/www/mydjangosite/config/gunicorn.conf.py
import multiprocessing
bind = "0.0.0.0:9000"
workers = multiprocessing.cpu_count() * 2 + 1
loglevel = 'info'
errorlog = '-'
accesslog = '-'
file: /var/www/mydjangosite/config/nginx.conf
user nginx;
worker_processes auto;
pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server {
listen 80; # Listen on IPv4
listen [::]:80; # Listen on IPv6
server_name mydjangosite.com www.mydjangosite.com;
location /.well-known/acme-challenge/ {
root /var/www/mydjangosite/config/www;
}
location / {
proxy_pass http://web:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static/ {
alias /code/staticfiles/;
}
location /media/ {
alias /code/media/;
}
}
}
file: /var/www/mydjangosite/docker-compose.yml
# version: '3.8' # not required
volumes:
postgres_data: {}
static_volume: {}
# certbot-etc: {}
# certbot-var: {}
services:
nginx:
image: nginx:latest
env_file:
- .env
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf
- ./config/certbot/conf/options-ssl-nginx.conf:/etc/letsencrypt/options-ssl-nginx.conf
- ./config/certbot/conf/ssl-dhparams.pem:/etc/letsencrypt/ssl-dhparams.pem
# - .:/code
- static_volume:/code/staticfiles
- ./config/certbot/conf:/etc/letsencrypt
- ./config/certbot/www:/var/www/mydjangosite/config/certbot/www
ports:
- "80:80"
- "443:443"
depends_on:
- web
command: nginx -g 'daemon off;'
certbot:
image: certbot/certbot
volumes:
- ./config/certbot/conf:/etc/letsencrypt
- ./config/certbot/www:/var/www/allhoa/config/certbot/www
- ./certbot-entrypoint.sh:/certbot-entrypoint.sh
entrypoint: ["/certbot-entrypoint.sh"]
web:
build:
context: .
command: >
bash -c "
cat .env &&
pip install --default-timeout=100 --retries=5 -r requirements.txt &&
python manage.py migrate &&
python manage.py collectstatic --no-input &&
gunicorn --config ./config/gunicorn.conf.py allhoa.wsgi:application"
environment:
- DATABASE_URL=postgres://${DBUSER}:${DBPASSWORD}@${DBHOST}:${DBPORT}/${DBNAME}
env_file:
- .env
volumes:
- .:/code
- static_volume:/code/staticfiles
ports:
- "9000:9000"
file: /var/www/mydjangosite/Dockerfile
# Use an official Python runtime as a parent image
FROM python:latest
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Set the working directory in the container
WORKDIR /code
# Copy the project code
COPY . /code/
# Install any needed packages specified in requirements.txt
RUN apt-get update && apt-get install -y libxslt-dev libxml2-dev libpam-dev libedit-dev && apt-get clean && rm -rf /var/lib/apt/lists/*
# RUN pip install --upgrade pip && pip install -r requirements.txt
RUN pip install --upgrade pip && pip install --default-timeout=100 --retries=5 -r requirements.txt
RUN python manage.py collectstatic --no-input
# Collect static files
RUN python manage.py collectstatic --no-input
# Command to run the Django application
CMD ["gunicorn", "mydjangosite.wsgi:application", "--bind", "0.0.0.0:9000"]
3