test/bin/convertdomain

1065 lines
52 KiB
Bash
Executable File

#!/bin/bash -x
#
# Federated Convert Domain
#
# Converts Federated Core services
# From: customer.federatedcomputer.cloud
# To: domain.com
#
# Assumes all services are currently running
. /federated/lib/functions.sh
. /etc/federated
check_gluerecords() {
echo -ne "\n* Checking glue records for $DOMAIN_NEW.."
local DOMAIN_PARENT=$(echo $DOMAIN_NEW |cut -d. -f2-)
local NS_PARENT=""
while true; do
NS_PARENT="$(dig @8.8.8.8 +short NS "$DOMAIN_PARENT." | head -n 1)"
[ -n "$NS_PARENT" ] && break
if ! echo $DOMAIN_PARENT |grep -q '\.'; then
failcheck "Could not determine parent NS for $DOMAIN_NEW"
fi
# When handling a subdomain, the parent NS may not be at the next
# level -- imagine
# DOMAIN_NEW=fed.a.b.c.d.com
# d.com has:
# c NS whatever
# c.d.com has
# b A something
# a.b A something
# fed.a.b NS something
DOMAIN_PARENT="$(echo $DOMAIN_PARENT |cut -d. -f2-)"
done
CHECK_NS1=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep NS | grep -i ns1.$DOMAIN_NEW`
[ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative NS record ns1.$DOMAIN_NEW"
CHECK_NS2=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep NS | grep -i ns2.$DOMAIN_NEW`
[ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative NS record ns2.$DOMAIN_NEW"
CHECK_A1=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep A | grep -i ns1.$DOMAIN_NEW | grep $EXTERNALIP`
[ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative A record ns1.$DOMAIN_NEW to $EXTERNALIP"
CHECK_A2=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep A | grep -i ns2.$DOMAIN_NEW | grep $EXTERNALIP`
[ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative A record ns2.$DOMAIN_NEW to $EXTERNALIP"
echo -ne "done."
}
do_serviceprep_dns() {
# Create DNS records for newdomain
docker exec pdns pdnsutil create-zone $DOMAIN_NEW
docker exec pdns pdnsutil set-kind $DOMAIN_NEW native
docker exec pdns pdnsutil set-meta $DOMAIN_NEW SOA-EDIT-API DEFAULT
for i in ns1 ns2 powerdns traefik mail www computer panel nextcloud collabora jitsi matrix element listmonk vaultwarden vpn wireguard baserow gitea blog documentation podcasts castopod caddy wordpress bookstack freescout msp espocrm dashboard plane calcom; do
docker exec pdns pdnsutil add-record $DOMAIN_NEW $i A 86400 $EXTERNALIP
done
docker exec pdns pdnsutil add-record $DOMAIN_NEW @ NS ns1.$DOMAIN_NEW
docker exec pdns pdnsutil add-record $DOMAIN_NEW @ NS ns2.$DOMAIN_NEW
docker exec pdns pdnsutil add-record $DOMAIN_NEW @ MX 86400 "10 mail.$DOMAIN_NEW"
docker exec pdns pdnsutil add-record $DOMAIN_NEW @ TXT 86400 "\"v=spf1 mx a:$DOMAIN_NEW ~all\""
docker exec pdns pdnsutil add-record $DOMAIN_NEW \* CNAME 86400 www.$DOMAIN_NEW
docker exec pdns pdnsutil add-record $DOMAIN_NEW @ A 86400 $EXTERNALIP
}
do_serviceprep_ldap() {
docker exec ldap bash -c "slapcat > /root/convertdomain.ldif"
# Remove first lines of ldap config, replace dc= with new domain, replace domain name
sed -n '/^dn: ou=people,dc=federatedcomputer,dc=cloud$/,$p' /federated/apps/ldap/data/root/convertdomain.ldif > /federated/apps/ldap/data/root/convertdomain1.ldif
sed -i "s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/ldap/data/root/convertdomain1.ldif
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/ldap/data/root/convertdomain1.ldif
}
convert_generic() {
#### Conversions that must be done for almost everything
# FIXME check if Jitsi really needs upper-case DC. If we can use lower case dc like everywhere else,
# we can avoid generating DOMAIN_NEW_LDAP_DC
# dc=federatedcomputer,dc=cloud is hardcoded for some stuff in initial
# core creation even if the original domain isn't under federatedcomputer.cloud,
# so let's migrate from that unconditionally
sed -i "s#$DOMAIN#$DOMAIN_NEW#g;s#$DOMAIN_LDAP_dc#$DOMAIN_NEW_LDAP_dc#g;s#$DOMAIN_LDAP_DC#$DOMAIN_NEW_LDAP_DC#g;s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/$1/docker-compose.yml
[ -e /federated/apps/$1/.env ] && sed -i "s#$DOMAIN#$DOMAIN_NEW#g;s#$DOMAIN_LDAP_dc#$DOMAIN_NEW_LDAP_dc#g;s#$DOMAIN_LDAP_DC#$DOMAIN_NEW_LDAP_DC#g;s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/$1/.env
}
convert_calcom() {
echo -ne "\n* Converting calcom..."
convert_generic calcom
/federated/bin/sync-calcomusers
start_service_convert "calcom" "nc -z 192.168.0.48 3000 &>/dev/null"
echo done
}
convert_plane() {
echo -ne "\n* Converting plane..."
convert_generic plane
docker exec postgresql psql -U plane -c "UPDATE instances SET domain='$DOMAIN_NEW' WHERE domain='$DOMAIN'"
docker exec postgresql psql -U plane -c "UPDATE users SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
docker exec postgresql psql -U plane -c "UPDATE profiles SET company_name='$DOMAIN_NEW' WHERE company_name='$DOMAIN'"
start_service_convert "plane" "nc -z 192.168.0.50 3000 &>/dev/null"
echo done
}
convert_pdnsmysql() {
#### Convert PowerDNS pdnsmysql
echo -ne "\n* Converting pdnsmysql.."
convert_generic pdnsmysql
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/pdnsmysql/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "pdnsmysql" "nc -z ${SERVICE_IP} 3306 &> /dev/null"
echo -ne "done."
}
convert_pdns() {
#### Convert PowerDNS pdns
echo -ne "\n* Converting pdns.."
convert_generic pdns
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/pdns/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "pdns" "nc -z ${SERVICE_IP} 8081 &> /dev/null"
echo -ne "done."
}
convert_pdnsadmin() {
#### Convert PowerDNS pdnsadmin
echo -ne "\n* Converting pdnsadmin.."
convert_generic pdnsadmin
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/pdnsadmin/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "pdnsadmin" "nc -z ${SERVICE_IP} 9494 &> /dev/null"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD pdns -e \"UPDATE user SET username=REPLACE(username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD pdns -e \"UPDATE user SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN';\""
echo -ne "done."
}
convert_traefik() {
#### Convert Traefik
echo -ne "\n* Converting traefik. Waiting 60s first for dns.."
sleep 60
convert_generic traefik
rm -rf /federated/apps/traefik/data/letsencrypt/acme.json
# Start Traefik
docker compose -f /federated/apps/traefik/docker-compose.yml -p traefik up -d &> /dev/null
# Keep trying to see that certificates are generated
RETRY="20"
while [ $RETRY -gt 0 ]; do
traefik-certs-dumper file --version v2 --source /federated/apps/traefik/data/letsencrypt/acme.json --dest /federated/certs &> /dev/null
# Check if certs are generated
ls /federated/certs/private/$DOMAIN_NEW.key /federated/certs/certs/$DOMAIN_NEW.crt &> /dev/null
if [ $? -eq 0 ]; then
break
else
if [ "$RETRY" == 1 ]; then
docker compose -f /federated/apps/traefik/docker-compose.yml -p traefik down &> /dev/null
failcheck "There was a problem starting service /federated/apps/traefik\nCheck the output of 'docker logs traefik'"
fi
((RETRY--))
sleep 9
fi
done
echo -ne "done."
}
convert_postgresql() {
#### Convert Postgresql
echo -ne "\n* Converting postgresql.."
convert_generic postgresql
cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/apps/postgresql/data/var/lib/postgresql/server.crt
cp /federated/certs/private/$DOMAIN_NEW.key /federated/apps/postgresql/data/var/lib/postgresql/server.key
chown 999 /federated/apps/postgresql/data/var/lib/postgresql/server.crt /federated/apps/postgresql/data/var/lib/postgresql/server.key
chmod 600 /federated/apps/postgresql/data/var/lib/postgresql/server.crt /federated/apps/postgresql/data/var/lib/postgresql/server.key
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/postgresql/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "postgresql" "nc -z ${SERVICE_IP} 5432 &> /dev/null"
echo -ne "done."
}
convert_ldap() {
#### Convert LDAP
echo -ne "\n* Converting ldap.."
# Remove LDAP files so we can start clean
rm -rf /federated/apps/ldap/data/var/lib/ldap/*
rm -rf /federated/apps/ldap/data/etc/ldap/slapd.d/*
rm -rf /federated/apps/ldap/data/root/.ldaprc
rm -rf /federated/apps/ldap/data/certs/dhparam.pem
convert_generic ldap
sed -i "s#LDAP_DOMAIN=.*#LDAP_DOMAIN=$DOMAIN_NEW#g" /federated/apps/ldap/.env
sed -i "s#LDAP_ORGANISATION=.*#LDAP_ORGANISATION=$ORG_NEW#g" /federated/apps/ldap/.env
cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/ldap/data/certs/
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/ldap/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "ldap" "nc -z $SERVICE_IP 636 &> /dev/null"
# DEBUG output of the ldif
echo "/root/convertdomain1.ldif before import"
echo "---------------------------------------"
cat /federated/apps/ldap/data/root/convertdomain1.ldif
# This imports the modified LDAP configuration above
docker exec ldap bash -c "slapadd -v -l /root/convertdomain1.ldif"
[ $? -ne 0 ] && failcheck "Couldn't slapadd convertdomain1.ldif inside ldap container"
echo -ne "done."
}
convert_mail() {
#### Convert Mail
echo -ne "\n* Converting mail.."
convert_generic mail
cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/mail/data/root/certs/
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/mail/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "mail" "nc -z $SERVICE_IP 25 &> /dev/null"
# Generate the DKIM DNS key for new domain
docker exec mail setup config dkim keysize 2048 domain $DOMAIN_NEW &> /dev/null
[ $? -ne 0 ] && fail "Couldn't generate DKIM record"
# Insert the DKIM DNS TXT entry into /federated/apps/pdns container
DKIM_RECORD_STRIP=`cat /federated/apps/mail/data/tmp/docker-mailserver/opendkim/keys/$DOMAIN_NEW/mail.txt | sed 's/.*(//'`
DKIM_RECORD=`echo $DKIM_RECORD_STRIP | sed 's/).*//'`
docker exec pdns pdnsutil add-record $DOMAIN_NEW mail._domainkey TXT 86400 "$DKIM_RECORD" &> /dev/null
[ $? -ne 0 ] && fail "Couldn't insert DKIM record into /federated/apps/pdns container"
# Insert the DMARC DNS TXT entry into /federated/apps/pdns container
docker exec pdns pdnsutil add-record $DOMAIN_NEW _dmarc TXT 86400 "\"v=DMARC1; p=quarantine; rua=mailto:admin@$DOMAIN_NEW; ruf=mailto:admin@$DOMAIN_NEW; sp=none; ri=86400\"" &> /dev/null
[ $? -ne 0 ] && fail "Couldn't insert DMARC record into /federated/apps/pdns container"
# Stop and Start mail to reload DKIM
/federated/bin/stop mail &> /dev/null
/federated/bin/start mail &> /dev/null
echo -ne "done."
}
convert_collabora() {
#### Convert Collabora
echo -ne "\n* Converting collabora.."
convert_generic collabora
cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/collabora/data/root/certs/
chown 104 /federated/apps/collabora/data/root/certs/*
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/collabora/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "collabora" "nc -z $SERVICE_IP 9980 &> /dev/null"
echo -ne "done."
}
convert_nextcloud() {
#### Convert Nextcloud
echo -ne "\n* Converting nextcloud.."
# Disable Nextcloud LDAP
docker exec -u 33 nextcloud /var/www/html/occ -vv ldap:delete-config s01
docker exec -u 33 nextcloud /var/www/html/occ app:disable user_ldap
convert_generic nextcloud
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/nextcloud/data/var/www/html/config/config.php
# Make new nextcloud config
cat > /federated/apps/nextcloud/data/configs.json <<EOF
{
"system": {
"mail_smtpmode": "smtp",
"mail_smtpsecure": "tls",
"mail_sendmailmode": "smtp",
"mail_from_address": "nextcloud",
"mail_domain": "$DOMAIN_NEW",
"mail_smtpauthtype": "LOGIN",
"mail_smtpauth": 1,
"mail_smtphost": "mail.$DOMAIN_NEW",
"mail_smtpport": "587",
"mail_smtpname": "$SMTPUSER",
"mail_smtppassword": "$ADMINPASS"
},
"apps": {
"side_menu": {
"background-color-opacity": "100",
"current-app-background-color": "#005b8d",
"types": "",
"enabled": "yes",
"text-color": "#ffffff",
"loader-color": "#339bd4",
"types": "",
"always-displayed": "0",
"big-menu": "0",
"side-with-categories": "0",
"background-color": "#0068a1",
"background-color-to": "#0068a1",
"icon-invert-filter": "0",
"icon-opacity": "100",
"opener": "side-menu-opener",
"dark-mode-background-color": "#0068a1",
"dark-mode-background-color-to": "#0068a1",
"dark-mode-background-color-opacity": "100",
"dark-mode-current-app-background-color": "#005b8d",
"dark-mode-text-color": "#ffffff",
"dark-mode-loader-color": "#ffffff",
"dark-mode-icon-invert-filter": "0",
"dark-mode-icon-opacity": "100",
"dark-mode-opener": "side-menu-opener",
"opener-position": "before",
"opener-only": "0",
"hide-when-no-apps": "0",
"opener-hover": "0",
"display-logo": "1",
"use-avatar": "0",
"add-logo-link": "1",
"big-menu-hidden-apps": "[]",
"show-settings": "0",
"size-icon": "normal",
"size-text": "normal",
"target-blank-apps": "[]",
"loader-enabled": "1",
"top-side-menu-apps": "[]",
"top-menu-mouse-over-hidden-label": "0",
"apps-order": "[\"dashboard\",\"mail\",\"calendar\",\"contacts\",\"notes\",\"tasks\",\"files\",\"deck\",\"bookmarks\",\"forms\",\"spreed\",\"photos\",\"activity\"]",
"categories-order-type": "default",
"categories-custom": "[]",
"apps-categories-custom": "[]",
"categories-order": "[\"other\",\"customization\",\"dashboard\",\"external_links\",\"files\",\"workflow\",\"games\",\"integration\",\"monitoring\",\"multimedia\",\"office\",\"organization\",\"search\",\"security\",\"social\",\"tools\"]",
"default-enabled": "1",
"force": "0",
"top-menu-apps": "[\"photos\",\"activity\",\"dashboard\",\"forms\",\"calendar\",\"tasks\",\"bookmarks\",\"deck\",\"contacts\",\"notes\",\"spreed\",\"mail\",\"files\"]",
"cache": "2"
}
}
}
EOF
cat > /federated/apps/nextcloud/data/config.sh <<EOF
#!/bin/sh
PATH=/var/www/html:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/sbin:/bin
/var/www/html/occ app:enable user_ldap
/var/www/html/occ ldap:create-empty-config
/var/www/html/occ ldap:set-config s01 ldapHost 'ldaps://ldap.$DOMAIN_NEW'
/var/www/html/occ ldap:set-config s01 ldapAgentName cn=admin,$DOMAIN_NEW_LDAP_dc
/var/www/html/occ ldap:set-config s01 ldapAgentPassword $LDAP_SECRET
/var/www/html/occ ldap:set-config s01 ldapBase ou=people,dc=$DOMAIN_NEW_LDAP_dc
/var/www/html/occ ldap:set-config s01 ldapBaseGroups ou=groups,dc=$DOMAIN_NEW_LDAP_dc
/var/www/html/occ ldap:set-config s01 ldapBaseUsers ou=people,dc=$DOMAIN_NEW_LDAP_dc
/var/www/html/occ ldap:set-config s01 ldapEmailAttribute mail
/var/www/html/occ ldap:set-config s01 ldapGidNumber gidNumber
/var/www/html/occ ldap:set-config s01 ldapGroupDisplayName cn
/var/www/html/occ ldap:set-config s01 ldapGroupFilter '(&(|(objectclass=posixGroup)))'
/var/www/html/occ ldap:set-config s01 ldapGroupFilterMode 0
/var/www/html/occ ldap:set-config s01 ldapGroupFilterObjectclass inetOrgPerson
/var/www/html/occ ldap:set-config s01 ldapGroupMemberAssocAttr uniqueMember
/var/www/html/occ ldap:set-config s01 ldapLoginFilter '(&(|(objectclass=inetOrgPerson))(mail=%uid))'
/var/www/html/occ ldap:set-config s01 ldapLoginFilterEmail 0
/var/www/html/occ ldap:set-config s01 ldapLoginFilterMode 0
/var/www/html/occ ldap:set-config s01 ldapLoginFilterUsername 1
/var/www/html/occ ldap:set-config s01 ldapLoginFilterEmail 0
/var/www/html/occ ldap:set-config s01 ldapMatchingRuleInChainState unknown
/var/www/html/occ ldap:set-config s01 ldapNestedGroups 0
/var/www/html/occ ldap:set-config s01 ldapPagingSize 500
/var/www/html/occ ldap:set-config s01 ldapPort 636
/var/www/html/occ ldap:set-config s01 ldapTLS 1
/var/www/html/occ ldap:set-config s01 ldapUserAvatarRule default
/var/www/html/occ ldap:set-config s01 ldapUserDisplayName cn
/var/www/html/occ ldap:set-config s01 ldapUserFilter '(|(objectclass=inetOrgPerson))'
/var/www/html/occ ldap:set-config s01 ldapUserFilterMode 0
/var/www/html/occ ldap:set-config s01 ldapUserFilterObjectclass inetOrgPerson
/var/www/html/occ ldap:set-config s01 ldapUuidGroupAttribute auto
/var/www/html/occ ldap:set-config s01 ldapUuidUserAttribute auto
/var/www/html/occ ldap:set-config s01 turnOffCertCheck 0
/var/www/html/occ ldap:set-config s01 turnOnPasswordChange 0
/var/www/html/occ ldap:set-config s01 useMemberOfToDetectMembership 1
/var/www/html/occ ldap:set-config s01 ldapConfigurationActive 1
/var/www/html/occ ldap:set-config s01 ldap_expert_username_attr uid
/var/www/html/occ ldap:set-config s01 ldap_display_name givenName
/var/www/html/occ config:system:set overwriteprotocol --value=https
/var/www/html/occ config:system:set default_phone_region --value="$COUNTRY"
/var/www/html/occ config:system:delete trusted_domains
/var/www/html/occ config:system:set trusted_domains 1 --value=*
/var/www/html/occ group:adduser admin admin
/var/www/html/occ user:delete nextcloud
/var/www/html/occ app:enable mail
/var/www/html/occ app:enable calendar
/var/www/html/occ app:enable contacts
/var/www/html/occ app:enable notes
/var/www/html/occ app:enable deck
/var/www/html/occ app:enable tasks
/var/www/html/occ app:enable bookmarks
/var/www/html/occ app:enable forms
/var/www/html/occ app:enable spreed
/var/www/html/occ app:enable side_menu
/var/www/html/occ app:enable external
/var/www/html/occ app:enable richdocuments
/var/www/html/occ config:app:set --value https:\/\/collabora.$DOMAIN_NEW richdocuments public_wopi_url
/var/www/html/occ config:app:set --value https:\/\/collabora.$DOMAIN_NEW richdocuments wopi_url
/var/www/html/occ config:app:set --value ooxml richdocuments doc_format
/var/www/html/occ config:app:set --value "" richdocuments disable_certificate_verification
/var/www/html/occ config:app:set external sites "--value={\"1\":{\"icon\":\"external.svg\",\"lang\":\"\",\"type\":\"link\",\"device\":\"browser\",\"groups\":[],\"redirect\":true,\"id\":1,\"name\":\"Video Conference (Jitsi)\",\"url\":\"https:\/\/jitsi.$DOMAIN_NEW\"},\"2\":{\"icon\":\"external.svg\",\"lang\":\"\",\"type\":\"link\",\"device\":\"browser\",\"groups\":[],\"redirect\":true,\"id\":2,\"name\":\"Worldwide Chat (Element)\",\"url\":\"https:\/\/element.$DOMAIN_NEW\"},\"3\":{\"icon\":\"external.svg\",\"lang\":\"\",\"type\":\"link\",\"device\":\"browser\",\"groups\":[],\"redirect\":true,\"id\":3,\"name\":\"Mailing Lists (Listmonk)\",\"url\":\"https:\/\/listmonk.$DOMAIN_NEW\"},\"4\":{\"icon\":\"external.svg\",\"lang\":\"\",\"type\":\"link\",\"device\":\"browser\",\"groups\":[],\"redirect\":true,\"id\":4,\"name\":\"Databases (Baserow)\",\"url\":\"https:\/\/baserow.$DOMAIN_NEW\"},\"5\":{\"icon\":\"external.svg\",\"lang\":\"\",\"type\":\"link\",\"device\":\"browser\",\"groups\":[],\"redirect\":true,\"id\":5,\"name\":\"Passwords (Vaultwarden)\",\"url\":\"https:\/\/vaultwarden.$DOMAIN_NEW\"},\"7\":{\"icon\":\"external.svg\",\"lang\":\"\",\"type\":\"link\",\"device\":\"browser\",\"groups\":[],\"redirect\":true,\"id\":7,\"name\":\"Source code (Gitea)\",\"url\":\"https:\/\/gitea.$DOMAIN_NEW\"}}"
/var/www/html/occ config:import configs.json
EOF
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/nextcloud/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "nextcloud" "nc -z $SERVICE_IP 80 &> /dev/null"
# Move config.sh and sidemenu config, set config.sh executable
mv /federated/apps/nextcloud/data/config.sh /federated/apps/nextcloud/data/configs.json /federated/apps/nextcloud/data/var/www/html/
docker exec nextcloud chown www-data:root /var/www/html/config.sh /var/www/html/configs.json
docker exec nextcloud chmod 755 /var/www/html/config.sh
[ $? -ne 0 ] && fail "Couldn't chown config.sh in /federated/apps/nextcloud container"
# Run config.sh - Setup LDAP, configuration for nextcloud
docker exec -u 33 nextcloud /var/www/html/config.sh &> /dev/null
[ $? -ne 0 ] && fail "Couldn't run config.sh inside /federated/apps/nextcloud container"
# Add admin user to group
# Have to do it this many times so it will query LDAP and populate admin user first
docker exec -u 33 nextcloud /var/www/html/occ ldap:search admin
docker exec -u 33 nextcloud /var/www/html/occ group:list
docker exec -u 33 nextcloud /var/www/html/occ group:adduser admin admin
docker exec -u 33 nextcloud /var/www/html/occ group:adduser admin admin
docker exec -u 33 nextcloud /var/www/html/occ group:list
# Config admin email
docker exec -u 33 nextcloud bash -c "/var/www/html/occ mail:account:create admin admin admin@$DOMAIN_NEW mail.$DOMAIN_NEW 993 ssl admin@$DOMAIN_NEW $ADMINPASS mail.$DOMAIN_NEW 465 ssl admin@$DOMAIN_NEW $ADMINPASS password"
# Remove configs
rm /federated/apps/nextcloud/data/var/www/html/config.sh /federated/apps/nextcloud/data/var/www/html/configs.json
# Configure SSO to Authelia
NEXTCLOUD_CLIENT_SECRET=$(cat /federated/apps/nextcloud/.nextcloud.client.secret)
docker exec -u 33 nextcloud /var/www/html/occ user_oidc:provider:delete Authelia -f
docker exec -u 33 nextcloud /var/www/html/occ config:system:set allow_local_remote_servers --value=true
docker exec -u 33 nextcloud /var/www/html/occ app:enable user_oidc
docker exec -u 33 nextcloud /var/www/html/occ config:system:set --value=true --type=boolean user_oidc use_pkce
docker exec -u 33 nextcloud /var/www/html/occ user_oidc:provider Authelia --clientid="nextcloud" --clientsecret="$NEXTCLOUD_CLIENT_SECRET" --discoveryuri="https://authelia.$DOMAIN_NEW/.well-known/openid-configuration" --mapping-uid=name --endsessionendpointuri=https://authelia.$DOMAIN_NEW/logout
docker exec -u 33 nextcloud /var/www/html/occ ldap:set-config s01 ldapLoginFilter '(&(|(objectclass=inetOrgPerson))(uid=%uid))'
echo -ne "done."
}
convert_matrix() {
#### Convert Matrix
echo -ne "\n* Converting matrix.."
# Delete matrix database so we can start from scratch
MATRIX_SECRET=$(create_password);
COTURN_MATRIX_SECRET=$(create_password);
docker exec postgresql psql -U postgres -c "drop database matrix" &> /dev/null
docker exec postgresql psql -U postgres -c "drop user matrix" &> /dev/null
docker exec postgresql psql -U postgres -c "CREATE USER matrix WITH PASSWORD '$MATRIX_SECRET'"
docker exec postgresql psql -U postgres -c "CREATE DATABASE matrix"
docker exec postgresql psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE matrix TO matrix"
convert_generic matrix
rm -rf /federated/apps/matrix/data
mkdir -p /federated/apps/matrix/data/matrix
cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/matrix/data/matrix/
chmod 644 /federated/apps/matrix/data/matrix/$DOMAIN_NEW.crt /federated/apps/matrix/data/matrix/$DOMAIN_NEW.key
chown -R 991:991 /federated/apps/matrix/data/matrix
# Generate the matrix homeserver.yaml file
docker run --rm -v "/federated/apps/matrix/data/matrix:/data" -e SYNAPSE_SERVER_NAME=matrix.$DOMAIN_NEW -e SYNAPSE_REPORT_STATS=yes matrixdotorg/synapse:latest generate &> /dev/null
[ $? -ne 0 ] && fail "Couldn't run docker matrixdotorg/synapse:latest generate"
# Take out default Sqlite database config
sed -i 's!database: /data/homeserver.db!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
sed -i 's!database:!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
sed -i 's!name: sqlite3!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
sed -i 's!args:!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
# Insert our Postgres and LDAP config
cat >> /federated/apps/matrix/data/matrix/homeserver.yaml <<EOF
web_client_location: https://element.$DOMAIN/
public_baseurl: https://matrix.$DOMAIN_NEW/
serve_server_wellknown: true
turn_uris: [ "turn:turn.$DOMAIN_NEW?transport=udp", "turn:turn.$DOMAIN_NEW?transport=tcp" ]
turn_shared_secret: "$COTURN_MATRIX_SECRET"
turn_user_lifetime: 86400000
database:
name: psycopg2
args:
user: matrix
password: $MATRIX_SECRET
host: postgresql.$DOMAIN_NEW
database: matrix
cp_min: 5
cp_max: 10
email:
smtp_host: "mail.$DOMAIN_NEW"
smtp_port: 587
smtp_user: "$SMTPUSER"
smtp_pass: "$ADMINPASS"
force_tls: true
# require_transport_security: true
enable_tls: true
notif_from: "Your Friendly %(app)s homeserver <matrix@matrix.$DOMAIN_NEW>"
app_name: $ORG_NEW Matrix Server
modules:
- module: "ldap_auth_provider.LdapAuthProviderModule"
config:
enabled: true
uri: "ldaps://ldap.$DOMAIN_NEW:636"
start_tls: true
base: "$DOMAIN_NEW_LDAP_dc"
attributes:
mail: "mail"
uid: "uid"
name: "givenName"
bind_dn: cn=admin,$DOMAIN_NEW_LDAP_dc
bind_password: $LDAP_SECRET
tls_options:
validate: true
local_certificate_file: /data/$DOMAIN_NEW.crt
local_private_key_file: /data/$DOMAIN_NEW.key
EOF
chown -R 991:991 /federated/apps/matrix/data/matrix
# sed -i "s#server_name: \"matrix.$DOMAIN\"#server_name: \"matrix.$DOMAIN_NEW\"#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#smtp_host: \"mail.$DOMAIN\"#smtp_host: \"mail.$DOMAIN_NEW\"#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#notif_from:.*#notif_from: \"Your Friendly %(app)s homeserver <matrix@matrix.$DOMAIN_NEW>\"#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#app_name:.*#app_name: $ORG_NEW Matrix Server#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#postgresql.$DOMAIN#postgresql.$DOMAIN_NEW#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#ldap.$DOMAIN#ldap.$DOMAIN_NEW#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#$DOMAIN.crt#$DOMAIN_NEW.crt#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# sed -i "s#$DOMAIN.key#$DOMAIN_NEW.key#g" /federated/apps/matrix/data/matrix/homeserver.yaml
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/matrix/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "matrix" "nc -z $SERVICE_IP 8008 &> /dev/null"
chown -R 991:991 /federated/apps/matrix/data/matrix
# Set admin user as admin in Matrix
docker exec postgresql psql -U matrix -c "update users set admin='1' where name='\"@admin:matrix.$DOMAIN_NEW\"'" &> /dev/null
# Configure SSO to Authelia
MATRIX_CLIENT_SECRET=$(cat /federated/apps/matrix/.matrix.client.secret)
cat >> /federated/apps/matrix/data/matrix/homeserver.yaml <<EOF
oidc_providers:
- idp_id: authelia
idp_name: "Authelia"
idp_icon: "mxc://authelia.com/cKlrTPsGvlpKxAYeHWJsdVHI"
discover: true
issuer: "https://authelia.$DOMAIN_NEW"
client_id: "matrix"
client_secret: "$MATRIX_CLIENT_SECRET"
scopes: ["openid", "profile", "email"]
allow_existing_users: true
user_mapping_provider:
config:
subject_claim: "sub"
localpart_template: "{{ user.name }}"
display_name_template: "{{ user.name }}"
email_template: "{{ user.email }}"
EOF
# Restart Matrix for changes to take the above configuration
run_command "/federated/bin/stop matrix"
run_command "/federated/bin/start matrix"
echo -ne "done."
}
convert_element() {
#### Convert Element
echo -ne "\n* Converting element.."
convert_generic element
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/element/data/element/element-config.json
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/element/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "element" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_listmonk() {
#### Convert Listmonk
echo -ne "\n* Converting listmonk.."
convert_generic listmonk
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/listmonk/data/listmonk/config.toml
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/listmonk/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "listmonk" "nc -z $SERVICE_IP 9000 &> /dev/null"
# Change app.root_url and other settings to our domain
docker exec postgresql psql -U listmonk -c "update settings set value='\"http://listmonk.$DOMAIN_NEW\"' where key='app.root_url'" &> /dev/null
docker exec postgresql psql -U listmonk -c "update settings set value='\"listmonk <listmonk@listmonk.$DOMAIN_NEW>\"' where key='app.from_email'" &> /dev/null
docker exec postgresql psql -U listmonk -c "update settings set value='[{\"host\": \"mail.$DOMAIN_NEW\", \"port\": 587, \"enabled\": true, \"password\": \"$ADMINPASS\", \"tls_type\": \"STARTTLS\", \"username\": \"$SMTPUSER\", \"max_conns\": 10, \"idle_timeout\": \"15s\", \"wait_timeout\": \"5s\", \"auth_protocol\": \"login\", \"email_headers\": [], \"hello_hostname\": \"\", \"max_msg_retries\": 2, \"tls_skip_verify\": false}, {\"host\": \"smtp.gmail.com\", \"port\": 465, \"enabled\": false, \"password\": \"password\", \"tls_type\": \"TLS\", \"username\": \"username@gmail.com\", \"max_conns\": 10, \"idle_timeout\": \"15s\", \"wait_timeout\": \"5s\", \"auth_protocol\": \"login\", \"email_headers\": [], \"hello_hostname\": \"\", \"max_msg_retries\": 2, \"tls_skip_verify\": false}]' where key='smtp';" &> /dev/null
echo -ne "done."
}
convert_vaultwarden() {
#### Convert Vaultwarden
echo -ne "\n* Converting vaultwarden.."
convert_generic vaultwarden
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/vaultwarden/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "vaultwarden" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_panel() {
#### Convert Panel
echo -ne "\n* Converting panel.."
convert_generic panel
sed -i "s#SITE_NAME=.*#SITE_NAME=$ORG_NEW Panel#g" /federated/apps/panel/.env
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/panel/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "panel" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_wireguard() {
#### Convert Wireguard
echo -ne "\n* Converting wireguard.."
convert_generic wireguard
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wireguard/data/config/.donoteditthisfile
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wireguard/data/config/peer1/peer1.conf
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wireguard/data/config/coredns/Corefile
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/wireguard/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "wireguard" "nc -uvz $SERVICE_IP 51820 &> /dev/null"
echo -ne "done."
}
convert_jitsi() {
#### Convert Jitsi
echo -ne "\n* Converting jitsi.."
convert_generic jitsi
start_service_convert "jitsi" "nc -z 192.168.0.25 443 &> /dev/null"
echo -ne "done."
}
convert_baserow() {
#### Convert Baserow
echo -ne "\n* Converting baserow.."
convert_generic baserow
docker exec postgresql bash -c "psql -U baserow -c \"UPDATE auth_user SET username=REPLACE(username, '@$DOMAIN','@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN'\"" &> /dev/null
[ $? -ne 0 ] && fail "Couldn't update auth_user table (username) in baserow"
docker exec postgresql bash -c "psql -U baserow -c \"UPDATE auth_user SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'\"" &> /dev/null
[ $? -ne 0 ] && fail "Couldn't update auth_user table (email) in baserow"
start_service_convert "baserow" "docker exec baserow curl http://localhost:8000 &> /dev/null"
echo -ne "done."
}
convert_gitea() {
#### Convert Gitea
echo -ne "\n* Converting gitea.."
convert_generic gitea
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/gitea/data/data/gitea/conf/app.ini
# Replace users in Gitea postgres database with new domain name
LOWER_DOMAIN_NEW="$(echo $DOMAIN_NEW |tr 'A-Z' 'a-z')"
docker exec postgresql bash -c "psql -U gitea -c \"UPDATE email_address SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'\""
docker exec postgresql bash -c "psql -U gitea -c \"UPDATE email_address SET lower_email=REPLACE(lower_email, '@$DOMAIN', '@$LOWER_DOMAIN_NEW') WHERE lower_email LIKE '%@$DOMAIN'\""
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/gitea/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "gitea" "nc -z $SERVICE_IP 3000 &> /dev/null"
# Delete the current admin and create the admin user with new domain name
# FIXME we used to do
#docker exec --user 1000 gitea bash -c "gitea admin user delete --id 1"
#docker exec --user 1000 gitea gitea admin user create --admin --username gitea --password $ADMINPASS --email admin@$DOMAIN_NEW
# here, but that doesn't seem necessary given we fixed the users above?
# Configure SSO to Authelia
GITEA_CLIENT_SECRET=$(cat /federated/apps/gitea/.gitea.client.secret)
GITEA_AUTH_ID=$(docker exec --user 1000 gitea gitea admin auth list | tail -1 | awk '{ print $1 }')
docker exec --user 1000 gitea gitea admin auth delete --id ${GITEA_AUTH_ID}
docker exec --user 1000 gitea gitea admin auth add-oauth --name "Authelia" --provider "openidConnect" --key "gitea" --secret "$GITEA_CLIENT_SECRET" --auto-discover-url "https://authelia.$DOMAIN_NEW/.well-known/openid-configuration" --skip-local-2fa "true" --scopes "openid email profile" --group-claim-name "groups" --admin-group "admin" --restricted-group "guest"
echo -ne "done."
}
convert_caddy() {
#### Convert Caddy
echo -ne "\n* Converting caddy.."
convert_generic caddy
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/caddy/data/etc/caddy/Caddyfile
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/caddy/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "caddy" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_castopod() {
#### Convert Castopod
echo -ne "\n* Converting castopod.."
convert_generic castopod
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/castopod/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "castopod" "nc -z $SERVICE_IP 8000 &> /dev/null"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD castopod -e \"UPDATE cp_auth_identities SET secret=REPLACE(secret, '@$DOMAIN', '@$DOMAIN_NEW) WHERE secret LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD castopod -e \"UPDATE cp_users SET username=REPLACE(username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN';\""
echo -ne "done."
}
convert_autodiscover() {
#### Convert Autodiscover
echo -ne "\n* Converting autodiscover.."
convert_generic autodiscover
sed -i "s#COMPANY_NAME=.*#COMPANY_NAME=$ORG_NEW#g" /federated/apps/autodiscover/.env
# Add DNS records for auto discovery
docker exec pdns pdnsutil add-record $DOMAIN_NEW autoconfig A 86400 $EXTERNALIP
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW autodiscover A 86400 $EXTERNALIP
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW @ TXT 86400 "\"mailconf=https://autoconfig.$DOMAIN_NEW/mail/config-v1.1.xml\""
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW _imaps._tcp SRV 86400 "0 0 993 mail.$DOMAIN_NEW"
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW _pop3s._tcp SRV 86400 "0 0 995 mail.$DOMAIN_NEW"
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW _imaps._tcp SRV 86400 "0 0 993 mail.$DOMAIN_NEW"
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW _submission._tcp SRV 86400 "0 0 587 $DOMAIN_NEW"
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW _autodiscover._tcp SRV 86400 "0 0 443 autodiscover.$DOMAIN_NEW"
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
docker exec pdns pdnsutil add-record $DOMAIN_NEW _ldap._tcp SRV 86400 "0 0 636 ldap.$DOMAIN_NEW"
[ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/autodiscover/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "autodiscover" "nc -z $SERVICE_IP 8000 &> /dev/null"
echo -ne "done."
}
convert_wordpress() {
#### Convert Wordpress
echo -ne "\n* Converting wordpress.."
convert_generic wordpress
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wordpress/data/bitnami/wordpress/wp-config.php
sed -i "s#WORDPRESS_BLOG_NAME=.*#WORDPRESS_BLOG_NAME=$ORG_NEW#g" /federated/apps/wordpress/.env
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_users SET user_login=REPLACE(user_login, '@$DOMAIN', '@$DOMAIN_NEW') WHERE user_login LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_users SET user_email=REPLACE(user_email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE user_email LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_usermeta SET meta_value=REPLACE(meta_value, '@$DOMAIN', '@$DOMAIN_NEW') WHERE meta_value LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_users SET display_name=REPLACE(display_name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE display_name LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_options SET option_value = '$ORG_NEW Blog' WHERE option_name = 'blogname';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_options SET option_value = 'admin@$DOMAIN_NEW' WHERE option_name = 'admin_email';\""
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/wordpress/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "wordpress" "nc -z $SERVICE_IP 8080 &> /dev/null"
echo -ne "done."
}
convert_coturn() {
#### Convert Coturn
echo -ne "\n* Converting coturn.."
convert_generic coturn
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/coturn/data/etc/turnserver.conf
sed -i "s#static-auth-secret=.*#static-auth-secret=$COTURN_MATRIX_SECRET#g" /federated/apps/coturn/data/etc/turnserver.conf
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/coturn/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "coturn" "nc -z $SERVICE_IP 3478 &> /dev/null"
echo -ne "done."
}
convert_bookstack() {
#### Convert Bookstack
echo -ne "\n* Converting bookstack.."
convert_generic bookstack
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/bookstack/data/config/www/.env
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD bookstack -e \"UPDATE users SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN';\""
# Setup external_auth_id for each user in bookstack users table
BOOKSTACK_SECRET=$(cat /federated/apps/bookstack/.env | grep "DB_PASS" | awk -F= '{ print $2 }')
# for i in $(docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -sN -e "select email from users;"); do
# docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -e "update users set external_auth_id = '$i' where email = '$i'";
# done
LOWER_DOMAIN="$(echo $DOMAIN |tr 'A-Z' 'a-z')"
LOWER_DOMAIN_NEW="$(echo $DOMAIN_NEW |tr 'A-Z' 'a-z')"
docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -sN -e "UPDATE users SET email=REPLACE(email, '@$LOWER_DOMAIN', '@$LOWER_DOMAIN_NEW') WHERE email LIKE '%@$LOWER_DOMAIN';";
docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -sN -e "UPDATE users SET external_auth_id=REPLACE(external_auth_id, '@$LOWER_DOMAIN', '@$LOWER_DOMAIN_NEW) WHERE external_auth_id LIKE '%@$LOWER_DOMAIN';";
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/bookstack/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "bookstack" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_freescout() {
#### Convert Freescout
echo -ne "\n* Converting freescout.."
convert_generic freescout
docker exec postgresql bash -c "psql -U freescout -c \"UPDATE users SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'\""
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/freescout/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "freescout" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_msp() {
#### Convert MSP
echo -ne "\n* Converting msp.."
convert_generic msp
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/msp/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "msp" "nc -z $SERVICE_IP 3000 &> /dev/null"
echo -ne "done."
}
convert_espocrm() {
#### Convert EspoCRM
echo -ne "\n* Converting espocrm.."
# Grab the SSO client secret for config below before removing espocrm
ESPOCRM_CLIENT_SECRET=$(cat /federated/apps/espocrm/.env | grep ESPOCRM_CONFIG_OIDC_CLIENT_SECRET | awk -F= '{ print $2 }')
ESPOCRM_IMAGE_VERSION=$(cat /federated/apps/espocrm/.env | grep IMAGE_VERSION | awk -F\" '{ print $2 }')
convert_generic espocrm
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/espocrm/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "espocrm" "nc -z $SERVICE_IP 80 &> /dev/null"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE user SET user_name=REPLACE(user_name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE user_name LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_account SET email_address=REPLACE(email_address, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email_address LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_account SET username=REPLACE(username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_account SET smtp_username=REPLACE(smtp_username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE smtp_username LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_address SET name=REPLACE(name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE name LIKE '%@$DOMAIN';\""
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_address SET lower=REPLACE(lower, '@$DOMAIN', '@$DOMAIN_NEW') WHERE lower LIKE '%@$DOMAIN';\""
# FIXME did we catch every possible place for email addresses above?
run_command "/federated/bin/stop espocrm"
run_command "/federated/bin/start espocrm"
echo -ne "done."
}
convert_dashboard() {
#### Convert Dashboard
echo -ne "\n* Converting dashboard.."
convert_generic dashboard
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/dashboard/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "dashboard" "nc -z $SERVICE_IP 8080 &> /dev/null"
echo -ne "done."
}
convert_roundcube() {
#### Convert Roundcube
echo -ne "\n* Converting roundcube.."
convert_generic roundcube
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/roundcube/data/var/www/html/config/config.inc.php
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/roundcube/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "roundcube" "nc -z $SERVICE_IP 80 &> /dev/null"
echo -ne "done."
}
convert_authelia() {
#### Convert Authelia
echo -ne "\n* Converting authelia.."
convert_generic authelia
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/authelia/data/config/configuration.yml
sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/authelia/data/config/idproviders.yml
# Configure SSO to Authelia
# Delete the entries in the pdns settings table
[[ -d "/federated/apps/pdnsmysql/data/var/lib/mysql/pdnsadmin" ]] && POWERDNS_DB="pdnsadmin" || POWERDNS_DB="pdns"
docker exec pdnsmysql mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e "delete from setting where name like '%oidc_oauth%';"
POWERDNS_CLIENT_SECRET=$(cat /federated/apps/authelia/.powerdns.client.secret)
# Insert PowerDNS configuration because we need an initial
# config for Authelia to run
PDNS_MYSQL_COMMAND1="insert into setting (name, value) values (\"oidc_oauth_enabled\", \"True\");insert into setting (name, value) values (\"oidc_oauth_key\", \"powerdns\");"
PDNS_MYSQL_COMMAND2="insert into setting (name, value) values (\"oidc_oauth_scope\", \"openid profile groups email\");insert into setting (name, value) values (\"oidc_oauth_api_url\", \"https://authelia.$DOMAIN_NEW/api/oidc/userinfo\");"
PDNS_MYSQL_COMMAND3="insert into setting (name, value) values (\"oidc_oauth_auto_configure\", \"True\");insert into setting (name, value) values (\"oidc_oauth_metadata_url\", \"https://authelia.$DOMAIN_NEW/.well-known/openid-configuration\");"
PDNS_MYSQL_COMMAND4="insert into setting (name, value) values (\"oidc_oauth_token_url\", \"\");insert into setting (name, value) values (\"oidc_oauth_authorize_url\", \"\");"
PDNS_MYSQL_COMMAND5="insert into setting (name, value) values (\"oidc_oauth_logout_url\", \"https://authelia.$DOMAIN_NEW/logout\");insert into setting (name, value) values (\"oidc_oauth_username\", \"preferred_username\");"
PDNS_MYSQL_COMMAND6="insert into setting (name, value) values (\"oidc_oauth_email\", \"email\");insert into setting (name, value) values (\"oidc_oauth_firstname\", \"preferred_username\");"
PDNS_MYSQL_COMMAND7="insert into setting (name, value) values (\"oidc_oauth_last_name\", \"name\");insert into setting (name, value) values (\"oidc_oauth_account_name_property\", \"preferred_username\");"
PDNS_MYSQL_COMMAND8="insert into setting (name, value) values (\"oidc_oauth_account_description_property\", \"name\");insert into setting (name, value) values (\"oidc_oauth_secret\", \"$POWERDNS_CLIENT_SECRET\");"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND1;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND2;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND3;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND4;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND5;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND6;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND7;'"
docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND8;'"
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/authelia/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
start_service_convert "authelia" "nc -z $SERVICE_IP 9091 &> /dev/null"
echo -ne "done."
}
convert_jitsiopenid() {
#### Convert JitsiOpenID
echo -ne "\n* Converting jitsiopenid.."
convert_generic jitsiopenid
# Grab the container IP from docker-compose
SERVICE_IP=`grep ipv4_address /federated/apps/jitsiopenid/docker-compose.yml | awk '{ print $2 }'`
# Start service with command to make sure it's up before proceeding
run_command "/federated/bin/start jitsiopenid"
echo -ne "done."
}
usage() {
echo "$0: <domain.com> <organization name>"
exit 2
}
[ $# != 2 ] && usage
DOMAIN_NEW=$1
ORG_NEW=$2
# Check if DNS works
EXTERNALIP=`dig @resolver4.opendns.com myip.opendns.com +short 2> /dev/null`
[ $? -ne 0 ] && failcheck "Couldn't run dig, dns is not working"
# Setup DOMAIN variables for domain or subdomain
if ! echo $DOMAIN_NEW |grep -q '\.'; then
failcheck "$DOMAIN_NEW is not a valid domain.com or sub.domain.com"
fi
DOMAIN_NEW_LDAP_dc="dc=${DOMAIN_NEW//./,dc=}"
DOMAIN_NEW_LDAP_DC="DC=${DOMAIN_NEW//./,DC=}"
DOMAIN_LDAP_dc="dc=${DOMAIN//./,dc=}"
DOMAIN_LDAP_DC="DC=${DOMAIN//./,DC=}"
ADMINPASS=`cat /federated/bin/.adminpass | head -1`
LDAP_SECRET=`cat /federated/apps/ldap/.ldap.secret`
MYSQL_ROOTPASSWORD=`cat /federated/apps/pdnsmysql/.env | grep MYSQL_ROOT_PASSWORD | awk -F= '{ print $2 }'`
# Set SMTP user based on if fcore exists
[[ $(docker exec ldap slapcat | grep fcore) ]] && SMTPUSER="fcore" || SMTPUSER="admin"
echo -ne "\n\nConverting Federated Core $DOMAIN to $DOMAIN_NEW.\n\n"
# Key initial steps
check_gluerecords
#get_installedapps
do_serviceprep_dns
do_serviceprep_ldap
# Stop all services
/federated/bin/stop all &> /dev/null
# Convert each services in SERVICES list
for i in "${SERVICES[@]}"; do
if [ -d "/federated/apps/$i" ]; then
convert_$i
fi
done