update docker to use certbot for ssl (hopefully)

This commit is contained in:
Chris Bell 2025-07-03 09:56:38 -05:00
parent e0891f0c7f
commit e035db829f
6 changed files with 198 additions and 3 deletions

View File

@ -18,8 +18,19 @@ FROM nginx:alpine AS final
WORKDIR /usr/share/nginx/html
COPY --from=build /app/publish/wwwroot .
COPY nginx.conf /etc/nginx/nginx.conf
COPY init-letsencrypt.sh /init-letsencrypt.sh
# Install certbot and dependencies
RUN apk add --no-cache certbot certbot-nginx bash
# Make init script executable
RUN chmod +x /init-letsencrypt.sh
EXPOSE 80
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
# Add entrypoint script to run certbot and nginx
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]

81
README.letsencrypt.md Normal file
View File

@ -0,0 +1,81 @@
# Let's Encrypt SSL Setup for SessionZero
## Overview
This repository has been configured to automatically obtain and renew SSL certificates from Let's Encrypt for secure HTTPS connections. The setup uses Certbot with the Nginx plugin to handle certificate issuance and renewal.
## Setup Instructions
1. **Initial Setup**
Before deploying for the first time, edit the `init-letsencrypt.sh` script and add your email address for Let's Encrypt notifications:
```bash
# In init-letsencrypt.sh
email="your-email@example.com" # Add your email here
```
Additionally, modify if needed:
- `domains` - The domain(s) you want certificates for
- `rsa_key_size` - The RSA key size (default: 4096)
- Remove the `--staging` flag after you've verified everything works
2. **Directory Structure**
Ensure the following directories exist on your host machine:
```bash
mkdir -p ./data/certbot/conf
mkdir -p ./data/certbot/www
```
3. **Starting the Service**
```bash
docker-compose up -d
```
The first time you run the container, it will:
- Start a temporary Nginx server
- Request certificates from Let's Encrypt
- Store certificates in the mounted volume
- Restart Nginx with the SSL configuration
## Certificate Renewal
Certificates will automatically renew when they're within 30 days of expiration. The container has a cron job that runs twice daily to check for renewals.
## Troubleshooting
1. **Certificate Issuance Failed**
Check the logs:
```bash
docker-compose logs sessionzero
```
Common issues:
- DNS not pointing to your server
- Firewall blocking ports 80/443
- Rate limits exceeded (use `--staging` flag to test)
2. **Manual Certificate Renewal**
You can force a renewal by executing:
```bash
docker-compose exec sessionzero certbot renew --force-renewal
```
3. **Starting Over**
If you need to reset and start fresh:
```bash
docker-compose down
rm -rf ./data/certbot
mkdir -p ./data/certbot/conf
mkdir -p ./data/certbot/www
```
## Additional Information
- Certificates are stored in `/etc/letsencrypt` inside the container, mounted to `./data/certbot/conf` on the host
- Webroot challenges are stored in `/var/www/certbot` inside the container, mounted to `./data/certbot/www` on the host

View File

@ -6,10 +6,13 @@ services:
context: .
dockerfile: Dockerfile
ports:
- "80:80" # Map container port 80 to host port 80
- "80:80" # HTTP
- "443:443" # HTTPS
restart: unless-stopped
volumes:
- nginx-cache:/var/cache/nginx
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80

15
docker-entrypoint.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/bash
set -e
# Check if we have certificates already
if [ ! -d /etc/letsencrypt/live/web.sessionzero.app ]; then
echo "No certificates found, running init script..."
/init-letsencrypt.sh
fi
# Set up automatic renewal
echo "0 0,12 * * * certbot renew --quiet" > /etc/crontabs/root
crond
# Start nginx in foreground
exec nginx -g 'daemon off;'

47
init-letsencrypt.sh Normal file
View File

@ -0,0 +1,47 @@
#!/bin/bash
domains=(web.sessionzero.app)
email="" # Add your email for Let's Encrypt notifications
rsa_key_size=4096
data_path="/etc/letsencrypt"
stagingflag="--staging"
echo "### Creating certificate directories..."
mkdir -p "$data_path/www"
mkdir -p "$data_path/live/$domains"
echo "### Starting temporary nginx server for webroot challenge..."
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
cat > /etc/nginx/nginx.conf << EOF
events { worker_connections 1024; }
http {
server {
listen 80;
server_name ${domains[*]};
location /.well-known/acme-challenge/ { root /var/www/certbot; }
}
}
EOF
nginx
echo "### Obtaining SSL certificate..."
# Once you're confident the setup works, remove the --staging flag
# First run with --staging to verify everything works
certbot certonly --webroot -w /var/www/certbot \
$stagingflag \
--email $email \
--agree-tos \
--no-eff-email \
--force-renewal \
-d ${domains[0]} \
--rsa-key-size $rsa_key_size
# Once verified, run without staging flag
if [ -d "/etc/letsencrypt/live/$domains" ]; then
echo "### Certificate obtained successfully. Stopping temporary nginx..."
nginx -s stop
cp /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf
echo "### Setup completed successfully."
fi

View File

@ -13,10 +13,43 @@ http {
server {
listen 80;
server_name _; # Accept any server name
server_name web.sessionzero.app;
# Redirect all HTTP requests to HTTPS
location / {
return 301 https://$host$request_uri;
}
# Allow certbot challenge response
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
server {
listen 443 ssl;
server_name web.sessionzero.app;
root /usr/share/nginx/html;
index index.html;
# SSL certificates managed by Certbot
ssl_certificate /etc/letsencrypt/live/web.sessionzero.app/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/web.sessionzero.app/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/web.sessionzero.app/chain.pem;
# Improve SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# Add HSTS header
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
try_files $uri $uri/ /index.html =404;
add_header 'Access-Control-Allow-Origin' '*';
@ -39,5 +72,10 @@ http {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
# Let's Encrypt challenge location
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
}