[TOOLS][SSL] Added bin/boostrap_certificates.sh, allowing for easy configuration of SSL certificates with Let's Encrypt

This commit is contained in:
Hugo Sales 2020-05-05 01:23:55 +00:00 committed by Hugo Sales
parent 3b5789639b
commit a97c511c7a
14 changed files with 272 additions and 49 deletions

4
.gitignore vendored
View File

@ -23,4 +23,6 @@
/file
DOCUMENTATION/database/*
!DOCUMENTATION/database/database.pdf
!DOCUMENTATION/database/database.pdf
docker/certbot

40
bin/bootstrap_certificates.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
echo "Domain: "
read doamin
echo "Email: "
read email
cat > ../docker/bootstrap/bootstrap.env <<EOF
email=${email}
domain=${domain}
EOF
echo "Social database name: "
read db
echo "Database user: "
read user
echo "Database password: "
read password
echo "Sitename: "
read sitename
echo "Admin nickname: "
read admin_nick
echo "Admin password: "
read admin_password
echo "Site profile (public|private|community|singleuser): "
read profile
cat > ../docker/social/social.env <<EOF
SOCIAL_DB=${db}
SOCIAL_USER=${user}
SOCIAL_PASSWORD=${password}
SOCIAL_DOMAIN=${domain}
SOCIAL_SITENAME=${sitename}
SOCIAL_ADMIN_NICK=${nick}
SOCIAL_ADMIN_PASSWORD=${admin_password}
SOCIAL_ADMIN_EMAIL=${email}
SOCIAL_SITE_PROFILE=${profile}
EOF
docker-compose -f docker/bootstrap/bootstrap.yaml up

View File

@ -3,35 +3,67 @@ version: '3.3'
services:
nginx:
image: nginx:latest
depends_on:
- php
restart: always
tty: false
ports:
- 80:80
- 443:443
volumes:
- .:/var/www/gnusocial
- ./nginx.conf:/etc/nginx/conf.d/gnusocial.conf
- ./public:/var/www/social/public
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/social.conf
command: /bin/sh -c 'sed -ri "s/%hostname%/$domain/" /etc/nginx/conf.d/social.conf
while :; do sleep 6h & wait $${!};
nginx -s reload;
done &
nginx -g "daemon off;"'
certbot:
image: certbot/certbot
depends_on:
- nginx
# Check for certificate renewal every 12h as
# recomnended by Let's Encryot
entrypoint: /bin/sh -c 'trap exit TERM;
while :; do
certbot renew > /dev/null;
sleep 12h & wait $${!};
done'
volumes:
- ./docker/certbot/www:/var/www/certbot
- ./docker/certbot/files:/etc/letsencrypt
php:
build: docker/php
depends_on:
- db
restart: always
tty: true
ports:
- 9000:9000
volumes:
- .:/var/www/gnusocial
# Entrypoint
- ./docker/php/entrypoint.sh:/entrypoint.sh
- ./docker/db/wait_for_db.sh:/wait_for_db.sh
- ./docker/social/install.sh:/var/entrypoint.d/social_install.sh
# Main files
- .:/var/www/social
env_files:
- ./docker/social/social.env
- ./docker/db/db.env
command: /entrypoint.sh
postgres:
db:
image: postgres:alpine
restart: always
tty: false
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=foobar
- POSTGRES_DB=social
- PGDATA=/var/lib/postgresql/data
env_file:
- ./docker/db/db.env
volumes:
- database:/var/lib/postgresql/data

View File

@ -0,0 +1,16 @@
FROM nginx:alpine
RUN echo "Installing bootstrap utils"
RUN apk add curl certbot openssl > /dev/null
RUN echo ' \
server { \
listen [::]:80; \
listen 80; \
server_name %hostname%; \
location /.well-known/acme-challenge/ { \
root /var/www/certbot; \
} \
} \
' > /etc/nginx/conf.d/challenge.conf

View File

@ -0,0 +1,2 @@
email=example@foo.bar
domain=domain.foo

52
docker/bootstrap/bootstrap.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/sh
sed -ri "s/%hostname%/$domain/" /etc/nginx/conf.d/challenge.conf
nginx
rsa_key_size=4096
certbot_path="/var/www/certbot"
lets_path="/etc/letsencrypt"
echo "Starting bootstrap"
if [ ! -e "${lets_path}/live//options-ssl-nginx.conf" ] \
|| [ ! -e "${lets_path}/live/ssl-dhparams.pem" ]; then
echo "### Downloading recommended TLS parameters ..."
mkdir -p "${lets_path}/live"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > \
"${lets_path}/options-ssl-nginx.conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > \
"${lets_path}/ssl-dhparams.pem"
echo "### Creating dummy certificate for ${root_domain} ..."
openssl req -x509 -nodes -newkey rsa:1024 -days 1\
-keyout "${lets_path}/live/privkey.pem" \
-out "${lets_path}/live/fullchain.pem" -subj '/CN=localhost'
nginx -s reload
rm -Rf "${lets_path}/live/${root_domain}"
rm -Rf "${lets_path}/archive/${root_domain}"
rm -Rf "${lets_path}/renewal/${root_domain}.conf"
echo "### Requesting Let's Encrypt certificate for $root_domain ..."
# Format domain_args with the cartesian product of `root_domain` and `subdomains`
email_arg="--email $email"
domain_arg="-d $domain"
# Ask Let's Encrypt to create certificates, if challenge passed
certbot certonly --webroot -w /var/www/certbot \
$email_arg \
$domain_arg \
--non-interactive \
--rsa-key-size $rsa_key_size \
--agree-tos \
--force-renewal
else
echo "Certificate related files exists, exiting"
fi

View File

@ -0,0 +1,14 @@
version: "3.3"
services:
bootstrap:
build: .
volumes:
- ../certbot/www:/var/www/certbot
- ../certbot/files:/etc/letsencrypt
- ./bootstrap.sh:/bootstrap.sh
ports:
- 80:80
env_file:
- bootstrap.env
entrypoint: /bootstrap.sh

19
docker/db/wait_for_db.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
case $SOCIAL_DBMS in
"mariadb")
CMD=mysqladmin ping --silent -hdb -uroot -p${MYSQL_ROOT_PASSWORD}
;;
"postgres")
CMD=su postgres && pg_isready -hdb -q
;;
*)
exit 1
esac
while ! $CMD;
do
echo "Waiting for DB..."
sleep 3
done

View File

@ -1,20 +1,22 @@
# server {
# server_name social.localhost;
# # redirect all traffic to HTTPS
# rewrite ^ https://$host$request_uri? permanent;
# }
server {
listen [::]:80;
listen 80;
# Root
root /var/www/gnusocial/public;
server_name %hostname%;
# redirect all traffic to HTTPS
rewrite ^ https://$host$request_uri? permanent;
}
server {
include ssl-common.conf
root /var/www/social/public;
# Server name
server_name social.localhost;
server_name %hostname%;
# Index
index index.php;
@ -22,9 +24,7 @@ server {
# X-Accel/X-Sendfile. Still needs to be enabled in the config
location /file {
internal;
# FIXME: Change "/path/to/gnusocial/root/" to the folder where
# attachments are stored (normally the same as the site root)
root /var/www/gnusocial;
root /var/www/social;
}
# PHP
@ -68,23 +68,23 @@ server {
#
# Hardening (optional)
#
# add_header Strict-Transport-Security "max-age=15768000; preload;";
# add_header X-Content-Type-Options nosniff;
# add_header Referrer-Policy strict-origin-when-cross-origin;
# add_header Content-Security-Policy "default-src 'self' 'unsafe-inline'; frame-ancestors 'self'; form-action 'self'; style-src 'self' 'unsafe-inline'; img-src * blob: data:;";
# add_header X-Permitted-Cross-Domain-Policies none;
# add_header X-Robots-Tag all; # Not really hardening, just here for strictness purposes
#
# client_max_body_size 15M;
# client_body_buffer_size 128k;
# gzip_vary on;
#
# location ~* \.(?:css|js|woff|svg|gif|png|webp|ttf|ico|jpe?g)$ {
# gzip on;
# gzip_comp_level 4;
# add_header Cache-Control "public";
# expires 30d;
# access_log off;
# log_not_found off;
# }
add_header Strict-Transport-Security "max-age=15768000; preload;";
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy strict-origin-when-cross-origin;
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline'; frame-ancestors 'self'; form-action 'self'; style-src 'self' 'unsafe-inline'; img-src * blob: data:;";
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Robots-Tag all; # Not really hardening, just here for strictness purposes
client_max_body_size 15M;
client_body_buffer_size 128k;
gzip_vary on;
location ~* \.(?:css|js|woff|svg|gif|png|webp|ttf|ico|jpe?g)$ {
gzip on;
gzip_comp_level 4;
add_header Cache-Control "public";
expires 30d;
access_log off;
log_not_found off;
}
}

View File

@ -0,0 +1,10 @@
listen [::]:443 ssl http2;
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/hsal.es/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hsal.es/privkey.pem;
# Let's Encrypt best practices
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

View File

@ -1,17 +1,12 @@
FROM php:fpm-alpine
RUN apk update && apk add gettext-dev icu-dev zlib-dev libpng-dev gmp-dev postgresql-dev
RUN apk update && apk add gettext-dev icu-dev zlib-dev libpng-dev gmp-dev postgresql-dev composer > /dev/null
ARG exts=" bcmath exif gd gettext gmp intl mysqli opcache pdo pdo_pgsql pgsql"
ARG exts=" bcmath exif gd gettext gmp intl mysqli opcache pdo_mysql"
ARG MEMCACHED_DEPS="zlib-dev libmemcached-dev cyrus-sasl-dev"
RUN apk add libmemcached-libs zlib
RUN apk add --virtual .phpize-deps $PHPIZE_DEPS \
&& apk add --virtual .memcached-deps $MEMCACHED_DEPS \
&& pecl install memcached \
&& echo "extension=memcached.so" > /usr/local/etc/php/conf.d/20_memcached.ini \
&& rm -rf /usr/share/php7 \
&& rm -rf /tmp/* \
&& apk del .memcached-deps .phpize-deps
&& apk del .phpize-deps > /dev/null
RUN docker-php-ext-install ${exts}

11
docker/php/entrypoint.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
/wait_for_db.sh
echo "Got response from DB"
for script in /var/entrypoint.d/*.sh; do
$script
done
exec php-fpm

20
docker/social/install.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh
if [ ! -e /var/www/social/config.php ]; then
echo -e "Installing GNU social\nInstalling composer dependencies"
cd /var/www/social
composer install
chmod g+w -R /var/www/social
chown -R :www-data /var/www/social
php /var/www/social/scripts/install_cli.php --server="${SOCIAL_DOMAIN}" --sitename="${SOCIAL_SITENAME}" \
--host=db --fancy=yes --database="${SOCIAL_DB}" \
--username="${SOCIAL_USER}" --password="${SOCIAL_PASSWORD}" \
--admin-nick="${SOCIAL_ADMIN_NICK}" --admin-pass="${SOCIAL_ADMIN_PASSWORD}" || exit 1
echo "GNU social is installed"
fi

10
social.env Normal file
View File

@ -0,0 +1,10 @@
#!/bin/sh
SOCIAL_DB=social
SOCIAL_USER=social
SOCIAL_PASSWORD=foobar
SOCIAL_DOMAIN=social.hsal.es
SOCIAL_SITENAME="Test instance"
SOCIAL_ADMIN_NICK=foo
SOCIAL_ADMIN_PASSWORD=foobar
SOCIAL_SITE_PROFILE=public