Skip to content
[Unit]
Description=static importer
# Dependency ordering
Before=static-git@%i.service
Before=backup@%i.timer
[Service]
Type=oneshot
RemainAfterExit=yes
Environment=DOMAIN=%i
ExecStartPre=/data/indiehosters/scripts/backup-init.sh
ExecStartPre=/data/indiehosters/scripts/import.sh
ExecStart=/bin/bash -euxc ' \
cp /data/domains/%i/TLS/%i.pem /data/runtime/haproxy/approved-certs/%i.pem; \
git_folder=/data/runtime/domains/%i/static-git; \
if [ ! -d $git_folder/www-content/.git ]; then \
mkdir -p $git_folder; \
git clone `cat /data/domains/%i/static-git/GITURL` $git_folder/www-content; \
fi;'
[Install]
WantedBy=static-git@%i.service
[Unit]
Description=git puller
# Dependency ordering
After=static-git-importer@%i.service
[Service]
Type=oneshot
ExecStart=/bin/bash -euxc ' \
app=`echo %p | cut -d"-" -f1,2`; \
cd /data/runtime/domains/%i/$app/www-content; \
git pull'
[Unit]
Description=Run git puller service every 10 minutes
# Dependency binding
BindsTo=static-git@%i.service
[Timer]
OnActiveSec=0
OnUnitActiveSec=10min
[Install]
WantedBy=timers.target
[Unit]
Description=%p-%i
# Requirements
Requires=docker.service
Requires=%p-importer@%i.service
Requires=%p-discovery@%i.service
Requires=%p-puller@%i.timer
Requires=backup@%i.timer
# Dependency ordering
After=docker.service
After=%p-importer@%i.service
Before=%p-discovery@%i.service
[Service]
Restart=always
ExecStartPre=-/usr/bin/docker kill %p-%i
ExecStartPre=-/usr/bin/docker rm %p-%i
ExecStart=/usr/bin/docker run \
--name %p-%i \
-v /data/runtime/domains/%i/%p/www-content:/app \
indiehosters/nginx
ExecReload=/usr/bin/docker restart %p-%i
ExecStop=/usr/bin/docker stop %p-%i
[Install]
WantedBy=multi-user.target
[Unit]
Description=static importer
# Dependency ordering
Before=static@%i.service
Before=backup@%i.timer
[Service]
Type=oneshot
RemainAfterExit=yes
Environment=DOMAIN=%i
ExecStartPre=/data/indiehosters/scripts/backup-init.sh
ExecStartPre=/data/indiehosters/scripts/import.sh
ExecStart=/bin/bash -euxc ' \
cp /data/domains/%i/TLS/%i.pem /data/runtime/haproxy/approved-certs/%i.pem; \
static_folder=/data/domains/%i/static/www-content; \
if [ ! -f $static_folder/index.html ]; then \
mkdir -p $static_folder; \
echo Hello %i > $static_folder/index.html; \
fi;'
[Install]
WantedBy=static@%i.service
[Unit]
Description=%p-%i
# Requirements
Requires=docker.service
Requires=%p-importer@%i.service
Requires=%p-discovery@%i.service
Requires=backup@%i.timer
# Dependency ordering
After=docker.service
After=%p-importer@%i.service
Before=%p-discovery@%i.service
[Service]
Restart=always
ExecStartPre=-/usr/bin/docker kill %p-%i
ExecStartPre=-/usr/bin/docker rm %p-%i
ExecStart=/usr/bin/docker run \
--name %p-%i \
-v /data/domains/%i/%p/www-content:/app \
indiehosters/nginx
ExecReload=/usr/bin/docker restart %p-%i
ExecStop=/usr/bin/docker stop %p-%i
[Install]
WantedBy=multi-user.target
[Unit]
Description=Turn on swap
[Service]
Type=oneshot
RemainAfterExit=true
ExecStartPre=-/bin/bash -euxc ' \
fallocate -l 8192m /swap &&\
chmod 600 /swap &&\
mkswap /swap'
ExecStart=/sbin/swapon /swap
ExecStop=/sbin/swapoff /swap
[Install]
WantedBy=local.target
[Unit]
Description=%p
Description=%p-%i
# Requirements
Requires=docker.service
......@@ -9,16 +9,15 @@ After=docker.service
[Service]
Restart=always
ExecStartPre=-/usr/bin/docker kill %p
ExecStartPre=-/usr/bin/docker rm %p
ExecStart=/usr/bin/docker run \
--name %p \
-v /data/runtime/haproxy:/etc/haproxy \
-p 80:80 \
-p 443:443 \
indiehosters/haproxy
ExecReload=/usr/bin/docker restart %p
ExecStop=/usr/bin/docker stop %p
RestartSec=10
TimeoutStartSec=60
TimeoutStopSec=15
EnvironmentFile=-/data/domains/%i/env
Environment=HOSTNAME=%H
WorkingDirectory=/data/domains/%i/
ExecStartPre=-docker-compose rm -f
ExecStart=/bin/bash -euxc "LETSENCRYPT_HOST=%i VIRTUAL_HOST=%i,www.%i docker-compose up"
ExecStop=docker-compose stop
[Install]
WantedBy=multi-user.target
[Unit]
Description=Create lb_web network
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/docker network create lb_web
ExecStop=/usr/bin/docker network rm lb_web
[Install]
WantedBy=local.target
[Unit]
Description=%p for %i etcd registration
# Requirements
Requires=etcd.service
# Dependency ordering
After=etcd.service
After=wordpress@%i.service
# Dependency binding
BindsTo=wordpress@%i.service
[Service]
# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c ' \
sleep 30; \
while true; do \
app=`echo %p | cut -d"-" -f1`; \
ip=`docker inspect --format \'{{.NetworkSettings.IPAddress}}\' $app-%i`; \
curl -f $ip; \
if [ $? -eq 0 ]; then \
etcdctl set /services/$app/%i \'{"ip":"\'$ip\'", "port":"80"}\' --ttl 60; \
else \
etcdctl rm /services/$app/%i; \
fi; \
sleep 50; \
done'
# Stop
ExecStop=-/bin/bash -euxc ' \
app=`echo %p | cut -d"-" -f1`; \
/usr/bin/etcdctl rm /services/$app/%i
[Unit]
Description=WordPress importer
# Dependency ordering
After=mysql@%i.service
Before=wordpress@%i.service
Before=backup@%i.timer
# Dependency binding
BindsTo=wordpress@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
Environment=DOMAIN=%i
ExecStartPre=/data/indiehosters/scripts/backup-init.sh
ExecStartPre=/data/indiehosters/scripts/import.sh
ExecStart=/bin/bash -euxc ' \
cp /data/domains/%i/TLS/%i.pem /data/runtime/haproxy/approved-certs/%i.pem; \
wordpress_folder=/data/domains/%i/wordpress; \
if [ ! -d $wordpress_folder/wp-content ]; then \
mkdir -p $wordpress_folder; \
cd $wordpress_folder; \
tar xvzf /data/indiehosters/blueprints/wordpress.tgz; \
touch .htaccess; \
fi; \
cat /data/domains/%i/mysql/.env | sed s/MYSQL_PASS/DB_PASS/ > $wordpress_folder/.env'
[Install]
WantedBy=wordpress@%i.service
[Unit]
Description=%p-%i
# Requirements
Requires=docker.service
Requires=etcd.service
Requires=mysql@%i.service
Requires=%p-importer@%i.service
Requires=%p-discovery@%i.service
Requires=backup@%i.timer
# Dependency ordering
After=docker.service
After=mysql@%i.service
After=%p-importer@%i.service
Before=%p-discovery@%i.service
[Service]
Restart=always
ExecStartPre=-/usr/bin/docker kill %p-%i
ExecStartPre=-/usr/bin/docker rm %p-%i
ExecStart=/usr/bin/docker run \
--name %p-%i \
--link mysql-%i:db \
-v /data/domains/%i/%p/wp-content:/app/wp-content \
-v /data/domains/%i/%p/.htaccess:/app/.htaccess \
--env-file /data/domains/%i/%p/.env \
indiehosters/wordpress
ExecReload=/usr/bin/docker restart %p-%i
ExecStop=/usr/bin/docker stop %p-%i
[Install]
WantedBy=multi-user.target
#cloud-config
ssh_authorized_keys:
- "PUT YOUR SSH KEY PUBLIC HERE"
write_files:
- path: /etc/ssh/sshd_config
permissions: 0600
owner: root:root
content: |
# Use most defaults for sshd configuration.
UsePrivilegeSeparation sandbox
Subsystem sftp internal-sftp
PermitRootLogin no
AllowUsers core
PasswordAuthentication no
ChallengeResponseAuthentication no
- path: /etc/sysctl.d/libresh.conf
permissions: 0644
owner: root
content: |
fs.aio-max-nr=1048576
vm.max_map_count=262144
vm.overcommit_memory=1
vm.nr_hugepages=0
- path: /etc/hosts
permissions: 0644
owner: root
content: |
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
- path: /etc/environment
permissions: 0644
owner: root
content: |
NAMECHEAP_URL="namecheap.com"
NAMECHEAP_API_USER="pierreo"
NAMECHEAP_API_KEY=
IP=`curl -s http://icanhazip.com/`
FirstName="Pierre"
LastName="Ozoux"
Address=""
PostalCode=""
Country="Portugal"
Phone="+351.967184553"
EmailAddress="pierre@ozoux.net"
City="Lisbon"
CountryCode="PT"
BACKUP_DESTINATION=root@xxxxx:port
MAIL_USER=
MAIL_PASS=
MAIL_HOST=mail.indie.host
MAIL_PORT=587
coreos:
update:
reboot-strategy: off
units:
- name: systemd-sysctl.service
command: restart
- name: swap.service
enable: true
command: start
content: |
[Unit]
Description=Turn on swap
[Service]
Type=oneshot
RemainAfterExit=true
ExecStartPre=-/bin/bash -euxc ' \
fallocate -l 8192m /swap &&\
chmod 600 /swap &&\
mkswap /swap'
ExecStart=/sbin/swapon /swap
ExecStop=/sbin/swapoff /swap
[Install]
WantedBy=local.target
- name: install-compose.service
command: start
content: |
[Unit]
Description=Install Docker Compose
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=-/bin/bash -euxc ' \
mkdir -p /opt/bin &&\
url=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r \'.assets[].browser_download_url | select(contains("Linux") and contains("x86_64"))\') &&\
curl -L $url > /opt/bin/docker-compose &&\
chmod +x /opt/bin/docker-compose'
- name: install-libresh.service
command: start
content: |
[Unit]
Description=Install libre.sh
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=-/bin/bash -euxc ' \
git clone https://github.com/indiehosters/libre.sh.git /libre.sh &&\
mkdir /{data,system} &&\
mkdir /data/trash &&\
cp /libre.sh/unit-files/* /etc/systemd/system && systemctl daemon-reload &&\
systemctl enable web-net.service &&\
systemctl start web-net.service &&\
cp /libre.sh/utils/* /opt/bin/'
#!/bin/bash -eux
source /etc/environment
user=$1
email=$2
quota=$3
curl -X POST -H "OCS-APIRequest:true" --user ${cloud_admin}:${cloud_pass} https://${cloud_hostname}/ocs/v1.php/cloud/users -d userid="$1" -d password="`tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10 | xargs`"
curl -X PUT -H "OCS-APIRequest:true" --user ${cloud_admin}:${cloud_pass} https://${cloud_hostname}/ocs/v1.php/cloud/users/${user} -d key="email" -d value="${email}"
curl -X PUT -H "OCS-APIRequest:true" --user ${cloud_admin}:${cloud_pass} https://${cloud_hostname}/ocs/v1.php/cloud/users/${user} -d key="quota" -d value="${quota}"
#!/bin/bash
set -e
set -u
set -x
source /etc/environment
email=$1
email_password=$2
local_part=`echo $email | cut -d@ -f1`
email_domain=`echo $email | cut -d@ -f2`
curl --data "username=${mail_username}&password=${mail_password}&login=Log+In&rememberme=0" -c /tmp/cookie.txt https://${mail_hostname}/auth/login
domain_id=`curl -b /tmp/cookie.txt https://${mail_hostname}/domain | grep $email_domain | grep purge-domain | grep -o 'purge-domain-[0-9]*' | grep -o '[0-9]*'`
curl --data "local_part=${local_part}&domain=${domain_id}&password=${email_password}" -b /tmp/cookie.txt https://${mail_hostname}/mailbox/add
rm /tmp/cookie.txt
#!/bin/bash -eux
source /etc/environment
user=$1
group=$2
curl -X POST -H "OCS-APIRequest:true" --user ${cloud_admin}:${cloud_pass} https://${cloud_hostname}/ocs/v1.php/cloud/users/${1}/groups -d groupid="${2}"
#!/bin/bash -eux
source /etc/environment
email=$1
cc_welcome_email=$2
quota=$3
password=`tr -dc A-Za-z0-9_ < /dev/urandom | head -c 10 | xargs`
local_part=`echo $email | cut -d@ -f1`
email_domain=`echo $email | cut -d@ -f2`
curl --data "username=${mail_username}&password=${mail_password}&login=Log+In&rememberme=0" -c /tmp/cookie.txt https://${mail_hostname}/auth/login
if ! curl -b /tmp/cookie.txt https://${mail_hostname}/domain | grep $email_domain | grep purge-domain | grep -o 'purge-domain-[0-9]*' | grep -o '[0-9]*' ; then
curl --data "backupmx=0&active=1&max_aliases=0&max_mailboxes=0&max_quota=0&quota=0&transport=virtual&domain=${email_domain}" -b /tmp/cookie.txt https://${mail_hostname}/domain/add
fi
domain_id=`curl -b /tmp/cookie.txt https://${mail_hostname}/domain | grep $email_domain | grep purge-domain | grep -o 'purge-domain-[0-9]*' | grep -o '[0-9]*'`
curl --data "local_part=${local_part}&domain=${domain_id}&password=${password}&welcome_email=1&cc_welcome_email=${cc_welcome_email}" -b /tmp/cookie.txt https://${mail_hostname}/mailbox/add
rm /tmp/cookie.txt
curl -X PUT --user ${cloud_admin}:${cloud_pass} https://${cloud_hostname}/ocs/v1.php/cloud/users/${email} -d key="quota" -d value="${quota}"
#docker exec -it --user www-data `echo ${cloud_hostname}_app_1 |sed 's/-//g' | sed 's/\.//g'` bash -c "\
# php occ mail:account:create ${email} ${email} ${email} ${mail_hostname} 993 ssl ${email} ${password} ${mail_hostname} 587 tls ${email} ${password}"
#!/bin/bash -eux
source /etc/environment
function provision_dkim () {
docker exec mailindiehost_postfix_1 /add_domain.sh ${arg_u}
}
function configure_dns () {
domain_key=`cat /data/domains/mail.indie.host/opendkim/keys/${arg_u}/mail.txt | cut -d\" -f2 | sed 'N;s/\n//g' | sed 's/ //g' | sed 's/+/%2B/g' | sed 's/\//%2F/g'`
info "Configuring DNS."
arguments="&Command=namecheap.domains.dns.setHosts\
&DomainName=${arg_u}\
&SLD=$(SLD)\
&TLD=$(TLD)\
&HostName1=@\
&RecordType1=A\
&Address1=${IP}\
&HostName2=www\
&RecordType2=CNAME\
&Address2=${arg_u}\
&HostName3=@\
&RecordType3=MX\
&Address3=${mail_hostname}\
&MXPref3=10\
&HostName4=@\
&RecordType4=TXT\
&Address4=v=spf1%20include:${mail_hostname}\
&Hostname5=_dmarc\
&RecordType5=TXT\
&Address5=v=DMARC1;%20p=none;%20rua=mailto:support@indie.host\
&HostName6=mail._domainkey\
&RecordType6=TXT\
&Address6=${domain_key}\
&HostName7=autoconfig\
&RecordType7=CNAME\
&Address7=autoconfig.`echo $mail_hostname | cut -d. -f2,3`\
&EmailType=mx"
call_API ${arguments}
}
#!/bin/bash -eux
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin
echo BEGIN > /tmp/dump-logs
date > /tmp/dump-logs
for domain in `ls /data/domains`; do
echo $domain >> /tmp/dump-logs
cd /data/domains/${domain}/
if [[ -f ./scripts/pre-backup ]]; then
cat ./scripts/pre-backup >> /tmp/dump-logs
./scripts/pre-backup >> /tmp/dump-logs
fi
done
date > /tmp/dump
echo END >> /tmp/dump-logs
date >> /tmp/dump-logs
function contains () {
local n=$#
local value=${!n}
for ((i=1;i < $#;i++)) {
if [ "${!i}" == "${value}" ]; then
echo "y"
return 0
fi
}
echo "n"
return 1
}
function TLD () {
echo ${arg_u} | cut -d. -f2,3
}
function SLD () {
echo ${arg_u} | cut -d. -f1
}
function call_API () {
url="https://api.$NAMECHEAP_URL/xml.response\?ApiUser=${NAMECHEAP_API_USER}&ApiKey=${NAMECHEAP_API_KEY}&UserName=${NAMECHEAP_API_USER}&ClientIp=${IP}$1"
output=$(curl -s ${url})
if [ $(echo ${output} | grep -c 'Status="OK"') -eq 0 ]; then
error "API call failed. Please read the output"
echo ${output}
exit 1
else
info "API call is a success."
fi
}
function _fmt () {
local color_ok="\x1b[32m"
local color_bad="\x1b[31m"
local color="${color_bad}"
if [ "${1}" = "debug" ] || [ "${1}" = "info" ] || [ "${1}" = "notice" ]; then
color="${color_ok}"
fi
local color_reset="\x1b[0m"
if [[ "${TERM}" != "xterm"* ]] || [ -t 1 ]; then
# Don't use colors on pipes or non-recognized terminals
color=""; color_reset=""
fi
echo -e "$(date -u +"%Y-%m-%d %H:%M:%S UTC") ${color}$(printf "[%9s]" ${1})${color_reset}";
}
function emergency () { echo "$(_fmt emergency) ${@}" 1>&2 || true; exit 1; }
function alert () { [ "${LOG_LEVEL}" -ge 1 ] && echo "$(_fmt alert) ${@}" 1>&2 || true; }
function critical () { [ "${LOG_LEVEL}" -ge 2 ] && echo "$(_fmt critical) ${@}" 1>&2 || true; }
function error () { [ "${LOG_LEVEL}" -ge 3 ] && echo "$(_fmt error) ${@}" 1>&2 || true; }
function warning () { [ "${LOG_LEVEL}" -ge 4 ] && echo "$(_fmt warning) ${@}" 1>&2 || true; }
function notice () { [ "${LOG_LEVEL}" -ge 5 ] && echo "$(_fmt notice) ${@}" 1>&2 || true; }
function info () { [ "${LOG_LEVEL}" -ge 6 ] && echo "$(_fmt info) ${@}" 1>&2 || true; }
function debug () { [ "${LOG_LEVEL}" -ge 7 ] && echo "$(_fmt debug) ${@}" 1>&2 || true; }
function help () {
echo "" 1>&2
echo " ${@}" 1>&2
echo "" 1>&2
echo " ${usage}" 1>&2
echo "" 1>&2
exit 1
}