nginx renewal fixes, oauth mastodon setup, secret restructure, etc

single-dockerfile
Trammell Hudson 2 years ago
parent 317d6b0e3a
commit 628f37fa37
  1. 1
      env.production
  2. 30
      hedgedoc/setup
  3. 38
      keycloak/client-delete
  4. 6
      keycloak/docker-compose.yaml
  5. 1
      keycloak/env.production
  6. 1
      keycloak/setup
  7. 4
      mastodon/docker-compose.yaml
  8. 6
      mastodon/env.production
  9. 47
      mastodon/setup
  10. 7
      nextcloud/docker-compose.yaml
  11. 2
      nextcloud/env.production
  12. 71
      nextcloud/setup
  13. 21
      nginx/certbot-renew
  14. 43
      nginx/setup

@ -5,3 +5,4 @@ KEYCLOAK_HOSTNAME=login.hackerspace.zone
HEDGEDOC_HOSTNAME=docs.hackerspace.zone
MASTODON_HOSTNAME=social.hackerspace.zone
NEXTCLOUD_HOSTNAME=cloud.hackerspace.zone
GRAFANA_HOSTNAME=dashboard.hackerspace.zone

@ -3,20 +3,24 @@ die() { echo >&2 "$@" ; exit 1 ; }
DIRNAME="$(dirname $0)"
cd "$DIRNAME"
[ -r env.production ] && source env.production
[ -r ../env.production ] && source ../env.production
source ../env.production || die "no top levle env?"
source env.production || die "no local env?"
cd ../keycloak
docker-compose down
source env.production
# regenerate the client secrets
CLIENT_SECRET="$(openssl rand -hex 20)"
SESSION_SECRET="$(openssl rand -hex 20)"
sudo docker-compose exec -T keycloak \
/opt/keycloak/bin/kcadm.sh \
create clients \
--user admin \
--password "$KEYCLOAK_ADMIN_PASSWORD" \
-r "$REALM" \
-f - <<EOF || die "unable to create hedgedoc client"
rm -f env.secrets
cat <<EOF > env.secrets
CMD_OAUTH2_CLIENT_SECRET=$CLIENT_SECRET
CMD_SESSION_SECRET=$SESSION_SECRET
EOF
../keycloak/client-delete hedgedoc
../keycloak/client-create <<EOF || die "unable to create hedgedoc client"
{
"clientId": "hedgedoc",
"rootUrl": "https://$HEDGEDOC_HOSTNAME",
@ -24,7 +28,7 @@ sudo docker-compose exec -T keycloak \
"redirectUris": [ "https://$HEDGEDOC_HOSTNAME/*" ],
"webOrigins": [ "https://$HEDGEDOC_HOSTNAME" ],
"clientAuthenticatorType": "client-secret",
"secret": "$CMD_OAUTH2_CLIENT_SECRET",
"secret": "$CLIENT_SECRET",
"defaultClientScopes": [
"web-origins",
"acr",
@ -42,3 +46,5 @@ sudo docker-compose exec -T keycloak \
}
EOF
docker-compose up -d || die "unable to start container"

@ -0,0 +1,38 @@
#!/bin/bash
die() { echo >&2 "$@" ; exit 1 ; }
DIRNAME="$(dirname $0)"
cd "$DIRNAME"
source ../env.production || die "no top levle env?"
source env.production || die "no local env?"
source env.secrets || die "no local secrets?"
# try to get the clients by name
CLIENT_NAME="$1"
if [ -z "$CLIENT_NAME" ]; then
die "usage: $0 clientName"
fi
CLIENT_ID="$(docker-compose exec -T keycloak \
/opt/keycloak/bin/kcadm.sh \
get clients \
--server http://localhost:8080/ \
--user admin \
--password "$KEYCLOAK_ADMIN_PASSWORD" \
-r "$REALM" \
| jq -r ".[] | select( .clientId == \"$CLIENT_NAME\" ).id")"
if [ -z "$CLIENT_ID" ]; then
die "$CLIENT_NAME: no such client"
fi
echo "$0: $CLIENT_NAME = $CLIENT_ID"
docker-compose exec -T keycloak \
/opt/keycloak/bin/kcadm.sh \
delete "clients/$CLIENT_ID" \
--server http://localhost:8080/ \
--user admin \
--password "$KEYCLOAK_ADMIN_PASSWORD" \
-r "$REALM" \
|| die "$CLIENT_NAME($CLIENT_ID): unable to remove"

@ -17,10 +17,12 @@ services:
keycloak:
image: quay.io/keycloak/keycloak:18.0.0
entrypoint: /opt/keycloak/bin/kc.sh start-dev --proxy=edge
entrypoint: /opt/keycloak/bin/kc.sh start --hostname="$${KEYCLOAK_HOSTNAME}" --proxy=edge
user: "0:0" # otherwise the persistent data directory is not writable
env_file:
- ../env.production
- env.production
- env.secrets
environment:
DB_VENDOR: MYSQL
DB_ADDR: mysql
@ -28,9 +30,11 @@ services:
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_ADMIN: admin
# KEYCLOAK_ADMIN_PASSWORD should be set in env.secrets
PROXY_ADDRESS_FORWARDING: 'true'
volumes:
- ./data/certs:/etc/x509/https
- ./data/keycloak:/opt/keycloak/data
ports:
- 8080:8080
depends_on:

@ -1 +0,0 @@
KEYCLOAK_ADMIN_PASSWORD=abcd@1234!

@ -6,6 +6,7 @@ DIRNAME="$(dirname $0)"
cd "$DIRNAME"
source ../env.production
source ./env.production
source ./env.secrets
info "logging into server"
sudo docker-compose exec keycloak \

@ -46,7 +46,7 @@ services:
soft: -1
hard: -1
web:
mastodon:
image: tootsuite/mastodon
restart: always
env_file:
@ -70,7 +70,6 @@ services:
- ./data/system:/mastodon/public/system
streaming:
build: .
image: tootsuite/mastodon
restart: always
env_file:
@ -91,7 +90,6 @@ services:
- redis
sidekiq:
build: .
image: tootsuite/mastodon
restart: always
env_file:

@ -14,7 +14,7 @@
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=social.hackerspace.zone
# LOCAL_DOMAIN is set in env.secrets
#WEB_DOMAIN=social.example.com
# Redis
@ -77,12 +77,10 @@ OMNIAUTH_ONLY=true
# OIDC supported since https://github.com/mastodon/mastodon/pull/16221
OIDC_ENABLED=true
OIDC_PROMPT=Keycloak
OIDC_DISPLAY_NAME=hackerspace.zone
OIDC_ISSUER=https://login.hackerspace.zone/realms/hackerspace
OIDC_REDIRECT_URI=https://social.hackerspace.zone/auth/auth/openid_connect/callback
OIDC_DISCOVERY=true
OIDC_SCOPE=openid,profile
OIDC_UID_FIELD=preferred_username
OIDC_CLIENT_ID=mastodon
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED=true
# OIDC URLs are in env.secrets since they require env expansion
# OIDC_CLIENT_SECRET is in env.secrets

@ -18,40 +18,39 @@ OTP_SECRET=000000
OIDC_CLIENT_SECRET=000000
EOF
# have to bring it all down before we touch the files
docker-compose down
if [ -z "$MASTODON_SKIP_DB_INIT" ]; then
info "configuring mastodon"
sudo docker-compose run web \
sudo docker-compose run --rm mastodon \
rails db:setup \
|| die "unable to login"
fi
# now create the real secrets file
echo > env.secrets "# DO NOT CHECK IN"
OIDC_CLIENT_SECRET="$(openssl rand -hex 32)"
# now create the real secrets file,
# along with some parameters that should be in the environment
cat <<EOF > env.secrets
# DO NOT CHECK IN
LOCAL_DOMAIN=$MASTODON_HOSTNAME
OIDC_DISPLAY_NAME=$REALM
OIDC_ISSUER=https://$KEYCLOAK_HOSTNAME/realms/$REALM
OIDC_REDIRECT_URI=https://$MASTODON_HOSTNAME/auth/auth/openid_connect/callback
OIDC_CLIENT_SECRET=$OIDC_CLIENT_SECRET
SECRET_KEY_BASE=$(openssl rand -hex 32)
OTP_SECRET=$(openssl rand -hex 32)
EOF
sudo docker-compose run web \
docker-compose run --rm mastodon \
rails mastodon:webpush:generate_vapid_key \
>> env.secrets \
|| die "unable to generate vapid key"
echo "SECRET_KEY_BASE=$(openssl rand -hex 32)" >> env.secrets
echo "OTP_SECRET=$(openssl rand -hex 32)" >> env.secrets
CLIENT_SECRET="$(openssl rand -hex 32)"
echo "OIDC_CLIENT_SECRET=$CLIENT_SECRET" >> env.secrets
# create the keycloak side of the secret
cd ../keycloak
source env.production
sudo docker-compose exec -T keycloak \
/opt/keycloak/bin/kcadm.sh \
create clients \
--server http://localhost:8080/ \
--user admin \
--password "$KEYCLOAK_ADMIN_PASSWORD" \
--realm master \
-r "$REALM" \
-f - <<EOF || die "unable to create client id"
../keycloak/client-delete mastodon
../keycloak/client-create <<EOF || die "Unable to create keycloak client"
{
"clientId": "mastodon",
"rootUrl": "https://$MASTODON_HOSTNAME/",
@ -59,6 +58,8 @@ sudo docker-compose exec -T keycloak \
"redirectUris": [ "https://$MASTODON_HOSTNAME/*" ],
"webOrigins": [ "https://$MASTODON_HOSTNAME" ],
"clientAuthenticatorType": "client-secret",
"secret": "$CLIENT_SECRET"
"secret": "$OIDC_CLIENT_SECRET"
}
EOF
docker-compose up -d

@ -19,15 +19,16 @@ services:
env_file:
- ../env.production
- env.production
- env.secrets
environment:
POSTGRES_HOST: database
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: nextcloud
#NEXTCLOUD_TRUSTED_DOMAINS: "${NEXTCLOUD_HOSTNAME}"
NEXTCLOUD_TRUSTED_DOMAINS: cloud.hackerspace.zone
NEXTCLOUD_ADMIN_USER: admin
OVERWRITEPROTOCOL: https
NEXTCLOUD_ADMIN_USER: admin
# NEXTCLOUD_ADMIN_PASSWORD in env.secrets
# NEXTCLOUD_TRUSTED_DOMAINS also set in env.secrets
volumes:
- ./data/nextcloud:/var/www/html
depends_on:

@ -1 +1 @@
NEXTCLOUD_ADMIN_PASSWORD=admin
# non-secret nextcloud config

@ -3,23 +3,25 @@ die() { echo >&2 "$@" ; exit 1 ; }
DIRNAME="$(dirname $0)"
cd "$DIRNAME"
[ -r env.production ] && source env.production
[ -r ../env.production ] && source ../env.production
source ../env.production || die "no top level env?"
source env.production || die "no local env?"
sudo docker-compose exec -u www-data -T nextcloud \
./occ app:install sociallogin \
|| die "unable to install sociallogin app"
if [ ! -r "env.secrets" ]; then
NEXTCLOUD_CLIENT_SECRET="$(openssl rand -hex 32)"
NEXTCLOUD_ADMIN_PASSWORD="$(openssl rand -hex 4)"
sudo docker-compose exec -u www-data -T nextcloud \
./occ config:app:set sociallogin prevent_create_email_exists --value=1 \
|| die "unable to config sociallogin"
sudo docker-compose exec -u www-data -T nextcloud \
./occ config:app:set sociallogin update_profile_on_login --value=1 \
|| die "unable to config sociallogin"
echo "Generating secrets: admin password $NEXTCLOUD_ADMIN_PASSWORD"
cat <<EOF > env.secrets
# Do not check in!
NEXTCLOUD_ADMIN_PASSWORD=$NEXTCLOUD_ADMIN_PASSWORD
NEXTCLOUD_TRUSTED_DOMAINS=$NEXTCLOUD_HOSTNAME
NEXTCLOUD_CLIENT_SECRET=$NEXTCLOUD_CLIENT_SECRET
EOF
else
source env.secrets || die "no secret env?"
fi
BASE="https://$KEYCLOAK_HOSTNAME/realms/$REALM/protocol/openid-connect"
SECRET="$(openssl rand -hex 20)"
PROVIDER="$(jq -c . <<EOF
{
"custom_oidc": [
@ -27,15 +29,15 @@ PROVIDER="$(jq -c . <<EOF
"name": "keycloak",
"title": "Keycloak",
"clientId": "nextcloud",
"clientSecret": "$SECRET",
"clientSecret": "$NEXTCLOUD_CLIENT_SECRET",
"authorizeUrl": "$BASE/auth",
"tokenUrl": "$BASE/token",
"userInfoUrl": "$BASE/userinfo",
"logoutUrl": "",
"displayNameClaim": "",
"logoutUrl": "$BASE/logout",
"scope": "openid",
"groupsClaim": "roles",
"style": "keycloak",
"displayNameClaim": "",
"defaultGroup": ""
}
]
@ -43,26 +45,27 @@ PROVIDER="$(jq -c . <<EOF
EOF
)"
sudo docker-compose exec -u www-data -T nextcloud \
./occ config:app:set \
sociallogin custom_providers \
--value="$PROVIDER" \
|| die "unable to set keycloak parameters"
docker-compose up -d || die "unable to bring up docker"
# wait for the nextcloud instance to be responsive
# TODO: how to find out if it is ready?
echo "SLEEPING..."
sleep 30
docker-compose exec -u www-data -T nextcloud bash -x <<EOF || die "unable to configure sociallogin"
./occ app:remove sociallogin || echo "not yet installed"
./occ app:install sociallogin || exit 1
./occ config:app:set sociallogin prevent_create_email_exists --value=1 || exit 1
./occ config:app:set sociallogin update_profile_on_login --value=1 || exit 1
./occ config:app:set sociallogin custom_providers --value='$PROVIDER' || exit 1
EOF
# create the keycloak side of the secret
cd ../keycloak
source env.production
../keycloak/client-delete 'nextcloud' || echo "client did not exist?"
sudo docker-compose exec -T keycloak \
/opt/keycloak/bin/kcadm.sh \
create clients \
--server http://localhost:8080/ \
--user admin \
--password "$KEYCLOAK_ADMIN_PASSWORD" \
--realm master \
-r "$REALM" \
-f - <<EOF || die "unable to create client id"
../keycloak/client-create << EOF || die "unable to create client id"
{
"clientId": "nextcloud",
"rootUrl": "https://$NEXTCLOUD_HOSTNAME/",
@ -70,6 +73,6 @@ sudo docker-compose exec -T keycloak \
"redirectUris": [ "https://$NEXTCLOUD_HOSTNAME/*" ],
"webOrigins": [ "https://$NEXTCLOUD_HOSTNAME" ],
"clientAuthenticatorType": "client-secret",
"secret": "$SECRET"
"secret": "$NEXTCLOUD_CLIENT_SECRET"
}
EOF

@ -1,23 +1,30 @@
#!/bin/bash
die() { echo >&2 "$@" ; exit 1 ; }
DIRNAME="$(dirname $0)"
cd "$DIRNAME"
source ../env.production
source ./env.production
domain_args="-d $DOMAIN_NAME,$KEYCLOAK_HOSTNAME,$HEDGEDOC_HOSTNAME,$MASTODON_HOSTNAME,$NEXTCLOUD_HOSTNAME"
domain_args="-d $DOMAIN_NAME,$KEYCLOAK_HOSTNAME,$HEDGEDOC_HOSTNAME,$MASTODON_HOSTNAME,$NEXTCLOUD_HOSTNAME,$GRAFANA_HOSTNAME"
rsa_key_size=2048
set -x
# move the old live directory away
rm -rf data/certbot/conf/live.old
mv data/certbot/conf/live data/certbot/conf/live.old
# move the temp live directory away if
# this is the first time we've run anything here
if [ ! -d "data/certbot/conf/accounts" ]; then
echo "deleting temp keys"
rm -rf data/certbot/conf/live
fi
docker-compose run --rm certbot \
certonly --webroot -w /var/www/certbot \
$staging_arg \
certonly \
--webroot \
--webroot-path /var/www/certbot \
--email "admin@$DOMAIN_NAME" \
--rsa-key-size $rsa_key_size \
--rsa-key-size "$rsa_key_size" \
--agree-tos \
--no-eff-email \
--force-renewal \

@ -1,28 +1,39 @@
#!/bin/bash
die() { echo >&2 "$@" ; exit 1 ; }
ENV=env.production
if [ ! -r "$ENV" ]; then
die "$ENV: not found?"
fi
DIRNAME="$(dirname $0)"
cd "$DIRNAME"
source ../env.production
source env.production
source ../env.production || die "no top level env"
source env.production || die "no local env"
if [ -z "${DOMAIN_NAME}" ]; then
die "DOMAIN_NAME not set"
fi
docker-compose down
certdir="data/certbot/conf/live/${DOMAIN_NAME}"
mkdir -p "$certdir" || die "$certdir: unable to make"
openssl req \
-x509 \
-newkey rsa:2048 \
-keyout "$certdir/privkey.pem" \
-out "$certdir/fullchain.pem" \
-sha256 \
-nodes \
-days 365 \
-subj "/CN=${DOMAIN_NAME}'" \
|| die "$certdir/privkey.pem: unable to create temp key"
if [ ! -r "$certdir/privkey.pem" ]; then
openssl req \
-x509 \
-newkey rsa:2048 \
-keyout "$certdir/privkey.pem" \
-out "$certdir/fullchain.pem" \
-sha256 \
-nodes \
-days 365 \
-subj "/CN=${DOMAIN_NAME}'" \
|| die "$certdir/privkey.pem: unable to create temp key"
fi
docker-compose up -d || die "unable to bring up nginx"
echo "SLEEPING..."
sleep 10
./certbot-renew || die "unable to create certs"

Loading…
Cancel
Save