Skip to content

Instantly share code, notes, and snippets.

@wezzels
Created September 14, 2022 05:00
Show Gist options
  • Save wezzels/1e981589c1852a143be2106be4486533 to your computer and use it in GitHub Desktop.
Save wezzels/1e981589c1852a143be2106be4486533 to your computer and use it in GitHub Desktop.
Docker registry and letsencrypt auto reconfigure.
#Basic setup for my container registry, minio, and openVPN. Keep and SSL updates
DOMAIN_NAME=example.com
USER=myuser
sudo mkdir -p /opt/registry/data
sudo mkdir -p /opt/registry/web
sudo mkdir -p /opt/registry/web/certbot/conf
sudo mkdir -p /opt/registry/web/certbot/www
sudo mkdir -p /opt/registry/setup
sudo mkdir -p /opt/registry/auth
sudo mkdir -p /opt/registry/cert
sudo chown -R $USER:$USER /opt/registry
sudo apt -y install apache2-utils
#curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh > init-letsencrypt.sh
#chmod +x init-letsencrypt.sh
#sudo ./init-letsencrypt.sh
#htpasswd -Bc /opt/registry/registry.password testuser
cat <<EOF > /opt/registry/auth/docker-compose.yml
version: '3'
services:
registry:
image: registry:2
ports:
- "5000:5000"
environment:
REGISTRY_HTTP_ADDR: 0.0.0.0:5000
REGISTRY_HTTP_TLS_CERTIFICATE: /etc/letsencrypt/live/$DOMAIN_NAME/fullchain.pem
REGISTRY_HTTP_TLS_KEY: /etc/letsencrypt/live/$DOMAIN_NAME/privkey.pem
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
restart: always
volumes:
- /opt/registry/web/certbot/conf:/etc/letsencrypt
- /opt/registry/auth:/auth
- /opt/registry/cert:/cert
- /opt/registry/data:/data
#dummy password and user are:testuser:passwordtester
nginx:
image: nginx:1.15-alpine
ports:
- "80:80"
- "8443:8443"
command: "/bin/sh -c 'while :; do sleep 6h & wait 303468{!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
volumes:
- /opt/registry/app:/data/www
- /opt/registry/web:/etc/nginx/conf.d
- /opt/registry/web/certbot/conf:/etc/letsencrypt
- /opt/registry/web/certbot/www:/var/www/certbot
certbot:
image: certbot/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait 303468{!}; done;'"
volumes:
- /opt/registry/web/certbot/conf:/etc/letsencrypt
- /opt/registry/web/certbot/www:/var/www/certbot
EOF
cat <<EOF > /opt/registry/web/app.conf
server {
listen 80;
server_name $DOMAIN_NAME;
location / {
return 301 https://$host$request_uri;
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
server {
listen 8443 ssl;
server_name $DOMAIN_NAME;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_certificate /etc/letsencrypt/live/$DOMAIN_NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN_NAME/privkey.pem;
location / {
proxy_pass http://$DOMAIN_NAME; #for demo purposes
}
}
EOF
cat <<EOF > /opt/registry/init-letsencrypt.sh
#!/bin/bash
if ! [ -x "$(command -v docker-compose)" ]; then
echo 'Error: docker-compose is not installed.' >&2
exit 1
fi
domains=($DOMAIN_NAME)
rsa_key_size=4096
data_path="/opt/registry/web/certbot/"
email="wlrobbi@sandia.gov" # Adding a valid address is strongly recommended
staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits
if [ -d "$data_path" ]; then
read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision
if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then
exit
fi
fi
if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
echo "### Downloading recommended TLS parameters ..."
mkdir -p "$data_path/conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
echo
fi
echo "### Creating dummy certificate for $domains ..."
path="/etc/letsencrypt/live/$domains"
mkdir -p "$data_path/conf/live/$domains"
docker-compose run --rm --entrypoint "\
openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 1\
-keyout '$path/privkey.pem' \
-out '$path/fullchain.pem' \
-subj '/CN=localhost'" certbot
echo
echo "### Starting nginx ..."
docker-compose up --force-recreate -d nginx
echo
echo "### Deleting dummy certificate for $domains ..."
docker-compose run --rm --entrypoint "\
rm -Rf /etc/letsencrypt/live/$domains && \
rm -Rf /etc/letsencrypt/archive/$domains && \
rm -Rf /etc/letsencrypt/renewal/$domains.conf" certbot
echo
echo "### Requesting Let's Encrypt certificate for $domains ..."
#Join $domains to -d args
domain_args=""
for domain in "${domains[@]}"; do
domain_args="$domain_args -d $domain"
done
# Select appropriate email arg
case "$email" in
"") email_arg="--register-unsafely-without-email" ;;
*) email_arg="--email $email" ;;
esac
# Enable staging mode if needed
if [ $staging != "0" ]; then staging_arg="--staging"; fi
docker-compose run --rm --entrypoint "\
certbot certonly --webroot -w /var/www/certbot \
$staging_arg \
$email_arg \
$domain_args \
--rsa-key-size $rsa_key_size \
--agree-tos \
--force-renewal" certbot
echo
echo "### Reloading nginx ..."
docker-compose exec nginx nginx -s reload
EOF
sudo sh ./init-letsencrypt.sh
cd /opt/registry
docker-compose up -d
DOMAIN_NAME=example.com
sudo mkdir -p /opt/minio/data1-1
sudo mkdir -p /opt/minio/data1-2
sudo mkdir -p /opt/minio/data2-1
sudo mkdir -p /opt/minio/data2-2
sudo mkdir -p /opt/minio/data3-1
sudo mkdir -p /opt/minio/data3-2
sudo mkdir -p /opt/minio/data4-1
sudo mkdir -p /opt/minio/data4-2
cat <<EOF > /opt/minio/docker-compose.yml
version: '3.7'
# Settings and configurations that are common for all containers
x-minio-common: &minio-common
image: quay.io/minio/minio:RELEASE.2022-09-07T22-25-02Z
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
# command: server --certs-dir /root/.minio/certs --skipcertcheck --console-address ":9001" https://minio{1...4}/data{1...2}
expose:
- "9000"
- "9001"
environment:
MINIO_ROOT_USER: adminUser
MINIO_ROOT_PASSWORD: adminPssword
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
# starts 4 docker containers running minio server instances.
# using nginx reverse proxy, load balancing, you can access
# it through port 9000.
services:
minio1:
<<: *minio-common
hostname: minio1
volumes:
- /opt/minio/data1-1:/data1
- /opt/minio/data1-2:/data2
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/fullchain.pem:/root/.minio/certs/public.crt
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/privkey.pem:/root/.minio/certs/private.key
minio2:
<<: *minio-common
hostname: minio2
volumes:
- /opt/minio/data2-1:/data1
- /opt/minio/data2-2:/data2
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/fullchain.pem:/root/.minio/certs/public.crt
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/privkey.pem:/root/.minio/certs/private.key
minio3:
<<: *minio-common
hostname: minio3
volumes:
- /opt/minio/data3-1:/data1
- /opt/minio/data3-2:/data2
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/fullchain.pem:/root/.minio/certs/public.crt
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/privkey.pem:/root/.minio/certs/private.key
minio4:
<<: *minio-common
hostname: minio4
volumes:
- /opt/minio/data4-1:/data1
- /opt/minio/data4-2:/data2
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/fullchain.pem:/root/.minio/certs/public.crt
# - /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/privkey.pem:/root/.minio/certs/private.key
nginx:
image: nginx:1.19.2-alpine
hostname: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/fullchain.pem:/etc/nginx/certs/public.crt
- /opt/registry/web/certbot/conf/live/$DOMAIN_NAME/privkey.pem:/etc/nginx/certs/private.key
ports:
- "9000:9000"
- "9001:9001"
depends_on:
- minio1
- minio2
- minio3
- minio4
EOF
cat <<EOF > /opt/minio/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
}
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;
sendfile on;
keepalive_timeout 65;
# include /etc/nginx/conf.d/*.conf;
upstream minio {
server minio1:9000;
server minio2:9000;
server minio3:9000;
server minio4:9000;
}
upstream console {
ip_hash;
server minio1:9001;
server minio2:9001;
server minio3:9001;
server minio4:9001;
}
server {
listen 9000 ssl http2 default_server;
server_name $DOMAIN_NAME;
ssl_certificate /etc/nginx/certs/public.crt;
ssl_certificate_key /etc/nginx/certs/private.key;
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# To disable buffering
proxy_buffering off;
proxy_request_buffering off;
location / {
proxy_set_header Host \$http_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;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass http://minio;
}
}
server {
listen 9001 ssl http2 default_server;
server_name $DOMAIN_NAME;
ssl_certificate /etc/nginx/certs/public.crt;
ssl_certificate_key /etc/nginx/certs/private.key;
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# To disable buffering
proxy_buffering off;
proxy_request_buffering off;
location / {
proxy_set_header Host \$http_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;
proxy_set_header X-NginX-Proxy true;
# This is necessary to pass the correct IP to be hashed
real_ip_header X-Real-IP;
proxy_connect_timeout 300;
# To support websocket
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_pass http://console;
}
}
}
EOF
cd /opt/minio
docker-compose up -d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment